LCOV - code coverage report
Current view: top level - filter/source/config/cache - typedetection.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 333 418 79.7 %
Date: 2014-04-11 Functions: 28 29 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "typedetection.hxx"
      21             : #include "constant.hxx"
      22             : 
      23             : #include <com/sun/star/document/XExtendedFilterDetection.hpp>
      24             : #include <com/sun/star/util/URLTransformer.hpp>
      25             : #include <com/sun/star/util/XURLTransformer.hpp>
      26             : 
      27             : #include <com/sun/star/io/XInputStream.hpp>
      28             : #include <com/sun/star/io/XSeekable.hpp>
      29             : #include <com/sun/star/task/XInteractionHandler.hpp>
      30             : #include <tools/wldcrd.hxx>
      31             : #include <rtl/ustrbuf.hxx>
      32             : #include <framework/interaction.hxx>
      33             : #include <tools/urlobj.hxx>
      34             : #include <unotools/localfilehelper.hxx>
      35             : #include <comphelper/processfactory.hxx>
      36             : 
      37             : #define DEBUG_TYPE_DETECTION 0
      38             : 
      39             : #if DEBUG_TYPE_DETECTION
      40             : #include <iostream>
      41             : using std::cout;
      42             : using std::endl;
      43             : #endif
      44             : 
      45             : using namespace com::sun::star;
      46             : 
      47             : namespace filter{
      48             :     namespace config{
      49             : 
      50       25457 : TypeDetection::TypeDetection(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
      51       25457 :    : m_xContext(rxContext)
      52             : {
      53             :     BaseContainer::init(rxContext                                     ,
      54             :                         TypeDetection::impl_getImplementationName()   ,
      55             :                         TypeDetection::impl_getSupportedServiceNames(),
      56       25457 :                         FilterCache::E_TYPE                           );
      57       25457 : }
      58             : 
      59             : 
      60             : 
      61       50914 : TypeDetection::~TypeDetection()
      62             : {
      63       50914 : }
      64             : 
      65             : 
      66             : 
      67       14464 : OUString SAL_CALL TypeDetection::queryTypeByURL(const OUString& sURL)
      68             :     throw (css::uno::RuntimeException, std::exception)
      69             : {
      70       14464 :     OUString sType;
      71             : 
      72             :     // SAFE ->
      73       28928 :     ::osl::ResettableMutexGuard aLock(m_aLock);
      74             : 
      75       28928 :     css::util::URL  aURL;
      76       14464 :     aURL.Complete = sURL;
      77       28928 :     css::uno::Reference< css::util::XURLTransformer > xParser( css::util::URLTransformer::create(m_xContext) );
      78       14464 :     xParser->parseStrict(aURL);
      79             : 
      80             :     // set std types as minimum requirement first!
      81             :     // Only in case no type was found for given URL,
      82             :     // use optional types too ...
      83       28928 :     FlatDetection lFlatTypes;
      84       14464 :     m_rCache->detectFlatForURL(aURL, lFlatTypes);
      85             : 
      86       14464 :     if (
      87       27882 :         (lFlatTypes.size() < 1                                ) &&
      88       13418 :         (!m_rCache->isFillState(FilterCache::E_CONTAINS_TYPES))
      89             :        )
      90             :     {
      91           0 :         m_rCache->load(FilterCache::E_CONTAINS_TYPES);
      92           0 :         m_rCache->detectFlatForURL(aURL, lFlatTypes);
      93             :     }
      94             : 
      95             :     // first item is guaranteed as "preferred" one!
      96       14464 :     if (lFlatTypes.size() > 0)
      97             :     {
      98        1046 :         const FlatDetectionInfo& aMatch = *(lFlatTypes.begin());
      99        1046 :         sType = aMatch.sType;
     100             :     }
     101             : 
     102       28928 :     return sType;
     103             :     // <- SAFE
     104             : }
     105             : 
     106             : namespace {
     107             : 
     108             : /**
     109             :  * Rank format types in order of complexity.  More complex formats are
     110             :  * ranked higher so that they get tested sooner over simpler formats.
     111             :  *
     112             :  * Guidelines to determine how complex a format is (subject to change):
     113             :  *
     114             :  * 1) compressed text (XML, HTML, etc)
     115             :  * 2) binary
     116             :  * 3) non-compressed text
     117             :  *   3.1) structured text
     118             :  *     3.1.1) dialect of a structured text (e.g. docbook XML)
     119             :  *     3.1.2) generic structured text (e.g. generic XML)
     120             :  *   3.2) non-structured text
     121             :  *
     122             :  * In each category, rank them from strictly-structured to
     123             :  * loosely-structured.
     124             :  */
     125     4038382 : int getFlatTypeRank(const OUString& rType)
     126             : {
     127             :     // List formats from more complex to less complex.
     128             :     // TODO: Add more.
     129             :     static const char* ranks[] = {
     130             : 
     131             :         // Compressed XML (ODF XML zip formats)
     132             :         "writer8_template",
     133             :         "writer8",
     134             :         "calc8_template",
     135             :         "calc8",
     136             :         "impress8_template",
     137             :         "impress8",
     138             :         "draw8_template",
     139             :         "draw8",
     140             :         "chart8",
     141             :         "math8",
     142             :         "writerglobal8",
     143             :         "writerweb8_writer_template",
     144             :         "StarBase",
     145             : 
     146             :         // Compressed XML (OOXML)
     147             :         "writer_OOXML_Text_Template",
     148             :         "writer_OOXML",
     149             :         "writer_MS_Word_2007_Template",
     150             :         "writer_MS_Word_2007",
     151             :         "Office Open XML Spreadsheet Template",
     152             :         "Office Open XML Spreadsheet",
     153             :         "MS Excel 2007 XML Template",
     154             :         "MS Excel 2007 XML",
     155             :         "MS PowerPoint 2007 XML Template",
     156             :         "MS PowerPoint 2007 XML AutoPlay",
     157             :         "MS PowerPoint 2007 XML",
     158             : 
     159             :         // Compressed XML (Uniform/Unified Office Format)
     160             :         "Unified_Office_Format_text",
     161             :         "Unified_Office_Format_spreadsheet",
     162             :         "Unified_Office_Format_presentation",
     163             : 
     164             :         // Compressed XML (StarOffice XML zip formats)
     165             :         "calc_StarOffice_XML_Calc",
     166             :         "calc_StarOffice_XML_Calc_Template",
     167             :         "chart_StarOffice_XML_Chart",
     168             :         "draw_StarOffice_XML_Draw",
     169             :         "draw_StarOffice_XML_Draw_Template",
     170             :         "impress_StarOffice_XML_Impress",
     171             :         "impress_StarOffice_XML_Impress_Template",
     172             :         "math_StarOffice_XML_Math",
     173             :         "writer_StarOffice_XML_Writer",
     174             :         "writer_StarOffice_XML_Writer_Template",
     175             :         "writer_globaldocument_StarOffice_XML_Writer_GlobalDocument",
     176             :         "writer_web_StarOffice_XML_Writer_Web_Template",
     177             : 
     178             :         // Compressed text
     179             :         "pdf_Portable_Document_Format",
     180             : 
     181             :         // Binary
     182             :         "writer_T602_Document",
     183             :         "writer_WordPerfect_Document",
     184             :         "writer_MS_Works_Document",
     185             :         "writer_MS_Word_97_Vorlage",
     186             :         "writer_MS_Word_97",
     187             :         "writer_MS_Word_95_Vorlage",
     188             :         "writer_MS_Word_95",
     189             :         "writer_MS_WinWord_60",
     190             :         "writer_MS_WinWord_5",
     191             :         "MS Excel 2007 Binary",
     192             :         "calc_MS_Excel_97_VorlageTemplate",
     193             :         "calc_MS_Excel_97",
     194             :         "calc_MS_Excel_95_VorlageTemplate",
     195             :         "calc_MS_Excel_95",
     196             :         "calc_MS_Excel_5095_VorlageTemplate",
     197             :         "calc_MS_Excel_5095",
     198             :         "calc_MS_Excel_40_VorlageTemplate",
     199             :         "calc_MS_Excel_40",
     200             :         "calc_Pocket_Excel_File",
     201             :         "impress_MS_PowerPoint_97_Vorlage",
     202             :         "impress_MS_PowerPoint_97_AutoPlay",
     203             :         "impress_MS_PowerPoint_97",
     204             :         "calc_Lotus",
     205             :         "calc_QPro",
     206             :         "calc_SYLK",
     207             :         "calc_DIF",
     208             :         "calc_dBase",
     209             : 
     210             :         // Binary (raster and vector image files)
     211             :         "emf_MS_Windows_Metafile",
     212             :         "wmf_MS_Windows_Metafile",
     213             :         "met_OS2_Metafile",
     214             :         "svm_StarView_Metafile",
     215             :         "sgv_StarDraw_20",
     216             :         "tif_Tag_Image_File",
     217             :         "tga_Truevision_TARGA",
     218             :         "sgf_StarOffice_Writer_SGF",
     219             :         "ras_Sun_Rasterfile",
     220             :         "psd_Adobe_Photoshop",
     221             :         "png_Portable_Network_Graphic",
     222             :         "jpg_JPEG",
     223             :         "mov_MOV",
     224             :         "gif_Graphics_Interchange",
     225             :         "bmp_MS_Windows",
     226             :         "pcx_Zsoft_Paintbrush",
     227             :         "pct_Mac_Pict",
     228             :         "pcd_Photo_CD_Base",
     229             :         "pcd_Photo_CD_Base4",
     230             :         "pcd_Photo_CD_Base16",
     231             :         "impress_CGM_Computer_Graphics_Metafile", // There is binary and ascii variants ?
     232             :         "draw_WordPerfect_Graphics",
     233             :         "draw_Visio_Document",
     234             :         "draw_Publisher_Document",
     235             :         "draw_Corel_Presentation_Exchange",
     236             :         "draw_CorelDraw_Document",
     237             :         "writer_LotusWordPro_Document",
     238             :         "writer_MIZI_Hwp_97", // Hanword (Hancom Office)
     239             : 
     240             :         // Non-compressed XML
     241             :         "writer_ODT_FlatXML",
     242             :         "calc_ODS_FlatXML",
     243             :         "impress_ODP_FlatXML",
     244             :         "draw_ODG_FlatXML",
     245             :         "calc_MS_Excel_2003_XML",
     246             :         "writer_MS_Word_2003_XML",
     247             :         "writer_DocBook_File",
     248             :         "XHTML_File",
     249             :         "svg_Scalable_Vector_Graphics",
     250             :         "math_MathML_XML_Math",
     251             : 
     252             :         // Non-compressed text
     253             :         "dxf_AutoCAD_Interchange",
     254             :         "eps_Encapsulated_PostScript",
     255             :         "pbm_Portable_Bitmap",   // There is 'raw' and 'ascii' variants.
     256             :         "ppm_Portable_Pixelmap", // There is 'raw' and 'ascii' variants.
     257             :         "pgm_Portable_Graymap",  // There is 'raw' and 'ascii' variants.
     258             :         "xpm_XPM",
     259             :         "xbm_X_Consortium",
     260             :         "writer_Rich_Text_Format",
     261             :         "writer_web_HTML_help",
     262             :         "generic_HTML",
     263             : 
     264             :         "generic_Text", // Plain text (catch all)
     265             : 
     266             :         // Anything ranked lower than generic_Text will never be used during
     267             :         // type detection (since generic_Text catches all).
     268             : 
     269             :         // Export only
     270             :         "writer_layout_dump_xml",
     271             :         "pwp_PlaceWare",
     272             :         "graphic_SWF",
     273             :         "graphic_HTML",
     274             : 
     275             :         // Internal use only
     276             :         "StarBaseReportChart",
     277             :         "StarBaseReport",
     278             :         "math_MathType_3x", // MathType equation embedded in Word doc.
     279             :     };
     280             : 
     281     4038382 :     size_t n = SAL_N_ELEMENTS(ranks);
     282             : 
     283   304899780 :     for (size_t i = 0; i < n; ++i)
     284             :     {
     285   304031649 :         if (rType.equalsAscii(ranks[i]))
     286     3170251 :             return n - i - 1;
     287             :     }
     288             : 
     289             :     // Not ranked.  Treat them equally.  Unranked formats have higher priority
     290             :     // than the ranked internal ones since they may be defined externally.
     291      868131 :     return n;
     292             : }
     293             : 
     294             : /**
     295             :  * Types with matching pattern first, then extension, then custom ranks by
     296             :  * types, then types that are supported by the document service come next.
     297             :  * Lastly, sort them alphabetically.
     298             :  */
     299             : struct SortByPriority : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
     300             : {
     301     2039491 :     bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
     302             :     {
     303     2039491 :         if (r1.bMatchByPattern != r2.bMatchByPattern)
     304        4998 :             return r1.bMatchByPattern;
     305             : 
     306     2034493 :         if (r1.bMatchByExtension != r2.bMatchByExtension)
     307       15302 :             return r1.bMatchByExtension;
     308             : 
     309     2019191 :         int rank1 = getFlatTypeRank(r1.sType);
     310     2019191 :         int rank2 = getFlatTypeRank(r2.sType);
     311             : 
     312     2019191 :         if (rank1 != rank2)
     313     1709718 :             return rank1 > rank2;
     314             : 
     315      309473 :         if (r1.bPreselectedByDocumentService != r2.bPreselectedByDocumentService)
     316       81084 :             return r1.bPreselectedByDocumentService;
     317             : 
     318             :         // All things being equal, sort them alphabetically.
     319      228389 :         return r1.sType > r2.sType;
     320             :     }
     321             : };
     322             : 
     323             : struct SortByType : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
     324             : 
     325             : {
     326     3179297 :     bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
     327             :     {
     328     3179297 :         return r1.sType > r2.sType;
     329             :     }
     330             : };
     331             : 
     332             : struct EqualByType : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
     333             : {
     334      802110 :     bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
     335             :     {
     336      802110 :         return r1.sType == r2.sType;
     337             :     }
     338             : };
     339             : 
     340      263103 : class FindByType : std::unary_function<FlatDetectionInfo, bool>
     341             : {
     342             :     OUString maType;
     343             : public:
     344       87701 :     FindByType(const OUString& rType) : maType(rType) {}
     345     4145922 :     bool operator() (const FlatDetectionInfo& rInfo) const
     346             :     {
     347     4145922 :         return rInfo.sType == maType;
     348             :     }
     349             : };
     350             : 
     351             : #if DEBUG_TYPE_DETECTION
     352             : void printFlatDetectionList(const char* caption, const FlatDetection& types)
     353             : {
     354             :     cout << "-- " << caption << " (size=" << types.size() << ")" << endl;
     355             :     FlatDetection::const_iterator it = types.begin(), itEnd = types.end();
     356             :     for (; it != itEnd; ++it)
     357             :     {
     358             :         const FlatDetectionInfo& item = *it;
     359             :         cout << "  type='" << item.sType << "'; match by extension (" << item.bMatchByExtension
     360             :             << "); match by pattern (" << item.bMatchByPattern << "); pre-selected by doc service ("
     361             :             << item.bPreselectedByDocumentService << ")" << endl;
     362             :     }
     363             :     cout << "--" << endl;
     364             : }
     365             : #endif
     366             : 
     367             : }
     368             : 
     369        2078 : OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
     370             :                                                               sal_Bool                                         bAllowDeep )
     371             :     throw (css::uno::RuntimeException, std::exception)
     372             : {
     373             :     // make the descriptor more useable :-)
     374        2078 :     utl::MediaDescriptor stlDescriptor(lDescriptor);
     375             : 
     376             :     // SAFE -> ----------------------------------
     377        4156 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     378             : 
     379             : 
     380             :     // parse given URL to split it into e.g. main and jump marks ...
     381        4156 :     OUString sURL = stlDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL(), OUString());
     382             : 
     383             : #if OSL_DEBUG_LEVEL > 0
     384             :     if (stlDescriptor.find( "FileName" ) != stlDescriptor.end())
     385             :         OSL_FAIL("Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
     386             : #endif
     387             : 
     388        4156 :     css::util::URL  aURL;
     389        2078 :     aURL.Complete = sURL;
     390        4156 :     css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
     391        2078 :     xParser->parseStrict(aURL);
     392             : 
     393             :     OUString aSelectedFilter = stlDescriptor.getUnpackedValueOrDefault(
     394        4156 :         utl::MediaDescriptor::PROP_FILTERNAME(), OUString());
     395        2078 :     if (!aSelectedFilter.isEmpty())
     396             :     {
     397             :         // Caller specified the filter type.  Honor it.  Just get the default
     398             :         // type for that filter, and bail out.
     399           0 :         if (impl_validateAndSetFilterOnDescriptor(stlDescriptor, aSelectedFilter))
     400           0 :             return stlDescriptor[utl::MediaDescriptor::PROP_TYPENAME()].get<OUString>();
     401             :     }
     402             : 
     403        4156 :     FlatDetection lFlatTypes;
     404        2078 :     impl_getAllFormatTypes(aURL, stlDescriptor, lFlatTypes);
     405             : 
     406        2078 :     aLock.clear();
     407             :     // <- SAFE ----------------------------------
     408             : 
     409             :     // Properly prioritize all candidate types.
     410        2078 :     lFlatTypes.sort(SortByPriority());
     411        2078 :     lFlatTypes.unique(EqualByType());
     412             : 
     413        4156 :     OUString sType      ;
     414        4156 :     OUString sLastChance;
     415             : 
     416             :     try
     417             :     {
     418             : 
     419             :         // verify every flat detected (or preselected!) type
     420             :         // by calling its registered deep detection service.
     421             :         // But break this loop if a type match to the given descriptor
     422             :         // by an URL pattern(!) or if deep detection isnt allowed from
     423             :         // outside (bAllowDeep=sal_False) or break the whole detection by
     424             :         // throwing an exception if creation of the might needed input
     425             :         // stream failed by e.g. an IO exception ...
     426        2078 :         OUStringList lUsedDetectors;
     427        2078 :         if (lFlatTypes.size()>0)
     428        2078 :             sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, lUsedDetectors, sLastChance);
     429             : 
     430             : 
     431             :         // flat detection failed
     432             :         // pure deep detection failed
     433             :         // => ask might existing InteractionHandler
     434             :         // means: ask user for it's decision
     435        2078 :         if (sType.isEmpty())
     436           4 :             sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor);
     437             : 
     438             : 
     439             :         // no real detected type - but a might valid one.
     440             :         // update descriptor and set last chance for return.
     441        2078 :         if (sType.isEmpty() && !sLastChance.isEmpty())
     442             :         {
     443             :             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!");
     444           4 :             sType = sLastChance;
     445        2078 :         }
     446             :     }
     447           0 :     catch(const css::uno::RuntimeException&)
     448           0 :         { throw; }
     449           0 :     catch(const css::uno::Exception& e)
     450             :         {
     451             :             SAL_WARN(
     452             :                 "filter.config",
     453             :                 "caught Exception \"" << e.Message
     454             :                     << "\" while querying type of <" << sURL << ">");
     455           0 :             sType = OUString();
     456             :         }
     457             : 
     458             : 
     459             :     // adapt media descriptor, so it contains the right values
     460             :     // for type/filter name/document service/ etcpp.
     461        2078 :     impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!!
     462        2078 :     impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType);
     463             : 
     464        2078 :     stlDescriptor >> lDescriptor;
     465        4156 :     return sType;
     466             : }
     467             : 
     468             : 
     469             : 
     470        2078 : void TypeDetection::impl_checkResultsAndAddBestFilter(utl::MediaDescriptor& rDescriptor,
     471             :                                                       OUString&               sType      )
     472             : {
     473             :     // a)
     474             :     // Dont overwrite a might preselected filter!
     475             :     OUString sFilter = rDescriptor.getUnpackedValueOrDefault(
     476        2078 :                                 utl::MediaDescriptor::PROP_FILTERNAME(),
     477        4156 :                                 OUString());
     478        2078 :     if (!sFilter.isEmpty())
     479          65 :         return;
     480             : 
     481             :     // b)
     482             :     // check a preselected document service too.
     483             :     // Then we have to search a suitable filter witin this module.
     484             :     OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault(
     485        2013 :                                             utl::MediaDescriptor::PROP_DOCUMENTSERVICE(),
     486        4027 :                                             OUString());
     487        2013 :     if (!sDocumentService.isEmpty())
     488             :     {
     489             :         try
     490             :         {
     491        1270 :             OUString sRealType = sType;
     492             : 
     493             :             // SAFE ->
     494        1274 :             ::osl::ResettableMutexGuard aLock(m_aLock);
     495             : 
     496             :             // Attention: For executing next lines of code, We must be shure that
     497             :             // all filters already loaded :-(
     498             :             // That can disturb our "load on demand feature". But we have no other chance!
     499        1270 :             m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     500             : 
     501        1274 :             CacheItem lIProps;
     502        1270 :             lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService;
     503        1270 :             lIProps[PROPNAME_TYPE           ] <<= sRealType;
     504        1274 :             OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
     505             : 
     506        1270 :             aLock.clear();
     507             :             // <- SAFE
     508             : 
     509        6450 :             for (OUStringList::const_iterator pIt  = lFilters.begin();
     510        4300 :                   pIt != lFilters.end(); ++pIt)
     511             :             {
     512             :                 // SAFE ->
     513        1266 :                 aLock.reset();
     514             :                 try
     515             :                 {
     516        1266 :                     CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt);
     517        1266 :                     sal_Int32 nFlags  = 0;
     518        1266 :                     aFilter[PROPNAME_FLAGS] >>= nFlags;
     519             : 
     520        1266 :                     if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
     521        1266 :                         sFilter = *pIt;
     522        1266 :                     if ((nFlags & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED)
     523         386 :                         break;
     524             :                 }
     525           0 :                 catch(const css::uno::Exception&) {}
     526         880 :                 aLock.clear();
     527             :                 // <- SAFE
     528             :             }
     529             : 
     530        1270 :             if (!sFilter.isEmpty())
     531             :             {
     532        1266 :                 rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()  ] <<= sRealType;
     533        1266 :                 rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
     534        1266 :                 sType = sRealType;
     535        1266 :                 return;
     536           4 :             }
     537             :         }
     538           0 :         catch(const css::uno::Exception&)
     539             :             {}
     540             :     }
     541             : 
     542             :     // c)
     543             :     // We can use the preferred filter for the specified type.
     544             :     // Such preferred filter points:
     545             :     // - to the default filter of the preferred application
     546             :     // - or to any other filter if no preferred filter was set.
     547             :     // Note: It's an optimization only!
     548             :     // It's not guaranteed, that such preferred filter exists.
     549         747 :     sFilter = OUString();
     550             :     try
     551             :     {
     552             :         // SAFE ->
     553         747 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     554             : 
     555        1494 :         CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
     556         747 :         aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
     557        1493 :         CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
     558             : 
     559         746 :         aLock.clear();
     560             :         // <- SAFE
     561             : 
     562             :         // no exception => found valid type and filter => set it on the given descriptor
     563         746 :         rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
     564         746 :         rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
     565        1493 :         return;
     566             :     }
     567           1 :     catch(const css::uno::Exception&)
     568             :         {}
     569             : 
     570             :     // d)
     571             :     // Search for any import(!) filter, which is registered for this type.
     572           1 :     sFilter = OUString();
     573             :     try
     574             :     {
     575             :         // SAFE ->
     576           1 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     577             : 
     578             :         // Attention: For executing next lines of code, We must be shure that
     579             :         // all filters already loaded :-(
     580             :         // That can disturb our "load on demand feature". But we have no other chance!
     581           1 :         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     582             : 
     583           2 :         CacheItem lIProps;
     584           1 :         lIProps[PROPNAME_TYPE] <<= sType;
     585           2 :         OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
     586             : 
     587           1 :         aLock.clear();
     588             :         // <- SAFE
     589             : 
     590           1 :         OUStringList::const_iterator pIt;
     591           3 :         for (  pIt  = lFilters.begin();
     592           2 :                pIt != lFilters.end()  ;
     593             :              ++pIt                    )
     594             :         {
     595           0 :             sFilter = *pIt;
     596             : 
     597             :             // SAFE ->
     598           0 :             aLock.reset();
     599             :             try
     600             :             {
     601           0 :                 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
     602           0 :                 sal_Int32 nFlags  = 0;
     603           0 :                 aFilter[PROPNAME_FLAGS] >>= nFlags;
     604             : 
     605           0 :                 if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
     606           0 :                     break;
     607             :             }
     608           0 :             catch(const css::uno::Exception&)
     609           0 :                 { continue; }
     610           0 :             aLock.clear();
     611             :             // <- SAFE
     612             : 
     613           0 :             sFilter = OUString();
     614             :         }
     615             : 
     616           1 :         if (!sFilter.isEmpty())
     617             :         {
     618           0 :             rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
     619           0 :             rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
     620           0 :             return;
     621           1 :         }
     622             :     }
     623           0 :     catch(const css::uno::Exception&)
     624           1 :         {}
     625             : }
     626             : 
     627             : 
     628             : 
     629       84936 : bool TypeDetection::impl_getPreselectionForType(
     630             :     const OUString& sPreSelType, const util::URL& aParsedURL, FlatDetection& rFlatTypes, bool bDocService)
     631             : {
     632             :     // Can be used to supress execution of some parts of this method
     633             :     // if its already clear that detected type is valid or not.
     634             :     // Its necessary to use shared code at the end, which update
     635             :     // all return parameters constistency!
     636       84936 :     bool bBreakDetection = false;
     637             : 
     638             :     // Further we must know if it matches by pattern
     639             :     // Every flat detected type by pattern wont be detected deep!
     640       84936 :     bool bMatchByPattern = false;
     641             : 
     642             :     // And we must know if a preselection must be preferred, because
     643             :     // it matches by it's extension too.
     644       84936 :     bool bMatchByExtension = false;
     645             : 
     646             :     // validate type
     647       84936 :     OUString sType(sPreSelType);
     648      169872 :     CacheItem       aType;
     649             :     try
     650             :     {
     651             :         // SAFE -> --------------------------
     652       84936 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     653       84936 :         aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
     654       84936 :         aLock.clear();
     655             :         // <- SAFE --------------------------
     656             :     }
     657           0 :     catch(const css::container::NoSuchElementException&)
     658             :     {
     659           0 :         sType = OUString();
     660           0 :         bBreakDetection = true;
     661             :     }
     662             : 
     663       84936 :     if (!bBreakDetection)
     664             :     {
     665             :         // We cant check a preselected type for a given stream!
     666             :         // So we must believe, that it can work ...
     667       84936 :         if ( aParsedURL.Complete == "private:stream" )
     668           0 :             bBreakDetection = true;
     669             :     }
     670             : 
     671       84936 :     if (!bBreakDetection)
     672             :     {
     673             :         // extract extension from URL .. to check it case-insensitive !
     674       84936 :         INetURLObject   aParser    (aParsedURL.Main);
     675             :         OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT       ,
     676             :                                                           true                          ,
     677      169872 :                                                           INetURLObject::DECODE_WITH_CHARSET);
     678       84936 :         sExtension = sExtension.toAsciiLowerCase();
     679             : 
     680             :         // otherwise we must know, if it matches to the given URL really.
     681             :         // especialy if it matches by its extension or pattern registration.
     682      169872 :         OUStringList lExtensions(aType[PROPNAME_EXTENSIONS]);
     683      169872 :         OUStringList lURLPattern(aType[PROPNAME_URLPATTERN]);
     684             : 
     685      631746 :         for (OUStringList::const_iterator pIt  = lExtensions.begin();
     686      421164 :                                           pIt != lExtensions.end()  ;
     687             :                                         ++pIt                       )
     688             :         {
     689      127591 :             OUString sCheckExtension(pIt->toAsciiLowerCase());
     690      127591 :             if (sCheckExtension.equals(sExtension))
     691             :             {
     692        1945 :                 bBreakDetection        = true;
     693        1945 :                 bMatchByExtension      = true;
     694        1945 :                 break;
     695             :             }
     696      125646 :         }
     697             : 
     698       84936 :         if (!bBreakDetection)
     699             :         {
     700      256653 :             for (OUStringList::const_iterator pIt  = lURLPattern.begin();
     701      171102 :                                               pIt != lURLPattern.end()  ;
     702             :                                             ++pIt                       )
     703             :             {
     704        2560 :                 WildCard aCheck(*pIt);
     705        2560 :                 if (aCheck.Matches(aParsedURL.Main))
     706             :                 {
     707           0 :                     bBreakDetection        = true;
     708           0 :                     bMatchByPattern        = true;
     709           0 :                     break;
     710             :                 }
     711        2560 :             }
     712       84936 :         }
     713             :     }
     714             : 
     715             :     // if it's a valid type - set it on all return values!
     716       84936 :     if (!sType.isEmpty())
     717             :     {
     718       84936 :         FlatDetection::iterator it = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(sType));
     719       84936 :         if (it != rFlatTypes.end())
     720             :         {
     721       84936 :             if (bMatchByExtension)
     722        1945 :                 it->bMatchByExtension = true;
     723       84936 :             if (bMatchByPattern)
     724           0 :                 it->bMatchByPattern = true;
     725       84936 :             if (bDocService)
     726       84936 :                 it->bPreselectedByDocumentService = true;
     727             :         }
     728             : 
     729       84936 :         return true;
     730             :     }
     731             : 
     732             :     // not valid!
     733       84936 :     return false;
     734             : }
     735             : 
     736        1311 : bool TypeDetection::impl_getPreselectionForDocumentService(
     737             :     const OUString& sPreSelDocumentService, const util::URL& aParsedURL, FlatDetection& rFlatTypes)
     738             : {
     739             :     // get all filters, which match to this doc service
     740        1311 :     OUStringList lFilters;
     741             :     try
     742             :     {
     743             :         // SAFE -> --------------------------
     744        1311 :         ::osl::ResettableMutexGuard aLock(m_aLock);
     745             : 
     746             :         // Attention: For executing next lines of code, We must be shure that
     747             :         // all filters already loaded :-(
     748             :         // That can disturb our "load on demand feature". But we have no other chance!
     749        1311 :         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     750             : 
     751        2622 :         CacheItem lIProps;
     752        1311 :         lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService;
     753        1311 :         lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
     754             : 
     755        2622 :         aLock.clear();
     756             :         // <- SAFE --------------------------
     757             :     }
     758           0 :     catch (const css::container::NoSuchElementException&)
     759             :     {
     760           0 :         lFilters.clear();
     761             :     }
     762             : 
     763             :     // step over all filters, and check if its registered type
     764             :     // match the given URL.
     765             :     // But use temp. list of "preselected types" instead of incoming rFlatTypes list!
     766             :     // The reason behind: we must filter the getted results. And copying of stl entries
     767             :     // is an easier job then removing it .-)
     768      258741 :     for (OUStringList::const_iterator pFilter  = lFilters.begin();
     769      172494 :          pFilter != lFilters.end();
     770             :          ++pFilter)
     771             :     {
     772       84936 :         OUString aType = impl_getTypeFromFilter(*pFilter);
     773       84936 :         if (aType.isEmpty())
     774           0 :             continue;
     775             : 
     776       84936 :         impl_getPreselectionForType(aType, aParsedURL, rFlatTypes, true);
     777       84936 :     }
     778             : 
     779        1311 :     return true;
     780             : }
     781             : 
     782      560798 : OUString TypeDetection::impl_getTypeFromFilter(const OUString& rFilterName)
     783             : {
     784      560798 :     CacheItem aFilter;
     785             :     try
     786             :     {
     787      560798 :         osl::MutexGuard aLock(m_aLock);
     788      560798 :         aFilter = m_rCache->getItem(FilterCache::E_FILTER, rFilterName);
     789             :     }
     790           0 :     catch (const container::NoSuchElementException&)
     791             :     {
     792           0 :         return OUString();
     793             :     }
     794             : 
     795     1121596 :     OUString aType;
     796      560798 :     aFilter[PROPNAME_TYPE] >>= aType;
     797     1121596 :     return aType;
     798             : }
     799             : 
     800        2078 : void TypeDetection::impl_getAllFormatTypes(
     801             :     const util::URL& aParsedURL, utl::MediaDescriptor& rDescriptor, FlatDetection& rFlatTypes)
     802             : {
     803        2078 :     rFlatTypes.clear();
     804             : 
     805             :     // Get all filters that we have.
     806        2078 :     OUStringList aFilterNames;
     807             :     try
     808             :     {
     809        2078 :         osl::MutexGuard aLock(m_aLock);
     810        2078 :         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
     811        2078 :         aFilterNames = m_rCache->getItemNames(FilterCache::E_FILTER);
     812             :     }
     813           0 :     catch (const container::NoSuchElementException&)
     814             :     {
     815        2078 :         return;
     816             :     }
     817             : 
     818             :     // Retrieve the default type for each of these filters, and store them.
     819      477940 :     for (OUStringList::const_iterator it = aFilterNames.begin(); it != aFilterNames.end(); ++it)
     820             :     {
     821      475862 :         OUString aType = impl_getTypeFromFilter(*it);
     822             : 
     823      475862 :         if (aType.isEmpty())
     824           0 :             continue;
     825             : 
     826      951724 :         FlatDetectionInfo aInfo; // all flags set to false by default.
     827      475862 :         aInfo.sType = aType;
     828      475862 :         rFlatTypes.push_back(aInfo);
     829      475862 :     }
     830             : 
     831             :     {
     832             :         // Get all types that match the URL alone.
     833        2078 :         FlatDetection aFlatByURL;
     834        2078 :         m_rCache->detectFlatForURL(aParsedURL, aFlatByURL);
     835        2078 :         FlatDetection::const_iterator it = aFlatByURL.begin(), itEnd = aFlatByURL.end();
     836        4843 :         for (; it != itEnd; ++it)
     837             :         {
     838        2765 :             FlatDetection::iterator itPos = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(it->sType));
     839        2765 :             if (itPos == rFlatTypes.end())
     840             :                 // Not in the list yet.
     841           1 :                 rFlatTypes.push_back(*it);
     842             :             else
     843             :             {
     844             :                 // Already in the list. Update the flags.
     845        2764 :                 FlatDetectionInfo& rInfo = *itPos;
     846        2764 :                 const FlatDetectionInfo& rThisInfo = *it;
     847        2764 :                 if (rThisInfo.bMatchByExtension)
     848        2102 :                     rInfo.bMatchByExtension = true;
     849        2764 :                 if (rThisInfo.bMatchByPattern)
     850         662 :                     rInfo.bMatchByPattern = true;
     851        2764 :                 if (rThisInfo.bPreselectedByDocumentService)
     852           0 :                     rInfo.bPreselectedByDocumentService = true;
     853             :             }
     854        2078 :         }
     855             :     }
     856             : 
     857             :     // Remove duplicates.
     858        2078 :     rFlatTypes.sort(SortByType());
     859        2078 :     rFlatTypes.unique(EqualByType());
     860             : 
     861             :     // Mark pre-selected type (if any) to have it prioritized.
     862        4156 :     OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME(), OUString());
     863        2078 :     if (!sSelectedType.isEmpty())
     864           0 :         impl_getPreselectionForType(sSelectedType, aParsedURL, rFlatTypes, false);
     865             : 
     866             :     // Mark all types preferred by the current document service, to have it prioritized.
     867        4156 :     OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString());
     868        2078 :     if (!sSelectedDoc.isEmpty())
     869        3389 :         impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes);
     870             : }
     871             : 
     872             : 
     873             : 
     874        2078 : OUString TypeDetection::impl_detectTypeFlatAndDeep(      utl::MediaDescriptor& rDescriptor   ,
     875             :                                                           const FlatDetection&                 lFlatTypes    ,
     876             :                                                                 sal_Bool                       bAllowDeep    ,
     877             :                                                                 OUStringList&                  rUsedDetectors,
     878             :                                                                 OUString&               rLastChance   )
     879             : {
     880             :     // reset it everytimes, so the outside code can distinguish between
     881             :     // a set and a not set value.
     882        2078 :     rLastChance = OUString();
     883        2078 :     rUsedDetectors.clear();
     884             : 
     885             :     // step over all possible types for this URL.
     886             :     // solutions:
     887             :     // a) no types                                => no detection
     888             :     // b) deep detection not allowed              => return first valid type of list (because its the preferred or the first valid one)
     889             :     //    or(!) match by URLPattern               => in such case a deep detection will be supressed!
     890             :     // c) type has no detect service              => safe the first occurred type without a detect service
     891             :     //                                               as "last chance"(!). It will be used outside of this method
     892             :     //                                               if no further type could be detected.
     893             :     //                                               It must be the first one, because it can be a preferred type.
     894             :     //                                               Our types list was sorted by such criteria!
     895             :     // d) detect service return a valid result    => return its decision
     896             :     // e) detect service return an invalid result
     897             :     //    or any needed information could not be
     898             :     //    getted from the cache                   => ignore it, and continue with search
     899             : 
     900       64869 :     for (FlatDetection::const_iterator pFlatIt  = lFlatTypes.begin();
     901       43246 :                                        pFlatIt != lFlatTypes.end()  ;
     902             :                                      ++pFlatIt                      )
     903             :     {
     904       21619 :         const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt;
     905       21619 :         OUString sFlatType = aFlatTypeInfo.sType;
     906             : 
     907       21619 :         if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType))
     908           0 :             continue;
     909             : 
     910             :         // b)
     911       21619 :         if (
     912       21619 :             (!bAllowDeep                  ) ||
     913             :             (aFlatTypeInfo.bMatchByPattern)
     914             :            )
     915             :         {
     916         663 :             return sFlatType;
     917             :         }
     918             : 
     919             :         try
     920             :         {
     921             :             // SAFE -> ----------------------------------
     922       20956 :             ::osl::ResettableMutexGuard aLock(m_aLock);
     923       40340 :             CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType);
     924       20956 :             aLock.clear();
     925             : 
     926       40340 :             OUString sDetectService;
     927       20956 :             aType[PROPNAME_DETECTSERVICE] >>= sDetectService;
     928             : 
     929             :             // c)
     930       20956 :             if (sDetectService.isEmpty())
     931             :             {
     932             :                 // flat detected types without any registered deep detection service and not
     933             :                 // preselected by the user can be used as LAST CHANCE in case no other type could
     934             :                 // be detected. Of course only the first type without deep detector can be used.
     935             :                 // Further ones has to be ignored.
     936         161 :                 if (rLastChance.isEmpty())
     937          72 :                     rLastChance = sFlatType;
     938             : 
     939         161 :                 continue;
     940             :             }
     941             : 
     942             :             // dont forget to add every real asked deep detection service here.
     943             :             // Such detectors will be ignored if may be "impl_detectTypeDeepOnly()"
     944             :             // must be called later!
     945       20795 :             rUsedDetectors.push_back(sDetectService);
     946       40179 :             OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
     947             : 
     948             :             // d)
     949       20795 :             if (!sDeepType.isEmpty())
     950       20795 :                 return sDeepType;
     951             :         }
     952           0 :         catch(const css::container::NoSuchElementException&)
     953             :             {}
     954             :         // e)
     955       19384 :     }
     956             : 
     957           4 :     return OUString();
     958             :     // <- SAFE ----------------------------------
     959             : }
     960             : 
     961       23368 : void TypeDetection::impl_seekStreamToZero(utl::MediaDescriptor& rDescriptor)
     962             : {
     963             :     // try to seek to 0 ...
     964             :     // But because XSeekable is an optional interface ... try it only .-)
     965             :     css::uno::Reference< css::io::XInputStream > xStream = rDescriptor.getUnpackedValueOrDefault(
     966       23368 :                                                             utl::MediaDescriptor::PROP_INPUTSTREAM(),
     967       46736 :                                                             css::uno::Reference< css::io::XInputStream >());
     968       46736 :     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
     969       23368 :     if (xSeek.is())
     970             :     {
     971             :         try
     972             :         {
     973       23363 :             xSeek->seek(0);
     974             :         }
     975           0 :         catch(const css::uno::RuntimeException&)
     976             :         {
     977           0 :             throw;
     978             :         }
     979           0 :         catch(const css::uno::Exception&)
     980             :         {
     981             :         }
     982       23368 :     }
     983       23368 : }
     984             : 
     985       20795 : OUString TypeDetection::impl_askDetectService(const OUString&               sDetectService,
     986             :                                                            utl::MediaDescriptor& rDescriptor   )
     987             : {
     988             :     // Open the stream and add it to the media descriptor if this method is called for the first time.
     989             :     // All following requests to this method will detect, that there already exists a stream .-)
     990             :     // Attention: This method throws an exception if the stream could not be opened.
     991             :     // It's important to break any further detection in such case.
     992             :     // Catch it on the highest detection level only !!!
     993       20795 :     impl_openStream(rDescriptor);
     994             : 
     995             :     // seek to 0 is an optional feature to be more robust against
     996             :     // "simple implemented detect services" .-)
     997       20795 :     impl_seekStreamToZero(rDescriptor);
     998             : 
     999       20795 :     css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
    1000       41590 :     css::uno::Reference< css::uno::XComponentContext >         xContext;
    1001             : 
    1002             :     // SAFE ->
    1003       41590 :     ::osl::ResettableMutexGuard aLock(m_aLock);
    1004       20795 :     xContext = m_xContext;
    1005       20795 :     aLock.clear();
    1006             :     // <- SAFE
    1007             : 
    1008             :     try
    1009             :     {
    1010             :         // Attention! If e.g. an office module was not installed sometimes we
    1011             :         // find a registered detect service, which is referred inside the
    1012             :         // configuration ... but not really installed. On the other side we use
    1013             :         // third party components here, which can make trouble anyway.  So we
    1014             :         // should handle errors during creation of such services more
    1015             :         // gracefully .-)
    1016       23368 :         xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >(
    1017       41590 :                 xContext->getServiceManager()->createInstanceWithContext(sDetectService, xContext),
    1018        2573 :                 css::uno::UNO_QUERY_THROW);
    1019             :     }
    1020       18222 :     catch (...)
    1021             :     {
    1022             :     }
    1023             : 
    1024       20795 :     if ( ! xDetector.is())
    1025       18222 :         return OUString();
    1026             : 
    1027        5146 :     OUString sDeepType;
    1028             :     try
    1029             :     {
    1030             :         // start deep detection
    1031             :         // Dont forget to convert stl descriptor to its uno representation.
    1032             : 
    1033             :         /* Attention!
    1034             :                 You have to use an explicit instance of this uno sequence ...
    1035             :                 Because its used as an in out parameter. And in case of a temp. used object
    1036             :                 we will run into memory corruptions!
    1037             :         */
    1038        2573 :         css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
    1039        2573 :         rDescriptor >> lDescriptor;
    1040        2573 :         sDeepType = xDetector->detect(lDescriptor);
    1041        2573 :         rDescriptor << lDescriptor;
    1042             :     }
    1043           0 :     catch(const css::uno::Exception&)
    1044             :         {
    1045             :             // We should ignore errors here.
    1046             :             // Thrown exceptions mostly will end in crash recovery ...
    1047             :             // But might be we find another deep detection service which can detect the same
    1048             :             // document without a problem .-)
    1049           0 :             sDeepType = OUString();
    1050             :         }
    1051             : 
    1052             :     // seek to 0 is an optional feature to be more robust against
    1053             :     // "simple implemented detect services" .-)
    1054        2573 :     impl_seekStreamToZero(rDescriptor);
    1055             : 
    1056             :     // analyze the results
    1057             :     // a) detect service returns "" => return "" too and remove TYPE/FILTER prop from descriptor
    1058             :     // b) returned type is unknown  => return "" too and remove TYPE/FILTER prop from descriptor
    1059             :     // c) returned type is valid    => check TYPE/FILTER props inside descriptor and return the type
    1060             : 
    1061             :     // this special helper checks for a valid type
    1062             :     // and set right values on the descriptor!
    1063        2573 :     sal_Bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType);
    1064        2573 :     if (bValidType)
    1065        1411 :         return sDeepType;
    1066             : 
    1067       21957 :     return OUString();
    1068             : }
    1069             : 
    1070             : 
    1071             : 
    1072           4 : OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(utl::MediaDescriptor& rDescriptor)
    1073             : {
    1074             :     css::uno::Reference< css::task::XInteractionHandler > xInteraction =
    1075           4 :         rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INTERACTIONHANDLER(),
    1076           8 :         css::uno::Reference< css::task::XInteractionHandler >());
    1077             : 
    1078           4 :     if (!xInteraction.is())
    1079           4 :         return OUString();
    1080             : 
    1081             :     OUString sURL =
    1082           0 :         rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL(),
    1083           0 :         OUString());
    1084             : 
    1085             :     css::uno::Reference< css::io::XInputStream > xStream =
    1086           0 :         rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INPUTSTREAM(),
    1087           0 :         css::uno::Reference< css::io::XInputStream >());
    1088             : 
    1089             :     // Dont distrub the user for "non existing files - means empty URLs" or
    1090             :     // if we was forced to detect a stream.
    1091             :     // Reason behind: We must be shure to ask user for "unknown contents" only ...
    1092             :     // and not for "missing files". Especialy if detection is done by a stream only
    1093             :     // we cant check if the stream points to an "existing content"!
    1094           0 :     if (
    1095           0 :         (sURL.isEmpty()                                     ) || // "non existing file" ?
    1096           0 :         (!xStream.is()                                         ) || // non existing file !
    1097           0 :         (sURL.equalsIgnoreAsciiCase("private:stream"))    // not a good idea .-)
    1098             :        )
    1099           0 :         return OUString();
    1100             : 
    1101             :     try
    1102             :     {
    1103             :         // create a new request to ask user for it's decision about the usable filter
    1104           0 :         ::framework::RequestFilterSelect aRequest(sURL);
    1105           0 :         xInteraction->handle(aRequest.GetRequest());
    1106             : 
    1107             :         // "Cancel" pressed? => return with error
    1108           0 :         if (aRequest.isAbort())
    1109           0 :             return OUString();
    1110             : 
    1111             :         // "OK" pressed => verify the selected filter, get its corresponding
    1112             :         // type and return it. (BTW: We must update the media descriptor here ...)
    1113             :         // The user selected explicitly a filter ... but normaly we are interested on
    1114             :         // a type here only. But we must be shure, that the selected filter is used
    1115             :         // too and no ambigous filter registration disturb us .-)
    1116             : 
    1117           0 :         OUString sFilter = aRequest.getFilter();
    1118           0 :         if (!impl_validateAndSetFilterOnDescriptor(rDescriptor, sFilter))
    1119           0 :             return OUString();
    1120             : 
    1121           0 :         OUString sType;
    1122           0 :         rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()] >>= sType;
    1123           0 :         return sType;
    1124             :     }
    1125           0 :     catch(const css::uno::Exception&)
    1126             :         {}
    1127             : 
    1128           4 :     return OUString();
    1129             : }
    1130             : 
    1131             : 
    1132             : 
    1133       20795 : void TypeDetection::impl_openStream(utl::MediaDescriptor& rDescriptor)
    1134             :     throw (css::uno::Exception)
    1135             : {
    1136       20795 :     sal_Bool bSuccess = sal_False;
    1137       20795 :     OUString sURL = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_URL(), OUString() );
    1138       20795 :     sal_Bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_READONLY(), sal_False );
    1139       20795 :     if ( !sURL.isEmpty() && ::utl::LocalFileHelper::IsLocalFile( INetURLObject( sURL ).GetMainURL( INetURLObject::NO_DECODE ) ) )
    1140             :     {
    1141             :         // OOo uses own file locking mechanics in case of local file
    1142       20187 :         bSuccess = rDescriptor.addInputStreamOwnLock();
    1143             :     }
    1144             :     else
    1145         608 :         bSuccess = rDescriptor.addInputStream();
    1146             : 
    1147       20795 :     if ( !bSuccess )
    1148             :         throw css::uno::Exception(
    1149           0 :             "Could not open stream for <" + sURL + ">",
    1150           0 :             static_cast<OWeakObject *>(this));
    1151             : 
    1152       20795 :     if ( !bRequestedReadOnly )
    1153             :     {
    1154             :         // The MediaDescriptor implementation adds ReadOnly argument if the file can not be opened for writing
    1155             :         // this argument should be either removed or an additional argument should be added so that application
    1156             :         // can separate the case when the user explicitly requests readonly document.
    1157             :         // The current solution is to remove it here.
    1158       20794 :         rDescriptor.erase( utl::MediaDescriptor::PROP_READONLY() );
    1159       20795 :     }
    1160       20795 : }
    1161             : 
    1162             : 
    1163             : 
    1164        1162 : void TypeDetection::impl_removeTypeFilterFromDescriptor(utl::MediaDescriptor& rDescriptor)
    1165             : {
    1166        1162 :     utl::MediaDescriptor::iterator pItType   = rDescriptor.find(utl::MediaDescriptor::PROP_TYPENAME()  );
    1167        1162 :     utl::MediaDescriptor::iterator pItFilter = rDescriptor.find(utl::MediaDescriptor::PROP_FILTERNAME());
    1168        1162 :     if (pItType != rDescriptor.end())
    1169        1162 :         rDescriptor.erase(pItType);
    1170        1162 :     if (pItFilter != rDescriptor.end())
    1171           0 :         rDescriptor.erase(pItFilter);
    1172        1162 : }
    1173             : 
    1174             : 
    1175             : 
    1176       26270 : sal_Bool TypeDetection::impl_validateAndSetTypeOnDescriptor(      utl::MediaDescriptor& rDescriptor,
    1177             :                                                             const OUString&               sType      )
    1178             : {
    1179             :     // SAFE ->
    1180       26270 :     ::osl::ResettableMutexGuard aLock(m_aLock);
    1181       26270 :     if (m_rCache->hasItem(FilterCache::E_TYPE, sType))
    1182             :     {
    1183       25108 :         rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()] <<= sType;
    1184       25108 :         return sal_True;
    1185             :     }
    1186        1162 :     aLock.clear();
    1187             :     // <- SAFE
    1188             : 
    1189             :     // remove all related information from the descriptor
    1190        1162 :     impl_removeTypeFilterFromDescriptor(rDescriptor);
    1191        1162 :     return sal_False;
    1192             : }
    1193             : 
    1194             : 
    1195             : 
    1196           0 : sal_Bool TypeDetection::impl_validateAndSetFilterOnDescriptor(      utl::MediaDescriptor& rDescriptor,
    1197             :                                                               const OUString&               sFilter    )
    1198             : {
    1199             :     try
    1200             :     {
    1201             :         // SAFE ->
    1202           0 :         ::osl::ResettableMutexGuard aLock(m_aLock);
    1203             : 
    1204           0 :         CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
    1205           0 :         OUString sType;
    1206           0 :         aFilter[PROPNAME_TYPE] >>= sType;
    1207           0 :         CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
    1208             : 
    1209           0 :         aLock.clear();
    1210             :         // <- SAFE
    1211             : 
    1212             :         // found valid type and filter => set it on the given descriptor
    1213           0 :         rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
    1214           0 :         rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
    1215           0 :         return sal_True;
    1216             :     }
    1217           0 :     catch(const css::container::NoSuchElementException&){}
    1218             : 
    1219             :     // remove all related information from the descriptor
    1220           0 :     impl_removeTypeFilterFromDescriptor(rDescriptor);
    1221           0 :     return sal_False;
    1222             : }
    1223             : 
    1224             : 
    1225             : 
    1226       25843 : OUString TypeDetection::impl_getImplementationName()
    1227             : {
    1228       25843 :     return OUString( "com.sun.star.comp.filter.config.TypeDetection" );
    1229             : }
    1230             : 
    1231             : 
    1232             : 
    1233       25531 : css::uno::Sequence< OUString > TypeDetection::impl_getSupportedServiceNames()
    1234             : {
    1235       25531 :     css::uno::Sequence< OUString > lServiceNames(1);
    1236       25531 :     lServiceNames[0] = "com.sun.star.document.TypeDetection";
    1237       25531 :     return lServiceNames;
    1238             : }
    1239             : 
    1240             : 
    1241             : 
    1242       25457 : css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
    1243             : {
    1244       25457 :     TypeDetection* pNew = new TypeDetection( comphelper::getComponentContext(xSMGR) );
    1245       25457 :     return css::uno::Reference< css::uno::XInterface >(static_cast< css::document::XTypeDetection* >(pNew), css::uno::UNO_QUERY);
    1246             : }
    1247             : 
    1248             :     } // namespace config
    1249             : } // namespace filter
    1250             : 
    1251             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10