LCOV - code coverage report
Current view: top level - filter/source/config/cache - typedetection.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 352 468 75.2 %
Date: 2012-08-25 Functions: 25 26 96.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 412 990 41.6 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "typedetection.hxx"
      30                 :            : #include "constant.hxx"
      31                 :            : 
      32                 :            : #include <com/sun/star/document/XExtendedFilterDetection.hpp>
      33                 :            : #include <com/sun/star/util/URLTransformer.hpp>
      34                 :            : #include <com/sun/star/util/XURLTransformer.hpp>
      35                 :            : 
      36                 :            : #include <com/sun/star/io/XInputStream.hpp>
      37                 :            : #include <com/sun/star/io/XSeekable.hpp>
      38                 :            : #include <com/sun/star/task/XInteractionHandler.hpp>
      39                 :            : #include <tools/wldcrd.hxx>
      40                 :            : #include <rtl/ustrbuf.hxx>
      41                 :            : #include <framework/interaction.hxx>
      42                 :            : #include <tools/urlobj.hxx>
      43                 :            : #include <unotools/localfilehelper.hxx>
      44                 :            : #include <comphelper/componentcontext.hxx>
      45                 :            : 
      46                 :            : 
      47                 :            : namespace filter{
      48                 :            :     namespace config{
      49                 :            : 
      50                 :            : namespace css = ::com::sun::star;
      51                 :            : 
      52                 :      11828 : TypeDetection::TypeDetection(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
      53                 :            : {
      54                 :            :     BaseContainer::init(xSMGR                                         ,
      55                 :            :                         TypeDetection::impl_getImplementationName()   ,
      56                 :            :                         TypeDetection::impl_getSupportedServiceNames(),
      57 [ +  - ][ +  - ]:      11828 :                         FilterCache::E_TYPE                           );
         [ +  - ][ +  - ]
      58                 :      11828 : }
      59                 :            : 
      60                 :            : 
      61                 :            : 
      62                 :      11828 : TypeDetection::~TypeDetection()
      63                 :            : {
      64         [ -  + ]:      23656 : }
      65                 :            : 
      66                 :            : 
      67                 :            : 
      68                 :        644 : ::rtl::OUString SAL_CALL TypeDetection::queryTypeByURL(const ::rtl::OUString& sURL)
      69                 :            :     throw (css::uno::RuntimeException)
      70                 :            : {
      71                 :        644 :     ::rtl::OUString sType;
      72                 :            : 
      73                 :            :     // SAFE ->
      74         [ +  - ]:        644 :     ::osl::ResettableMutexGuard aLock(m_aLock);
      75                 :            : 
      76                 :        644 :     css::util::URL  aURL;
      77                 :        644 :     aURL.Complete = sURL;
      78 [ +  - ][ +  - ]:        644 :     css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(comphelper::ComponentContext(m_xSMGR).getUNOContext()));
         [ +  - ][ +  - ]
      79 [ +  - ][ +  - ]:        644 :     xParser->parseStrict(aURL);
      80                 :            : 
      81                 :            :     // set std types as minimum requirement first!
      82                 :            :     // Only in case no type was found for given URL,
      83                 :            :     // use optional types too ...
      84         [ +  - ]:        644 :     FlatDetection lFlatTypes;
      85 [ +  - ][ +  - ]:        644 :     m_rCache->detectFlatForURL(aURL, lFlatTypes);
      86                 :            : 
      87 [ -  + ][ -  + ]:        793 :     if (
                 [ +  + ]
      88                 :        644 :         (lFlatTypes.size() < 1                                ) &&
      89 [ +  - ][ +  - ]:        149 :         (!m_rCache->isFillState(FilterCache::E_CONTAINS_TYPES))
      90                 :            :        )
      91                 :            :     {
      92 [ #  # ][ #  # ]:          0 :         m_rCache->load(FilterCache::E_CONTAINS_TYPES);
      93 [ #  # ][ #  # ]:          0 :         m_rCache->detectFlatForURL(aURL, lFlatTypes);
      94                 :            :     }
      95                 :            : 
      96                 :            :     // first item is guaranteed as "preferred" one!
      97         [ +  + ]:        644 :     if (lFlatTypes.size() > 0)
      98                 :            :     {
      99                 :        495 :         const FlatDetectionInfo& aMatch = *(lFlatTypes.begin());
     100                 :        495 :         sType = aMatch.sType;
     101                 :            :     }
     102                 :            : 
     103         [ +  - ]:        644 :     return sType;
     104                 :            :     // <- SAFE
     105                 :            : }
     106                 :            : 
     107                 :            : namespace {
     108                 :            : 
     109                 :            : /**
     110                 :            :  * Rank format types in order of complexity.  More complex formats are
     111                 :            :  * ranked higher so that they get tested sooner over simpler formats.
     112                 :            :  *
     113                 :            :  * Guidelines to determine how complex a format is (subject to change):
     114                 :            :  *
     115                 :            :  * 1) compressed text (XML, HTML, etc)
     116                 :            :  * 2) binary
     117                 :            :  * 3) non-compressed text
     118                 :            :  *   3.1) structured text
     119                 :            :  *     3.1.1) dialect of a structured text (e.g. docbook XML)
     120                 :            :  *     3.1.2) generic structured text (e.g. generic XML)
     121                 :            :  *   3.2) non-structured text
     122                 :            :  *
     123                 :            :  * In each category, rank them from strictly-structured to
     124                 :            :  * loosely-structured.
     125                 :            :  */
     126                 :       2080 : int getFlatTypeRank(const rtl::OUString& rType)
     127                 :            : {
     128                 :            :     // List formats from more complex to less complex.
     129                 :            :     // TODO: Add more.
     130                 :            :     static const char* ranks[] = {
     131                 :            :         // Compressed XML
     132                 :            :         "writer8_template",
     133                 :            :         "writer8",
     134                 :            :         "calc8_template",
     135                 :            :         "calc8",
     136                 :            :         "writer_OOXML_Text_Template",
     137                 :            :         "writer_OOXML",
     138                 :            :         "writer_MS_Word_2007_Template",
     139                 :            :         "writer_MS_Word_2007",
     140                 :            :         "Office Open XML Spreadsheet Template",
     141                 :            :         "Office Open XML Spreadsheet",
     142                 :            :         "MS Excel 2007 XML Template",
     143                 :            :         "MS Excel 2007 XML",
     144                 :            : 
     145                 :            :         // Compressed text
     146                 :            :         "pdf_Portable_Document_Format",
     147                 :            : 
     148                 :            :         // Binary
     149                 :            :         "writer_T602_Document",
     150                 :            :         "writer_WordPerfect_Document",
     151                 :            :         "writer_MS_Works_Document",
     152                 :            :         "writer_MS_Word_97_Vorlage",
     153                 :            :         "writer_MS_Word_97",
     154                 :            :         "writer_MS_Word_95_Vorlage",
     155                 :            :         "writer_MS_Word_95",
     156                 :            :         "writer_MS_WinWord_60",
     157                 :            :         "writer_MS_WinWord_5",
     158                 :            :         "MS Excel 2007 Binary",
     159                 :            :         "calc_MS_Excel_97_VorlageTemplate",
     160                 :            :         "calc_MS_Excel_97",
     161                 :            :         "calc_MS_Excel_95_VorlageTemplate",
     162                 :            :         "calc_MS_Excel_95",
     163                 :            :         "calc_MS_Excel_5095_VorlageTemplate",
     164                 :            :         "calc_MS_Excel_5095",
     165                 :            :         "calc_MS_Excel_40_VorlageTemplate",
     166                 :            :         "calc_MS_Excel_40",
     167                 :            :         "calc_Pocket_Excel_File",
     168                 :            :         "calc_Lotus",
     169                 :            :         "calc_QPro",
     170                 :            :         "calc_SYLK",
     171                 :            :         "calc_DIF",
     172                 :            :         "calc_dBase",
     173                 :            : 
     174                 :            : 
     175                 :            :         // Non-compressed XML
     176                 :            :         "writer_ODT_FlatXML",
     177                 :            :         "calc_ODS_FlatXML",
     178                 :            :         "calc_MS_Excel_2003_XML",
     179                 :            :         "writer_MS_Word_2003_XML",
     180                 :            :         "writer_DocBook_File",
     181                 :            :         "XHTML_File",
     182                 :            : 
     183                 :            :         // Non-compressed text
     184                 :            :         "writer_Rich_Text_Format",
     185                 :            :         "generic_HTML",
     186                 :            :         "generic_Text"
     187                 :            :     };
     188                 :            : 
     189                 :       2080 :     size_t n = SAL_N_ELEMENTS(ranks);
     190                 :            : 
     191         [ +  + ]:      50803 :     for (size_t i = 0; i < n; ++i)
     192                 :            :     {
     193         [ +  + ]:      50716 :         if (rType.equalsAscii(ranks[i]))
     194                 :       1993 :             return n - i - 1;
     195                 :            :     }
     196                 :            : 
     197                 :            :     // Not ranked.  Treat them equally.  Unranked formats have higher priority
     198                 :            :     // than the ranked internal ones since they may be defined externally.
     199                 :       2080 :     return n;
     200                 :            : }
     201                 :            : 
     202                 :            : /**
     203                 :            :  * Types with matching pattern first, then extension, then custom ranks by
     204                 :            :  * types, then types that are supported by the document service come next.
     205                 :            :  * Lastly, sort them alphabetically.
     206                 :            :  */
     207                 :            : struct SortByPriority : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
     208                 :            : {
     209                 :       1075 :     bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
     210                 :            :     {
     211         [ -  + ]:       1075 :         if (r1.bMatchByPattern != r2.bMatchByPattern)
     212                 :          0 :             return r1.bMatchByPattern;
     213                 :            : 
     214         [ +  + ]:       1075 :         if (r1.bMatchByExtension != r2.bMatchByExtension)
     215                 :         35 :             return r1.bMatchByExtension;
     216                 :            : 
     217                 :       1040 :         int rank1 = getFlatTypeRank(r1.sType);
     218                 :       1040 :         int rank2 = getFlatTypeRank(r2.sType);
     219                 :            : 
     220         [ +  + ]:       1040 :         if (rank1 != rank2)
     221                 :       1016 :             return rank1 > rank2;
     222                 :            : 
     223         [ +  + ]:         24 :         if (r1.bPreselectedByDocumentService != r2.bPreselectedByDocumentService)
     224                 :          5 :             return r1.bPreselectedByDocumentService;
     225                 :            : 
     226                 :            :         // All things being equal, sort them alphabetically.
     227                 :       1075 :         return r1.sType > r2.sType;
     228                 :            :     }
     229                 :            : };
     230                 :            : 
     231                 :            : struct EqualByName : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
     232                 :            : {
     233                 :        506 :     bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
     234                 :            :     {
     235                 :        506 :         return r1.sType == r2.sType;
     236                 :            :     }
     237                 :            : };
     238                 :            : 
     239                 :            : }
     240                 :            : 
     241                 :       1757 : ::rtl::OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
     242                 :            :                                                               sal_Bool                                         bAllowDeep )
     243                 :            :     throw (css::uno::RuntimeException)
     244                 :            : {
     245                 :            :     // make the descriptor more useable :-)
     246         [ +  - ]:       1757 :     ::comphelper::MediaDescriptor stlDescriptor(lDescriptor);
     247                 :            : 
     248                 :            :     // SAFE -> ----------------------------------
     249         [ +  - ]:       1757 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     250                 :            : 
     251                 :            :     //*******************************************
     252                 :            :     // parse given URL to split it into e.g. main and jump marks ...
     253 [ +  - ][ +  - ]:       1757 :     ::rtl::OUString sURL = stlDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString());
     254                 :            : 
     255                 :            : #if OSL_DEBUG_LEVEL > 0
     256                 :            :     if (stlDescriptor.find(::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ))) != stlDescriptor.end())
     257                 :            :         OSL_FAIL("Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
     258                 :            : #endif
     259                 :            : 
     260                 :       1757 :     css::util::URL  aURL;
     261                 :       1757 :     aURL.Complete = sURL;
     262 [ +  - ][ +  - ]:       1757 :     css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(comphelper::ComponentContext(m_xSMGR).getUNOContext()));
         [ +  - ][ +  - ]
     263 [ +  - ][ +  - ]:       1757 :     xParser->parseStrict(aURL);
     264                 :            : 
     265                 :            :     rtl::OUString aSelectedFilter = stlDescriptor.getUnpackedValueOrDefault(
     266 [ +  - ][ +  - ]:       1757 :         comphelper::MediaDescriptor::PROP_FILTERNAME(), rtl::OUString());
     267         [ -  + ]:       1757 :     if (!aSelectedFilter.isEmpty())
     268                 :            :     {
     269                 :            :         // Caller specified the filter type.  Honor it.  Just get the default
     270                 :            :         // type for that filter, and bail out.
     271 [ #  # ][ #  # ]:          0 :         if (impl_validateAndSetFilterOnDescriptor(stlDescriptor, aSelectedFilter))
     272 [ #  # ][ #  # ]:          0 :             return stlDescriptor[comphelper::MediaDescriptor::PROP_TYPENAME()].get<rtl::OUString>();
                 [ #  # ]
     273                 :            :     }
     274                 :            : 
     275                 :            :     // preselected type or document service? use it as first "flat" detected
     276                 :            :     // type later!
     277         [ +  - ]:       1757 :     FlatDetection lFlatTypes;
     278         [ +  - ]:       1757 :     impl_getPreselection(aURL, stlDescriptor, lFlatTypes);
     279                 :            : 
     280                 :            :     //*******************************************
     281                 :            :     // get all types, which match to the given descriptor
     282                 :            :     // That can be true by: extensions/url pattern/mime type etcpp.
     283 [ +  - ][ +  - ]:       1757 :     m_rCache->detectFlatForURL(aURL, lFlatTypes);
     284                 :            : 
     285         [ +  - ]:       1757 :     aLock.clear();
     286                 :            :     // <- SAFE ----------------------------------
     287                 :            : 
     288                 :            :     // Properly prioritize all candidate types.
     289         [ +  - ]:       1757 :     lFlatTypes.sort(SortByPriority());
     290         [ +  - ]:       1757 :     lFlatTypes.unique(EqualByName());
     291                 :            : 
     292                 :       1757 :     ::rtl::OUString sType      ;
     293                 :       1757 :     ::rtl::OUString sLastChance;
     294                 :            : 
     295                 :            :     try
     296                 :            :     {
     297                 :            :         //*******************************************
     298                 :            :         // verify every flat detected (or preselected!) type
     299                 :            :         // by calling its registered deep detection service.
     300                 :            :         // But break this loop if a type match to the given descriptor
     301                 :            :         // by an URL pattern(!) or if deep detection isnt allowed from
     302                 :            :         // outside (bAllowDeep=sal_False) or break the whole detection by
     303                 :            :         // throwing an exception if creation of the might needed input
     304                 :            :         // stream failed by e.g. an IO exception ...
     305         [ +  - ]:       1757 :         OUStringList lUsedDetectors;
     306         [ +  + ]:       1757 :         if (lFlatTypes.size()>0)
     307         [ +  - ]:       1599 :             sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, lUsedDetectors, sLastChance);
     308                 :            : 
     309                 :            :         //*******************************************
     310                 :            :         // if no flat detected (nor preselected!) type could be
     311                 :            :         // verified and no error occurred during creation of
     312                 :            :         // the might needed input stream, start detection
     313                 :            :         // which uses all registered deep detection services.
     314 [ +  - ][ +  + ]:       1757 :         if (
                 [ +  + ]
     315                 :       1757 :             (sType.isEmpty()) &&
     316                 :            :             (bAllowDeep        )
     317                 :            :            )
     318                 :            :         {
     319         [ +  - ]:        166 :             sType = impl_detectTypeDeepOnly(stlDescriptor, lUsedDetectors);
     320                 :            :         }
     321                 :            : 
     322                 :            :         //*******************************************
     323                 :            :         // flat detection failed
     324                 :            :         // pure deep detection failed
     325                 :            :         // => ask might existing InteractionHandler
     326                 :            :         // means: ask user for it's decision
     327         [ +  + ]:       1757 :         if (sType.isEmpty())
     328         [ +  - ]:          9 :             sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor);
     329                 :            : 
     330                 :            :         //*******************************************
     331                 :            :         // no real detected type - but a might valid one.
     332                 :            :         // update descriptor and set last chance for return.
     333 [ +  + ][ -  + ]:       1757 :         if (sType.isEmpty() && !sLastChance.isEmpty())
                 [ -  + ]
     334                 :            :         {
     335                 :            :             OSL_FAIL("set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!");
     336                 :          0 :             sType = sLastChance;
     337                 :       1757 :         }
     338                 :            :     }
     339      [ #  #  # ]:          0 :     catch(const css::uno::RuntimeException&)
     340                 :          0 :         { throw; }
     341         [ #  # ]:          0 :     catch(const css::uno::Exception&)
     342                 :          0 :         { sType = ::rtl::OUString(); }
     343                 :            : 
     344                 :            :     //*******************************************
     345                 :            :     // adapt media descriptor, so it contains the right values
     346                 :            :     // for type/filter name/document service/ etcpp.
     347         [ +  - ]:       1757 :     impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!!
     348         [ +  - ]:       1757 :     impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType);
     349                 :            : 
     350         [ +  - ]:       1757 :     stlDescriptor >> lDescriptor;
     351 [ +  - ][ +  - ]:       1757 :     return sType;
     352                 :            : }
     353                 :            : 
     354                 :            : 
     355                 :            : 
     356                 :       1757 : void TypeDetection::impl_checkResultsAndAddBestFilter(::comphelper::MediaDescriptor& rDescriptor,
     357                 :            :                                                       ::rtl::OUString&               sType      )
     358                 :            : {
     359                 :            :     // a)
     360                 :            :     // Dont overwrite a might preselected filter!
     361                 :            :     ::rtl::OUString sFilter = rDescriptor.getUnpackedValueOrDefault(
     362         [ +  - ]:       1757 :                                 ::comphelper::MediaDescriptor::PROP_FILTERNAME(),
     363         [ +  - ]:       3514 :                                 ::rtl::OUString());
     364         [ -  + ]:       1757 :     if (!sFilter.isEmpty())
     365                 :            :         return;
     366                 :            : 
     367                 :            :     // b)
     368                 :            :     // check a preselected document service too.
     369                 :            :     // Then we have to search a suitable filter witin this module.
     370                 :            :     ::rtl::OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault(
     371         [ +  - ]:       1757 :                                             ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(),
     372         [ +  - ]:       3514 :                                             ::rtl::OUString());
     373         [ +  + ]:       1757 :     if (!sDocumentService.isEmpty())
     374                 :            :     {
     375                 :            :         try
     376                 :            :         {
     377                 :          5 :             ::rtl::OUString sRealType = sType;
     378                 :            : 
     379                 :            :             // SAFE ->
     380         [ +  - ]:          5 :             ::osl::ResettableMutexGuard aLock(m_aLock);
     381                 :            : 
     382                 :            :             // Attention: For executing next lines of code, We must be shure that
     383                 :            :             // all filters already loaded :-(
     384                 :            :             // That can disturb our "load on demand feature". But we have no other chance!
     385 [ +  - ][ +  - ]:          5 :             m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     386                 :            : 
     387         [ +  - ]:          5 :             CacheItem lIProps;
     388 [ +  - ][ +  - ]:          5 :             lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService;
     389 [ +  - ][ +  - ]:          5 :             lIProps[PROPNAME_TYPE           ] <<= sRealType;
     390 [ +  - ][ +  - ]:          5 :             OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
         [ +  - ][ +  - ]
     391                 :            : 
     392         [ +  - ]:          5 :             aLock.clear();
     393                 :            :             // <- SAFE
     394                 :            : 
     395 [ +  - ][ +  - ]:         20 :             for (OUStringList::const_iterator pIt  = lFilters.begin();
                 [ +  + ]
     396                 :         10 :                   pIt != lFilters.end(); ++pIt)
     397                 :            :             {
     398                 :            :                 // SAFE ->
     399         [ +  - ]:          5 :                 aLock.reset();
     400                 :            :                 try
     401                 :            :                 {
     402 [ +  - ][ +  - ]:          5 :                     CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt);
     403                 :          5 :                     sal_Int32 nFlags  = 0;
     404         [ +  - ]:          5 :                     aFilter[PROPNAME_FLAGS] >>= nFlags;
     405                 :            : 
     406         [ +  - ]:          5 :                     if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
     407                 :          5 :                         sFilter = *pIt;
     408         [ -  + ]:          5 :                     if ((nFlags & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED)
     409 [ +  - ][ +  - ]:          5 :                         break;
                 [ #  # ]
     410                 :            :                 }
     411         [ #  # ]:          0 :                 catch(const css::uno::Exception&) {}
     412         [ +  - ]:          5 :                 aLock.clear();
     413                 :            :                 // <- SAFE
     414                 :            :             }
     415                 :            : 
     416         [ +  - ]:          5 :             if (!sFilter.isEmpty())
     417                 :            :             {
     418 [ +  - ][ +  - ]:          5 :                 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sRealType;
                 [ +  - ]
     419 [ +  - ][ +  - ]:          5 :                 rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
                 [ +  - ]
     420                 :          5 :                 sType = sRealType;
     421                 :            :                 return;
     422 [ +  - ][ +  - ]:          5 :             }
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
                 [ #  # ]
     423                 :            :         }
     424         [ #  # ]:          0 :         catch(const css::uno::Exception&)
     425                 :            :             {}
     426                 :            :     }
     427                 :            : 
     428                 :            :     // c)
     429                 :            :     // We can use the preferred filter for the specified type.
     430                 :            :     // Such preferred filter points:
     431                 :            :     // - to the default filter of the preferred application
     432                 :            :     // - or to any other filter if no preferred filter was set.
     433                 :            :     // Note: It's an optimization only!
     434                 :            :     // It's not guaranteed, that such preferred filter exists.
     435                 :       1752 :     sFilter = ::rtl::OUString();
     436                 :            :     try
     437                 :            :     {
     438                 :            :         // SAFE ->
     439         [ +  - ]:       1752 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     440                 :            : 
     441 [ +  - ][ +  + ]:       1752 :         CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
     442         [ +  - ]:       1743 :         aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
     443 [ +  + ][ +  - ]:       1743 :         CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
     444                 :            : 
     445         [ +  - ]:       1741 :         aLock.clear();
     446                 :            :         // <- SAFE
     447                 :            : 
     448                 :            :         // no exception => found valid type and filter => set it on the given descriptor
     449 [ +  - ][ +  - ]:       1741 :         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
                 [ +  - ]
     450 [ +  - ][ +  - ]:       1741 :         rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
                 [ +  - ]
     451 [ +  - ][ +  - ]:       1752 :         return;
         [ +  - ][ -  + ]
     452                 :            :     }
     453         [ +  - ]:         11 :     catch(const css::uno::Exception&)
     454                 :            :         {}
     455                 :            : 
     456                 :            :     // d)
     457                 :            :     // Search for any import(!) filter, which is registered for this type.
     458                 :         11 :     sFilter = ::rtl::OUString();
     459                 :            :     try
     460                 :            :     {
     461                 :            :         // SAFE ->
     462         [ +  - ]:         11 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     463                 :            : 
     464                 :            :         // Attention: For executing next lines of code, We must be shure that
     465                 :            :         // all filters already loaded :-(
     466                 :            :         // That can disturb our "load on demand feature". But we have no other chance!
     467 [ +  - ][ +  - ]:         11 :         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     468                 :            : 
     469         [ +  - ]:         11 :         CacheItem lIProps;
     470 [ +  - ][ +  - ]:         11 :         lIProps[PROPNAME_TYPE] <<= sType;
     471 [ +  - ][ +  - ]:         11 :         OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
         [ +  - ][ +  - ]
     472                 :            : 
     473         [ +  - ]:         11 :         aLock.clear();
     474                 :            :         // <- SAFE
     475                 :            : 
     476                 :         11 :         OUStringList::const_iterator pIt;
     477 [ +  - ][ +  - ]:         22 :         for (  pIt  = lFilters.begin();
                 [ -  + ]
     478                 :         11 :                pIt != lFilters.end()  ;
     479                 :            :              ++pIt                    )
     480                 :            :         {
     481                 :          0 :             sFilter = *pIt;
     482                 :            : 
     483                 :            :             // SAFE ->
     484         [ #  # ]:          0 :             aLock.reset();
     485                 :            :             try
     486                 :            :             {
     487   [ #  #  #  # ]:          0 :                 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
     488                 :          0 :                 sal_Int32 nFlags  = 0;
     489         [ #  # ]:          0 :                 aFilter[PROPNAME_FLAGS] >>= nFlags;
     490                 :            : 
     491         [ #  # ]:          0 :                 if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
     492   [ #  #  #  #  :          0 :                     break;
                   #  # ]
     493                 :            :             }
     494         [ #  # ]:          0 :             catch(const css::uno::Exception&)
     495                 :          0 :                 { continue; }
     496         [ #  # ]:          0 :             aLock.clear();
     497                 :            :             // <- SAFE
     498                 :            : 
     499                 :          0 :             sFilter = ::rtl::OUString();
     500                 :            :         }
     501                 :            : 
     502         [ -  + ]:         11 :         if (!sFilter.isEmpty())
     503                 :            :         {
     504   [ #  #  #  #  :          0 :             rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
                   #  # ]
     505   [ #  #  #  #  :         11 :             rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
                   #  # ]
     506                 :            :             return;
     507 [ -  + ][ +  - ]:         11 :         }
         [ -  + ][ +  - ]
         [ +  - ][ #  # ]
     508                 :            :     }
     509         [ #  # ]:          0 :     catch(const css::uno::Exception&)
     510 [ +  + ][ +  + ]:       1757 :         {}
     511                 :            : }
     512                 :            : 
     513                 :            : 
     514                 :            : 
     515                 :        165 : sal_Bool TypeDetection::impl_getPreselectionForType(const ::rtl::OUString& sPreSelType,
     516                 :            :                                                     const css::util::URL&  aParsedURL ,
     517                 :            :                                                           FlatDetection&   rFlatTypes )
     518                 :            : {
     519                 :            :     // Can be used to supress execution of some parts of this method
     520                 :            :     // if its already clear that detected type is valid or not.
     521                 :            :     // Its neccessary to use shared code at the end, which update
     522                 :            :     // all return parameters constistency!
     523                 :        165 :     sal_Bool bBreakDetection = sal_False;
     524                 :            : 
     525                 :            :     // Further we must know if it matches by pattern
     526                 :            :     // Every flat detected type by pattern wont be detected deep!
     527                 :        165 :     sal_Bool bMatchByPattern = sal_False;
     528                 :            : 
     529                 :            :     // And we must know if a preselection must be preferred, because
     530                 :            :     // it matches by it's extension too.
     531                 :        165 :     sal_Bool bMatchByExtension = sal_False;
     532                 :            : 
     533                 :            :     // If we e.g. collect all filters of a factory (be a forced factory preselection)
     534                 :            :     // we should preferr all filters of this factory, where the type match the given URL.
     535                 :            :     // All other types (which sorrespond to filters of the same factory - but dont match
     536                 :            :     // the URL) should be "used later" for detection and sorted at the end of our return vector
     537                 :            :     // rFlatTypes!
     538                 :            :     // => bPreferredPreselection = (matchByExtension || matchByURLPattern)
     539                 :        165 :     sal_Bool bPreferredPreselection = sal_False;
     540                 :            : 
     541                 :            :     // validate type
     542                 :        165 :     ::rtl::OUString sType(sPreSelType);
     543         [ +  - ]:        165 :     CacheItem       aType;
     544                 :            :     try
     545                 :            :     {
     546                 :            :         // SAFE -> --------------------------
     547         [ +  - ]:        165 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     548 [ +  - ][ +  - ]:        165 :         aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
         [ +  - ][ +  - ]
     549 [ +  - ][ +  - ]:        165 :         aLock.clear();
                 [ #  # ]
     550                 :            :         // <- SAFE --------------------------
     551                 :            :     }
     552         [ #  # ]:          0 :     catch(const css::container::NoSuchElementException&)
     553                 :            :     {
     554                 :          0 :         sType = ::rtl::OUString();
     555                 :          0 :         bBreakDetection = sal_True;
     556                 :            :     }
     557                 :            : 
     558         [ +  - ]:        165 :     if (!bBreakDetection)
     559                 :            :     {
     560                 :            :         // We cant check a preselected type for a given stream!
     561                 :            :         // So we must believe, that it can work ...
     562         [ -  + ]:        165 :         if ( aParsedURL.Complete == "private:stream" )
     563                 :          0 :             bBreakDetection = sal_True;
     564                 :            :     }
     565                 :            : 
     566         [ +  - ]:        165 :     if (!bBreakDetection)
     567                 :            :     {
     568                 :            :         // extract extension from URL .. to check it case-insensitive !
     569         [ +  - ]:        165 :         INetURLObject   aParser    (aParsedURL.Main);
     570                 :            :         ::rtl::OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT       ,
     571                 :            :                                                           sal_True                          ,
     572         [ +  - ]:        165 :                                                           INetURLObject::DECODE_WITH_CHARSET);
     573                 :        165 :         sExtension = sExtension.toAsciiLowerCase();
     574                 :            : 
     575                 :            :         // otherwhise we must know, if it matches to the given URL realy.
     576                 :            :         // especialy if it matches by its extension or pattern registration.
     577 [ +  - ][ +  - ]:        165 :         OUStringList lExtensions(aType[PROPNAME_EXTENSIONS]);
     578 [ +  - ][ +  - ]:        165 :         OUStringList lURLPattern(aType[PROPNAME_URLPATTERN]);
     579                 :            : 
     580 [ +  - ][ +  + ]:        935 :         for (OUStringList::const_iterator pIt  = lExtensions.begin();
                 [ +  - ]
     581                 :        465 :                                           pIt != lExtensions.end()  ;
     582                 :            :                                         ++pIt                       )
     583                 :            :         {
     584                 :        305 :             ::rtl::OUString sCheckExtension(pIt->toAsciiLowerCase());
     585         [ +  + ]:        305 :             if (sCheckExtension.equals(sExtension))
     586                 :            :             {
     587                 :          5 :                 bBreakDetection        = sal_True;
     588                 :          5 :                 bMatchByExtension      = sal_True;
     589                 :        305 :                 bPreferredPreselection = sal_True;
     590                 :            :                 break;
     591                 :            :             }
     592         [ +  + ]:        305 :         }
     593                 :            : 
     594         [ +  + ]:        165 :         if (!bBreakDetection)
     595                 :            :         {
     596 [ +  - ][ +  - ]:        350 :             for (OUStringList::const_iterator pIt  = lURLPattern.begin();
                 [ +  + ]
     597                 :        175 :                                               pIt != lURLPattern.end()  ;
     598                 :            :                                             ++pIt                       )
     599                 :            :             {
     600         [ +  - ]:         15 :                 WildCard aCheck(*pIt);
     601 [ +  - ][ +  - ]:         15 :                 if (aCheck.Matches(aParsedURL.Main))
         [ +  - ][ -  + ]
     602                 :            :                 {
     603                 :          0 :                     bBreakDetection        = sal_True;
     604                 :          0 :                     bMatchByPattern        = sal_True;
     605                 :         15 :                     bPreferredPreselection = sal_True;
     606                 :            :                     break;
     607                 :            :                 }
     608 [ +  - ][ +  - ]:         15 :             }
     609         [ +  - ]:        165 :         }
     610                 :            :     }
     611                 :            : 
     612                 :            :     // if its a valid type - set it on all return values!
     613         [ +  - ]:        165 :     if (!sType.isEmpty())
     614                 :            :     {
     615                 :        165 :         FlatDetectionInfo aInfo;
     616                 :        165 :         aInfo.sType              = sType;
     617                 :        165 :         aInfo.bMatchByExtension  = bMatchByExtension;
     618                 :        165 :         aInfo.bMatchByPattern    = bMatchByPattern;
     619                 :            : 
     620         [ +  + ]:        165 :         if (bPreferredPreselection)
     621         [ +  - ]:          5 :             rFlatTypes.push_front(aInfo);
     622                 :            :         else
     623         [ +  - ]:        160 :             rFlatTypes.push_back(aInfo);
     624                 :            : 
     625                 :        165 :         return sal_True;
     626                 :            :     }
     627                 :            : 
     628                 :            :     // not valid!
     629         [ +  - ]:        165 :     return sal_False;
     630                 :            : }
     631                 :            : 
     632                 :            : 
     633                 :            : 
     634                 :        165 : sal_Bool TypeDetection::impl_getPreselectionForFilter(const ::rtl::OUString& sPreSelFilter,
     635                 :            :                                                       const css::util::URL&  aParsedURL   ,
     636                 :            :                                                             FlatDetection&   rFlatTypes   )
     637                 :            : {
     638                 :            :     // Can be used to supress execution of some parts of this method
     639                 :            :     // if its already clear that detected filter is valid or not.
     640                 :            :     // Its neccessary to use shared code at the end, which update
     641                 :            :     // all return parameters constistency!
     642                 :        165 :     sal_Bool bBreakDetection = sal_False;
     643                 :            : 
     644                 :            :     // validate filter
     645                 :        165 :     ::rtl::OUString sFilter(sPreSelFilter);
     646         [ +  - ]:        165 :     CacheItem       aFilter;
     647                 :            :     try
     648                 :            :     {
     649                 :            :         // SAFE -> --------------------------
     650         [ +  - ]:        165 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     651 [ +  - ][ +  - ]:        165 :         aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
         [ +  - ][ +  - ]
     652 [ +  - ][ +  - ]:        165 :         aLock.clear();
                 [ #  # ]
     653                 :            :         // <- SAFE --------------------------
     654                 :            :     }
     655         [ #  # ]:          0 :     catch(const css::container::NoSuchElementException&)
     656                 :            :     {
     657                 :          0 :         sFilter = ::rtl::OUString();
     658                 :          0 :         bBreakDetection = sal_True;
     659                 :            :     }
     660                 :            : 
     661         [ +  - ]:        165 :     if (!bBreakDetection)
     662                 :            :     {
     663                 :            :         // get its type and check if it matches the given URL
     664                 :        165 :         ::rtl::OUString sType;
     665         [ +  - ]:        165 :         aFilter[PROPNAME_TYPE] >>= sType;
     666                 :            : 
     667         [ +  - ]:        165 :         bBreakDetection = impl_getPreselectionForType(sType, aParsedURL, rFlatTypes);
     668                 :            : 
     669                 :            :         // not a valid type? -> not a valid filter!
     670         [ -  + ]:        165 :         if (!bBreakDetection)
     671                 :        165 :             sFilter = ::rtl::OUString();
     672                 :            :     }
     673                 :            : 
     674         [ +  - ]:        165 :     if (!sFilter.isEmpty())
     675                 :        165 :         return sal_True;
     676                 :            :     else
     677         [ +  - ]:        165 :         return sal_False;
     678                 :            : }
     679                 :            : 
     680                 :            : 
     681                 :            : 
     682                 :          5 : sal_Bool TypeDetection::impl_getPreselectionForDocumentService(const ::rtl::OUString& sPreSelDocumentService,
     683                 :            :                                                                const css::util::URL&  aParsedURL            ,
     684                 :            :                                                                      FlatDetection&   rFlatTypes            )
     685                 :            : {
     686                 :            :     // get all filters, which match to this doc service
     687         [ +  - ]:          5 :     OUStringList lFilters;
     688                 :            :     try
     689                 :            :     {
     690                 :            :         // SAFE -> --------------------------
     691         [ +  - ]:          5 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     692                 :            : 
     693                 :            :         // Attention: For executing next lines of code, We must be shure that
     694                 :            :         // all filters already loaded :-(
     695                 :            :         // That can disturb our "load on demand feature". But we have no other chance!
     696 [ +  - ][ +  - ]:          5 :         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     697                 :            : 
     698         [ +  - ]:          5 :         CacheItem lIProps;
     699 [ +  - ][ +  - ]:          5 :         lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService;
     700 [ +  - ][ +  - ]:          5 :         lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
         [ +  - ][ +  - ]
                 [ +  - ]
     701                 :            : 
     702 [ +  - ][ +  - ]:          5 :         aLock.clear();
         [ +  - ][ #  # ]
     703                 :            :         // <- SAFE --------------------------
     704                 :            :     }
     705         [ #  # ]:          0 :     catch(const css::container::NoSuchElementException&)
     706                 :            :     {
     707                 :          0 :         lFilters.clear();
     708                 :            :     }
     709                 :            : 
     710                 :            :     // step over all filters, and check if its registered type
     711                 :            :     // match the given URL.
     712                 :            :     // But use temp. list of "preselected types" instead of incoming rFlatTypes list!
     713                 :            :     // The reason behind: we must filter the getted results. And copying of stl entries
     714                 :            :     // is an easier job then removing it .-)
     715         [ +  - ]:          5 :     FlatDetection lPreselections;
     716 [ +  - ][ +  - ]:        340 :     for (OUStringList::const_iterator pFilter  = lFilters.begin();
                 [ +  + ]
     717                 :        170 :                                       pFilter != lFilters.end()  ;
     718                 :            :                                     ++pFilter                    )
     719                 :            :     {
     720                 :        165 :         const ::rtl::OUString sFilter = *pFilter;
     721         [ +  - ]:        165 :         impl_getPreselectionForFilter(sFilter, aParsedURL, lPreselections);
     722                 :        165 :     }
     723                 :            : 
     724                 :            :     // We have to mark all retrieved preselection items as "preselected by document service".
     725                 :            :     // Further we must ignore all preselected items, which does not match the URL!
     726                 :          5 :     FlatDetection::iterator pIt;
     727         [ +  + ]:        340 :     for (  pIt  = lPreselections.begin();
     728                 :        170 :            pIt != lPreselections.end()  ;
     729                 :            :          ++pIt                          )
     730                 :            :     {
     731                 :        165 :         FlatDetectionInfo& rInfo = *pIt;
     732                 :        165 :         rInfo.bPreselectedByDocumentService = sal_True ;
     733         [ +  - ]:        165 :         rFlatTypes.push_back(rInfo);
     734                 :            :     }
     735                 :            : 
     736                 :          5 :     return sal_True;
     737                 :            : }
     738                 :            : 
     739                 :            : 
     740                 :            : 
     741                 :       1757 : void TypeDetection::impl_getPreselection(const css::util::URL&                aParsedURL ,
     742                 :            :                                                ::comphelper::MediaDescriptor& rDescriptor,
     743                 :            :                                                FlatDetection&                 rFlatTypes )
     744                 :            : {
     745                 :            :     // done to be shure, that only valid results leave this function!
     746                 :       1757 :     rFlatTypes.clear();
     747                 :            : 
     748                 :            :     /* #i55122#
     749                 :            :         Sometimes we must detect files without or with real unknown extensions.
     750                 :            :         If it does not work /which can happen of course .-)/, the user tried to preselect
     751                 :            :         the right format. But some special dialogs (e.g. "Insert->Sheet From File")
     752                 :            :         add it's own preselection too.
     753                 :            :         So we have a combination of preselected values ...
     754                 :            : 
     755                 :            :         The we should preferr the most important one - set by the user.
     756                 :            :         And the user normaly preselects a filter or type. The preslected
     757                 :            :         document service cames from the dialog.
     758                 :            : 
     759                 :            :         Further it doesnt matter if the user preselected a filter or a document service.
     760                 :            :         A filter selection is always more explicit then a document service selection.
     761                 :            :         So it must be pereferred. An order between type and filter selection cant be discussed .-)
     762                 :            :     */
     763                 :            : 
     764 [ +  - ][ +  - ]:       1757 :     ::rtl::OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
     765         [ -  + ]:       1757 :     if (!sSelectedType.isEmpty())
     766         [ #  # ]:          0 :         impl_getPreselectionForType(sSelectedType, aParsedURL, rFlatTypes);
     767                 :            : 
     768 [ +  - ][ +  - ]:       1757 :     ::rtl::OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), ::rtl::OUString());
     769         [ +  + ]:       1757 :     if (!sSelectedDoc.isEmpty())
     770         [ +  - ]:       1757 :         impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes);
     771                 :       1757 : }
     772                 :            : 
     773                 :            : 
     774                 :            : 
     775                 :       1599 : ::rtl::OUString TypeDetection::impl_detectTypeFlatAndDeep(      ::comphelper::MediaDescriptor& rDescriptor   ,
     776                 :            :                                                           const FlatDetection&                 lFlatTypes    ,
     777                 :            :                                                                 sal_Bool                       bAllowDeep    ,
     778                 :            :                                                                 OUStringList&                  rUsedDetectors,
     779                 :            :                                                                 ::rtl::OUString&               rLastChance   )
     780                 :            : {
     781                 :            :     // reset it everytimes, so the outside code can distinguish between
     782                 :            :     // a set and a not set value.
     783                 :       1599 :     rLastChance = ::rtl::OUString();
     784                 :       1599 :     rUsedDetectors.clear();
     785                 :            : 
     786                 :            :     // step over all possible types for this URL.
     787                 :            :     // solutions:
     788                 :            :     // a) no types                                => no detection
     789                 :            :     // b) deep detection not allowed              => return first valid type of list (because its the preferred or the first valid one)
     790                 :            :     //    or(!) match by URLPattern               => in such case a deep detection will be supressed!
     791                 :            :     // c) type has no detect service              => safe the first occurred type without a detect service
     792                 :            :     //                                               as "last chance"(!). It will be used outside of this method
     793                 :            :     //                                               if no further type could be detected.
     794                 :            :     //                                               It must be the first one, because it can be a preferred type.
     795                 :            :     //                                               Our types list was sorted by such criteria!
     796                 :            :     // d) detect service return a valid result    => return its decision
     797                 :            :     // e) detect service return an invalid result
     798                 :            :     //    or any needed information could not be
     799                 :            :     //    getted from the cache                   => ignore it, and continue with search
     800                 :            : 
     801         [ +  + ]:       3230 :     for (FlatDetection::const_iterator pFlatIt  = lFlatTypes.begin();
     802                 :       1615 :                                        pFlatIt != lFlatTypes.end()  ;
     803                 :            :                                      ++pFlatIt                      )
     804                 :            :     {
     805                 :       1607 :         const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt;
     806                 :       1607 :               ::rtl::OUString    sFlatType     = aFlatTypeInfo.sType;
     807                 :            : 
     808 [ -  + ][ +  - ]:       1607 :         if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType))
     809                 :          0 :             continue;
     810                 :            : 
     811                 :            :         // b)
     812 [ +  - ][ +  + ]:       1607 :         if (
     813                 :            :             (!bAllowDeep                  ) ||
     814                 :            :             (aFlatTypeInfo.bMatchByPattern)
     815                 :            :            )
     816                 :            :         {
     817                 :       1123 :             return sFlatType;
     818                 :            :         }
     819                 :            : 
     820                 :            :         try
     821                 :            :         {
     822                 :            :             // SAFE -> ----------------------------------
     823         [ +  - ]:        484 :             ::osl::ResettableMutexGuard aLock(m_aLock);
     824 [ +  - ][ +  - ]:        484 :             CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType);
     825         [ +  - ]:        484 :             aLock.clear();
     826                 :            : 
     827                 :        484 :             ::rtl::OUString sDetectService;
     828         [ +  - ]:        484 :             aType[PROPNAME_DETECTSERVICE] >>= sDetectService;
     829                 :            : 
     830                 :            :             // c)
     831         [ +  + ]:        484 :             if (sDetectService.isEmpty())
     832                 :            :             {
     833                 :            :                 // flat detected types without any registered deep detection service and not
     834                 :            :                 // preselected by the user can be used as LAST CHANCE in case no other type could
     835                 :            :                 // be detected. Of course only the first type without deep detector can be used.
     836                 :            :                 // Further ones has to be ignored.
     837         [ +  - ]:          8 :                 if (rLastChance.isEmpty())
     838                 :          8 :                     rLastChance = sFlatType;
     839                 :            : 
     840                 :          8 :                 continue;
     841                 :            :             }
     842                 :            : 
     843                 :            :             // dont forget to add every real asked deep detection service here.
     844                 :            :             // Such detectors will be ignored if may be "impl_detectTypeDeepOnly()"
     845                 :            :             // must be called later!
     846         [ +  - ]:        476 :             rUsedDetectors.push_back(sDetectService);
     847         [ +  - ]:        476 :             ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
     848                 :            : 
     849                 :            :             // d)
     850         [ +  + ]:        476 :             if (!sDeepType.isEmpty())
     851         [ +  + ]:        484 :                 return sDeepType;
              [ +  +  + ]
                 [ +  - ]
              [ +  +  + ]
                 [ +  - ]
              [ +  +  + ]
                 [ #  # ]
     852                 :            :         }
     853         [ #  # ]:          0 :         catch(const css::container::NoSuchElementException&)
     854                 :            :             {}
     855                 :            :         // e)
     856      [ +  +  + ]:       1607 :     }
     857                 :            : 
     858                 :       1599 :     return ::rtl::OUString();
     859                 :            :     // <- SAFE ----------------------------------
     860                 :            : }
     861                 :            : 
     862                 :            : //TO-DO: add a priority entry to filter config, e.g. defaulting to 50 and
     863                 :            : //flag externally that some filters are lower e.g. 25 and are catch-alls
     864                 :            : //to be tried last. Split up writer/calc/etc. filter detection to standalone
     865                 :            : //those problematic formats
     866                 :            : namespace
     867                 :            : {
     868                 :      21534 :     bool sort_catchalls_to_end(const rtl::OUString& rA, const rtl::OUString& rB)
     869                 :            :     {
     870         [ -  + ]:      21534 :         if (rA == rB)
     871                 :          0 :             return false;
     872         [ +  + ]:      21534 :         if ( rA == "com.sun.star.text.FormatDetector" )
     873                 :        332 :             return false;
     874         [ +  + ]:      21202 :         if ( rB == "com.sun.star.text.FormatDetector" )
     875                 :        156 :             return true;
     876                 :      21534 :         return rA < rB;
     877                 :            :     }
     878                 :            : }
     879                 :            : 
     880                 :        166 : ::rtl::OUString TypeDetection::impl_detectTypeDeepOnly(      ::comphelper::MediaDescriptor& rDescriptor          ,
     881                 :            :                                                        const OUStringList&                  lOutsideUsedDetectors)
     882                 :            : {
     883                 :            :     // We must know if a detect service was already used:
     884                 :            :     //  i) in a combined flat/deep detection scenario outside or
     885                 :            :     // ii) in this method for a deep detection only.
     886                 :            :     // Reason: Such deep detection services work differently in these two modes!
     887         [ +  - ]:        166 :     OUStringList                 lInsideUsedDetectors;
     888                 :        166 :     OUStringList::const_iterator pIt;
     889                 :            : 
     890                 :            :     // a)
     891                 :            :     // The list of "already used detect services" correspond to the list
     892                 :            :     // of preselected or flat detected types. But these detect services was called
     893                 :            :     // to check these types explicitly and return black/white ... yes/no only.
     894                 :            :     // Now they are called to return any possible result. But we should preferr
     895                 :            :     // these already used detect services against all other ones!
     896 [ +  - ][ +  + ]:        336 :     for (  pIt  = lOutsideUsedDetectors.begin();
     897                 :        168 :            pIt != lOutsideUsedDetectors.end()  ;
     898                 :            :          ++pIt                                 )
     899                 :            :     {
     900                 :          2 :         const ::rtl::OUString& sDetectService = *pIt;
     901         [ +  - ]:          2 :               ::rtl::OUString  sDeepType      = impl_askDetectService(sDetectService, rDescriptor);
     902         [ -  + ]:          2 :         if (!sDeepType.isEmpty())
     903                 :          0 :             return sDeepType;
     904 [ +  - ][ +  - ]:          4 :         lInsideUsedDetectors.push_back(sDetectService);
     905                 :          2 :     }
     906                 :            : 
     907                 :            :     // SAFE -> ----------------------------------
     908         [ +  - ]:        166 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     909 [ +  - ][ +  - ]:        166 :     OUStringList lDetectors = m_rCache->getItemNames(FilterCache::E_DETECTSERVICE);
     910         [ +  - ]:        166 :     std::sort(lDetectors.begin(), lDetectors.end(), sort_catchalls_to_end);
     911         [ +  - ]:        166 :     aLock.clear();
     912                 :            :     // <- SAFE ----------------------------------
     913                 :            : 
     914                 :            :     // b)
     915                 :            :     // Sometimes it would be nice to ask a special set of detect services before
     916                 :            :     // any other detect service is asked. E.g. by using a preselection of a DocumentService.
     917                 :            :     // That's needed to prevent us from asking the "wrong application module" and
     918                 :            :     // opening the files into the "wrong application".
     919                 :            :     ::rtl::OUString sPreselDocumentService = rDescriptor.getUnpackedValueOrDefault(
     920         [ +  - ]:        166 :                                                 ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(),
     921         [ +  - ]:        332 :                                                 ::rtl::OUString());
     922         [ -  + ]:        166 :     if (!sPreselDocumentService.isEmpty())
     923                 :            :     {
     924 [ #  # ][ #  # ]:          0 :         for (  pIt  = lDetectors.begin();
                 [ #  # ]
     925                 :          0 :                pIt != lDetectors.end()  ;
     926                 :            :              ++pIt                      )
     927                 :            :         {
     928                 :          0 :             const ::rtl::OUString& sDetectService = *pIt;
     929                 :            : 
     930 [ #  # ][ #  # ]:          0 :             OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService);
     931 [ #  # ][ #  # ]:          0 :             if (pAlreadyUsed != lInsideUsedDetectors.end())
     932                 :          0 :                 continue;
     933                 :            : 
     934                 :            :             // SAFE -> --------------------------------------------------------
     935         [ #  # ]:          0 :             aLock.reset();
     936                 :            : 
     937         [ #  # ]:          0 :             CacheItem lIProps;
     938 [ #  # ][ #  # ]:          0 :             lIProps[PROPNAME_DETECTSERVICE] <<= sDetectService;
     939 [ #  # ][ #  # ]:          0 :             OUStringList lTypes = m_rCache->getMatchingItemsByProps(FilterCache::E_TYPE, lIProps);
         [ #  # ][ #  # ]
     940                 :            : 
     941         [ #  # ]:          0 :             aLock.clear();
     942                 :            :             // <- SAFE --------------------------------------------------------
     943                 :            : 
     944                 :          0 :             sal_Bool bMatchDetectorToDocumentService = sal_False;
     945                 :          0 :             OUStringList::const_iterator pIt2;
     946 [ #  # ][ #  # ]:          0 :             for (  pIt2  = lTypes.begin();
                 [ #  # ]
     947                 :          0 :                    pIt2 != lTypes.end()  ;
     948                 :            :                  ++pIt2                  )
     949                 :            :             {
     950                 :          0 :                 const ::rtl::OUString& sType  = *pIt2;
     951                 :            : 
     952                 :            :                 try
     953                 :            :                 {
     954                 :            :                     // SAFE -> ----------------------------------------------------
     955         [ #  # ]:          0 :                     aLock.reset();
     956                 :            : 
     957 [ #  # ][ #  # ]:          0 :                     CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
     958                 :          0 :                     ::rtl::OUString sFilter;
     959         [ #  # ]:          0 :                     aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
     960 [ #  # ][ #  # ]:          0 :                     CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
     961                 :          0 :                     ::rtl::OUString sCheckDocumentService;
     962         [ #  # ]:          0 :                     aFilter[PROPNAME_DOCUMENTSERVICE] >>= sCheckDocumentService;
     963                 :            : 
     964         [ #  # ]:          0 :                     aLock.clear();
     965                 :            :                     // <- SAFE
     966                 :            : 
     967         [ #  # ]:          0 :                     if (sCheckDocumentService.equals(sPreselDocumentService))
     968                 :            :                     {
     969                 :          0 :                         bMatchDetectorToDocumentService = sal_True;
     970                 :            :                         break;
     971 [ #  # ][ #  # ]:          0 :                     }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     972                 :            :                 }
     973         [ #  # ]:          0 :                 catch(const css::uno::Exception&)
     974                 :          0 :                     { continue; }
     975                 :            :             }
     976                 :            : 
     977         [ #  # ]:          0 :             if (bMatchDetectorToDocumentService)
     978                 :            :             {
     979         [ #  # ]:          0 :                 ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
     980         [ #  # ]:          0 :                 if (!sDeepType.isEmpty())
     981                 :          0 :                     return sDeepType;
     982 [ #  # ][ #  # ]:          0 :                 lInsideUsedDetectors.push_back(sDetectService);
     983                 :            :             }
     984 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     985                 :            :     }
     986                 :            : 
     987                 :            :     // c)
     988                 :            :     // Last chance. No "used detectors", no "preselected detectors" ... ask any existing detect services
     989                 :            :     // for this till know unknown format.
     990 [ +  - ][ +  - ]:       6802 :     for (  pIt  = lDetectors.begin();
                 [ +  + ]
     991                 :       3401 :            pIt != lDetectors.end()  ;
     992                 :            :          ++pIt                      )
     993                 :            :     {
     994                 :       3392 :         const ::rtl::OUString& sDetectService = *pIt;
     995                 :            : 
     996 [ +  - ][ +  - ]:       3392 :         OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService);
     997 [ +  - ][ +  + ]:       3392 :         if (pAlreadyUsed != lInsideUsedDetectors.end())
     998                 :          2 :             continue;
     999                 :            : 
    1000         [ +  - ]:       3390 :         ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
    1001         [ +  + ]:       3390 :         if (!sDeepType.isEmpty())
    1002                 :       3390 :             return sDeepType;
    1003         [ +  + ]:       3390 :     }
    1004                 :            : 
    1005         [ +  - ]:        166 :     return ::rtl::OUString();
    1006                 :            : }
    1007                 :            : 
    1008                 :       4730 : void TypeDetection::impl_seekStreamToZero(comphelper::MediaDescriptor& rDescriptor)
    1009                 :            : {
    1010                 :            :     // try to seek to 0 ...
    1011                 :            :     // But because XSeekable is an optional interface ... try it only .-)
    1012                 :            :     css::uno::Reference< css::io::XInputStream > xStream = rDescriptor.getUnpackedValueOrDefault(
    1013         [ +  - ]:       4730 :                                                             ::comphelper::MediaDescriptor::PROP_INPUTSTREAM(),
    1014         [ +  - ]:       9460 :                                                             css::uno::Reference< css::io::XInputStream >());
    1015         [ +  - ]:       4730 :     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
    1016         [ +  - ]:       4730 :     if (xSeek.is())
    1017                 :            :     {
    1018                 :            :         try
    1019                 :            :         {
    1020 [ +  - ][ +  - ]:       4730 :             xSeek->seek(0);
    1021                 :            :         }
    1022      [ #  #  # ]:          0 :         catch(const css::uno::RuntimeException&)
    1023                 :            :         {
    1024                 :          0 :             throw;
    1025                 :            :         }
    1026         [ #  # ]:          0 :         catch(const css::uno::Exception&)
    1027                 :            :         {
    1028                 :            :         }
    1029                 :       4730 :     }
    1030                 :       4730 : }
    1031                 :            : 
    1032                 :       3868 : ::rtl::OUString TypeDetection::impl_askDetectService(const ::rtl::OUString&               sDetectService,
    1033                 :            :                                                            ::comphelper::MediaDescriptor& rDescriptor   )
    1034                 :            : {
    1035                 :            :     // Open the stream and add it to the media descriptor if this method is called for the first time.
    1036                 :            :     // All following requests to this method will detect, that there already exists a stream .-)
    1037                 :            :     // Attention: This method throws an exception if the stream could not be opened.
    1038                 :            :     // It's important to break any further detection in such case.
    1039                 :            :     // Catch it on the highest detection level only !!!
    1040         [ +  - ]:       3868 :     impl_openStream(rDescriptor);
    1041                 :            : 
    1042                 :            :     // seek to 0 is an optional feature to be more robust against
    1043                 :            :     // "simple implemented detect services" .-)
    1044         [ +  - ]:       3868 :     impl_seekStreamToZero(rDescriptor);
    1045                 :            : 
    1046                 :       3868 :     css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
    1047                 :       3868 :     css::uno::Reference< css::lang::XMultiServiceFactory >         xSMGR;
    1048                 :            : 
    1049                 :            :     // SAFE ->
    1050         [ +  - ]:       3868 :     ::osl::ResettableMutexGuard aLock(m_aLock);
    1051         [ +  - ]:       3868 :     xSMGR = m_xSMGR;
    1052         [ +  - ]:       3868 :     aLock.clear();
    1053                 :            :     // <- SAFE
    1054                 :            : 
    1055                 :            :     try
    1056                 :            :     {
    1057                 :            :         // Attention! If e.g. an office module was not installed sometimes we
    1058                 :            :         // find a registered detect service, which is referred inside the
    1059                 :            :         // configuration ... but not realy installed. On the other side we use
    1060                 :            :         // third party components here, which can make trouble anyway.  So we
    1061                 :            :         // should handle errors during creation of such services more
    1062                 :            :         // gracefully .-)
    1063                 :            :         xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >(
    1064         [ +  - ]:       3868 :                 xSMGR->createInstance(sDetectService),
    1065 [ +  - ][ +  + ]:       3868 :                 css::uno::UNO_QUERY_THROW);
                 [ +  - ]
    1066                 :            :     }
    1067         [ +  - ]:       3006 :     catch (...)
    1068                 :            :     {
    1069                 :            :     }
    1070                 :            : 
    1071         [ +  + ]:       3868 :     if ( ! xDetector.is())
    1072                 :       3006 :         return ::rtl::OUString();
    1073                 :            : 
    1074                 :        862 :     ::rtl::OUString sDeepType;
    1075                 :            :     try
    1076                 :            :     {
    1077                 :            :         // start deep detection
    1078                 :            :         // Dont forget to convert stl descriptor to its uno representation.
    1079                 :            : 
    1080                 :            :         /* Attention!
    1081                 :            :                 You have to use an explicit instance of this uno sequence ...
    1082                 :            :                 Because its used as an in out parameter. And in case of a temp. used object
    1083                 :            :                 we will run into memory corruptions!
    1084                 :            :         */
    1085         [ +  - ]:        862 :         css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
    1086         [ +  - ]:        862 :         rDescriptor >> lDescriptor;
    1087 [ +  - ][ +  - ]:        862 :         sDeepType = xDetector->detect(lDescriptor);
    1088 [ +  - ][ #  # ]:        862 :         rDescriptor << lDescriptor;
                 [ +  - ]
    1089                 :            :     }
    1090         [ #  # ]:          0 :     catch(const css::uno::Exception&)
    1091                 :            :         {
    1092                 :            :             // We should ignore errors here.
    1093                 :            :             // Thrown exceptions mostly will end in crash recovery ...
    1094                 :            :             // But might be we find another deep detection service which can detect the same
    1095                 :            :             // document without a problem .-)
    1096                 :          0 :             sDeepType = ::rtl::OUString();
    1097                 :            :         }
    1098                 :            : 
    1099                 :            :     // seek to 0 is an optional feature to be more robust against
    1100                 :            :     // "simple implemented detect services" .-)
    1101         [ +  - ]:        862 :     impl_seekStreamToZero(rDescriptor);
    1102                 :            : 
    1103                 :            :     // analyze the results
    1104                 :            :     // a) detect service returns "" => return "" too and remove TYPE/FILTER prop from descriptor
    1105                 :            :     // b) returned type is unknown  => return "" too and remove TYPE/FILTER prop from descriptor
    1106                 :            :     // c) returned type is valid    => check TYPE/FILTER props inside descriptor and return the type
    1107                 :            : 
    1108                 :            :     // this special helper checks for a valid type
    1109                 :            :     // and set right values on the descriptor!
    1110         [ +  - ]:        862 :     sal_Bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType);
    1111         [ +  + ]:        862 :     if (bValidType)
    1112                 :        625 :         return sDeepType;
    1113                 :            : 
    1114         [ +  - ]:       3868 :     return ::rtl::OUString();
    1115                 :            : }
    1116                 :            : 
    1117                 :            : 
    1118                 :            : 
    1119                 :          9 : ::rtl::OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(::comphelper::MediaDescriptor& rDescriptor)
    1120                 :            : {
    1121                 :            :     // SAFE ->
    1122         [ +  - ]:          9 :     ::osl::ResettableMutexGuard aLock(m_aLock);
    1123                 :          9 :     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
    1124         [ +  - ]:          9 :     aLock.clear();
    1125                 :            :     // <- SAFE
    1126                 :            : 
    1127                 :            :     css::uno::Reference< css::task::XInteractionHandler > xInteraction =
    1128         [ +  - ]:          9 :         rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(),
    1129         [ +  - ]:         18 :         css::uno::Reference< css::task::XInteractionHandler >());
    1130                 :            : 
    1131         [ +  - ]:          9 :     if (!xInteraction.is())
    1132                 :          9 :         return ::rtl::OUString();
    1133                 :            : 
    1134                 :            :     ::rtl::OUString sURL =
    1135         [ #  # ]:          0 :         rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(),
    1136         [ #  # ]:          0 :         ::rtl::OUString());
    1137                 :            : 
    1138                 :            :     css::uno::Reference< css::io::XInputStream > xStream =
    1139         [ #  # ]:          0 :         rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INPUTSTREAM(),
    1140         [ #  # ]:          0 :         css::uno::Reference< css::io::XInputStream >());
    1141                 :            : 
    1142                 :            :     // Dont distrub the user for "non existing files - means empty URLs" or
    1143                 :            :     // if we was forced to detect a stream.
    1144                 :            :     // Reason behind: We must be shure to ask user for "unknown contents" only ...
    1145                 :            :     // and not for "missing files". Especialy if detection is done by a stream only
    1146                 :            :     // we cant check if the stream points to an "existing content"!
    1147 [ #  # ][ #  #  :          0 :     if (
             #  #  #  # ]
    1148                 :          0 :         (sURL.isEmpty()                                     ) || // "non existing file" ?
    1149                 :          0 :         (!xStream.is()                                         ) || // non existing file !
    1150                 :          0 :         (sURL.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("private:stream")))    // not a good idea .-)
    1151                 :            :        )
    1152                 :          0 :         return ::rtl::OUString();
    1153                 :            : 
    1154                 :            :     try
    1155                 :            :     {
    1156                 :            :         // create a new request to ask user for it's decision about the usable filter
    1157         [ #  # ]:          0 :         ::framework::RequestFilterSelect aRequest(sURL);
    1158 [ #  # ][ #  # ]:          0 :         xInteraction->handle(aRequest.GetRequest());
                 [ #  # ]
    1159                 :            : 
    1160                 :            :         // "Cancel" pressed? => return with error
    1161 [ #  # ][ #  # ]:          0 :         if (aRequest.isAbort())
    1162                 :          0 :             return ::rtl::OUString();
    1163                 :            : 
    1164                 :            :         // "OK" pressed => verify the selected filter, get it's coressponding
    1165                 :            :         // type and return it. (BTW: We must update the media descriptor here ...)
    1166                 :            :         // The user selected explicitly a filter ... but normaly we are interested on
    1167                 :            :         // a type here only. But we must be shure, that the selected filter is used
    1168                 :            :         // too and no ambigous filter registration disturb us .-)
    1169                 :            : 
    1170         [ #  # ]:          0 :         ::rtl::OUString sFilter = aRequest.getFilter();
    1171 [ #  # ][ #  # ]:          0 :         if (!impl_validateAndSetFilterOnDescriptor(rDescriptor, sFilter))
    1172                 :          0 :             return ::rtl::OUString();
    1173                 :            : 
    1174                 :          0 :         ::rtl::OUString sType;
    1175 [ #  # ][ #  # ]:          0 :         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] >>= sType;
    1176 [ #  # ][ #  # ]:          0 :         return sType;
    1177                 :            :     }
    1178         [ #  # ]:          0 :     catch(const css::uno::Exception&)
    1179                 :            :         {}
    1180                 :            : 
    1181         [ +  - ]:          9 :     return ::rtl::OUString();
    1182                 :            : }
    1183                 :            : 
    1184                 :            : 
    1185                 :            : 
    1186                 :       3868 : void TypeDetection::impl_openStream(::comphelper::MediaDescriptor& rDescriptor)
    1187                 :            :     throw (css::uno::Exception)
    1188                 :            : {
    1189                 :       3868 :     sal_Bool bSuccess = sal_False;
    1190 [ +  - ][ +  - ]:       3868 :     ::rtl::OUString sURL = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString() );
    1191 [ +  - ][ +  - ]:       3868 :     sal_Bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_READONLY(), sal_False );
    1192 [ +  - ][ +  - ]:       3868 :     if ( !sURL.isEmpty() && ::utl::LocalFileHelper::IsLocalFile( INetURLObject( sURL ).GetMainURL( INetURLObject::NO_DECODE ) ) )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
           [ +  +  #  #  
                   #  # ]
    1193                 :            :     {
    1194                 :            :         // OOo uses own file locking mechanics in case of local file
    1195         [ +  - ]:       3679 :         bSuccess = rDescriptor.addInputStreamOwnLock();
    1196                 :            :     }
    1197                 :            :     else
    1198         [ +  - ]:        189 :         bSuccess = rDescriptor.addInputStream();
    1199                 :            : 
    1200         [ -  + ]:       3868 :     if ( !bSuccess )
    1201 [ #  # ][ #  # ]:          0 :         throw css::uno::Exception(_FILTER_CONFIG_FROM_ASCII_("Could not open stream."), static_cast< css::document::XTypeDetection* >(this));
                 [ #  # ]
    1202                 :            : 
    1203         [ +  + ]:       3868 :     if ( !bRequestedReadOnly )
    1204                 :            :     {
    1205                 :            :         // The MediaDescriptor implementation adds ReadOnly argument if the file can not be opened for writing
    1206                 :            :         // this argument should be either removed or an additional argument should be added so that application
    1207                 :            :         // can separate the case when the user explicitly requests readonly document.
    1208                 :            :         // The current solution is to remove it here.
    1209 [ +  - ][ +  - ]:       3866 :         rDescriptor.erase( ::comphelper::MediaDescriptor::PROP_READONLY() );
    1210                 :       3868 :     }
    1211                 :       3868 : }
    1212                 :            : 
    1213                 :            : 
    1214                 :            : 
    1215                 :        246 : void TypeDetection::impl_removeTypeFilterFromDescriptor(::comphelper::MediaDescriptor& rDescriptor)
    1216                 :            : {
    1217 [ +  - ][ +  - ]:        246 :     ::comphelper::MediaDescriptor::iterator pItType   = rDescriptor.find(::comphelper::MediaDescriptor::PROP_TYPENAME()  );
    1218 [ +  - ][ +  - ]:        246 :     ::comphelper::MediaDescriptor::iterator pItFilter = rDescriptor.find(::comphelper::MediaDescriptor::PROP_FILTERNAME());
    1219 [ +  - ][ +  + ]:        246 :     if (pItType != rDescriptor.end())
    1220         [ +  - ]:         14 :         rDescriptor.erase(pItType);
    1221 [ +  - ][ -  + ]:        246 :     if (pItFilter != rDescriptor.end())
    1222         [ #  # ]:          0 :         rDescriptor.erase(pItFilter);
    1223                 :        246 : }
    1224                 :            : 
    1225                 :            : 
    1226                 :            : 
    1227                 :       4226 : sal_Bool TypeDetection::impl_validateAndSetTypeOnDescriptor(      ::comphelper::MediaDescriptor& rDescriptor,
    1228                 :            :                                                             const ::rtl::OUString&               sType      )
    1229                 :            : {
    1230                 :            :     // SAFE ->
    1231         [ +  - ]:       4226 :     ::osl::ResettableMutexGuard aLock(m_aLock);
    1232 [ +  - ][ +  - ]:       4226 :     if (m_rCache->hasItem(FilterCache::E_TYPE, sType))
                 [ +  + ]
    1233                 :            :     {
    1234 [ +  - ][ +  - ]:       3980 :         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType;
                 [ +  - ]
    1235                 :       3980 :         return sal_True;
    1236                 :            :     }
    1237         [ +  - ]:        246 :     aLock.clear();
    1238                 :            :     // <- SAFE
    1239                 :            : 
    1240                 :            :     // remove all related informations from the descriptor
    1241         [ +  - ]:        246 :     impl_removeTypeFilterFromDescriptor(rDescriptor);
    1242         [ +  - ]:       4226 :     return sal_False;
    1243                 :            : }
    1244                 :            : 
    1245                 :            : 
    1246                 :            : 
    1247                 :          0 : sal_Bool TypeDetection::impl_validateAndSetFilterOnDescriptor(      ::comphelper::MediaDescriptor& rDescriptor,
    1248                 :            :                                                               const ::rtl::OUString&               sFilter    )
    1249                 :            : {
    1250                 :            :     try
    1251                 :            :     {
    1252                 :            :         // SAFE ->
    1253         [ #  # ]:          0 :         ::osl::ResettableMutexGuard aLock(m_aLock);
    1254                 :            : 
    1255 [ #  # ][ #  # ]:          0 :         CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
    1256                 :          0 :         ::rtl::OUString sType;
    1257         [ #  # ]:          0 :         aFilter[PROPNAME_TYPE] >>= sType;
    1258 [ #  # ][ #  # ]:          0 :         CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
    1259                 :            : 
    1260         [ #  # ]:          0 :         aLock.clear();
    1261                 :            :         // <- SAFE
    1262                 :            : 
    1263                 :            :         // found valid type and filter => set it on the given descriptor
    1264 [ #  # ][ #  # ]:          0 :         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
                 [ #  # ]
    1265 [ #  # ][ #  # ]:          0 :         rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
                 [ #  # ]
    1266 [ #  # ][ #  # ]:          0 :         return sal_True;
         [ #  # ][ #  # ]
    1267                 :            :     }
    1268                 :          0 :     catch(const css::container::NoSuchElementException&){}
    1269                 :            : 
    1270                 :            :     // remove all related informations from the descriptor
    1271                 :          0 :     impl_removeTypeFilterFromDescriptor(rDescriptor);
    1272                 :          0 :     return sal_False;
    1273                 :            : }
    1274                 :            : 
    1275                 :            : 
    1276                 :            : 
    1277                 :      12467 : ::rtl::OUString TypeDetection::impl_getImplementationName()
    1278                 :            : {
    1279                 :      12467 :     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.filter.config.TypeDetection" ));
    1280                 :            : }
    1281                 :            : 
    1282                 :            : 
    1283                 :            : 
    1284                 :      11955 : css::uno::Sequence< ::rtl::OUString > TypeDetection::impl_getSupportedServiceNames()
    1285                 :            : {
    1286                 :      11955 :     css::uno::Sequence< ::rtl::OUString > lServiceNames(1);
    1287 [ +  - ][ +  - ]:      11955 :     lServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.TypeDetection" ));
    1288                 :      11955 :     return lServiceNames;
    1289                 :            : }
    1290                 :            : 
    1291                 :            : 
    1292                 :            : 
    1293                 :      11828 : css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
    1294                 :            : {
    1295         [ +  - ]:      11828 :     TypeDetection* pNew = new TypeDetection(xSMGR);
    1296         [ +  - ]:      11828 :     return css::uno::Reference< css::uno::XInterface >(static_cast< css::document::XTypeDetection* >(pNew), css::uno::UNO_QUERY);
    1297                 :            : }
    1298                 :            : 
    1299                 :            :     } // namespace config
    1300                 :            : } // namespace filter
    1301                 :            : 
    1302                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10