/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 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 #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 #include #include #include #include #include #include #include #include #include #include #include #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; #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 #include #include namespace { class theSfxFilterListener : public rtl::Static {}; } static SfxFilterList_Impl* pFilterArr = 0; static sal_Bool bFirstRead = sal_True; static void CreateFilterArr() { pFilterArr = new SfxFilterList_Impl; theSfxFilterListener::get(); } //---------------------------------------------------------------- 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( GetFilter4EA, const String&, rEA ); IMPL_FORWARD_LOOP( GetFilter4Extension, const String&, rExt ); IMPL_FORWARD_LOOP( GetFilter4FilterName, 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(); for ( size_t i = 0, n = pFilterArr->size(); i < n; ++i ) { const SfxFilter* pCheckFilter = pFilterArr->at( i ); if ( pCheckFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) == COMPARE_EQUAL ) { pFilter = pCheckFilter; break; } } } return pFilter; } //---------------------------------------------------------------- // 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(const ::rtl::OUString &rName) : aName(rName) , pList(0) { } }; namespace { typedef boost::ptr_vector SfxFilterMatcherArr_Impl; static SfxFilterMatcherArr_Impl aImplArr; static int nSfxFilterMatcherCount; class hasName : public std::unary_function { private: const rtl::OUString& mrName; public: hasName(const rtl::OUString &rName) : mrName(rName) {} bool operator() (const SfxFilterMatcher_Impl& rImpl) const { return rImpl.aName == mrName; } }; SfxFilterMatcher_Impl & getSfxFilterMatcher_Impl(const rtl::OUString &rName) { rtl::OUString aName; if (rName.getLength()) aName = SfxObjectShell::GetServiceNameFromFactory(rName); // find the impl-Data of any comparable FilterMatcher that was created // previously SfxFilterMatcherArr_Impl::iterator aEnd = aImplArr.end(); SfxFilterMatcherArr_Impl::iterator aIter = std::find_if(aImplArr.begin(), aEnd, hasName(rName)); if (aIter != aEnd) return *aIter; // first Matcher created for this factory SfxFilterMatcher_Impl *pImpl = new SfxFilterMatcher_Impl(aName); aImplArr.push_back(pImpl); return *pImpl; } } SfxFilterMatcher::SfxFilterMatcher( const String& rName ) : m_rImpl( getSfxFilterMatcher_Impl(rName) ) { ++nSfxFilterMatcherCount; } SfxFilterMatcher::SfxFilterMatcher() : m_rImpl( getSfxFilterMatcher_Impl(::rtl::OUString()) ) { // global FilterMatcher always uses global filter array (also created on // demand) ++nSfxFilterMatcherCount; } SfxFilterMatcher::~SfxFilterMatcher() { --nSfxFilterMatcherCount; if (nSfxFilterMatcherCount == 0) aImplArr.clear(); } void SfxFilterMatcher_Impl::Update() { if ( pList ) { // this List was already used pList->clear(); for ( size_t i = 0, n = pFilterArr->size(); i < n; ++i ) { SfxFilter* pFilter = pFilterArr->at( i ); if ( pFilter->GetServiceName() == String(aName) ) pList->push_back( pFilter ); } } } 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 { m_rImpl.InitForIterating(); for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i ) { const SfxFilter* pFilter = m_rImpl.pList->at( i ); 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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.TypeDetection"))), UNO_QUERY ); ::rtl::OUString sTypeName; try { sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ); } catch( Exception& ) { } *ppFilter = NULL; if ( sTypeName.getLength() ) { // make sure filter list is initialized m_rImpl.InitForIterating(); *ppFilter = GetFilter4EA( sTypeName, nMust, nDont ); } return *ppFilter ? ERRCODE_NONE : 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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.TypeDetection"))), UNO_QUERY ); if (!xDetection.is()) return ERRCODE_ABORT; ::rtl::OUString sTypeName; try { // open the stream one times only ... // Otherwhise it will be tried more then once and show the same interaction more then 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 ( m_rImpl.aName.getLength() ) aDescriptor[::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE()] <<= m_rImpl.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(RTL_CONSTASCII_USTRINGPARAM("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 ) { // Here could a re-installation be offered 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 // Start Setup InfoBox( NULL, DEFINE_CONST_UNICODE("Here should the Setup now be starting!") ).Execute(); #endif // Installation must still give feedback if it worked or not, // then the Filterflag be deleted } 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 /* [Description] Here the Filter selection box is pulled up. Otherwise 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; // Now test the filter which are not installed (ErrCode is irrelevant) GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, SFX_FILTER_CONSULTSERVICE ); if ( pInstallFilter ) { if ( IsFilterInstalled_Impl( pInstallFilter ) ) // Maybe the filter was installed was installed afterwards. pFilter = pInstallFilter; } else { // Now test the filter, which first must be obtained by Star // (ErrCode is 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(RTL_CONSTASCII_USTRINGPARAM("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 ( m_rImpl.aName.getLength() ) { // if this is not the global FilterMatcher: check if filter matches the document type ::rtl::OUString aService; if ( pFilter->GetServiceName() != String(m_rImpl.aName) ) { // preferred filter belongs to another document type; now we must search the filter m_rImpl.InitForIterating(); aProps[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name"))] >>= aValue; pFilter = GetFilter4EA( aValue, nMust, nDont ); if ( pFilter ) return pFilter; } else return pFilter; } else return pFilter; } } } return 0; } const SfxFilter* SfxFilterMatcher::GetFilter4Mime( const ::rtl::OUString& rMediaType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { if ( m_rImpl.pList ) { for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i ) { const SfxFilter* pFilter = m_rImpl.pList->at( i ); 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(RTL_CONSTASCII_USTRINGPARAM("MediaType")); aSeq[0].Value <<= rMediaType; return GetFilterForProps( aSeq, nMust, nDont ); } const SfxFilter* SfxFilterMatcher::GetFilter4EA( const String& rType,SfxFilterFlags nMust, SfxFilterFlags nDont ) const { if ( m_rImpl.pList ) { const SfxFilter* pFirst = 0; for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i ) { const SfxFilter* pFilter = m_rImpl.pList->at( i ); 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(RTL_CONSTASCII_USTRINGPARAM("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 ( m_rImpl.pList ) { for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i ) { const SfxFilter* pFilter = m_rImpl.pList->at( i ); SfxFilterFlags nFlags = pFilter->GetFilterFlags(); if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) ) { String sWildCard = ToUpper_Impl( pFilter->GetWildcard().getGlob() ); 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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("ClipboardFormat")); aSeq[0].Value <<= aName; return GetFilterForProps( aSeq, nMust, nDont ); } const SfxFilter* SfxFilterMatcher::GetFilter4UIName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const { m_rImpl.InitForIterating(); const SfxFilter* pFirstFilter=0; for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i ) { const SfxFilter* pFilter = m_rImpl.pList->at( i ); 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 ) { OSL_FAIL("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 ( size_t i = 0, n = pFilterArr->size(); i < n; ++i ) { const SfxFilter* pFilter = pFilterArr->at( i ); 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 = m_rImpl.pList; if ( !pList ) pList = pFilterArr; for ( size_t i = 0, n = pList->size(); i < n; ++i ) { const SfxFilter* pFilter = pList->at( i ); 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().Matches(DEFINE_CONST_UNICODE("*.*")) && !pFilter->GetWildcard().Matches('*') ) { return sal_True; } return sal_False; } //---------------------------------------------------------------- SfxFilterMatcherIter::SfxFilterMatcherIter( const SfxFilterMatcher& rMatcher, SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP ) : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ), nCurrent(0), m_rMatch(rMatcher.m_rImpl) { if( nOrMask == 0xffff ) //Due to falty build on s nOrMask = 0; m_rMatch.InitForIterating(); } //---------------------------------------------------------------- const SfxFilter* SfxFilterMatcherIter::Find_Impl() { const SfxFilter* pFilter = 0; while( nCurrent < m_rMatch.pList->size() ) { pFilter = m_rMatch.pList->at( 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 formated 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.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("TemplateName")) ) { lFilterProperties[nFilterProperty].Value >>= sDefaultTemplate; } else if( lFilterProperties[nFilterProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Flags")) ) { lFilterProperties[nFilterProperty].Value >>= nFlags; } else if( lFilterProperties[nFilterProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UIName")) ) { lFilterProperties[nFilterProperty].Value >>= sUIName; } else if( lFilterProperties[nFilterProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UserData")) ) { ::com::sun::star::uno::Sequence< ::rtl::OUString > lUserData; lFilterProperties[nFilterProperty].Value >>= lUserData; sUserData = implc_convertStringlistToString( lUserData, ',', ::rtl::OUString() ); } else if( lFilterProperties[nFilterProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DocumentService")) ) { lFilterProperties[nFilterProperty].Value >>= sServiceName; } else if( lFilterProperties[nFilterProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Type")) ) { 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 (const ::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.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DocumentIconID")) ) { lTypeProperties[nTypeProperty].Value >>= nDocumentIconId; } else if( lTypeProperties[nTypeProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MediaType")) ) { lTypeProperties[nTypeProperty].Value >>= sMimeType; } else if( lTypeProperties[nTypeProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Extensions")) ) { ::com::sun::star::uno::Sequence< ::rtl::OUString > lExtensions; lTypeProperties[nTypeProperty].Value >>= lExtensions; sExtension = implc_convertStringlistToString( lExtensions, ';', DEFINE_CONST_UNICODE("*.") ); } else if( lTypeProperties[nTypeProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URLPattern")) ) { ::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 ); // 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 ) { OSL_FAIL("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.push_back( pFilter ); } } 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 seams to mark all filters NOT_INSTALLED // and change it back for all valid filters afterwards. if( !rList.empty() ) { bUpdate = sal_True; SfxFilter* pFilter; for ( size_t i = 0, n = rList.size(); i < n; ++i ) { pFilter = NULL; pFilter = rList[ i ]; pFilter->nFormatType |= 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