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 25457 : TypeDetection::TypeDetection(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
51 25457 : : m_xContext(rxContext)
52 : {
53 : BaseContainer::init(rxContext ,
54 : TypeDetection::impl_getImplementationName() ,
55 : TypeDetection::impl_getSupportedServiceNames(),
56 25457 : FilterCache::E_TYPE );
57 25457 : }
58 :
59 :
60 :
61 50914 : TypeDetection::~TypeDetection()
62 : {
63 50914 : }
64 :
65 :
66 :
67 14464 : OUString SAL_CALL TypeDetection::queryTypeByURL(const OUString& sURL)
68 : throw (css::uno::RuntimeException, std::exception)
69 : {
70 14464 : OUString sType;
71 :
72 : // SAFE ->
73 28928 : ::osl::ResettableMutexGuard aLock(m_aLock);
74 :
75 28928 : css::util::URL aURL;
76 14464 : aURL.Complete = sURL;
77 28928 : css::uno::Reference< css::util::XURLTransformer > xParser( css::util::URLTransformer::create(m_xContext) );
78 14464 : 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 28928 : FlatDetection lFlatTypes;
84 14464 : m_rCache->detectFlatForURL(aURL, lFlatTypes);
85 :
86 14464 : if (
87 27882 : (lFlatTypes.size() < 1 ) &&
88 13418 : (!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 14464 : if (lFlatTypes.size() > 0)
97 : {
98 1046 : const FlatDetectionInfo& aMatch = *(lFlatTypes.begin());
99 1046 : sType = aMatch.sType;
100 : }
101 :
102 28928 : 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 4038382 : 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 : "mov_MOV",
224 : "gif_Graphics_Interchange",
225 : "bmp_MS_Windows",
226 : "pcx_Zsoft_Paintbrush",
227 : "pct_Mac_Pict",
228 : "pcd_Photo_CD_Base",
229 : "pcd_Photo_CD_Base4",
230 : "pcd_Photo_CD_Base16",
231 : "impress_CGM_Computer_Graphics_Metafile", // There is binary and ascii variants ?
232 : "draw_WordPerfect_Graphics",
233 : "draw_Visio_Document",
234 : "draw_Publisher_Document",
235 : "draw_Corel_Presentation_Exchange",
236 : "draw_CorelDraw_Document",
237 : "writer_LotusWordPro_Document",
238 : "writer_MIZI_Hwp_97", // Hanword (Hancom Office)
239 :
240 : // Non-compressed XML
241 : "writer_ODT_FlatXML",
242 : "calc_ODS_FlatXML",
243 : "impress_ODP_FlatXML",
244 : "draw_ODG_FlatXML",
245 : "calc_MS_Excel_2003_XML",
246 : "writer_MS_Word_2003_XML",
247 : "writer_DocBook_File",
248 : "XHTML_File",
249 : "svg_Scalable_Vector_Graphics",
250 : "math_MathML_XML_Math",
251 :
252 : // Non-compressed text
253 : "dxf_AutoCAD_Interchange",
254 : "eps_Encapsulated_PostScript",
255 : "pbm_Portable_Bitmap", // There is 'raw' and 'ascii' variants.
256 : "ppm_Portable_Pixelmap", // There is 'raw' and 'ascii' variants.
257 : "pgm_Portable_Graymap", // There is 'raw' and 'ascii' variants.
258 : "xpm_XPM",
259 : "xbm_X_Consortium",
260 : "writer_Rich_Text_Format",
261 : "writer_web_HTML_help",
262 : "generic_HTML",
263 :
264 : "generic_Text", // Plain text (catch all)
265 :
266 : // Anything ranked lower than generic_Text will never be used during
267 : // type detection (since generic_Text catches all).
268 :
269 : // Export only
270 : "writer_layout_dump_xml",
271 : "pwp_PlaceWare",
272 : "graphic_SWF",
273 : "graphic_HTML",
274 :
275 : // Internal use only
276 : "StarBaseReportChart",
277 : "StarBaseReport",
278 : "math_MathType_3x", // MathType equation embedded in Word doc.
279 : };
280 :
281 4038382 : size_t n = SAL_N_ELEMENTS(ranks);
282 :
283 304899780 : for (size_t i = 0; i < n; ++i)
284 : {
285 304031649 : if (rType.equalsAscii(ranks[i]))
286 3170251 : return n - i - 1;
287 : }
288 :
289 : // Not ranked. Treat them equally. Unranked formats have higher priority
290 : // than the ranked internal ones since they may be defined externally.
291 868131 : return n;
292 : }
293 :
294 : /**
295 : * Types with matching pattern first, then extension, then custom ranks by
296 : * types, then types that are supported by the document service come next.
297 : * Lastly, sort them alphabetically.
298 : */
299 : struct SortByPriority : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
300 : {
301 2039491 : bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
302 : {
303 2039491 : if (r1.bMatchByPattern != r2.bMatchByPattern)
304 4998 : return r1.bMatchByPattern;
305 :
306 2034493 : if (r1.bMatchByExtension != r2.bMatchByExtension)
307 15302 : return r1.bMatchByExtension;
308 :
309 2019191 : int rank1 = getFlatTypeRank(r1.sType);
310 2019191 : int rank2 = getFlatTypeRank(r2.sType);
311 :
312 2019191 : if (rank1 != rank2)
313 1709718 : return rank1 > rank2;
314 :
315 309473 : if (r1.bPreselectedByDocumentService != r2.bPreselectedByDocumentService)
316 81084 : return r1.bPreselectedByDocumentService;
317 :
318 : // All things being equal, sort them alphabetically.
319 228389 : return r1.sType > r2.sType;
320 : }
321 : };
322 :
323 : struct SortByType : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
324 :
325 : {
326 3179297 : bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
327 : {
328 3179297 : return r1.sType > r2.sType;
329 : }
330 : };
331 :
332 : struct EqualByType : public std::binary_function<FlatDetectionInfo, FlatDetectionInfo, bool>
333 : {
334 802110 : bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
335 : {
336 802110 : return r1.sType == r2.sType;
337 : }
338 : };
339 :
340 263103 : class FindByType : std::unary_function<FlatDetectionInfo, bool>
341 : {
342 : OUString maType;
343 : public:
344 87701 : FindByType(const OUString& rType) : maType(rType) {}
345 4145922 : bool operator() (const FlatDetectionInfo& rInfo) const
346 : {
347 4145922 : return rInfo.sType == maType;
348 : }
349 : };
350 :
351 : #if DEBUG_TYPE_DETECTION
352 : void printFlatDetectionList(const char* caption, const FlatDetection& types)
353 : {
354 : cout << "-- " << caption << " (size=" << types.size() << ")" << endl;
355 : FlatDetection::const_iterator it = types.begin(), itEnd = types.end();
356 : for (; it != itEnd; ++it)
357 : {
358 : const FlatDetectionInfo& item = *it;
359 : cout << " type='" << item.sType << "'; match by extension (" << item.bMatchByExtension
360 : << "); match by pattern (" << item.bMatchByPattern << "); pre-selected by doc service ("
361 : << item.bPreselectedByDocumentService << ")" << endl;
362 : }
363 : cout << "--" << endl;
364 : }
365 : #endif
366 :
367 : }
368 :
369 2078 : OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
370 : sal_Bool bAllowDeep )
371 : throw (css::uno::RuntimeException, std::exception)
372 : {
373 : // make the descriptor more useable :-)
374 2078 : utl::MediaDescriptor stlDescriptor(lDescriptor);
375 :
376 : // SAFE -> ----------------------------------
377 4156 : ::osl::ResettableMutexGuard aLock(m_aLock);
378 :
379 :
380 : // parse given URL to split it into e.g. main and jump marks ...
381 4156 : OUString sURL = stlDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL(), OUString());
382 :
383 : #if OSL_DEBUG_LEVEL > 0
384 : if (stlDescriptor.find( "FileName" ) != stlDescriptor.end())
385 : OSL_FAIL("Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
386 : #endif
387 :
388 4156 : css::util::URL aURL;
389 2078 : aURL.Complete = sURL;
390 4156 : css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
391 2078 : xParser->parseStrict(aURL);
392 :
393 : OUString aSelectedFilter = stlDescriptor.getUnpackedValueOrDefault(
394 4156 : utl::MediaDescriptor::PROP_FILTERNAME(), OUString());
395 2078 : if (!aSelectedFilter.isEmpty())
396 : {
397 : // Caller specified the filter type. Honor it. Just get the default
398 : // type for that filter, and bail out.
399 0 : if (impl_validateAndSetFilterOnDescriptor(stlDescriptor, aSelectedFilter))
400 0 : return stlDescriptor[utl::MediaDescriptor::PROP_TYPENAME()].get<OUString>();
401 : }
402 :
403 4156 : FlatDetection lFlatTypes;
404 2078 : impl_getAllFormatTypes(aURL, stlDescriptor, lFlatTypes);
405 :
406 2078 : aLock.clear();
407 : // <- SAFE ----------------------------------
408 :
409 : // Properly prioritize all candidate types.
410 2078 : lFlatTypes.sort(SortByPriority());
411 2078 : lFlatTypes.unique(EqualByType());
412 :
413 4156 : OUString sType ;
414 4156 : OUString sLastChance;
415 :
416 : try
417 : {
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 isnt 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 2078 : OUStringList lUsedDetectors;
427 2078 : if (lFlatTypes.size()>0)
428 2078 : 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 2078 : if (sType.isEmpty())
436 4 : 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 2078 : 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 4 : sType = sLastChance;
445 2078 : }
446 : }
447 0 : catch(const css::uno::RuntimeException&)
448 0 : { throw; }
449 0 : catch(const css::uno::Exception& e)
450 : {
451 : SAL_WARN(
452 : "filter.config",
453 : "caught Exception \"" << e.Message
454 : << "\" while querying type of <" << sURL << ">");
455 0 : sType = OUString();
456 : }
457 :
458 :
459 : // adapt media descriptor, so it contains the right values
460 : // for type/filter name/document service/ etcpp.
461 2078 : impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!!
462 2078 : impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType);
463 :
464 2078 : stlDescriptor >> lDescriptor;
465 4156 : return sType;
466 : }
467 :
468 :
469 :
470 2078 : 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 2078 : utl::MediaDescriptor::PROP_FILTERNAME(),
477 4156 : OUString());
478 2078 : if (!sFilter.isEmpty())
479 65 : 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 2013 : utl::MediaDescriptor::PROP_DOCUMENTSERVICE(),
486 4027 : OUString());
487 2013 : if (!sDocumentService.isEmpty())
488 : {
489 : try
490 : {
491 1270 : OUString sRealType = sType;
492 :
493 : // SAFE ->
494 1274 : ::osl::ResettableMutexGuard aLock(m_aLock);
495 :
496 : // Attention: For executing next lines of code, We must be shure that
497 : // all filters already loaded :-(
498 : // That can disturb our "load on demand feature". But we have no other chance!
499 1270 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
500 :
501 1274 : CacheItem lIProps;
502 1270 : lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService;
503 1270 : lIProps[PROPNAME_TYPE ] <<= sRealType;
504 1274 : OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
505 :
506 1270 : aLock.clear();
507 : // <- SAFE
508 :
509 6450 : for (OUStringList::const_iterator pIt = lFilters.begin();
510 4300 : pIt != lFilters.end(); ++pIt)
511 : {
512 : // SAFE ->
513 1266 : aLock.reset();
514 : try
515 : {
516 1266 : CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt);
517 1266 : sal_Int32 nFlags = 0;
518 1266 : aFilter[PROPNAME_FLAGS] >>= nFlags;
519 :
520 1266 : if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
521 1266 : sFilter = *pIt;
522 1266 : if ((nFlags & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED)
523 386 : break;
524 : }
525 0 : catch(const css::uno::Exception&) {}
526 880 : aLock.clear();
527 : // <- SAFE
528 : }
529 :
530 1270 : if (!sFilter.isEmpty())
531 : {
532 1266 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME() ] <<= sRealType;
533 1266 : rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
534 1266 : sType = sRealType;
535 1266 : return;
536 4 : }
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 747 : sFilter = OUString();
550 : try
551 : {
552 : // SAFE ->
553 747 : ::osl::ResettableMutexGuard aLock(m_aLock);
554 :
555 1494 : CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
556 747 : aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
557 1493 : CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
558 :
559 746 : aLock.clear();
560 : // <- SAFE
561 :
562 : // no exception => found valid type and filter => set it on the given descriptor
563 746 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME() ] <<= sType ;
564 746 : rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
565 1493 : return;
566 : }
567 1 : catch(const css::uno::Exception&)
568 : {}
569 :
570 : // d)
571 : // Search for any import(!) filter, which is registered for this type.
572 1 : sFilter = OUString();
573 : try
574 : {
575 : // SAFE ->
576 1 : ::osl::ResettableMutexGuard aLock(m_aLock);
577 :
578 : // Attention: For executing next lines of code, We must be shure that
579 : // all filters already loaded :-(
580 : // That can disturb our "load on demand feature". But we have no other chance!
581 1 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
582 :
583 2 : CacheItem lIProps;
584 1 : lIProps[PROPNAME_TYPE] <<= sType;
585 2 : OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
586 :
587 1 : aLock.clear();
588 : // <- SAFE
589 :
590 1 : OUStringList::const_iterator pIt;
591 3 : for ( pIt = lFilters.begin();
592 2 : pIt != lFilters.end() ;
593 : ++pIt )
594 : {
595 0 : sFilter = *pIt;
596 :
597 : // SAFE ->
598 0 : aLock.reset();
599 : try
600 : {
601 0 : CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter);
602 0 : sal_Int32 nFlags = 0;
603 0 : aFilter[PROPNAME_FLAGS] >>= nFlags;
604 :
605 0 : if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
606 0 : break;
607 : }
608 0 : catch(const css::uno::Exception&)
609 0 : { continue; }
610 0 : aLock.clear();
611 : // <- SAFE
612 :
613 0 : sFilter = OUString();
614 : }
615 :
616 1 : if (!sFilter.isEmpty())
617 : {
618 0 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME() ] <<= sType ;
619 0 : rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
620 0 : return;
621 1 : }
622 : }
623 0 : catch(const css::uno::Exception&)
624 1 : {}
625 : }
626 :
627 :
628 :
629 84936 : bool TypeDetection::impl_getPreselectionForType(
630 : const OUString& sPreSelType, const util::URL& aParsedURL, FlatDetection& rFlatTypes, bool bDocService)
631 : {
632 : // Can be used to supress 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 84936 : 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 84936 : 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 84936 : bool bMatchByExtension = false;
645 :
646 : // validate type
647 84936 : OUString sType(sPreSelType);
648 169872 : CacheItem aType;
649 : try
650 : {
651 : // SAFE -> --------------------------
652 84936 : ::osl::ResettableMutexGuard aLock(m_aLock);
653 84936 : aType = m_rCache->getItem(FilterCache::E_TYPE, sType);
654 84936 : aLock.clear();
655 : // <- SAFE --------------------------
656 : }
657 0 : catch(const css::container::NoSuchElementException&)
658 : {
659 0 : sType = OUString();
660 0 : bBreakDetection = true;
661 : }
662 :
663 84936 : if (!bBreakDetection)
664 : {
665 : // We cant check a preselected type for a given stream!
666 : // So we must believe, that it can work ...
667 84936 : if ( aParsedURL.Complete == "private:stream" )
668 0 : bBreakDetection = true;
669 : }
670 :
671 84936 : if (!bBreakDetection)
672 : {
673 : // extract extension from URL .. to check it case-insensitive !
674 84936 : INetURLObject aParser (aParsedURL.Main);
675 : OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT ,
676 : true ,
677 169872 : INetURLObject::DECODE_WITH_CHARSET);
678 84936 : sExtension = sExtension.toAsciiLowerCase();
679 :
680 : // otherwise we must know, if it matches to the given URL really.
681 : // especialy if it matches by its extension or pattern registration.
682 169872 : OUStringList lExtensions(aType[PROPNAME_EXTENSIONS]);
683 169872 : OUStringList lURLPattern(aType[PROPNAME_URLPATTERN]);
684 :
685 631746 : for (OUStringList::const_iterator pIt = lExtensions.begin();
686 421164 : pIt != lExtensions.end() ;
687 : ++pIt )
688 : {
689 127591 : OUString sCheckExtension(pIt->toAsciiLowerCase());
690 127591 : if (sCheckExtension.equals(sExtension))
691 : {
692 1945 : bBreakDetection = true;
693 1945 : bMatchByExtension = true;
694 1945 : break;
695 : }
696 125646 : }
697 :
698 84936 : if (!bBreakDetection)
699 : {
700 256653 : for (OUStringList::const_iterator pIt = lURLPattern.begin();
701 171102 : pIt != lURLPattern.end() ;
702 : ++pIt )
703 : {
704 2560 : WildCard aCheck(*pIt);
705 2560 : if (aCheck.Matches(aParsedURL.Main))
706 : {
707 0 : bBreakDetection = true;
708 0 : bMatchByPattern = true;
709 0 : break;
710 : }
711 2560 : }
712 84936 : }
713 : }
714 :
715 : // if it's a valid type - set it on all return values!
716 84936 : if (!sType.isEmpty())
717 : {
718 84936 : FlatDetection::iterator it = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(sType));
719 84936 : if (it != rFlatTypes.end())
720 : {
721 84936 : if (bMatchByExtension)
722 1945 : it->bMatchByExtension = true;
723 84936 : if (bMatchByPattern)
724 0 : it->bMatchByPattern = true;
725 84936 : if (bDocService)
726 84936 : it->bPreselectedByDocumentService = true;
727 : }
728 :
729 84936 : return true;
730 : }
731 :
732 : // not valid!
733 84936 : return false;
734 : }
735 :
736 1311 : 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 1311 : OUStringList lFilters;
741 : try
742 : {
743 : // SAFE -> --------------------------
744 1311 : ::osl::ResettableMutexGuard aLock(m_aLock);
745 :
746 : // Attention: For executing next lines of code, We must be shure that
747 : // all filters already loaded :-(
748 : // That can disturb our "load on demand feature". But we have no other chance!
749 1311 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
750 :
751 2622 : CacheItem lIProps;
752 1311 : lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService;
753 1311 : lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
754 :
755 2622 : 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 258741 : for (OUStringList::const_iterator pFilter = lFilters.begin();
769 172494 : pFilter != lFilters.end();
770 : ++pFilter)
771 : {
772 84936 : OUString aType = impl_getTypeFromFilter(*pFilter);
773 84936 : if (aType.isEmpty())
774 0 : continue;
775 :
776 84936 : impl_getPreselectionForType(aType, aParsedURL, rFlatTypes, true);
777 84936 : }
778 :
779 1311 : return true;
780 : }
781 :
782 560798 : OUString TypeDetection::impl_getTypeFromFilter(const OUString& rFilterName)
783 : {
784 560798 : CacheItem aFilter;
785 : try
786 : {
787 560798 : osl::MutexGuard aLock(m_aLock);
788 560798 : aFilter = m_rCache->getItem(FilterCache::E_FILTER, rFilterName);
789 : }
790 0 : catch (const container::NoSuchElementException&)
791 : {
792 0 : return OUString();
793 : }
794 :
795 1121596 : OUString aType;
796 560798 : aFilter[PROPNAME_TYPE] >>= aType;
797 1121596 : return aType;
798 : }
799 :
800 2078 : void TypeDetection::impl_getAllFormatTypes(
801 : const util::URL& aParsedURL, utl::MediaDescriptor& rDescriptor, FlatDetection& rFlatTypes)
802 : {
803 2078 : rFlatTypes.clear();
804 :
805 : // Get all filters that we have.
806 2078 : OUStringList aFilterNames;
807 : try
808 : {
809 2078 : osl::MutexGuard aLock(m_aLock);
810 2078 : m_rCache->load(FilterCache::E_CONTAINS_FILTERS);
811 2078 : aFilterNames = m_rCache->getItemNames(FilterCache::E_FILTER);
812 : }
813 0 : catch (const container::NoSuchElementException&)
814 : {
815 2078 : return;
816 : }
817 :
818 : // Retrieve the default type for each of these filters, and store them.
819 477940 : for (OUStringList::const_iterator it = aFilterNames.begin(); it != aFilterNames.end(); ++it)
820 : {
821 475862 : OUString aType = impl_getTypeFromFilter(*it);
822 :
823 475862 : if (aType.isEmpty())
824 0 : continue;
825 :
826 951724 : FlatDetectionInfo aInfo; // all flags set to false by default.
827 475862 : aInfo.sType = aType;
828 475862 : rFlatTypes.push_back(aInfo);
829 475862 : }
830 :
831 : {
832 : // Get all types that match the URL alone.
833 2078 : FlatDetection aFlatByURL;
834 2078 : m_rCache->detectFlatForURL(aParsedURL, aFlatByURL);
835 2078 : FlatDetection::const_iterator it = aFlatByURL.begin(), itEnd = aFlatByURL.end();
836 4843 : for (; it != itEnd; ++it)
837 : {
838 2765 : FlatDetection::iterator itPos = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(it->sType));
839 2765 : if (itPos == rFlatTypes.end())
840 : // Not in the list yet.
841 1 : rFlatTypes.push_back(*it);
842 : else
843 : {
844 : // Already in the list. Update the flags.
845 2764 : FlatDetectionInfo& rInfo = *itPos;
846 2764 : const FlatDetectionInfo& rThisInfo = *it;
847 2764 : if (rThisInfo.bMatchByExtension)
848 2102 : rInfo.bMatchByExtension = true;
849 2764 : if (rThisInfo.bMatchByPattern)
850 662 : rInfo.bMatchByPattern = true;
851 2764 : if (rThisInfo.bPreselectedByDocumentService)
852 0 : rInfo.bPreselectedByDocumentService = true;
853 : }
854 2078 : }
855 : }
856 :
857 : // Remove duplicates.
858 2078 : rFlatTypes.sort(SortByType());
859 2078 : rFlatTypes.unique(EqualByType());
860 :
861 : // Mark pre-selected type (if any) to have it prioritized.
862 4156 : OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME(), OUString());
863 2078 : 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 4156 : OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString());
868 2078 : if (!sSelectedDoc.isEmpty())
869 3389 : impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes);
870 : }
871 :
872 :
873 :
874 2078 : OUString TypeDetection::impl_detectTypeFlatAndDeep( utl::MediaDescriptor& rDescriptor ,
875 : const FlatDetection& lFlatTypes ,
876 : sal_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 2078 : rLastChance = OUString();
883 2078 : 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 supressed!
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 64869 : for (FlatDetection::const_iterator pFlatIt = lFlatTypes.begin();
901 43246 : pFlatIt != lFlatTypes.end() ;
902 : ++pFlatIt )
903 : {
904 21619 : const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt;
905 21619 : OUString sFlatType = aFlatTypeInfo.sType;
906 :
907 21619 : if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType))
908 0 : continue;
909 :
910 : // b)
911 21619 : if (
912 21619 : (!bAllowDeep ) ||
913 : (aFlatTypeInfo.bMatchByPattern)
914 : )
915 : {
916 663 : return sFlatType;
917 : }
918 :
919 : try
920 : {
921 : // SAFE -> ----------------------------------
922 20956 : ::osl::ResettableMutexGuard aLock(m_aLock);
923 40340 : CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType);
924 20956 : aLock.clear();
925 :
926 40340 : OUString sDetectService;
927 20956 : aType[PROPNAME_DETECTSERVICE] >>= sDetectService;
928 :
929 : // c)
930 20956 : 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 161 : if (rLastChance.isEmpty())
937 72 : rLastChance = sFlatType;
938 :
939 161 : 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 20795 : rUsedDetectors.push_back(sDetectService);
946 40179 : OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
947 :
948 : // d)
949 20795 : if (!sDeepType.isEmpty())
950 20795 : return sDeepType;
951 : }
952 0 : catch(const css::container::NoSuchElementException&)
953 : {}
954 : // e)
955 19384 : }
956 :
957 4 : return OUString();
958 : // <- SAFE ----------------------------------
959 : }
960 :
961 23368 : 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 23368 : utl::MediaDescriptor::PROP_INPUTSTREAM(),
967 46736 : css::uno::Reference< css::io::XInputStream >());
968 46736 : css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
969 23368 : if (xSeek.is())
970 : {
971 : try
972 : {
973 23363 : 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 23368 : }
983 23368 : }
984 :
985 20795 : 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 20795 : impl_openStream(rDescriptor);
994 :
995 : // seek to 0 is an optional feature to be more robust against
996 : // "simple implemented detect services" .-)
997 20795 : impl_seekStreamToZero(rDescriptor);
998 :
999 20795 : css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
1000 41590 : css::uno::Reference< css::uno::XComponentContext > xContext;
1001 :
1002 : // SAFE ->
1003 41590 : ::osl::ResettableMutexGuard aLock(m_aLock);
1004 20795 : xContext = m_xContext;
1005 20795 : 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 23368 : xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >(
1017 41590 : xContext->getServiceManager()->createInstanceWithContext(sDetectService, xContext),
1018 2573 : css::uno::UNO_QUERY_THROW);
1019 : }
1020 18222 : catch (...)
1021 : {
1022 : }
1023 :
1024 20795 : if ( ! xDetector.is())
1025 18222 : return OUString();
1026 :
1027 5146 : 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 2573 : css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1039 2573 : rDescriptor >> lDescriptor;
1040 2573 : sDeepType = xDetector->detect(lDescriptor);
1041 2573 : 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 2573 : 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 2573 : sal_Bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType);
1064 2573 : if (bValidType)
1065 1411 : return sDeepType;
1066 :
1067 21957 : return OUString();
1068 : }
1069 :
1070 :
1071 :
1072 4 : OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(utl::MediaDescriptor& rDescriptor)
1073 : {
1074 : css::uno::Reference< css::task::XInteractionHandler > xInteraction =
1075 4 : rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INTERACTIONHANDLER(),
1076 8 : css::uno::Reference< css::task::XInteractionHandler >());
1077 :
1078 4 : if (!xInteraction.is())
1079 4 : 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 shure to ask user for "unknown contents" only ...
1092 : // and not for "missing files". Especialy if detection is done by a stream only
1093 : // we cant 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 shure, 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 4 : return OUString();
1129 : }
1130 :
1131 :
1132 :
1133 20795 : void TypeDetection::impl_openStream(utl::MediaDescriptor& rDescriptor)
1134 : throw (css::uno::Exception)
1135 : {
1136 20795 : sal_Bool bSuccess = sal_False;
1137 20795 : OUString sURL = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_URL(), OUString() );
1138 20795 : sal_Bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_READONLY(), sal_False );
1139 20795 : 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 20187 : bSuccess = rDescriptor.addInputStreamOwnLock();
1143 : }
1144 : else
1145 608 : bSuccess = rDescriptor.addInputStream();
1146 :
1147 20795 : if ( !bSuccess )
1148 : throw css::uno::Exception(
1149 0 : "Could not open stream for <" + sURL + ">",
1150 0 : static_cast<OWeakObject *>(this));
1151 :
1152 20795 : 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 20794 : rDescriptor.erase( utl::MediaDescriptor::PROP_READONLY() );
1159 20795 : }
1160 20795 : }
1161 :
1162 :
1163 :
1164 1162 : void TypeDetection::impl_removeTypeFilterFromDescriptor(utl::MediaDescriptor& rDescriptor)
1165 : {
1166 1162 : utl::MediaDescriptor::iterator pItType = rDescriptor.find(utl::MediaDescriptor::PROP_TYPENAME() );
1167 1162 : utl::MediaDescriptor::iterator pItFilter = rDescriptor.find(utl::MediaDescriptor::PROP_FILTERNAME());
1168 1162 : if (pItType != rDescriptor.end())
1169 1162 : rDescriptor.erase(pItType);
1170 1162 : if (pItFilter != rDescriptor.end())
1171 0 : rDescriptor.erase(pItFilter);
1172 1162 : }
1173 :
1174 :
1175 :
1176 26270 : sal_Bool TypeDetection::impl_validateAndSetTypeOnDescriptor( utl::MediaDescriptor& rDescriptor,
1177 : const OUString& sType )
1178 : {
1179 : // SAFE ->
1180 26270 : ::osl::ResettableMutexGuard aLock(m_aLock);
1181 26270 : if (m_rCache->hasItem(FilterCache::E_TYPE, sType))
1182 : {
1183 25108 : rDescriptor[utl::MediaDescriptor::PROP_TYPENAME()] <<= sType;
1184 25108 : return sal_True;
1185 : }
1186 1162 : aLock.clear();
1187 : // <- SAFE
1188 :
1189 : // remove all related information from the descriptor
1190 1162 : impl_removeTypeFilterFromDescriptor(rDescriptor);
1191 1162 : return sal_False;
1192 : }
1193 :
1194 :
1195 :
1196 0 : sal_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 sal_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 sal_False;
1222 : }
1223 :
1224 :
1225 :
1226 25843 : OUString TypeDetection::impl_getImplementationName()
1227 : {
1228 25843 : return OUString( "com.sun.star.comp.filter.config.TypeDetection" );
1229 : }
1230 :
1231 :
1232 :
1233 25531 : css::uno::Sequence< OUString > TypeDetection::impl_getSupportedServiceNames()
1234 : {
1235 25531 : css::uno::Sequence< OUString > lServiceNames(1);
1236 25531 : lServiceNames[0] = "com.sun.star.document.TypeDetection";
1237 25531 : return lServiceNames;
1238 : }
1239 :
1240 :
1241 :
1242 25457 : css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
1243 : {
1244 25457 : TypeDetection* pNew = new TypeDetection( comphelper::getComponentContext(xSMGR) );
1245 25457 : 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: */
|