1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 #include "typedetection.hxx"
27 #include "constant.hxx"
28 
29 //_______________________________________________
30 // includes
31 #include <com/sun/star/document/XExtendedFilterDetection.hpp>
32 #include <com/sun/star/util/XURLTransformer.hpp>
33 
34 #ifndef _COM_SUN_STAR_IO_XINPUSTREAM_HPP_
35 #include <com/sun/star/io/XInputStream.hpp>
36 #endif
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 
45 //_______________________________________________
46 // namespace
47 
48 namespace filter{
49     namespace config{
50 
51 namespace css = ::com::sun::star;
52 
53 //_______________________________________________
54 // definitions
55 
56 // Use this switch to change the behavior of preselection DocumentService ... (see using for further informations)
57 #define IGNORE_NON_URLMATCHING_TYPES_FOR_PRESELECTION_DOCUMENTSERVICE
58 
59 // enable/disable special handling for CSV/TXT problem
60 #define WORKAROUND_CSV_TXT_BUG_i60158
61 
62 /*-----------------------------------------------
63     03.07.2003 11:25
64 -----------------------------------------------*/
TypeDetection(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)65 TypeDetection::TypeDetection(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
66 {
67     BaseContainer::init(xSMGR                                         ,
68                         TypeDetection::impl_getImplementationName()   ,
69                         TypeDetection::impl_getSupportedServiceNames(),
70                         FilterCache::E_TYPE                           );
71 }
72 
73 /*-----------------------------------------------
74     03.07.2003 10:36
75 -----------------------------------------------*/
~TypeDetection()76 TypeDetection::~TypeDetection()
77 {
78 }
79 
80 /*-----------------------------------------------
81     03.11.2003 08:43
82 -----------------------------------------------*/
queryTypeByURL(const::rtl::OUString & sURL)83 ::rtl::OUString SAL_CALL TypeDetection::queryTypeByURL(const ::rtl::OUString& sURL)
84     throw (css::uno::RuntimeException)
85 {
86     ::rtl::OUString sType;
87 
88     // SAFE ->
89     ::osl::ResettableMutexGuard aLock(m_aLock);
90 
91     css::util::URL  aURL;
92     aURL.Complete = sURL;
93     css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICE_URLTRANSFORMER), css::uno::UNO_QUERY);
94     xParser->parseStrict(aURL);
95 
96     // set std types as minimum requirement first!
97     // Only in case no type was found for given URL,
98     // use optional types too ...
99     FlatDetection lFlatTypes;
100     m_rCache->detectFlatForURL(aURL, lFlatTypes);
101 
102     if (
103         (lFlatTypes.size() < 1                                ) &&
104         (!m_rCache->isFillState(FilterCache::E_CONTAINS_TYPES))
105        )
106     {
107         m_rCache->load(FilterCache::E_CONTAINS_TYPES);
108         m_rCache->detectFlatForURL(aURL, lFlatTypes);
109     }
110 
111     // first item is guaranteed as "preferred" one!
112     if (lFlatTypes.size() > 0)
113     {
114         const FlatDetectionInfo& aMatch = *(lFlatTypes.begin());
115         sType = aMatch.sType;
116     }
117 
118     return sType;
119     // <- SAFE
120 }
121 
122 /*-----------------------------------------------
123     31.10.2003 09:36
124 -----------------------------------------------*/
queryTypeByDescriptor(css::uno::Sequence<css::beans::PropertyValue> & lDescriptor,sal_Bool bAllowDeep)125 ::rtl::OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
126                                                               sal_Bool                                         bAllowDeep )
127     throw (css::uno::RuntimeException)
128 {
129     // make the descriptor more usable :-)
130     ::comphelper::MediaDescriptor stlDescriptor(lDescriptor);
131 
132     // SAFE -> ----------------------------------
133     ::osl::ResettableMutexGuard aLock(m_aLock);
134 
135     //*******************************************
136     // parse given URL to split it into e.g. main and jump marks ...
137     ::rtl::OUString sURL = stlDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString());
138 
139 #if OSL_DEBUG_LEVEL > 0
140     if (stlDescriptor.find(::rtl::OUString::createFromAscii("FileName")) != stlDescriptor.end())
141         OSL_ENSURE(sal_False, "Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
142 #endif
143 
144     css::util::URL  aURL;
145     aURL.Complete = sURL;
146     css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICE_URLTRANSFORMER), css::uno::UNO_QUERY);
147     xParser->parseStrict(aURL);
148 
149     //*******************************************
150     // preselected filter, type or document service?
151     // use it as first "flat" detected type later!
152     FlatDetection lFlatTypes;
153     impl_getPreselection(aURL, stlDescriptor, lFlatTypes);
154 
155     //*******************************************
156     // get all types, which match to the given descriptor
157     // That can be true by: extensions/url pattern/mime type etcpp.
158     m_rCache->detectFlatForURL(aURL, lFlatTypes);
159 
160     aLock.clear();
161     // <- SAFE ----------------------------------
162 
163     ::rtl::OUString sType      ;
164     ::rtl::OUString sLastChance;
165 
166     try
167     {
168         //*******************************************
169         // verify every flat detected (or preselected!) type
170         // by calling its registered deep detection service.
171         // But break this loop if a type match to the given descriptor
172         // by an URL pattern(!) or if deep detection isn't allowed from
173         // outside (bAllowDeep=sal_False) or break the whole detection by
174         // throwing an exception if creation of the might needed input
175         // stream failed by e.g. an IO exception ...
176         OUStringList lUsedDetectors;
177         if (lFlatTypes.size()>0)
178             sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, lUsedDetectors, sLastChance);
179 
180         //*******************************************
181         // if no flat detected (nor preselected!) type could be
182         // verified and no error occurred during creation of
183         // the might needed input stream, start detection
184         // which uses all registered deep detection services.
185         if (
186             (!sType.getLength()) &&
187             (bAllowDeep        )
188            )
189         {
190             sType = impl_detectTypeDeepOnly(stlDescriptor, lUsedDetectors);
191         }
192 
193         //*******************************************
194         // flat detection failed
195         // pure deep detection failed
196         // => ask might existing InteractionHandler
197         // means: ask user for it's decision
198         if (!sType.getLength())
199             sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor);
200 
201         //*******************************************
202         // no real detected type - but a might valid one.
203         // update descriptor and set last chance for return.
204         if (!sType.getLength() && sLastChance.getLength())
205         {
206             OSL_ENSURE(sal_False, "set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!");
207             sType = sLastChance;
208         }
209     }
210     catch(const css::uno::RuntimeException&)
211         { throw; }
212     catch(const css::uno::Exception&)
213         { sType = ::rtl::OUString(); }
214 
215     //*******************************************
216     // adapt media descriptor, so it contains the right values
217     // for type/filter name/document service/ etcpp.
218     impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!!
219     impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType);
220 
221     stlDescriptor >> lDescriptor;
222     return sType;
223 }
224 
225 /*-----------------------------------------------
226     03.07.2003 10:36
227 -----------------------------------------------*/
impl_checkResultsAndAddBestFilter(::comphelper::MediaDescriptor & rDescriptor,::rtl::OUString & sType)228 void TypeDetection::impl_checkResultsAndAddBestFilter(::comphelper::MediaDescriptor& rDescriptor,
229                                                       ::rtl::OUString&               sType      )
230 {
231     // a)
232     // Don't overwrite a might preselected filter!
233     ::rtl::OUString sFilter = rDescriptor.getUnpackedValueOrDefault(
234                                 ::comphelper::MediaDescriptor::PROP_FILTERNAME(),
235                                 ::rtl::OUString());
236     if (sFilter.getLength())
237         return;
238 
239     // b)
240     // check a preselected document service too.
241     // Then we have to search a suitable filter witin this module.
242     ::rtl::OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault(
243                                             ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(),
244                                             ::rtl::OUString());
245     if (sDocumentService.getLength())
246     {
247         try
248         {
249             ::rtl::OUString sRealType = sType;
250 
251             #ifdef WORKAROUND_CSV_TXT_BUG_i60158
252             // Workaround for #i60158#
253             // We do not have right filter for Text_Ascii in calc nor a suitable filter for CSV in writer.
254             // So we must overrule our detection and make the right things. Normally we should have
255             // one type TextAscii and two filters registered for these one type.
256             // But then we loose automatic opening of CSV files in calc instead of opening these files
257             // inside writer.
258             if (
259                 (sDocumentService.equalsAscii("com.sun.star.sheet.SpreadsheetDocument")) &&
260                 (
261                     (sRealType.equalsAscii("writer_Text"        )) ||
262                     (sRealType.equalsAscii("writer_Text_encoded"))
263                 )
264                )
265             {
266                 sRealType = ::rtl::OUString::createFromAscii("calc_Text_txt_csv_StarCalc");
267             }
268             else
269             if (
270                 (sDocumentService.equalsAscii("com.sun.star.text.TextDocument")) &&
271                 (sRealType.equalsAscii("calc_Text_txt_csv_StarCalc"           ))
272                )
273             {
274                 sRealType = ::rtl::OUString::createFromAscii("writer_Text");
275             }
276             #endif // WORKAROUND_CSV_TXT_BUG_i60158
277 
278             // SAFE ->
279             ::osl::ResettableMutexGuard aLock(m_aLock);
280 
281             // Attention: For executing next lines of code, We must be sure that
282             // all filters already loaded :-(
283             // That can disturb our "load on demand feature". But we have no other chance!
284             m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
285 
286             CacheItem lIProps;
287             lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService;
288             lIProps[PROPNAME_TYPE           ] <<= sRealType;
289             OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
290 
291             aLock.clear();
292             // <- SAFE
293 
294             for (  OUStringList::const_iterator pIt  = lFilters.begin();
295                    pIt != lFilters.end() && sFilter.getLength() == 0 ;
296                  ++pIt                    )
297             {
298                 // SAFE ->
299                 aLock.reset();
300                 try
301                 {
302                     CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt);
303                     sal_Int32 nFlags  = 0;
304                     aFilter[PROPNAME_FLAGS] >>= nFlags;
305 
306                     if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
307                         sFilter = *pIt;
308                 }
309                 catch(const css::uno::Exception&) {}
310                 aLock.clear();
311                 // <- SAFE
312             }
313 
314             if (sFilter.getLength() > 0)
315             {
316                 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sRealType;
317                 rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
318                 sType = sRealType;
319                 return;
320             }
321         }
322         catch(const css::uno::Exception&)
323             {}
324     }
325 
326     // c)
327     // We can use the preferred filter for the specified type.
328     // Such preferred filter points:
329     // - to the default filter of the preferred application
330     // - or to any other filter if no preferred filter was set.
331     // Note: It's an optimization only!
332     // It's not guaranteed, that such preferred filter exists.
333     sFilter = ::rtl::OUString();
334     try
335     {
336         // SAFE ->
337         ::osl::ResettableMutexGuard aLock(m_aLock);
338 
339         CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
340         aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
341         CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
342 
343         aLock.clear();
344         // <- SAFE
345 
346         // no exception => found valid type and filter => set it on the given descriptor
347         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
348         rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
349         return;
350     }
351     catch(const css::uno::Exception&)
352         {}
353 
354     // d)
355     // Search for any import(!) filter, which is registered for this type.
356     sFilter = ::rtl::OUString();
357     try
358     {
359         // SAFE ->
360         ::osl::ResettableMutexGuard aLock(m_aLock);
361 
362         // Attention: For executing next lines of code, We must be sure that
363         // all filters already loaded :-(
364         // That can disturb our "load on demand feature". But we have no other chance!
365         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
366 
367         CacheItem lIProps;
368         lIProps[PROPNAME_TYPE] <<= sType;
369         OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
370 
371         aLock.clear();
372         // <- SAFE
373 
374         OUStringList::const_iterator pIt;
375         for (  pIt  = lFilters.begin();
376                pIt != lFilters.end()  ;
377              ++pIt                    )
378         {
379             sFilter = *pIt;
380 
381             // SAFE ->
382             aLock.reset();
383             try
384             {
385                 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
386                 sal_Int32 nFlags  = 0;
387                 aFilter[PROPNAME_FLAGS] >>= nFlags;
388 
389                 if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
390                     break;
391             }
392             catch(const css::uno::Exception&)
393                 { continue; }
394             aLock.clear();
395             // <- SAFE
396 
397             sFilter = ::rtl::OUString();
398         }
399 
400         if (sFilter.getLength())
401         {
402             rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
403             rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
404             return;
405         }
406     }
407     catch(const css::uno::Exception&)
408         {}
409 }
410 
411 /*-----------------------------------------------
412     14.11.2003 12:06
413 -----------------------------------------------*/
impl_getPreselectionForType(const::rtl::OUString & sPreSelType,const css::util::URL & aParsedURL,FlatDetection & rFlatTypes)414 sal_Bool TypeDetection::impl_getPreselectionForType(const ::rtl::OUString& sPreSelType,
415                                                     const css::util::URL&  aParsedURL ,
416                                                           FlatDetection&   rFlatTypes )
417 {
418     // Can be used to suppress execution of some parts of this method
419     // if it's already clear that detected type is valid or not.
420     // It's necessary to use shared code at the end, which updates
421     // all return parameters consistent!
422     sal_Bool bBreakDetection = sal_False;
423 
424     // Further we must know if it matches by pattern
425     // Every flat detected type by pattern won't be detected deep!
426     sal_Bool bMatchByPattern = sal_False;
427 
428     // And we must know if a preselection must be preferred, because
429     // it matches by it's extension too.
430     sal_Bool bMatchByExtension = sal_False;
431 
432     // If we e.g. collect all filters of a factory (be a forced factory preselection)
433     // we should prefer all filters of this factory, where the type match the given URL.
434     // All other types (which correspond to filters of the same factory - but don't match
435     // the URL) should be "used later" for detection and sorted at the end of our return vector
436     // rFlatTypes!
437     // => bPreferredPreselection = (matchByExtension || matchByURLPattern)
438     sal_Bool bPreferredPreselection = sal_False;
439 
440     // validate type
441     ::rtl::OUString sType(sPreSelType);
442     CacheItem       aType;
443     try
444     {
445         // SAFE -> --------------------------
446         ::osl::ResettableMutexGuard aLock(m_aLock);
447         aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
448         aLock.clear();
449         // <- SAFE --------------------------
450     }
451     catch(const css::container::NoSuchElementException&)
452     {
453         sType = ::rtl::OUString();
454         bBreakDetection = sal_True;
455     }
456 
457     if (!bBreakDetection)
458     {
459         // We can't check a preselected type for a given stream!
460         // So we must believe, that it can work ...
461         if (aParsedURL.Complete.equalsAsciiL("private:stream", 14))
462             bBreakDetection = sal_True;
463     }
464 
465     if (!bBreakDetection)
466     {
467         // extract extension from URL .. to check it case-insensitive !
468         INetURLObject   aParser    (aParsedURL.Main);
469         ::rtl::OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT       ,
470                                                           sal_True                          ,
471                                                           INetURLObject::DECODE_WITH_CHARSET);
472         sExtension = sExtension.toAsciiLowerCase();
473 
474         // otherwise we must know, if it matches to the given URL really.
475         // especially if it matches by its extension or pattern registration.
476         OUStringList lExtensions(aType[PROPNAME_EXTENSIONS]);
477         OUStringList lURLPattern(aType[PROPNAME_URLPATTERN]);
478 
479         for (OUStringList::const_iterator pIt  = lExtensions.begin();
480                                           pIt != lExtensions.end()  ;
481                                         ++pIt                       )
482         {
483             ::rtl::OUString sCheckExtension(pIt->toAsciiLowerCase());
484             if (sCheckExtension.equals(sExtension))
485             {
486                 bBreakDetection        = sal_True;
487                 bMatchByExtension      = sal_True;
488                 bPreferredPreselection = sal_True;
489                 break;
490             }
491         }
492 
493         if (!bBreakDetection)
494         {
495             for (OUStringList::const_iterator pIt  = lURLPattern.begin();
496                                               pIt != lURLPattern.end()  ;
497                                             ++pIt                       )
498             {
499                 WildCard aCheck(*pIt);
500                 if (aCheck.Matches(aParsedURL.Main))
501                 {
502                     bBreakDetection        = sal_True;
503                     bMatchByPattern        = sal_True;
504                     bPreferredPreselection = sal_True;
505                     break;
506                 }
507             }
508         }
509 
510         /*
511             Comment ... why the following line of code should be commented out .-)
512 
513             This type does not seem to fit the requirements
514             But it's an existing and well known type.
515             At least - [because maybe the extension was missing :-( ]
516             we should try to detect this type deep ...
517             So we accept it here :-)
518 
519 		if (!bBreakDetection)
520             sType = ::rtl::OUString();
521 		*/
522     }
523 
524     // if it's a valid type - set it on all return values!
525     if (sType.getLength())
526     {
527         FlatDetectionInfo aInfo;
528         aInfo.sType              = sType;
529         aInfo.bMatchByExtension  = bMatchByExtension;
530         aInfo.bMatchByPattern    = bMatchByPattern;
531         aInfo.bPreselectedAsType = sal_True;
532 
533         if (bPreferredPreselection)
534             rFlatTypes.push_front(aInfo);
535         else
536             rFlatTypes.push_back(aInfo);
537 
538         return sal_True;
539     }
540 
541     // not valid!
542     return sal_False;
543 }
544 
545 /*-----------------------------------------------
546     14.11.2003 12:09
547 -----------------------------------------------*/
impl_getPreselectionForFilter(const::rtl::OUString & sPreSelFilter,const css::util::URL & aParsedURL,FlatDetection & rFlatTypes)548 sal_Bool TypeDetection::impl_getPreselectionForFilter(const ::rtl::OUString& sPreSelFilter,
549                                                       const css::util::URL&  aParsedURL   ,
550                                                             FlatDetection&   rFlatTypes   )
551 {
552     // Can be used to suppress execution of some parts of this method
553     // if it's already clear that detected filter is valid or not.
554     // It's necessary to use shared code at the end, which updates
555     // all return parameters consistent!
556     sal_Bool bBreakDetection = sal_False;
557 
558     // validate filter
559     ::rtl::OUString sFilter(sPreSelFilter);
560     CacheItem       aFilter;
561     try
562     {
563         // SAFE -> --------------------------
564         ::osl::ResettableMutexGuard aLock(m_aLock);
565         aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
566         aLock.clear();
567         // <- SAFE --------------------------
568     }
569     catch(const css::container::NoSuchElementException&)
570     {
571         sFilter = ::rtl::OUString();
572         bBreakDetection = sal_True;
573     }
574 
575     if (!bBreakDetection)
576     {
577         // get its type and check if it matches the given URL
578         ::rtl::OUString sType;
579         aFilter[PROPNAME_TYPE] >>= sType;
580 
581         bBreakDetection = impl_getPreselectionForType(sType, aParsedURL, rFlatTypes);
582 
583         // not a valid type? -> not a valid filter!
584         if (!bBreakDetection)
585             sFilter = ::rtl::OUString();
586     }
587 
588     // We have to mark all retrieved preselection items as "preselected by filter"!
589     FlatDetection::iterator pIt;
590     for (  pIt  = rFlatTypes.begin();
591            pIt != rFlatTypes.end()  ;
592          ++pIt                      )
593     {
594         FlatDetectionInfo& rInfo = *pIt;
595         rInfo.bPreselectedAsType   = sal_False;
596         rInfo.bPreselectedByFilter = sal_True;
597     }
598 
599     if (sFilter.getLength())
600         return sal_True;
601     else
602         return sal_False;
603 }
604 
605 /*-----------------------------------------------
606     14.11.2003 12:11
607 -----------------------------------------------*/
impl_getPreselectionForDocumentService(const::rtl::OUString & sPreSelDocumentService,const css::util::URL & aParsedURL,FlatDetection & rFlatTypes)608 sal_Bool TypeDetection::impl_getPreselectionForDocumentService(const ::rtl::OUString& sPreSelDocumentService,
609                                                                const css::util::URL&  aParsedURL            ,
610                                                                      FlatDetection&   rFlatTypes            )
611 {
612     // get all filters, which match to this doc service
613     OUStringList lFilters;
614     try
615     {
616         // SAFE -> --------------------------
617         ::osl::ResettableMutexGuard aLock(m_aLock);
618 
619         // Attention: For executing next lines of code, We must be sure that
620         // all filters already loaded :-(
621         // That can disturb our "load on demand feature". But we have no other chance!
622         m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
623 
624         CacheItem lIProps;
625         lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService;
626         lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
627 
628         aLock.clear();
629         // <- SAFE --------------------------
630     }
631     catch(const css::container::NoSuchElementException&)
632     {
633         lFilters.clear();
634     }
635 
636     // step over all filters, and check if its registered type
637     // match the given URL.
638     // But use temp. list of "preselected types" instead of incoming rFlatTypes list!
639     // The reason behind: we must filter the getted results. And copying of stl entries
640     // is an easier job then removing it .-)
641     FlatDetection lPreselections;
642     for (OUStringList::const_iterator pFilter  = lFilters.begin();
643                                       pFilter != lFilters.end()  ;
644                                     ++pFilter                    )
645     {
646         const ::rtl::OUString sFilter = *pFilter;
647         impl_getPreselectionForFilter(sFilter, aParsedURL, lPreselections);
648     }
649 
650     // We have to mark all retrieved preselection items as "preselected by document service".
651     // Further we must ignore all preselected items, which does not match the URL!
652     FlatDetection::iterator pIt;
653     for (  pIt  = lPreselections.begin();
654            pIt != lPreselections.end()  ;
655          ++pIt                          )
656     {
657         FlatDetectionInfo& rInfo = *pIt;
658 
659         /*
660             #i60158#
661             Preselection by DocumentService ...
662             How many filters (and corresponding types) must be checked ?
663             All or only the list of filters/types, which match to the given URL too ?
664             There is no final decision about this currently. So we make it "configurable" .-)
665         */
666         #ifdef IGNORE_NON_URLMATCHING_TYPES_FOR_PRESELECTION_DOCUMENTSERVICE
667         if (
668             (!rInfo.bMatchByExtension) &&
669             (!rInfo.bMatchByPattern  )
670            )
671            continue;
672         #endif
673 
674         rInfo.bPreselectedAsType            = sal_False;
675         rInfo.bPreselectedByFilter          = sal_False;
676         rInfo.bPreselectedByDocumentService = sal_True ;
677         rFlatTypes.push_back(rInfo);
678     }
679 
680     return sal_True;
681 }
682 
683 /*-----------------------------------------------
684     14.11.2003 12:21
685 -----------------------------------------------*/
impl_getPreselection(const css::util::URL & aParsedURL,::comphelper::MediaDescriptor & rDescriptor,FlatDetection & rFlatTypes)686 void TypeDetection::impl_getPreselection(const css::util::URL&                aParsedURL ,
687                                                ::comphelper::MediaDescriptor& rDescriptor,
688                                                FlatDetection&                 rFlatTypes )
689 {
690     // done to be sure, that only valid results leave this function!
691     rFlatTypes.clear();
692 
693     /* #i55122#
694         Sometimes we must detect files without or with real unknown extensions.
695         If it does not work /which can happen of course .-)/, the user tried to preselect
696         the right format. But some special dialogs (e.g. "Insert->Sheet From File")
697         add it's own preselection too.
698         So we have a combination of preselected values ...
699 
700         Then we should prefer the most important one - set by the user.
701         And the user normally preselects a filter or type. The preselected
702         document service cames from the dialog.
703 
704         Further it doesn't matter if the user preselected a filter or a document service.
705         A filter selection is always more explicit then a document service selection.
706         So it must be pereferred. An order between type and filter selection can't be discussed .-)
707     */
708 
709     ::rtl::OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
710     if (sSelectedType.getLength())
711         impl_getPreselectionForType(sSelectedType, aParsedURL, rFlatTypes);
712 
713     ::rtl::OUString sSelectedFilter = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString());
714     if (sSelectedFilter.getLength())
715         impl_getPreselectionForFilter(sSelectedFilter, aParsedURL, rFlatTypes);
716 
717     ::rtl::OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), ::rtl::OUString());
718     if (sSelectedDoc.getLength())
719         impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes);
720 }
721 
722 /*-----------------------------------------------
723     03.11.2003 09:17
724 -----------------------------------------------*/
impl_detectTypeFlatAndDeep(::comphelper::MediaDescriptor & rDescriptor,const FlatDetection & lFlatTypes,sal_Bool bAllowDeep,OUStringList & rUsedDetectors,::rtl::OUString & rLastChance)725 ::rtl::OUString TypeDetection::impl_detectTypeFlatAndDeep(      ::comphelper::MediaDescriptor& rDescriptor   ,
726                                                           const FlatDetection&                 lFlatTypes    ,
727                                                                 sal_Bool                       bAllowDeep    ,
728                                                                 OUStringList&                  rUsedDetectors,
729                                                                 ::rtl::OUString&               rLastChance   )
730 {
731     // reset it every time, so the outside code can distinguish between
732     // a set and a not set value.
733     rLastChance = ::rtl::OUString();
734     rUsedDetectors.clear();
735 
736     // step over all possible types for this URL.
737     // solutions:
738     // a) no types                                => no detection
739     // b) deep detection not allowed              => return first valid type of list (because it's the preferred or the first valid one)
740     //    or(!) match by URLPattern               => in such case a deep detection will be suppressed!
741     // c) type has no detect service              => safe the first occurred type without a detect service
742     //                                               as "last chance"(!). It will be used outside of this method
743     //                                               if no further type could be detected.
744     //                                               It must be the first one, because it can be a preferred type.
745     //                                               Our types list was sorted by such criteria!
746     // d) detect service return a valid result    => return its decision
747     // e) detect service return an invalid result
748     //    or any needed information could not be
749     //    getted from the cache                   => ignore it, and continue with search
750 
751     for (FlatDetection::const_iterator pFlatIt  = lFlatTypes.begin();
752                                        pFlatIt != lFlatTypes.end()  ;
753                                      ++pFlatIt                      )
754     {
755         const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt;
756               ::rtl::OUString    sFlatType     = aFlatTypeInfo.sType;
757 
758         if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType))
759             continue;
760 
761         // b)
762         if (
763             (!bAllowDeep                  ) ||
764             (aFlatTypeInfo.bMatchByPattern)
765            )
766         {
767             return sFlatType;
768         }
769 
770         try
771         {
772             // SAFE -> ----------------------------------
773             ::osl::ResettableMutexGuard aLock(m_aLock);
774             CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType);
775             aLock.clear();
776 
777             ::rtl::OUString sDetectService;
778             aType[PROPNAME_DETECTSERVICE] >>= sDetectService;
779 
780             // c)
781             if (!sDetectService.getLength())
782             {
783                 // accept or not accept flat types without deep detection: that's the question :-)
784                 // May be there exists some states, where we have to use our LastChance feature instead
785                 // of using the flat type directly.
786                 // Here the list of task ID's, which was related to these lines of code:
787                 // #i47159#, #i43404#, #i46494#
788 
789                 // a flat detected type without the chance for a deep detection ... but preselected by the user
790                 // explicitly (means preselected as type or filter ... not as documentservice!)
791                 // should be accepted. So the user can overrule our detection.
792                 if (
793                     (aFlatTypeInfo.bPreselectedAsType  ) ||
794                     (aFlatTypeInfo.bPreselectedByFilter)
795                    )
796                     return sFlatType;
797 
798                 // flat detected types without any registered deep detection service and not
799                 // preselected by the user can be used as LAST CHANCE in case no other type could
800                 // be detected. Of course only the first type without deep detector can be used.
801                 // Further ones has to be ignored.
802                 if (rLastChance.getLength() < 1)
803                     rLastChance = sFlatType;
804 
805                 continue;
806             }
807 
808             // don't forget to add every real asked deep detection service here.
809             // Such detectors will be ignored if may be "impl_detectTypeDeepOnly()"
810             // must be called later!
811             rUsedDetectors.push_back(sDetectService);
812             ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
813 
814             // d)
815             if (sDeepType.getLength())
816                 return sDeepType;
817         }
818         catch(const css::container::NoSuchElementException&)
819             {}
820         // e)
821     }
822 
823     return ::rtl::OUString();
824     // <- SAFE ----------------------------------
825 }
826 
827 /*-----------------------------------------------
828     03.11.2003 09:19
829 -----------------------------------------------*/
impl_detectTypeDeepOnly(::comphelper::MediaDescriptor & rDescriptor,const OUStringList & lOutsideUsedDetectors)830 ::rtl::OUString TypeDetection::impl_detectTypeDeepOnly(      ::comphelper::MediaDescriptor& rDescriptor          ,
831                                                        const OUStringList&                  lOutsideUsedDetectors)
832 {
833     // We must know if a detect service was already used:
834     //  i) in a combined flat/deep detection scenario outside or
835     // ii) in this method for a deep detection only.
836     // Reason: Such deep detection services work differently in these two modes!
837     OUStringList                 lInsideUsedDetectors;
838     OUStringList::const_iterator pIt;
839 
840     // a)
841     // The list of "already used detect services" correspond to the list
842     // of preselected or flat detected types. But these detect services was called
843     // to check these types explicitly and return black/white ... yes/no only.
844     // Now they are called to return any possible result. But we should prefer
845     // these already used detect services against all other ones!
846     for (  pIt  = lOutsideUsedDetectors.begin();
847            pIt != lOutsideUsedDetectors.end()  ;
848          ++pIt                                 )
849     {
850         const ::rtl::OUString& sDetectService = *pIt;
851               ::rtl::OUString  sDeepType      = impl_askDetectService(sDetectService, rDescriptor);
852         if (sDeepType.getLength())
853             return sDeepType;
854         lInsideUsedDetectors.push_back(sDetectService);
855     }
856 
857     // SAFE -> ----------------------------------
858     ::osl::ResettableMutexGuard aLock(m_aLock);
859     OUStringList lDetectors = m_rCache->getItemNames(FilterCache::E_DETECTSERVICE);
860     aLock.clear();
861     // <- SAFE ----------------------------------
862 
863     // b)
864     // Sometimes it would be nice to ask a special set of detect services before
865     // any other detect service is asked. E.g. by using a preselection of a DocumentService.
866     // That's needed to prevent us from asking the "wrong application module" and
867     // opening the files into the "wrong application".
868     ::rtl::OUString sPreselDocumentService = rDescriptor.getUnpackedValueOrDefault(
869                                                 ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(),
870                                                 ::rtl::OUString());
871     if (sPreselDocumentService.getLength())
872     {
873         for (  pIt  = lDetectors.begin();
874                pIt != lDetectors.end()  ;
875              ++pIt                      )
876         {
877             const ::rtl::OUString& sDetectService = *pIt;
878 
879             OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService);
880             if (pAlreadyUsed != lInsideUsedDetectors.end())
881                 continue;
882 
883             // SAFE -> --------------------------------------------------------
884             aLock.reset();
885 
886             CacheItem lIProps;
887             lIProps[PROPNAME_DETECTSERVICE] <<= sDetectService;
888             OUStringList lTypes = m_rCache->getMatchingItemsByProps(FilterCache::E_TYPE, lIProps);
889 
890             aLock.clear();
891             // <- SAFE --------------------------------------------------------
892 
893             sal_Bool bMatchDetectorToDocumentService = sal_False;
894             OUStringList::const_iterator pIt2;
895             for (  pIt2  = lTypes.begin();
896                    pIt2 != lTypes.end()  ;
897                  ++pIt2                  )
898             {
899                 const ::rtl::OUString& sType  = *pIt2;
900 
901                 try
902                 {
903                     // SAFE -> ----------------------------------------------------
904                     aLock.reset();
905 
906                     CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
907                     ::rtl::OUString sFilter;
908                     aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
909                     CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
910                     ::rtl::OUString sCheckDocumentService;
911                     aFilter[PROPNAME_DOCUMENTSERVICE] >>= sCheckDocumentService;
912 
913                     aLock.clear();
914                     // <- SAFE
915 
916                     if (sCheckDocumentService.equals(sPreselDocumentService))
917                     {
918                         bMatchDetectorToDocumentService = sal_True;
919                         break;
920                     }
921                 }
922                 catch(const css::uno::Exception&)
923                     { continue; }
924             }
925 
926             if (bMatchDetectorToDocumentService)
927             {
928                 ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
929                 if (sDeepType.getLength())
930                     return sDeepType;
931                 lInsideUsedDetectors.push_back(sDetectService);
932             }
933         }
934     }
935 
936     // c)
937     // Last chance. No "used detectors", no "preselected detectors" ... ask any existing detect services
938     // for this till know unknown format.
939     for (  pIt  = lDetectors.begin();
940            pIt != lDetectors.end()  ;
941          ++pIt                      )
942     {
943         const ::rtl::OUString& sDetectService = *pIt;
944 
945         OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService);
946         if (pAlreadyUsed != lInsideUsedDetectors.end())
947             continue;
948 
949         ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
950         if (sDeepType.getLength())
951             return sDeepType;
952     }
953 
954     return ::rtl::OUString();
955 }
956 
957 /*-----------------------------------------------
958     07.03.2005 11:13
959 -----------------------------------------------*/
impl_seekStreamToZero(comphelper::MediaDescriptor & rDescriptor)960 void TypeDetection::impl_seekStreamToZero(comphelper::MediaDescriptor& rDescriptor)
961 {
962     // try to seek to 0 ...
963     // But because XSeekable is an optional interface ... try it only .-)
964     css::uno::Reference< css::io::XInputStream > xStream = rDescriptor.getUnpackedValueOrDefault(
965                                                             ::comphelper::MediaDescriptor::PROP_INPUTSTREAM(),
966                                                             css::uno::Reference< css::io::XInputStream >());
967     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
968     if (xSeek.is())
969     {
970         try
971         {
972             xSeek->seek(0);
973         }
974         catch(const css::uno::RuntimeException& exRun)
975             { throw exRun; }
976         catch(const css::uno::Exception&)
977             {}
978     }
979 }
980 
981 /*-----------------------------------------------
982     30.10.2003 15:12
983 -----------------------------------------------*/
impl_askDetectService(const::rtl::OUString & sDetectService,::comphelper::MediaDescriptor & rDescriptor)984 ::rtl::OUString TypeDetection::impl_askDetectService(const ::rtl::OUString&               sDetectService,
985                                                            ::comphelper::MediaDescriptor& rDescriptor   )
986 {
987     // Open the stream and add it to the media descriptor if this method is called for the first time.
988     // All following requests to this method will detect, that there already exists a stream .-)
989     // Attention: This method throws an exception if the stream could not be opened.
990     // It's important to break any further detection in such case.
991     // Catch it on the highest detection level only !!!
992     impl_openStream(rDescriptor);
993 
994     // seek to 0 is an optional feature to be more robust against
995     // "simple implemented detect services" .-)
996     impl_seekStreamToZero(rDescriptor);
997 
998     css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
999     css::uno::Reference< css::lang::XMultiServiceFactory >         xSMGR;
1000 
1001     // SAFE ->
1002     ::osl::ResettableMutexGuard aLock(m_aLock);
1003     xSMGR = m_xSMGR;
1004     aLock.clear();
1005     // <- SAFE
1006 
1007     // Attention! If e.g. an office module was not installed sometimes we find a
1008     // registered detect service, which is referred inside the configuration ... but not really
1009     // installed. On the other side we use third party components here, which can make trouble anyway.
1010     // So we should handle errors during creation of such services more gracefully .-)
1011     xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >(
1012             xSMGR->createInstance(sDetectService),
1013             css::uno::UNO_QUERY);
1014 
1015     if ( ! xDetector.is())
1016         return ::rtl::OUString();
1017 
1018     ::rtl::OUString sDeepType;
1019     try
1020     {
1021         // start deep detection
1022         // Don't forget to convert stl descriptor to its uno representation.
1023 
1024         /* Attention!
1025                 You have to use an explicit instance of this uno sequence ...
1026                 Because it's used as an in out parameter. And in case of a temp. used object
1027                 we will run into memory corruptions!
1028         */
1029         css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1030         rDescriptor >> lDescriptor;
1031         sDeepType = xDetector->detect(lDescriptor);
1032         rDescriptor << lDescriptor;
1033     }
1034     catch(const css::uno::Exception&)
1035         {
1036             // We should ignore errors here.
1037             // Thrown exceptions mostly will end in crash recovery ...
1038             // But might be we find another deep detection service which can detect the same
1039             // document without a problem .-)
1040             sDeepType = ::rtl::OUString();
1041         }
1042 
1043     // seek to 0 is an optional feature to be more robust against
1044     // "simple implemented detect services" .-)
1045     impl_seekStreamToZero(rDescriptor);
1046 
1047     // analyze the results
1048     // a) detect service returns "" => return "" too and remove TYPE/FILTER prop from descriptor
1049     // b) returned type is unknown  => return "" too and remove TYPE/FILTER prop from descriptor
1050     // c) returned type is valid    => check TYPE/FILTER props inside descriptor and return the type
1051 
1052     // this special helper checks for a valid type
1053     // and set right values on the descriptor!
1054     sal_Bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType);
1055     if (bValidType)
1056         return sDeepType;
1057 
1058     return ::rtl::OUString();
1059 }
1060 
1061 /*-----------------------------------------------
1062     17.12.2004 13:47
1063 -----------------------------------------------*/
impl_askUserForTypeAndFilterIfAllowed(::comphelper::MediaDescriptor & rDescriptor)1064 ::rtl::OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(::comphelper::MediaDescriptor& rDescriptor)
1065 {
1066     // SAFE ->
1067     ::osl::ResettableMutexGuard aLock(m_aLock);
1068     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1069     aLock.clear();
1070     // <- SAFE
1071 
1072     css::uno::Reference< css::task::XInteractionHandler > xInteraction =
1073         rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(),
1074         css::uno::Reference< css::task::XInteractionHandler >());
1075 
1076     if (!xInteraction.is())
1077         return ::rtl::OUString();
1078 
1079     ::rtl::OUString sURL =
1080         rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(),
1081         ::rtl::OUString());
1082 
1083     css::uno::Reference< css::io::XInputStream > xStream =
1084         rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INPUTSTREAM(),
1085         css::uno::Reference< css::io::XInputStream >());
1086 
1087     // Don't disturb the user for "non existing files - means empty URLs" or
1088     // if we were forced to detect a stream.
1089     // Reason behind: We must be sure to ask user for "unknown contents" only ...
1090     // and not for "missing files". Especially if detection is done by a stream only
1091     // we can't check if the stream points to an "existing content"!
1092     if (
1093         (!sURL.getLength()                                     ) || // "non existing file" ?
1094         (!xStream.is()                                         ) || // non existing file !
1095         (sURL.equalsIgnoreAsciiCaseAsciiL("private:stream", 14))    // not a good idea .-)
1096        )
1097         return ::rtl::OUString();
1098 
1099     try
1100     {
1101         // create a new request to ask user for his decision about the usable filter
1102         ::framework::RequestFilterSelect aRequest(sURL);
1103         xInteraction->handle(aRequest.GetRequest());
1104 
1105         // "Cancel" pressed? => return with error
1106         if (aRequest.isAbort())
1107             return ::rtl::OUString();
1108 
1109         // "OK" pressed => verify the selected filter, get its corresponding
1110         // type and return it. (BTW: We must update the media descriptor here ...)
1111         // The user selected explicitly a filter ... but normally we are interested on
1112         // a type here only. But we must be sure, that the selected filter is used
1113         // too and no ambiguous filter registration disturb us .-)
1114 
1115         ::rtl::OUString sFilter = aRequest.getFilter();
1116         if (!impl_validateAndSetFilterOnDescriptor(rDescriptor, sFilter))
1117             return ::rtl::OUString();
1118 
1119         ::rtl::OUString sType;
1120         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] >>= sType;
1121         return sType;
1122     }
1123     catch(const css::uno::Exception&)
1124         {}
1125 
1126     return ::rtl::OUString();
1127 }
1128 
1129 /*-----------------------------------------------
1130     10.03.2004 10:30
1131 -----------------------------------------------*/
impl_openStream(::comphelper::MediaDescriptor & rDescriptor)1132 void TypeDetection::impl_openStream(::comphelper::MediaDescriptor& rDescriptor)
1133     throw (css::uno::Exception)
1134 {
1135     sal_Bool bSuccess = sal_False;
1136     ::rtl::OUString sURL = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString() );
1137     sal_Bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_READONLY(), sal_False );
1138     if ( sURL.getLength() && ::utl::LocalFileHelper::IsLocalFile( INetURLObject( sURL ).GetMainURL( INetURLObject::NO_DECODE ) ) )
1139     {
1140         // AOO uses own file locking mechanics in case of local file
1141         bSuccess = rDescriptor.addInputStreamOwnLock();
1142     }
1143     else
1144         bSuccess = rDescriptor.addInputStream();
1145 
1146     if ( !bSuccess )
1147         throw css::uno::Exception(_FILTER_CONFIG_FROM_ASCII_("Could not open stream."), static_cast< css::document::XTypeDetection* >(this));
1148 
1149     if ( !bRequestedReadOnly )
1150     {
1151         // The MediaDescriptor implementation adds ReadOnly argument if the file can not be opened for writing
1152         // this argument should be either removed or an additional argument should be added so that application
1153         // can separate the case when the user explicitly requests readonly document.
1154         // The current solution is to remove it here.
1155         rDescriptor.erase( ::comphelper::MediaDescriptor::PROP_READONLY() );
1156     }
1157 }
1158 
1159 /*-----------------------------------------------
1160     04.07.2003 13:47
1161 -----------------------------------------------*/
impl_removeTypeFilterFromDescriptor(::comphelper::MediaDescriptor & rDescriptor)1162 void TypeDetection::impl_removeTypeFilterFromDescriptor(::comphelper::MediaDescriptor& rDescriptor)
1163 {
1164     ::comphelper::MediaDescriptor::iterator pItType   = rDescriptor.find(::comphelper::MediaDescriptor::PROP_TYPENAME()  );
1165     ::comphelper::MediaDescriptor::iterator pItFilter = rDescriptor.find(::comphelper::MediaDescriptor::PROP_FILTERNAME());
1166     if (pItType != rDescriptor.end())
1167         rDescriptor.erase(pItType);
1168     if (pItFilter != rDescriptor.end())
1169         rDescriptor.erase(pItFilter);
1170 }
1171 
1172 /*-----------------------------------------------
1173     14.10.2003 11:15
1174 -----------------------------------------------*/
impl_validateAndSetTypeOnDescriptor(::comphelper::MediaDescriptor & rDescriptor,const::rtl::OUString & sType)1175 sal_Bool TypeDetection::impl_validateAndSetTypeOnDescriptor(      ::comphelper::MediaDescriptor& rDescriptor,
1176                                                             const ::rtl::OUString&               sType      )
1177 {
1178     // SAFE ->
1179     ::osl::ResettableMutexGuard aLock(m_aLock);
1180     if (m_rCache->hasItem(FilterCache::E_TYPE, sType))
1181     {
1182         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType;
1183         return sal_True;
1184     }
1185     aLock.clear();
1186     // <- SAFE
1187 
1188     // remove all related informations from the descriptor
1189     impl_removeTypeFilterFromDescriptor(rDescriptor);
1190     return sal_False;
1191 }
1192 
1193 /*-----------------------------------------------
1194     04.07.2003 14:01
1195 -----------------------------------------------*/
impl_validateAndSetFilterOnDescriptor(::comphelper::MediaDescriptor & rDescriptor,const::rtl::OUString & sFilter)1196 sal_Bool TypeDetection::impl_validateAndSetFilterOnDescriptor(      ::comphelper::MediaDescriptor& rDescriptor,
1197                                                               const ::rtl::OUString&               sFilter    )
1198 {
1199     try
1200     {
1201         // SAFE ->
1202         ::osl::ResettableMutexGuard aLock(m_aLock);
1203 
1204         CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
1205         ::rtl::OUString sType;
1206         aFilter[PROPNAME_TYPE] >>= sType;
1207         CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
1208 
1209         aLock.clear();
1210         // <- SAFE
1211 
1212         // found valid type and filter => set it on the given descriptor
1213         rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= sType  ;
1214         rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
1215         return sal_True;
1216     }
1217     catch(const css::container::NoSuchElementException&){}
1218 
1219     // remove all related informations from the descriptor
1220     impl_removeTypeFilterFromDescriptor(rDescriptor);
1221     return sal_False;
1222 }
1223 
1224 /*-----------------------------------------------
1225     03.07.2003 10:36
1226 -----------------------------------------------*/
impl_getImplementationName()1227 ::rtl::OUString TypeDetection::impl_getImplementationName()
1228 {
1229     return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.TypeDetection");
1230 }
1231 
1232 /*-----------------------------------------------
1233     03.07.2003 11:27
1234 -----------------------------------------------*/
impl_getSupportedServiceNames()1235 css::uno::Sequence< ::rtl::OUString > TypeDetection::impl_getSupportedServiceNames()
1236 {
1237     css::uno::Sequence< ::rtl::OUString > lServiceNames(1);
1238     lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection");
1239     return lServiceNames;
1240 }
1241 
1242 /*-----------------------------------------------
1243     09.07.2003 08:02
1244 -----------------------------------------------*/
impl_createInstance(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)1245 css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
1246 {
1247     TypeDetection* pNew = new TypeDetection(xSMGR);
1248     return css::uno::Reference< css::uno::XInterface >(static_cast< css::document::XTypeDetection* >(pNew), css::uno::UNO_QUERY);
1249 }
1250 
1251     } // namespace config
1252 } // namespace filter
1253