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 std::unique_lock
aGuard(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 std::unique_lock
aGuard(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(aGuard
);
196 // <- SAFE ----------------------------------
199 void FilterCache::load(EFillState eRequired
)
201 // SAFE -> ----------------------------------
202 std::unique_lock
aGuard(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(aGuard
, 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(aGuard
);
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(aGuard
, eRequired
);
238 bool FilterCache::isFillState(FilterCache::EFillState eState
) const
241 std::unique_lock
aGuard(m_aMutex
);
242 return ((m_eFillState
& eState
) == eState
);
247 std::vector
<OUString
> FilterCache::getMatchingItemsByProps( EItemType eType
,
248 o3tl::span
< const css::beans::NamedValue
> lIProps
,
249 o3tl::span
< const css::beans::NamedValue
> lEProps
) const
252 std::unique_lock
aGuard(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(aGuard
, 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 std::unique_lock
aGuard(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(aGuard
, eType
);
290 return !rList
.empty();
295 std::vector
<OUString
> FilterCache::getItemNames(EItemType eType
) const
298 std::unique_lock
aGuard(m_aMutex
);
299 return getItemNames(aGuard
, eType
);
303 std::vector
<OUString
> FilterCache::getItemNames(std::unique_lock
<std::mutex
>& rGuard
, EItemType eType
) const
305 // search for right list
306 // An exception is thrown - "eType" is unknown.
307 // => rList will be valid everytimes next line is reached.
308 const CacheItemList
& rList
= impl_getItemList(rGuard
, eType
);
310 std::vector
<OUString
> lKeys
;
311 for (auto const& elem
: rList
)
313 lKeys
.push_back(elem
.first
);
319 bool FilterCache::hasItem( EItemType eType
,
320 const OUString
& sItem
)
323 std::unique_lock
aGuard(m_aMutex
);
325 // search for right list
326 // An exception is thrown - "eType" is unknown.
327 // => rList will be valid everytimes next line is reached.
328 const CacheItemList
& rList
= impl_getItemList(aGuard
, eType
);
330 // if item could not be found - check if it can be loaded
331 // from the underlying configuration layer. Might it was not already
332 // loaded into this FilterCache object before.
333 CacheItemList::const_iterator pIt
= rList
.find(sItem
);
334 if (pIt
!= rList
.end())
339 impl_loadItemOnDemand(aGuard
, eType
, sItem
);
340 // no exception => item could be loaded!
343 catch(const css::container::NoSuchElementException
&)
351 CacheItem
FilterCache::getItem( EItemType eType
,
352 const OUString
& sItem
)
355 std::unique_lock
aGuard(m_aMutex
);
357 CacheItem aItem
= impl_getItem(aGuard
, eType
, sItem
);
363 CacheItem
& FilterCache::impl_getItem( std::unique_lock
<std::mutex
>& rGuard
,
365 const OUString
& sItem
)
367 // search for right list
368 // An exception is thrown if "eType" is unknown.
369 // => rList will be valid everytimes next line is reached.
370 CacheItemList
& rList
= impl_getItemList(rGuard
, eType
);
372 // check if item exists ...
373 CacheItemList::iterator pIt
= rList
.find(sItem
);
374 if (pIt
== rList
.end())
376 // ... or load it on demand from the
377 // underlying configuration layer.
378 // Note: NoSuchElementException is thrown automatically here if
379 // item could not be loaded!
380 pIt
= impl_loadItemOnDemand(rGuard
, eType
, sItem
);
383 /* Workaround for #137955#
384 Draw types and filters are installed ... but draw was disabled during setup.
385 We must suppress accessing these filters. Otherwise the office can crash.
386 Solution for the next major release: do not install those filters !
388 if (eType
== E_FILTER
)
390 CacheItem
& rFilter
= pIt
->second
;
391 OUString sDocService
;
392 rFilter
[PROPNAME_DOCUMENTSERVICE
] >>= sDocService
;
394 // In Standalone-Impress the module WriterWeb is not installed
395 // but it is there to load help pages
396 bool bIsHelpFilter
= sItem
== "writer_web_HTML_help";
398 if ( !bIsHelpFilter
&& !impl_isModuleInstalled(rGuard
, sDocService
) )
400 OUString
sMsg("The requested filter '" + sItem
+
401 "' exists ... but it should not; because the corresponding LibreOffice module was not installed.");
402 throw css::container::NoSuchElementException(sMsg
, css::uno::Reference
< css::uno::XInterface
>());
410 void FilterCache::removeItem( EItemType eType
,
411 const OUString
& sItem
)
414 std::unique_lock
aGuard(m_aMutex
);
416 // search for right list
417 // An exception is thrown - "eType" is unknown.
418 // => rList will be valid everytimes next line is reached.
419 CacheItemList
& rList
= impl_getItemList(aGuard
, eType
);
421 CacheItemList::iterator pItem
= rList
.find(sItem
);
422 if (pItem
== rList
.end())
423 pItem
= impl_loadItemOnDemand(aGuard
, eType
, sItem
); // throws NoSuchELementException!
426 impl_addItem2FlushList(eType
, sItem
);
430 void FilterCache::setItem( EItemType eType
,
431 const OUString
& sItem
,
432 const CacheItem
& aValue
)
435 std::unique_lock
aGuard(m_aMutex
);
437 // search for right list
438 // An exception is thrown - "eType" is unknown.
439 // => rList will be valid everytimes next line is reached.
440 CacheItemList
& rList
= impl_getItemList(aGuard
, eType
);
442 // name must be part of the property set too ... otherwise our
443 // container query can't work correctly
444 CacheItem aItem
= aValue
;
445 aItem
[PROPNAME_NAME
] <<= sItem
;
446 aItem
.validateUINames(m_sActLocale
);
448 // remove implicit properties as e.g. FINALIZED or MANDATORY
449 // They can't be saved here and must be read on demand later, if they are needed.
450 removeStatePropsFromItem(aItem
);
452 rList
[sItem
] = aItem
;
454 impl_addItem2FlushList(eType
, sItem
);
458 void FilterCache::refreshItem( EItemType eType
,
459 const OUString
& sItem
)
462 std::unique_lock
aGuard(m_aMutex
);
463 impl_loadItemOnDemand(aGuard
, eType
, sItem
);
467 css::uno::Any
FilterCache::getItemWithStateProps( EItemType eType
,
468 const OUString
& sItem
)
471 std::unique_lock
aGuard(m_aMutex
);
473 const CacheItem
& rItem
= impl_getItem(aGuard
, eType
, sItem
);
475 // Note: Opening of the configuration layer throws some exceptions
476 // if it failed. So we mustn't check any reference here...
477 css::uno::Reference
< css::container::XNameAccess
> xPackage
;
478 css::uno::Reference
< css::container::XNameAccess
> xSet
;
483 xPackage
.set(impl_openConfig(aGuard
, E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
484 xPackage
->getByName(CFGSET_TYPES
) >>= xSet
;
490 xPackage
.set(impl_openConfig(aGuard
, E_PROVIDER_FILTERS
), css::uno::UNO_QUERY_THROW
);
491 xPackage
->getByName(CFGSET_FILTERS
) >>= xSet
;
499 The default frame loader can't be located inside the normal set of frame loaders.
500 It's an atomic property inside the misc cfg package. So we can't retrieve the information
501 about FINALIZED and MANDATORY very easy ... :-(
502 => set it to readonly/required everytimes :-)
504 css::uno::Any aDirectValue
= impl_getDirectCFGValue(aGuard
, CFGDIRECTKEY_DEFAULTFRAMELOADER
);
505 OUString sDefaultFrameLoader
;
507 (aDirectValue
>>= sDefaultFrameLoader
) &&
508 (!sDefaultFrameLoader
.isEmpty() ) &&
509 (sItem
== sDefaultFrameLoader
)
512 css::uno::Sequence aProps
= rItem
.getAsPackedPropertyValueList(true, true);
513 return css::uno::Any(aProps
);
517 xPackage
.set(impl_openConfig(aGuard
, E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
518 xPackage
->getByName(CFGSET_FRAMELOADERS
) >>= xSet
;
522 case E_CONTENTHANDLER
:
524 xPackage
.set(impl_openConfig(aGuard
, E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
525 xPackage
->getByName(CFGSET_CONTENTHANDLERS
) >>= xSet
;
531 bool bFinalized
, bMandatory
;
534 css::uno::Reference
< css::beans::XProperty
> xItem
;
535 xSet
->getByName(sItem
) >>= xItem
;
536 css::beans::Property aDescription
= xItem
->getAsProperty();
538 bFinalized
= ((aDescription
.Attributes
& css::beans::PropertyAttribute::READONLY
) == css::beans::PropertyAttribute::READONLY
);
539 bMandatory
= ((aDescription
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
) != css::beans::PropertyAttribute::REMOVABLE
);
542 catch(const css::container::NoSuchElementException
&)
544 /* Ignore exceptions for missing elements inside configuration.
545 May by the following reason exists:
546 - The item does not exists inside the new configuration package org.openoffice.TypeDetection - but
547 we got it from the old package org.openoffice.Office/TypeDetection. We don't migrate such items
548 automatically to the new format. Because it will disturb e.g. the deinstallation of an external filter
549 package. Because such external filter can remove the old file - but not the automatically created new one ...
551 => mark item as FINALIZED / MANDATORY, we don't support writing to the old format
557 css::uno::Sequence
<css::beans::PropertyValue
> aProps
= rItem
.getAsPackedPropertyValueList(bFinalized
, bMandatory
);
559 return css::uno::Any(aProps
);
564 void FilterCache::removeStatePropsFromItem(CacheItem
& rItem
)
566 CacheItem::iterator pIt
= rItem
.find(PROPNAME_FINALIZED
);
567 if (pIt
!= rItem
.end())
569 pIt
= rItem
.find(PROPNAME_MANDATORY
);
570 if (pIt
!= rItem
.end())
575 void FilterCache::flush()
578 std::unique_lock
aGuard(m_aMutex
);
580 // renew all dependencies and optimizations
581 impl_validateAndOptimize(aGuard
);
583 if (!m_lChangedTypes
.empty())
585 css::uno::Reference
< css::container::XNameAccess
> xConfig(impl_openConfig(aGuard
, E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
586 css::uno::Reference
< css::container::XNameAccess
> xSet
;
588 xConfig
->getByName(CFGSET_TYPES
) >>= xSet
;
589 impl_flushByList(xSet
, E_TYPE
, m_lTypes
, m_lChangedTypes
);
591 css::uno::Reference
< css::util::XChangesBatch
> xFlush(xConfig
, css::uno::UNO_QUERY
);
592 xFlush
->commitChanges();
595 if (!m_lChangedFilters
.empty())
597 css::uno::Reference
< css::container::XNameAccess
> xConfig(impl_openConfig(aGuard
, E_PROVIDER_FILTERS
), css::uno::UNO_QUERY_THROW
);
598 css::uno::Reference
< css::container::XNameAccess
> xSet
;
600 xConfig
->getByName(CFGSET_FILTERS
) >>= xSet
;
601 impl_flushByList(xSet
, E_FILTER
, m_lFilters
, m_lChangedFilters
);
603 css::uno::Reference
< css::util::XChangesBatch
> xFlush(xConfig
, css::uno::UNO_QUERY
);
604 xFlush
->commitChanges();
607 /*TODO FrameLoader/ContentHandler must be flushed here too ... */
611 void FilterCache::impl_flushByList(const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
613 const CacheItemList
& rCache
,
614 const std::vector
<OUString
>& lItems
)
616 css::uno::Reference
< css::container::XNameContainer
> xAddRemoveSet(xSet
, css::uno::UNO_QUERY
);
617 css::uno::Reference
< css::lang::XSingleServiceFactory
> xFactory(xSet
, css::uno::UNO_QUERY
);
619 for (auto const& item
: lItems
)
621 EItemFlushState eState
= impl_specifyFlushOperation(xSet
, rCache
, item
);
624 case E_ITEM_REMOVED
:
626 xAddRemoveSet
->removeByName(item
);
632 css::uno::Reference
< css::container::XNameReplace
> xItem (xFactory
->createInstance(), css::uno::UNO_QUERY
);
634 // special case. no exception - but not a valid item => set must be finalized or mandatory!
635 // Reject flush operation by throwing an exception. At least one item couldn't be flushed.
637 throw css::uno::Exception("Can not add item. Set is finalized or mandatory!",
638 css::uno::Reference
< css::uno::XInterface
>());
640 CacheItemList::const_iterator pItem
= rCache
.find(item
);
641 impl_saveItem(xItem
, eType
, pItem
->second
);
642 xAddRemoveSet
->insertByName(item
, css::uno::Any(xItem
));
646 case E_ITEM_CHANGED
:
648 css::uno::Reference
< css::container::XNameReplace
> xItem
;
649 xSet
->getByName(item
) >>= xItem
;
651 // special case. no exception - but not a valid item => it must be finalized or mandatory!
652 // Reject flush operation by throwing an exception. At least one item couldn't be flushed.
654 throw css::uno::Exception("Can not change item. It's finalized or mandatory!",
655 css::uno::Reference
< css::uno::XInterface
>());
657 CacheItemList::const_iterator pItem
= rCache
.find(item
);
658 impl_saveItem(xItem
, eType
, pItem
->second
);
667 void FilterCache::detectFlatForURL(const css::util::URL
& aURL
,
668 FlatDetection
& rFlatTypes
) const
670 // extract extension from URL, so it can be used directly as key into our hash map!
671 // Note further: It must be converted to lower case, because the optimize hash
672 // (which maps extensions to types) work with lower case key strings!
673 INetURLObject
aParser (aURL
.Main
);
674 OUString sExtension
= aParser
.getExtension(INetURLObject::LAST_SEGMENT
,
676 INetURLObject::DecodeMechanism::WithCharset
);
677 sExtension
= sExtension
.toAsciiLowerCase();
679 // SAFE -> ----------------------------------
680 std::unique_lock
aGuard(m_aMutex
);
683 // i) Step over all well known URL pattern
684 // and add registered types to the return list too
685 // Do it as first one - because: if a type match by a
686 // pattern a following deep detection can be suppressed!
687 // Further we can stop after first match ...
688 for (auto const& pattern
: m_lURLPattern2Types
)
690 WildCard
aPatternCheck(pattern
.first
);
691 if (aPatternCheck
.Matches(aURL
.Main
))
693 const std::vector
<OUString
>& rTypesForPattern
= pattern
.second
;
695 FlatDetectionInfo aInfo
;
696 aInfo
.sType
= *(rTypesForPattern
.begin());
697 aInfo
.bMatchByPattern
= true;
699 rFlatTypes
.push_back(aInfo
);
705 // ii) search types matching to the given extension.
706 // Copy every matching type without changing its order!
707 // Because preferred types was added as first one during
708 // loading configuration.
709 CacheItemRegistration::const_iterator pExtReg
= m_lExtensions2Types
.find(sExtension
);
710 if (pExtReg
!= m_lExtensions2Types
.end())
712 const std::vector
<OUString
>& rTypesForExtension
= pExtReg
->second
;
713 for (auto const& elem
: rTypesForExtension
)
715 FlatDetectionInfo aInfo
;
717 aInfo
.bMatchByExtension
= true;
719 rFlatTypes
.push_back(aInfo
);
723 // <- SAFE ----------------------------------
726 const CacheItemList
& FilterCache::impl_getItemList(std::unique_lock
<std::mutex
>& /*rGuard*/, EItemType eType
) const
730 case E_TYPE
: return m_lTypes
;
731 case E_FILTER
: return m_lFilters
;
732 case E_FRAMELOADER
: return m_lFrameLoaders
;
733 case E_CONTENTHANDLER
: return m_lContentHandlers
;
737 throw css::uno::RuntimeException("unknown sub container requested.",
738 css::uno::Reference
< css::uno::XInterface
>());
741 CacheItemList
& FilterCache::impl_getItemList(std::unique_lock
<std::mutex
>& /*rGuard*/, EItemType eType
)
745 case E_TYPE
: return m_lTypes
;
746 case E_FILTER
: return m_lFilters
;
747 case E_FRAMELOADER
: return m_lFrameLoaders
;
748 case E_CONTENTHANDLER
: return m_lContentHandlers
;
752 throw css::uno::RuntimeException("unknown sub container requested.",
753 css::uno::Reference
< css::uno::XInterface
>());
756 css::uno::Reference
< css::uno::XInterface
> FilterCache::impl_openConfig(std::unique_lock
<std::mutex
>& rGuard
, EConfigProvider eProvider
)
759 css::uno::Reference
< css::uno::XInterface
>* pConfig
= nullptr;
760 css::uno::Reference
< css::uno::XInterface
> xOld
;
765 case E_PROVIDER_TYPES
:
767 if (m_xConfigTypes
.is())
768 return m_xConfigTypes
;
769 sPath
= CFGPACKAGE_TD_TYPES
;
770 pConfig
= &m_xConfigTypes
;
771 sRtlLog
= "impl_openconfig(E_PROVIDER_TYPES)";
775 case E_PROVIDER_FILTERS
:
777 if (m_xConfigFilters
.is())
778 return m_xConfigFilters
;
779 sPath
= CFGPACKAGE_TD_FILTERS
;
780 pConfig
= &m_xConfigFilters
;
781 sRtlLog
= "impl_openconfig(E_PROVIDER_FILTERS)";
785 case E_PROVIDER_OTHERS
:
787 if (m_xConfigOthers
.is())
788 return m_xConfigOthers
;
789 sPath
= CFGPACKAGE_TD_OTHERS
;
790 pConfig
= &m_xConfigOthers
;
791 sRtlLog
= "impl_openconfig(E_PROVIDER_OTHERS)";
795 case E_PROVIDER_OLD
:
797 // This special provider is used to work with
798 // the old configuration format only. It's not cached!
799 sPath
= CFGPACKAGE_TD_OLD
;
801 sRtlLog
= "impl_openconfig(E_PROVIDER_OLD)";
805 default : throw css::uno::RuntimeException("These configuration node is not supported here for open!", nullptr);
809 SAL_INFO( "filter.config", "" << sRtlLog
);
810 *pConfig
= impl_createConfigAccess(rGuard
, sPath
,
812 true ); // bLocalesMode
816 // Start listening for changes on that configuration access.
819 case E_PROVIDER_TYPES
:
821 m_xTypesChglisteners
.set(new CacheUpdateListener(*this, *pConfig
, FilterCache::E_TYPE
));
822 m_xTypesChglisteners
->startListening();
825 case E_PROVIDER_FILTERS
:
827 m_xFiltersChgListener
.set(new CacheUpdateListener(*this, *pConfig
, FilterCache::E_FILTER
));
828 m_xFiltersChgListener
->startListening();
838 css::uno::Any
FilterCache::impl_getDirectCFGValue(std::unique_lock
<std::mutex
>& rGuard
, std::u16string_view sDirectKey
)
844 (!::utl::splitLastFromConfigurationPath(sDirectKey
, sRoot
, sKey
)) ||
845 (sRoot
.isEmpty() ) ||
848 return css::uno::Any();
850 css::uno::Reference
< css::uno::XInterface
> xCfg
= impl_createConfigAccess(rGuard
, sRoot
,
852 false); // bLocalesMode
854 return css::uno::Any();
856 css::uno::Reference
< css::container::XNameAccess
> xAccess(xCfg
, css::uno::UNO_QUERY
);
858 return css::uno::Any();
860 css::uno::Any aValue
;
863 aValue
= xAccess
->getByName(sKey
);
865 catch(const css::uno::RuntimeException
&)
867 catch(const css::uno::Exception
&)
869 TOOLS_WARN_EXCEPTION( "filter.config", "");
877 css::uno::Reference
< css::uno::XInterface
> FilterCache::impl_createConfigAccess(std::unique_lock
<std::mutex
>& /*rGuard*/,
878 const OUString
& sRoot
,
882 css::uno::Reference
< css::uno::XInterface
> xCfg
;
884 if (!utl::ConfigManager::IsFuzzing())
888 css::uno::Reference
< css::lang::XMultiServiceFactory
> xConfigProvider(
889 css::configuration::theDefaultProvider::get( comphelper::getProcessComponentContext() ) );
891 ::std::vector
< css::uno::Any
> lParams
;
892 css::beans::NamedValue aParam
;
895 aParam
.Name
= "nodepath";
896 aParam
.Value
<<= sRoot
;
897 lParams
.push_back(css::uno::Any(aParam
));
899 // enable "all locales mode" ... if required
902 aParam
.Name
= "locale";
903 aParam
.Value
<<= OUString("*");
904 lParams
.push_back(css::uno::Any(aParam
));
909 xCfg
= xConfigProvider
->createInstanceWithArguments(SERVICE_CONFIGURATIONACCESS
,
910 comphelper::containerToSequence(lParams
));
912 xCfg
= xConfigProvider
->createInstanceWithArguments(SERVICE_CONFIGURATIONUPDATEACCESS
,
913 comphelper::containerToSequence(lParams
));
915 // If configuration could not be opened... but factory method did not throw an exception
916 // trigger throwing of our own CorruptedFilterConfigurationException.
917 // Let message empty. The normal exception text show enough information to the user.
919 throw css::uno::Exception(
920 "Got NULL reference on opening configuration file ... but no exception.",
921 css::uno::Reference
< css::uno::XInterface
>());
923 catch(const css::uno::Exception
& ex
)
925 throw css::document::CorruptedFilterConfigurationException(
926 "filter configuration, caught: " + ex
.Message
,
927 css::uno::Reference
< css::uno::XInterface
>(),
936 void FilterCache::impl_validateAndOptimize(std::unique_lock
<std::mutex
>& rGuard
)
938 // First check if any filter or type could be read
939 // from the underlying configuration!
940 bool bSomeTypesShouldExist
= ((m_eFillState
& E_CONTAINS_STANDARD
) == E_CONTAINS_STANDARD
);
941 bool bAllFiltersShouldExist
= ((m_eFillState
& E_CONTAINS_FILTERS
) == E_CONTAINS_FILTERS
);
943 #if OSL_DEBUG_LEVEL > 0
945 sal_Int32 nWarnings
= 0;
947 // sal_Bool bAllTypesShouldExist = ((m_eFillState & E_CONTAINS_TYPES ) == E_CONTAINS_TYPES );
948 bool bAllLoadersShouldExist
= ((m_eFillState
& E_CONTAINS_FRAMELOADERS
) == E_CONTAINS_FRAMELOADERS
);
949 bool bAllHandlersShouldExist
= ((m_eFillState
& E_CONTAINS_CONTENTHANDLERS
) == E_CONTAINS_CONTENTHANDLERS
);
954 bSomeTypesShouldExist
&& m_lTypes
.empty()
957 bAllFiltersShouldExist
&& m_lFilters
.empty()
961 throw css::document::CorruptedFilterConfigurationException(
962 "filter configuration: the list of types or filters is empty",
963 css::uno::Reference
< css::uno::XInterface
>(),
964 "The list of types or filters is empty." );
967 // Create a log for all detected problems, which
968 // occur in the next few lines.
969 // If there are some real errors throw a RuntimException!
970 // If there are some warnings only, show an assertion.
971 sal_Int32 nErrors
= 0;
972 OUStringBuffer
sLog(256);
974 for (auto const& elem
: m_lTypes
)
976 const OUString
& sType
= elem
.first
;
977 const CacheItem
& aType
= elem
.second
;
979 // get its registration for file Extensions AND(!) URLPattern ...
980 // It doesn't matter if these items exists or if our
981 // used index access create some default ones ...
982 // only in case there is no filled set of Extensions AND
983 // no filled set of URLPattern -> we must try to remove this invalid item
985 css::uno::Sequence
< OUString
> lExtensions
;
986 css::uno::Sequence
< OUString
> lURLPattern
;
987 auto it
= aType
.find(PROPNAME_EXTENSIONS
);
988 if (it
!= aType
.end())
989 it
->second
>>= lExtensions
;
990 it
= aType
.find(PROPNAME_URLPATTERN
);
991 if (it
!= aType
.end())
992 it
->second
>>= lURLPattern
;
993 sal_Int32 ce
= lExtensions
.getLength();
994 sal_Int32 cu
= lURLPattern
.getLength();
996 #if OSL_DEBUG_LEVEL > 0
998 OUString sInternalTypeNameCheck
;
999 it
= aType
.find(PROPNAME_NAME
);
1000 if (it
!= aType
.end())
1001 it
->second
>>= sInternalTypeNameCheck
;
1002 if (sInternalTypeNameCheck
!= sType
)
1004 sLog
.append("Warning\t:\t" "The type \"" + sType
+ "\" does support the property \"Name\" correctly.\n");
1010 sLog
.append("Warning\t:\t" "The type \"" + sType
+ "\" does not contain any URL pattern nor any extensions.\n");
1015 // create an optimized registration for this type to
1016 // its set list of extensions/url pattern. If it's a "normal" type
1017 // set it at the end of this optimized list. But if it's
1018 // a "Preferred" one - set it to the front of this list.
1019 // Of course multiple "Preferred" registrations can occur
1020 // (they shouldn't - but they can!) ... Ignore it. The last
1021 // preferred type is usable in the same manner then every
1023 bool bPreferred
= false;
1024 it
= aType
.find(PROPNAME_PREFERRED
);
1025 if (it
!= aType
.end())
1026 it
->second
>>= bPreferred
;
1028 const OUString
* pExtensions
= lExtensions
.getConstArray();
1029 for (sal_Int32 e
=0; e
<ce
; ++e
)
1031 // Note: We must be sure that address the right hash entry
1032 // does not depend from any upper/lower case problems ...
1033 OUString sNormalizedExtension
= pExtensions
[e
].toAsciiLowerCase();
1035 std::vector
<OUString
>& lTypesForExtension
= m_lExtensions2Types
[sNormalizedExtension
];
1036 if (::std::find(lTypesForExtension
.begin(), lTypesForExtension
.end(), sType
) != lTypesForExtension
.end())
1040 lTypesForExtension
.insert(lTypesForExtension
.begin(), sType
);
1042 lTypesForExtension
.push_back(sType
);
1045 const OUString
* pURLPattern
= lURLPattern
.getConstArray();
1046 for (sal_Int32 u
=0; u
<cu
; ++u
)
1048 std::vector
<OUString
>& lTypesForURLPattern
= m_lURLPattern2Types
[pURLPattern
[u
]];
1049 if (::std::find(lTypesForURLPattern
.begin(), lTypesForURLPattern
.end(), sType
) != lTypesForURLPattern
.end())
1053 lTypesForURLPattern
.insert(lTypesForURLPattern
.begin(), sType
);
1055 lTypesForURLPattern
.push_back(sType
);
1058 #if OSL_DEBUG_LEVEL > 0
1060 // Don't check cross references between types and filters, if
1061 // not all filters read from disk!
1062 // OK - this cache can read single filters on demand too ...
1063 // but then the fill state of this cache should not be set to E_CONTAINS_FILTERS!
1064 if (!bAllFiltersShouldExist
)
1067 OUString sPrefFilter
;
1068 it
= aType
.find(PROPNAME_PREFERREDFILTER
);
1069 if (it
!= aType
.end())
1070 it
->second
>>= sPrefFilter
;
1071 if (sPrefFilter
.isEmpty())
1073 // OK - there is no filter for this type. But that's not an error.
1074 // Maybe it can be handled by a ContentHandler...
1075 // But at this time it's not guaranteed that there is any ContentHandler
1076 // or FrameLoader inside this cache... but on disk...
1077 bool bReferencedByLoader
= true;
1078 bool bReferencedByHandler
= true;
1079 if (bAllLoadersShouldExist
)
1080 bReferencedByLoader
= !impl_searchFrameLoaderForType(sType
).isEmpty();
1082 if (bAllHandlersShouldExist
)
1083 bReferencedByHandler
= !impl_searchContentHandlerForType(sType
).isEmpty();
1086 (!bReferencedByLoader
) &&
1087 (!bReferencedByHandler
)
1090 sLog
.append("Warning\t:\t" "The type \"" + sType
+ "\" is not used by any filter, loader or content handler.\n");
1095 if (!sPrefFilter
.isEmpty())
1097 CacheItemList::const_iterator pIt2
= m_lFilters
.find(sPrefFilter
);
1098 if (pIt2
== m_lFilters
.end())
1100 if (bAllFiltersShouldExist
)
1102 ++nWarnings
; // preferred filters can point to a non-installed office module ! no error ... it's a warning only .-(
1103 sLog
.append("error\t:\t");
1108 sLog
.append("warning\t:\t");
1111 sLog
.append("The type \"" + sType
+ "\" points to an invalid filter \"" + sPrefFilter
+ "\".\n");
1115 CacheItem aPrefFilter
= pIt2
->second
;
1116 OUString sFilterTypeReg
;
1117 aPrefFilter
[PROPNAME_TYPE
] >>= sFilterTypeReg
;
1118 if (sFilterTypeReg
!= sType
)
1120 sLog
.append("error\t:\t" "The preferred filter \"" +
1121 sPrefFilter
+ "\" of type \"" + sType
+
1122 "\" is registered for another type \"" + sFilterTypeReg
+
1127 sal_Int32 nFlags
= 0;
1128 aPrefFilter
[PROPNAME_FLAGS
] >>= nFlags
;
1129 if (!(static_cast<SfxFilterFlags
>(nFlags
) & SfxFilterFlags::IMPORT
))
1131 sLog
.append("error\t:\t" "The preferred filter \"" + sPrefFilter
+ "\" of type \"" +
1132 sType
+ "\" is not an IMPORT filter!\n");
1136 OUString sInternalFilterNameCheck
;
1137 aPrefFilter
[PROPNAME_NAME
] >>= sInternalFilterNameCheck
;
1138 if (sInternalFilterNameCheck
!= sPrefFilter
)
1140 sLog
.append("Warning\t:\t" "The filter \"" + sPrefFilter
+
1141 "\" does support the property \"Name\" correctly.\n");
1148 // create dependencies between the global default frame loader
1149 // and all types (and of course if registered filters), which
1150 // does not registered for any other loader.
1151 css::uno::Any aDirectValue
= impl_getDirectCFGValue(rGuard
, CFGDIRECTKEY_DEFAULTFRAMELOADER
);
1152 OUString sDefaultFrameLoader
;
1155 (!(aDirectValue
>>= sDefaultFrameLoader
)) ||
1156 (sDefaultFrameLoader
.isEmpty() )
1159 sLog
.append("error\t:\t" "There is no valid default frame loader!?\n");
1163 // a) get list of all well known types
1164 // b) step over all well known frame loader services
1165 // and remove all types from list a), which already
1166 // referenced by a loader b)
1167 std::vector
<OUString
> lTypes
= getItemNames(rGuard
, E_TYPE
);
1168 for (auto & frameLoader
: m_lFrameLoaders
)
1170 // Note: of course the default loader must be ignored here.
1171 // Because we replace its registration later completely with all
1172 // types, which are not referenced by any other loader.
1173 // So we can avoid our code against the complexity of a diff!
1174 OUString sLoader
= frameLoader
.first
;
1175 if (sLoader
== sDefaultFrameLoader
)
1178 CacheItem
& rLoader
= frameLoader
.second
;
1179 css::uno::Any
& rTypesReg
= rLoader
[PROPNAME_TYPES
];
1180 const css::uno::Sequence
<OUString
> lTypesReg
= rTypesReg
.get
<css::uno::Sequence
<OUString
> >();
1182 for (auto const& typeReg
: lTypesReg
)
1184 auto pTypeCheck
= ::std::find(lTypes
.begin(), lTypes
.end(), typeReg
);
1185 if (pTypeCheck
!= lTypes
.end())
1186 lTypes
.erase(pTypeCheck
);
1190 CacheItem
& rDefaultLoader
= m_lFrameLoaders
[sDefaultFrameLoader
];
1191 rDefaultLoader
[PROPNAME_NAME
] <<= sDefaultFrameLoader
;
1192 rDefaultLoader
[PROPNAME_TYPES
] <<= comphelper::containerToSequence(lTypes
);
1194 OUString sLogOut
= sLog
.makeStringAndClear();
1195 OSL_ENSURE(!nErrors
, OUStringToOString(sLogOut
,RTL_TEXTENCODING_UTF8
).getStr());
1197 throw css::document::CorruptedFilterConfigurationException(
1198 "filter configuration: " + sLogOut
,
1199 css::uno::Reference
< css::uno::XInterface
>(),
1201 #if OSL_DEBUG_LEVEL > 0
1202 OSL_ENSURE(!nWarnings
, OUStringToOString(sLogOut
,RTL_TEXTENCODING_UTF8
).getStr());
1206 void FilterCache::impl_addItem2FlushList( EItemType eType
,
1207 const OUString
& sItem
)
1209 std::vector
<OUString
>* pList
= nullptr;
1213 pList
= &m_lChangedTypes
;
1217 pList
= &m_lChangedFilters
;
1220 case E_FRAMELOADER
:
1221 pList
= &m_lChangedFrameLoaders
;
1224 case E_CONTENTHANDLER
:
1225 pList
= &m_lChangedContentHandlers
;
1228 default : throw css::uno::RuntimeException("unsupported item type", nullptr);
1231 auto pItem
= ::std::find(pList
->cbegin(), pList
->cend(), sItem
);
1232 if (pItem
== pList
->cend())
1233 pList
->push_back(sItem
);
1236 FilterCache::EItemFlushState
FilterCache::impl_specifyFlushOperation(const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
1237 const CacheItemList
& rList
,
1238 const OUString
& sItem
)
1240 bool bExistsInConfigLayer
= xSet
->hasByName(sItem
);
1241 bool bExistsInMemory
= (rList
.find(sItem
) != rList
.end());
1243 EItemFlushState
eState( E_ITEM_UNCHANGED
);
1245 // !? ... such situation can occur, if an item was added and(!) removed before it was flushed :-)
1246 if (!bExistsInConfigLayer
&& !bExistsInMemory
)
1247 eState
= E_ITEM_UNCHANGED
;
1248 else if (!bExistsInConfigLayer
&& bExistsInMemory
)
1249 eState
= E_ITEM_ADDED
;
1250 else if (bExistsInConfigLayer
&& bExistsInMemory
)
1251 eState
= E_ITEM_CHANGED
;
1252 else if (bExistsInConfigLayer
&& !bExistsInMemory
)
1253 eState
= E_ITEM_REMOVED
;
1258 void FilterCache::impl_load(std::unique_lock
<std::mutex
>& rGuard
, EFillState eRequiredState
)
1260 // Attention: Detect services are part of the standard set!
1261 // So there is no need to handle it separately.
1264 // a) The standard set of config value is needed.
1266 ((eRequiredState
& E_CONTAINS_STANDARD
) == E_CONTAINS_STANDARD
) &&
1267 ((m_eFillState
& E_CONTAINS_STANDARD
) != E_CONTAINS_STANDARD
)
1270 // Attention! If config couldn't be opened successfully
1271 // and exception is thrown automatically and must be forwarded
1273 css::uno::Reference
< css::container::XNameAccess
> xTypes(impl_openConfig(rGuard
, E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
1275 SAL_INFO( "filter.config", "FilterCache::load std");
1276 impl_loadSet(rGuard
, xTypes
, E_TYPE
, E_READ_STANDARD
, &m_lTypes
);
1281 // b) We need all type information ...
1283 ((eRequiredState
& E_CONTAINS_TYPES
) == E_CONTAINS_TYPES
) &&
1284 ((m_eFillState
& E_CONTAINS_TYPES
) != E_CONTAINS_TYPES
)
1287 // Attention! If config couldn't be opened successfully
1288 // and exception is thrown automatically and must be forwarded
1290 css::uno::Reference
< css::container::XNameAccess
> xTypes(impl_openConfig(rGuard
, E_PROVIDER_TYPES
), css::uno::UNO_QUERY_THROW
);
1292 SAL_INFO( "filter.config", "FilterCache::load all types");
1293 impl_loadSet(rGuard
, xTypes
, E_TYPE
, E_READ_UPDATE
, &m_lTypes
);
1298 // c) We need all filter information ...
1300 ((eRequiredState
& E_CONTAINS_FILTERS
) == E_CONTAINS_FILTERS
) &&
1301 ((m_eFillState
& E_CONTAINS_FILTERS
) != E_CONTAINS_FILTERS
)
1304 // Attention! If config couldn't be opened successfully
1305 // and exception is thrown automatically and must be forwarded
1307 css::uno::Reference
< css::container::XNameAccess
> xFilters(impl_openConfig(rGuard
, E_PROVIDER_FILTERS
), css::uno::UNO_QUERY_THROW
);
1309 SAL_INFO( "filter.config", "FilterCache::load all filters");
1310 impl_loadSet(rGuard
, xFilters
, E_FILTER
, E_READ_ALL
, &m_lFilters
);
1315 // c) We need all frame loader information ...
1317 ((eRequiredState
& E_CONTAINS_FRAMELOADERS
) == E_CONTAINS_FRAMELOADERS
) &&
1318 ((m_eFillState
& E_CONTAINS_FRAMELOADERS
) != E_CONTAINS_FRAMELOADERS
)
1321 // Attention! If config couldn't be opened successfully
1322 // and exception is thrown automatically and must be forwarded
1324 css::uno::Reference
< css::container::XNameAccess
> xLoaders(impl_openConfig(rGuard
, E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
1326 SAL_INFO( "filter.config", "FilterCache::load all frame loader");
1327 impl_loadSet(rGuard
, xLoaders
, E_FRAMELOADER
, E_READ_ALL
, &m_lFrameLoaders
);
1332 // d) We need all content handler information...
1334 ((eRequiredState
& E_CONTAINS_CONTENTHANDLERS
) == E_CONTAINS_CONTENTHANDLERS
) &&
1335 ((m_eFillState
& E_CONTAINS_CONTENTHANDLERS
) != E_CONTAINS_CONTENTHANDLERS
)
1338 // Attention! If config couldn't be opened successfully
1339 // and exception is thrown automatically and must be forwarded
1341 css::uno::Reference
< css::container::XNameAccess
> xHandlers(impl_openConfig(rGuard
, E_PROVIDER_OTHERS
), css::uno::UNO_QUERY_THROW
);
1343 SAL_INFO( "filter.config", "FilterCache::load all content handler");
1344 impl_loadSet(rGuard
, xHandlers
, E_CONTENTHANDLER
, E_READ_ALL
, &m_lContentHandlers
);
1348 // update fill state. Note: it's a bit field, which combines different parts.
1349 m_eFillState
= static_cast<EFillState
>(static_cast<sal_Int32
>(m_eFillState
) | static_cast<sal_Int32
>(eRequiredState
));
1352 // yes! => validate it and update optimized structures.
1353 impl_validateAndOptimize(rGuard
);
1356 void FilterCache::impl_loadSet(std::unique_lock
<std::mutex
>& rGuard
,
1357 const css::uno::Reference
< css::container::XNameAccess
>& xConfig
,
1359 EReadOption eOption
,
1360 CacheItemList
* pCache
)
1362 // get access to the right configuration set
1367 sSetName
= CFGSET_TYPES
;
1371 sSetName
= CFGSET_FILTERS
;
1374 case E_FRAMELOADER
:
1375 sSetName
= CFGSET_FRAMELOADERS
;
1378 case E_CONTENTHANDLER
:
1379 sSetName
= CFGSET_CONTENTHANDLERS
;
1384 css::uno::Reference
< css::container::XNameAccess
> xSet
;
1385 css::uno::Sequence
< OUString
> lItems
;
1389 css::uno::Any aVal
= xConfig
->getByName(sSetName
);
1390 if (!(aVal
>>= xSet
) || !xSet
.is())
1392 OUString
sMsg("Could not open configuration set \"" + sSetName
+ "\".");
1393 throw css::uno::Exception(sMsg
, css::uno::Reference
< css::uno::XInterface
>());
1395 lItems
= xSet
->getElementNames();
1397 catch(const css::uno::Exception
& ex
)
1399 throw css::document::CorruptedFilterConfigurationException(
1400 "filter configuration, caught: " + ex
.Message
,
1401 css::uno::Reference
< css::uno::XInterface
>(),
1405 // get names of all existing sub items of this set
1406 // step over it and fill internal cache structures.
1408 // But don't update optimized structures like e.g. hash
1409 // for mapping extensions to its types!
1411 const OUString
* pItems
= lItems
.getConstArray();
1412 sal_Int32 c
= lItems
.getLength();
1413 for (sal_Int32 i
=0; i
<c
; ++i
)
1415 CacheItemList::iterator pItem
= pCache
->find(pItems
[i
]);
1418 // a) read a standard set of properties only or read all
1419 case E_READ_STANDARD
:
1424 (*pCache
)[pItems
[i
]] = impl_loadItem(rGuard
, xSet
, eType
, pItems
[i
], eOption
);
1426 catch(const css::uno::Exception
& ex
)
1428 throw css::document::CorruptedFilterConfigurationException(
1429 "filter configuration, caught: " + ex
.Message
,
1430 css::uno::Reference
< css::uno::XInterface
>(),
1436 // b) read optional properties only!
1437 // All items must already exist inside our cache.
1438 // But they must be updated.
1439 case E_READ_UPDATE
:
1441 if (pItem
== pCache
->end())
1443 OUString
sMsg("item \"" + pItems
[i
] + "\" not found for update!");
1444 throw css::uno::Exception(sMsg
, css::uno::Reference
< css::uno::XInterface
>());
1448 CacheItem aItem
= impl_loadItem(rGuard
, xSet
, eType
, pItems
[i
], eOption
);
1449 pItem
->second
.update(aItem
);
1451 catch(const css::uno::Exception
& ex
)
1453 throw css::document::CorruptedFilterConfigurationException(
1454 "filter configuration, caught: " + ex
.Message
,
1455 css::uno::Reference
< css::uno::XInterface
>(),
1465 void FilterCache::impl_readPatchUINames(std::unique_lock
<std::mutex
>& /*rGuard*/,
1466 const css::uno::Reference
< css::container::XNameAccess
>& xNode
,
1470 OUString sActLocale
= m_sActLocale
;
1472 css::uno::Any aVal
= xNode
->getByName(PROPNAME_UINAME
);
1473 css::uno::Reference
< css::container::XNameAccess
> xUIName
;
1474 if (!(aVal
>>= xUIName
) && !xUIName
.is())
1477 const ::std::vector
< OUString
> lLocales(comphelper::sequenceToContainer
< ::std::vector
< OUString
>>(
1478 xUIName
->getElementNames()));
1479 ::std::vector
< OUString
>::const_iterator pLocale
;
1480 ::comphelper::SequenceAsHashMap lUINames
;
1482 for (auto const& locale
: lLocales
)
1485 xUIName
->getByName(locale
) >>= sValue
;
1487 lUINames
[locale
] <<= sValue
;
1490 aVal
<<= lUINames
.getAsConstPropertyValueList();
1491 rItem
[PROPNAME_UINAMES
] = aVal
;
1493 // find right UIName for current office locale
1494 // Use fallbacks too!
1495 pLocale
= LanguageTag::getFallback(lLocales
, sActLocale
);
1496 if (pLocale
== lLocales
.end())
1498 #if OSL_DEBUG_LEVEL > 0
1499 if ( sActLocale
== "en-US" )
1501 OUString sName
= rItem
.getUnpackedValueOrDefault(PROPNAME_NAME
, OUString());
1503 SAL_WARN("filter.config", "Fallback scenario for filter or type '" << sName
<< "' and locale '" <<
1504 sActLocale
<< "' failed. Please check your filter configuration.");
1509 const OUString
& sLocale
= *pLocale
;
1510 ::comphelper::SequenceAsHashMap::const_iterator pUIName
= lUINames
.find(sLocale
);
1511 if (pUIName
!= lUINames
.end())
1512 rItem
[PROPNAME_UINAME
] = pUIName
->second
;
1515 void FilterCache::impl_savePatchUINames(const css::uno::Reference
< css::container::XNameReplace
>& xNode
,
1516 const CacheItem
& rItem
)
1518 css::uno::Reference
< css::container::XNameContainer
> xAdd (xNode
, css::uno::UNO_QUERY
);
1520 css::uno::Sequence
< css::beans::PropertyValue
> lUINames
= rItem
.getUnpackedValueOrDefault(PROPNAME_UINAMES
, css::uno::Sequence
< css::beans::PropertyValue
>());
1521 sal_Int32 c
= lUINames
.getLength();
1522 const css::beans::PropertyValue
* pUINames
= lUINames
.getConstArray();
1524 for (sal_Int32 i
=0; i
<c
; ++i
)
1526 if (xNode
->hasByName(pUINames
[i
].Name
))
1527 xNode
->replaceByName(pUINames
[i
].Name
, pUINames
[i
].Value
);
1529 xAdd
->insertByName(pUINames
[i
].Name
, pUINames
[i
].Value
);
1533 /*-----------------------------------------------
1535 clarify, how the real problem behind the
1536 wrong constructed CacheItem instance (which
1537 will force a crash during destruction)
1539 -----------------------------------------------*/
1540 CacheItem
FilterCache::impl_loadItem(std::unique_lock
<std::mutex
>& rGuard
,
1541 const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
1543 const OUString
& sItem
,
1544 EReadOption eOption
)
1546 // try to get an API object, which points directly to the
1547 // requested item. If it fail an exception should occur and
1548 // break this operation. Of course returned API object must be
1550 css::uno::Reference
< css::container::XNameAccess
> xItem
;
1551 css::uno::Any aVal
= xSet
->getByName(sItem
);
1552 if (!(aVal
>>= xItem
) || !xItem
.is())
1554 throw css::uno::RuntimeException("found corrupted item \"" + sItem
+ "\".",
1555 css::uno::Reference
< css::uno::XInterface
>());
1558 // set too. Of course it's already used as key into the e.g. outside
1559 // used hash map... but some of our API methods provide
1560 // this property set as result only. But the user of this CacheItem
1561 // should know, which value the key names has :-) IT'S IMPORTANT!
1563 aItem
[PROPNAME_NAME
] <<= sItem
;
1568 assert(eOption
>= 0 && eOption
<= E_READ_ALL
);
1569 css::uno::Sequence
< OUString
> &rNames
= m_aTypeProps
[eOption
];
1571 // read standard properties of a filter
1572 if (rNames
.hasElements())
1574 css::uno::Reference
< css::beans::XMultiPropertySet
>
1575 xPropSet( xItem
, css::uno::UNO_QUERY_THROW
);
1576 css::uno::Sequence
< css::uno::Any
> aValues
= xPropSet
->getPropertyValues(rNames
);
1578 for (sal_Int32 i
= 0; i
< aValues
.getLength(); i
++)
1579 aItem
[rNames
[i
]] = aValues
[i
];
1582 // read optional properties of a type
1583 // no else here! Is an additional switch ...
1584 if (eOption
== E_READ_UPDATE
|| eOption
== E_READ_ALL
)
1585 impl_readPatchUINames(rGuard
, xItem
, aItem
);
1592 assert(eOption
>= 0 && eOption
<= E_READ_ALL
);
1593 css::uno::Sequence
< OUString
> &rNames
= m_aStandardProps
[eOption
];
1595 // read standard properties of a filter
1596 if (rNames
.hasElements())
1598 css::uno::Reference
< css::beans::XMultiPropertySet
>
1599 xPropSet( xItem
, css::uno::UNO_QUERY_THROW
);
1600 css::uno::Sequence
< css::uno::Any
> aValues
= xPropSet
->getPropertyValues(rNames
);
1602 for (sal_Int32 i
= 0; i
< rNames
.getLength(); i
++)
1604 const OUString
&rPropName
= rNames
[i
];
1605 if (i
!= rNames
.getLength() - 1 || rPropName
!= PROPNAME_FLAGS
)
1606 aItem
[rPropName
] = aValues
[i
];
1609 assert(rPropName
== PROPNAME_FLAGS
);
1610 // special handling for flags! Convert it from a list of names to its
1611 // int representation ...
1612 css::uno::Sequence
< OUString
> lFlagNames
;
1613 if (aValues
[i
] >>= lFlagNames
)
1614 aItem
[rPropName
] <<= static_cast<sal_Int32
>(FilterCache::impl_convertFlagNames2FlagField(lFlagNames
));
1618 //TODO remove it if moving of filter uinames to type uinames
1619 // will be finished really
1620 #ifdef AS_ENABLE_FILTER_UINAMES
1621 if (eOption
== E_READ_UPDATE
|| eOption
== E_READ_ALL
)
1622 impl_readPatchUINames(rGuard
, xItem
, aItem
);
1623 #endif // AS_ENABLE_FILTER_UINAMES
1627 case E_FRAMELOADER
:
1628 case E_CONTENTHANDLER
:
1629 aItem
[PROPNAME_TYPES
] = xItem
->getByName(PROPNAME_TYPES
);
1637 CacheItemList::iterator
FilterCache::impl_loadItemOnDemand( std::unique_lock
<std::mutex
>& rGuard
,
1639 const OUString
& sItem
)
1641 CacheItemList
* pList
= nullptr;
1642 css::uno::Reference
< css::uno::XInterface
> xConfig
;
1650 xConfig
= impl_openConfig(rGuard
, E_PROVIDER_TYPES
);
1651 sSet
= CFGSET_TYPES
;
1657 pList
= &m_lFilters
;
1658 xConfig
= impl_openConfig(rGuard
, E_PROVIDER_FILTERS
);
1659 sSet
= CFGSET_FILTERS
;
1663 case E_FRAMELOADER
:
1665 pList
= &m_lFrameLoaders
;
1666 xConfig
= impl_openConfig(rGuard
, E_PROVIDER_OTHERS
);
1667 sSet
= CFGSET_FRAMELOADERS
;
1671 case E_CONTENTHANDLER
:
1673 pList
= &m_lContentHandlers
;
1674 xConfig
= impl_openConfig(rGuard
, E_PROVIDER_OTHERS
);
1675 sSet
= CFGSET_CONTENTHANDLERS
;
1681 throw css::container::NoSuchElementException();
1683 css::uno::Reference
< css::container::XNameAccess
> xRoot(xConfig
, css::uno::UNO_QUERY_THROW
);
1684 css::uno::Reference
< css::container::XNameAccess
> xSet
;
1685 xRoot
->getByName(sSet
) >>= xSet
;
1687 CacheItemList::iterator pItemInCache
= pList
->find(sItem
);
1688 bool bItemInConfig
= xSet
->hasByName(sItem
);
1692 (*pList
)[sItem
] = impl_loadItem(rGuard
, xSet
, eType
, sItem
, E_READ_ALL
);
1696 if (pItemInCache
!= pList
->end())
1697 pList
->erase(pItemInCache
);
1698 // OK - this item does not exists inside configuration.
1699 // And we already updated our internal cache.
1700 // But the outside code needs this NoSuchElementException
1701 // to know, that this item does notexists.
1702 // Nobody checks the iterator!
1703 throw css::container::NoSuchElementException();
1706 return pList
->find(sItem
);
1709 void FilterCache::impl_saveItem(const css::uno::Reference
< css::container::XNameReplace
>& xItem
,
1711 const CacheItem
& aItem
)
1713 // This function changes the properties of aItem one-by-one; but it also
1714 // listens to the configuration changes and reloads the whole item from the
1715 // configuration on change, so use a copy of aItem throughout:
1716 CacheItem
copiedItem(aItem
);
1718 CacheItem::const_iterator pIt
;
1724 pIt
= copiedItem
.find(PROPNAME_PREFERREDFILTER
);
1725 if (pIt
!= copiedItem
.end())
1726 xItem
->replaceByName(PROPNAME_PREFERREDFILTER
, pIt
->second
);
1727 pIt
= copiedItem
.find(PROPNAME_DETECTSERVICE
);
1728 if (pIt
!= copiedItem
.end())
1729 xItem
->replaceByName(PROPNAME_DETECTSERVICE
, pIt
->second
);
1730 pIt
= copiedItem
.find(PROPNAME_URLPATTERN
);
1731 if (pIt
!= copiedItem
.end())
1732 xItem
->replaceByName(PROPNAME_URLPATTERN
, pIt
->second
);
1733 pIt
= copiedItem
.find(PROPNAME_EXTENSIONS
);
1734 if (pIt
!= copiedItem
.end())
1735 xItem
->replaceByName(PROPNAME_EXTENSIONS
, pIt
->second
);
1736 pIt
= copiedItem
.find(PROPNAME_PREFERRED
);
1737 if (pIt
!= copiedItem
.end())
1738 xItem
->replaceByName(PROPNAME_PREFERRED
, pIt
->second
);
1739 pIt
= copiedItem
.find(PROPNAME_MEDIATYPE
);
1740 if (pIt
!= copiedItem
.end())
1741 xItem
->replaceByName(PROPNAME_MEDIATYPE
, pIt
->second
);
1742 pIt
= copiedItem
.find(PROPNAME_CLIPBOARDFORMAT
);
1743 if (pIt
!= copiedItem
.end())
1744 xItem
->replaceByName(PROPNAME_CLIPBOARDFORMAT
, pIt
->second
);
1746 css::uno::Reference
< css::container::XNameReplace
> xUIName
;
1747 xItem
->getByName(PROPNAME_UINAME
) >>= xUIName
;
1748 impl_savePatchUINames(xUIName
, copiedItem
);
1755 pIt
= copiedItem
.find(PROPNAME_TYPE
);
1756 if (pIt
!= copiedItem
.end())
1757 xItem
->replaceByName(PROPNAME_TYPE
, pIt
->second
);
1758 pIt
= copiedItem
.find(PROPNAME_FILEFORMATVERSION
);
1759 if (pIt
!= copiedItem
.end())
1760 xItem
->replaceByName(PROPNAME_FILEFORMATVERSION
, pIt
->second
);
1761 pIt
= copiedItem
.find(PROPNAME_UICOMPONENT
);
1762 if (pIt
!= copiedItem
.end())
1763 xItem
->replaceByName(PROPNAME_UICOMPONENT
, pIt
->second
);
1764 pIt
= copiedItem
.find(PROPNAME_FILTERSERVICE
);
1765 if (pIt
!= copiedItem
.end())
1766 xItem
->replaceByName(PROPNAME_FILTERSERVICE
, pIt
->second
);
1767 pIt
= copiedItem
.find(PROPNAME_DOCUMENTSERVICE
);
1768 if (pIt
!= copiedItem
.end())
1769 xItem
->replaceByName(PROPNAME_DOCUMENTSERVICE
, pIt
->second
);
1770 pIt
= copiedItem
.find(PROPNAME_USERDATA
);
1771 if (pIt
!= copiedItem
.end())
1772 xItem
->replaceByName(PROPNAME_USERDATA
, pIt
->second
);
1773 pIt
= copiedItem
.find(PROPNAME_TEMPLATENAME
);
1774 if (pIt
!= copiedItem
.end())
1775 xItem
->replaceByName(PROPNAME_TEMPLATENAME
, pIt
->second
);
1777 // special handling for flags! Convert it from an integer flag field back
1778 // to a list of names ...
1779 pIt
= copiedItem
.find(PROPNAME_FLAGS
);
1780 if (pIt
!= copiedItem
.end())
1782 sal_Int32 nFlags
= 0;
1783 pIt
->second
>>= nFlags
;
1784 css::uno::Any aFlagNameList
;
1785 aFlagNameList
<<= FilterCache::impl_convertFlagField2FlagNames(static_cast<SfxFilterFlags
>(nFlags
));
1786 xItem
->replaceByName(PROPNAME_FLAGS
, aFlagNameList
);
1789 //TODO remove it if moving of filter uinames to type uinames
1790 // will be finished really
1791 #ifdef AS_ENABLE_FILTER_UINAMES
1792 css::uno::Reference
< css::container::XNameReplace
> xUIName
;
1793 xItem
->getByName(PROPNAME_UINAME
) >>= xUIName
;
1794 impl_savePatchUINames(xUIName
, copiedItem
);
1795 #endif // AS_ENABLE_FILTER_UINAMES
1800 case E_FRAMELOADER
:
1801 case E_CONTENTHANDLER
:
1803 pIt
= copiedItem
.find(PROPNAME_TYPES
);
1804 if (pIt
!= copiedItem
.end())
1805 xItem
->replaceByName(PROPNAME_TYPES
, pIt
->second
);
1812 /*-----------------------------------------------
1813 static! => no locks necessary
1814 -----------------------------------------------*/
1815 css::uno::Sequence
< OUString
> FilterCache::impl_convertFlagField2FlagNames(SfxFilterFlags nFlags
)
1817 std::vector
<OUString
> lFlagNames
;
1819 if (nFlags
& SfxFilterFlags::STARONEFILTER
) lFlagNames
.emplace_back(FLAGNAME_3RDPARTYFILTER
);
1820 if (nFlags
& SfxFilterFlags::ALIEN
) lFlagNames
.emplace_back(FLAGNAME_ALIEN
);
1821 if (nFlags
& SfxFilterFlags::CONSULTSERVICE
) lFlagNames
.emplace_back(FLAGNAME_CONSULTSERVICE
);
1822 if (nFlags
& SfxFilterFlags::DEFAULT
) lFlagNames
.emplace_back(FLAGNAME_DEFAULT
);
1823 if (nFlags
& SfxFilterFlags::ENCRYPTION
) lFlagNames
.emplace_back(FLAGNAME_ENCRYPTION
);
1824 if (nFlags
& SfxFilterFlags::EXPORT
) lFlagNames
.emplace_back(FLAGNAME_EXPORT
);
1825 if (nFlags
& SfxFilterFlags::IMPORT
) lFlagNames
.emplace_back(FLAGNAME_IMPORT
);
1826 if (nFlags
& SfxFilterFlags::INTERNAL
) lFlagNames
.emplace_back(FLAGNAME_INTERNAL
);
1827 if (nFlags
& SfxFilterFlags::NOTINFILEDLG
) lFlagNames
.emplace_back(FLAGNAME_NOTINFILEDIALOG
);
1828 if (nFlags
& SfxFilterFlags::MUSTINSTALL
) lFlagNames
.emplace_back(FLAGNAME_NOTINSTALLED
);
1829 if (nFlags
& SfxFilterFlags::OWN
) lFlagNames
.emplace_back(FLAGNAME_OWN
);
1830 if (nFlags
& SfxFilterFlags::PACKED
) lFlagNames
.emplace_back(FLAGNAME_PACKED
);
1831 if (nFlags
& SfxFilterFlags::PASSWORDTOMODIFY
) lFlagNames
.emplace_back(FLAGNAME_PASSWORDTOMODIFY
);
1832 if (nFlags
& SfxFilterFlags::PREFERED
) lFlagNames
.emplace_back(FLAGNAME_PREFERRED
);
1833 if (nFlags
& SfxFilterFlags::STARTPRESENTATION
) lFlagNames
.emplace_back(FLAGNAME_STARTPRESENTATION
);
1834 if (nFlags
& SfxFilterFlags::OPENREADONLY
) lFlagNames
.emplace_back(FLAGNAME_READONLY
);
1835 if (nFlags
& SfxFilterFlags::SUPPORTSSELECTION
) lFlagNames
.emplace_back(FLAGNAME_SUPPORTSSELECTION
);
1836 if (nFlags
& SfxFilterFlags::TEMPLATE
) lFlagNames
.emplace_back(FLAGNAME_TEMPLATE
);
1837 if (nFlags
& SfxFilterFlags::TEMPLATEPATH
) lFlagNames
.emplace_back(FLAGNAME_TEMPLATEPATH
);
1838 if (nFlags
& SfxFilterFlags::COMBINED
) lFlagNames
.emplace_back(FLAGNAME_COMBINED
);
1839 if (nFlags
& SfxFilterFlags::SUPPORTSSIGNING
) lFlagNames
.emplace_back(FLAGNAME_SUPPORTSSIGNING
);
1840 if (nFlags
& SfxFilterFlags::GPGENCRYPTION
) lFlagNames
.emplace_back(FLAGNAME_GPGENCRYPTION
);
1841 if (nFlags
& SfxFilterFlags::EXOTIC
) lFlagNames
.emplace_back(FLAGNAME_EXOTIC
);
1843 return comphelper::containerToSequence(lFlagNames
);
1846 /*-----------------------------------------------
1847 static! => no locks necessary
1848 -----------------------------------------------*/
1849 SfxFilterFlags
FilterCache::impl_convertFlagNames2FlagField(const css::uno::Sequence
< OUString
>& lNames
)
1851 SfxFilterFlags nField
= SfxFilterFlags::NONE
;
1853 const OUString
* pNames
= lNames
.getConstArray();
1854 sal_Int32 c
= lNames
.getLength();
1855 for (sal_Int32 i
=0; i
<c
; ++i
)
1857 if (pNames
[i
] == FLAGNAME_3RDPARTYFILTER
)
1859 nField
|= SfxFilterFlags::STARONEFILTER
;
1862 if (pNames
[i
] == FLAGNAME_ALIEN
)
1864 nField
|= SfxFilterFlags::ALIEN
;
1867 if (pNames
[i
] == FLAGNAME_CONSULTSERVICE
)
1869 nField
|= SfxFilterFlags::CONSULTSERVICE
;
1872 if (pNames
[i
] == FLAGNAME_DEFAULT
)
1874 nField
|= SfxFilterFlags::DEFAULT
;
1877 if (pNames
[i
] == FLAGNAME_ENCRYPTION
)
1879 nField
|= SfxFilterFlags::ENCRYPTION
;
1882 if (pNames
[i
] == FLAGNAME_EXOTIC
)
1884 nField
|= SfxFilterFlags::EXOTIC
;
1887 if (pNames
[i
] == FLAGNAME_EXPORT
)
1889 nField
|= SfxFilterFlags::EXPORT
;
1892 if (pNames
[i
] == FLAGNAME_GPGENCRYPTION
)
1894 nField
|= SfxFilterFlags::GPGENCRYPTION
;
1897 if (pNames
[i
] == FLAGNAME_IMPORT
)
1899 nField
|= SfxFilterFlags::IMPORT
;
1902 if (pNames
[i
] == FLAGNAME_INTERNAL
)
1904 nField
|= SfxFilterFlags::INTERNAL
;
1907 if (pNames
[i
] == FLAGNAME_NOTINFILEDIALOG
)
1909 nField
|= SfxFilterFlags::NOTINFILEDLG
;
1912 if (pNames
[i
] == FLAGNAME_NOTINSTALLED
)
1914 nField
|= SfxFilterFlags::MUSTINSTALL
;
1917 if (pNames
[i
] == FLAGNAME_OWN
)
1919 nField
|= SfxFilterFlags::OWN
;
1922 if (pNames
[i
] == FLAGNAME_PACKED
)
1924 nField
|= SfxFilterFlags::PACKED
;
1927 if (pNames
[i
] == FLAGNAME_PASSWORDTOMODIFY
)
1929 nField
|= SfxFilterFlags::PASSWORDTOMODIFY
;
1932 if (pNames
[i
] == FLAGNAME_PREFERRED
)
1934 nField
|= SfxFilterFlags::PREFERED
;
1937 if (pNames
[i
] == FLAGNAME_STARTPRESENTATION
)
1939 nField
|= SfxFilterFlags::STARTPRESENTATION
;
1942 if (pNames
[i
] == FLAGNAME_SUPPORTSSIGNING
)
1944 nField
|= SfxFilterFlags::SUPPORTSSIGNING
;
1947 if (pNames
[i
] == FLAGNAME_READONLY
)
1949 nField
|= SfxFilterFlags::OPENREADONLY
;
1952 if (pNames
[i
] == FLAGNAME_SUPPORTSSELECTION
)
1954 nField
|= SfxFilterFlags::SUPPORTSSELECTION
;
1957 if (pNames
[i
] == FLAGNAME_TEMPLATE
)
1959 nField
|= SfxFilterFlags::TEMPLATE
;
1962 if (pNames
[i
] == FLAGNAME_TEMPLATEPATH
)
1964 nField
|= SfxFilterFlags::TEMPLATEPATH
;
1967 if (pNames
[i
] == FLAGNAME_COMBINED
)
1969 nField
|= SfxFilterFlags::COMBINED
;
1978 void FilterCache::impl_interpretDataVal4Type(const OUString
& sValue
,
1985 case 0: rItem
[PROPNAME_PREFERRED
] <<= (sValue
.toInt32() == 1);
1988 case 1: rItem
[PROPNAME_MEDIATYPE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1991 case 2: rItem
[PROPNAME_CLIPBOARDFORMAT
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
1994 case 3: rItem
[PROPNAME_URLPATTERN
] <<= comphelper::containerToSequence(impl_tokenizeString(sValue
, ';'));
1997 case 4: rItem
[PROPNAME_EXTENSIONS
] <<= comphelper::containerToSequence(impl_tokenizeString(sValue
, ';'));
2003 void FilterCache::impl_interpretDataVal4Filter(const OUString
& sValue
,
2011 sal_Int32 nOrder
= sValue
.toInt32();
2014 SAL_WARN( "filter.config", "FilterCache::impl_interpretDataVal4Filter()\nCan not move Order value from filter to type on demand!");
2019 case 1: rItem
[PROPNAME_TYPE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
2022 case 2: rItem
[PROPNAME_DOCUMENTSERVICE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
2025 case 3: rItem
[PROPNAME_FILTERSERVICE
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
2028 case 4: rItem
[PROPNAME_FLAGS
] <<= sValue
.toInt32();
2031 case 5: rItem
[PROPNAME_USERDATA
] <<= comphelper::containerToSequence(impl_tokenizeString(sValue
, ';'));
2033 // FileFormatVersion
2034 case 6: rItem
[PROPNAME_FILEFORMATVERSION
] <<= sValue
.toInt32();
2037 case 7: rItem
[PROPNAME_TEMPLATENAME
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
2039 // [optional!] UIComponent
2040 case 8: rItem
[PROPNAME_UICOMPONENT
] <<= ::rtl::Uri::decode(sValue
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
2045 /*-----------------------------------------------
2046 TODO work on a cache copy first, which can be flushed afterwards
2047 That would be useful to guarantee a consistent cache.
2048 -----------------------------------------------*/
2049 void FilterCache::impl_readOldFormat(std::unique_lock
<std::mutex
>& rGuard
)
2051 // Attention: Opening/Reading of this old configuration format has to be handled gracefully.
2052 // It's optional and should not disturb our normal work!
2053 // E.g. we must check, if the package exists...
2056 css::uno::Reference
< css::uno::XInterface
> xInt
= impl_openConfig(rGuard
, E_PROVIDER_OLD
);
2057 css::uno::Reference
< css::container::XNameAccess
> xCfg(xInt
, css::uno::UNO_QUERY_THROW
);
2059 OUString
TYPES_SET("Types");
2061 // May be there is no type set ...
2062 if (xCfg
->hasByName(TYPES_SET
))
2064 css::uno::Reference
< css::container::XNameAccess
> xSet
;
2065 xCfg
->getByName(TYPES_SET
) >>= xSet
;
2066 const css::uno::Sequence
< OUString
> lItems
= xSet
->getElementNames();
2067 for (const OUString
& rName
: lItems
)
2068 m_lTypes
[rName
] = impl_readOldItem(rGuard
, xSet
, E_TYPE
, rName
);
2071 OUString
FILTER_SET("Filters");
2072 // May be there is no filter set ...
2073 if (xCfg
->hasByName(FILTER_SET
))
2075 css::uno::Reference
< css::container::XNameAccess
> xSet
;
2076 xCfg
->getByName(FILTER_SET
) >>= xSet
;
2077 const css::uno::Sequence
< OUString
> lItems
= xSet
->getElementNames();
2078 for (const OUString
& rName
: lItems
)
2079 m_lFilters
[rName
] = impl_readOldItem(rGuard
, xSet
, E_FILTER
, rName
);
2082 /* corrupt filter addon? Because it's external (optional) code... we can ignore it. Addon won't work then...
2083 but that seems to be acceptable.
2084 see #139088# for further information
2086 catch(const css::uno::Exception
&)
2091 CacheItem
FilterCache::impl_readOldItem(std::unique_lock
<std::mutex
>& rGuard
,
2092 const css::uno::Reference
< css::container::XNameAccess
>& xSet
,
2094 const OUString
& sItem
)
2096 css::uno::Reference
< css::container::XNameAccess
> xItem
;
2097 xSet
->getByName(sItem
) >>= xItem
;
2099 throw css::uno::Exception("Can not read old item.", css::uno::Reference
< css::uno::XInterface
>());
2102 aItem
[PROPNAME_NAME
] <<= sItem
;
2104 // Installed flag ...
2105 // Isn't used any longer!
2108 impl_readPatchUINames(rGuard
, xItem
, aItem
);
2112 std::vector
<OUString
> lData
;
2113 xItem
->getByName( "Data" ) >>= sData
;
2114 lData
= impl_tokenizeString(sData
, ',');
2116 (sData
.isEmpty()) ||
2120 throw css::uno::Exception( "Can not read old item property DATA.", css::uno::Reference
< css::uno::XInterface
>());
2123 sal_Int32 nProp
= 0;
2124 for (auto const& prop
: lData
)
2129 impl_interpretDataVal4Type(prop
, nProp
, aItem
);
2133 impl_interpretDataVal4Filter(prop
, nProp
, aItem
);
2144 std::vector
<OUString
> FilterCache::impl_tokenizeString(std::u16string_view sData
,
2145 sal_Unicode cSeparator
)
2147 std::vector
<OUString
> lData
;
2148 sal_Int32 nToken
= 0;
2151 OUString
sToken( o3tl::getToken(sData
, 0, cSeparator
, nToken
) );
2152 lData
.push_back(sToken
);
2158 #if OSL_DEBUG_LEVEL > 0
2161 OUString
FilterCache::impl_searchFrameLoaderForType(const OUString
& sType
) const
2163 for (auto const& frameLoader
: m_lFrameLoaders
)
2165 const OUString
& sItem
= frameLoader
.first
;
2166 ::comphelper::SequenceAsHashMap
lProps(frameLoader
.second
);
2167 const css::uno::Sequence
<OUString
> lTypes
=
2168 lProps
[PROPNAME_TYPES
].get
<css::uno::Sequence
<OUString
> >();
2170 if (::std::find(lTypes
.begin(), lTypes
.end(), sType
) != lTypes
.end())
2178 OUString
FilterCache::impl_searchContentHandlerForType(const OUString
& sType
) const
2180 for (auto const& contentHandler
: m_lContentHandlers
)
2182 const OUString
& sItem
= contentHandler
.first
;
2183 ::comphelper::SequenceAsHashMap
lProps(contentHandler
.second
);
2184 const css::uno::Sequence
<OUString
> lTypes
=
2185 lProps
[PROPNAME_TYPES
].get
<css::uno::Sequence
<OUString
> >();
2186 if (::std::find(lTypes
.begin(), lTypes
.end(), sType
) != lTypes
.end())
2195 bool FilterCache::impl_isModuleInstalled(std::unique_lock
<std::mutex
>& /*rGuard*/, const OUString
& sModule
)
2197 css::uno::Reference
< css::container::XNameAccess
> xCfg
;
2199 if (!m_xModuleCfg
.is())
2201 m_xModuleCfg
= officecfg::Setup::Office::Factories::get();
2204 xCfg
= m_xModuleCfg
;
2207 return xCfg
->hasByName(sModule
);
2212 } // namespace filter
2214 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */