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