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