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 : #include <comphelper/sequence.hxx>
37 :
38 : #define DEBUG_TYPE_DETECTION 0
39 :
40 : #if DEBUG_TYPE_DETECTION
41 : #include <iostream>
42 : using std::cout;
43 : using std::endl;
44 : #endif
45 :
46 : using namespace com::sun::star;
47 :
48 : namespace filter{
49 : namespace config{
50 :
51 44102 : TypeDetection::TypeDetection(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
52 44102 : : m_xContext(rxContext)
53 : {
54 : BaseContainer::init(rxContext ,
55 : TypeDetection::impl_getImplementationName() ,
56 : TypeDetection::impl_getSupportedServiceNames(),
57 44102 : FilterCache::E_TYPE );
58 44102 : }
59 :
60 :
61 :
62 88204 : TypeDetection::~TypeDetection()
63 : {
64 88204 : }
65 :
66 :
67 :
68 23158 : OUString SAL_CALL TypeDetection::queryTypeByURL(const OUString& sURL)
69 : throw (css::uno::RuntimeException, std::exception)
70 : {
71 23158 : OUString sType;
72 :
73 : // SAFE ->
74 46316 : ::osl::ResettableMutexGuard aLock(m_aLock);
75 :
76 46316 : css::util::URL aURL;
77 23158 : aURL.Complete = sURL;
78 46316 : css::uno::Reference< css::util::XURLTransformer > xParser( css::util::URLTransformer::create(m_xContext) );
79 23158 : xParser->parseStrict(aURL);
80 :
81 : // set std types as minimum requirement first!
82 : // Only in case no type was found for given URL,
83 : // use optional types too ...
84 46316 : FlatDetection lFlatTypes;
85 23158 : m_rCache->detectFlatForURL(aURL, lFlatTypes);
86 :
87 23158 : if (
88 44468 : (lFlatTypes.size() < 1 ) &&
89 21310 : (!m_rCache->isFillState(FilterCache::E_CONTAINS_TYPES))
90 : )
91 : {
92 4 : m_rCache->load(FilterCache::E_CONTAINS_TYPES);
93 4 : m_rCache->detectFlatForURL(aURL, lFlatTypes);
94 : }
95 :
96 : // first item is guaranteed as "preferred" one!
97 23158 : if (lFlatTypes.size() > 0)
98 : {
99 1848 : const FlatDetectionInfo& aMatch = *(lFlatTypes.begin());
100 1848 : sType = aMatch.sType;
101 : }
102 :
103 46316 : return sType;
104 : // <- SAFE
105 : }
106 :
107 : namespace {
108 :
109 : /**
110 : * Rank format types in order of complexity. More complex formats are
111 : * ranked higher so that they get tested sooner over simpler formats.
112 : *
113 : * Guidelines to determine how complex a format is (subject to change):
114 : *
115 : * 1) compressed text (XML, HTML, etc)
116 : * 2) binary
117 : * 3) non-compressed text
118 : * 3.1) structured text
119 : * 3.1.1) dialect of a structured text (e.g. docbook XML)
120 : * 3.1.2) generic structured text (e.g. generic XML)
121 : * 3.2) non-structured text
122 : *
123 : * In each category, rank them from strictly-structured to
124 : * loosely-structured.
125 : */
126 7173598 : int getFlatTypeRank(const OUString& rType)
127 : {
128 : // List formats from more complex to less complex.
129 : // TODO: Add more.
130 : static const char* ranks[] = {
131 :
132 : // Compressed XML (ODF XML zip formats)
133 : "writer8_template",
134 : "writer8",
135 : "calc8_template",
136 : "calc8",
137 : "impress8_template",
138 : "impress8",
139 : "draw8_template",
140 : "draw8",
141 : "chart8",
142 : "math8",
143 : "writerglobal8_template",
144 : "writerglobal8",
145 : "writerweb8_writer_template",
146 : "StarBase",
147 :
148 : // Compressed XML (OOXML)
149 : "writer_OOXML_Text_Template",
150 : "writer_OOXML",
151 : "writer_MS_Word_2007_Template",
152 : "writer_MS_Word_2007",
153 : "Office Open XML Spreadsheet Template",
154 : "Office Open XML Spreadsheet",
155 : "MS Excel 2007 XML Template",
156 : "MS Excel 2007 XML",
157 : "MS PowerPoint 2007 XML Template",
158 : "MS PowerPoint 2007 XML AutoPlay",
159 : "MS PowerPoint 2007 XML",
160 :
161 : // Compressed XML (Uniform/Unified Office Format)
162 : "Unified_Office_Format_text",
163 : "Unified_Office_Format_spreadsheet",
164 : "Unified_Office_Format_presentation",
165 :
166 : // Compressed XML (StarOffice XML zip formats)
167 : "calc_StarOffice_XML_Calc",
168 : "calc_StarOffice_XML_Calc_Template",
169 : "chart_StarOffice_XML_Chart",
170 : "draw_StarOffice_XML_Draw",
171 : "draw_StarOffice_XML_Draw_Template",
172 : "impress_StarOffice_XML_Impress",
173 : "impress_StarOffice_XML_Impress_Template",
174 : "math_StarOffice_XML_Math",
175 : "writer_StarOffice_XML_Writer",
176 : "writer_StarOffice_XML_Writer_Template",
177 : "writer_globaldocument_StarOffice_XML_Writer_GlobalDocument",
178 : "writer_web_StarOffice_XML_Writer_Web_Template",
179 :
180 : // Compressed text
181 : "pdf_Portable_Document_Format",
182 :
183 : // Binary
184 : "writer_T602_Document",
185 : "writer_WordPerfect_Document",
186 : "writer_MS_Works_Document",
187 : "writer_MS_Word_97_Vorlage",
188 : "writer_MS_Word_97",
189 : "writer_MS_Word_95_Vorlage",
190 : "writer_MS_Word_95",
191 : "writer_MS_WinWord_60",
192 : "writer_MS_WinWord_5",
193 : "MS Excel 2007 Binary",
194 : "calc_MS_Excel_97_VorlageTemplate",
195 : "calc_MS_Excel_97",
196 : "calc_MS_Excel_95_VorlageTemplate",
197 : "calc_MS_Excel_95",
198 : "calc_MS_Excel_5095_VorlageTemplate",
199 : "calc_MS_Excel_5095",
200 : "calc_MS_Excel_40_VorlageTemplate",
201 : "calc_MS_Excel_40",
202 : "calc_Pocket_Excel_File",
203 : "impress_MS_PowerPoint_97_Vorlage",
204 : "impress_MS_PowerPoint_97_AutoPlay",
205 : "impress_MS_PowerPoint_97",
206 : "calc_Lotus",
207 : "calc_QPro",
208 : "calc_SYLK",
209 : "calc_DIF",
210 : "calc_dBase",
211 :
212 : // Binary (raster and vector image files)
213 : "emf_MS_Windows_Metafile",
214 : "wmf_MS_Windows_Metafile",
215 : "met_OS2_Metafile",
216 : "svm_StarView_Metafile",
217 : "sgv_StarDraw_20",
218 : "tif_Tag_Image_File",
219 : "tga_Truevision_TARGA",
220 : "sgf_StarOffice_Writer_SGF",
221 : "ras_Sun_Rasterfile",
222 : "psd_Adobe_Photoshop",
223 : "png_Portable_Network_Graphic",
224 : "jpg_JPEG",
225 : "mov_MOV",
226 : "gif_Graphics_Interchange",
227 : "bmp_MS_Windows",
228 : "pcx_Zsoft_Paintbrush",
229 : "pct_Mac_Pict",
230 : "pcd_Photo_CD_Base",
231 : "pcd_Photo_CD_Base4",
232 : "pcd_Photo_CD_Base16",
233 : "impress_CGM_Computer_Graphics_Metafile", // There is binary and ascii variants ?
234 : "draw_WordPerfect_Graphics",
235 : "draw_Visio_Document",
236 : "draw_Publisher_Document",
237 : "draw_Corel_Presentation_Exchange",
238 : "draw_CorelDraw_Document",
239 : "writer_LotusWordPro_Document",
240 : "writer_MIZI_Hwp_97", // Hanword (Hancom Office)
241 :
242 : // Non-compressed XML
243 : "writer_ODT_FlatXML",
244 : "calc_ODS_FlatXML",
245 : "impress_ODP_FlatXML",
246 : "draw_ODG_FlatXML",
247 : "calc_MS_Excel_2003_XML",
248 : "writer_MS_Word_2003_XML",
249 : "writer_DocBook_File",
250 : "XHTML_File",
251 : "svg_Scalable_Vector_Graphics",
252 : "math_MathML_XML_Math",
253 :
254 : // Non-compressed text
255 : "dxf_AutoCAD_Interchange",
256 : "eps_Encapsulated_PostScript",
257 : "pbm_Portable_Bitmap", // There is 'raw' and 'ascii' variants.
258 : "ppm_Portable_Pixelmap", // There is 'raw' and 'ascii' variants.
259 : "pgm_Portable_Graymap", // There is 'raw' and 'ascii' variants.
260 : "xpm_XPM",
261 : "xbm_X_Consortium",
262 : "writer_Rich_Text_Format",
263 : "writer_web_HTML_help",
264 : "generic_HTML",
265 :
266 : "generic_Text", // Plain text (catch all)
267 :
268 : // Anything ranked lower than generic_Text will never be used during
269 : // type detection (since generic_Text catches all).
270 :
271 : // Export only
272 : "writer_layout_dump_xml",
273 : "pwp_PlaceWare",
274 : "graphic_SWF",
275 : "graphic_HTML",
276 :
277 : // Internal use only
278 : "StarBaseReportChart",
279 : "StarBaseReport",
280 : "math_MathType_3x", // MathType equation embedded in Word doc.
281 : };
282 :
283 7173598 : size_t n = SAL_N_ELEMENTS(ranks);
284 :
285 555542401 : for (size_t i = 0; i < n; ++i)
286 : {
287 553453163 : if (rType.equalsAscii(ranks[i]))
288 5084360 : return n - i - 1;
289 : }
290 :
291 : // Not ranked. Treat them equally. Unranked formats have higher priority
292 : // than the ranked internal ones since they may be defined externally.
293 2089238 : return n;
294 : }
295 :
296 : /**
297 : * Types with matching pattern first, then extension, then custom ranks by
298 : * types, then types that are supported by the document service come next.
299 : * Lastly, sort them alphabetically.
300 : */
301 : struct SortByPriority : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
302 : {
303 3619462 : bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
304 : {
305 3619462 : if (r1.bMatchByPattern != r2.bMatchByPattern)
306 5466 : return r1.bMatchByPattern;
307 :
308 3613996 : if (r1.bMatchByExtension != r2.bMatchByExtension)
309 27197 : return r1.bMatchByExtension;
310 :
311 3586799 : int rank1 = getFlatTypeRank(r1.sType);
312 3586799 : int rank2 = getFlatTypeRank(r2.sType);
313 :
314 3586799 : if (rank1 != rank2)
315 2892172 : return rank1 > rank2;
316 :
317 694627 : if (r1.bPreselectedByDocumentService != r2.bPreselectedByDocumentService)
318 157927 : return r1.bPreselectedByDocumentService;
319 :
320 : // All things being equal, sort them alphabetically.
321 536700 : return r1.sType > r2.sType;
322 : }
323 : };
324 :
325 : struct SortByType : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
326 :
327 : {
328 5488062 : bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
329 : {
330 5488062 : return r1.sType > r2.sType;
331 : }
332 : };
333 :
334 : struct EqualByType : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
335 : {
336 1405352 : bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
337 : {
338 1405352 : return r1.sType == r2.sType;
339 : }
340 : };
341 :
342 495867 : class FindByType : std::unary_function<FlatDetectionInfo, bool>
343 : {
344 : OUString maType;
345 : public:
346 165289 : FindByType(const OUString& rType) : maType(rType) {}
347 8891562 : bool operator() (const FlatDetectionInfo& rInfo) const
348 : {
349 8891562 : return rInfo.sType == maType;
350 : }
351 : };
352 :
353 : #if DEBUG_TYPE_DETECTION
354 : void printFlatDetectionList(const char* caption, const FlatDetection& types)
355 : {
356 : cout << "-- " << caption << " (size=" << types.size() << ")" << endl;
357 : FlatDetection::const_iterator it = types.begin(), itEnd = types.end();
358 : for (; it != itEnd; ++it)
359 : {
360 : const FlatDetectionInfo& item = *it;
361 : cout << " type='" << item.sType << "'; match by extension (" << item.bMatchByExtension
362 : << "); match by pattern (" << item.bMatchByPattern << "); pre-selected by doc service ("
363 : << item.bPreselectedByDocumentService << ")" << endl;
364 : }
365 : cout << "--" << endl;
366 : }
367 : #endif
368 :
369 : }
370 :
371 3253 : OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
372 : sal_Bool bAllowDeep )
373 : throw (css::uno::RuntimeException, std::exception)
374 : {
375 : // make the descriptor more useable :-)
376 3253 : utl::MediaDescriptor stlDescriptor(lDescriptor);
377 6506 : OUString sType, sURL;
378 :
379 : try
380 : {
381 : // SAFE -> ----------------------------------
382 3253 : ::osl::ResettableMutexGuard aLock(m_aLock);
383 :
384 : // parse given URL to split it into e.g. main and jump marks ...
385 3253 : sURL = stlDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL(), OUString());
386 :
387 : #if OSL_DEBUG_LEVEL > 0
388 : if (stlDescriptor.find( "FileName" ) != stlDescriptor.end())
389 : OSL_FAIL("Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
390 : #endif
391 :
392 6506 : css::util::URL aURL;
393 3253 : aURL.Complete = sURL;
394 6506 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
395 3253 : xParser->parseStrict(aURL);
396 :
397 : OUString aSelectedFilter = stlDescriptor.getUnpackedValueOrDefault(
398 6506 : utl::MediaDescriptor::PROP_FILTERNAME(), OUString());
399 3253 : if (!aSelectedFilter.isEmpty())
400 : {
401 : // Caller specified the filter type. Honor it. Just get the default
402 : // type for that filter, and bail out.
403 0 : if (impl_validateAndSetFilterOnDescriptor(stlDescriptor, aSelectedFilter))
404 0 : return stlDescriptor[utl::MediaDescriptor::PROP_TYPENAME()].get<OUString>();
405 : }
406 :
407 6506 : FlatDetection lFlatTypes;
408 3253 : impl_getAllFormatTypes(aURL, stlDescriptor, lFlatTypes);
409 :
410 3253 : aLock.clear();
411 : // <- SAFE ----------------------------------
412 :
413 : // Properly prioritize all candidate types.
414 3253 : lFlatTypes.sort(SortByPriority());
415 3253 : lFlatTypes.unique(EqualByType());
416 :
417 6506 : OUString sLastChance;
418 :
419 : // verify every flat detected (or preselected!) type
420 : // by calling its registered deep detection service.
421 : // But break this loop if a type match to the given descriptor
422 : // by an URL pattern(!) or if deep detection isn't allowed from
423 : // outside (bAllowDeep=sal_False) or break the whole detection by
424 : // throwing an exception if creation of the might needed input
425 : // stream failed by e.g. an IO exception ...
426 6506 : OUStringList lUsedDetectors;
427 3253 : if (lFlatTypes.size()>0)
428 3253 : sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, lUsedDetectors, sLastChance);
429 :
430 :
431 : // flat detection failed
432 : // pure deep detection failed
433 : // => ask might existing InteractionHandler
434 : // means: ask user for it's decision
435 3252 : if (sType.isEmpty())
436 15 : sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor);
437 :
438 :
439 : // no real detected type - but a might valid one.
440 : // update descriptor and set last chance for return.
441 3252 : if (sType.isEmpty() && !sLastChance.isEmpty())
442 : {
443 : OSL_FAIL("set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!");
444 15 : sType = sLastChance;
445 3253 : }
446 : }
447 0 : catch(const css::uno::RuntimeException&)
448 : {
449 0 : throw;
450 : }
451 2 : catch(const css::uno::Exception& e)
452 : {
453 : SAL_WARN(
454 : "filter.config",
455 : "caught Exception \"" << e.Message
456 : << "\" while querying type of <" << sURL << ">");
457 1 : sType.clear();
458 : }
459 :
460 : // adapt media descriptor, so it contains the right values
461 : // for type/filter name/document service/ etcpp.
462 3253 : impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!!
463 3253 : impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType);
464 :
465 3253 : stlDescriptor >> lDescriptor;
466 6506 : return sType;
467 : }
468 :
469 :
470 :
471 3253 : void TypeDetection::impl_checkResultsAndAddBestFilter(utl::MediaDescriptor& rDescriptor,
472 : OUString& sType )
473 : {
474 : // a)
475 : // Dont overwrite a might preselected filter!
476 : OUString sFilter = rDescriptor.getUnpackedValueOrDefault(
477 3253 : utl::MediaDescriptor::PROP_FILTERNAME(),
478 6506 : OUString());
479 3253 : if (!sFilter.isEmpty())
480 43 : return;
481 :
482 : // b)
483 : // check a preselected document service too.
484 : // Then we have to search a suitable filter witin this module.
485 : OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault(
486 3210 : utl::MediaDescriptor::PROP_DOCUMENTSERVICE(),
487 6437 : OUString());
488 3210 : if (!sDocumentService.isEmpty())
489 : {
490 : try
491 : {
492 2388 : OUString sRealType = sType;
493 :
494 : // SAFE ->
495 2393 : ::osl::ResettableMutexGuard aLock(m_aLock);
496 :
497 : // Attention: For executing next lines of code, We must be sure that
498 : // all filters already loaded :-(
499 : // That can disturb our "load on demand feature". But we have no other chance!
500 2388 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
501 :
502 2393 : CacheItem lIProps;
503 2388 : lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService;
504 2388 : lIProps[PROPNAME_TYPE ] <<= sRealType;
505 2393 : OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
506 :
507 2388 : aLock.clear();
508 : // <- SAFE
509 :
510 11922 : for (OUStringList::const_iterator pIt = lFilters.begin();
511 7948 : pIt != lFilters.end(); ++pIt)
512 : {
513 : // SAFE ->
514 2384 : aLock.reset();
515 : try
516 : {
517 2384 : CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt);
518 2384 : sal_Int32 nFlags = 0;
519 2384 : aFilter[PROPNAME_FLAGS] >>= nFlags;
520 :
521 2384 : if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
522 2383 : sFilter = *pIt;
523 2384 : if ((nFlags & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED)
524 798 : break;
525 : }
526 0 : catch(const css::uno::Exception&) {}
527 1586 : aLock.clear();
528 : // <- SAFE
529 : }
530 :
531 2388 : if (!sFilter.isEmpty())
532 : {
533 2383 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME() ] <<= sRealType;
534 2383 : rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
535 2383 : sType = sRealType;
536 2383 : return;
537 5 : }
538 : }
539 0 : catch(const css::uno::Exception&)
540 : {}
541 : }
542 :
543 : // c)
544 : // We can use the preferred filter for the specified type.
545 : // Such preferred filter points:
546 : // - to the default filter of the preferred application
547 : // - or to any other filter if no preferred filter was set.
548 : // Note: It's an optimization only!
549 : // It's not guaranteed, that such preferred filter exists.
550 827 : sFilter.clear();
551 : try
552 : {
553 : // SAFE ->
554 827 : ::osl::ResettableMutexGuard aLock(m_aLock);
555 :
556 1653 : CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
557 826 : aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
558 1636 : CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
559 :
560 810 : aLock.clear();
561 : // <- SAFE
562 :
563 : // no exception => found valid type and filter => set it on the given descriptor
564 810 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME() ] <<= sType ;
565 810 : rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
566 1637 : return;
567 : }
568 17 : catch(const css::uno::Exception&)
569 : {}
570 :
571 : // d)
572 : // Search for any import(!) filter, which is registered for this type.
573 17 : sFilter.clear();
574 : try
575 : {
576 : // SAFE ->
577 17 : ::osl::ResettableMutexGuard aLock(m_aLock);
578 :
579 : // Attention: For executing next lines of code, We must be sure that
580 : // all filters already loaded :-(
581 : // That can disturb our "load on demand feature". But we have no other chance!
582 17 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
583 :
584 34 : CacheItem lIProps;
585 17 : lIProps[PROPNAME_TYPE] <<= sType;
586 34 : OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
587 :
588 17 : aLock.clear();
589 : // <- SAFE
590 :
591 17 : OUStringList::const_iterator pIt;
592 96 : for ( pIt = lFilters.begin();
593 64 : pIt != lFilters.end() ;
594 : ++pIt )
595 : {
596 15 : sFilter = *pIt;
597 :
598 : // SAFE ->
599 15 : aLock.reset();
600 : try
601 : {
602 15 : CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
603 15 : sal_Int32 nFlags = 0;
604 15 : aFilter[PROPNAME_FLAGS] >>= nFlags;
605 :
606 15 : if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
607 0 : break;
608 : }
609 0 : catch(const css::uno::Exception&)
610 0 : { continue; }
611 15 : aLock.clear();
612 : // <- SAFE
613 :
614 15 : sFilter.clear();
615 : }
616 :
617 17 : if (!sFilter.isEmpty())
618 : {
619 0 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME() ] <<= sType ;
620 0 : rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
621 0 : return;
622 17 : }
623 : }
624 0 : catch(const css::uno::Exception&)
625 17 : {}
626 : }
627 :
628 :
629 :
630 160809 : bool TypeDetection::impl_getPreselectionForType(
631 : const OUString& sPreSelType, const util::URL& aParsedURL, FlatDetection& rFlatTypes, bool bDocService)
632 : {
633 : // Can be used to suppress execution of some parts of this method
634 : // if its already clear that detected type is valid or not.
635 : // Its necessary to use shared code at the end, which update
636 : // all return parameters constistency!
637 160809 : bool bBreakDetection = false;
638 :
639 : // Further we must know if it matches by pattern
640 : // Every flat detected type by pattern wont be detected deep!
641 160809 : bool bMatchByPattern = false;
642 :
643 : // And we must know if a preselection must be preferred, because
644 : // it matches by it's extension too.
645 160809 : bool bMatchByExtension = false;
646 :
647 : // validate type
648 160809 : OUString sType(sPreSelType);
649 321618 : CacheItem aType;
650 : try
651 : {
652 : // SAFE -> --------------------------
653 160809 : ::osl::ResettableMutexGuard aLock(m_aLock);
654 160809 : aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
655 160809 : aLock.clear();
656 : // <- SAFE --------------------------
657 : }
658 0 : catch(const css::container::NoSuchElementException&)
659 : {
660 0 : sType.clear();
661 0 : bBreakDetection = true;
662 : }
663 :
664 160809 : if (!bBreakDetection)
665 : {
666 : // We can't check a preselected type for a given stream!
667 : // So we must believe, that it can work ...
668 160809 : if ( aParsedURL.Complete == "private:stream" )
669 0 : bBreakDetection = true;
670 : }
671 :
672 160809 : if (!bBreakDetection)
673 : {
674 : // extract extension from URL .. to check it case-insensitive !
675 160809 : INetURLObject aParser (aParsedURL.Main);
676 : OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT ,
677 : true ,
678 321618 : INetURLObject::DECODE_WITH_CHARSET);
679 160809 : sExtension = sExtension.toAsciiLowerCase();
680 :
681 : // otherwise we must know, if it matches to the given URL really.
682 : // especially if it matches by its extension or pattern registration.
683 321618 : OUStringList lExtensions(comphelper::sequenceToContainer<OUStringList>(aType[PROPNAME_EXTENSIONS].get<css::uno::Sequence<OUString> >() ));
684 321618 : OUStringList lURLPattern(comphelper::sequenceToContainer<OUStringList>(aType[PROPNAME_URLPATTERN].get<css::uno::Sequence<OUString> >() ));
685 :
686 1192008 : for (OUStringList::const_iterator pIt = lExtensions.begin();
687 794672 : pIt != lExtensions.end() ;
688 : ++pIt )
689 : {
690 240056 : OUString sCheckExtension(pIt->toAsciiLowerCase());
691 240056 : if (sCheckExtension.equals(sExtension))
692 : {
693 3529 : bBreakDetection = true;
694 3529 : bMatchByExtension = true;
695 3529 : break;
696 : }
697 236527 : }
698 :
699 160809 : if (!bBreakDetection)
700 : {
701 485967 : for (OUStringList::const_iterator pIt = lURLPattern.begin();
702 323978 : pIt != lURLPattern.end() ;
703 : ++pIt )
704 : {
705 4710 : WildCard aCheck(*pIt);
706 4710 : if (aCheck.Matches(aParsedURL.Main))
707 : {
708 1 : bMatchByPattern = true;
709 1 : break;
710 : }
711 4709 : }
712 160809 : }
713 : }
714 :
715 : // if it's a valid type - set it on all return values!
716 160809 : if (!sType.isEmpty())
717 : {
718 160809 : FlatDetection::iterator it = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(sType));
719 160809 : if (it != rFlatTypes.end())
720 : {
721 160809 : if (bMatchByExtension)
722 3529 : it->bMatchByExtension = true;
723 160809 : if (bMatchByPattern)
724 1 : it->bMatchByPattern = true;
725 160809 : if (bDocService)
726 160809 : it->bPreselectedByDocumentService = true;
727 : }
728 :
729 160809 : return true;
730 : }
731 :
732 : // not valid!
733 160809 : return false;
734 : }
735 :
736 2425 : 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 2425 : OUStringList lFilters;
741 : try
742 : {
743 : // SAFE -> --------------------------
744 2425 : ::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 2425 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
750 :
751 4850 : CacheItem lIProps;
752 2425 : lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService;
753 2425 : lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
754 :
755 4850 : 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 489702 : for (OUStringList::const_iterator pFilter = lFilters.begin();
769 326468 : pFilter != lFilters.end();
770 : ++pFilter)
771 : {
772 160809 : OUString aType = impl_getTypeFromFilter(*pFilter);
773 160809 : if (aType.isEmpty())
774 0 : continue;
775 :
776 160809 : impl_getPreselectionForType(aType, aParsedURL, rFlatTypes, true);
777 160809 : }
778 :
779 2425 : return true;
780 : }
781 :
782 980565 : OUString TypeDetection::impl_getTypeFromFilter(const OUString& rFilterName)
783 : {
784 980565 : CacheItem aFilter;
785 : try
786 : {
787 980565 : osl::MutexGuard aLock(m_aLock);
788 980565 : aFilter = m_rCache->getItem(FilterCache::E_FILTER, rFilterName);
789 : }
790 0 : catch (const container::NoSuchElementException&)
791 : {
792 0 : return OUString();
793 : }
794 :
795 1961130 : OUString aType;
796 980565 : aFilter[PROPNAME_TYPE] >>= aType;
797 1961130 : return aType;
798 : }
799 :
800 3253 : void TypeDetection::impl_getAllFormatTypes(
801 : const util::URL& aParsedURL, utl::MediaDescriptor& rDescriptor, FlatDetection& rFlatTypes)
802 : {
803 3253 : rFlatTypes.clear();
804 :
805 : // Get all filters that we have.
806 3253 : OUStringList aFilterNames;
807 : try
808 : {
809 3253 : osl::MutexGuard aLock(m_aLock);
810 3253 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
811 3253 : aFilterNames = m_rCache->getItemNames(FilterCache::E_FILTER);
812 : }
813 0 : catch (const container::NoSuchElementException&)
814 : {
815 3253 : return;
816 : }
817 :
818 : // Retrieve the default type for each of these filters, and store them.
819 823009 : for (OUStringList::const_iterator it = aFilterNames.begin(); it != aFilterNames.end(); ++it)
820 : {
821 819756 : OUString aType = impl_getTypeFromFilter(*it);
822 :
823 819756 : if (aType.isEmpty())
824 0 : continue;
825 :
826 1639512 : FlatDetectionInfo aInfo; // all flags set to false by default.
827 819756 : aInfo.sType = aType;
828 819756 : rFlatTypes.push_back(aInfo);
829 819756 : }
830 :
831 : {
832 : // Get all types that match the URL alone.
833 3253 : FlatDetection aFlatByURL;
834 3253 : m_rCache->detectFlatForURL(aParsedURL, aFlatByURL);
835 3253 : FlatDetection::const_iterator it = aFlatByURL.begin(), itEnd = aFlatByURL.end();
836 7733 : for (; it != itEnd; ++it)
837 : {
838 4480 : FlatDetection::iterator itPos = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(it->sType));
839 4480 : if (itPos == rFlatTypes.end())
840 : // Not in the list yet.
841 28 : rFlatTypes.push_back(*it);
842 : else
843 : {
844 : // Already in the list. Update the flags.
845 4452 : FlatDetectionInfo& rInfo = *itPos;
846 4452 : const FlatDetectionInfo& rThisInfo = *it;
847 4452 : if (rThisInfo.bMatchByExtension)
848 3734 : rInfo.bMatchByExtension = true;
849 4452 : if (rThisInfo.bMatchByPattern)
850 718 : rInfo.bMatchByPattern = true;
851 4452 : if (rThisInfo.bPreselectedByDocumentService)
852 0 : rInfo.bPreselectedByDocumentService = true;
853 : }
854 3253 : }
855 : }
856 :
857 : // Remove duplicates.
858 3253 : rFlatTypes.sort(SortByType());
859 3253 : rFlatTypes.unique(EqualByType());
860 :
861 : // Mark pre-selected type (if any) to have it prioritized.
862 6506 : OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME(), OUString());
863 3253 : 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 6506 : OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString());
868 3253 : if (!sSelectedDoc.isEmpty())
869 5678 : impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes);
870 : }
871 :
872 :
873 :
874 3253 : 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 3253 : rLastChance.clear();
883 3253 : 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 171924 : for (FlatDetection::const_iterator pFlatIt = lFlatTypes.begin();
901 114616 : pFlatIt != lFlatTypes.end() ;
902 : ++pFlatIt )
903 : {
904 57293 : const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt;
905 57293 : OUString sFlatType = aFlatTypeInfo.sType;
906 :
907 57293 : if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType))
908 0 : continue;
909 :
910 : // b)
911 57293 : if (
912 114586 : (!bAllowDeep ) ||
913 : (aFlatTypeInfo.bMatchByPattern)
914 : )
915 : {
916 719 : return sFlatType;
917 : }
918 :
919 : try
920 : {
921 : // SAFE -> ----------------------------------
922 56574 : ::osl::ResettableMutexGuard aLock(m_aLock);
923 110570 : CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType);
924 56574 : aLock.clear();
925 :
926 110570 : OUString sDetectService;
927 56574 : aType[PROPNAME_DETECTSERVICE] >>= sDetectService;
928 :
929 : // c)
930 56574 : 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 60 : if (rLastChance.isEmpty())
937 15 : rLastChance = sFlatType;
938 :
939 60 : 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 56514 : rUsedDetectors.push_back(sDetectService);
946 110509 : OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
947 :
948 : // d)
949 56513 : if (!sDeepType.isEmpty())
950 56514 : return sDeepType;
951 : }
952 0 : catch(const css::container::NoSuchElementException&)
953 : {}
954 : // e)
955 53996 : }
956 :
957 15 : return OUString();
958 : // <- SAFE ----------------------------------
959 : }
960 :
961 75764 : 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 75764 : utl::MediaDescriptor::PROP_INPUTSTREAM(),
967 151528 : css::uno::Reference< css::io::XInputStream >());
968 151528 : css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
969 75764 : if (xSeek.is())
970 : {
971 : try
972 : {
973 75757 : 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 75764 : }
983 75764 : }
984 :
985 56514 : 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 56514 : impl_openStream(rDescriptor);
994 :
995 : // seek to 0 is an optional feature to be more robust against
996 : // "simple implemented detect services" .-)
997 56513 : impl_seekStreamToZero(rDescriptor);
998 :
999 56513 : css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
1000 113026 : css::uno::Reference< css::uno::XComponentContext > xContext;
1001 :
1002 : // SAFE ->
1003 113026 : ::osl::ResettableMutexGuard aLock(m_aLock);
1004 56513 : xContext = m_xContext;
1005 56513 : 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 75764 : xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >(
1017 113026 : xContext->getServiceManager()->createInstanceWithContext(sDetectService, xContext),
1018 19251 : css::uno::UNO_QUERY_THROW);
1019 : }
1020 37262 : catch (...)
1021 : {
1022 : }
1023 :
1024 56513 : if ( ! xDetector.is())
1025 37262 : return OUString();
1026 :
1027 38502 : 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 19251 : css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1039 19251 : rDescriptor >> lDescriptor;
1040 19251 : sDeepType = xDetector->detect(lDescriptor);
1041 19251 : 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.clear();
1050 : }
1051 :
1052 : // seek to 0 is an optional feature to be more robust against
1053 : // "simple implemented detect services" .-)
1054 19251 : 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 19251 : bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType);
1064 19251 : if (bValidType)
1065 2518 : return sDeepType;
1066 :
1067 73246 : return OUString();
1068 : }
1069 :
1070 :
1071 :
1072 15 : OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(utl::MediaDescriptor& rDescriptor)
1073 : {
1074 : css::uno::Reference< css::task::XInteractionHandler > xInteraction =
1075 15 : rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INTERACTIONHANDLER(),
1076 30 : css::uno::Reference< css::task::XInteractionHandler >());
1077 :
1078 15 : if (!xInteraction.is())
1079 15 : 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". Especially 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 15 : return OUString();
1129 : }
1130 :
1131 :
1132 :
1133 56514 : void TypeDetection::impl_openStream(utl::MediaDescriptor& rDescriptor)
1134 : throw (css::uno::Exception)
1135 : {
1136 56514 : bool bSuccess = false;
1137 56514 : OUString sURL = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_URL(), OUString() );
1138 56514 : bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_READONLY(), false );
1139 56514 : 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 55743 : bSuccess = rDescriptor.addInputStreamOwnLock();
1143 : }
1144 : else
1145 771 : bSuccess = rDescriptor.addInputStream();
1146 :
1147 56514 : if ( !bSuccess )
1148 : throw css::uno::Exception(
1149 2 : "Could not open stream for <" + sURL + ">",
1150 3 : static_cast<OWeakObject *>(this));
1151 :
1152 56513 : 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 56503 : rDescriptor.erase( utl::MediaDescriptor::PROP_READONLY() );
1159 56514 : }
1160 56513 : }
1161 :
1162 :
1163 :
1164 16734 : void TypeDetection::impl_removeTypeFilterFromDescriptor(utl::MediaDescriptor& rDescriptor)
1165 : {
1166 16734 : utl::MediaDescriptor::iterator pItType = rDescriptor.find(utl::MediaDescriptor::PROP_TYPENAME() );
1167 16734 : utl::MediaDescriptor::iterator pItFilter = rDescriptor.find(utl::MediaDescriptor::PROP_FILTERNAME());
1168 16734 : if (pItType != rDescriptor.end())
1169 16734 : rDescriptor.erase(pItType);
1170 16734 : if (pItFilter != rDescriptor.end())
1171 0 : rDescriptor.erase(pItFilter);
1172 16734 : }
1173 :
1174 :
1175 :
1176 79797 : bool TypeDetection::impl_validateAndSetTypeOnDescriptor( utl::MediaDescriptor& rDescriptor,
1177 : const OUString& sType )
1178 : {
1179 : // SAFE ->
1180 79797 : ::osl::ResettableMutexGuard aLock(m_aLock);
1181 79797 : if (m_rCache->hasItem(FilterCache::E_TYPE, sType))
1182 : {
1183 63063 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()] <<= sType;
1184 63063 : return true;
1185 : }
1186 16734 : aLock.clear();
1187 : // <- SAFE
1188 :
1189 : // remove all related information from the descriptor
1190 16734 : impl_removeTypeFilterFromDescriptor(rDescriptor);
1191 16734 : 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 44716 : OUString TypeDetection::impl_getImplementationName()
1227 : {
1228 44716 : return OUString( "com.sun.star.comp.filter.config.TypeDetection" );
1229 : }
1230 :
1231 :
1232 :
1233 44219 : css::uno::Sequence< OUString > TypeDetection::impl_getSupportedServiceNames()
1234 : {
1235 44219 : css::uno::Sequence< OUString > lServiceNames(1);
1236 44219 : lServiceNames[0] = "com.sun.star.document.TypeDetection";
1237 44219 : return lServiceNames;
1238 : }
1239 :
1240 :
1241 :
1242 44102 : css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
1243 : {
1244 44102 : TypeDetection* pNew = new TypeDetection( comphelper::getComponentContext(xSMGR) );
1245 44102 : 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: */
|