/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include "fltfnc.hxx" #include #include #include #include #include #include #include #include #include #ifndef _EXCHANGE_HXX //autogen #include #endif #include #include #include #include #include #include #include #ifndef _MSGBOX_HXX //autogen #include #endif #ifndef _RTL_USTRING_HXX //autogen #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef _UNOTOOLS_PROCESSFACTORY_HXX #include #endif #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star::uno; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::document; using namespace ::com::sun::star::beans; using namespace ::vos; #include #include #include #include "sfx2/sfxhelp.hxx" #include #include #include "sfxtypes.hxx" #include #include #include #include "openflag.hxx" #include "bastyp.hrc" #include "sfx2/sfxresid.hxx" #include #include #include #include #include "helper.hxx" #include "fltlst.hxx" #include #include "arrdecl.hxx" #include #include static SfxFilterList_Impl* pFilterArr = 0; static sal_Bool bFirstRead = sal_True; static void CreateFilterArr() { pFilterArr = new SfxFilterList_Impl; new SfxFilterListener(); } //---------------------------------------------------------------- inline String ToUpper_Impl( const String &rStr ) { return SvtSysLocale().GetCharClass().upper( rStr ); } //---------------------------------------------------------------- class SfxFilterContainer_Impl { public: String aName; String aServiceName; SfxFilterContainer_Impl( const String& rName ) : aName( rName ) { aServiceName = SfxObjectShell::GetServiceNameFromFactory( rName ); } }; #define IMPL_FORWARD_LOOP( aMethod, ArgType, aArg ) \ const SfxFilter* SfxFilterContainer::aMethod( ArgType aArg, SfxFilterFlags nMust, SfxFilterFlags nDont ) const \ {\ SfxFilterMatcher aMatch( pImpl->aName ); \ return aMatch.aMethod( aArg, nMust, nDont ); \ } IMPL_FORWARD_LOOP( GetFilter4Mime, const String&, rMime ); IMPL_FORWARD_LOOP( GetFilter4ClipBoardId, sal_uInt32, nId ); IMPL_FORWARD_LOOP( GetFilter4EA, const String&, rEA ); IMPL_FORWARD_LOOP( GetFilter4Extension, const String&, rExt ); IMPL_FORWARD_LOOP( GetFilter4FilterName, const String&, rName ); IMPL_FORWARD_LOOP( GetFilter4UIName, const String&, rName ); const SfxFilter* SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const { SfxFilterMatcher aMatch( pImpl->aName ); return aMatch.GetAnyFilter( nMust, nDont ); } //---------------------------------------------------------------- SfxFilterContainer::SfxFilterContainer( const String& rName ) { pImpl = new SfxFilterContainer_Impl( rName ); } //---------------------------------------------------------------- SfxFilterContainer::~SfxFilterContainer() { delete pImpl; } //---------------------------------------------------------------- const String SfxFilterContainer::GetName() const { return pImpl->aName; } const SfxFilter* SfxFilterContainer::GetDefaultFilter_Impl( const String& rName ) { // Try to find out the type of factory. // Interpret given name as Service- and ShortName! SvtModuleOptions aOpt; SvtModuleOptions::EFactory eFactory = aOpt.ClassifyFactoryByServiceName(rName); if (eFactory == SvtModuleOptions::E_UNKNOWN_FACTORY) eFactory = aOpt.ClassifyFactoryByShortName(rName); // could not classify factory by its service nor by its short name. // Must be an unknown factory! => return NULL if (eFactory == SvtModuleOptions::E_UNKNOWN_FACTORY) return NULL; // For the following code we need some additional informations. String sServiceName = aOpt.GetFactoryName(eFactory); String sShortName = aOpt.GetFactoryShortName(eFactory); String sDefaultFilter = aOpt.GetFactoryDefaultFilter(eFactory); // Try to get the default filter. Dont fiorget to verify it. // May the set default filter does not exists any longer or // does not fit the given factory. const SfxFilterMatcher aMatcher; const SfxFilter* pFilter = aMatcher.GetFilter4FilterName(sDefaultFilter); if ( (pFilter ) && (pFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) != COMPARE_EQUAL) ) { pFilter = 0; } // If at least no default filter could be located - use any filter of this // factory. if (!pFilter) { if ( bFirstRead ) ReadFilters_Impl(); sal_uInt16 nCount = ( sal_uInt16 ) pFilterArr->Count(); for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pCheckFilter = pFilterArr->GetObject( n ); if ( pCheckFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) == COMPARE_EQUAL ) { pFilter = pCheckFilter; break; } } } return pFilter; } //---------------------------------------------------------------- class SfxFilterMatcherArr_Impl; static SfxFilterMatcherArr_Impl* pImplArr = 0; // Impl-Data is shared between all FilterMatchers of the same factory class SfxFilterMatcher_Impl { public: ::rtl::OUString aName; SfxFilterList_Impl* pList; // is created on demand void InitForIterating() const; void Update(); SfxFilterMatcher_Impl() : pList(0) {} }; DECL_PTRARRAY( SfxFilterMatcherArr_Impl, SfxFilterMatcher_Impl*, 2, 2 ) SfxFilterMatcher::SfxFilterMatcher( const String& rName ) : pImpl( 0 ) { if ( !pImplArr ) // keep track of created filter matchers to recycle the FilterLists pImplArr = new SfxFilterMatcherArr_Impl; String aName = SfxObjectShell::GetServiceNameFromFactory( rName ); DBG_ASSERT(aName.Len(), "Found boes type :-)"); for ( sal_uInt16 n=0; nCount(); n++ ) { // find the impl-Data of any comparable FilterMatcher that was created before SfxFilterMatcher_Impl* pImp = pImplArr->GetObject(n); if ( String(pImp->aName) == aName ) pImpl = pImp; } if ( !pImpl ) { // first Matcher created for this factory pImpl = new SfxFilterMatcher_Impl; pImpl->aName = aName; pImplArr->Insert( pImplArr->Count(), pImpl ); } } SfxFilterMatcher::SfxFilterMatcher() { // global FilterMatcher always uses global filter array (also created on demand) pImpl = new SfxFilterMatcher_Impl; } SfxFilterMatcher::~SfxFilterMatcher() { if ( !pImpl->aName.getLength() ) // only the global Matcher owns his ImplData delete pImpl; } void SfxFilterMatcher_Impl::Update() { if ( pList ) { // this List was already used pList->Clear(); for ( sal_uInt16 n=0; nCount(); n++ ) { SfxFilter* pFilter = pFilterArr->GetObject(n); if ( pFilter->GetServiceName() == String(aName) ) pList->Insert( pFilter, LIST_APPEND ); } } } void SfxFilterMatcher_Impl::InitForIterating() const { if ( pList ) return; if ( bFirstRead ) // global filter array has not been created yet SfxFilterContainer::ReadFilters_Impl(); if ( aName.getLength() ) { // matcher of factory: use only filters of that document type ((SfxFilterMatcher_Impl*)this)->pList = new SfxFilterList_Impl; ((SfxFilterMatcher_Impl*)this)->Update(); } else { // global matcher: use global filter array ((SfxFilterMatcher_Impl*)this)->pList = pFilterArr; } } const SfxFilter* SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const { pImpl->InitForIterating(); sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count(); for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pFilter = pImpl->pList->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) ) return pFilter; } return NULL; } //---------------------------------------------------------------- sal_uInt32 SfxFilterMatcher::GuessFilterIgnoringContent( SfxMedium& rMedium, const SfxFilter**ppFilter, SfxFilterFlags /*nMust*/, SfxFilterFlags /*nDont*/ ) const { Reference< XTypeDetection > xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection")), UNO_QUERY ); ::rtl::OUString sTypeName; try { //!MBA: nmust, ndont? sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ); } catch( Exception& ) { } *ppFilter = NULL; if ( sTypeName.getLength() ) *ppFilter = GetFilter4EA( sTypeName ); return *ppFilter ? ERRCODE_NONE : ERRCODE_ABORT; } //---------------------------------------------------------------- #define CHECKERROR() \ if( nErr == 1 || nErr == USHRT_MAX || nErr == ULONG_MAX ) \ { \ ByteString aText = "Fehler in FilterDetection: Returnwert ";\ aText += ByteString::CreateFromInt32(nErr); \ if( pFilter ) \ { \ aText += ' '; \ aText += ByteString(U2S(pFilter->GetFilterName())); \ } \ DBG_ERROR( aText.GetBuffer() ); \ nErr = ERRCODE_ABORT; \ } //---------------------------------------------------------------- sal_uInt32 SfxFilterMatcher::GuessFilter( SfxMedium& rMedium, const SfxFilter**ppFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { return GuessFilterControlDefaultUI( rMedium, ppFilter, nMust, nDont, sal_True ); } //---------------------------------------------------------------- sal_uInt32 SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, const SfxFilter** ppFilter, SfxFilterFlags nMust, SfxFilterFlags nDont, sal_Bool /*bDefUI*/ ) const { const SfxFilter* pOldFilter = *ppFilter; // no detection service -> nothing to do ! Reference< XTypeDetection > xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection")), UNO_QUERY ); if (!xDetection.is()) return ERRCODE_ABORT; ::rtl::OUString sTypeName; try { // open the stream one time only ... // Otherwise it will be tried more than once and show the same interaction more than once ... ::rtl::OUString sURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ); ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInStream = rMedium.GetInputStream(); // stream exists => deep detection (with preselection ... if possible) if (xInStream.is()) { ::comphelper::MediaDescriptor aDescriptor; aDescriptor[::comphelper::MediaDescriptor::PROP_URL() ] <<= sURL; aDescriptor[::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] <<= xInStream; aDescriptor[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= rMedium.GetInteractionHandler(); if ( pImpl->aName.getLength() ) aDescriptor[::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE()] <<= pImpl->aName; if ( pOldFilter ) { aDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= ::rtl::OUString( pOldFilter->GetTypeName() ); aDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= ::rtl::OUString( pOldFilter->GetFilterName() ); } ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lDescriptor = aDescriptor.getAsConstPropertyValueList(); sTypeName = xDetection->queryTypeByDescriptor(lDescriptor, sal_True); // lDescriptor is used as In/Out param ... dont use aDescriptor.getAsConstPropertyValueList() directly! } // no stream exists => try flat detection without preselection as fallback else sTypeName = xDetection->queryTypeByURL(sURL); if (sTypeName.getLength()) { // detect filter by given type // In case of this matcher is bound to a particular document type: // If there is no acceptable type for this document at all, the type detection has possibly returned something else. // The DocumentService property is only a preselection, and all preselections are considered as optional! // This "wrong" type will be sorted out now because we match only allowed filters to the detected type ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > lQuery(1); lQuery[0].Name = ::rtl::OUString::createFromAscii("Name"); lQuery[0].Value <<= sTypeName; const SfxFilter* pFilter = GetFilterForProps(lQuery, nMust, nDont); if (pFilter) { *ppFilter = pFilter; return ERRCODE_NONE; } } } catch(const Exception&) {} return ERRCODE_ABORT; } //---------------------------------------------------------------- sal_Bool SfxFilterMatcher::IsFilterInstalled_Impl( const SfxFilter* pFilter ) { if ( pFilter->GetFilterFlags() & SFX_FILTER_MUSTINSTALL ) { // Hier k"onnte noch eine Nachinstallation angeboten werden String aText( SfxResId( STR_FILTER_NOT_INSTALLED ) ); aText.SearchAndReplaceAscii( "$(FILTER)", pFilter->GetUIName() ); QueryBox aQuery( NULL, WB_YES_NO | WB_DEF_YES, aText ); short nRet = aQuery.Execute(); if ( nRet == RET_YES ) { #ifdef DBG_UTIL // Setup starten InfoBox( NULL, DEFINE_CONST_UNICODE("Hier soll jetzt das Setup starten!") ).Execute(); #endif // Installation mu\s hier noch mitteilen, ob es geklappt hat, dann kann das // Filterflag gel"oscht werden } return ( !(pFilter->GetFilterFlags() & SFX_FILTER_MUSTINSTALL) ); } else if ( pFilter->GetFilterFlags() & SFX_FILTER_CONSULTSERVICE ) { String aText( SfxResId( STR_FILTER_CONSULT_SERVICE ) ); aText.SearchAndReplaceAscii( "$(FILTER)", pFilter->GetUIName() ); InfoBox ( NULL, aText ).Execute(); return sal_False; } else return sal_True; } sal_uInt32 SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, const SfxFilter**ppFilter, sal_Bool /*bPlugIn*/, sal_Bool bAPI ) const /* [Beschreibung] Hier wird noch die Filterauswahlbox hochgezogen. Sonst GuessFilter */ { const SfxFilter* pOldFilter = rMedium.GetFilter(); if ( pOldFilter ) { if( !IsFilterInstalled_Impl( pOldFilter ) ) pOldFilter = 0; else { SFX_ITEMSET_ARG( rMedium.GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False); if ( ( pOldFilter->GetFilterFlags() & SFX_FILTER_PACKED ) && pSalvageItem ) // Salvage is always done without packing pOldFilter = 0; } } const SfxFilter* pFilter = pOldFilter; sal_Bool bPreview = rMedium.IsPreview_Impl(); SFX_ITEMSET_ARG(rMedium.GetItemSet(), pReferer, SfxStringItem, SID_REFERER, sal_False); if ( bPreview && rMedium.IsRemote() && ( !pReferer || pReferer->GetValue().CompareToAscii("private:searchfolder:",21 ) != COMPARE_EQUAL ) ) return ERRCODE_ABORT; ErrCode nErr = GuessFilter( rMedium, &pFilter ); if ( nErr == ERRCODE_ABORT ) return nErr; if ( nErr == ERRCODE_IO_PENDING ) { *ppFilter = pFilter; return nErr; } if ( !pFilter ) { const SfxFilter* pInstallFilter = NULL; // Jetzt auch Filter testen, die nicht installiert sind ( ErrCode ist irrelevant ) GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, SFX_FILTER_CONSULTSERVICE ); if ( pInstallFilter ) { if ( IsFilterInstalled_Impl( pInstallFilter ) ) // Eventuell wurde der Filter nachinstalliert pFilter = pInstallFilter; } else { // Jetzt auch Filter testen, die erst von Star bezogen werden m"ussen ( ErrCode ist irrelevant ) GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, 0 ); if ( pInstallFilter ) IsFilterInstalled_Impl( pInstallFilter ); } } sal_Bool bHidden = bPreview; SFX_ITEMSET_ARG( rMedium.GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False); if ( !bHidden && pFlags ) { String aFlags( pFlags->GetValue() ); aFlags.ToUpperAscii(); if( STRING_NOTFOUND != aFlags.Search( 'H' ) ) bHidden = sal_True; } *ppFilter = pFilter; if ( bHidden || (bAPI && nErr == ERRCODE_SFX_CONSULTUSER) ) nErr = pFilter ? ERRCODE_NONE : ERRCODE_ABORT; return nErr; } const SfxFilter* SfxFilterMatcher::GetFilterForProps( const com::sun::star::uno::Sequence < ::com::sun::star::beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > xTypeCFG; if( xServiceManager.is() == sal_True ) 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 ); if ( xTypeCFG.is() ) { // make query for all types matching the properties ::com::sun::star::uno::Reference < com::sun::star::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq ); while ( xEnum->hasMoreElements() ) { ::comphelper::SequenceAsHashMap aProps( xEnum->nextElement() ); ::rtl::OUString aValue; // try to get the preferred filter (works without loading all filters!) if ( (aProps[::rtl::OUString::createFromAscii("PreferredFilter")] >>= aValue) && aValue.getLength() ) { const SfxFilter* pFilter = SfxFilter::GetFilterByName( aValue ); if ( !pFilter || (pFilter->GetFilterFlags() & nMust) != nMust || (pFilter->GetFilterFlags() & nDont ) ) // check for filter flags // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed continue; if ( pImpl->aName.getLength() ) { // if this is not the global FilterMatcher: check if filter matches the document type ::rtl::OUString aService; if ( pFilter->GetServiceName() != String(pImpl->aName) ) { // preferred filter belongs to another document type; now we must search the filter pImpl->InitForIterating(); aProps[::rtl::OUString::createFromAscii("Name")] >>= aValue; pFilter = GetFilter4EA( aValue, nMust, nDont ); if ( pFilter ) return pFilter; } else return pFilter; } else return pFilter; } } } return 0; } const SfxFilter* SfxFilterMatcher::GetFilter4Mime( const String& rMediaType,SfxFilterFlags nMust, SfxFilterFlags nDont ) const { if ( pImpl->pList ) { sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count(); for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pFilter = pImpl->pList->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetMimeType() == rMediaType ) return pFilter; } return 0; } com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1); aSeq[0].Name = ::rtl::OUString::createFromAscii("MediaType"); aSeq[0].Value <<= ::rtl::OUString( rMediaType ); return GetFilterForProps( aSeq, nMust, nDont ); } const SfxFilter* SfxFilterMatcher::GetFilter4EA( const String& rType,SfxFilterFlags nMust, SfxFilterFlags nDont ) const { if ( pImpl->pList ) { sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count(); const SfxFilter* pFirst = 0; for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pFilter = pImpl->pList->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetTypeName() == rType ) { if (nFlags & SFX_FILTER_PREFERED) return pFilter; if (!pFirst) pFirst = pFilter; } } if (pFirst) return pFirst; return 0; } com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1); aSeq[0].Name = ::rtl::OUString::createFromAscii("Name"); aSeq[0].Value <<= ::rtl::OUString( rType ); return GetFilterForProps( aSeq, nMust, nDont ); } const SfxFilter* SfxFilterMatcher::GetFilter4Extension( const String& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { if ( pImpl->pList ) { sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count(); for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pFilter = pImpl->pList->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) ) { String sWildCard = ToUpper_Impl( pFilter->GetWildcard().GetWildCard() ); String sExt = ToUpper_Impl( rExt ); if (!sExt.Len()) continue; if (sExt.GetChar(0) != (sal_Unicode)'.') sExt.Insert((sal_Unicode)'.', 0); WildCard aCheck(sWildCard, ';'); if (aCheck.Matches(sExt)) return pFilter; } } return 0; } // Use extension without dot! String sExt( rExt ); if ( sExt.Len() && ( sExt.GetChar(0) == (sal_Unicode)'.' )) sExt.Erase(0,1); com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1); aSeq[0].Name = ::rtl::OUString::createFromAscii("Extensions"); ::com::sun::star::uno::Sequence < ::rtl::OUString > aExts(1); aExts[0] = sExt; aSeq[0].Value <<= aExts; return GetFilterForProps( aSeq, nMust, nDont ); } const SfxFilter* SfxFilterMatcher::GetFilter4ClipBoardId( sal_uInt32 nId, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { if (nId == 0) return 0; com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1); ::rtl::OUString aName = SotExchange::GetFormatName( nId ); aSeq[0].Name = ::rtl::OUString::createFromAscii("ClipboardFormat"); aSeq[0].Value <<= aName; return GetFilterForProps( aSeq, nMust, nDont ); } const SfxFilter* SfxFilterMatcher::GetFilter4UIName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { pImpl->InitForIterating(); const SfxFilter* pFirstFilter=0; sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count(); for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pFilter = pImpl->pList->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetUIName() == rName ) { if ( pFilter->GetFilterFlags() & SFX_FILTER_PREFERED ) return pFilter; else if ( !pFirstFilter ) pFirstFilter = pFilter; } } return pFirstFilter; } const SfxFilter* SfxFilterMatcher::GetFilter4FilterName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { String aName( rName ); sal_uInt16 nIndex = aName.SearchAscii(": "); if ( nIndex != STRING_NOTFOUND ) { DBG_ERROR("Old filter name used!"); aName = rName.Copy( nIndex + 2 ); } if ( bFirstRead ) { ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG ; ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xTypeCFG ; if( xServiceManager.is() == sal_True ) { 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 ); 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 ); } if( xFilterCFG.is() && xTypeCFG.is() ) { if ( !pFilterArr ) CreateFilterArr(); else { for( sal_uInt16 n=0; nCount(); n++ ) { const SfxFilter* pFilter = pFilterArr->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().CompareIgnoreCaseToAscii( aName ) == COMPARE_EQUAL ) return pFilter; } } SfxFilterContainer::ReadSingleFilter_Impl( rName, xTypeCFG, xFilterCFG, sal_False ); } } SfxFilterList_Impl* pList = pImpl->pList; if ( !pList ) pList = pFilterArr; sal_uInt16 nCount = ( sal_uInt16 ) pList->Count(); for( sal_uInt16 n = 0; n < nCount; n++ ) { const SfxFilter* pFilter = pList->GetObject( n ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().CompareIgnoreCaseToAscii( aName ) == COMPARE_EQUAL ) return pFilter; } return NULL; } IMPL_STATIC_LINK( SfxFilterMatcher, MaybeFileHdl_Impl, String*, pString ) { const SfxFilter* pFilter = pThis->GetFilter4Extension( *pString, SFX_FILTER_IMPORT ); if( pFilter && !pFilter->GetWildcard().Matches( String() ) && pFilter->GetWildcard() != DEFINE_CONST_UNICODE("*.*") && pFilter->GetWildcard() != '*' ) return sal_True; return sal_False; } //---------------------------------------------------------------- SfxFilterMatcherIter::SfxFilterMatcherIter( const SfxFilterMatcher* pMatchP, SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP ) : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ), nCurrent(0), pMatch( pMatchP->pImpl) { if( nOrMask == 0xffff ) //Wg. Fehlbuild auf s nOrMask = 0; pMatch->InitForIterating(); } //---------------------------------------------------------------- const SfxFilter* SfxFilterMatcherIter::Find_Impl() { const SfxFilter* pFilter = 0; while( nCurrent < pMatch->pList->Count() ) { pFilter = pMatch->pList->GetObject(nCurrent++); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if( ((nFlags & nOrMask) == nOrMask ) && !(nFlags & nAndMask ) ) break; pFilter = 0; } return pFilter; } const SfxFilter* SfxFilterMatcherIter::First() { nCurrent = 0; return Find_Impl(); } //---------------------------------------------------------------- const SfxFilter* SfxFilterMatcherIter::Next() { return Find_Impl(); } /*--------------------------------------------------------------- helper to build own formatted string from given stringlist by using given seperator ---------------------------------------------------------------*/ ::rtl::OUString implc_convertStringlistToString( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& lList , const sal_Unicode& cSeperator, const ::rtl::OUString& sPrefix ) { ::rtl::OUStringBuffer sString ( 1000 ) ; sal_Int32 nCount = lList.getLength(); sal_Int32 nItem = 0 ; for( nItem=0; nItem 0 ) { sString.append( sPrefix ); } sString.append( lList[nItem] ); if( nItem+1& xTypeCFG, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xFilterCFG, sal_Bool bUpdate ) { ::rtl::OUString sFilterName( rName ); SfxFilterList_Impl& rList = *pFilterArr; ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lFilterProperties ; ::com::sun::star::uno::Any aResult; try { aResult = xFilterCFG->getByName( sFilterName ); } catch( ::com::sun::star::container::NoSuchElementException& ) { aResult = ::com::sun::star::uno::Any(); } if( aResult >>= lFilterProperties ) { // collect informations to add filter to container // (attention: some informations aren't available on filter directly ... you must search for corresponding type too!) sal_Int32 nFlags = 0 ; sal_Int32 nClipboardId = 0 ; sal_Int32 nDocumentIconId = 0 ; sal_Int32 nFormatVersion = 0 ; ::rtl::OUString sMimeType ; ::rtl::OUString sType ; ::rtl::OUString sUIName ; ::rtl::OUString sHumanName ; ::rtl::OUString sDefaultTemplate ; ::rtl::OUString sUserData ; ::rtl::OUString sExtension ; ::rtl::OUString sPattern ; ::rtl::OUString sServiceName ; // first get directly available properties sal_Int32 nFilterPropertyCount = lFilterProperties.getLength(); sal_Int32 nFilterProperty = 0 ; for( nFilterProperty=0; nFilterProperty>= nFormatVersion; } else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "TemplateName" ) == 0 ) { lFilterProperties[nFilterProperty].Value >>= sDefaultTemplate; } else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "Flags" ) == 0 ) { lFilterProperties[nFilterProperty].Value >>= nFlags; } else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "UIName" ) == 0 ) { lFilterProperties[nFilterProperty].Value >>= sUIName; } else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "UserData" ) == 0 ) { ::com::sun::star::uno::Sequence< ::rtl::OUString > lUserData; lFilterProperties[nFilterProperty].Value >>= lUserData; sUserData = implc_convertStringlistToString( lUserData, ',', ::rtl::OUString() ); } else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "DocumentService" ) == 0 ) { lFilterProperties[nFilterProperty].Value >>= sServiceName; } else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "Type" ) == 0 ) { lFilterProperties[nFilterProperty].Value >>= sType; // Try to get filter .. but look for any exceptions! // May be filter was deleted by another thread ... try { aResult = xTypeCFG->getByName( sType ); } catch( ::com::sun::star::container::NoSuchElementException& ) { aResult = ::com::sun::star::uno::Any(); } ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lTypeProperties; if( aResult >>= lTypeProperties ) { // get indirect available properties then (types) sal_Int32 nTypePropertyCount = lTypeProperties.getLength(); sal_Int32 nTypeProperty = 0 ; for( nTypeProperty=0; nTypeProperty>= sHumanName; } else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "DocumentIconID" ) == 0 ) { lTypeProperties[nTypeProperty].Value >>= nDocumentIconId; } else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "MediaType" ) == 0 ) { lTypeProperties[nTypeProperty].Value >>= sMimeType; } else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "Extensions" ) == 0 ) { ::com::sun::star::uno::Sequence< ::rtl::OUString > lExtensions; lTypeProperties[nTypeProperty].Value >>= lExtensions; sExtension = implc_convertStringlistToString( lExtensions, ';', DEFINE_CONST_UNICODE("*.") ); } else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "URLPattern" ) == 0 ) { ::com::sun::star::uno::Sequence< ::rtl::OUString > lPattern; lTypeProperties[nTypeProperty].Value >>= lPattern; sPattern = implc_convertStringlistToString( lPattern, ';', ::rtl::OUString() ); } } } } } if ( !sServiceName.getLength() ) return; // old formats are found ... using HumanPresentableName! if( sHumanName.getLength() ) { nClipboardId = SotExchange::RegisterFormatName( sHumanName ); // #100570# For external filters ignore clipboard IDs if((nFlags & SFX_FILTER_STARONEFILTER) == SFX_FILTER_STARONEFILTER) { nClipboardId = 0; } } // register SfxFilter // first erase module name from old filter names! // e.g: "scalc: DIF" => "DIF" sal_Int32 nStartRealName = sFilterName.indexOf( DEFINE_CONST_UNICODE(": "), 0 ); if( nStartRealName != -1 ) { DBG_ERROR("Old format, not supported!"); sFilterName = sFilterName.copy( nStartRealName+2 ); } SfxFilter* pFilter = bUpdate ? (SfxFilter*) SfxFilter::GetFilterByName( sFilterName ) : 0; sal_Bool bNew = sal_False; if (!pFilter) { bNew = sal_True; pFilter = new SfxFilter( sFilterName , sExtension , nFlags , nClipboardId , sType , (sal_uInt16)nDocumentIconId , sMimeType , sUserData , sServiceName ); } else { pFilter->aFilterName = sFilterName; pFilter->aWildCard = WildCard(sExtension, ';'); pFilter->nFormatType = nFlags; pFilter->lFormat = nClipboardId; pFilter->aTypeName = sType; pFilter->nDocIcon = (sal_uInt16)nDocumentIconId; pFilter->aMimeType = sMimeType; pFilter->aUserData = sUserData; pFilter->aServiceName = sServiceName; } // Don't forget to set right UIName! // Otherwise internal name is used as fallback ... pFilter->SetUIName( sUIName ); pFilter->SetDefaultTemplate( sDefaultTemplate ); if( nFormatVersion ) { pFilter->SetVersion( nFormatVersion ); } pFilter->SetURLPattern(sPattern); if (bNew) rList.Insert( pFilter, USHRT_MAX ); } } void SfxFilterContainer::ReadFilters_Impl( sal_Bool bUpdate ) { RTL_LOGFILE_CONTEXT( aMeasure, "sfx2 (as96863) ::SfxFilterContainer::ReadFilters" ); if ( !pFilterArr ) CreateFilterArr(); bFirstRead = sal_False; SfxFilterList_Impl& rList = *pFilterArr; try { // get the FilterFactory service to access the registered filters ... and types! ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG ; ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xTypeCFG ; if( xServiceManager.is() == sal_True ) { 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 ); 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 ); } if( ( xFilterCFG.is() == sal_True ) && ( xTypeCFG.is() == sal_True ) ) { // select right query to get right set of filters for search modul ::com::sun::star::uno::Sequence< ::rtl::OUString > lFilterNames = xFilterCFG->getElementNames(); if ( lFilterNames.getLength() ) { // If list of filters already exist ... // ReadExternalFilters must work in update mode. // Best way seems to mark all filters NOT_INSTALLED // and change it back for all valid filters afterwards. if( rList.Count() > 0 ) { bUpdate = sal_True; sal_uInt16 nCount = (sal_uInt16)rList.Count(); SfxFilter* pFilter; for (sal_uInt16 f=0; fnFormatType |= SFX_FILTER_NOTINSTALLED; } } // get all properties of filters ... put it into the filter container sal_Int32 nFilterCount = lFilterNames.getLength(); sal_Int32 nFilter=0; for( nFilter=0; nFilter-1) bDBGStop = sal_True; #endif ReadSingleFilter_Impl( sFilterName, xTypeCFG, xFilterCFG, bUpdate ); } } } } catch( ::com::sun::star::uno::Exception& ) { DBG_ASSERT( sal_False, "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached.\n" ); } if ( pImplArr && bUpdate ) { // global filter arry was modified, factory specific ones might need an update too for ( sal_uInt16 n=0; nCount(); n++ ) pImplArr->GetObject(n)->Update(); } }