1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include "filtercache.hxx"
28 #include "lateinitlistener.hxx"
29 #include "macros.hxx"
30 #include "constant.hxx"
31 #include "cacheupdatelistener.hxx"
32 
33 /*TODO see using below ... */
34 #define AS_ENABLE_FILTER_UINAMES
35 #define WORKAROUND_EXCEPTION_PROBLEM
36 
37 //_______________________________________________
38 // includes
39 #include <com/sun/star/util/XChangesBatch.hpp>
40 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
41 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/beans/XProperty.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/beans/Property.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
48 #include <comphelper/sequenceasvector.hxx>
49 #include <comphelper/locale.hxx>
50 #include <unotools/processfactory.hxx>
51 
52 #ifndef _UNOTOOLS_CONFIGPATHES_HXX_
53 #include <unotools/configpathes.hxx>
54 #endif
55 #include <rtl/ustrbuf.hxx>
56 #include <rtl/logfile.hxx>
57 #include <rtl/uri.hxx>
58 #include <tools/urlobj.hxx>
59 #include <tools/wldcrd.hxx>
60 
61 #include <comphelper/configurationhelper.hxx>
62 
63 //_______________________________________________
64 // namespace
65 
66 namespace filter{
67 	namespace config{
68 
69 namespace css = ::com::sun::star;
70 
71 //_______________________________________________
72 // definitions
73 
74 // Error message in case filter config seems to be corrupted.
75 // Note: Don't tell user something about "setup -repair"!
76 // It's no longer supported by using native installers ...
77 static ::rtl::OUString MESSAGE_CORRUPTED_FILTERCONFIG = ::rtl::OUString::createFromAscii("The filter configuration appears to be defective. Please install the office suite again.");
78 
79 /*-----------------------------------------------
80 	15.03.2004 08:59
81 -----------------------------------------------*/
FilterCache()82 FilterCache::FilterCache()
83     : BaseLock    (                                        )
84     , m_xSMGR     (::comphelper::getProcessServiceFactory())
85     , m_eFillState(E_CONTAINS_NOTHING                      )
86 {
87     RTL_LOGFILE_TRACE("{ (as96863) FilterCache lifetime");
88 }
89 
90 /*-----------------------------------------------
91 	15.03.2004 08:59
92 -----------------------------------------------*/
~FilterCache()93 FilterCache::~FilterCache()
94 {
95     RTL_LOGFILE_TRACE("} (as96863) FilterCache lifetime");
96 }
97 
98 /*-----------------------------------------------
99 	03.03.2004 11:27
100 -----------------------------------------------*/
clone() const101 FilterCache* FilterCache::clone() const
102 {
103     // SAFE -> ----------------------------------
104     ::osl::ResettableMutexGuard aLock(m_aLock);
105 
106     FilterCache* pClone = new FilterCache();
107 
108     // Don't copy the configuration access points here.
109     // They will be created on demand inside the cloned instance,
110     // if they are needed.
111 
112     pClone->m_xSMGR                      = m_xSMGR;
113 
114     pClone->m_lTypes                     = m_lTypes;
115     pClone->m_lDetectServices            = m_lDetectServices;
116     pClone->m_lFilters                   = m_lFilters;
117     pClone->m_lFrameLoaders              = m_lFrameLoaders;
118     pClone->m_lContentHandlers           = m_lContentHandlers;
119     pClone->m_lExtensions2Types          = m_lExtensions2Types;
120     pClone->m_lURLPattern2Types          = m_lURLPattern2Types;
121 
122     pClone->m_sActLocale                 = m_sActLocale;
123     pClone->m_sProductName               = m_sProductName;
124     pClone->m_sOOoXMLFormatName          = m_sOOoXMLFormatName;
125     pClone->m_sOOoXMLFormatVersion       = m_sOOoXMLFormatVersion;
126 
127     pClone->m_eFillState                 = m_eFillState;
128 
129     pClone->m_lChangedTypes              = m_lChangedTypes;
130     pClone->m_lChangedFilters            = m_lChangedFilters;
131     pClone->m_lChangedDetectServices     = m_lChangedDetectServices;
132     pClone->m_lChangedFrameLoaders       = m_lChangedFrameLoaders;
133     pClone->m_lChangedContentHandlers    = m_lChangedContentHandlers;
134 
135     return pClone;
136     // <- SAFE ----------------------------------
137 }
138 
139 /*-----------------------------------------------
140 	03.03.2004 14:39
141 -----------------------------------------------*/
takeOver(const FilterCache & rClone)142 void FilterCache::takeOver(const FilterCache& rClone)
143 {
144     // SAFE -> ----------------------------------
145     ::osl::ResettableMutexGuard aLock(m_aLock);
146 
147     // a)
148 	// Don't copy the configuration access points here!
149     // We must use our own ones ...
150 
151     // b)
152 	// Further we can ignore the uno service manager.
153     // We should already have a valid instance.
154 
155 	// c)
156 	// Take over only changed items!
157 	// Otherwise we risk the following scenario:
158 	// c1) clone_1 contains changed filters
159 	// c2) clone_2 container changed types
160 	// c3) clone_1 take over changed filters and unchanged types
161 	// c4) clone_2 take over unchanged filters(!) and changed types(!)
162 	// c5) c4 overwrites c3!
163 
164 	if (rClone.m_lChangedTypes.size()>0)
165 	    m_lTypes = rClone.m_lTypes;
166 	if (rClone.m_lChangedDetectServices.size()>0)
167 		m_lDetectServices = rClone.m_lDetectServices;
168 	if (rClone.m_lChangedFilters.size()>0)
169 	    m_lFilters = rClone.m_lFilters;
170 	if (rClone.m_lChangedFrameLoaders.size()>0)
171 		m_lFrameLoaders = rClone.m_lFrameLoaders;
172 	if (rClone.m_lChangedContentHandlers.size()>0)
173 		m_lContentHandlers = rClone.m_lContentHandlers;
174 
175 	m_lChangedTypes.clear();
176 	m_lChangedDetectServices.clear();
177 	m_lChangedFilters.clear();
178 	m_lChangedFrameLoaders.clear();
179 	m_lChangedContentHandlers.clear();
180 
181 	m_sActLocale = rClone.m_sActLocale;
182 	m_sProductName = rClone.m_sProductName;
183 	m_sOOoXMLFormatName = rClone.m_sOOoXMLFormatName;
184 	m_sOOoXMLFormatVersion = rClone.m_sOOoXMLFormatVersion;
185 
186 	m_eFillState = rClone.m_eFillState;
187 
188 	// renew all dependencies and optimizations
189 	// Because we can't be sure, that changed filters on one clone
190 	// and changed types of another clone work together.
191 	// But here we can check against the lates changes ...
192 	impl_validateAndOptimize();
193 	// <- SAFE ----------------------------------
194 }
195 
196 /*-----------------------------------------------
197 	28.10.2003 09:01
198 -----------------------------------------------*/
load(EFillState eRequired,sal_Bool bByThread)199 void FilterCache::load(EFillState eRequired,
200 #if OSL_DEBUG_LEVEL > 1
201 	sal_Bool bByThread
202 #else
203 	sal_Bool
204 #endif
205 )
206     throw(css::uno::Exception)
207 {
208     // SAFE -> ----------------------------------
209     ::osl::ResettableMutexGuard aLock(m_aLock);
210 
211     // check if required fill state is already reached ...
212     // There is nothing to do then.
213     if ((m_eFillState & eRequired) == eRequired)
214         return;
215 
216 #if OSL_DEBUG_LEVEL > 1 && !defined(OS2)
217     if (
218         (!bByThread) &&
219         (
220             ((eRequired & E_CONTAINS_FILTERS) == E_CONTAINS_FILTERS) ||
221             ((eRequired & E_CONTAINS_ALL    ) == E_CONTAINS_ALL    )
222         )
223        )
224     {
225         OSL_TRACE("Who disturbs our \"fill cache on demand\" feature and force loading of ALL data during office startup? Please optimize your code, so a full filled filter cache is not really needed here!");
226     }
227 #endif
228 
229     // Otherwise load the missing items.
230 
231     // ------------------------------------------
232     // a) load some const values from configuration.
233     //    These values are needed there for loading
234     //    config items ...
235     //    Further we load some std items from the
236     //    configuration so we can try to load the first
237     //    office document with a minimal set of values.
238     if (m_eFillState == E_CONTAINS_NOTHING)
239     {
240         impl_getDirectCFGValue(CFGDIRECTKEY_OFFICELOCALE) >>= m_sActLocale;
241         if (!m_sActLocale.getLength())
242         {
243             _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify office locale => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_OFFICELOCALE));
244             m_sActLocale = DEFAULT_OFFICELOCALE;
245         }
246 
247         impl_getDirectCFGValue(CFGDIRECTKEY_PRODUCTNAME) >>= m_sProductName;
248 
249         impl_getDirectCFGValue(CFGDIRECTKEY_FORMATNAME) >>= m_sOOoXMLFormatName;
250         if (!m_sOOoXMLFormatName.getLength())
251         {
252             _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format name => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATNAME));
253             m_sOOoXMLFormatName = DEFAULT_FORMATNAME;
254         }
255 
256         impl_getDirectCFGValue(CFGDIRECTKEY_FORMATVERSION) >>= m_sOOoXMLFormatVersion;
257         if (!m_sOOoXMLFormatVersion.getLength())
258         {
259             _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format version => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATVERSION));
260             m_sOOoXMLFormatVersion = DEFAULT_FORMATVERSION;
261         }
262 
263         // Support the old configuration support. Read it only one time during office runtime!
264         impl_readOldFormat();
265 
266         // enable "loadOnDemand" feature ...
267         // Create uno listener, which waits for finishing the office startup
268         // and starts a thread, which calls loadAll() at this filter cache.
269         // Note: It's not a leak to create this listener with new here.
270         // It kills itself after working!
271         /* LateInitListener* pLateInit = */ new LateInitListener(m_xSMGR);
272     }
273 
274     // ------------------------------------------
275     // b) If the required fill state was not reached
276     //    but std values was already loaded ...
277     //    we must load some further missing items.
278     impl_load(eRequired);
279     // <- SAFE
280 }
281 
282 /*-----------------------------------------------
283 	28.10.2003 09:50
284 -----------------------------------------------*/
isFillState(FilterCache::EFillState eState) const285 sal_Bool FilterCache::isFillState(FilterCache::EFillState eState) const
286     throw(css::uno::Exception)
287 {
288     // SAFE ->
289     ::osl::ResettableMutexGuard aLock(m_aLock);
290     return ((m_eFillState & eState) == eState);
291     // <- SAFE
292 }
293 
294 /*-----------------------------------------------
295 	14.07.2003 10:45
296 -----------------------------------------------*/
getMatchingItemsByProps(EItemType eType,const CacheItem & lIProps,const CacheItem & lEProps) const297 OUStringList FilterCache::getMatchingItemsByProps(      EItemType  eType  ,
298                                                   const CacheItem& lIProps,
299                                                   const CacheItem& lEProps) const
300     throw(css::uno::Exception)
301 {
302     // SAFE ->
303     ::osl::ResettableMutexGuard aLock(m_aLock);
304 
305     // search for right list
306     // An exception is thrown if "eType" is unknown.
307     // => rList will be valid every time the next line is reached.
308     CacheItemList& rList = impl_getItemList(eType);
309 
310     OUStringList lKeys;
311 
312     // search items, which provides all needed properties of set "lIProps"
313     // but not of set "lEProps"!
314     for (CacheItemList::const_iterator pIt  = rList.begin();
315                                        pIt != rList.end()  ;
316                                      ++pIt                 )
317     {
318         _FILTER_CONFIG_LOG_1_("getMatchingProps for \"%s\"  ...\n",
319                               _FILTER_CONFIG_TO_ASCII_(pIt->first))
320         if (
321             (pIt->second.haveProps(lIProps)    ) &&
322             (pIt->second.dontHaveProps(lEProps))
323            )
324         {
325             lKeys.push_back(pIt->first);
326         }
327     }
328 
329     return lKeys;
330     // <- SAFE
331 }
332 
333 /*-----------------------------------------------
334 	02.07.2003 09:32
335 -----------------------------------------------*/
hasItems(EItemType eType) const336 sal_Bool FilterCache::hasItems(EItemType eType) const
337     throw(css::uno::Exception)
338 {
339     // SAFE ->
340     ::osl::ResettableMutexGuard aLock(m_aLock);
341 
342     // search for right list
343     // An exception is thrown if "eType" is unknown.
344     // => rList will be valid every time the next line is reached.
345     CacheItemList& rList = impl_getItemList(eType);
346 
347     return (rList.size()>0);
348     // <- SAFE
349 }
350 
351 /*-----------------------------------------------
352 	02.07.2003 11:48
353 -----------------------------------------------*/
getItemNames(EItemType eType) const354 OUStringList FilterCache::getItemNames(EItemType eType) const
355     throw(css::uno::Exception)
356 {
357     // SAFE ->
358     ::osl::ResettableMutexGuard aLock(m_aLock);
359 
360     // search for right list
361     // An exception is thrown if "eType" is unknown.
362     // => rList will be valid every time the next line is reached.
363     CacheItemList& rList = impl_getItemList(eType);
364 
365     OUStringList lKeys;
366     for (CacheItemList::const_iterator pIt  = rList.begin();
367                                        pIt != rList.end()  ;
368                                      ++pIt                 )
369     {
370         lKeys.push_back(pIt->first);
371     }
372     return lKeys;
373     // <- SAFE
374 }
375 
376 /*-----------------------------------------------
377 	27.10.2003 08:37
378 -----------------------------------------------*/
hasItem(EItemType eType,const::rtl::OUString & sItem)379 sal_Bool FilterCache::hasItem(      EItemType        eType,
380                               const ::rtl::OUString& sItem)
381     throw(css::uno::Exception)
382 {
383     // SAFE ->
384     ::osl::ResettableMutexGuard aLock(m_aLock);
385 
386     // search for right list
387     // An exception is thrown if "eType" is unknown.
388     // => rList will be valid every time the next line is reached.
389     CacheItemList& rList = impl_getItemList(eType);
390 
391     // if item could not be found - check if it can be loaded
392     // from the underlying configuration layer. Might it was not already
393     // loaded into this FilterCache object before.
394     CacheItemList::const_iterator pIt = rList.find(sItem);
395     if (pIt != rList.end())
396         return sal_True;
397 
398     try
399     {
400         impl_loadItemOnDemand(eType, sItem);
401         // no exception => item could be loaded!
402         return sal_True;
403     }
404     catch(const css::container::NoSuchElementException&)
405     {}
406 
407     return sal_False;
408     // <- SAFE
409 }
410 
411 /*-----------------------------------------------
412 	17.07.2006 09:15
413 -----------------------------------------------*/
getItem(EItemType eType,const::rtl::OUString & sItem)414 CacheItem FilterCache::getItem(      EItemType        eType,
415                                const ::rtl::OUString& sItem)
416     throw(css::uno::Exception)
417 {
418     // SAFE ->
419     ::osl::ResettableMutexGuard aLock(m_aLock);
420 
421     // search for right list
422     // An exception is thrown if "eType" is unknown.
423     // => rList will be valid every time the next line is reached.
424     CacheItemList& rList = impl_getItemList(eType);
425 
426     // check if item exists ...
427     CacheItemList::iterator pIt = rList.find(sItem);
428     if (pIt == rList.end())
429     {
430         // ... or load it on demand from the
431         // underlying configuration layer.
432         // Note: NoSuchElementException is thrown automatically here if
433         // item could not be loaded!
434         pIt = impl_loadItemOnDemand(eType, sItem);
435     }
436 
437     /* Workaround for #137955#
438        Draw types and filters are installed ... but draw was disabled during setup.
439        We must suppress accessing these filters. Otherwise the office can crash.
440        Solution for the next major release: do not install those filters !
441      */
442     if (eType == E_FILTER)
443     {
444         CacheItem& rFilter = pIt->second;
445         ::rtl::OUString sDocService;
446         rFilter[PROPNAME_DOCUMENTSERVICE] >>= sDocService;
447 
448         // --> PB 2006-10-18 #142498#
449         // In Standalone-Impress the module WriterWeb is not installed
450         // but it is there to load help pages
451         sal_Bool bIsHelpFilter = sItem.equalsAscii( "writer_web_HTML_help" );
452 
453         if ( !bIsHelpFilter && !impl_isModuleInstalled(sDocService) )
454         // <--
455         {
456             ::rtl::OUStringBuffer sMsg(256);
457             sMsg.appendAscii("The requested filter '"                                                               );
458             sMsg.append     (sItem                                                                                  );
459             sMsg.appendAscii("' exists ... but it shouldn't; because the corresponding AOO module was not installed.");
460             throw css::container::NoSuchElementException(sMsg.makeStringAndClear(), css::uno::Reference< css::uno::XInterface >());
461         }
462     }
463 
464     return pIt->second;
465     // <- SAFE
466 }
467 
468 /*-----------------------------------------------
469 	03.03.2004 11:28
470 -----------------------------------------------*/
removeItem(EItemType eType,const::rtl::OUString & sItem)471 void FilterCache::removeItem(      EItemType        eType,
472                              const ::rtl::OUString& sItem)
473     throw(css::uno::Exception)
474 {
475     // SAFE ->
476     ::osl::ResettableMutexGuard aLock(m_aLock);
477 
478     // search for right list
479     // An exception is thrown if "eType" is unknown.
480     // => rList will be valid every time the next line is reached.
481     CacheItemList& rList = impl_getItemList(eType);
482 
483     CacheItemList::iterator pItem = rList.find(sItem);
484     if (pItem == rList.end())
485         pItem = impl_loadItemOnDemand(eType, sItem); // throws NoSuchELementException!
486     rList.erase(pItem);
487 
488     impl_addItem2FlushList(eType, sItem);
489 }
490 
491 /*-----------------------------------------------
492 	26.11.2003 13:28
493 -----------------------------------------------*/
setItem(EItemType eType,const::rtl::OUString & sItem,const CacheItem & aValue)494 void FilterCache::setItem(      EItemType        eType ,
495                           const ::rtl::OUString& sItem ,
496                           const CacheItem&       aValue)
497     throw(css::uno::Exception)
498 {
499     // SAFE ->
500     ::osl::ResettableMutexGuard aLock(m_aLock);
501 
502     // search for right list
503     // An exception is thrown if "eType" is unknown.
504     // => rList will be valid every time the next line is reached.
505     CacheItemList& rList = impl_getItemList(eType);
506 
507     // name must be part of the property set too ... otherwise our
508     // container query can't work correctly
509     CacheItem aItem = aValue;
510     aItem[PROPNAME_NAME] <<= sItem;
511     aItem.validateUINames(m_sActLocale);
512 
513 	// remove implicit properties as e.g. FINALIZED or MANDATORY
514 	// They can't be saved here and must be read on demand later, if they are needed.
515 	removeStatePropsFromItem(aItem);
516 
517     rList[sItem] = aItem;
518 
519     impl_addItem2FlushList(eType, sItem);
520 }
521 
522 //-----------------------------------------------
refreshItem(EItemType eType,const::rtl::OUString & sItem)523 void FilterCache::refreshItem(      EItemType        eType,
524                               const ::rtl::OUString& sItem)
525     throw(css::uno::Exception)
526 {
527     // SAFE ->
528     ::osl::ResettableMutexGuard aLock(m_aLock);
529     impl_loadItemOnDemand(eType, sItem);
530 }
531 
532 /*-----------------------------------------------
533 	27.10.2003 08:14
534 -----------------------------------------------*/
addStatePropsToItem(EItemType eType,const::rtl::OUString & sItem,CacheItem & rItem)535 void FilterCache::addStatePropsToItem(      EItemType        eType,
536                                       const ::rtl::OUString& sItem,
537                                             CacheItem&       rItem)
538     throw(css::uno::Exception)
539 {
540     // SAFE ->
541     ::osl::ResettableMutexGuard aLock(m_aLock);
542 
543 	// Note: Opening of the configuration layer throws some exceptions
544 	// if it failed. So we don't have to check any reference here ...
545     css::uno::Reference< css::container::XNameAccess > xPackage;
546     css::uno::Reference< css::container::XNameAccess > xSet;
547     switch(eType)
548     {
549         case E_TYPE :
550 			{
551 				xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY);
552 				xPackage->getByName(CFGSET_TYPES) >>= xSet;
553 			}
554             break;
555 
556         case E_FILTER :
557 			{
558 				xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY);
559 				xPackage->getByName(CFGSET_FILTERS) >>= xSet;
560 			}
561             break;
562 
563         case E_FRAMELOADER :
564 			{
565 				/* TODO
566 					Hack -->
567 						The default frame loader can't be located inside the normal set of frame loaders.
568 						It's an atomic property inside the misc cfg package. So we can't retrieve the information
569 						about FINALIZED and MANDATORY very easy ... :-(
570 						=> set it to readonly/required every time :-)
571 				*/
572 				css::uno::Any   aDirectValue       = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER);
573 				::rtl::OUString sDefaultFrameLoader;
574 				if (
575 					(aDirectValue >>= sDefaultFrameLoader) &&
576 					(sDefaultFrameLoader.getLength()     ) &&
577 					(sItem.equals(sDefaultFrameLoader)   )
578 				   )
579 				{
580 					rItem[PROPNAME_FINALIZED] <<= sal_True;
581 					rItem[PROPNAME_MANDATORY] <<= sal_True;
582 					return;
583 				}
584 				/* <-- HACK */
585 
586 				xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY);
587 				xPackage->getByName(CFGSET_FRAMELOADERS) >>= xSet;
588 			}
589             break;
590 
591         case E_CONTENTHANDLER :
592 			{
593 				xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY);
594 				xPackage->getByName(CFGSET_CONTENTHANDLERS) >>= xSet;
595 			}
596             break;
597 		default: break;
598     }
599 
600 	try
601 	{
602 		css::uno::Reference< css::beans::XProperty > xItem;
603 		xSet->getByName(sItem) >>= xItem;
604 		css::beans::Property aDescription = xItem->getAsProperty();
605 
606 		sal_Bool bFinalized = ((aDescription.Attributes & css::beans::PropertyAttribute::READONLY  ) == css::beans::PropertyAttribute::READONLY  );
607 		sal_Bool bMandatory = ((aDescription.Attributes & css::beans::PropertyAttribute::REMOVEABLE) != css::beans::PropertyAttribute::REMOVEABLE);
608 
609 		rItem[PROPNAME_FINALIZED] <<= bFinalized;
610 		rItem[PROPNAME_MANDATORY] <<= bMandatory;
611 	}
612 	catch(const css::container::NoSuchElementException&)
613 	{
614 		/*	Ignore exceptions for missing elements inside configuration.
615 			Maybe the following reason exists:
616 				-	The item does not exists inside the new configuration package org.openoffice.TypeDetection - but
617 					we got it from the old package org.openoffice.Office/TypeDetection. We don't migrate such items
618 					automatically to the new format. Because it will disturb e.g. the deinstallation of an external filter
619 					package. Because such external filter can remove the old file - but not the automatically created new one ...
620 
621 			=> mark item as FINALIZED / MANDATORY, we don't support writing to the old format
622 		*/
623 		rItem[PROPNAME_FINALIZED] <<= sal_True;
624 		rItem[PROPNAME_MANDATORY] <<= sal_True;
625 	}
626 
627     // <- SAFE
628 }
629 
630 /*-----------------------------------------------
631 	05.03.2004 10:36
632 -----------------------------------------------*/
removeStatePropsFromItem(CacheItem & rItem)633 void FilterCache::removeStatePropsFromItem(CacheItem& rItem)
634     throw(css::uno::Exception)
635 {
636 	CacheItem::iterator pIt;
637 	pIt = rItem.find(PROPNAME_FINALIZED);
638 	if (pIt != rItem.end())
639 		rItem.erase(pIt);
640 	pIt = rItem.find(PROPNAME_MANDATORY);
641 	if (pIt != rItem.end())
642 		rItem.erase(pIt);
643 }
644 
645 /*-----------------------------------------------
646 	02.07.2003 09:17
647 -----------------------------------------------*/
flush()648 void FilterCache::flush()
649     throw(css::uno::Exception)
650 {
651     // SAFE ->
652     ::osl::ResettableMutexGuard aLock(m_aLock);
653 
654     // renew all dependencies and optimizations
655     impl_validateAndOptimize();
656 
657     if (m_lChangedTypes.size() > 0)
658     {
659         css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY);
660         css::uno::Reference< css::container::XNameAccess > xSet   ;
661 
662         xConfig->getByName(CFGSET_TYPES) >>= xSet;
663         impl_flushByList(xSet, E_TYPE, m_lTypes, m_lChangedTypes);
664 
665         css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY);
666         xFlush->commitChanges();
667     }
668 
669     if (m_lChangedFilters.size() > 0)
670     {
671         css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY);
672         css::uno::Reference< css::container::XNameAccess > xSet   ;
673 
674         xConfig->getByName(CFGSET_FILTERS) >>= xSet;
675         impl_flushByList(xSet, E_FILTER, m_lFilters, m_lChangedFilters);
676 
677         css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY);
678         xFlush->commitChanges();
679     }
680 
681     /*TODO FrameLoader/ContentHandler must be flushed here too ... */
682 }
683 
684 /*-----------------------------------------------
685 	20.10.2003 09:22
686 -----------------------------------------------*/
impl_flushByList(const css::uno::Reference<css::container::XNameAccess> & xSet,EItemType eType,const CacheItemList & rCache,const OUStringList & lItems)687 void FilterCache::impl_flushByList(const css::uno::Reference< css::container::XNameAccess >& xSet  ,
688                                          EItemType                                           eType ,
689                                    const CacheItemList&                                      rCache,
690                                    const OUStringList&                                       lItems)
691     throw(css::uno::Exception)
692 {
693     css::uno::Reference< css::container::XNameContainer >   xAddRemoveSet = css::uno::Reference< css::container::XNameContainer >  (xSet, css::uno::UNO_QUERY);
694     css::uno::Reference< css::container::XNameReplace >     xReplaceeSet  = css::uno::Reference< css::container::XNameReplace >    (xSet, css::uno::UNO_QUERY);
695     css::uno::Reference< css::lang::XSingleServiceFactory > xFactory      = css::uno::Reference< css::lang::XSingleServiceFactory >(xSet, css::uno::UNO_QUERY);
696 
697     for (OUStringList::const_iterator pIt  = lItems.begin();
698                                       pIt != lItems.end()  ;
699                                     ++pIt                  )
700     {
701         const ::rtl::OUString& sItem  = *pIt;
702               EItemFlushState  eState = impl_specifyFlushOperation(xSet, rCache, sItem);
703         switch(eState)
704         {
705             case E_ITEM_REMOVED :
706             {
707                 xAddRemoveSet->removeByName(sItem);
708             }
709             break;
710 
711             case E_ITEM_ADDED :
712             {
713                 css::uno::Reference< css::container::XNameReplace > xItem (xFactory->createInstance(), css::uno::UNO_QUERY);
714 
715 				// special case. no exception - but not a valid item => set must be finalized or mandatory!
716 				// Reject flush operation by throwing an exception. At least one item couldn't be flushed.
717 				if (!xItem.is())
718 					throw css::uno::Exception(::rtl::OUString::createFromAscii("Can't add item. Set is finalized or mandatory!"),
719 											  css::uno::Reference< css::uno::XInterface >()									  );
720 
721                 CacheItemList::const_iterator pItem = rCache.find(sItem);
722                 impl_saveItem(xItem, eType, pItem->second);
723                 xAddRemoveSet->insertByName(sItem, css::uno::makeAny(xItem));
724             }
725             break;
726 
727             case E_ITEM_CHANGED :
728             {
729                 css::uno::Reference< css::container::XNameReplace > xItem;
730                 xSet->getByName(sItem) >>= xItem;
731 
732 				// special case. no exception - but not a valid item => it must be finalized or mandatory!
733 				// Reject flush operation by throwing an exception. At least one item couldn't be flushed.
734 				if (!xItem.is())
735 					throw css::uno::Exception(::rtl::OUString::createFromAscii("Can't change item. It's finalized or mandatory!"),
736 											  css::uno::Reference< css::uno::XInterface >()									   );
737 
738                 CacheItemList::const_iterator pItem = rCache.find(sItem);
739                 impl_saveItem(xItem, eType, pItem->second);
740             }
741             break;
742 			default: break;
743         }
744     }
745 }
746 
747 /*-----------------------------------------------
748 	03.11.2003 08:38
749 -----------------------------------------------*/
detectFlatForURL(const css::util::URL & aURL,FlatDetection & rFlatTypes) const750 void FilterCache::detectFlatForURL(const css::util::URL& aURL      ,
751                                          FlatDetection&  rFlatTypes) const
752     throw(css::uno::Exception)
753 {
754     // extract extension from URL, so it can be used directly as key into our hash map!
755     // Note further: It must be converted to lower case, because the optimize hash
756     // (which maps extensions to types) work with lower case key strings!
757     INetURLObject   aParser    (aURL.Main);
758     ::rtl::OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT       ,
759                                                       sal_True                          ,
760                                                       INetURLObject::DECODE_WITH_CHARSET);
761     sExtension = sExtension.toAsciiLowerCase();
762 
763     // SAFE -> ----------------------------------
764     ::osl::ResettableMutexGuard aLock(m_aLock);
765 
766     //*******************************************
767     // i) Step over all well known URL pattern
768     //    and add registered types to the return list too
769     //    Do it as first one - because: if a type match by a
770     //    pattern a following deep detection can be suppressed!
771     //    Further we can stop after first match ...
772     for (CacheItemRegistration::const_iterator pPattReg  = m_lURLPattern2Types.begin();
773                                                pPattReg != m_lURLPattern2Types.end()  ;
774                                              ++pPattReg                               )
775     {
776 		WildCard aPatternCheck(pPattReg->first);
777         if (aPatternCheck.Matches(aURL.Main))
778         {
779             const OUStringList& rTypesForPattern = pPattReg->second;
780 
781             FlatDetectionInfo aInfo;
782             aInfo.sType = *(rTypesForPattern.begin());
783             aInfo.bMatchByPattern = sal_True;
784 
785             rFlatTypes.push_back(aInfo);
786 //          return;
787         }
788     }
789 
790     //*******************************************
791     // ii) search types matching to the given extension.
792     //     Copy every matching type without changing its order!
793     //     Because preferred type was added as first one during
794     //     loading configuration.
795     CacheItemRegistration::const_iterator pExtReg = m_lExtensions2Types.find(sExtension);
796     if (pExtReg != m_lExtensions2Types.end())
797     {
798         const OUStringList& rTypesForExtension = pExtReg->second;
799         for (OUStringList::const_iterator pIt  = rTypesForExtension.begin();
800                                           pIt != rTypesForExtension.end()  ;
801                                         ++pIt                              )
802         {
803             FlatDetectionInfo aInfo;
804             aInfo.sType             = *pIt;
805             aInfo.bMatchByExtension = sal_True;
806 
807             rFlatTypes.push_back(aInfo);
808         }
809     }
810 
811     aLock.clear();
812     // <- SAFE ----------------------------------
813 }
814 
815 /*-----------------------------------------------
816 	03.11.2003 08:38
817 -----------------------------------------------*/
impl_getItemList(EItemType eType) const818 CacheItemList& FilterCache::impl_getItemList(EItemType eType) const
819     throw(css::uno::Exception)
820 {
821     // SAFE -> ----------------------------------
822     ::osl::ResettableMutexGuard aLock(m_aLock);
823 
824     switch(eType)
825     {
826         case E_TYPE           : return m_lTypes          ;
827         case E_FILTER         : return m_lFilters        ;
828         case E_FRAMELOADER    : return m_lFrameLoaders   ;
829         case E_CONTENTHANDLER : return m_lContentHandlers;
830         case E_DETECTSERVICE  : return m_lDetectServices ;
831 
832         default : throw css::uno::Exception(::rtl::OUString::createFromAscii("unknown sub container requested."),
833                                             css::uno::Reference< css::uno::XInterface >()                      );
834     }
835 
836     // <- SAFE ----------------------------------
837 }
838 
839 /*-----------------------------------------------
840 	21.10.2003 13:20
841 -----------------------------------------------*/
impl_openConfig(EConfigProvider eProvider)842 css::uno::Reference< css::uno::XInterface > FilterCache::impl_openConfig(EConfigProvider eProvider)
843     throw(css::uno::Exception)
844 {
845     // SAFE ->
846     ::osl::ResettableMutexGuard aLock(m_aLock);
847 
848     ::rtl::OUString                              sPath      ;
849     css::uno::Reference< css::uno::XInterface >* pConfig = 0;
850     css::uno::Reference< css::uno::XInterface >  xOld       ;
851     ::rtl::OString                               sRtlLog    ;
852     FilterCache::EItemType                       eItemType( FilterCache::E_TYPE ) ;
853     sal_Bool                                     bStartListening = sal_False;
854 
855     switch(eProvider)
856     {
857         case E_PROVIDER_TYPES :
858         {
859             if (m_xConfigTypes.is())
860                 return m_xConfigTypes;
861             sPath           = CFGPACKAGE_TD_TYPES;
862             pConfig         = &m_xConfigTypes;
863             eItemType       = FilterCache::E_TYPE;
864             bStartListening = sal_True;
865             sRtlLog         = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_TYPES)");
866         }
867         break;
868 
869         case E_PROVIDER_FILTERS :
870         {
871             if (m_xConfigFilters.is())
872                 return m_xConfigFilters;
873             sPath           = CFGPACKAGE_TD_FILTERS;
874             pConfig         = &m_xConfigFilters;
875             eItemType       = FilterCache::E_FILTER;
876             bStartListening = sal_True;
877             sRtlLog         = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_FILTERS)");
878         }
879         break;
880 
881         case E_PROVIDER_OTHERS :
882         {
883             if (m_xConfigOthers.is())
884                 return m_xConfigOthers;
885             sPath   = CFGPACKAGE_TD_OTHERS;
886             pConfig = &m_xConfigOthers;
887             eItemType = FilterCache::E_TYPE;
888             sRtlLog = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_OTHERS)");
889         }
890         break;
891 
892         case E_PROVIDER_OLD :
893         {
894             // This special provider is used to work with
895             // the old configuration format only. It's not cached!
896             sPath   = CFGPACKAGE_TD_OLD;
897             pConfig = &xOld;
898             sRtlLog = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_OLD)");
899         }
900         break;
901 
902         default : throw css::uno::Exception(::rtl::OUString::createFromAscii("These configuration node isn't supported here for open!"), 0);
903     }
904 
905     {
906         RTL_LOGFILE_CONTEXT(aLog, sRtlLog.getStr());
907         *pConfig = impl_createConfigAccess(sPath    ,
908                                            sal_False,   // bReadOnly
909                                            sal_True );  // bLocalesMode
910     }
911 
912     // Start listening for changes on that configuration access.
913     // We must not control the lifetime of this listener. Itself
914     // checks, when it's time to die :-)
915     if (bStartListening)
916     {
917         CacheUpdateListener* pListener = new CacheUpdateListener(m_xSMGR, *pConfig, eItemType);
918         pListener->startListening();
919     }
920 
921     return *pConfig;
922     // <- SAFE
923 }
924 
925 /*-----------------------------------------------
926 	17.07.2003 10:10
927 -----------------------------------------------*/
impl_getDirectCFGValue(const::rtl::OUString & sDirectKey)928 css::uno::Any FilterCache::impl_getDirectCFGValue(const ::rtl::OUString& sDirectKey)
929 {
930     ::rtl::OUString sRoot;
931     ::rtl::OUString sKey ;
932 
933     if (
934         (!::utl::splitLastFromConfigurationPath(sDirectKey, sRoot, sKey)) ||
935         (!sRoot.getLength()                                             ) ||
936         (!sKey.getLength()                                              )
937        )
938         return css::uno::Any();
939 
940     css::uno::Reference< css::uno::XInterface > xCfg = impl_createConfigAccess(sRoot    ,
941                                                                                sal_True ,  // bReadOnly
942                                                                                sal_False); // bLocalesMode
943     if (!xCfg.is())
944         return css::uno::Any();
945 
946     css::uno::Reference< css::container::XNameAccess > xAccess(xCfg, css::uno::UNO_QUERY);
947     if (!xAccess.is())
948         return css::uno::Any();
949 
950     css::uno::Any aValue;
951     try
952     {
953         aValue = xAccess->getByName(sKey);
954     }
955     catch(const css::uno::RuntimeException& exRun)
956         { throw exRun; }
957     #if OSL_DEBUG_LEVEL>0
958     catch(const css::uno::Exception& ex)
959     #else
960     catch(const css::uno::Exception&)
961     #endif
962         {
963             #if OSL_DEBUG_LEVEL > 0
964             OSL_ENSURE(sal_False, ::rtl::OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
965             #endif
966             aValue.clear();
967         }
968 
969     return aValue;
970 }
971 
972 /*-----------------------------------------------
973 	17.07.2003 09:49
974 -----------------------------------------------*/
impl_createConfigAccess(const::rtl::OUString & sRoot,sal_Bool bReadOnly,sal_Bool bLocalesMode)975 css::uno::Reference< css::uno::XInterface > FilterCache::impl_createConfigAccess(const ::rtl::OUString& sRoot       ,
976                                                                                        sal_Bool         bReadOnly   ,
977                                                                                        sal_Bool         bLocalesMode)
978 {
979     // SAFE ->
980     ::osl::ResettableMutexGuard aLock(m_aLock);
981 
982     css::uno::Reference< css::uno::XInterface > xCfg;
983 
984     try
985     {
986         css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
987             m_xSMGR->createInstance(SERVICE_CONFIGURATIONPROVIDER), css::uno::UNO_QUERY);
988 
989         if (!xConfigProvider.is())
990             return css::uno::Reference< css::uno::XInterface >();
991 
992         ::comphelper::SequenceAsVector< css::uno::Any > lParams;
993         css::beans::PropertyValue                       aParam ;
994 
995         // set root path
996         aParam.Name    = _FILTER_CONFIG_FROM_ASCII_("nodepath");
997         aParam.Value <<= sRoot;
998         lParams.push_back(css::uno::makeAny(aParam));
999 
1000         // enable "all locales mode" ... if required
1001         if (bLocalesMode)
1002         {
1003             aParam.Name    = _FILTER_CONFIG_FROM_ASCII_("locale");
1004             aParam.Value <<= _FILTER_CONFIG_FROM_ASCII_("*"     );
1005             lParams.push_back(css::uno::makeAny(aParam));
1006         }
1007 
1008         // open it
1009         if (bReadOnly)
1010             xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONACCESS, lParams.getAsConstList());
1011         else
1012             xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONUPDATEACCESS, lParams.getAsConstList());
1013 
1014         // If configuration could not be opened ... but factory method does not throw an exception
1015         // trigger throwing of our own CorruptedFilterConfigurationException.
1016         // Let message empty. The normal exception text show enough informations to the user.
1017         if (! xCfg.is())
1018             throw css::uno::Exception(
1019                     _FILTER_CONFIG_FROM_ASCII_("Got NULL reference on opening configuration file ... but no exception."),
1020                     css::uno::Reference< css::uno::XInterface >());
1021     }
1022     catch(const css::uno::Exception& ex)
1023     {
1024         throw css::document::CorruptedFilterConfigurationException(
1025                 MESSAGE_CORRUPTED_FILTERCONFIG,
1026                 css::uno::Reference< css::uno::XInterface >(),
1027                 ex.Message);
1028     }
1029 
1030     return xCfg;
1031     // <- SAFE
1032 }
1033 
1034 /*-----------------------------------------------
1035 	24.10.2003 10:03
1036 -----------------------------------------------*/
impl_validateAndOptimize()1037 void FilterCache::impl_validateAndOptimize()
1038     throw(css::uno::Exception)
1039 {
1040     // SAFE ->
1041     ::osl::ResettableMutexGuard aLock(m_aLock);
1042 
1043     RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::impl_validateAndOptimize");
1044 
1045     // First check if any filter or type could be read
1046     // from the underlying configuration!
1047     sal_Bool bSomeTypesShouldExist   = ((m_eFillState & E_CONTAINS_STANDARD       ) == E_CONTAINS_STANDARD       );
1048     sal_Bool bAllFiltersShouldExist  = ((m_eFillState & E_CONTAINS_FILTERS        ) == E_CONTAINS_FILTERS        );
1049 
1050 #if OSL_DEBUG_LEVEL > 0
1051 
1052 	sal_Int32             nWarnings = 0;
1053 
1054 //	sal_Bool bAllTypesShouldExist    = ((m_eFillState & E_CONTAINS_TYPES          ) == E_CONTAINS_TYPES          );
1055 	sal_Bool bAllLoadersShouldExist  = ((m_eFillState & E_CONTAINS_FRAMELOADERS   ) == E_CONTAINS_FRAMELOADERS   );
1056 	sal_Bool bAllHandlersShouldExist = ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS);
1057 #endif
1058 
1059     if (
1060         (
1061             (bSomeTypesShouldExist) &&
1062             (m_lTypes.size() < 1  )
1063         ) ||
1064         (
1065             (bAllFiltersShouldExist) &&
1066             (m_lFilters.size() < 1 )
1067         )
1068        )
1069     {
1070         throw css::document::CorruptedFilterConfigurationException(
1071                 MESSAGE_CORRUPTED_FILTERCONFIG,
1072                 css::uno::Reference< css::uno::XInterface >(),
1073                 ::rtl::OUString::createFromAscii("The list of types or filters is empty."));
1074     }
1075 
1076     // Create a log for all detected problems, which
1077     // occur in the next few lines.
1078     // If there are some real errors throw a RuntimException!
1079     // If there are some warnings only, show an assertion.
1080     sal_Int32             nErrors   = 0;
1081     ::rtl::OUStringBuffer sLog(256);
1082 
1083     CacheItemList::iterator pIt;
1084 
1085     for (pIt = m_lTypes.begin(); pIt != m_lTypes.end(); ++pIt)
1086     {
1087         ::rtl::OUString sType = pIt->first;
1088         CacheItem       aType = pIt->second;
1089 
1090         // create list of all known detect services / frame loader / content handler on demand
1091         // Because these informations are available as type properties!
1092         ::rtl::OUString sDetectService;
1093         aType[PROPNAME_DETECTSERVICE ] >>= sDetectService;
1094         if (sDetectService.getLength())
1095             impl_resolveItem4TypeRegistration(&m_lDetectServices, sDetectService, sType);
1096 
1097         // get its registration for file Extensions AND(!) URLPattern ...
1098         // It doesn't matter if these items exists or if our
1099         // used index access create some default ones ...
1100         // only in case there is no filled set of Extensions AND
1101         // no filled set of URLPattern -> we must try to remove this invalid item
1102         // from this cache!
1103         css::uno::Sequence< ::rtl::OUString > lExtensions;
1104         css::uno::Sequence< ::rtl::OUString > lURLPattern;
1105         aType[PROPNAME_EXTENSIONS] >>= lExtensions;
1106         aType[PROPNAME_URLPATTERN] >>= lURLPattern;
1107         sal_Int32 ce = lExtensions.getLength();
1108         sal_Int32 cu = lURLPattern.getLength();
1109 
1110 #if OSL_DEBUG_LEVEL > 0
1111 
1112         ::rtl::OUString sInternalTypeNameCheck;
1113         aType[PROPNAME_NAME] >>= sInternalTypeNameCheck;
1114         if (!sInternalTypeNameCheck.equals(sType))
1115         {
1116             sLog.appendAscii("Warning\t:\t");
1117             sLog.appendAscii("The type \"" );
1118             sLog.append     (sType         );
1119             sLog.appendAscii("\" does support the property \"Name\" correctly.\n");
1120             ++nWarnings;
1121         }
1122 
1123         if (!ce && !cu)
1124         {
1125             sLog.appendAscii("Warning\t:\t");
1126             sLog.appendAscii("The type \"" );
1127             sLog.append     (sType         );
1128             sLog.appendAscii("\" does not contain any URL pattern nor any extensions.\n");
1129             ++nWarnings;
1130         }
1131 #endif
1132 
1133         // create an optimized registration for this type to
1134         // its set list of extensions/url pattern. If it's a "normal" type
1135         // set it at the end of this optimized list. But if it's
1136         // a "Preferred" one - set it to the front of this list.
1137         // Of course multiple "Preferred" registrations can occur
1138         // (they shouldn't - but they can!) ... Ignore it. The last
1139         // preferred type is usable in the same manner then every
1140         // other type!
1141         sal_Bool bPreferred = sal_False;
1142         aType[PROPNAME_PREFERRED] >>= bPreferred;
1143 
1144         const ::rtl::OUString* pExtensions = lExtensions.getConstArray();
1145         for (sal_Int32 e=0; e<ce; ++e)
1146         {
1147             // Note: We must be sure that address the right hash entry
1148             // does not depend from any upper/lower case problems ...
1149             ::rtl::OUString sNormalizedExtension = pExtensions[e].toAsciiLowerCase();
1150 
1151             OUStringList& lTypesForExtension = m_lExtensions2Types[sNormalizedExtension];
1152             if (::std::find(lTypesForExtension.begin(), lTypesForExtension.end(), sType) != lTypesForExtension.end())
1153                 continue;
1154 
1155             if (bPreferred)
1156                 lTypesForExtension.insert(lTypesForExtension.begin(), sType);
1157             else
1158                 lTypesForExtension.push_back(sType);
1159         }
1160 
1161         const ::rtl::OUString* pURLPattern = lURLPattern.getConstArray();
1162         for (sal_Int32 u=0; u<cu; ++u)
1163         {
1164             OUStringList& lTypesForURLPattern = m_lURLPattern2Types[pURLPattern[u]];
1165             if (::std::find(lTypesForURLPattern.begin(), lTypesForURLPattern.end(), sType) != lTypesForURLPattern.end())
1166                 continue;
1167 
1168             if (bPreferred)
1169                 lTypesForURLPattern.insert(lTypesForURLPattern.begin(), sType);
1170             else
1171                 lTypesForURLPattern.push_back(sType);
1172         }
1173 
1174 #if OSL_DEBUG_LEVEL > 0
1175 
1176         // Don't check cross references between types and filters, if
1177         // not all filters read from disk!
1178         // OK - this cache can read single filters on demand too ...
1179         // but then the fill state of this cache shouldn't be set to E_CONTAINS_FILTERS!
1180         if (!bAllFiltersShouldExist)
1181             continue;
1182 
1183         ::rtl::OUString sPrefFilter;
1184         aType[PROPNAME_PREFERREDFILTER] >>= sPrefFilter;
1185         if (!sPrefFilter.getLength())
1186         {
1187             // OK - there is no filter for this type. But that's not an error.
1188             // Maybe it can be handled by a ContentHandler ...
1189             // But at this time it's not guaranteed that there is any ContentHandler
1190             // or FrameLoader inside this cache ... but on disk ...
1191             sal_Bool bReferencedByLoader  = sal_True;
1192             sal_Bool bReferencedByHandler = sal_True;
1193             if (bAllLoadersShouldExist)
1194                 bReferencedByLoader = (impl_searchFrameLoaderForType(sType).getLength()!=0);
1195 
1196             if (bAllHandlersShouldExist)
1197                 bReferencedByHandler = (impl_searchContentHandlerForType(sType).getLength()!=0);
1198 
1199             if (
1200                 (!bReferencedByLoader ) &&
1201                 (!bReferencedByHandler)
1202                )
1203             {
1204                 sLog.appendAscii("Warning\t:\t"                                            );
1205                 sLog.appendAscii("The type \""                                             );
1206                 sLog.append     (sType                                                     );
1207                 sLog.appendAscii("\" isn't used by any filter, loader or content handler.\n");
1208                 ++nWarnings;
1209             }
1210         }
1211 
1212         if (sPrefFilter.getLength())
1213         {
1214             CacheItemList::const_iterator pIt2 = m_lFilters.find(sPrefFilter);
1215             if (pIt2 == m_lFilters.end())
1216             {
1217                 if (bAllFiltersShouldExist)
1218                 {
1219                     ++nWarnings; // preferred filters can point to a non-installed office module ! no error ... it's a warning only .-(
1220                     sLog.appendAscii("error\t:\t");
1221                 }
1222                 else
1223                 {
1224                     ++nWarnings;
1225                     sLog.appendAscii("warning\t:\t");
1226                 }
1227 
1228                 sLog.appendAscii("The type \""                      );
1229                 sLog.append     (sType                              );
1230                 sLog.appendAscii("\" points to an invalid filter \"");
1231                 sLog.append     (sPrefFilter                        );
1232                 sLog.appendAscii("\".\n"                            );
1233 
1234                 continue;
1235             }
1236 
1237             CacheItem       aPrefFilter   = pIt2->second;
1238             ::rtl::OUString sFilterTypeReg;
1239             aPrefFilter[PROPNAME_TYPE] >>= sFilterTypeReg;
1240             if (sFilterTypeReg != sType)
1241             {
1242                 sLog.appendAscii("error\t:\t"                       );
1243                 sLog.appendAscii("The preferred filter \""          );
1244                 sLog.append     (sPrefFilter                        );
1245                 sLog.appendAscii("\" of type \""                    );
1246                 sLog.append     (sType                              );
1247                 sLog.appendAscii("is registered for another type \"");
1248                 sLog.append     (sFilterTypeReg                     );
1249                 sLog.appendAscii("\".\n"                            );
1250                 ++nErrors;
1251             }
1252 
1253             sal_Int32 nFlags = 0;
1254             aPrefFilter[PROPNAME_FLAGS] >>= nFlags;
1255             if ((nFlags & FLAGVAL_IMPORT) != FLAGVAL_IMPORT)
1256             {
1257                 sLog.appendAscii("error\t:\t"                   );
1258                 sLog.appendAscii("The preferred filter \""      );
1259                 sLog.append     (sPrefFilter                    );
1260                 sLog.appendAscii("\" of type \""                );
1261                 sLog.append     (sType                          );
1262                 sLog.appendAscii("\" is not an IMPORT filter!\n");
1263                 ++nErrors;
1264             }
1265 
1266             ::rtl::OUString sInternalFilterNameCheck;
1267             aPrefFilter[PROPNAME_NAME] >>= sInternalFilterNameCheck;
1268             if (!sInternalFilterNameCheck.equals(sPrefFilter))
1269             {
1270                 sLog.appendAscii("Warning\t:\t"  );
1271                 sLog.appendAscii("The filter \"" );
1272                 sLog.append     (sPrefFilter     );
1273                 sLog.appendAscii("\" does support the property \"Name\" correctly.\n");
1274                 ++nWarnings;
1275             }
1276         }
1277 #endif
1278     }
1279 
1280     // create dependencies between the global default frame loader
1281     // and all types (and of course if registered filters), which
1282     // does not registered for any other loader.
1283     css::uno::Any   aDirectValue       = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER);
1284     ::rtl::OUString sDefaultFrameLoader;
1285 
1286     if (
1287         (!(aDirectValue >>= sDefaultFrameLoader)) ||
1288         (!sDefaultFrameLoader.getLength()       )
1289        )
1290     {
1291         sLog.appendAscii("error\t:\t"                                );
1292         sLog.appendAscii("There is no valid default frame loader!?\n");
1293         ++nErrors;
1294     }
1295 
1296     // a) get list of all well known types
1297     // b) step over all well known frame loader services
1298     //    and remove all types from list a), which already
1299     //    referenced by a loader b)
1300     OUStringList lTypes = getItemNames(E_TYPE);
1301     for (  pIt  = m_lFrameLoaders.begin();
1302            pIt != m_lFrameLoaders.end()  ;
1303          ++pIt                           )
1304     {
1305         // Note: of course the default loader must be ignored here.
1306         // Because we replace its registration later completely with all
1307         // types, which are not referenced by any other loader.
1308         // So we can avoid our code against the complexity of a diff!
1309         ::rtl::OUString sLoader = pIt->first;
1310         if (sLoader.equals(sDefaultFrameLoader))
1311             continue;
1312 
1313         CacheItem&     rLoader   = pIt->second;
1314         css::uno::Any& rTypesReg = rLoader[PROPNAME_TYPES];
1315         OUStringList   lTypesReg (rTypesReg);
1316 
1317         for (OUStringList::const_iterator pTypesReg  = lTypesReg.begin();
1318                                           pTypesReg != lTypesReg.end()  ;
1319                                         ++pTypesReg                     )
1320         {
1321             OUStringList::iterator pTypeCheck = ::std::find(lTypes.begin(), lTypes.end(), *pTypesReg);
1322             if (pTypeCheck != lTypes.end())
1323                 lTypes.erase(pTypeCheck);
1324         }
1325     }
1326 
1327     CacheItem& rDefaultLoader = m_lFrameLoaders[sDefaultFrameLoader];
1328     rDefaultLoader[PROPNAME_NAME ] <<= sDefaultFrameLoader;
1329     rDefaultLoader[PROPNAME_TYPES] <<= lTypes.getAsConstList();
1330 
1331     ::rtl::OUString sLogOut = sLog.makeStringAndClear();
1332     OSL_ENSURE(!nErrors, ::rtl::OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr());
1333     if (nErrors>0)
1334         throw css::document::CorruptedFilterConfigurationException(
1335                 MESSAGE_CORRUPTED_FILTERCONFIG,
1336                 css::uno::Reference< css::uno::XInterface >(),
1337                 sLogOut);
1338     OSL_ENSURE(!nWarnings, ::rtl::OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr());
1339 
1340     // <- SAFE
1341 }
1342 
1343 /*-----------------------------------------------
1344 	20.10.2003 08:15
1345 -----------------------------------------------*/
impl_addItem2FlushList(EItemType eType,const::rtl::OUString & sItem)1346 void FilterCache::impl_addItem2FlushList(      EItemType        eType,
1347                                          const ::rtl::OUString& sItem)
1348     throw(css::uno::Exception)
1349 {
1350     OUStringList* pList = 0;
1351     switch(eType)
1352     {
1353         case E_TYPE :
1354                 pList = &m_lChangedTypes;
1355                 break;
1356 
1357         case E_FILTER :
1358                 pList = &m_lChangedFilters;
1359                 break;
1360 
1361         case E_FRAMELOADER :
1362                 pList = &m_lChangedFrameLoaders;
1363                 break;
1364 
1365         case E_CONTENTHANDLER :
1366                 pList = &m_lChangedContentHandlers;
1367                 break;
1368 
1369         case E_DETECTSERVICE :
1370                 pList = &m_lChangedDetectServices;
1371                 break;
1372 
1373         default : throw css::uno::Exception(::rtl::OUString::createFromAscii("unsupported item type"), 0);
1374     }
1375 
1376     OUStringList::const_iterator pItem = ::std::find(pList->begin(), pList->end(), sItem);
1377     if (pItem == pList->end())
1378         pList->push_back(sItem);
1379 }
1380 
1381 /*-----------------------------------------------
1382 	20.10.2003 08:49
1383 -----------------------------------------------*/
impl_specifyFlushOperation(const css::uno::Reference<css::container::XNameAccess> & xSet,const CacheItemList & rList,const::rtl::OUString & sItem)1384 FilterCache::EItemFlushState FilterCache::impl_specifyFlushOperation(const css::uno::Reference< css::container::XNameAccess >& xSet ,
1385                                                                      const CacheItemList&                                      rList,
1386                                                                      const ::rtl::OUString&                                    sItem)
1387     throw(css::uno::Exception)
1388 {
1389     sal_Bool bExistsInConfigLayer = xSet->hasByName(sItem);
1390     sal_Bool bExistsInMemory      = (rList.find(sItem) != rList.end());
1391 
1392     EItemFlushState eState( E_ITEM_UNCHANGED );
1393 
1394     // !? ... such a situation can occur, if an item was added and(!) removed before it was flushed :-)
1395     if (!bExistsInConfigLayer && !bExistsInMemory)
1396         eState = E_ITEM_UNCHANGED;
1397     else
1398     if (!bExistsInConfigLayer && bExistsInMemory)
1399         eState = E_ITEM_ADDED;
1400     else
1401     if (bExistsInConfigLayer && bExistsInMemory)
1402         eState = E_ITEM_CHANGED;
1403     else
1404     if (bExistsInConfigLayer && !bExistsInMemory)
1405         eState = E_ITEM_REMOVED;
1406 
1407     return eState;
1408 }
1409 
1410 /*-----------------------------------------------
1411 	14.10.2003 09:26
1412 -----------------------------------------------*/
impl_resolveItem4TypeRegistration(CacheItemList * pList,const::rtl::OUString & sItem,const::rtl::OUString & sType)1413 void FilterCache::impl_resolveItem4TypeRegistration(      CacheItemList*   pList,
1414                                                     const ::rtl::OUString& sItem,
1415                                                     const ::rtl::OUString& sType)
1416     throw(css::uno::Exception)
1417 {
1418     CacheItem& rItem = (*pList)[sItem];
1419     // In case it's a new created entry (automatically done by the hash_map index operator!)
1420     // we must be sure, that this entry has its own name as property available.
1421     // It's needed later at our container interface!
1422     rItem[PROPNAME_NAME] <<= sItem;
1423 
1424     OUStringList lTypeRegs(rItem[PROPNAME_TYPES]);
1425     if (::std::find(lTypeRegs.begin(), lTypeRegs.end(), sType) == lTypeRegs.end())
1426     {
1427         lTypeRegs.push_back(sType);
1428         rItem[PROPNAME_TYPES] <<= lTypeRegs.getAsConstList();
1429     }
1430 }
1431 
1432 /*-----------------------------------------------
1433 	28.10.2003 09:18
1434 -----------------------------------------------*/
impl_load(EFillState eRequiredState)1435 void FilterCache::impl_load(EFillState eRequiredState)
1436     throw(css::uno::Exception)
1437 {
1438     // SAFE ->
1439     ::osl::ResettableMutexGuard aLock(m_aLock);
1440 
1441     // Attention: Detect services are part of the standard set!
1442     // So there is no need to handle it separately.
1443 
1444     // ------------------------------------------
1445     // a) The standard set of config value is needed.
1446     if (
1447         ((eRequiredState & E_CONTAINS_STANDARD) == E_CONTAINS_STANDARD) &&
1448         ((m_eFillState   & E_CONTAINS_STANDARD) != E_CONTAINS_STANDARD)
1449        )
1450     {
1451         // Attention! If config couldn't be opened successfully
1452         // and exception os thrown automatically and must be forwarded
1453         // to our calli ...
1454         css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY);
1455         {
1456             RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load std");
1457             impl_loadSet(xTypes, E_TYPE, E_READ_STANDARD, &m_lTypes);
1458         }
1459     }
1460 
1461     // ------------------------------------------
1462     // b) We need all type informations ...
1463     if (
1464         ((eRequiredState & E_CONTAINS_TYPES) == E_CONTAINS_TYPES) &&
1465         ((m_eFillState   & E_CONTAINS_TYPES) != E_CONTAINS_TYPES)
1466        )
1467     {
1468         // Attention! If config couldn't be opened successfully
1469         // and exception os thrown automatically and must be forwarded
1470         // to our calli ...
1471         css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY);
1472         {
1473             RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all types");
1474             impl_loadSet(xTypes, E_TYPE, E_READ_UPDATE, &m_lTypes);
1475         }
1476     }
1477 
1478     // ------------------------------------------
1479     // c) We need all filter informations ...
1480     if (
1481         ((eRequiredState & E_CONTAINS_FILTERS) == E_CONTAINS_FILTERS) &&
1482         ((m_eFillState   & E_CONTAINS_FILTERS) != E_CONTAINS_FILTERS)
1483        )
1484     {
1485         // Attention! If config couldn't be opened successfully
1486         // and exception os thrown automatically and must be forwarded
1487         // to our calli ...
1488         css::uno::Reference< css::container::XNameAccess > xFilters(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY);
1489         {
1490             RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all filters");
1491             impl_loadSet(xFilters, E_FILTER, E_READ_ALL, &m_lFilters);
1492         }
1493     }
1494 
1495     // ------------------------------------------
1496     // c) We need all frame loader informations ...
1497     if (
1498         ((eRequiredState & E_CONTAINS_FRAMELOADERS) == E_CONTAINS_FRAMELOADERS) &&
1499         ((m_eFillState   & E_CONTAINS_FRAMELOADERS) != E_CONTAINS_FRAMELOADERS)
1500        )
1501     {
1502         // Attention! If config couldn't be opened successfully
1503         // and exception os thrown automatically and must be forwarded
1504         // to our calli ...
1505         css::uno::Reference< css::container::XNameAccess > xLoaders(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY);
1506         {
1507             RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all frame loader");
1508             impl_loadSet(xLoaders, E_FRAMELOADER, E_READ_ALL, &m_lFrameLoaders);
1509         }
1510     }
1511 
1512     // ------------------------------------------
1513     // d) We need all content handler informations ...
1514     if (
1515         ((eRequiredState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS) &&
1516         ((m_eFillState   & E_CONTAINS_CONTENTHANDLERS) != E_CONTAINS_CONTENTHANDLERS)
1517        )
1518     {
1519         // Attention! If config couldn't be opened successfully
1520         // and exception os thrown automatically and must be forwarded
1521         // to our calli ...
1522         css::uno::Reference< css::container::XNameAccess > xHandlers(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY);
1523         {
1524             RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all content handler");
1525             impl_loadSet(xHandlers, E_CONTENTHANDLER, E_READ_ALL, &m_lContentHandlers);
1526         }
1527     }
1528 
1529     // update fill state. Note: it's a bit field, which combines different parts.
1530     m_eFillState = (EFillState) ((sal_Int32)m_eFillState | (sal_Int32)eRequiredState);
1531 
1532     // any data read?
1533     // yes! => validate it and update optimized structures.
1534     impl_validateAndOptimize();
1535 
1536     // <- SAFE
1537 }
1538 
1539 /*-----------------------------------------------
1540 	22.09.2003 14:27
1541 -----------------------------------------------*/
impl_loadSet(const css::uno::Reference<css::container::XNameAccess> & xConfig,EItemType eType,EReadOption eOption,CacheItemList * pCache)1542 void FilterCache::impl_loadSet(const css::uno::Reference< css::container::XNameAccess >& xConfig,
1543                                      EItemType                                           eType  ,
1544                                      EReadOption                                         eOption,
1545                                      CacheItemList*                                      pCache )
1546     throw(css::uno::Exception)
1547 {
1548     // get access to the right configuration set
1549     ::rtl::OUString sSetName;
1550     switch(eType)
1551     {
1552         case E_TYPE :
1553             sSetName = CFGSET_TYPES;
1554             break;
1555 
1556         case E_FILTER :
1557             sSetName = CFGSET_FILTERS;
1558             break;
1559 
1560         case E_FRAMELOADER :
1561             sSetName = CFGSET_FRAMELOADERS;
1562             break;
1563 
1564         case E_CONTENTHANDLER :
1565             sSetName = CFGSET_CONTENTHANDLERS;
1566             break;
1567 		default: break;
1568     }
1569 
1570     css::uno::Reference< css::container::XNameAccess > xSet;
1571     css::uno::Sequence< ::rtl::OUString >              lItems;
1572 
1573     try
1574     {
1575         css::uno::Any aVal = xConfig->getByName(sSetName);
1576         if (!(aVal >>= xSet) || !xSet.is())
1577         {
1578             ::rtl::OUStringBuffer sMsg(256);
1579             sMsg.appendAscii("Could not open configuration set \"");
1580             sMsg.append     (sSetName                             );
1581             sMsg.appendAscii("\"."                                );
1582             throw css::uno::Exception(
1583                     sMsg.makeStringAndClear(),
1584                     css::uno::Reference< css::uno::XInterface >());
1585         }
1586         lItems = xSet->getElementNames();
1587     }
1588     catch(const css::uno::Exception& ex)
1589     {
1590         throw css::document::CorruptedFilterConfigurationException(
1591                 MESSAGE_CORRUPTED_FILTERCONFIG,
1592                 css::uno::Reference< css::uno::XInterface >(),
1593                 ex.Message);
1594     }
1595 
1596     // get names of all existing sub items of this set
1597     // step over it and fill internal cache structures.
1598 
1599     // But don't update optimized structures like e.g. hash
1600     // for mapping extensions to its types!
1601 
1602     const ::rtl::OUString* pItems = lItems.getConstArray();
1603           sal_Int32        c      = lItems.getLength();
1604     for (sal_Int32 i=0; i<c; ++i)
1605     {
1606         CacheItemList::iterator pItem = pCache->find(pItems[i]);
1607         switch(eOption)
1608         {
1609             // a) read a standard set of properties only or read all
1610             case E_READ_STANDARD :
1611             case E_READ_ALL      :
1612             {
1613                 try
1614                 {
1615                     (*pCache)[pItems[i]] = impl_loadItem(xSet, eType, pItems[i], eOption);
1616                 }
1617                 catch(const css::uno::Exception& ex)
1618                 {
1619                     throw css::document::CorruptedFilterConfigurationException(
1620                             MESSAGE_CORRUPTED_FILTERCONFIG,
1621                             css::uno::Reference< css::uno::XInterface >(),
1622                             ex.Message);
1623                 }
1624             }
1625             break;
1626 
1627             // b) read optional properties only!
1628             //    All items must already exist inside our cache.
1629             //    But they must be updated.
1630             case E_READ_UPDATE :
1631             {
1632                 if (pItem == pCache->end())
1633                 {
1634                     ::rtl::OUStringBuffer sMsg(256);
1635                     sMsg.appendAscii("item \""                 );
1636                     sMsg.append     (pItems[i]                 );
1637                     sMsg.appendAscii("\" not found for update!");
1638                     throw css::uno::Exception(sMsg.makeStringAndClear()                    ,
1639                                               css::uno::Reference< css::uno::XInterface >());
1640                 }
1641                 try
1642                 {
1643                     CacheItem aItem = impl_loadItem(xSet, eType, pItems[i], eOption);
1644                     pItem->second.update(aItem);
1645                 }
1646                 catch(const css::uno::Exception& ex)
1647                 {
1648                     throw css::document::CorruptedFilterConfigurationException(
1649                             MESSAGE_CORRUPTED_FILTERCONFIG,
1650                             css::uno::Reference< css::uno::XInterface >(),
1651                             ex.Message);
1652                 }
1653             }
1654             break;
1655 			default: break;
1656         }
1657     }
1658 }
1659 
1660 /*-----------------------------------------------
1661 	26.11.2003 12:49
1662 -----------------------------------------------*/
impl_readPatchUINames(const css::uno::Reference<css::container::XNameAccess> & xNode,CacheItem & rItem)1663 void FilterCache::impl_readPatchUINames(const css::uno::Reference< css::container::XNameAccess >& xNode,
1664                                               CacheItem&                                          rItem)
1665     throw(css::uno::Exception)
1666 {
1667     static ::rtl::OUString PRODUCTNAME_VAR      = ::rtl::OUString::createFromAscii("%productname%");
1668     static ::rtl::OUString FORMATNAME_VAR       = ::rtl::OUString::createFromAscii("%oooxmlformatname%"  );
1669     static ::rtl::OUString FORMATVERSION_VAR    = ::rtl::OUString::createFromAscii("%oooxmlformatversion%");
1670 
1671     // SAFE -> ----------------------------------
1672     ::osl::ResettableMutexGuard aLock(m_aLock);
1673     ::rtl::OUString sProductName   = m_sProductName;
1674     ::rtl::OUString sFormatName    = m_sOOoXMLFormatName;
1675     ::rtl::OUString sFormatVersion = m_sOOoXMLFormatVersion;
1676     ::rtl::OUString sActLocale     = m_sActLocale    ;
1677     aLock.clear();
1678     // <- SAFE ----------------------------------
1679 
1680     css::uno::Any aVal = xNode->getByName(PROPNAME_UINAME);
1681     css::uno::Reference< css::container::XNameAccess > xUIName;
1682     if (!(aVal >>= xUIName) && !xUIName.is())
1683         return;
1684 
1685     const ::comphelper::SequenceAsVector< ::rtl::OUString >                 lLocales(xUIName->getElementNames());
1686           ::comphelper::SequenceAsVector< ::rtl::OUString >::const_iterator pLocale ;
1687           ::comphelper::SequenceAsHashMap                                   lUINames;
1688 
1689     // patch %productname%, %oooxmlformatname% and %oooxmlformatversion%
1690     for (  pLocale  = lLocales.begin();
1691            pLocale != lLocales.end()  ;
1692          ++pLocale                    )
1693     {
1694         const ::rtl::OUString& sLocale = *pLocale;
1695 
1696         ::rtl::OUString sValue;
1697         xUIName->getByName(sLocale) >>= sValue;
1698 
1699         // replace %productname%
1700         sal_Int32 nIndex = sValue.indexOf(PRODUCTNAME_VAR);
1701         while(nIndex != -1)
1702         {
1703             sValue = sValue.replaceAt(nIndex, PRODUCTNAME_VAR.getLength(), sProductName);
1704             nIndex = sValue.indexOf(PRODUCTNAME_VAR, nIndex);
1705         }
1706         // replace %oooxmlformatname%
1707         nIndex = sValue.indexOf(FORMATNAME_VAR);
1708         while(nIndex != -1)
1709         {
1710             sValue = sValue.replaceAt(nIndex, FORMATNAME_VAR.getLength(), sFormatName);
1711             nIndex = sValue.indexOf(FORMATNAME_VAR, nIndex);
1712         }
1713         // replace %oooxmlformatversion%
1714         nIndex = sValue.indexOf(FORMATVERSION_VAR);
1715         while(nIndex != -1)
1716         {
1717             sValue = sValue.replaceAt(nIndex, FORMATVERSION_VAR.getLength(), sFormatVersion);
1718             nIndex = sValue.indexOf(FORMATVERSION_VAR, nIndex);
1719         }
1720 
1721         lUINames[sLocale] <<= sValue;
1722     }
1723 
1724     aVal <<= lUINames.getAsConstPropertyValueList();
1725     rItem[PROPNAME_UINAMES] = aVal;
1726 
1727     // find right UIName for current office locale
1728     // Use fallbacks too!
1729     pLocale = ::comphelper::Locale::getFallback(lLocales, sActLocale);
1730     if (pLocale == lLocales.end())
1731     {
1732         #if OSL_DEBUG_LEVEL > 0
1733             ::rtl::OUString sName = rItem.getUnpackedValueOrDefault(PROPNAME_NAME, ::rtl::OUString());
1734 
1735             ::rtl::OUStringBuffer sMsg(256);
1736             sMsg.appendAscii("Fallback scenario for filter or type '"           );
1737             sMsg.append     (sName                                              );
1738             sMsg.appendAscii("' and locale '"                                   );
1739             sMsg.append     (sActLocale                                         );
1740             sMsg.appendAscii("' failed. Please check your filter configuration.");
1741 
1742             OSL_ENSURE(sal_False, _FILTER_CONFIG_TO_ASCII_(sMsg.makeStringAndClear()));
1743         #endif
1744         return;
1745     }
1746 
1747     const ::rtl::OUString& sLocale = *pLocale;
1748     ::comphelper::SequenceAsHashMap::const_iterator pUIName = lUINames.find(sLocale);
1749     if (pUIName != lUINames.end())
1750         rItem[PROPNAME_UINAME] = pUIName->second;
1751 }
1752 
1753 /*-----------------------------------------------
1754 	26.11.2003 12:56
1755 -----------------------------------------------*/
impl_savePatchUINames(const css::uno::Reference<css::container::XNameReplace> & xNode,const CacheItem & rItem)1756 void FilterCache::impl_savePatchUINames(const css::uno::Reference< css::container::XNameReplace >& xNode,
1757                                         const CacheItem&                                           rItem)
1758     throw(css::uno::Exception)
1759 {
1760     css::uno::Reference< css::container::XNameContainer > xAdd  (xNode, css::uno::UNO_QUERY);
1761     css::uno::Reference< css::container::XNameAccess >    xCheck(xNode, css::uno::UNO_QUERY);
1762 
1763     css::uno::Sequence< css::beans::PropertyValue > lUINames = rItem.getUnpackedValueOrDefault(PROPNAME_UINAMES, css::uno::Sequence< css::beans::PropertyValue >());
1764     sal_Int32                                       c        = lUINames.getLength();
1765     const css::beans::PropertyValue*                pUINames = lUINames.getConstArray();
1766 
1767     for (sal_Int32 i=0; i<c; ++i)
1768 	{
1769 		if (xCheck->hasByName(pUINames[i].Name))
1770 			xNode->replaceByName(pUINames[i].Name, pUINames[i].Value);
1771 		else
1772 			xAdd->insertByName(pUINames[i].Name, pUINames[i].Value);
1773 	}
1774 }
1775 
1776 /*-----------------------------------------------
1777 	29.10.2003 13:17
1778 	TODO
1779 		clarify, how the real problem behind the
1780 		wrong constructed CacheItem instance (which
1781 		will force a crash during destruction)
1782 		can be solved ...
1783 -----------------------------------------------*/
impl_loadItem(const css::uno::Reference<css::container::XNameAccess> & xSet,EItemType eType,const::rtl::OUString & sItem,EReadOption eOption)1784 CacheItem FilterCache::impl_loadItem(const css::uno::Reference< css::container::XNameAccess >& xSet   ,
1785                                            EItemType                                           eType  ,
1786                                      const ::rtl::OUString&                                    sItem  ,
1787                                            EReadOption                                         eOption)
1788     throw(css::uno::Exception)
1789 {
1790     // try to get an API object, which points directly to the
1791     // requested item. If it fail an exception should occur and
1792     // break this operation. Of course returned API object must be
1793     // checked too.
1794     css::uno::Reference< css::container::XNameAccess > xItem;
1795     #ifdef WORKAROUND_EXCEPTION_PROBLEM
1796     try
1797     {
1798     #endif
1799         css::uno::Any aVal = xSet->getByName(sItem);
1800         if (!(aVal >>= xItem) || !xItem.is())
1801         {
1802             ::rtl::OUStringBuffer sMsg(256);
1803             sMsg.appendAscii("found corrupted item \"");
1804             sMsg.append     (sItem                    );
1805             sMsg.appendAscii("\"."                    );
1806             throw css::uno::Exception(sMsg.makeStringAndClear()                    ,
1807                                       css::uno::Reference< css::uno::XInterface >());
1808         }
1809     #ifdef WORKAROUND_EXCEPTION_PROBLEM
1810     }
1811     catch(const css::container::NoSuchElementException&)
1812     {
1813         throw;
1814     }
1815     #endif
1816 
1817     // The internal name of an item must(!) be part of the property
1818     // set too. Of course it's already used as key into the e.g. outside
1819     // used hash map ... but some of our API methods provide
1820     // this property set as result only. But the user of this CacheItem
1821     // should know, which value the key names has :-) IT'S IMPORTANT!
1822     CacheItem aItem;
1823     aItem[PROPNAME_NAME] = css::uno::makeAny(sItem);
1824     switch(eType)
1825     {
1826         //---------------------------------------
1827         case E_TYPE :
1828         {
1829             // read standard properties of a type
1830             if (
1831                 (eOption == E_READ_STANDARD) ||
1832                 (eOption == E_READ_ALL     )
1833                )
1834             {
1835                 aItem[PROPNAME_PREFERREDFILTER] = xItem->getByName(PROPNAME_PREFERREDFILTER);
1836                 aItem[PROPNAME_DETECTSERVICE  ] = xItem->getByName(PROPNAME_DETECTSERVICE  );
1837                 aItem[PROPNAME_URLPATTERN     ] = xItem->getByName(PROPNAME_URLPATTERN     );
1838                 aItem[PROPNAME_EXTENSIONS     ] = xItem->getByName(PROPNAME_EXTENSIONS     );
1839                 aItem[PROPNAME_PREFERRED      ] = xItem->getByName(PROPNAME_PREFERRED      );
1840                 aItem[PROPNAME_CLIPBOARDFORMAT] = xItem->getByName(PROPNAME_CLIPBOARDFORMAT);
1841             }
1842             // read optional properties of a type
1843             // no else here! Is an additional switch ...
1844             if (
1845                 (eOption == E_READ_UPDATE) ||
1846                 (eOption == E_READ_ALL   )
1847                )
1848             {
1849                 aItem[PROPNAME_MEDIATYPE      ] = xItem->getByName(PROPNAME_MEDIATYPE      );
1850                 impl_readPatchUINames(xItem, aItem);
1851             }
1852         }
1853         break;
1854 
1855         //---------------------------------------
1856         case E_FILTER :
1857         {
1858             // read standard properties of a filter
1859             if (
1860                 (eOption == E_READ_STANDARD) ||
1861                 (eOption == E_READ_ALL     )
1862                )
1863             {
1864                 aItem[PROPNAME_TYPE             ] = xItem->getByName(PROPNAME_TYPE             );
1865                 aItem[PROPNAME_FILEFORMATVERSION] = xItem->getByName(PROPNAME_FILEFORMATVERSION);
1866                 aItem[PROPNAME_UICOMPONENT      ] = xItem->getByName(PROPNAME_UICOMPONENT      );
1867                 aItem[PROPNAME_FILTERSERVICE    ] = xItem->getByName(PROPNAME_FILTERSERVICE    );
1868                 aItem[PROPNAME_DOCUMENTSERVICE  ] = xItem->getByName(PROPNAME_DOCUMENTSERVICE  );
1869 
1870                 // special handling for flags! Convert it from a list of names to its
1871                 // int representation ...
1872                 css::uno::Sequence< ::rtl::OUString > lFlagNames;
1873                 if (xItem->getByName(PROPNAME_FLAGS) >>= lFlagNames)
1874                     aItem[PROPNAME_FLAGS] <<= FilterCache::impl_convertFlagNames2FlagField(lFlagNames);
1875             }
1876             // read optional properties of a filter
1877             // no else here! It's an additional switch ...
1878             if (
1879                 (eOption == E_READ_UPDATE) ||
1880                 (eOption == E_READ_ALL   )
1881                )
1882             {
1883                 aItem[PROPNAME_USERDATA    ] = xItem->getByName(PROPNAME_USERDATA    );
1884                 aItem[PROPNAME_TEMPLATENAME] = xItem->getByName(PROPNAME_TEMPLATENAME);
1885 //TODO remove it if moving of filter uinames to type uinames
1886 //       will be finished really
1887 #ifdef AS_ENABLE_FILTER_UINAMES
1888                 impl_readPatchUINames(xItem, aItem);
1889 #endif // AS_ENABLE_FILTER_UINAMES
1890             }
1891         }
1892         break;
1893 
1894         //---------------------------------------
1895         case E_FRAMELOADER :
1896         case E_CONTENTHANDLER :
1897         {
1898             aItem[PROPNAME_TYPES] = xItem->getByName(PROPNAME_TYPES);
1899         }
1900         break;
1901 		default: break;
1902     }
1903 
1904     return aItem;
1905 }
1906 
1907 /*-----------------------------------------------
1908 	27.10.2003 08:47
1909 -----------------------------------------------*/
impl_loadItemOnDemand(EItemType eType,const::rtl::OUString & sItem)1910 CacheItemList::iterator FilterCache::impl_loadItemOnDemand(      EItemType        eType,
1911                                                            const ::rtl::OUString& sItem)
1912     throw(css::uno::Exception)
1913 {
1914     CacheItemList*                              pList   = 0;
1915     css::uno::Reference< css::uno::XInterface > xConfig    ;
1916     ::rtl::OUString                             sSet       ;
1917 
1918     switch(eType)
1919     {
1920         case E_TYPE :
1921         {
1922             pList   = &m_lTypes;
1923             xConfig = impl_openConfig(E_PROVIDER_TYPES);
1924             sSet    = CFGSET_TYPES;
1925         }
1926         break;
1927 
1928         case E_FILTER :
1929         {
1930             pList   = &m_lFilters;
1931             xConfig = impl_openConfig(E_PROVIDER_FILTERS);
1932             sSet    = CFGSET_FILTERS;
1933         }
1934         break;
1935 
1936         case E_FRAMELOADER :
1937         {
1938             pList   = &m_lFrameLoaders;
1939             xConfig = impl_openConfig(E_PROVIDER_OTHERS);
1940             sSet    = CFGSET_FRAMELOADERS;
1941         }
1942         break;
1943 
1944         case E_CONTENTHANDLER :
1945         {
1946             pList   = &m_lContentHandlers;
1947             xConfig = impl_openConfig(E_PROVIDER_OTHERS);
1948             sSet    = CFGSET_CONTENTHANDLERS;
1949         }
1950         break;
1951 
1952         case E_DETECTSERVICE :
1953         {
1954             OSL_ENSURE(sal_False, "Can't load detect services on demand. Who uses this unsupported feature?");
1955         }
1956         break;
1957     }
1958 
1959     css::uno::Reference< css::container::XNameAccess > xRoot(xConfig, css::uno::UNO_QUERY_THROW);
1960     css::uno::Reference< css::container::XNameAccess > xSet ;
1961     xRoot->getByName(sSet) >>= xSet;
1962 
1963     CacheItemList::iterator pItemInCache  = pList->find(sItem);
1964     sal_Bool                bItemInConfig = xSet->hasByName(sItem);
1965 
1966     if (bItemInConfig)
1967     {
1968         CacheItem aItem;
1969 	    CacheItem::iterator pDbgTest = aItem.find(PROPNAME_NAME);
1970 	    aItem = impl_loadItem(xSet, eType, sItem, E_READ_ALL);
1971         (*pList)[sItem] = aItem;
1972         _FILTER_CONFIG_LOG_2_("impl_loadItemOnDemand(%d, \"%s\") ... OK", (int)eType, _FILTER_CONFIG_TO_ASCII_(sItem).getStr())
1973     }
1974     else
1975     {
1976         if (pItemInCache != pList->end())
1977             pList->erase(pItemInCache);
1978         // OK - this item does not exist inside configuration.
1979         // And we already updated our internal cache.
1980         // But the outside code needs this NoSuchElementException
1981         // to know, that this item does not exist.
1982         // Nobody checks the iterator!
1983         throw css::container::NoSuchElementException();
1984     }
1985 
1986     return pList->find(sItem);
1987 }
1988 
1989 /*-----------------------------------------------
1990 	20.10.2003 09:38
1991 -----------------------------------------------*/
impl_saveItem(const css::uno::Reference<css::container::XNameReplace> & xItem,EItemType eType,const CacheItem & aItem)1992 void FilterCache::impl_saveItem(const css::uno::Reference< css::container::XNameReplace >& xItem,
1993                                       EItemType                                            eType,
1994                                 const CacheItem&                                           aItem)
1995     throw(css::uno::Exception)
1996 {
1997     CacheItem::const_iterator pIt;
1998     switch(eType)
1999     {
2000         //---------------------------------------
2001         case E_TYPE :
2002         {
2003             pIt = aItem.find(PROPNAME_PREFERREDFILTER);
2004             if (pIt != aItem.end())
2005                 xItem->replaceByName(PROPNAME_PREFERREDFILTER, pIt->second);
2006             pIt = aItem.find(PROPNAME_DETECTSERVICE);
2007             if (pIt != aItem.end())
2008                 xItem->replaceByName(PROPNAME_DETECTSERVICE, pIt->second);
2009             pIt = aItem.find(PROPNAME_URLPATTERN);
2010             if (pIt != aItem.end())
2011                 xItem->replaceByName(PROPNAME_URLPATTERN, pIt->second);
2012             pIt = aItem.find(PROPNAME_EXTENSIONS);
2013             if (pIt != aItem.end())
2014                 xItem->replaceByName(PROPNAME_EXTENSIONS, pIt->second);
2015             pIt = aItem.find(PROPNAME_PREFERRED);
2016             if (pIt != aItem.end())
2017                 xItem->replaceByName(PROPNAME_PREFERRED, pIt->second);
2018             pIt = aItem.find(PROPNAME_MEDIATYPE);
2019             if (pIt != aItem.end())
2020                 xItem->replaceByName(PROPNAME_MEDIATYPE, pIt->second);
2021             pIt = aItem.find(PROPNAME_CLIPBOARDFORMAT);
2022             if (pIt != aItem.end())
2023                 xItem->replaceByName(PROPNAME_CLIPBOARDFORMAT, pIt->second);
2024 
2025             css::uno::Reference< css::container::XNameReplace > xUIName;
2026             xItem->getByName(PROPNAME_UINAME) >>= xUIName;
2027             impl_savePatchUINames(xUIName, aItem);
2028         }
2029         break;
2030 
2031         //---------------------------------------
2032         case E_FILTER :
2033         {
2034             pIt = aItem.find(PROPNAME_TYPE);
2035             if (pIt != aItem.end())
2036                 xItem->replaceByName(PROPNAME_TYPE, pIt->second);
2037             pIt = aItem.find(PROPNAME_FILEFORMATVERSION);
2038             if (pIt != aItem.end())
2039                 xItem->replaceByName(PROPNAME_FILEFORMATVERSION, pIt->second);
2040             pIt = aItem.find(PROPNAME_UICOMPONENT);
2041             if (pIt != aItem.end())
2042                 xItem->replaceByName(PROPNAME_UICOMPONENT, pIt->second);
2043             pIt = aItem.find(PROPNAME_FILTERSERVICE);
2044             if (pIt != aItem.end())
2045                 xItem->replaceByName(PROPNAME_FILTERSERVICE, pIt->second);
2046             pIt = aItem.find(PROPNAME_DOCUMENTSERVICE);
2047             if (pIt != aItem.end())
2048                 xItem->replaceByName(PROPNAME_DOCUMENTSERVICE, pIt->second);
2049             pIt = aItem.find(PROPNAME_USERDATA);
2050             if (pIt != aItem.end())
2051                 xItem->replaceByName(PROPNAME_USERDATA, pIt->second);
2052             pIt = aItem.find(PROPNAME_TEMPLATENAME);
2053             if (pIt != aItem.end())
2054                 xItem->replaceByName(PROPNAME_TEMPLATENAME, pIt->second);
2055 
2056             // special handling for flags! Convert it from an integer flag field back
2057             // to a list of names ...
2058             // But note: because we work directly on a reference to the cache item,
2059             // it's not allowed to change the value here. We must work on a copy!
2060             sal_Int32 nFlags = 0;
2061             pIt = aItem.find(PROPNAME_FLAGS);
2062             if (pIt != aItem.end())
2063             {
2064                 pIt->second >>= nFlags;
2065                 css::uno::Any aFlagNameList;
2066                 aFlagNameList <<= FilterCache::impl_convertFlagField2FlagNames(nFlags);
2067                 xItem->replaceByName(PROPNAME_FLAGS, aFlagNameList);
2068             }
2069 
2070 //TODO remove it if moving of filter uinames to type uinames
2071 //       will be finished really
2072 #ifdef AS_ENABLE_FILTER_UINAMES
2073             css::uno::Reference< css::container::XNameReplace > xUIName;
2074             xItem->getByName(PROPNAME_UINAME) >>= xUIName;
2075             impl_savePatchUINames(xUIName, aItem);
2076 #endif //  AS_ENABLE_FILTER_UINAMES
2077         }
2078         break;
2079 
2080         //---------------------------------------
2081         case E_FRAMELOADER :
2082         case E_CONTENTHANDLER :
2083         {
2084             pIt = aItem.find(PROPNAME_TYPES);
2085             if (pIt != aItem.end())
2086                 xItem->replaceByName(PROPNAME_TYPES, pIt->second);
2087         }
2088         break;
2089 		default: break;
2090     }
2091 }
2092 
2093 /*-----------------------------------------------
2094 	20.10.2003 09:45
2095 	static! => no locks necessary
2096 -----------------------------------------------*/
impl_convertFlagField2FlagNames(sal_Int32 nFlags)2097 css::uno::Sequence< ::rtl::OUString > FilterCache::impl_convertFlagField2FlagNames(sal_Int32 nFlags)
2098 {
2099     OUStringList lFlagNames;
2100 
2101     if ((nFlags & FLAGVAL_3RDPARTYFILTER   ) == FLAGVAL_3RDPARTYFILTER   ) lFlagNames.push_back(FLAGNAME_3RDPARTYFILTER   );
2102     if ((nFlags & FLAGVAL_ALIEN            ) == FLAGVAL_ALIEN            ) lFlagNames.push_back(FLAGNAME_ALIEN            );
2103     if ((nFlags & FLAGVAL_ASYNCHRON        ) == FLAGVAL_ASYNCHRON        ) lFlagNames.push_back(FLAGNAME_ASYNCHRON        );
2104     if ((nFlags & FLAGVAL_BROWSERPREFERRED ) == FLAGVAL_BROWSERPREFERRED ) lFlagNames.push_back(FLAGNAME_BROWSERPREFERRED );
2105     if ((nFlags & FLAGVAL_CONSULTSERVICE   ) == FLAGVAL_CONSULTSERVICE   ) lFlagNames.push_back(FLAGNAME_CONSULTSERVICE   );
2106     if ((nFlags & FLAGVAL_DEFAULT          ) == FLAGVAL_DEFAULT          ) lFlagNames.push_back(FLAGNAME_DEFAULT          );
2107     if ((nFlags & FLAGVAL_ENCRYPTION       ) == FLAGVAL_ENCRYPTION       ) lFlagNames.push_back(FLAGNAME_ENCRYPTION       );
2108     if ((nFlags & FLAGVAL_EXPORT           ) == FLAGVAL_EXPORT           ) lFlagNames.push_back(FLAGNAME_EXPORT           );
2109     if ((nFlags & FLAGVAL_IMPORT           ) == FLAGVAL_IMPORT           ) lFlagNames.push_back(FLAGNAME_IMPORT           );
2110     if ((nFlags & FLAGVAL_INTERNAL         ) == FLAGVAL_INTERNAL         ) lFlagNames.push_back(FLAGNAME_INTERNAL         );
2111     if ((nFlags & FLAGVAL_NOTINCHOOSER     ) == FLAGVAL_NOTINCHOOSER     ) lFlagNames.push_back(FLAGNAME_NOTINCHOOSER     );
2112     if ((nFlags & FLAGVAL_NOTINFILEDIALOG  ) == FLAGVAL_NOTINFILEDIALOG  ) lFlagNames.push_back(FLAGNAME_NOTINFILEDIALOG  );
2113     if ((nFlags & FLAGVAL_NOTINSTALLED     ) == FLAGVAL_NOTINSTALLED     ) lFlagNames.push_back(FLAGNAME_NOTINSTALLED     );
2114     if ((nFlags & FLAGVAL_OWN              ) == FLAGVAL_OWN              ) lFlagNames.push_back(FLAGNAME_OWN              );
2115     if ((nFlags & FLAGVAL_PACKED           ) == FLAGVAL_PACKED           ) lFlagNames.push_back(FLAGNAME_PACKED           );
2116     if ((nFlags & FLAGVAL_PASSWORDTOMODIFY ) == FLAGVAL_PASSWORDTOMODIFY ) lFlagNames.push_back(FLAGNAME_PASSWORDTOMODIFY );
2117     if ((nFlags & FLAGVAL_PREFERRED        ) == FLAGVAL_PREFERRED        ) lFlagNames.push_back(FLAGNAME_PREFERRED        );
2118     if ((nFlags & FLAGVAL_READONLY         ) == FLAGVAL_READONLY         ) lFlagNames.push_back(FLAGNAME_READONLY         );
2119     if ((nFlags & FLAGVAL_SUPPORTSSELECTION) == FLAGVAL_SUPPORTSSELECTION) lFlagNames.push_back(FLAGNAME_SUPPORTSSELECTION);
2120     if ((nFlags & FLAGVAL_TEMPLATE         ) == FLAGVAL_TEMPLATE         ) lFlagNames.push_back(FLAGNAME_TEMPLATE         );
2121     if ((nFlags & FLAGVAL_TEMPLATEPATH     ) == FLAGVAL_TEMPLATEPATH     ) lFlagNames.push_back(FLAGNAME_TEMPLATEPATH     );
2122     if ((nFlags & FLAGVAL_USESOPTIONS      ) == FLAGVAL_USESOPTIONS      ) lFlagNames.push_back(FLAGNAME_USESOPTIONS      );
2123     if ((nFlags & FLAGVAL_COMBINED         ) == FLAGVAL_COMBINED         ) lFlagNames.push_back(FLAGNAME_COMBINED         );
2124 
2125     return lFlagNames.getAsConstList();
2126 }
2127 
2128 /*-----------------------------------------------
2129 	27.06.2003 09:26
2130 	static! => no locks necessary
2131 -----------------------------------------------*/
impl_convertFlagNames2FlagField(const css::uno::Sequence<::rtl::OUString> & lNames)2132 sal_Int32 FilterCache::impl_convertFlagNames2FlagField(const css::uno::Sequence< ::rtl::OUString >& lNames)
2133 {
2134     sal_Int32 nField = 0;
2135 
2136     const ::rtl::OUString* pNames = lNames.getConstArray();
2137           sal_Int32        c      = lNames.getLength();
2138     for (sal_Int32 i=0; i<c; ++i)
2139     {
2140         if (pNames[i].equals(FLAGNAME_3RDPARTYFILTER))
2141         {
2142             nField |= FLAGVAL_3RDPARTYFILTER;
2143             continue;
2144         }
2145         if (pNames[i].equals(FLAGNAME_ALIEN))
2146         {
2147             nField |= FLAGVAL_ALIEN;
2148             continue;
2149         }
2150         if (pNames[i].equals(FLAGNAME_ASYNCHRON))
2151         {
2152             nField |= FLAGVAL_ASYNCHRON;
2153             continue;
2154         }
2155         if (pNames[i].equals(FLAGNAME_BROWSERPREFERRED))
2156         {
2157             nField |= FLAGVAL_BROWSERPREFERRED;
2158             continue;
2159         }
2160         if (pNames[i].equals(FLAGNAME_CONSULTSERVICE))
2161         {
2162             nField |= FLAGVAL_CONSULTSERVICE;
2163             continue;
2164         }
2165         if (pNames[i].equals(FLAGNAME_DEFAULT))
2166         {
2167             nField |= FLAGVAL_DEFAULT;
2168             continue;
2169         }
2170         if (pNames[i].equals(FLAGNAME_ENCRYPTION))
2171         {
2172             nField |= FLAGVAL_ENCRYPTION;
2173             continue;
2174         }
2175         if (pNames[i].equals(FLAGNAME_EXPORT))
2176         {
2177             nField |= FLAGVAL_EXPORT;
2178             continue;
2179         }
2180         if (pNames[i].equals(FLAGNAME_IMPORT))
2181         {
2182             nField |= FLAGVAL_IMPORT;
2183             continue;
2184         }
2185         if (pNames[i].equals(FLAGNAME_INTERNAL))
2186         {
2187             nField |= FLAGVAL_INTERNAL;
2188             continue;
2189         }
2190         if (pNames[i].equals(FLAGNAME_NOTINCHOOSER))
2191         {
2192             nField |= FLAGVAL_NOTINCHOOSER;
2193             continue;
2194         }
2195         if (pNames[i].equals(FLAGNAME_NOTINFILEDIALOG))
2196         {
2197             nField |= FLAGVAL_NOTINFILEDIALOG;
2198             continue;
2199         }
2200         if (pNames[i].equals(FLAGNAME_NOTINSTALLED))
2201         {
2202             nField |= FLAGVAL_NOTINSTALLED;
2203             continue;
2204         }
2205         if (pNames[i].equals(FLAGNAME_OWN))
2206         {
2207             nField |= FLAGVAL_OWN;
2208             continue;
2209         }
2210         if (pNames[i].equals(FLAGNAME_PACKED))
2211         {
2212             nField |= FLAGVAL_PACKED;
2213             continue;
2214         }
2215         if (pNames[i].equals(FLAGNAME_PASSWORDTOMODIFY))
2216         {
2217             nField |= FLAGVAL_PASSWORDTOMODIFY;
2218             continue;
2219         }
2220         if (pNames[i].equals(FLAGNAME_PREFERRED))
2221         {
2222             nField |= FLAGVAL_PREFERRED;
2223             continue;
2224         }
2225         if (pNames[i].equals(FLAGNAME_READONLY))
2226         {
2227             nField |= FLAGVAL_READONLY;
2228             continue;
2229         }
2230         if (pNames[i].equals(FLAGNAME_SUPPORTSSELECTION))
2231         {
2232             nField |= FLAGVAL_SUPPORTSSELECTION;
2233             continue;
2234         }
2235         if (pNames[i].equals(FLAGNAME_TEMPLATE))
2236         {
2237             nField |= FLAGVAL_TEMPLATE;
2238             continue;
2239         }
2240         if (pNames[i].equals(FLAGNAME_TEMPLATEPATH))
2241         {
2242             nField |= FLAGVAL_TEMPLATEPATH;
2243             continue;
2244         }
2245         if (pNames[i].equals(FLAGNAME_USESOPTIONS))
2246         {
2247             nField |= FLAGVAL_USESOPTIONS;
2248             continue;
2249         }
2250         if (pNames[i].equals(FLAGNAME_COMBINED))
2251         {
2252             nField |= FLAGVAL_COMBINED;
2253             continue;
2254         }
2255     }
2256 
2257     return nField;
2258 }
2259 
2260 /*-----------------------------------------------
2261 	12.02.2004 08:40
2262 -----------------------------------------------*/
impl_interpretDataVal4Type(const::rtl::OUString & sValue,sal_Int32 nProp,CacheItem & rItem)2263 void FilterCache::impl_interpretDataVal4Type(const ::rtl::OUString& sValue,
2264                                                    sal_Int32        nProp ,
2265                                                    CacheItem&       rItem )
2266 {
2267     switch(nProp)
2268     {
2269         // Preferred
2270         case 0:     {
2271                         if (sValue.toInt32() == 1)
2272                             rItem[PROPNAME_PREFERRED] = css::uno::makeAny(sal_True);
2273                         else
2274                             rItem[PROPNAME_PREFERRED] = css::uno::makeAny(sal_False);
2275                     }
2276                     break;
2277         // MediaType
2278         case 1:     rItem[PROPNAME_MEDIATYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2279                     break;
2280         // ClipboardFormat
2281         case 2:     rItem[PROPNAME_CLIPBOARDFORMAT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2282                     break;
2283         // URLPattern
2284         case 3:     rItem[PROPNAME_URLPATTERN] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList();
2285                     break;
2286         // Extensions
2287         case 4:     rItem[PROPNAME_EXTENSIONS] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList();
2288                     break;
2289     }
2290 }
2291 
2292 /*-----------------------------------------------
2293 	12.02.2004 08:50
2294 -----------------------------------------------*/
impl_interpretDataVal4Filter(const::rtl::OUString & sValue,sal_Int32 nProp,CacheItem & rItem)2295 void FilterCache::impl_interpretDataVal4Filter(const ::rtl::OUString& sValue,
2296                                                      sal_Int32        nProp ,
2297                                                      CacheItem&       rItem )
2298 {
2299     switch(nProp)
2300     {
2301         // Order
2302         case 0:     {
2303                         sal_Int32 nOrder = sValue.toInt32();
2304                         if (nOrder > 0)
2305                         {
2306                             OSL_ENSURE(sal_False, "FilterCache::impl_interpretDataVal4Filter()\nCant move Order value from filter to type on demand!\n");
2307                             _FILTER_CONFIG_LOG_2_("impl_interpretDataVal4Filter(%d, \"%s\") ... OK", (int)eType, _FILTER_CONFIG_TO_ASCII_(rItem).getStr())
2308                         }
2309                     }
2310                     break;
2311         // Type
2312         case 1:     rItem[PROPNAME_TYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2313                     break;
2314         // DocumentService
2315         case 2:     rItem[PROPNAME_DOCUMENTSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2316                     break;
2317         // FilterService
2318         case 3:     rItem[PROPNAME_FILTERSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2319                     break;
2320         // Flags
2321         case 4:     rItem[PROPNAME_FLAGS] <<= sValue.toInt32();
2322                     break;
2323         // UserData
2324         case 5:     rItem[PROPNAME_USERDATA] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList();
2325                     break;
2326         // FileFormatVersion
2327         case 6:     rItem[PROPNAME_FILEFORMATVERSION] <<= sValue.toInt32();
2328                     break;
2329         // TemplateName
2330         case 7:     rItem[PROPNAME_TEMPLATENAME] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2331                     break;
2332         // [optional!] UIComponent
2333         case 8:     rItem[PROPNAME_UICOMPONENT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2334                     break;
2335     }
2336 }
2337 
2338 /*-----------------------------------------------
2339 	12.02.2004 08:30
2340     TODO work on a cache copy first, which can be flushed afterwards
2341          That would be usefully to guarantee a consistent cache.
2342 -----------------------------------------------*/
impl_readOldFormat()2343 void FilterCache::impl_readOldFormat()
2344     throw(css::uno::Exception)
2345 {
2346     static ::rtl::OUString TYPES_SET  = ::rtl::OUString::createFromAscii("Types"  );
2347     static ::rtl::OUString FILTER_SET = ::rtl::OUString::createFromAscii("Filters");
2348 
2349     // Attention: Opening/Reading of this old configuration format has to be handled gracefully.
2350     // It's optional and shouldn't disturb our normal work!
2351     // E.g. we must check, if the package exists ...
2352 
2353     css::uno::Reference< css::container::XNameAccess > xCfg;
2354     try
2355     {
2356         css::uno::Reference< css::uno::XInterface > xInt = impl_openConfig(E_PROVIDER_OLD);
2357         xCfg = css::uno::Reference< css::container::XNameAccess >(xInt, css::uno::UNO_QUERY_THROW);
2358     }
2359     /* corrupt filter addon ? because it's external (optional) code .. we can ignore it. Addon won't work then ...
2360        but that seems to be acceptable.
2361        see #139088# for further informations
2362     */
2363     catch(const css::uno::Exception&)
2364         { return; }
2365 
2366     // Maybe there is no type set ...
2367     if (xCfg->hasByName(TYPES_SET))
2368     {
2369         css::uno::Reference< css::container::XNameAccess > xSet;
2370         xCfg->getByName(TYPES_SET) >>= xSet;
2371         const css::uno::Sequence< ::rtl::OUString > lItems = xSet->getElementNames();
2372         const ::rtl::OUString*                      pItems = lItems.getConstArray();
2373         for (sal_Int32 i=0; i<lItems.getLength(); ++i)
2374             m_lTypes[pItems[i]] = impl_readOldItem(xSet, E_TYPE, pItems[i]);
2375     }
2376 
2377     // Maybe there is no filter set ...
2378     if (xCfg->hasByName(FILTER_SET))
2379     {
2380         css::uno::Reference< css::container::XNameAccess > xSet;
2381         xCfg->getByName(FILTER_SET) >>= xSet;
2382         const css::uno::Sequence< ::rtl::OUString > lItems = xSet->getElementNames();
2383         const ::rtl::OUString*                      pItems = lItems.getConstArray();
2384         for (sal_Int32 i=0; i<lItems.getLength(); ++i)
2385             m_lFilters[pItems[i]] = impl_readOldItem(xSet, E_FILTER, pItems[i]);
2386     }
2387 }
2388 
2389 /*-----------------------------------------------
2390 	12.02.2004 08:30
2391 -----------------------------------------------*/
impl_readOldItem(const css::uno::Reference<css::container::XNameAccess> & xSet,EItemType eType,const::rtl::OUString & sItem)2392 CacheItem FilterCache::impl_readOldItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
2393                                               EItemType                                           eType,
2394                                         const ::rtl::OUString&                                    sItem)
2395     throw(css::uno::Exception)
2396 {
2397     css::uno::Reference< css::container::XNameAccess > xItem;
2398     xSet->getByName(sItem) >>= xItem;
2399     if (!xItem.is())
2400         throw css::uno::Exception(
2401                 ::rtl::OUString::createFromAscii("Can't read old item."),
2402                 css::uno::Reference< css::uno::XInterface >());
2403 
2404     CacheItem aItem;
2405     aItem[PROPNAME_NAME] <<= sItem;
2406 
2407     // Installed flag ...
2408     // Isn't used any longer!
2409 
2410     // UIName
2411     impl_readPatchUINames(xItem, aItem);
2412 
2413     // Data
2414     ::rtl::OUString sData;
2415     OUStringList    lData;
2416     xItem->getByName(::rtl::OUString::createFromAscii("Data")) >>= sData;
2417     lData = impl_tokenizeString(sData, (sal_Unicode)',');
2418     if (
2419         (!sData.getLength()) ||
2420         (lData.size()<1    )
2421        )
2422     {
2423         throw css::uno::Exception(
2424                 ::rtl::OUString::createFromAscii("Can't read old item property DATA."),
2425                 css::uno::Reference< css::uno::XInterface >());
2426     }
2427 
2428     sal_Int32 nProp = 0;
2429     for (OUStringList::const_iterator pProp  = lData.begin();
2430                                       pProp != lData.end()  ;
2431                                     ++pProp                 )
2432     {
2433         const ::rtl::OUString& sProp = *pProp;
2434         switch(eType)
2435         {
2436             case E_TYPE :
2437                 impl_interpretDataVal4Type(sProp, nProp, aItem);
2438                 break;
2439 
2440             case E_FILTER :
2441                 impl_interpretDataVal4Filter(sProp, nProp, aItem);
2442                 break;
2443 			default: break;
2444         }
2445         ++nProp;
2446     }
2447 
2448     return aItem;
2449 }
2450 
2451 /*-----------------------------------------------
2452 	12.02.2004 08:15
2453 -----------------------------------------------*/
impl_tokenizeString(const::rtl::OUString & sData,sal_Unicode cSeperator)2454 OUStringList FilterCache::impl_tokenizeString(const ::rtl::OUString& sData     ,
2455                                                     sal_Unicode      cSeperator)
2456 {
2457     OUStringList lData  ;
2458     sal_Int32    nToken = 0;
2459     do
2460     {
2461         ::rtl::OUString sToken = sData.getToken(0, cSeperator, nToken);
2462         lData.push_back(sToken);
2463     }
2464     while(nToken >= 0);
2465     return lData;
2466 }
2467 
2468 #if OSL_DEBUG_LEVEL > 0
2469 /*-----------------------------------------------*/
impl_searchFrameLoaderForType(const::rtl::OUString & sType) const2470 ::rtl::OUString FilterCache::impl_searchFrameLoaderForType(const ::rtl::OUString& sType) const
2471 {
2472     CacheItemList::const_iterator pIt;
2473     for (  pIt  = m_lFrameLoaders.begin();
2474            pIt != m_lFrameLoaders.end()  ;
2475          ++pIt                           )
2476     {
2477         const ::rtl::OUString& sItem = pIt->first;
2478         ::comphelper::SequenceAsHashMap lProps(pIt->second);
2479         OUStringList                    lTypes(lProps[PROPNAME_TYPES]);
2480 
2481         if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end())
2482             return sItem;
2483     }
2484 
2485     return ::rtl::OUString();
2486 }
2487 
2488 /*-----------------------------------------------*/
impl_searchContentHandlerForType(const::rtl::OUString & sType) const2489 ::rtl::OUString FilterCache::impl_searchContentHandlerForType(const ::rtl::OUString& sType) const
2490 {
2491     CacheItemList::const_iterator pIt;
2492     for (  pIt  = m_lContentHandlers.begin();
2493            pIt != m_lContentHandlers.end()  ;
2494          ++pIt                              )
2495     {
2496         const ::rtl::OUString& sItem = pIt->first;
2497         ::comphelper::SequenceAsHashMap lProps(pIt->second);
2498         OUStringList                    lTypes(lProps[PROPNAME_TYPES]);
2499 
2500         if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end())
2501             return sItem;
2502     }
2503 
2504     return ::rtl::OUString();
2505 }
2506 #endif
2507 
2508 /*-----------------------------------------------*/
impl_isModuleInstalled(const::rtl::OUString & sModule)2509 sal_Bool FilterCache::impl_isModuleInstalled(const ::rtl::OUString& sModule)
2510 {
2511     css::uno::Reference< css::container::XNameAccess > xCfg;
2512 
2513     // SAFE ->
2514     ::osl::ResettableMutexGuard aLock(m_aLock);
2515     if (! m_xModuleCfg.is())
2516     {
2517         m_xModuleCfg = css::uno::Reference< css::container::XNameAccess >(
2518                             ::comphelper::ConfigurationHelper::openConfig(
2519                                 m_xSMGR,
2520                                 ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office/Factories"),
2521                                 ::comphelper::ConfigurationHelper::E_READONLY),
2522                             css::uno::UNO_QUERY_THROW);
2523     }
2524 
2525     xCfg = m_xModuleCfg;
2526     aLock.clear();
2527     // <- SAFE
2528 
2529     if (xCfg.is())
2530         return xCfg->hasByName(sModule);
2531 
2532     return sal_False;
2533 }
2534 
2535     } // namespace config
2536 } // namespace filter
2537