20#include <com/sun/star/beans/PropertyValue.hpp>
21#include <com/sun/star/configuration/theDefaultProvider.hpp>
22#include <com/sun/star/container/XContainerQuery.hpp>
23#include <com/sun/star/container/XNameAccess.hpp>
24#include <com/sun/star/embed/VerbDescriptor.hpp>
25#include <com/sun/star/document/XTypeDetection.hpp>
27#include <osl/diagnose.h>
35#include <rtl/ustrbuf.hxx>
43MimeConfigurationHelper::MimeConfigurationHelper( uno::Reference< uno::XComponentContext > xContext )
47 throw uno::RuntimeException();
53 OUStringBuffer aResult;
57 for ( sal_Int32 nInd = 0; nInd <
aClassID.getLength(); nInd++ )
59 if ( nInd == 4 || nInd == 6 || nInd == 8 || nInd == 10 )
62 sal_Int32 nDigit1 =
static_cast<sal_Int32
>(
static_cast<sal_uInt8>(
aClassID[nInd]) / 16 );
64 aResult.append( OUString::number(nDigit1, 16) + OUString::number( nDigit2, 16 ) );
68 return aResult.makeStringAndClear();
74 if ( aChar >=
'0' && aChar <=
'9' )
76 else if ( aChar >=
'a' && aChar <=
'f' )
77 return aChar -
'a' + 10;
78 else if ( aChar >=
'A' && aChar <=
'F' )
79 return aChar -
'A' + 10;
91 uno::Sequence< sal_Int8 > aResult( 16 );
92 auto pResult = aResult.getArray();
94 size_t nStrPointer = 0;
95 sal_Int32 nSeqInd = 0;
96 while( nSeqInd < 16 && nStrPointer + 1U <
nLength )
101 if ( nDigit1 > 15 || nDigit2 > 15 )
104 pResult[nSeqInd++] =
static_cast<sal_Int8>( nDigit1 * 16 + nDigit2 );
106 if ( nStrPointer <
nLength && aCharClassID[nStrPointer] ==
'-' )
110 if ( nSeqInd == 16 && nStrPointer ==
nLength )
114 return uno::Sequence< sal_Int8 >();
120 uno::Reference< container::XNameAccess > xConfig;
132 "com.sun.star.configuration.ConfigurationAccess",
136 catch( uno::Exception& )
145 std::unique_lock aGuard(
m_aMutex );
149 "/org.openoffice.Office.Embedding/Objects" );
157 std::unique_lock aGuard(
m_aMutex );
161 "/org.openoffice.Office.Embedding/Verbs");
169 std::unique_lock aGuard(
m_aMutex );
173 "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations");
181 std::unique_lock aGuard(
m_aMutex );
185 m_xContext->getServiceManager()->createInstanceWithContext(
"com.sun.star.document.FilterFactory",
m_xContext),
194 OUString aDocServiceName;
198 uno::Reference< container::XNameAccess > xFilterFactory(
200 uno::UNO_SET_THROW );
202 uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName );
203 uno::Sequence< beans::PropertyValue > aFilterData;
204 if ( aFilterAnyData >>= aFilterData )
206 for (
const auto & prop : std::as_const(aFilterData) )
207 if ( prop.Name ==
"DocumentService" )
208 prop.
Value >>= aDocServiceName;
211 catch( uno::Exception& )
214 return aDocServiceName;
220 uno::Reference< container::XContainerQuery > xTypeCFG(
221 m_xContext->getServiceManager()->createInstanceWithContext(
"com.sun.star.document.TypeDetection",
m_xContext),
229 uno::Sequence < beans::NamedValue >
aSeq { {
"MediaType", css::uno::Any(aMediaType) } };
231 uno::Reference < container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties(
aSeq );
232 while ( xEnum->hasMoreElements() )
234 uno::Sequence< beans::PropertyValue > aType;
235 if ( xEnum->nextElement() >>= aType )
237 for (
const auto & prop : std::as_const(aType) )
239 OUString aFilterName;
240 if ( prop.Name ==
"PreferredFilter"
241 && ( prop.Value >>= aFilterName ) && !aFilterName.isEmpty() )
244 if ( !aDocumentName.isEmpty() )
245 return aDocumentName;
251 catch( uno::Exception& )
260 embed::VerbDescriptor& aDescriptor )
262 bool bResult =
false;
265 uno::Reference< container::XNameAccess > xVerbsProps;
268 if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() )
270 embed::VerbDescriptor aTempDescr;
271 static constexpr OUStringLiteral sVerbID =
u"VerbID";
272 static constexpr OUStringLiteral sVerbUIName =
u"VerbUIName";
273 static constexpr OUStringLiteral sVerbFlags =
u"VerbFlags";
274 static constexpr OUStringLiteral sVerbAttributes =
u"VerbAttributes";
275 if ( ( xVerbsProps->getByName(sVerbID) >>= aTempDescr.VerbID )
276 && ( xVerbsProps->getByName(sVerbUIName) >>= aTempDescr.VerbName )
277 && ( xVerbsProps->getByName(sVerbFlags) >>= aTempDescr.VerbFlags )
278 && ( xVerbsProps->getByName(sVerbAttributes) >>= aTempDescr.VerbAttributes ) )
280 aDescriptor = aTempDescr;
285 catch( uno::Exception& )
294 const uno::Sequence< sal_Int8 >& aClassID,
295 const uno::Reference< container::XNameAccess >& xObjectProps )
297 uno::Sequence< beans::NamedValue > aResult;
303 const uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames();
305 aResult.realloc( aObjPropNames.getLength() + 1 );
306 auto pResult = aResult.getArray();
307 pResult[0].Name =
"ClassID";
310 for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ )
312 pResult[nInd + 1].Name = aObjPropNames[nInd];
314 if ( aObjPropNames[nInd] ==
"ObjectVerbs" )
316 uno::Sequence< OUString > aVerbShortcuts;
317 if ( !(xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts) )
318 throw uno::RuntimeException();
319 uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() );
320 auto aVerbDescriptorsRange = asNonConstRange(aVerbDescriptors);
321 for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ )
322 if ( !
GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptorsRange[nVerbI] ) )
323 throw uno::RuntimeException();
325 pResult[nInd+1].Value <<= aVerbDescriptors;
328 pResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] );
331 catch( uno::Exception& )
333 aResult.realloc( 0 );
343 OUString aStringClassID;
348 if ( xMediaTypeConfig.is() )
349 xMediaTypeConfig->getByName( aMediaType ) >>= aStringClassID;
351 catch( uno::Exception& )
355 return aStringClassID;
361 const OUString& aStringClassID )
363 uno::Sequence< beans::NamedValue > aObjProps;
368 aObjProps = { {
"ObjectFactory",
369 uno::Any(OUString(
"com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) },
377 uno::Reference< container::XNameAccess > xObjectProps;
381 if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
384 catch( uno::Exception& )
394 const uno::Sequence< sal_Int8 >& aClassID )
396 uno::Sequence< beans::NamedValue > aObjProps;
399 aObjProps = { {
"ObjectFactory",
400 uno::Any(OUString(
"com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) },
405 if ( !aStringClassID.isEmpty() )
408 uno::Reference< container::XNameAccess > xObjectProps;
411 if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
414 catch( uno::Exception& )
425 uno::Sequence< beans::NamedValue > aObject =
427 if ( aObject.hasElements() )
431 if ( !aDocumentName.isEmpty() )
434 return uno::Sequence< beans::NamedValue >();
441 if ( !aDocumentName.isEmpty() )
444 return uno::Sequence< beans::NamedValue >();
450 if ( !aDocName.empty() )
453 if ( xObjConfig.is() )
457 const uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
458 for (
const OUString &
id : aClassIDs )
460 uno::Reference< container::XNameAccess > xObjectProps;
461 OUString aEntryDocName;
463 if ( ( xObjConfig->getByName(
id ) >>= xObjectProps ) && xObjectProps.is()
464 && ( xObjectProps->getByName(
"ObjectDocumentServiceName") >>= aEntryDocName )
465 && aEntryDocName == aDocName )
472 catch( uno::Exception& )
477 return uno::Sequence< beans::NamedValue >();
491 if ( !aStringClassID.isEmpty() )
494 uno::Reference< container::XNameAccess > xObjectProps;
497 if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
498 xObjectProps->getByName(
"ObjectFactory") >>= aResult;
500 catch( uno::Exception& )
504 return "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory";
516 if ( !aDocName.empty() )
519 if ( xObjConfig.is() )
523 const uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
524 for (
const OUString &
id : aClassIDs )
526 uno::Reference< container::XNameAccess > xObjectProps;
527 OUString aEntryDocName;
529 if ( ( xObjConfig->getByName(
id ) >>= xObjectProps ) && xObjectProps.is()
530 && ( xObjectProps->getByName(
"ObjectDocumentServiceName" ) >>= aEntryDocName )
531 && aEntryDocName == aDocName )
533 xObjectProps->getByName(
"ObjectFactory") >>= aResult;
538 catch( uno::Exception& )
551 if ( aResult.isEmpty() )
554 if ( !aDocumentName.isEmpty() )
563 uno::Sequence< beans::PropertyValue >& aMediaDescr,
566 OUString aFilterName;
568 for (
const auto & prop : std::as_const(aMediaDescr) )
569 if ( prop.Name ==
"FilterName" )
570 prop.Value >>= aFilterName;
572 if ( aFilterName.isEmpty() )
576 uno::Reference< document::XTypeDetection > xTypeDetection(
577 m_xContext->getServiceManager()->createInstanceWithContext(
"com.sun.star.document.TypeDetection",
m_xContext),
578 uno::UNO_QUERY_THROW );
581 uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr );
584 OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD,
true );
587 for (
const auto & prop : std::as_const(aTempMD) )
588 if ( prop.Name ==
"FilterName" )
589 prop.Value >>= aFilterName;
591 if ( !aFilterName.isEmpty() )
593 sal_Int32 nOldLen = aMediaDescr.getLength();
594 aMediaDescr.realloc( nOldLen + 1 );
595 auto pMediaDescr = aMediaDescr.getArray();
596 pMediaDescr[nOldLen].Name =
"FilterName";
597 pMediaDescr[ nOldLen ].Value <<= aFilterName;
600 else if ( !aTypeName.isEmpty() && !bIgnoreType )
602 uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY );
603 uno::Sequence< beans::PropertyValue >
aTypes;
605 if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
607 for (
const auto & prop : std::as_const(aTypes) )
609 if ( prop.Name ==
"PreferredFilter" && ( prop.Value >>= aFilterName ) )
611 sal_Int32 nOldLen = aMediaDescr.getLength();
612 aMediaDescr.realloc( nOldLen + 1 );
613 auto pMediaDescr = aMediaDescr.getArray();
614 pMediaDescr[nOldLen].Name =
"FilterName";
615 pMediaDescr[ nOldLen ].Value = prop.Value;
627 uno::Sequence< beans::PropertyValue >& aMediaDescr,
628 uno::Sequence< beans::NamedValue >& aObject )
631 for (
const auto & nv : std::as_const(aObject) )
632 if ( nv.Name ==
"ObjectDocumentServiceName" )
634 nv.Value >>= aDocName;
638 OSL_ENSURE( !aDocName.isEmpty(),
"The name must exist at this point!" );
641 bool bNeedsAddition =
true;
642 for ( sal_Int32 nMedInd = 0; nMedInd < aMediaDescr.getLength(); nMedInd++ )
643 if ( aMediaDescr[nMedInd].Name ==
"DocumentService" )
645 aMediaDescr.getArray()[nMedInd].Value <<= aDocName;
646 bNeedsAddition =
false;
650 if ( bNeedsAddition )
652 sal_Int32 nOldLen = aMediaDescr.getLength();
653 aMediaDescr.realloc( nOldLen + 1 );
654 auto pMediaDescr = aMediaDescr.getArray();
655 pMediaDescr[nOldLen].Name =
"DocumentService";
656 pMediaDescr[nOldLen].Value <<= aDocName;
664SfxFilterFlags MimeConfigurationHelper::GetFilterFlags(
const OUString& aFilterName )
669 if ( !aFilterName.isEmpty() )
671 uno::Reference< container::XNameAccess > xFilterFactory(
673 uno::UNO_SET_THROW );
675 uno::Any aFilterAny = xFilterFactory->getByName( aFilterName );
676 uno::Sequence< beans::PropertyValue >
aData;
677 if ( aFilterAny >>= aData )
680 nFlags =
static_cast<SfxFilterFlags>(aFilterHM.getUnpackedValueOrDefault(
"Flags", sal_Int32(0) ));
683 }
catch( uno::Exception& )
689bool MimeConfigurationHelper::AddFilterNameCheckOwnFile(
690 uno::Sequence< beans::PropertyValue >& aMediaDescr )
693 if ( !aFilterName.isEmpty() )
709 if ( !aServiceName.isEmpty() &&
nVersion )
712 uno::Reference< container::XContainerQuery > xFilterQuery(
714 uno::UNO_QUERY_THROW );
716 uno::Sequence< beans::NamedValue > aSearchRequest
718 {
"DocumentService", css::uno::Any(aServiceName) },
719 {
"FileFormatVersion", css::uno::Any(
nVersion) }
722 uno::Reference< container::XEnumeration > xFilterEnum =
723 xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
726 if ( xFilterEnum.is() )
727 while ( xFilterEnum->hasMoreElements() )
729 uno::Sequence< beans::PropertyValue > aProps;
730 if ( xFilterEnum->nextElement() >>= aProps )
734 for (
const auto & rPropVal : aProps)
736 if (rPropVal.Name ==
"Flags")
739 if (rPropVal.Value >>= nTmp)
742 else if (rPropVal.Name ==
"Name")
743 rPropVal.Value >>=
sName;
765 catch( uno::Exception& )
774 OUString aExportFilterName;
778 if ( !aImportFilterName.isEmpty() )
780 uno::Reference< container::XNameAccess > xFilterFactory(
782 uno::UNO_SET_THROW );
784 uno::Any aImpFilterAny = xFilterFactory->getByName( aImportFilterName );
785 uno::Sequence< beans::PropertyValue > aImpData;
786 if ( aImpFilterAny >>= aImpData )
793 OSL_FAIL(
"This is no import filter!" );
794 throw uno::Exception(
"this is no import filter",
nullptr);
799 aExportFilterName = aImportFilterName;
806 OSL_ENSURE( !aDocumentServiceName.isEmpty() && !aTypeName.isEmpty(),
"Incomplete filter data!" );
807 if ( !(aDocumentServiceName.isEmpty() || aTypeName.isEmpty()) )
809 uno::Sequence< beans::NamedValue > aSearchRequest
811 {
"Type", css::uno::Any(aTypeName) },
812 {
"DocumentService", css::uno::Any(aDocumentServiceName) }
815 uno::Sequence< beans::PropertyValue > aExportFilterProps =
SearchForFilter(
816 uno::Reference< container::XContainerQuery >( xFilterFactory, uno::UNO_QUERY_THROW ),
821 if ( aExportFilterProps.hasElements() )
831 catch( uno::Exception& )
834 return aExportFilterName;
840 const uno::Reference< container::XContainerQuery >& xFilterQuery,
841 const uno::Sequence< beans::NamedValue >& aSearchRequest,
845 uno::Sequence< beans::PropertyValue > aFilterProps;
846 uno::Reference< container::XEnumeration > xFilterEnum =
847 xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
851 if ( xFilterEnum.is() )
853 while ( xFilterEnum->hasMoreElements() )
855 uno::Sequence< beans::PropertyValue > aProps;
856 if ( xFilterEnum->nextElement() >>= aProps )
861 if ( ( ( nFlags & nMustFlags ) == nMustFlags ) && !( nFlags & nDontFlags ) )
865 aFilterProps = aProps;
868 else if ( !aFilterProps.hasElements() )
869 aFilterProps = aProps;
881 return aClassID1 == aClassID2;
889 uno::Sequence< sal_Int8 > aResult{
static_cast<sal_Int8>(
n1 >> 24 ),
894 static_cast<sal_Int8>( ( n2 << 8 ) >> 8 ),
896 static_cast<sal_Int8>( ( n3 << 8 ) >> 8 ),
Reference< XComponentContext > m_xContext
css::uno::Reference< css::container::XNameAccess > m_xFilterFactory
OUString GetFactoryNameByStringClassID(const OUString &aStringClassID)
css::uno::Reference< css::container::XNameAccess > m_xMediaTypeConfig
css::uno::Sequence< css::beans::NamedValue > GetObjPropsFromConfigEntry(const css::uno::Sequence< sal_Int8 > &aClassID, const css::uno::Reference< css::container::XNameAccess > &xObjectProps)
css::uno::Reference< css::container::XNameAccess > GetVerbsConfiguration()
css::uno::Reference< css::container::XNameAccess > m_xObjectConfig
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByClassID(const css::uno::Sequence< sal_Int8 > &aClassID)
OUString GetExportFilterFromImportFilter(const OUString &aImportFilterName)
OUString GetDefaultFilterFromServiceName(const OUString &aServName, sal_Int32 nVersion)
css::uno::Reference< css::container::XNameAccess > GetConfigurationByPathImpl(const OUString &aPath)
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByDocumentName(std::u16string_view aDocumentName)
OUString GetDocServiceNameFromMediaType(const OUString &aMediaType)
static OUString GetStringClassIDRepresentation(const css::uno::Sequence< sal_Int8 > &aClassID)
static css::uno::Sequence< sal_Int8 > GetSequenceClassIDRepresentation(std::u16string_view aClassID)
static css::uno::Sequence< css::beans::PropertyValue > SearchForFilter(const css::uno::Reference< css::container::XContainerQuery > &xFilterQuery, const css::uno::Sequence< css::beans::NamedValue > &aSearchRequest, SfxFilterFlags nMustFlags, SfxFilterFlags nDontFlags)
OUString GetFactoryNameByClassID(const css::uno::Sequence< sal_Int8 > &aClassID)
OUString GetFactoryNameByMediaType(const OUString &aMediaType)
OUString UpdateMediaDescriptorWithFilterName(css::uno::Sequence< css::beans::PropertyValue > &aMediaDescr, bool bIgnoreType)
static css::uno::Sequence< sal_Int8 > GetSequenceClassID(sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15)
css::uno::Reference< css::container::XNameAccess > m_xVerbsConfig
css::uno::Reference< css::uno::XComponentContext > m_xContext
OUString GetFactoryNameByDocumentName(std::u16string_view aDocName)
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByMediaType(const OUString &aMediaType)
OUString GetExplicitlyRegisteredObjClassID(const OUString &aMediaType)
css::uno::Reference< css::container::XNameAccess > GetFilterFactory()
css::uno::Reference< css::container::XNameAccess > GetMediaTypeConfiguration()
css::uno::Reference< css::container::XNameAccess > GetObjConfiguration()
static bool ClassIDsEqual(const css::uno::Sequence< sal_Int8 > &aClassID1, const css::uno::Sequence< sal_Int8 > &aClassID2)
bool GetVerbByShortcut(const OUString &aVerbShortcut, css::embed::VerbDescriptor &aDescriptor)
css::uno::Reference< css::lang::XMultiServiceFactory > m_xConfigProvider
OUString GetDocServiceNameFromFilter(const OUString &aFilterName)
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByFilter(const OUString &aFilterName)
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByStringClassID(const OUString &aStringClassID)
TValueType getUnpackedValueOrDefault(const OUString &sKey, const TValueType &aDefault) const
check if the specified item exists and return its (unpacked!) value or it returns the specified defau...
#define SO3_DUMMY_CLASSID
Sequence< sal_Int8 > aSeq
static sal_uInt8 GetDigit_Impl(char aChar)
constexpr OUStringLiteral aData
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
Init list for property sequences that wrap the PropertyValues in Anys.
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
const char *const aClassID