1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <comphelper/diagnose_ex.hxx>
23 #include "filtercache.hxx"
24 #include "constant.hxx"
25 #include "cacheupdatelistener.hxx"
27 /*TODO see using below ... */
28 #define AS_ENABLE_FILTER_UINAMES
30 #include <com/sun/star/configuration/theDefaultProvider.hpp>
31 #include <com/sun/star/util/XChangesBatch.hpp>
32 #include <com/sun/star/container/XNameContainer.hpp>
33 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
34 #include <com/sun/star/beans/NamedValue.hpp>
35 #include <com/sun/star/beans/XMultiPropertySet.hpp>
36 #include <com/sun/star/beans/XProperty.hpp>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/beans/Property.hpp>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
41 #include <comphelper/sequence.hxx>
42 #include <comphelper/processfactory.hxx>
44 #include <unotools/configmgr.hxx>
45 #include <unotools/configpaths.hxx>
46 #include <rtl/ustrbuf.hxx>
47 #include <rtl/uri.hxx>
48 #include <sal/log.hxx>
49 #include <tools/urlobj.hxx>
50 #include <tools/wldcrd.hxx>
51 #include <i18nlangtag/languagetag.hxx>
53 #include <officecfg/Setup.hxx>
54 #include <o3tl/string_view.hxx>
57 namespace filter::config
{
59 FilterCache::FilterCache()
60 : m_eFillState(E_CONTAINS_NOTHING
)
63 OUString sStandardProps
[10];
65 sStandardProps
[i
++] = PROPNAME_USERDATA
;
66 sStandardProps
[i
++] = PROPNAME_TEMPLATENAME
;
67 sStandardProps
[i
++] = PROPNAME_ENABLED
;
68 // E_READ_UPDATE only above
69 sStandardProps
[i
++] = PROPNAME_TYPE
;
70 sStandardProps
[i
++] = PROPNAME_FILEFORMATVERSION
;
71 sStandardProps
[i
++] = PROPNAME_UICOMPONENT
;
72 sStandardProps
[i
++] = PROPNAME_FILTERSERVICE
;
73 sStandardProps
[i
++] = PROPNAME_DOCUMENTSERVICE
;
74 sStandardProps
[i
++] = PROPNAME_EXPORTEXTENSION
;
75 sStandardProps
[i
++] = PROPNAME_FLAGS
; // must be last.
76 assert(i
== SAL_N_ELEMENTS(sStandardProps
));
78 // E_READ_NOTHING -> creative nothingness.
79 m_aStandardProps
[E_READ_STANDARD
] =
80 css::uno::Sequence
< OUString
>(sStandardProps
+ 3, 7);
81 m_aStandardProps
[E_READ_UPDATE
] =
82 css::uno::Sequence
< OUString
>(sStandardProps
, 3);
83 m_aStandardProps
[E_READ_ALL
] =
84 css::uno::Sequence
< OUString
>(sStandardProps
,
85 SAL_N_ELEMENTS(sStandardProps
));
88 OUString sTypeProps
[7];
89 sTypeProps
[i
++] = PROPNAME_MEDIATYPE
;
90 // E_READ_UPDATE only above
91 sTypeProps
[i
++] = PROPNAME_PREFERREDFILTER
;
92 sTypeProps
[i
++] = PROPNAME_DETECTSERVICE
;
93 sTypeProps
[i
++] = PROPNAME_URLPATTERN
;
94 sTypeProps
[i
++] = PROPNAME_EXTENSIONS
;
95 sTypeProps
[i
++] = PROPNAME_PREFERRED
;
96 sTypeProps
[i
++] = PROPNAME_CLIPBOARDFORMAT
;
97 assert(i
== SAL_N_ELEMENTS(sTypeProps
));
99 // E_READ_NOTHING -> more creative nothingness.
100 m_aTypeProps
[E_READ_STANDARD
] =
101 css::uno::Sequence
< OUString
>(sTypeProps
+ 1, 6);
102 m_aTypeProps
[E_READ_UPDATE
] =
103 css::uno::Sequence
< OUString
>(sTypeProps
, 1);
104 m_aTypeProps
[E_READ_ALL
] =
105 css::uno::Sequence
< OUString
>(sTypeProps
,
106 SAL_N_ELEMENTS(sTypeProps
));
110 FilterCache::~FilterCache()
112 if (m_xTypesChglisteners
.is())
113 m_xTypesChglisteners
->stopListening();
114 if (m_xFiltersChgListener
.is())
115 m_xFiltersChgListener
->stopListening();
119 std::unique_ptr
<FilterCache
> FilterCache::clone() const
121 // SAFE -> ----------------------------------
122 osl::MutexGuard
aLock(m_aMutex
);
124 auto pClone
= std::make_unique
<FilterCache
>();
126 // Don't copy the configuration access points here.
127 // They will be created on demand inside the cloned instance,
128 // if they are needed.
130 pClone
->m_lTypes
= m_lTypes
;
131 pClone
->m_lFilters
= m_lFilters
;
132 pClone
->m_lFrameLoaders
= m_lFrameLoaders
;
133 pClone
->m_lContentHandlers
= m_lContentHandlers
;
134 pClone
->m_lExtensions2Types
= m_lExtensions2Types
;
135 pClone
->m_lURLPattern2Types
= m_lURLPattern2Types
;
137 pClone
->m_sActLocale
= m_sActLocale
;
139 pClone
->m_eFillState
= m_eFillState
;
141 pClone
->m_lChangedTypes
= m_lChangedTypes
;
142 pClone
->m_lChangedFilters
= m_lChangedFilters
;
143 pClone
->m_lChangedFrameLoaders
= m_lChangedFrameLoaders
;
144 pClone
->m_lChangedContentHandlers
= m_lChangedContentHandlers
;
147 // <- SAFE ----------------------------------
151 void FilterCache::takeOver(const FilterCache
& rClone
)
153 // SAFE -> ----------------------------------
154 osl::MutexGuard
aLock(m_aMutex
);
157 // Don't copy the configuration access points here!
158 // We must use our own ones...
161 // Further we can ignore the uno service manager.
162 // We should already have a valid instance.
165 // Take over only changed items!
166 // Otherwise we risk the following scenario:
167 // c1) clone_1 contains changed filters
168 // c2) clone_2 container changed types
169 // c3) clone_1 take over changed filters and unchanged types
170 // c4) clone_2 take over unchanged filters(!) and changed types(!)
171 // c5) c4 overwrites c3!
173 if (!rClone
.m_lChangedTypes
.empty())
174 m_lTypes
= rClone
.m_lTypes
;
175 if (!rClone
.m_lChangedFilters
.empty())
176 m_lFilters
= rClone
.m_lFilters
;
177 if (!rClone
.m_lChangedFrameLoaders
.empty())
178 m_lFrameLoaders
= rClone
.m_lFrameLoaders
;
179 if (!rClone
.m_lChangedContentHandlers
.empty())
180 m_lContentHandlers
= rClone
.m_lContentHandlers
;
182 m_lChangedTypes
.clear();
183 m_lChangedFilters
.clear();
184 m_lChangedFrameLoaders
.clear();
185 m_lChangedContentHandlers
.clear();
187 m_sActLocale
= rClone
.m_sActLocale
;
189 m_eFillState
= rClone
.m_eFillState
;
191 // renew all dependencies and optimizations
192 // Because we can't be sure, that changed filters on one clone
193 // and changed types of another clone work together.
194 // But here we can check against the later changes...
195 impl_validateAndOptimize();
196 // <- SAFE ----------------------------------
199 void FilterCache::load(EFillState eRequired
)
201 // SAFE -> ----------------------------------
202 osl::MutexGuard
aLock(m_aMutex
);
204 // check if required fill state is already reached ...
205 // There is nothing to do then.
206 if ((m_eFillState
& eRequired
) == eRequired
)
209 // Otherwise load the missing items.
212 // a) load some const values from configuration.
213 // These values are needed there for loading
215 // Further we load some std items from the
216 // configuration so we can try to load the first
217 // office document with a minimal set of values.
218 if (m_eFillState
== E_CONTAINS_NOTHING
)
220 impl_getDirectCFGValue(CFGDIRECTKEY_OFFICELOCALE
) >>= m_sActLocale
;
221 if (m_sActLocale
.isEmpty())
223 m_sActLocale
= DEFAULT_OFFICELOCALE
;
226 // Support the old configuration support. Read it only one times during office runtime!
227 impl_readOldFormat();
231 // b) If the required fill state was not reached
232 // but std values was already loaded ...
233 // we must load some further missing items.
234 impl_load(eRequired
);
238 bool FilterCache::isFillState(FilterCache::EFillState eState
) const
241 osl::MutexGuard
aLock(m_aMutex
);
242 return ((m_eFillState
& eState
) == eState
);
247 std::vector
<OUString
> FilterCache::getMatchingItemsByProps( EItemType eType
,
248 std::span
< const css::beans::NamedValue
> lIProps
,
249 std::span
< const css::beans::NamedValue
> lEProps
) const
252 osl::MutexGuard
aLock(m_aMutex
);
254 // search for right list
255 // An exception is thrown - "eType" is unknown.
256 // => rList will be valid everytimes next line is reached.
257 const CacheItemList
& rList
= impl_getItemList(eType
);
259 std::vector
<OUString
> lKeys
;
260 lKeys
.reserve(rList
.size());
262 // search items, which provides all needed properties of set "lIProps"
263 // but not of set "lEProps"!
264 for (auto const& elem
: rList
)
267 (elem
.second
.haveProps(lIProps
) ) &&
268 (elem
.second
.dontHaveProps(lEProps
))
271 lKeys
.push_back(elem
.first
);
280 bool FilterCache::hasItems(EItemType eType
) const
283 osl::MutexGuard
aLock(m_aMutex
);
285 // search for right list
286 // An exception is thrown - "eType" is unknown.
287 // => rList will be valid everytimes next line is reached.
288 const CacheItemList
& rList
= impl_getItemList(eType
);
290 return !rList
.empty();
295 std::vector
<OUString
> FilterCache::getItemNames(EItemType eType
) const
298 osl::MutexGuard
aLock(m_aMutex
);
300 // search for right list
301 // An exception is thrown - "eType" is unknown.
302 // => rList will be valid everytimes next line is reached.
303 const CacheItemList
& rList
= impl_getItemList(eType
);
305 std::vector
<OUString
> lKeys
;
306 for (auto const& elem
: rList
)
308 lKeys
.push_back(elem
.first
);
315 bool FilterCache::hasItem( EItemType eType
,
316 const OUString
& sItem
)
319 osl::MutexGuard
aLock(m_aMutex
);
321 // search for right list
322 // An exception is thrown - "eType" is unknown.
323 // => rList will be valid everytimes next line is reached.
324 const CacheItemList
& rList
= impl_getItemList(eType
);
326 // if item could not be found - check if it can be loaded
327 // from the underlying configuration layer. Might it was not already
328 // loaded into this FilterCache object before.
329 CacheItemList::const_iterator pIt
= rList
.find(sItem
);
330 if (pIt
!= rList
.end())
335 impl_loadItemOnDemand(eType
, sItem
);
336 // no exception => item could be loaded!
339 catch(const css::container::NoSuchElementException
&)
347 CacheItem
FilterCache::getItem( EItemType eType
,
348 const OUString
& sItem
)
351 osl::MutexGuard
aLock(m_aMutex
);
353 CacheItem aItem
= impl_getItem(eType
, sItem
);
359 CacheItem
& FilterCache::impl_getItem( EItemType eType
,
360 const OUString
& sItem
)
362 // search for right list
363 // An exception is thrown if "eType" is unknown.
364 // => rList will be valid everytimes next line is reached.
365 CacheItemList
& rList
= impl_getItemList(eType
);
367 // check if item exists ...
368 CacheItemList::iterator pIt
= rList
.find(sItem
);
369 if (pIt
== rList
.end())
371 // ... or load it on demand from the
372 // underlying configuration layer.
373 // Note: NoSuchElementException is thrown automatically here if
374 // item could not be loaded!
375 pIt
= impl_loadItemOnDemand(eType
, sItem
);
378 /* Workaround for #137955#
379 Draw types and filters are installed ... but draw was disabled during setup.
380 We must suppress accessing these filters. Otherwise the office can crash.
381 Solution for the next major release: do not install those filters !
383 if (eType
== E_FILTER
)
385 CacheItem
& rFilter
= pIt
->second
;
386 OUString sDocService
;
387 rFilter
[PROPNAME_DOCUMENTSERVICE
] >>= sDocService
;
389 // In Standalone-Impress the module WriterWeb is not installed
390 // but it is there to load help pages
391 bool bIsHelpFilter
= sItem
== "writer_web_HTML_help";
393 if ( !bIsHelpFilter
&& !impl_isModuleInstalled(sDocService
) )
395 OUString
sMsg("The requested filter '" + sItem
+
396 "' exists ... but it should not; because the corresponding LibreOffice module was not installed.");
397 throw css::container::NoSuchElementException(sMsg
, css::uno::Reference
< css::uno::XInterface
>());
405 void FilterCache::removeItem( EItemType eType
,
406 const OUString
& sItem
)
409 osl::MutexGuard
aLock(m_aMutex
);
411 // search for right list
412 // An exception is thrown - "eType" is unknown.
413 // => rList will be valid everytimes next line is reached.
414 CacheItemList
& rList
= impl_getItemList(eType
);
416 CacheItemList::iterator pItem
= rList
.find(sItem
);
417 if (pItem
== rList
.end())
418 pItem
= impl_loadItemOnDemand(eType
, sItem
); // throws NoSuchELementException!
421 impl_addItem2FlushList(eType
, sItem
);
425 void FilterCache::setItem( EItemType eType
,
426 const OUString
& sItem
,
427 const CacheItem
& aValue
)
430 osl::MutexGuard
aLock(m_aMutex
);
432 // search for right list
433 // An exception is thrown - "eType" is unknown.
434 // => rList will be valid everytimes next line is reached.
435 CacheItemList
& rList
= impl_getItemList(eType
);
437 // name must be part of the property set too ... otherwise our
438 // container query can't work correctly
439 CacheItem aItem
= aValue
;
440 aItem
[PROPNAME_NAME
] <<= sItem
;
441 aItem
.validateUINames(m_sActLocale
);
443 // remove implicit properties as e.g. FINALIZED or MANDATORY
444 // They can't be saved here and must be read on demand later, if they are needed.
445 removeStatePropsFromItem(aItem
);
447 rList
[sItem
] = std::move(aItem
);
449 impl_addItem2FlushList(eType
, sItem
);
453 void FilterCache::refreshItem( EItemType eType
,
454 const OUString
& sItem
)
457 osl::MutexGuard
aLock(m_aMutex
);
458 impl_loadItemOnDemand(eType
, sItem
);
462 css::uno::Any
FilterCache::getItemWithStateProps( EItemType eType
,
463 const OUString
& sItem
)
466 osl::MutexGuard
aLock(m_aMutex
);
468 const CacheItem
& rItem
= impl_getItem(eType
, sItem
);
470 // Note: Opening of the configuration layer throws some exceptions
471 // if it failed. So we mustn't check any reference here...
472 css::uno::Reference
< css::container::XNameAccess
> xPackage
;
473 css::uno::Reference
< css::container::XNameAccess
> xSet
;
478 xPackage
.set(impl_openConfig(E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
479 xPackage
->getByName(CFGSET_TYPES
) >>= xSet
;
485 xPackage
.set(impl_openConfig(E_PROVIDER_FILTERS
), css::uno::UNO_QUERY_THROW
);
486 xPackage
->getByName(CFGSET_FILTERS
) >>= xSet
;
494 The default frame loader can't be located inside the normal set of frame loaders.
495 It's an atomic property inside the misc cfg package. So we can't retrieve the information
496 about FINALIZED and MANDATORY very easy ... :-(
497 => set it to readonly/required everytimes :-)
499 css::uno::Any aDirectValue
= impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER
);
500 OUString sDefaultFrameLoader
;
502 (aDirectValue
>>= sDefaultFrameLoader
) &&
503 (!sDefaultFrameLoader
.isEmpty() ) &&
504 (sItem
== sDefaultFrameLoader
)
507 css::uno::Sequence aProps
= rItem
.getAsPackedPropertyValueList(true, true);
508 return css::uno::Any(aProps
);
512 xPackage
.set(impl_openConfig(E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
513 xPackage
->getByName(CFGSET_FRAMELOADERS
) >>= xSet
;
517 case E_CONTENTHANDLER
:
519 xPackage
.set(impl_openConfig(E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
520 xPackage
->getByName(CFGSET_CONTENTHANDLERS
) >>= xSet
;
526 bool bFinalized
, bMandatory
;
529 css::uno::Reference
< css::beans::XProperty
> xItem
;
530 xSet
->getByName(sItem
) >>= xItem
;
531 css::beans::Property aDescription
= xItem
->getAsProperty();
533 bFinalized
= ((aDescription
.Attributes
& css::beans::PropertyAttribute::READONLY
) == css::beans::PropertyAttribute::READONLY
);
534 bMandatory
= ((aDescription
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
) != css::beans::PropertyAttribute::REMOVABLE
);
537 catch(const css::container::NoSuchElementException
&)
539 /* Ignore exceptions for missing elements inside configuration.
540 May by the following reason exists:
541 - The item does not exists inside the new configuration package org.openoffice.TypeDetection - but
542 we got it from the old package org.openoffice.Office/TypeDetection. We don't migrate such items
543 automatically to the new format. Because it will disturb e.g. the deinstallation of an external filter
544 package. Because such external filter can remove the old file - but not the automatically created new one ...
546 => mark item as FINALIZED / MANDATORY, we don't support writing to the old format
552 css::uno::Sequence
<css::beans::PropertyValue
> aProps
= rItem
.getAsPackedPropertyValueList(bFinalized
, bMandatory
);
554 return css::uno::Any(aProps
);
559 void FilterCache::removeStatePropsFromItem(CacheItem
& rItem
)
561 CacheItem::iterator pIt
= rItem
.find(PROPNAME_FINALIZED
);
562 if (pIt
!= rItem
.end())
564 pIt
= rItem
.find(PROPNAME_MANDATORY
);
565 if (pIt
!= rItem
.end())
570 void FilterCache::flush()
573 osl::MutexGuard
aLock(m_aMutex
);
575 // renew all dependencies and optimizations
576 impl_validateAndOptimize();
578 if (!m_lChangedTypes
.empty())
580 css::uno::Reference
< css::container::XNameAccess
> xConfig(impl_openConfig(E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
581 css::uno::Reference
< css::container::XNameAccess
> xSet
;
583 xConfig
->getByName(CFGSET_TYPES
) >>= xSet
;
584 impl_flushByList(xSet
, E_TYPE
, m_lTypes
, m_lChangedTypes
);
586 css::uno::Reference
< css::util::XChangesBatch
> xFlush(xConfig
, css::uno::UNO_QUERY
);
587 xFlush
->commitChanges();
590 if (!m_lChangedFilters
.empty())
592 css::uno::Reference
< css::container::XNameAccess
> xConfig(impl_openConfig(E_PROVIDER_FILTERS
), css::uno::UNO_QUERY_THROW
);
593 css::uno::Reference
< css::container::XNameAccess
> xSet
;
595 xConfig
->getByName(CFGSET_FILTERS
) >>= xSet
;
596 impl_flushByList(xSet
, E_FILTER
, m_lFilters
, m_lChangedFilters
);
598 css::uno::Reference
< css::util::XChangesBatch
> xFlush(xConfig
, css::uno::UNO_QUERY
);
599 xFlush
->commitChanges();
602 /*TODO FrameLoader/ContentHandler must be flushed here too ... */
606 void FilterCache::impl_flushByList(const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
608 const CacheItemList
& rCache
,
609 const std::vector
<OUString
>& lItems
)
611 css::uno::Reference
< css::container::XNameContainer
> xAddRemoveSet(xSet
, css::uno::UNO_QUERY
);
612 css::uno::Reference
< css::lang::XSingleServiceFactory
> xFactory(xSet
, css::uno::UNO_QUERY
);
614 for (auto const& item
: lItems
)
616 EItemFlushState eState
= impl_specifyFlushOperation(xSet
, rCache
, item
);
619 case E_ITEM_REMOVED
:
621 xAddRemoveSet
->removeByName(item
);
627 css::uno::Reference
< css::container::XNameReplace
> xItem (xFactory
->createInstance(), css::uno::UNO_QUERY
);
629 // special case. no exception - but not a valid item => set must be finalized or mandatory!
630 // Reject flush operation by throwing an exception. At least one item couldn't be flushed.
632 throw css::uno::Exception(u
"Can not add item. Set is finalized or mandatory!"_ustr
,
633 css::uno::Reference
< css::uno::XInterface
>());
635 CacheItemList::const_iterator pItem
= rCache
.find(item
);
636 impl_saveItem(xItem
, eType
, pItem
->second
);
637 xAddRemoveSet
->insertByName(item
, css::uno::Any(xItem
));
641 case E_ITEM_CHANGED
:
643 css::uno::Reference
< css::container::XNameReplace
> xItem
;
644 xSet
->getByName(item
) >>= xItem
;
646 // special case. no exception - but not a valid item => it must be finalized or mandatory!
647 // Reject flush operation by throwing an exception. At least one item couldn't be flushed.
649 throw css::uno::Exception(u
"Can not change item. It's finalized or mandatory!"_ustr
,
650 css::uno::Reference
< css::uno::XInterface
>());
652 CacheItemList::const_iterator pItem
= rCache
.find(item
);
653 impl_saveItem(xItem
, eType
, pItem
->second
);
662 void FilterCache::detectFlatForURL(const css::util::URL
& aURL
,
663 FlatDetection
& rFlatTypes
) const
665 // extract extension from URL, so it can be used directly as key into our hash map!
666 // Note further: It must be converted to lower case, because the optimize hash
667 // (which maps extensions to types) work with lower case key strings!
668 INetURLObject
aParser (aURL
.Main
);
669 OUString sExtension
= aParser
.getExtension(INetURLObject::LAST_SEGMENT
,
671 INetURLObject::DecodeMechanism::WithCharset
);
672 sExtension
= sExtension
.toAsciiLowerCase();
674 // SAFE -> ----------------------------------
675 osl::MutexGuard
aLock(m_aMutex
);
678 // i) Step over all well known URL pattern
679 // and add registered types to the return list too
680 // Do it as first one - because: if a type match by a
681 // pattern a following deep detection can be suppressed!
682 // Further we can stop after first match ...
683 for (auto const& pattern
: m_lURLPattern2Types
)
685 WildCard
aPatternCheck(pattern
.first
);
686 if (aPatternCheck
.Matches(aURL
.Main
))
688 const std::vector
<OUString
>& rTypesForPattern
= pattern
.second
;
690 FlatDetectionInfo aInfo
;
691 aInfo
.sType
= *(rTypesForPattern
.begin());
692 aInfo
.bMatchByPattern
= true;
694 rFlatTypes
.push_back(aInfo
);
700 // ii) search types matching to the given extension.
701 // Copy every matching type without changing its order!
702 // Because preferred types was added as first one during
703 // loading configuration.
704 CacheItemRegistration::const_iterator pExtReg
= m_lExtensions2Types
.find(sExtension
);
705 if (pExtReg
!= m_lExtensions2Types
.end())
707 const std::vector
<OUString
>& rTypesForExtension
= pExtReg
->second
;
708 for (auto const& elem
: rTypesForExtension
)
710 FlatDetectionInfo aInfo
;
712 aInfo
.bMatchByExtension
= true;
714 rFlatTypes
.push_back(aInfo
);
718 // <- SAFE ----------------------------------
721 const CacheItemList
& FilterCache::impl_getItemList(EItemType eType
) const
723 // SAFE -> ----------------------------------
724 osl::MutexGuard
aLock(m_aMutex
);
728 case E_TYPE
: return m_lTypes
;
729 case E_FILTER
: return m_lFilters
;
730 case E_FRAMELOADER
: return m_lFrameLoaders
;
731 case E_CONTENTHANDLER
: return m_lContentHandlers
;
735 throw css::uno::RuntimeException(u
"unknown sub container requested."_ustr
,
736 css::uno::Reference
< css::uno::XInterface
>());
737 // <- SAFE ----------------------------------
740 CacheItemList
& FilterCache::impl_getItemList(EItemType eType
)
742 // SAFE -> ----------------------------------
743 osl::MutexGuard
aLock(m_aMutex
);
747 case E_TYPE
: return m_lTypes
;
748 case E_FILTER
: return m_lFilters
;
749 case E_FRAMELOADER
: return m_lFrameLoaders
;
750 case E_CONTENTHANDLER
: return m_lContentHandlers
;
754 throw css::uno::RuntimeException(u
"unknown sub container requested."_ustr
,
755 css::uno::Reference
< css::uno::XInterface
>());
756 // <- SAFE ----------------------------------
759 css::uno::Reference
< css::uno::XInterface
> FilterCache::impl_openConfig(EConfigProvider eProvider
)
761 osl::MutexGuard
aLock(m_aMutex
);
764 css::uno::Reference
< css::uno::XInterface
>* pConfig
= nullptr;
765 css::uno::Reference
< css::uno::XInterface
> xOld
;
770 case E_PROVIDER_TYPES
:
772 if (m_xConfigTypes
.is())
773 return m_xConfigTypes
;
774 sPath
= CFGPACKAGE_TD_TYPES
;
775 pConfig
= &m_xConfigTypes
;
776 sRtlLog
= "impl_openconfig(E_PROVIDER_TYPES)"_ostr
;
780 case E_PROVIDER_FILTERS
:
782 if (m_xConfigFilters
.is())
783 return m_xConfigFilters
;
784 sPath
= CFGPACKAGE_TD_FILTERS
;
785 pConfig
= &m_xConfigFilters
;
786 sRtlLog
= "impl_openconfig(E_PROVIDER_FILTERS)"_ostr
;
790 case E_PROVIDER_OTHERS
:
792 if (m_xConfigOthers
.is())
793 return m_xConfigOthers
;
794 sPath
= CFGPACKAGE_TD_OTHERS
;
795 pConfig
= &m_xConfigOthers
;
796 sRtlLog
= "impl_openconfig(E_PROVIDER_OTHERS)"_ostr
;
800 case E_PROVIDER_OLD
:
802 // This special provider is used to work with
803 // the old configuration format only. It's not cached!
804 sPath
= CFGPACKAGE_TD_OLD
;
806 sRtlLog
= "impl_openconfig(E_PROVIDER_OLD)"_ostr
;
810 default : throw css::uno::RuntimeException(u
"These configuration node is not supported here for open!"_ustr
, nullptr);
814 SAL_INFO( "filter.config", "" << sRtlLog
);
815 *pConfig
= impl_createConfigAccess(sPath
,
817 true ); // bLocalesMode
821 // Start listening for changes on that configuration access.
824 case E_PROVIDER_TYPES
:
826 m_xTypesChglisteners
.set(new CacheUpdateListener(*this, *pConfig
, FilterCache::E_TYPE
));
827 m_xTypesChglisteners
->startListening();
830 case E_PROVIDER_FILTERS
:
832 m_xFiltersChgListener
.set(new CacheUpdateListener(*this, *pConfig
, FilterCache::E_FILTER
));
833 m_xFiltersChgListener
->startListening();
843 css::uno::Any
FilterCache::impl_getDirectCFGValue(std::u16string_view sDirectKey
)
849 (!::utl::splitLastFromConfigurationPath(sDirectKey
, sRoot
, sKey
)) ||
850 (sRoot
.isEmpty() ) ||
853 return css::uno::Any();
855 css::uno::Reference
< css::uno::XInterface
> xCfg
= impl_createConfigAccess(sRoot
,
857 false); // bLocalesMode
859 return css::uno::Any();
861 css::uno::Reference
< css::container::XNameAccess
> xAccess(xCfg
, css::uno::UNO_QUERY
);
863 return css::uno::Any();
865 css::uno::Any aValue
;
868 aValue
= xAccess
->getByName(sKey
);
870 catch(const css::uno::RuntimeException
&)
872 catch(const css::uno::Exception
&)
874 TOOLS_WARN_EXCEPTION( "filter.config", "");
882 css::uno::Reference
< css::uno::XInterface
> FilterCache::impl_createConfigAccess(const OUString
& sRoot
,
887 osl::MutexGuard
aLock(m_aMutex
);
889 css::uno::Reference
< css::uno::XInterface
> xCfg
;
891 if (!comphelper::IsFuzzing())
895 css::uno::Reference
< css::lang::XMultiServiceFactory
> xConfigProvider(
896 css::configuration::theDefaultProvider::get( comphelper::getProcessComponentContext() ) );
898 ::std::vector
< css::uno::Any
> lParams
;
899 css::beans::NamedValue aParam
;
902 aParam
.Name
= "nodepath";
903 aParam
.Value
<<= sRoot
;
904 lParams
.push_back(css::uno::Any(aParam
));
906 // enable "all locales mode" ... if required
909 aParam
.Name
= "locale";
910 aParam
.Value
<<= u
"*"_ustr
;
911 lParams
.push_back(css::uno::Any(aParam
));
916 xCfg
= xConfigProvider
->createInstanceWithArguments(SERVICE_CONFIGURATIONACCESS
,
917 comphelper::containerToSequence(lParams
));
919 xCfg
= xConfigProvider
->createInstanceWithArguments(SERVICE_CONFIGURATIONUPDATEACCESS
,
920 comphelper::containerToSequence(lParams
));
922 // If configuration could not be opened... but factory method did not throw an exception
923 // trigger throwing of our own CorruptedFilterConfigurationException.
924 // Let message empty. The normal exception text show enough information to the user.
926 throw css::uno::Exception(
927 u
"Got NULL reference on opening configuration file ... but no exception."_ustr
,
928 css::uno::Reference
< css::uno::XInterface
>());
930 catch(const css::uno::Exception
& ex
)
932 throw css::document::CorruptedFilterConfigurationException(
933 "filter configuration, caught: " + ex
.Message
,
934 css::uno::Reference
< css::uno::XInterface
>(),
944 void FilterCache::impl_validateAndOptimize()
947 osl::MutexGuard
aLock(m_aMutex
);
949 // First check if any filter or type could be read
950 // from the underlying configuration!
951 bool bSomeTypesShouldExist
= ((m_eFillState
& E_CONTAINS_STANDARD
) == E_CONTAINS_STANDARD
);
952 bool bAllFiltersShouldExist
= ((m_eFillState
& E_CONTAINS_FILTERS
) == E_CONTAINS_FILTERS
);
954 #if OSL_DEBUG_LEVEL > 0
956 sal_Int32 nWarnings
= 0;
958 // sal_Bool bAllTypesShouldExist = ((m_eFillState & E_CONTAINS_TYPES ) == E_CONTAINS_TYPES );
959 bool bAllLoadersShouldExist
= ((m_eFillState
& E_CONTAINS_FRAMELOADERS
) == E_CONTAINS_FRAMELOADERS
);
960 bool bAllHandlersShouldExist
= ((m_eFillState
& E_CONTAINS_CONTENTHANDLERS
) == E_CONTAINS_CONTENTHANDLERS
);
965 bSomeTypesShouldExist
&& m_lTypes
.empty()
968 bAllFiltersShouldExist
&& m_lFilters
.empty()
972 throw css::document::CorruptedFilterConfigurationException(
973 u
"filter configuration: the list of types or filters is empty"_ustr
,
974 css::uno::Reference
< css::uno::XInterface
>(),
975 u
"The list of types or filters is empty."_ustr
);
978 // Create a log for all detected problems, which
979 // occur in the next few lines.
980 // If there are some real errors throw a RuntimException!
981 // If there are some warnings only, show an assertion.
982 sal_Int32 nErrors
= 0;
983 OUStringBuffer
sLog(256);
985 for (auto const& elem
: m_lTypes
)
987 const OUString
& sType
= elem
.first
;
988 const CacheItem
& aType
= elem
.second
;
990 // get its registration for file Extensions AND(!) URLPattern ...
991 // It doesn't matter if these items exists or if our
992 // used index access create some default ones ...
993 // only in case there is no filled set of Extensions AND
994 // no filled set of URLPattern -> we must try to remove this invalid item
996 css::uno::Sequence
< OUString
> lExtensions
;
997 css::uno::Sequence
< OUString
> lURLPattern
;
998 auto it
= aType
.find(PROPNAME_EXTENSIONS
);
999 if (it
!= aType
.end())
1000 it
->second
>>= lExtensions
;
1001 it
= aType
.find(PROPNAME_URLPATTERN
);
1002 if (it
!= aType
.end())
1003 it
->second
>>= lURLPattern
;
1004 sal_Int32 ce
= lExtensions
.getLength();
1005 sal_Int32 cu
= lURLPattern
.getLength();
1007 #if OSL_DEBUG_LEVEL > 0
1009 OUString sInternalTypeNameCheck
;
1010 it
= aType
.find(PROPNAME_NAME
);
1011 if (it
!= aType
.end())
1012 it
->second
>>= sInternalTypeNameCheck
;
1013 if (sInternalTypeNameCheck
!= sType
)
1015 sLog
.append("Warning\t:\t" "The type \"" + sType
+ "\" does support the property \"Name\" correctly.\n");
1021 sLog
.append("Warning\t:\t" "The type \"" + sType
+ "\" does not contain any URL pattern nor any extensions.\n");
1026 // create an optimized registration for this type to
1027 // its set list of extensions/url pattern. If it's a "normal" type
1028 // set it at the end of this optimized list. But if it's
1029 // a "Preferred" one - set it to the front of this list.
1030 // Of course multiple "Preferred" registrations can occur
1031 // (they shouldn't - but they can!) ... Ignore it. The last
1032 // preferred type is usable in the same manner then every
1034 bool bPreferred
= false;
1035 it
= aType
.find(PROPNAME_PREFERRED
);
1036 if (it
!= aType
.end())
1037 it
->second
>>= bPreferred
;
1039 const OUString
* pExtensions
= lExtensions
.getConstArray();
1040 for (sal_Int32 e
=0; e
<ce
; ++e
)
1042 // Note: We must be sure that address the right hash entry
1043 // does not depend from any upper/lower case problems ...
1044 OUString sNormalizedExtension
= pExtensions
[e
].toAsciiLowerCase();
1046 std::vector
<OUString
>& lTypesForExtension
= m_lExtensions2Types
[sNormalizedExtension
];
1047 if (::std::find(lTypesForExtension
.begin(), lTypesForExtension
.end(), sType
) != lTypesForExtension
.end())
1051 lTypesForExtension
.insert(lTypesForExtension
.begin(), sType
);
1053 lTypesForExtension
.push_back(sType
);
1056 const OUString
* pURLPattern
= lURLPattern
.getConstArray();
1057 for (sal_Int32 u
=0; u
<cu
; ++u
)
1059 std::vector
<OUString
>& lTypesForURLPattern
= m_lURLPattern2Types
[pURLPattern
[u
]];
1060 if (::std::find(lTypesForURLPattern
.begin(), lTypesForURLPattern
.end(), sType
) != lTypesForURLPattern
.end())
1064 lTypesForURLPattern
.insert(lTypesForURLPattern
.begin(), sType
);
1066 lTypesForURLPattern
.push_back(sType
);
1069 #if OSL_DEBUG_LEVEL > 0
1071 // Don't check cross references between types and filters, if
1072 // not all filters read from disk!
1073 // OK - this cache can read single filters on demand too ...
1074 // but then the fill state of this cache should not be set to E_CONTAINS_FILTERS!
1075 if (!bAllFiltersShouldExist
)
1078 OUString sPrefFilter
;
1079 it
= aType
.find(PROPNAME_PREFERREDFILTER
);
1080 if (it
!= aType
.end())
1081 it
->second
>>= sPrefFilter
;
1082 if (sPrefFilter
.isEmpty())
1084 // OK - there is no filter for this type. But that's not an error.
1085 // Maybe it can be handled by a ContentHandler...
1086 // But at this time it's not guaranteed that there is any ContentHandler
1087 // or FrameLoader inside this cache... but on disk...
1088 bool bReferencedByLoader
= true;
1089 bool bReferencedByHandler
= true;
1090 if (bAllLoadersShouldExist
)
1091 bReferencedByLoader
= !impl_searchFrameLoaderForType(sType
).isEmpty();
1093 if (bAllHandlersShouldExist
)
1094 bReferencedByHandler
= !impl_searchContentHandlerForType(sType
).isEmpty();
1097 (!bReferencedByLoader
) &&
1098 (!bReferencedByHandler
)
1101 sLog
.append("Warning\t:\t" "The type \"" + sType
+ "\" is not used by any filter, loader or content handler.\n");
1106 if (!sPrefFilter
.isEmpty())
1108 CacheItemList::const_iterator pIt2
= m_lFilters
.find(sPrefFilter
);
1109 if (pIt2
== m_lFilters
.end())
1111 if (bAllFiltersShouldExist
)
1113 ++nWarnings
; // preferred filters can point to a non-installed office module ! no error ... it's a warning only .-(
1114 sLog
.append("error\t:\t");
1119 sLog
.append("warning\t:\t");
1122 sLog
.append("The type \"" + sType
+ "\" points to an invalid filter \"" + sPrefFilter
+ "\".\n");
1126 CacheItem aPrefFilter
= pIt2
->second
;
1127 OUString sFilterTypeReg
;
1128 aPrefFilter
[PROPNAME_TYPE
] >>= sFilterTypeReg
;
1129 if (sFilterTypeReg
!= sType
)
1131 sLog
.append("error\t:\t" "The preferred filter \"" +
1132 sPrefFilter
+ "\" of type \"" + sType
+
1133 "\" is registered for another type \"" + sFilterTypeReg
+
1138 sal_Int32 nFlags
= 0;
1139 aPrefFilter
[PROPNAME_FLAGS
] >>= nFlags
;
1140 if (!(static_cast<SfxFilterFlags
>(nFlags
) & SfxFilterFlags::IMPORT
))
1142 sLog
.append("error\t:\t" "The preferred filter \"" + sPrefFilter
+ "\" of type \"" +
1143 sType
+ "\" is not an IMPORT filter!\n");
1147 OUString sInternalFilterNameCheck
;
1148 aPrefFilter
[PROPNAME_NAME
] >>= sInternalFilterNameCheck
;
1149 if (sInternalFilterNameCheck
!= sPrefFilter
)
1151 sLog
.append("Warning\t:\t" "The filter \"" + sPrefFilter
+
1152 "\" does support the property \"Name\" correctly.\n");
1159 // create dependencies between the global default frame loader
1160 // and all types (and of course if registered filters), which
1161 // does not registered for any other loader.
1162 css::uno::Any aDirectValue
= impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER
);
1163 OUString sDefaultFrameLoader
;
1166 (!(aDirectValue
>>= sDefaultFrameLoader
)) ||
1167 (sDefaultFrameLoader
.isEmpty() )
1170 sLog
.append("error\t:\t" "There is no valid default frame loader!?\n");
1174 // a) get list of all well known types
1175 // b) step over all well known frame loader services
1176 // and remove all types from list a), which already
1177 // referenced by a loader b)
1178 std::vector
<OUString
> lTypes
= getItemNames(E_TYPE
);
1179 for (auto & frameLoader
: m_lFrameLoaders
)
1181 // Note: of course the default loader must be ignored here.
1182 // Because we replace its registration later completely with all
1183 // types, which are not referenced by any other loader.
1184 // So we can avoid our code against the complexity of a diff!
1185 OUString sLoader
= frameLoader
.first
;
1186 if (sLoader
== sDefaultFrameLoader
)
1189 CacheItem
& rLoader
= frameLoader
.second
;
1190 css::uno::Any
& rTypesReg
= rLoader
[PROPNAME_TYPES
];
1191 const css::uno::Sequence
<OUString
> lTypesReg
= rTypesReg
.get
<css::uno::Sequence
<OUString
> >();
1193 for (auto const& typeReg
: lTypesReg
)
1195 auto pTypeCheck
= ::std::find(lTypes
.begin(), lTypes
.end(), typeReg
);
1196 if (pTypeCheck
!= lTypes
.end())
1197 lTypes
.erase(pTypeCheck
);
1201 CacheItem
& rDefaultLoader
= m_lFrameLoaders
[sDefaultFrameLoader
];
1202 rDefaultLoader
[PROPNAME_NAME
] <<= sDefaultFrameLoader
;
1203 rDefaultLoader
[PROPNAME_TYPES
] <<= comphelper::containerToSequence(lTypes
);
1205 OUString sLogOut
= sLog
.makeStringAndClear();
1206 OSL_ENSURE(!nErrors
, OUStringToOString(sLogOut
,RTL_TEXTENCODING_UTF8
).getStr());
1208 throw css::document::CorruptedFilterConfigurationException(
1209 "filter configuration: " + sLogOut
,
1210 css::uno::Reference
< css::uno::XInterface
>(),
1212 #if OSL_DEBUG_LEVEL > 0
1213 OSL_ENSURE(!nWarnings
, OUStringToOString(sLogOut
,RTL_TEXTENCODING_UTF8
).getStr());
1219 void FilterCache::impl_addItem2FlushList( EItemType eType
,
1220 const OUString
& sItem
)
1222 std::vector
<OUString
>* pList
= nullptr;
1226 pList
= &m_lChangedTypes
;
1230 pList
= &m_lChangedFilters
;
1233 case E_FRAMELOADER
:
1234 pList
= &m_lChangedFrameLoaders
;
1237 case E_CONTENTHANDLER
:
1238 pList
= &m_lChangedContentHandlers
;
1241 default : throw css::uno::RuntimeException(u
"unsupported item type"_ustr
, nullptr);
1244 auto pItem
= ::std::find(pList
->cbegin(), pList
->cend(), sItem
);
1245 if (pItem
== pList
->cend())
1246 pList
->push_back(sItem
);
1249 FilterCache::EItemFlushState
FilterCache::impl_specifyFlushOperation(const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
1250 const CacheItemList
& rList
,
1251 const OUString
& sItem
)
1253 bool bExistsInConfigLayer
= xSet
->hasByName(sItem
);
1254 bool bExistsInMemory
= (rList
.find(sItem
) != rList
.end());
1256 EItemFlushState
eState( E_ITEM_UNCHANGED
);
1258 // !? ... such situation can occur, if an item was added and(!) removed before it was flushed :-)
1259 if (!bExistsInConfigLayer
&& !bExistsInMemory
)
1260 eState
= E_ITEM_UNCHANGED
;
1261 else if (!bExistsInConfigLayer
&& bExistsInMemory
)
1262 eState
= E_ITEM_ADDED
;
1263 else if (bExistsInConfigLayer
&& bExistsInMemory
)
1264 eState
= E_ITEM_CHANGED
;
1265 else if (bExistsInConfigLayer
&& !bExistsInMemory
)
1266 eState
= E_ITEM_REMOVED
;
1271 void FilterCache::impl_load(EFillState eRequiredState
)
1274 osl::MutexGuard
aLock(m_aMutex
);
1276 // Attention: Detect services are part of the standard set!
1277 // So there is no need to handle it separately.
1280 // a) The standard set of config value is needed.
1282 ((eRequiredState
& E_CONTAINS_STANDARD
) == E_CONTAINS_STANDARD
) &&
1283 ((m_eFillState
& E_CONTAINS_STANDARD
) != E_CONTAINS_STANDARD
)
1286 // Attention! If config couldn't be opened successfully
1287 // and exception is thrown automatically and must be forwarded
1289 css::uno::Reference
< css::container::XNameAccess
> xTypes(impl_openConfig(E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
1291 SAL_INFO( "filter.config", "FilterCache::load std");
1292 impl_loadSet(xTypes
, E_TYPE
, E_READ_STANDARD
, &m_lTypes
);
1297 // b) We need all type information ...
1299 ((eRequiredState
& E_CONTAINS_TYPES
) == E_CONTAINS_TYPES
) &&
1300 ((m_eFillState
& E_CONTAINS_TYPES
) != E_CONTAINS_TYPES
)
1303 // Attention! If config couldn't be opened successfully
1304 // and exception is thrown automatically and must be forwarded
1306 css::uno::Reference
< css::container::XNameAccess
> xTypes(impl_openConfig(E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
1308 SAL_INFO( "filter.config", "FilterCache::load all types");
1309 impl_loadSet(xTypes
, E_TYPE
, E_READ_UPDATE
, &m_lTypes
);
1314 // c) We need all filter information ...
1316 ((eRequiredState
& E_CONTAINS_FILTERS
) == E_CONTAINS_FILTERS
) &&
1317 ((m_eFillState
& E_CONTAINS_FILTERS
) != E_CONTAINS_FILTERS
)
1320 // Attention! If config couldn't be opened successfully
1321 // and exception is thrown automatically and must be forwarded
1323 css::uno::Reference
< css::container::XNameAccess
> xFilters(impl_openConfig(E_PROVIDER_FILTERS
), css::uno::UNO_QUERY_THROW
);
1325 SAL_INFO( "filter.config", "FilterCache::load all filters");
1326 impl_loadSet(xFilters
, E_FILTER
, E_READ_ALL
, &m_lFilters
);
1331 // c) We need all frame loader information ...
1333 ((eRequiredState
& E_CONTAINS_FRAMELOADERS
) == E_CONTAINS_FRAMELOADERS
) &&
1334 ((m_eFillState
& E_CONTAINS_FRAMELOADERS
) != E_CONTAINS_FRAMELOADERS
)
1337 // Attention! If config couldn't be opened successfully
1338 // and exception is thrown automatically and must be forwarded
1340 css::uno::Reference
< css::container::XNameAccess
> xLoaders(impl_openConfig(E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
1342 SAL_INFO( "filter.config", "FilterCache::load all frame loader");
1343 impl_loadSet(xLoaders
, E_FRAMELOADER
, E_READ_ALL
, &m_lFrameLoaders
);
1348 // d) We need all content handler information...
1350 ((eRequiredState
& E_CONTAINS_CONTENTHANDLERS
) == E_CONTAINS_CONTENTHANDLERS
) &&
1351 ((m_eFillState
& E_CONTAINS_CONTENTHANDLERS
) != E_CONTAINS_CONTENTHANDLERS
)
1354 // Attention! If config couldn't be opened successfully
1355 // and exception is thrown automatically and must be forwarded
1357 css::uno::Reference
< css::container::XNameAccess
> xHandlers(impl_openConfig(E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
1359 SAL_INFO( "filter.config", "FilterCache::load all content handler");
1360 impl_loadSet(xHandlers
, E_CONTENTHANDLER
, E_READ_ALL
, &m_lContentHandlers
);
1364 // update fill state. Note: it's a bit field, which combines different parts.
1365 m_eFillState
= static_cast<EFillState
>(static_cast<sal_Int32
>(m_eFillState
) | static_cast<sal_Int32
>(eRequiredState
));
1368 // yes! => validate it and update optimized structures.
1369 impl_validateAndOptimize();
1374 void FilterCache::impl_loadSet(const css::uno::Reference
< css::container::XNameAccess
>& xConfig
,
1376 EReadOption eOption
,
1377 CacheItemList
* pCache
)
1379 // get access to the right configuration set
1384 sSetName
= CFGSET_TYPES
;
1388 sSetName
= CFGSET_FILTERS
;
1391 case E_FRAMELOADER
:
1392 sSetName
= CFGSET_FRAMELOADERS
;
1395 case E_CONTENTHANDLER
:
1396 sSetName
= CFGSET_CONTENTHANDLERS
;
1401 css::uno::Reference
< css::container::XNameAccess
> xSet
;
1402 css::uno::Sequence
< OUString
> lItems
;
1406 css::uno::Any aVal
= xConfig
->getByName(sSetName
);
1407 if (!(aVal
>>= xSet
) || !xSet
.is())
1409 OUString
sMsg("Could not open configuration set \"" + sSetName
+ "\".");
1410 throw css::uno::Exception(sMsg
, css::uno::Reference
< css::uno::XInterface
>());
1412 lItems
= xSet
->getElementNames();
1414 catch(const css::uno::Exception
& ex
)
1416 throw css::document::CorruptedFilterConfigurationException(
1417 "filter configuration, caught: " + ex
.Message
,
1418 css::uno::Reference
< css::uno::XInterface
>(),
1422 // get names of all existing sub items of this set
1423 // step over it and fill internal cache structures.
1425 // But don't update optimized structures like e.g. hash
1426 // for mapping extensions to its types!
1428 const OUString
* pItems
= lItems
.getConstArray();
1429 sal_Int32 c
= lItems
.getLength();
1430 for (sal_Int32 i
=0; i
<c
; ++i
)
1432 CacheItemList::iterator pItem
= pCache
->find(pItems
[i
]);
1435 // a) read a standard set of properties only or read all
1436 case E_READ_STANDARD
:
1441 (*pCache
)[pItems
[i
]] = impl_loadItem(xSet
, eType
, pItems
[i
], eOption
);
1443 catch(const css::uno::Exception
& ex
)
1445 throw css::document::CorruptedFilterConfigurationException(
1446 "filter configuration, caught: " + ex
.Message
,
1447 css::uno::Reference
< css::uno::XInterface
>(),
1453 // b) read optional properties only!
1454 // All items must already exist inside our cache.
1455 // But they must be updated.
1456 case E_READ_UPDATE
:
1458 if (pItem
== pCache
->end())
1460 OUString
sMsg("item \"" + pItems
[i
] + "\" not found for update!");
1461 throw css::uno::Exception(sMsg
, css::uno::Reference
< css::uno::XInterface
>());
1465 CacheItem aItem
= impl_loadItem(xSet
, eType
, pItems
[i
], eOption
);
1466 pItem
->second
.update(aItem
);
1468 catch(const css::uno::Exception
& ex
)
1470 throw css::document::CorruptedFilterConfigurationException(
1471 "filter configuration, caught: " + ex
.Message
,
1472 css::uno::Reference
< css::uno::XInterface
>(),
1482 void FilterCache::impl_readPatchUINames(const css::uno::Reference
< css::container::XNameAccess
>& xNode
,
1486 // SAFE -> ----------------------------------
1487 osl::ClearableMutexGuard
aLock(m_aMutex
);
1488 OUString sActLocale
= m_sActLocale
;
1490 // <- SAFE ----------------------------------
1492 css::uno::Any aVal
= xNode
->getByName(PROPNAME_UINAME
);
1493 css::uno::Reference
< css::container::XNameAccess
> xUIName
;
1494 if (!(aVal
>>= xUIName
) && !xUIName
.is())
1497 const ::std::vector
< OUString
> lLocales(comphelper::sequenceToContainer
< ::std::vector
< OUString
>>(
1498 xUIName
->getElementNames()));
1499 ::std::vector
< OUString
>::const_iterator pLocale
;
1500 ::comphelper::SequenceAsHashMap lUINames
;
1502 for (auto const& locale
: lLocales
)
1505 xUIName
->getByName(locale
) >>= sValue
;
1507 lUINames
[locale
] <<= sValue
;
1510 rItem
[PROPNAME_UINAMES
] <<= lUINames
.getAsConstPropertyValueList();
1512 // find right UIName for current office locale
1513 // Use fallbacks too!
1514 pLocale
= LanguageTag::getFallback(lLocales
, sActLocale
);
1515 if (pLocale
== lLocales
.end())
1517 #if OSL_DEBUG_LEVEL > 0
1518 if ( sActLocale
== "en-US" )
1520 OUString sName
= rItem
.getUnpackedValueOrDefault(PROPNAME_NAME
, OUString());
1522 SAL_WARN("filter.config", "Fallback scenario for filter or type '" << sName
<< "' and locale '" <<
1523 sActLocale
<< "' failed. Please check your filter configuration.");
1528 const OUString
& sLocale
= *pLocale
;
1529 ::comphelper::SequenceAsHashMap::const_iterator pUIName
= lUINames
.find(sLocale
);
1530 if (pUIName
!= lUINames
.end())
1531 rItem
[PROPNAME_UINAME
] = pUIName
->second
;
1534 void FilterCache::impl_savePatchUINames(const css::uno::Reference
< css::container::XNameReplace
>& xNode
,
1535 const CacheItem
& rItem
)
1537 css::uno::Reference
< css::container::XNameContainer
> xAdd (xNode
, css::uno::UNO_QUERY
);
1539 css::uno::Sequence
< css::beans::PropertyValue
> lUINames
= rItem
.getUnpackedValueOrDefault(PROPNAME_UINAMES
, css::uno::Sequence
< css::beans::PropertyValue
>());
1540 sal_Int32 c
= lUINames
.getLength();
1541 const css::beans::PropertyValue
* pUINames
= lUINames
.getConstArray();
1543 for (sal_Int32 i
=0; i
<c
; ++i
)
1545 if (xNode
->hasByName(pUINames
[i
].Name
))
1546 xNode
->replaceByName(pUINames
[i
].Name
, pUINames
[i
].Value
);
1548 xAdd
->insertByName(pUINames
[i
].Name
, pUINames
[i
].Value
);
1552 /*-----------------------------------------------
1554 clarify, how the real problem behind the
1555 wrong constructed CacheItem instance (which
1556 will force a crash during destruction)
1558 -----------------------------------------------*/
1559 CacheItem
FilterCache::impl_loadItem(const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
1561 const OUString
& sItem
,
1562 EReadOption eOption
)
1564 // try to get an API object, which points directly to the
1565 // requested item. If it fail an exception should occur and
1566 // break this operation. Of course returned API object must be
1568 css::uno::Reference
< css::container::XNameAccess
> xItem
;
1569 css::uno::Any aVal
= xSet
->getByName(sItem
);
1570 if (!(aVal
>>= xItem
) || !xItem
.is())
1572 throw css::uno::RuntimeException("found corrupted item \"" + sItem
+ "\".",
1573 css::uno::Reference
< css::uno::XInterface
>());
1576 // set too. Of course it's already used as key into the e.g. outside
1577 // used hash map... but some of our API methods provide
1578 // this property set as result only. But the user of this CacheItem
1579 // should know, which value the key names has :-) IT'S IMPORTANT!
1581 aItem
[PROPNAME_NAME
] <<= sItem
;
1586 assert(eOption
>= 0 && eOption
<= E_READ_ALL
);
1587 css::uno::Sequence
< OUString
> &rNames
= m_aTypeProps
[eOption
];
1589 // read standard properties of a filter
1590 if (rNames
.hasElements())
1592 css::uno::Reference
< css::beans::XMultiPropertySet
>
1593 xPropSet( xItem
, css::uno::UNO_QUERY_THROW
);
1594 css::uno::Sequence
< css::uno::Any
> aValues
= xPropSet
->getPropertyValues(rNames
);
1596 for (sal_Int32 i
= 0; i
< aValues
.getLength(); i
++)
1597 aItem
[rNames
[i
]] = aValues
[i
];
1600 // read optional properties of a type
1601 // no else here! Is an additional switch ...
1602 if (eOption
== E_READ_UPDATE
|| eOption
== E_READ_ALL
)
1603 impl_readPatchUINames(xItem
, aItem
);
1610 assert(eOption
>= 0 && eOption
<= E_READ_ALL
);
1611 css::uno::Sequence
< OUString
> &rNames
= m_aStandardProps
[eOption
];
1613 // read standard properties of a filter
1614 if (rNames
.hasElements())
1616 css::uno::Reference
< css::beans::XMultiPropertySet
>
1617 xPropSet( xItem
, css::uno::UNO_QUERY_THROW
);
1618 css::uno::Sequence
< css::uno::Any
> aValues
= xPropSet
->getPropertyValues(rNames
);
1620 for (sal_Int32 i
= 0; i
< rNames
.getLength(); i
++)
1622 const OUString
&rPropName
= rNames
[i
];
1623 if (i
!= rNames
.getLength() - 1 || rPropName
!= PROPNAME_FLAGS
)
1624 aItem
[rPropName
] = aValues
[i
];
1627 assert(rPropName
== PROPNAME_FLAGS
);
1628 // special handling for flags! Convert it from a list of names to its
1629 // int representation ...
1630 css::uno::Sequence
< OUString
> lFlagNames
;
1631 if (aValues
[i
] >>= lFlagNames
)
1632 aItem
[rPropName
] <<= static_cast<sal_Int32
>(FilterCache::impl_convertFlagNames2FlagField(lFlagNames
));
1636 //TODO remove it if moving of filter uinames to type uinames
1637 // will be finished really
1638 #ifdef AS_ENABLE_FILTER_UINAMES
1639 if (eOption
== E_READ_UPDATE
|| eOption
== E_READ_ALL
)
1640 impl_readPatchUINames(xItem
, aItem
);
1641 #endif // AS_ENABLE_FILTER_UINAMES
1645 case E_FRAMELOADER
:
1646 case E_CONTENTHANDLER
:
1647 aItem
[PROPNAME_TYPES
] = xItem
->getByName(PROPNAME_TYPES
);
1655 CacheItemList::iterator
FilterCache::impl_loadItemOnDemand( EItemType eType
,
1656 const OUString
& sItem
)
1658 CacheItemList
* pList
= nullptr;
1659 css::uno::Reference
< css::uno::XInterface
> xConfig
;
1667 xConfig
= impl_openConfig(E_PROVIDER_TYPES
);
1668 sSet
= CFGSET_TYPES
;
1674 pList
= &m_lFilters
;
1675 xConfig
= impl_openConfig(E_PROVIDER_FILTERS
);
1676 sSet
= CFGSET_FILTERS
;
1680 case E_FRAMELOADER
:
1682 pList
= &m_lFrameLoaders
;
1683 xConfig
= impl_openConfig(E_PROVIDER_OTHERS
);
1684 sSet
= CFGSET_FRAMELOADERS
;
1688 case E_CONTENTHANDLER
:
1690 pList
= &m_lContentHandlers
;
1691 xConfig
= impl_openConfig(E_PROVIDER_OTHERS
);
1692 sSet
= CFGSET_CONTENTHANDLERS
;
1698 throw css::container::NoSuchElementException();
1700 css::uno::Reference
< css::container::XNameAccess
> xRoot(xConfig
, css::uno::UNO_QUERY_THROW
);
1701 css::uno::Reference
< css::container::XNameAccess
> xSet
;
1702 xRoot
->getByName(sSet
) >>= xSet
;
1704 CacheItemList::iterator pItemInCache
= pList
->find(sItem
);
1705 bool bItemInConfig
= xSet
->hasByName(sItem
);
1709 (*pList
)[sItem
] = impl_loadItem(xSet
, eType
, sItem
, E_READ_ALL
);
1713 if (pItemInCache
!= pList
->end())
1714 pList
->erase(pItemInCache
);
1715 // OK - this item does not exists inside configuration.
1716 // And we already updated our internal cache.
1717 // But the outside code needs this NoSuchElementException
1718 // to know, that this item does notexists.
1719 // Nobody checks the iterator!
1720 throw css::container::NoSuchElementException();
1723 return pList
->find(sItem
);
1726 void FilterCache::impl_saveItem(const css::uno::Reference
< css::container::XNameReplace
>& xItem
,
1728 const CacheItem
& aItem
)
1730 // This function changes the properties of aItem one-by-one; but it also
1731 // listens to the configuration changes and reloads the whole item from the
1732 // configuration on change, so use a copy of aItem throughout:
1733 CacheItem
copiedItem(aItem
);
1735 CacheItem::const_iterator pIt
;
1741 pIt
= copiedItem
.find(PROPNAME_PREFERREDFILTER
);
1742 if (pIt
!= copiedItem
.end())
1743 xItem
->replaceByName(PROPNAME_PREFERREDFILTER
, pIt
->second
);
1744 pIt
= copiedItem
.find(PROPNAME_DETECTSERVICE
);
1745 if (pIt
!= copiedItem
.end())
1746 xItem
->replaceByName(PROPNAME_DETECTSERVICE
, pIt
->second
);
1747 pIt
= copiedItem
.find(PROPNAME_URLPATTERN
);
1748 if (pIt
!= copiedItem
.end())
1749 xItem
->replaceByName(PROPNAME_URLPATTERN
, pIt
->second
);
1750 pIt
= copiedItem
.find(PROPNAME_EXTENSIONS
);
1751 if (pIt
!= copiedItem
.end())
1752 xItem
->replaceByName(PROPNAME_EXTENSIONS
, pIt
->second
);
1753 pIt
= copiedItem
.find(PROPNAME_PREFERRED
);
1754 if (pIt
!= copiedItem
.end())
1755 xItem
->replaceByName(PROPNAME_PREFERRED
, pIt
->second
);
1756 pIt
= copiedItem
.find(PROPNAME_MEDIATYPE
);
1757 if (pIt
!= copiedItem
.end())
1758 xItem
->replaceByName(PROPNAME_MEDIATYPE
, pIt
->second
);
1759 pIt
= copiedItem
.find(PROPNAME_CLIPBOARDFORMAT
);
1760 if (pIt
!= copiedItem
.end())
1761 xItem
->replaceByName(PROPNAME_CLIPBOARDFORMAT
, pIt
->second
);
1763 css::uno::Reference
< css::container::XNameReplace
> xUIName
;
1764 xItem
->getByName(PROPNAME_UINAME
) >>= xUIName
;
1765 impl_savePatchUINames(xUIName
, copiedItem
);
1772 pIt
= copiedItem
.find(PROPNAME_TYPE
);
1773 if (pIt
!= copiedItem
.end())
1774 xItem
->replaceByName(PROPNAME_TYPE
, pIt
->second
);
1775 pIt
= copiedItem
.find(PROPNAME_FILEFORMATVERSION
);
1776 if (pIt
!= copiedItem
.end())
1777 xItem
->replaceByName(PROPNAME_FILEFORMATVERSION
, pIt
->second
);
1778 pIt
= copiedItem
.find(PROPNAME_UICOMPONENT
);
1779 if (pIt
!= copiedItem
.end())
1780 xItem
->replaceByName(PROPNAME_UICOMPONENT
, pIt
->second
);
1781 pIt
= copiedItem
.find(PROPNAME_FILTERSERVICE
);
1782 if (pIt
!= copiedItem
.end())
1783 xItem
->replaceByName(PROPNAME_FILTERSERVICE
, pIt
->second
);
1784 pIt
= copiedItem
.find(PROPNAME_DOCUMENTSERVICE
);
1785 if (pIt
!= copiedItem
.end())
1786 xItem
->replaceByName(PROPNAME_DOCUMENTSERVICE
, pIt
->second
);
1787 pIt
= copiedItem
.find(PROPNAME_USERDATA
);
1788 if (pIt
!= copiedItem
.end())
1789 xItem
->replaceByName(PROPNAME_USERDATA
, pIt
->second
);
1790 pIt
= copiedItem
.find(PROPNAME_TEMPLATENAME
);
1791 if (pIt
!= copiedItem
.end())
1792 xItem
->replaceByName(PROPNAME_TEMPLATENAME
, pIt
->second
);
1794 // special handling for flags! Convert it from an integer flag field back
1795 // to a list of names ...
1796 pIt
= copiedItem
.find(PROPNAME_FLAGS
);
1797 if (pIt
!= copiedItem
.end())
1799 sal_Int32 nFlags
= 0;
1800 pIt
->second
>>= nFlags
;
1801 css::uno::Any aFlagNameList
;
1802 aFlagNameList
<<= FilterCache::impl_convertFlagField2FlagNames(static_cast<SfxFilterFlags
>(nFlags
));
1803 xItem
->replaceByName(PROPNAME_FLAGS
, aFlagNameList
);
1806 //TODO remove it if moving of filter uinames to type uinames
1807 // will be finished really
1808 #ifdef AS_ENABLE_FILTER_UINAMES
1809 css::uno::Reference
< css::container::XNameReplace
> xUIName
;
1810 xItem
->getByName(PROPNAME_UINAME
) >>= xUIName
;
1811 impl_savePatchUINames(xUIName
, copiedItem
);
1812 #endif // AS_ENABLE_FILTER_UINAMES
1817 case E_FRAMELOADER
:
1818 case E_CONTENTHANDLER
:
1820 pIt
= copiedItem
.find(PROPNAME_TYPES
);
1821 if (pIt
!= copiedItem
.end())
1822 xItem
->replaceByName(PROPNAME_TYPES
, pIt
->second
);
1831 SfxFilterFlags eFlag
;
1833 } flagFilterSwitcher
[] = {
1834 { SfxFilterFlags::STARONEFILTER
, FLAGNAME_3RDPARTYFILTER
},
1835 { SfxFilterFlags::ALIEN
, FLAGNAME_ALIEN
},
1836 { SfxFilterFlags::CONSULTSERVICE
, FLAGNAME_CONSULTSERVICE
},
1837 { SfxFilterFlags::DEFAULT
, FLAGNAME_DEFAULT
},
1838 { SfxFilterFlags::ENCRYPTION
, FLAGNAME_ENCRYPTION
},
1839 { SfxFilterFlags::EXPORT
, FLAGNAME_EXPORT
},
1840 { SfxFilterFlags::IMPORT
, FLAGNAME_IMPORT
},
1841 { SfxFilterFlags::INTERNAL
, FLAGNAME_INTERNAL
},
1842 { SfxFilterFlags::NOTINFILEDLG
, FLAGNAME_NOTINFILEDIALOG
},
1843 { SfxFilterFlags::MUSTINSTALL
, FLAGNAME_NOTINSTALLED
},
1844 { SfxFilterFlags::OWN
, FLAGNAME_OWN
},
1845 { SfxFilterFlags::PACKED
, FLAGNAME_PACKED
},
1846 { SfxFilterFlags::PASSWORDTOMODIFY
, FLAGNAME_PASSWORDTOMODIFY
},
1847 { SfxFilterFlags::PREFERED
, FLAGNAME_PREFERRED
},
1848 { SfxFilterFlags::STARTPRESENTATION
, FLAGNAME_STARTPRESENTATION
},
1849 { SfxFilterFlags::OPENREADONLY
, FLAGNAME_READONLY
},
1850 { SfxFilterFlags::SUPPORTSSELECTION
, FLAGNAME_SUPPORTSSELECTION
},
1851 { SfxFilterFlags::TEMPLATE
, FLAGNAME_TEMPLATE
},
1852 { SfxFilterFlags::TEMPLATEPATH
, FLAGNAME_TEMPLATEPATH
},
1853 { SfxFilterFlags::COMBINED
, FLAGNAME_COMBINED
},
1854 { SfxFilterFlags::SUPPORTSSIGNING
, FLAGNAME_SUPPORTSSIGNING
},
1855 { SfxFilterFlags::GPGENCRYPTION
, FLAGNAME_GPGENCRYPTION
},
1856 { SfxFilterFlags::EXOTIC
, FLAGNAME_EXOTIC
},
1860 /*-----------------------------------------------
1861 static! => no locks necessary
1862 -----------------------------------------------*/
1863 css::uno::Sequence
< OUString
> FilterCache::impl_convertFlagField2FlagNames(SfxFilterFlags nFlags
)
1865 std::vector
<OUString
> lFlagNames
;
1867 for (const auto& [eFlag
, aName
] : flagFilterSwitcher
)
1870 lFlagNames
.emplace_back(aName
);
1873 return comphelper::containerToSequence(lFlagNames
);
1876 /*-----------------------------------------------
1877 static! => no locks necessary
1878 -----------------------------------------------*/
1879 SfxFilterFlags
FilterCache::impl_convertFlagNames2FlagField(const css::uno::Sequence
< OUString
>& lNames
)
1881 SfxFilterFlags nField
= SfxFilterFlags::NONE
;
1883 const OUString
* pNames
= lNames
.getConstArray();
1884 sal_Int32 c
= lNames
.getLength();
1885 for (sal_Int32 i
=0; i
<c
; ++i
)
1887 for (const auto& [eFlag
, aName
] : flagFilterSwitcher
)
1889 if (pNames
[i
] == aName
) {
1900 void FilterCache::impl_interpretDataVal4Type(const OUString
& sValue
,
1907 case 0: rItem
[PROPNAME_PREFERRED
] <<= (sValue
.toInt32() == 1);
1910 case 1: rItem
[PROPNAME_MEDIATYPE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1913 case 2: rItem
[PROPNAME_CLIPBOARDFORMAT
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1916 case 3: rItem
[PROPNAME_URLPATTERN
] <<= comphelper::containerToSequence(impl_tokenizeString(sValue
, ';'));
1919 case 4: rItem
[PROPNAME_EXTENSIONS
] <<= comphelper::containerToSequence(impl_tokenizeString(sValue
, ';'));
1925 void FilterCache::impl_interpretDataVal4Filter(const OUString
& sValue
,
1933 sal_Int32 nOrder
= sValue
.toInt32();
1936 SAL_WARN( "filter.config", "FilterCache::impl_interpretDataVal4Filter()\nCan not move Order value from filter to type on demand!");
1941 case 1: rItem
[PROPNAME_TYPE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1944 case 2: rItem
[PROPNAME_DOCUMENTSERVICE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1947 case 3: rItem
[PROPNAME_FILTERSERVICE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1950 case 4: rItem
[PROPNAME_FLAGS
] <<= sValue
.toInt32();
1953 case 5: rItem
[PROPNAME_USERDATA
] <<= comphelper::containerToSequence(impl_tokenizeString(sValue
, ';'));
1955 // FileFormatVersion
1956 case 6: rItem
[PROPNAME_FILEFORMATVERSION
] <<= sValue
.toInt32();
1959 case 7: rItem
[PROPNAME_TEMPLATENAME
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1961 // [optional!] UIComponent
1962 case 8: rItem
[PROPNAME_UICOMPONENT
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1967 /*-----------------------------------------------
1968 TODO work on a cache copy first, which can be flushed afterwards
1969 That would be useful to guarantee a consistent cache.
1970 -----------------------------------------------*/
1971 void FilterCache::impl_readOldFormat()
1973 // Attention: Opening/Reading of this old configuration format has to be handled gracefully.
1974 // It's optional and should not disturb our normal work!
1975 // E.g. we must check, if the package exists...
1978 css::uno::Reference
< css::uno::XInterface
> xInt
= impl_openConfig(E_PROVIDER_OLD
);
1979 css::uno::Reference
< css::container::XNameAccess
> xCfg(xInt
, css::uno::UNO_QUERY_THROW
);
1981 OUString
TYPES_SET(u
"Types"_ustr
);
1983 // May be there is no type set ...
1984 if (xCfg
->hasByName(TYPES_SET
))
1986 css::uno::Reference
< css::container::XNameAccess
> xSet
;
1987 xCfg
->getByName(TYPES_SET
) >>= xSet
;
1988 const css::uno::Sequence
< OUString
> lItems
= xSet
->getElementNames();
1989 for (const OUString
& rName
: lItems
)
1990 m_lTypes
[rName
] = impl_readOldItem(xSet
, E_TYPE
, rName
);
1993 OUString
FILTER_SET(u
"Filters"_ustr
);
1994 // May be there is no filter set ...
1995 if (xCfg
->hasByName(FILTER_SET
))
1997 css::uno::Reference
< css::container::XNameAccess
> xSet
;
1998 xCfg
->getByName(FILTER_SET
) >>= xSet
;
1999 const css::uno::Sequence
< OUString
> lItems
= xSet
->getElementNames();
2000 for (const OUString
& rName
: lItems
)
2001 m_lFilters
[rName
] = impl_readOldItem(xSet
, E_FILTER
, rName
);
2004 /* corrupt filter addon? Because it's external (optional) code... we can ignore it. Addon won't work then...
2005 but that seems to be acceptable.
2006 see #139088# for further information
2008 catch(const css::uno::Exception
&)
2013 CacheItem
FilterCache::impl_readOldItem(const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
2015 const OUString
& sItem
)
2017 css::uno::Reference
< css::container::XNameAccess
> xItem
;
2018 xSet
->getByName(sItem
) >>= xItem
;
2020 throw css::uno::Exception(u
"Can not read old item."_ustr
, css::uno::Reference
< css::uno::XInterface
>());
2023 aItem
[PROPNAME_NAME
] <<= sItem
;
2025 // Installed flag ...
2026 // Isn't used any longer!
2029 impl_readPatchUINames(xItem
, aItem
);
2033 std::vector
<OUString
> lData
;
2034 xItem
->getByName( u
"Data"_ustr
) >>= sData
;
2035 lData
= impl_tokenizeString(sData
, ',');
2037 (sData
.isEmpty()) ||
2041 throw css::uno::Exception( u
"Can not read old item property DATA."_ustr
, css::uno::Reference
< css::uno::XInterface
>());
2044 sal_Int32 nProp
= 0;
2045 for (auto const& prop
: lData
)
2050 impl_interpretDataVal4Type(prop
, nProp
, aItem
);
2054 impl_interpretDataVal4Filter(prop
, nProp
, aItem
);
2065 std::vector
<OUString
> FilterCache::impl_tokenizeString(std::u16string_view sData
,
2066 sal_Unicode cSeparator
)
2068 std::vector
<OUString
> lData
;
2069 sal_Int32 nToken
= 0;
2072 OUString
sToken( o3tl::getToken(sData
, 0, cSeparator
, nToken
) );
2073 lData
.push_back(sToken
);
2079 #if OSL_DEBUG_LEVEL > 0
2082 OUString
FilterCache::impl_searchFrameLoaderForType(const OUString
& sType
) const
2084 for (auto const& frameLoader
: m_lFrameLoaders
)
2086 const OUString
& sItem
= frameLoader
.first
;
2087 ::comphelper::SequenceAsHashMap
lProps(frameLoader
.second
);
2088 const css::uno::Sequence
<OUString
> lTypes
=
2089 lProps
[PROPNAME_TYPES
].get
<css::uno::Sequence
<OUString
> >();
2091 if (::std::find(lTypes
.begin(), lTypes
.end(), sType
) != lTypes
.end())
2099 OUString
FilterCache::impl_searchContentHandlerForType(const OUString
& sType
) const
2101 for (auto const& contentHandler
: m_lContentHandlers
)
2103 const OUString
& sItem
= contentHandler
.first
;
2104 ::comphelper::SequenceAsHashMap
lProps(contentHandler
.second
);
2105 const css::uno::Sequence
<OUString
> lTypes
=
2106 lProps
[PROPNAME_TYPES
].get
<css::uno::Sequence
<OUString
> >();
2107 if (::std::find(lTypes
.begin(), lTypes
.end(), sType
) != lTypes
.end())
2116 bool FilterCache::impl_isModuleInstalled(const OUString
& sModule
)
2118 css::uno::Reference
< css::container::XNameAccess
> xCfg
;
2122 osl::MutexGuard
aLock(m_aMutex
);
2123 if (!m_xModuleCfg
.is())
2125 m_xModuleCfg
= officecfg::Setup::Office::Factories::get();
2128 xCfg
= m_xModuleCfg
;
2133 return xCfg
->hasByName(sModule
);
2138 } // namespace filter
2140 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */