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