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