1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fltfnc.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
35 #include <com/sun/star/uno/Exception.hpp>
36 #include <com/sun/star/beans/PropertyValue.hpp>
37 #include <com/sun/star/beans/NamedValue.hpp>
38 #include <com/sun/star/container/XNameAccess.hpp>
39 #include <com/sun/star/container/XEnumeration.hpp>
40 #include <com/sun/star/datatransfer/DataFlavor.hpp>
41 #include <com/sun/star/document/XTypeDetection.hpp>
42 #include <com/sun/star/container/XContainerQuery.hpp>
44 #include <comphelper/sequenceashashmap.hxx>
46 #ifndef _EXCHANGE_HXX //autogen
47 #include <sot/exchange.hxx>
49 #include <tools/config.hxx>
50 #include <basic/sbmeth.hxx>
51 #include <basic/basmgr.hxx>
52 #include <basic/sbstar.hxx>
53 #include <basic/sbxobj.hxx>
54 #include <basic/sbxmeth.hxx>
55 #include <basic/sbxcore.hxx>
56 #ifndef _MSGBOX_HXX //autogen
57 #include <vcl/msgbox.hxx>
59 #ifndef _RTL_USTRING_HXX //autogen
60 #include <rtl/ustring.hxx>
62 #include <rtl/ustrbuf.hxx>
63 #include <svtools/eitem.hxx>
64 #include <svtools/intitem.hxx>
65 #include <svtools/stritem.hxx>
66 #include <svtools/lckbitem.hxx>
67 #include <svtools/inettype.hxx>
68 #include <svtools/rectitem.hxx>
70 #include <sot/storage.hxx>
71 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
72 #include <com/sun/star/frame/XDispatch.hpp>
73 #include <com/sun/star/frame/XDispatchProvider.hpp>
74 #include <com/sun/star/frame/XStatusListener.hpp>
75 #include <com/sun/star/frame/FrameSearchFlag.hpp>
76 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
77 #include <com/sun/star/frame/FeatureStateEvent.hpp>
78 #include <com/sun/star/frame/DispatchDescriptor.hpp>
79 #include <com/sun/star/frame/XController.hpp>
80 #include <com/sun/star/frame/XFrameActionListener.hpp>
81 #include <com/sun/star/frame/XComponentLoader.hpp>
82 #include <com/sun/star/frame/XFrame.hpp>
83 #include <com/sun/star/frame/FrameActionEvent.hpp>
84 #include <com/sun/star/frame/FrameAction.hpp>
85 #include <com/sun/star/frame/XFrameLoader.hpp>
86 #include <com/sun/star/frame/XLoadEventListener.hpp>
87 #include <com/sun/star/frame/XFilterDetect.hpp>
88 #include <com/sun/star/loader/XImplementationLoader.hpp>
89 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
90 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX
91 #include <comphelper/processfactory.hxx>
93 #include <com/sun/star/beans/PropertyValue.hpp>
95 #include <sal/types.h>
96 #include <com/sun/star/uno/Reference.hxx>
97 #include <com/sun/star/ucb/XContent.hpp>
98 #include <rtl/ustring.hxx>
99 #include <vos/process.hxx>
100 #include <svtools/pathoptions.hxx>
101 #include <svtools/moduleoptions.hxx>
102 #include <comphelper/mediadescriptor.hxx>
103 #include <tools/urlobj.hxx>
105 #include <rtl/logfile.hxx>
107 using namespace ::com::sun::star::uno
;
108 using namespace ::com::sun::star::ucb
;
109 using namespace ::com::sun::star::document
;
110 using namespace ::com::sun::star::beans
;
111 using namespace ::vos
;
112 #include <svtools/ctypeitm.hxx>
113 #include <svtools/sfxecode.hxx>
114 #include <svtools/syslocale.hxx>
116 #include "sfxhelp.hxx"
117 #include "sfxbasic.hxx"
118 #include <sfx2/docfilt.hxx>
119 #include <sfx2/docfac.hxx>
120 #include "sfxtypes.hxx"
121 #include <sfx2/sfxuno.hxx>
122 #include <sfx2/docfile.hxx>
123 #include <sfx2/progress.hxx>
124 #include "openflag.hxx"
125 #include "bastyp.hrc"
126 #include "sfxresid.hxx"
127 #include <sfx2/doctempl.hxx>
128 #include <sfx2/frame.hxx>
129 #include <sfx2/dispatch.hxx>
130 #include <sfx2/topfrm.hxx>
131 #include "helper.hxx"
132 #include "fltlst.hxx"
133 #include <sfx2/request.hxx>
134 #include "arrdecl.hxx"
135 #include <sfx2/appuno.hxx>
136 #include <sfx2/viewfrm.hxx>
138 static SfxFilterList_Impl
* pFilterArr
= 0;
139 static BOOL bFirstRead
= TRUE
;
141 static void CreateFilterArr()
143 pFilterArr
= new SfxFilterList_Impl
;
144 new SfxFilterListener();
147 //----------------------------------------------------------------
148 inline String
ToUpper_Impl( const String
&rStr
)
150 return SvtSysLocale().GetCharClass().upper( rStr
);
153 //----------------------------------------------------------------
154 class SfxFilterContainer_Impl
160 SfxFilterContainer_Impl( const String
& rName
)
163 aServiceName
= SfxObjectShell::GetServiceNameFromFactory( rName
);
167 #define IMPL_FORWARD_LOOP( aMethod, ArgType, aArg ) \
168 const SfxFilter* SfxFilterContainer::aMethod( ArgType aArg, SfxFilterFlags nMust, SfxFilterFlags nDont ) const \
170 SfxFilterMatcher aMatch( pImpl->aName ); \
171 return aMatch.aMethod( aArg, nMust, nDont ); \
174 IMPL_FORWARD_LOOP( GetFilter4Mime
, const String
&, rMime
);
175 IMPL_FORWARD_LOOP( GetFilter4ClipBoardId
, sal_uInt32
, nId
);
176 IMPL_FORWARD_LOOP( GetFilter4EA
, const String
&, rEA
);
177 IMPL_FORWARD_LOOP( GetFilter4Extension
, const String
&, rExt
);
178 IMPL_FORWARD_LOOP( GetFilter4FilterName
, const String
&, rName
);
179 IMPL_FORWARD_LOOP( GetFilter4UIName
, const String
&, rName
);
181 const SfxFilter
* SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
183 SfxFilterMatcher
aMatch( pImpl
->aName
);
184 return aMatch
.GetAnyFilter( nMust
, nDont
);
187 //----------------------------------------------------------------
189 SfxFilterContainer::SfxFilterContainer( const String
& rName
)
191 pImpl
= new SfxFilterContainer_Impl( rName
);
194 //----------------------------------------------------------------
196 SfxFilterContainer::~SfxFilterContainer()
200 //----------------------------------------------------------------
202 const String
SfxFilterContainer::GetName() const
207 const SfxFilter
* SfxFilterContainer::GetDefaultFilter_Impl( const String
& rName
)
209 // Try to find out the type of factory.
210 // Interpret given name as Service- and ShortName!
211 SvtModuleOptions aOpt
;
212 SvtModuleOptions::EFactory eFactory
= aOpt
.ClassifyFactoryByServiceName(rName
);
213 if (eFactory
== SvtModuleOptions::E_UNKNOWN_FACTORY
)
214 eFactory
= aOpt
.ClassifyFactoryByShortName(rName
);
216 // could not classify factory by its service nor by its short name.
217 // Must be an unknown factory! => return NULL
218 if (eFactory
== SvtModuleOptions::E_UNKNOWN_FACTORY
)
221 // For the following code we need some additional informations.
222 String sServiceName
= aOpt
.GetFactoryName(eFactory
);
223 String sShortName
= aOpt
.GetFactoryShortName(eFactory
);
224 String sDefaultFilter
= aOpt
.GetFactoryDefaultFilter(eFactory
);
226 // Try to get the default filter. Dont fiorget to verify it.
227 // May the set default filter does not exists any longer or
228 // does not fit the given factory.
229 const SfxFilterMatcher aMatcher
;
230 const SfxFilter
* pFilter
= aMatcher
.GetFilter4FilterName(sDefaultFilter
);
234 (pFilter
->GetServiceName().CompareIgnoreCaseToAscii( sServiceName
) != COMPARE_EQUAL
)
240 // If at least no default filter could be located - use any filter of this
247 sal_uInt16 nCount
= ( sal_uInt16
) pFilterArr
->Count();
248 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
250 const SfxFilter
* pCheckFilter
= pFilterArr
->GetObject( n
);
251 if ( pCheckFilter
->GetServiceName().CompareIgnoreCaseToAscii( sServiceName
) == COMPARE_EQUAL
)
253 pFilter
= pCheckFilter
;
263 //----------------------------------------------------------------
265 class SfxFilterMatcherArr_Impl
;
266 static SfxFilterMatcherArr_Impl
* pImplArr
= 0;
268 // Impl-Data is shared between all FilterMatchers of the same factory
269 class SfxFilterMatcher_Impl
272 ::rtl::OUString aName
;
273 SfxFilterList_Impl
* pList
; // is created on demand
275 void InitForIterating() const;
277 SfxFilterMatcher_Impl()
282 DECL_PTRARRAY( SfxFilterMatcherArr_Impl
, SfxFilterMatcher_Impl
*, 2, 2 )
284 SfxFilterMatcher::SfxFilterMatcher( const String
& rName
)
288 // keep track of created filter matchers to recycle the FilterLists
289 pImplArr
= new SfxFilterMatcherArr_Impl
;
291 String aName
= SfxObjectShell::GetServiceNameFromFactory( rName
);
292 DBG_ASSERT(aName
.Len(), "Found boes type :-)");
293 for ( USHORT n
=0; n
<pImplArr
->Count(); n
++ )
295 // find the impl-Data of any comparable FilterMatcher that was created before
296 SfxFilterMatcher_Impl
* pImp
= pImplArr
->GetObject(n
);
297 if ( String(pImp
->aName
) == aName
)
303 // first Matcher created for this factory
304 pImpl
= new SfxFilterMatcher_Impl
;
305 pImpl
->aName
= aName
;
306 pImplArr
->Insert( pImplArr
->Count(), pImpl
);
310 SfxFilterMatcher::SfxFilterMatcher()
312 // global FilterMatcher always uses global filter array (also created on demand)
313 pImpl
= new SfxFilterMatcher_Impl
;
316 SfxFilterMatcher::~SfxFilterMatcher()
318 if ( !pImpl
->aName
.getLength() )
319 // only the global Matcher owns his ImplData
323 void SfxFilterMatcher_Impl::Update()
327 // this List was already used
329 for ( USHORT n
=0; n
<pFilterArr
->Count(); n
++ )
331 SfxFilter
* pFilter
= pFilterArr
->GetObject(n
);
332 if ( pFilter
->GetServiceName() == String(aName
) )
333 pList
->Insert( pFilter
, LIST_APPEND
);
338 void SfxFilterMatcher_Impl::InitForIterating() const
344 // global filter array has not been created yet
345 SfxFilterContainer::ReadFilters_Impl();
347 if ( aName
.getLength() )
349 // matcher of factory: use only filters of that document type
350 ((SfxFilterMatcher_Impl
*)this)->pList
= new SfxFilterList_Impl
;
351 ((SfxFilterMatcher_Impl
*)this)->Update();
355 // global matcher: use global filter array
356 ((SfxFilterMatcher_Impl
*)this)->pList
= pFilterArr
;
360 const SfxFilter
* SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
362 pImpl
->InitForIterating();
363 sal_uInt16 nCount
= ( sal_uInt16
) pImpl
->pList
->Count();
364 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
366 const SfxFilter
* pFilter
= pImpl
->pList
->GetObject( n
);
367 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
368 if ( (nFlags
& nMust
) == nMust
&& !(nFlags
& nDont
) )
375 //----------------------------------------------------------------
377 sal_uInt32
SfxFilterMatcher::GuessFilterIgnoringContent(
379 const SfxFilter
**ppFilter
,
380 SfxFilterFlags
/*nMust*/,
381 SfxFilterFlags
/*nDont*/ ) const
383 Reference
< XTypeDetection
> xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection")), UNO_QUERY
);
384 ::rtl::OUString sTypeName
;
387 //!MBA: nmust, ndont?
388 sTypeName
= xDetection
->queryTypeByURL( rMedium
.GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) );
395 if ( sTypeName
.getLength() )
396 *ppFilter
= GetFilter4EA( sTypeName
);
398 return *ppFilter
? ERRCODE_NONE
: ERRCODE_ABORT
;
401 //----------------------------------------------------------------
403 #define CHECKERROR() \
404 if( nErr == 1 || nErr == USHRT_MAX || nErr == ULONG_MAX ) \
406 ByteString aText = "Fehler in FilterDetection: Returnwert ";\
407 aText += ByteString::CreateFromInt32(nErr); \
411 aText += ByteString(U2S(pFilter->GetFilterName())); \
413 DBG_ERROR( aText.GetBuffer() ); \
414 nErr = ERRCODE_ABORT; \
417 //----------------------------------------------------------------
419 sal_uInt32
SfxFilterMatcher::GuessFilter( SfxMedium
& rMedium
, const SfxFilter
**ppFilter
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
421 return GuessFilterControlDefaultUI( rMedium
, ppFilter
, nMust
, nDont
, sal_True
);
424 //----------------------------------------------------------------
426 sal_uInt32
SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium
& rMedium
, const SfxFilter
** ppFilter
, SfxFilterFlags nMust
, SfxFilterFlags nDont
, sal_Bool
/*bDefUI*/ ) const
428 const SfxFilter
* pOldFilter
= *ppFilter
;
430 // no detection service -> nothing to do !
431 Reference
< XTypeDetection
> xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection")), UNO_QUERY
);
432 if (!xDetection
.is())
433 return ERRCODE_ABORT
;
435 ::rtl::OUString sTypeName
;
438 // open the stream one times only ...
439 // Otherwhise it will be tried more then once and show the same interaction more then once ...
441 ::rtl::OUString
sURL( rMedium
.GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) );
442 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XInputStream
> xInStream
= rMedium
.GetInputStream();
444 // stream exists => deep detection (with preselection ... if possible)
447 ::comphelper::MediaDescriptor aDescriptor
;
449 aDescriptor
[::comphelper::MediaDescriptor::PROP_URL() ] <<= sURL
;
450 aDescriptor
[::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] <<= xInStream
;
451 aDescriptor
[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= rMedium
.GetInteractionHandler();
453 if ( pImpl
->aName
.getLength() )
454 aDescriptor
[::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE()] <<= pImpl
->aName
;
458 aDescriptor
[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= ::rtl::OUString( pOldFilter
->GetTypeName() );
459 aDescriptor
[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= ::rtl::OUString( pOldFilter
->GetFilterName() );
462 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
> lDescriptor
= aDescriptor
.getAsConstPropertyValueList();
463 sTypeName
= xDetection
->queryTypeByDescriptor(lDescriptor
, sal_True
); // lDescriptor is used as In/Out param ... dont use aDescriptor.getAsConstPropertyValueList() directly!
465 // no stream exists => try flat detection without preselection as fallback
467 sTypeName
= xDetection
->queryTypeByURL(sURL
);
469 if (sTypeName
.getLength())
471 // detect filter by given type
472 // In case of this matcher is bound to a particular document type:
473 // If there is no acceptable type for this document at all, the type detection has possibly returned something else.
474 // The DocumentService property is only a preselection, and all preselections are considered as optional!
475 // This "wrong" type will be sorted out now because we match only allowed filters to the detected type
476 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::NamedValue
> lQuery(1);
477 lQuery
[0].Name
= ::rtl::OUString::createFromAscii("Name");
478 lQuery
[0].Value
<<= sTypeName
;
480 const SfxFilter
* pFilter
= GetFilterForProps(lQuery
, nMust
, nDont
);
488 catch(const Exception
&)
491 return ERRCODE_ABORT
;
494 //----------------------------------------------------------------
495 sal_Bool
SfxFilterMatcher::IsFilterInstalled_Impl( const SfxFilter
* pFilter
)
497 if ( pFilter
->GetFilterFlags() & SFX_FILTER_MUSTINSTALL
)
499 // Hier k"onnte noch eine Nachinstallation angeboten werden
500 String
aText( SfxResId( STR_FILTER_NOT_INSTALLED
) );
501 aText
.SearchAndReplaceAscii( "$(FILTER)", pFilter
->GetUIName() );
502 QueryBox
aQuery( NULL
, WB_YES_NO
| WB_DEF_YES
, aText
);
503 short nRet
= aQuery
.Execute();
504 if ( nRet
== RET_YES
)
508 InfoBox( NULL
, DEFINE_CONST_UNICODE("Hier soll jetzt das Setup starten!") ).Execute();
510 // Installation mu\s hier noch mitteilen, ob es geklappt hat, dann kann das
511 // Filterflag gel"oscht werden
514 return ( !(pFilter
->GetFilterFlags() & SFX_FILTER_MUSTINSTALL
) );
516 else if ( pFilter
->GetFilterFlags() & SFX_FILTER_CONSULTSERVICE
)
518 String
aText( SfxResId( STR_FILTER_CONSULT_SERVICE
) );
519 aText
.SearchAndReplaceAscii( "$(FILTER)", pFilter
->GetUIName() );
520 InfoBox ( NULL
, aText
).Execute();
528 sal_uInt32
SfxFilterMatcher::DetectFilter( SfxMedium
& rMedium
, const SfxFilter
**ppFilter
, sal_Bool
/*bPlugIn*/, sal_Bool bAPI
) const
531 Hier wird noch die Filterauswahlbox hochgezogen. Sonst GuessFilter
535 const SfxFilter
* pOldFilter
= rMedium
.GetFilter();
538 if( !IsFilterInstalled_Impl( pOldFilter
) )
542 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
543 if ( ( pOldFilter
->GetFilterFlags() & SFX_FILTER_PACKED
) && pSalvageItem
)
544 // Salvage is always done without packing
549 const SfxFilter
* pFilter
= pOldFilter
;
551 sal_Bool bPreview
= rMedium
.IsPreview_Impl();
552 SFX_ITEMSET_ARG(rMedium
.GetItemSet(), pReferer
, SfxStringItem
, SID_REFERER
, FALSE
);
553 if ( bPreview
&& rMedium
.IsRemote() && ( !pReferer
|| pReferer
->GetValue().CompareToAscii("private:searchfolder:",21 ) != COMPARE_EQUAL
) )
554 return ERRCODE_ABORT
;
556 ErrCode nErr
= GuessFilter( rMedium
, &pFilter
);
557 if ( nErr
== ERRCODE_ABORT
)
560 if ( nErr
== ERRCODE_IO_PENDING
)
568 const SfxFilter
* pInstallFilter
= NULL
;
570 // Jetzt auch Filter testen, die nicht installiert sind ( ErrCode ist irrelevant )
571 GuessFilter( rMedium
, &pInstallFilter
, SFX_FILTER_IMPORT
, SFX_FILTER_CONSULTSERVICE
);
572 if ( pInstallFilter
)
574 if ( IsFilterInstalled_Impl( pInstallFilter
) )
575 // Eventuell wurde der Filter nachinstalliert
576 pFilter
= pInstallFilter
;
580 // Jetzt auch Filter testen, die erst von Star bezogen werden m"ussen ( ErrCode ist irrelevant )
581 GuessFilter( rMedium
, &pInstallFilter
, SFX_FILTER_IMPORT
, 0 );
582 if ( pInstallFilter
)
583 IsFilterInstalled_Impl( pInstallFilter
);
587 sal_Bool bHidden
= bPreview
;
588 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pFlags
, SfxStringItem
, SID_OPTIONS
, sal_False
);
589 if ( !bHidden
&& pFlags
)
591 String
aFlags( pFlags
->GetValue() );
592 aFlags
.ToUpperAscii();
593 if( STRING_NOTFOUND
!= aFlags
.Search( 'H' ) )
597 if ( ( !pFilter || nErr == ERRCODE_SFX_CONSULTUSER ) && !bAPI && !bHidden )
600 pFilter = pOldFilter;
604 aTmpName = pFilter->GetUIName();
606 SfxFilterMatcher *pMatcher;
607 if( bPlugIn && pFilter )
608 pMatcher = new SfxFilterMatcher( (SfxFilterContainer *) pFilter->GetFilterContainer() );
610 pMatcher = (SfxFilterMatcher*) this;
612 SfxFilterDialog *pDlg = new SfxFilterDialog( 0, &rMedium, *pMatcher, pFilter ? &aTmpName: 0, 0 );
613 const sal_Bool bOk = RET_OK == pDlg->Execute();
615 pFilter = pMatcher->GetFilter4UIName( pDlg->GetSelectEntry());
617 if( bPlugIn && pFilter )
622 nErr = ERRCODE_ABORT;
629 if ( bHidden
|| (bAPI
&& nErr
== ERRCODE_SFX_CONSULTUSER
) )
630 nErr
= pFilter
? ERRCODE_NONE
: ERRCODE_ABORT
;
634 const SfxFilter
* SfxFilterMatcher::GetFilterForProps( const com::sun::star::uno::Sequence
< ::com::sun::star::beans::NamedValue
>& aSeq
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
636 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
637 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XContainerQuery
> xTypeCFG
;
638 if( xServiceManager
.is() == sal_True
)
639 xTypeCFG
= ::com::sun::star::uno::Reference
< com::sun::star::container::XContainerQuery
>( xServiceManager
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY
);
642 // make query for all types matching the properties
643 ::com::sun::star::uno::Reference
< com::sun::star::container::XEnumeration
> xEnum
= xTypeCFG
->createSubSetEnumerationByProperties( aSeq
);
644 while ( xEnum
->hasMoreElements() )
646 ::comphelper::SequenceAsHashMap
aProps( xEnum
->nextElement() );
647 ::rtl::OUString aValue
;
649 // try to get the preferred filter (works without loading all filters!)
650 if ( (aProps
[::rtl::OUString::createFromAscii("PreferredFilter")] >>= aValue
) && aValue
.getLength() )
652 const SfxFilter
* pFilter
= SfxFilter::GetFilterByName( aValue
);
653 if ( !pFilter
|| (pFilter
->GetFilterFlags() & nMust
) != nMust
|| (pFilter
->GetFilterFlags() & nDont
) )
654 // check for filter flags
655 // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed
658 if ( pImpl
->aName
.getLength() )
660 // if this is not the global FilterMatcher: check if filter matches the document type
661 ::rtl::OUString aService
;
662 if ( pFilter
->GetServiceName() != String(pImpl
->aName
) )
664 // preferred filter belongs to another document type; now we must search the filter
665 pImpl
->InitForIterating();
666 aProps
[::rtl::OUString::createFromAscii("Name")] >>= aValue
;
667 pFilter
= GetFilter4EA( aValue
, nMust
, nDont
);
683 const SfxFilter
* SfxFilterMatcher::GetFilter4Mime( const String
& rMediaType
,SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
687 sal_uInt16 nCount
= ( sal_uInt16
) pImpl
->pList
->Count();
688 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
690 const SfxFilter
* pFilter
= pImpl
->pList
->GetObject( n
);
691 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
692 if ( (nFlags
& nMust
) == nMust
&& !(nFlags
& nDont
) && pFilter
->GetMimeType() == rMediaType
)
699 com::sun::star::uno::Sequence
< com::sun::star::beans::NamedValue
> aSeq(1);
700 aSeq
[0].Name
= ::rtl::OUString::createFromAscii("MediaType");
701 aSeq
[0].Value
<<= ::rtl::OUString( rMediaType
);
702 return GetFilterForProps( aSeq
, nMust
, nDont
);
705 const SfxFilter
* SfxFilterMatcher::GetFilter4EA( const String
& rType
,SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
709 sal_uInt16 nCount
= ( sal_uInt16
) pImpl
->pList
->Count();
710 const SfxFilter
* pFirst
= 0;
711 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
713 const SfxFilter
* pFilter
= pImpl
->pList
->GetObject( n
);
714 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
715 if ( (nFlags
& nMust
) == nMust
&& !(nFlags
& nDont
) && pFilter
->GetTypeName() == rType
)
717 if (nFlags
& SFX_FILTER_PREFERED
)
729 com::sun::star::uno::Sequence
< com::sun::star::beans::NamedValue
> aSeq(1);
730 aSeq
[0].Name
= ::rtl::OUString::createFromAscii("Name");
731 aSeq
[0].Value
<<= ::rtl::OUString( rType
);
732 return GetFilterForProps( aSeq
, nMust
, nDont
);
735 const SfxFilter
* SfxFilterMatcher::GetFilter4Extension( const String
& rExt
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
739 sal_uInt16 nCount
= ( sal_uInt16
) pImpl
->pList
->Count();
740 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
742 const SfxFilter
* pFilter
= pImpl
->pList
->GetObject( n
);
743 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
744 if ( (nFlags
& nMust
) == nMust
&& !(nFlags
& nDont
) )
746 String sWildCard
= ToUpper_Impl( pFilter
->GetWildcard().GetWildCard() );
747 String sExt
= ToUpper_Impl( rExt
);
752 if (sExt
.GetChar(0) != (sal_Unicode
)'.')
753 sExt
.Insert((sal_Unicode
)'.', 0);
755 WildCard
aCheck(sWildCard
, ';');
756 if (aCheck
.Matches(sExt
))
764 // Use extension without dot!
766 if ( sExt
.Len() && ( sExt
.GetChar(0) == (sal_Unicode
)'.' ))
769 com::sun::star::uno::Sequence
< com::sun::star::beans::NamedValue
> aSeq(1);
770 aSeq
[0].Name
= ::rtl::OUString::createFromAscii("Extensions");
771 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> aExts(1);
773 aSeq
[0].Value
<<= aExts
;
774 return GetFilterForProps( aSeq
, nMust
, nDont
);
777 const SfxFilter
* SfxFilterMatcher::GetFilter4ClipBoardId( sal_uInt32 nId
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
782 sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count();
783 for( sal_uInt16 n = 0; n < nCount; n++ )
785 const SfxFilter* pFilter = pImpl->pList->GetObject( n );
786 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
787 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFormat() == nId )
798 com::sun::star::uno::Sequence
< com::sun::star::beans::NamedValue
> aSeq(1);
799 ::rtl::OUString aName
= SotExchange::GetFormatName( nId
);
800 aSeq
[0].Name
= ::rtl::OUString::createFromAscii("ClipboardFormat");
801 aSeq
[0].Value
<<= aName
;
802 return GetFilterForProps( aSeq
, nMust
, nDont
);
805 const SfxFilter
* SfxFilterMatcher::GetFilter4UIName( const String
& rName
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
807 pImpl
->InitForIterating();
808 const SfxFilter
* pFirstFilter
=0;
809 sal_uInt16 nCount
= ( sal_uInt16
) pImpl
->pList
->Count();
810 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
812 const SfxFilter
* pFilter
= pImpl
->pList
->GetObject( n
);
813 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
814 if ( (nFlags
& nMust
) == nMust
&&
815 !(nFlags
& nDont
) && pFilter
->GetUIName() == rName
)
817 if ( pFilter
->GetFilterFlags() & SFX_FILTER_PREFERED
)
819 else if ( !pFirstFilter
)
820 pFirstFilter
= pFilter
;
826 const SfxFilter
* SfxFilterMatcher::GetFilter4FilterName( const String
& rName
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
828 String
aName( rName
);
829 USHORT nIndex
= aName
.SearchAscii(": ");
830 if ( nIndex
!= STRING_NOTFOUND
)
832 DBG_ERROR("Old filter name used!");
833 aName
= rName
.Copy( nIndex
+ 2 );
838 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
839 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
> xFilterCFG
;
840 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
> xTypeCFG
;
841 if( xServiceManager
.is() == sal_True
)
843 xFilterCFG
= ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>( xServiceManager
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), ::com::sun::star::uno::UNO_QUERY
);
844 xTypeCFG
= ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>( xServiceManager
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY
);
847 if( xFilterCFG
.is() && xTypeCFG
.is() )
853 for( sal_uInt16 n
=0; n
<pFilterArr
->Count(); n
++ )
855 const SfxFilter
* pFilter
= pFilterArr
->GetObject( n
);
856 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
857 if ( (nFlags
& nMust
) == nMust
&& !(nFlags
& nDont
) && pFilter
->GetFilterName().CompareIgnoreCaseToAscii( aName
) == COMPARE_EQUAL
)
862 SfxFilterContainer::ReadSingleFilter_Impl( rName
, xTypeCFG
, xFilterCFG
, FALSE
);
866 SfxFilterList_Impl
* pList
= pImpl
->pList
;
870 sal_uInt16 nCount
= ( sal_uInt16
) pList
->Count();
871 for( sal_uInt16 n
= 0; n
< nCount
; n
++ )
873 const SfxFilter
* pFilter
= pList
->GetObject( n
);
874 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
875 if ( (nFlags
& nMust
) == nMust
&& !(nFlags
& nDont
) && pFilter
->GetFilterName().CompareIgnoreCaseToAscii( aName
) == COMPARE_EQUAL
)
882 IMPL_STATIC_LINK( SfxFilterMatcher
, MaybeFileHdl_Impl
, String
*, pString
)
884 const SfxFilter
* pFilter
= pThis
->GetFilter4Extension( *pString
, SFX_FILTER_IMPORT
);
885 if( pFilter
&& !pFilter
->GetWildcard().Matches( String() ) &&
886 pFilter
->GetWildcard() != DEFINE_CONST_UNICODE("*.*") && pFilter
->GetWildcard() != '*' )
891 //----------------------------------------------------------------
893 SfxFilterMatcherIter::SfxFilterMatcherIter(
894 const SfxFilterMatcher
* pMatchP
,
895 SfxFilterFlags nOrMaskP
, SfxFilterFlags nAndMaskP
)
896 : nOrMask( nOrMaskP
), nAndMask( nAndMaskP
),
897 nCurrent(0), pMatch( pMatchP
->pImpl
)
899 if( nOrMask
== 0xffff ) //Wg. Fehlbuild auf s
901 pMatch
->InitForIterating();
904 //----------------------------------------------------------------
906 const SfxFilter
* SfxFilterMatcherIter::Find_Impl()
908 const SfxFilter
* pFilter
= 0;
909 while( nCurrent
< pMatch
->pList
->Count() )
911 pFilter
= pMatch
->pList
->GetObject(nCurrent
++);
912 SfxFilterFlags nFlags
= pFilter
->GetFilterFlags();
913 if( ((nFlags
& nOrMask
) == nOrMask
) && !(nFlags
& nAndMask
) )
921 const SfxFilter
* SfxFilterMatcherIter::First()
927 //----------------------------------------------------------------
929 const SfxFilter
* SfxFilterMatcherIter::Next()
934 /*---------------------------------------------------------------
935 helper to build own formated string from given stringlist by
936 using given seperator
937 ---------------------------------------------------------------*/
938 ::rtl::OUString
implc_convertStringlistToString( const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& lList
,
939 const sal_Unicode
& cSeperator
,
940 const ::rtl::OUString
& sPrefix
)
942 ::rtl::OUStringBuffer
sString ( 1000 ) ;
943 sal_Int32 nCount
= lList
.getLength();
944 sal_Int32 nItem
= 0 ;
945 for( nItem
=0; nItem
<nCount
; ++nItem
)
947 if( sPrefix
.getLength() > 0 )
949 sString
.append( sPrefix
);
951 sString
.append( lList
[nItem
] );
954 sString
.append( cSeperator
);
957 return sString
.makeStringAndClear();
961 void SfxFilterContainer::ReadSingleFilter_Impl(
962 const ::rtl::OUString
& rName
,
963 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>& xTypeCFG
,
964 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>& xFilterCFG
,
968 ::rtl::OUString
sFilterName( rName
);
969 SfxFilterList_Impl
& rList
= *pFilterArr
;
970 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
> lFilterProperties
;
971 ::com::sun::star::uno::Any aResult
;
974 aResult
= xFilterCFG
->getByName( sFilterName
);
976 catch( ::com::sun::star::container::NoSuchElementException
& )
978 aResult
= ::com::sun::star::uno::Any();
981 if( aResult
>>= lFilterProperties
)
983 // collect informations to add filter to container
984 // (attention: some informations aren't available on filter directly ... you must search for corresponding type too!)
985 sal_Int32 nFlags
= 0 ;
986 sal_Int32 nClipboardId
= 0 ;
987 sal_Int32 nDocumentIconId
= 0 ;
988 sal_Int32 nFormatVersion
= 0 ;
989 ::rtl::OUString sMimeType
;
990 ::rtl::OUString sType
;
991 ::rtl::OUString sUIName
;
992 ::rtl::OUString sHumanName
;
993 ::rtl::OUString sDefaultTemplate
;
994 ::rtl::OUString sUserData
;
995 ::rtl::OUString sExtension
;
996 ::rtl::OUString sPattern
;
997 ::rtl::OUString sServiceName
;
999 // first get directly available properties
1000 sal_Int32 nFilterPropertyCount
= lFilterProperties
.getLength();
1001 sal_Int32 nFilterProperty
= 0 ;
1002 for( nFilterProperty
=0; nFilterProperty
<nFilterPropertyCount
; ++nFilterProperty
)
1004 if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "FileFormatVersion" ) == 0 )
1006 lFilterProperties
[nFilterProperty
].Value
>>= nFormatVersion
;
1008 else if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "TemplateName" ) == 0 )
1010 lFilterProperties
[nFilterProperty
].Value
>>= sDefaultTemplate
;
1012 else if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "Flags" ) == 0 )
1014 lFilterProperties
[nFilterProperty
].Value
>>= nFlags
;
1016 else if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "UIName" ) == 0 )
1018 lFilterProperties
[nFilterProperty
].Value
>>= sUIName
;
1020 else if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "UserData" ) == 0 )
1022 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> lUserData
;
1023 lFilterProperties
[nFilterProperty
].Value
>>= lUserData
;
1024 sUserData
= implc_convertStringlistToString( lUserData
, ',', ::rtl::OUString() );
1026 else if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "DocumentService" ) == 0 )
1028 lFilterProperties
[nFilterProperty
].Value
>>= sServiceName
;
1030 else if( lFilterProperties
[nFilterProperty
].Name
.compareToAscii( "Type" ) == 0 )
1032 lFilterProperties
[nFilterProperty
].Value
>>= sType
;
1033 // Try to get filter .. but look for any exceptions!
1034 // May be filter was deleted by another thread ...
1037 aResult
= xTypeCFG
->getByName( sType
);
1039 catch( ::com::sun::star::container::NoSuchElementException
& )
1041 aResult
= ::com::sun::star::uno::Any();
1044 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
> lTypeProperties
;
1045 if( aResult
>>= lTypeProperties
)
1047 // get indirect available properties then (types)
1048 sal_Int32 nTypePropertyCount
= lTypeProperties
.getLength();
1049 sal_Int32 nTypeProperty
= 0 ;
1050 for( nTypeProperty
=0; nTypeProperty
<nTypePropertyCount
; ++nTypeProperty
)
1052 if( lTypeProperties
[nTypeProperty
].Name
.compareToAscii( "ClipboardFormat" ) == 0 )
1054 lTypeProperties
[nTypeProperty
].Value
>>= sHumanName
;
1056 else if( lTypeProperties
[nTypeProperty
].Name
.compareToAscii( "DocumentIconID" ) == 0 )
1058 lTypeProperties
[nTypeProperty
].Value
>>= nDocumentIconId
;
1060 else if( lTypeProperties
[nTypeProperty
].Name
.compareToAscii( "MediaType" ) == 0 )
1062 lTypeProperties
[nTypeProperty
].Value
>>= sMimeType
;
1064 else if( lTypeProperties
[nTypeProperty
].Name
.compareToAscii( "Extensions" ) == 0 )
1066 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> lExtensions
;
1067 lTypeProperties
[nTypeProperty
].Value
>>= lExtensions
;
1068 sExtension
= implc_convertStringlistToString( lExtensions
, ';', DEFINE_CONST_UNICODE("*.") );
1070 else if( lTypeProperties
[nTypeProperty
].Name
.compareToAscii( "URLPattern" ) == 0 )
1072 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> lPattern
;
1073 lTypeProperties
[nTypeProperty
].Value
>>= lPattern
;
1074 sPattern
= implc_convertStringlistToString( lPattern
, ';', ::rtl::OUString() );
1081 if ( !sServiceName
.getLength() )
1084 // old formats are found ... using HumanPresentableName!
1085 if( sHumanName
.getLength() )
1087 nClipboardId
= SotExchange::RegisterFormatName( sHumanName
);
1089 // #100570# For external filters ignore clipboard IDs
1090 if((nFlags
& SFX_FILTER_STARONEFILTER
) == SFX_FILTER_STARONEFILTER
)
1095 // register SfxFilter
1096 // first erase module name from old filter names!
1097 // e.g: "scalc: DIF" => "DIF"
1098 sal_Int32 nStartRealName
= sFilterName
.indexOf( DEFINE_CONST_UNICODE(": "), 0 );
1099 if( nStartRealName
!= -1 )
1101 DBG_ERROR("Old format, not supported!");
1102 sFilterName
= sFilterName
.copy( nStartRealName
+2 );
1105 SfxFilter
* pFilter
= bUpdate
? (SfxFilter
*) SfxFilter::GetFilterByName( sFilterName
) : 0;
1110 pFilter
= new SfxFilter( sFilterName
,
1115 (USHORT
)nDocumentIconId
,
1122 pFilter
->aFilterName
= sFilterName
;
1123 pFilter
->aWildCard
= WildCard(sExtension
, ';');
1124 pFilter
->nFormatType
= nFlags
;
1125 pFilter
->lFormat
= nClipboardId
;
1126 pFilter
->aTypeName
= sType
;
1127 pFilter
->nDocIcon
= (USHORT
)nDocumentIconId
;
1128 pFilter
->aMimeType
= sMimeType
;
1129 pFilter
->aUserData
= sUserData
;
1130 pFilter
->aServiceName
= sServiceName
;
1133 // Don't forget to set right UIName!
1134 // Otherwise internal name is used as fallback ...
1135 pFilter
->SetUIName( sUIName
);
1136 pFilter
->SetDefaultTemplate( sDefaultTemplate
);
1137 if( nFormatVersion
)
1139 pFilter
->SetVersion( nFormatVersion
);
1141 pFilter
->SetURLPattern(sPattern
);
1144 rList
.Insert( pFilter
, USHRT_MAX
);
1148 void SfxFilterContainer::ReadFilters_Impl( BOOL bUpdate
)
1150 RTL_LOGFILE_CONTEXT( aMeasure
, "sfx2 (as96863) ::SfxFilterContainer::ReadFilters" );
1155 SfxFilterList_Impl
& rList
= *pFilterArr
;
1159 // get the FilterFactory service to access the registered filters ... and types!
1160 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
1161 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
> xFilterCFG
;
1162 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
> xTypeCFG
;
1163 if( xServiceManager
.is() == sal_True
)
1165 xFilterCFG
= ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>( xServiceManager
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), ::com::sun::star::uno::UNO_QUERY
);
1166 xTypeCFG
= ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>( xServiceManager
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY
);
1170 ( xFilterCFG
.is() == sal_True
) &&
1171 ( xTypeCFG
.is() == sal_True
)
1174 // select right query to get right set of filters for search modul
1175 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> lFilterNames
= xFilterCFG
->getElementNames();
1176 if ( lFilterNames
.getLength() )
1178 // If list of filters already exist ...
1179 // ReadExternalFilters must work in update mode.
1180 // Best way seams to mark all filters NOT_INSTALLED
1181 // and change it back for all valid filters afterwards.
1182 if( rList
.Count() > 0 )
1185 USHORT nCount
= (USHORT
)rList
.Count();
1187 for (USHORT f
=0; f
<nCount
; ++f
)
1190 pFilter
= rList
.GetObject(f
);
1191 pFilter
->nFormatType
|= SFX_FILTER_NOTINSTALLED
;
1195 // get all properties of filters ... put it into the filter container
1196 sal_Int32 nFilterCount
= lFilterNames
.getLength();
1197 sal_Int32 nFilter
=0;
1198 for( nFilter
=0; nFilter
<nFilterCount
; ++nFilter
)
1200 // Try to get filter .. but look for any exceptions!
1201 // May be filter was deleted by another thread ...
1202 ::rtl::OUString sFilterName
= lFilterNames
[nFilter
];
1204 // This debug code can be used to break on inserting/updating
1205 // special debug filters at runtime.
1206 // Otherwise you have to check more then 300 filter names manually .-)
1207 // And conditional breakpoints on unicode values seams not to be supported .-(
1209 bool bDBGStop
= FALSE
;
1210 if (sFilterName
.indexOf(::rtl::OUString::createFromAscii("DBG_"))>-1)
1214 ReadSingleFilter_Impl( sFilterName
, xTypeCFG
, xFilterCFG
, bUpdate
);
1219 catch( ::com::sun::star::uno::Exception
& )
1221 DBG_ASSERT( sal_False
, "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached.\n" );
1224 if ( pImplArr
&& bUpdate
)
1226 // global filter arry was modified, factory specific ones might need an update too
1227 for ( USHORT n
=0; n
<pImplArr
->Count(); n
++ )
1228 pImplArr
->GetObject(n
)->Update();