1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
29 #include <comphelper/fileformat.h>
30 #include <comphelper/mimeconfighelper.hxx>
31 #include <comphelper/classids.hxx>
32 #include <comphelper/sequenceashashmap.hxx>
33 #include <comphelper/documentconstants.hxx>
34 #include <comphelper/propertysequence.hxx>
35 #include <rtl/ustrbuf.hxx>
39 using namespace ::com::sun::star
;
40 using namespace comphelper
;
43 MimeConfigurationHelper::MimeConfigurationHelper( uno::Reference
< uno::XComponentContext
> xContext
)
44 : m_xContext(std::move( xContext
))
46 if ( !m_xContext
.is() )
47 throw uno::RuntimeException();
51 OUString
MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Sequence
< sal_Int8
>& aClassID
)
53 OUStringBuffer aResult
;
55 if ( aClassID
.getLength() == 16 )
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 );
63 sal_Int32 nDigit2
= static_cast<sal_uInt8
>(aClassID
[nInd
]) % 16;
64 aResult
.append( OUString::number(nDigit1
, 16) + OUString::number( nDigit2
, 16 ) );
68 return aResult
.makeStringAndClear();
72 static sal_uInt8
GetDigit_Impl( char aChar
)
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;
85 uno::Sequence
< sal_Int8
> MimeConfigurationHelper::GetSequenceClassIDRepresentation( std::u16string_view aClassID
)
87 size_t nLength
= aClassID
.size();
90 OString aCharClassID
= OUStringToOString( aClassID
, RTL_TEXTENCODING_ASCII_US
);
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
)
98 sal_uInt8 nDigit1
= GetDigit_Impl( aCharClassID
[nStrPointer
++] );
99 sal_uInt8 nDigit2
= GetDigit_Impl( aCharClassID
[nStrPointer
++] );
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
>();
118 uno::Reference
< container::XNameAccess
> MimeConfigurationHelper::GetConfigurationByPathImpl( const OUString
& aPath
)
120 uno::Reference
< container::XNameAccess
> xConfig
;
124 if ( !m_xConfigProvider
.is() )
125 m_xConfigProvider
= configuration::theDefaultProvider::get( m_xContext
);
127 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
129 {"nodepath", uno::Any(aPath
)}
131 xConfig
.set( m_xConfigProvider
->createInstanceWithArguments(
132 "com.sun.star.configuration.ConfigurationAccess",
136 catch( uno::Exception
& )
143 uno::Reference
< container::XNameAccess
> MimeConfigurationHelper::GetObjConfiguration()
145 std::unique_lock
aGuard( m_aMutex
);
147 if ( !m_xObjectConfig
.is() )
148 m_xObjectConfig
= GetConfigurationByPathImpl(
149 "/org.openoffice.Office.Embedding/Objects" );
151 return m_xObjectConfig
;
155 uno::Reference
< container::XNameAccess
> MimeConfigurationHelper::GetVerbsConfiguration()
157 std::unique_lock
aGuard( m_aMutex
);
159 if ( !m_xVerbsConfig
.is() )
160 m_xVerbsConfig
= GetConfigurationByPathImpl(
161 "/org.openoffice.Office.Embedding/Verbs");
163 return m_xVerbsConfig
;
167 uno::Reference
< container::XNameAccess
> MimeConfigurationHelper::GetMediaTypeConfiguration()
169 std::unique_lock
aGuard( m_aMutex
);
171 if ( !m_xMediaTypeConfig
.is() )
172 m_xMediaTypeConfig
= GetConfigurationByPathImpl(
173 "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations");
175 return m_xMediaTypeConfig
;
179 uno::Reference
< container::XNameAccess
> MimeConfigurationHelper::GetFilterFactory()
181 std::unique_lock
aGuard( m_aMutex
);
183 if ( !m_xFilterFactory
.is() )
184 m_xFilterFactory
.set(
185 m_xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_xContext
),
188 return m_xFilterFactory
;
192 OUString
MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString
& aFilterName
)
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
;
218 OUString
MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString
& aMediaType
)
220 uno::Reference
< container::XContainerQuery
> xTypeCFG(
221 m_xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext
),
228 // make query for all types matching the properties
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() )
243 OUString aDocumentName
= GetDocServiceNameFromFilter( aFilterName
);
244 if ( !aDocumentName
.isEmpty() )
245 return aDocumentName
;
251 catch( uno::Exception
& )
259 bool MimeConfigurationHelper::GetVerbByShortcut( const OUString
& aVerbShortcut
,
260 embed::VerbDescriptor
& aDescriptor
)
262 bool bResult
= false;
264 uno::Reference
< container::XNameAccess
> xVerbsConfig
= GetVerbsConfiguration();
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
& )
293 uno::Sequence
< beans::NamedValue
> MimeConfigurationHelper::GetObjPropsFromConfigEntry(
294 const uno::Sequence
< sal_Int8
>& aClassID
,
295 const uno::Reference
< container::XNameAccess
>& xObjectProps
)
297 uno::Sequence
< beans::NamedValue
> aResult
;
299 if ( aClassID
.getLength() == 16 )
303 const uno::Sequence
< OUString
> aObjPropNames
= xObjectProps
->getElementNames();
305 aResult
.realloc( aObjPropNames
.getLength() + 1 );
306 auto pResult
= aResult
.getArray();
307 pResult
[0].Name
= "ClassID";
308 pResult
[0].Value
<<= aClassID
;
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 );
341 OUString
MimeConfigurationHelper::GetExplicitlyRegisteredObjClassID( const OUString
& aMediaType
)
343 OUString aStringClassID
;
345 uno::Reference
< container::XNameAccess
> xMediaTypeConfig
= GetMediaTypeConfiguration();
348 if ( xMediaTypeConfig
.is() )
349 xMediaTypeConfig
->getByName( aMediaType
) >>= aStringClassID
;
351 catch( uno::Exception
& )
355 return aStringClassID
;
360 uno::Sequence
< beans::NamedValue
> MimeConfigurationHelper::GetObjectPropsByStringClassID(
361 const OUString
& aStringClassID
)
363 uno::Sequence
< beans::NamedValue
> aObjProps
;
365 uno::Sequence
< sal_Int8
> aClassID
= GetSequenceClassIDRepresentation( aStringClassID
);
366 if ( ClassIDsEqual( aClassID
, GetSequenceClassID( SO3_DUMMY_CLASSID
) ) )
368 aObjProps
= { { "ObjectFactory",
369 uno::Any(OUString("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) },
370 { "ClassID", uno::Any(aClassID
) } };
374 if ( aClassID
.getLength() == 16 )
376 uno::Reference
< container::XNameAccess
> xObjConfig
= GetObjConfiguration();
377 uno::Reference
< container::XNameAccess
> xObjectProps
;
380 // TODO/LATER: allow to provide ClassID string in any format, only digits are counted
381 if ( xObjConfig
.is() && ( xObjConfig
->getByName( aStringClassID
.toAsciiUpperCase() ) >>= xObjectProps
) && xObjectProps
.is() )
382 aObjProps
= GetObjPropsFromConfigEntry( aClassID
, xObjectProps
);
384 catch( uno::Exception
& )
393 uno::Sequence
< beans::NamedValue
> MimeConfigurationHelper::GetObjectPropsByClassID(
394 const uno::Sequence
< sal_Int8
>& aClassID
)
396 uno::Sequence
< beans::NamedValue
> aObjProps
;
397 if ( ClassIDsEqual( aClassID
, GetSequenceClassID( SO3_DUMMY_CLASSID
) ) )
399 aObjProps
= { { "ObjectFactory",
400 uno::Any(OUString("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) },
401 { "ClassID", uno::Any(aClassID
) } };
404 OUString aStringClassID
= GetStringClassIDRepresentation( aClassID
);
405 if ( !aStringClassID
.isEmpty() )
407 uno::Reference
< container::XNameAccess
> xObjConfig
= GetObjConfiguration();
408 uno::Reference
< container::XNameAccess
> xObjectProps
;
411 if ( xObjConfig
.is() && ( xObjConfig
->getByName( aStringClassID
.toAsciiUpperCase() ) >>= xObjectProps
) && xObjectProps
.is() )
412 aObjProps
= GetObjPropsFromConfigEntry( aClassID
, xObjectProps
);
414 catch( uno::Exception
& )
423 uno::Sequence
< beans::NamedValue
> MimeConfigurationHelper::GetObjectPropsByMediaType( const OUString
& aMediaType
)
425 uno::Sequence
< beans::NamedValue
> aObject
=
426 GetObjectPropsByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType
) );
427 if ( aObject
.hasElements() )
430 OUString aDocumentName
= GetDocServiceNameFromMediaType( aMediaType
);
431 if ( !aDocumentName
.isEmpty() )
432 return GetObjectPropsByDocumentName( aDocumentName
);
434 return uno::Sequence
< beans::NamedValue
>();
438 uno::Sequence
< beans::NamedValue
> MimeConfigurationHelper::GetObjectPropsByFilter( const OUString
& aFilterName
)
440 OUString aDocumentName
= GetDocServiceNameFromFilter( aFilterName
);
441 if ( !aDocumentName
.isEmpty() )
442 return GetObjectPropsByDocumentName( aDocumentName
);
444 return uno::Sequence
< beans::NamedValue
>();
448 uno::Sequence
< beans::NamedValue
> MimeConfigurationHelper::GetObjectPropsByDocumentName( std::u16string_view aDocName
)
450 if ( !aDocName
.empty() )
452 uno::Reference
< container::XNameAccess
> xObjConfig
= GetObjConfiguration();
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
)
467 return GetObjPropsFromConfigEntry( GetSequenceClassIDRepresentation( id
),
472 catch( uno::Exception
& )
477 return uno::Sequence
< beans::NamedValue
>();
481 OUString
MimeConfigurationHelper::GetFactoryNameByClassID( const uno::Sequence
< sal_Int8
>& aClassID
)
483 return GetFactoryNameByStringClassID( GetStringClassIDRepresentation( aClassID
) );
487 OUString
MimeConfigurationHelper::GetFactoryNameByStringClassID( const OUString
& aStringClassID
)
491 if ( !aStringClassID
.isEmpty() )
493 uno::Reference
< container::XNameAccess
> xObjConfig
= GetObjConfiguration();
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
& )
502 uno::Sequence
< sal_Int8
> aClassID
= GetSequenceClassIDRepresentation( aStringClassID
);
503 if ( ClassIDsEqual( aClassID
, GetSequenceClassID( SO3_DUMMY_CLASSID
) ) )
504 return "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory";
512 OUString
MimeConfigurationHelper::GetFactoryNameByDocumentName( std::u16string_view aDocName
)
516 if ( !aDocName
.empty() )
518 uno::Reference
< container::XNameAccess
> xObjConfig
= GetObjConfiguration();
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
& )
547 OUString
MimeConfigurationHelper::GetFactoryNameByMediaType( const OUString
& aMediaType
)
549 OUString aResult
= GetFactoryNameByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType
) );
551 if ( aResult
.isEmpty() )
553 OUString aDocumentName
= GetDocServiceNameFromMediaType( aMediaType
);
554 if ( !aDocumentName
.isEmpty() )
555 aResult
= GetFactoryNameByDocumentName( aDocumentName
);
562 OUString
MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName(
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() )
574 // filter name is not specified, so type detection should be done
576 uno::Reference
< document::XTypeDetection
> xTypeDetection(
577 m_xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext
),
578 uno::UNO_QUERY_THROW
);
580 // typedetection can change the mode, add a stream and so on, thus a copy should be used
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
;
626 OUString
MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName(
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
;
659 return UpdateMediaDescriptorWithFilterName( aMediaDescr
, true );
664 SfxFilterFlags
MimeConfigurationHelper::GetFilterFlags( const OUString
& aFilterName
)
666 SfxFilterFlags nFlags
= SfxFilterFlags::NONE
;
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
)
679 SequenceAsHashMap
aFilterHM( aData
);
680 nFlags
= static_cast<SfxFilterFlags
>(aFilterHM
.getUnpackedValueOrDefault( "Flags", sal_Int32(0) ));
683 } catch( uno::Exception
& )
689 bool MimeConfigurationHelper::AddFilterNameCheckOwnFile(
690 uno::Sequence
< beans::PropertyValue
>& aMediaDescr
)
692 OUString aFilterName
= UpdateMediaDescriptorWithFilterName( aMediaDescr
, false );
693 if ( !aFilterName
.isEmpty() )
695 SfxFilterFlags nFlags
= GetFilterFlags( aFilterName
);
696 // check the OWN flag
697 return bool(nFlags
& SfxFilterFlags::OWN
);
705 OUString
MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUString
& aServiceName
, sal_Int32 nVersion
)
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
);
725 // use the first filter that is found
726 if ( xFilterEnum
.is() )
727 while ( xFilterEnum
->hasMoreElements() )
729 uno::Sequence
< beans::PropertyValue
> aProps
;
730 if ( xFilterEnum
->nextElement() >>= aProps
)
732 SfxFilterFlags nFlags
= SfxFilterFlags::NONE
;
734 for (const auto & rPropVal
: aProps
)
736 if (rPropVal
.Name
== "Flags")
739 if (rPropVal
.Value
>>= nTmp
)
740 nFlags
= static_cast<SfxFilterFlags
>(nTmp
);
742 else if (rPropVal
.Name
== "Name")
743 rPropVal
.Value
>>= sName
;
746 // that should be import, export, own filter and not a template filter ( TemplatePath flag )
747 SfxFilterFlags
const nRequired
= SfxFilterFlags::OWN
748 // fdo#78159 for OOoXML, there is code to convert
749 // to ODF in OCommonEmbeddedObject::store*
750 // so accept it even though there's no export
751 | (SOFFICE_FILEFORMAT_60
== nVersion
? SfxFilterFlags::NONE
: SfxFilterFlags::EXPORT
)
752 | SfxFilterFlags::IMPORT
;
753 if ( ( ( nFlags
& nRequired
) == nRequired
) && !( nFlags
& SfxFilterFlags::TEMPLATEPATH
) )
755 // if there are more than one filter the preferred one should be used
756 // if there is no preferred filter the first one will be used
757 if ( aResult
.isEmpty() || ( nFlags
& SfxFilterFlags::PREFERED
) )
759 if ( nFlags
& SfxFilterFlags::PREFERED
)
760 break; // the preferred filter was found
765 catch( uno::Exception
& )
772 OUString
MimeConfigurationHelper::GetExportFilterFromImportFilter( const OUString
& aImportFilterName
)
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
)
788 SequenceAsHashMap
aImpFilterHM( aImpData
);
789 SfxFilterFlags nFlags
= static_cast<SfxFilterFlags
>(aImpFilterHM
.getUnpackedValueOrDefault( "Flags", sal_Int32(0) ));
791 if ( !( nFlags
& SfxFilterFlags::IMPORT
) )
793 OSL_FAIL( "This is no import filter!" );
794 throw uno::Exception("this is no import filter", nullptr);
797 if ( nFlags
& SfxFilterFlags::EXPORT
)
799 aExportFilterName
= aImportFilterName
;
803 OUString aDocumentServiceName
= aImpFilterHM
.getUnpackedValueOrDefault( "DocumentService", OUString() );
804 OUString aTypeName
= aImpFilterHM
.getUnpackedValueOrDefault( "Type", OUString() );
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
),
818 SfxFilterFlags::EXPORT
,
819 SfxFilterFlags::INTERNAL
);
821 if ( aExportFilterProps
.hasElements() )
823 SequenceAsHashMap
aExpPropsHM( aExportFilterProps
);
824 aExportFilterName
= aExpPropsHM
.getUnpackedValueOrDefault( "Name", OUString() );
831 catch( uno::Exception
& )
834 return aExportFilterName
;
839 uno::Sequence
< beans::PropertyValue
> MimeConfigurationHelper::SearchForFilter(
840 const uno::Reference
< container::XContainerQuery
>& xFilterQuery
,
841 const uno::Sequence
< beans::NamedValue
>& aSearchRequest
,
842 SfxFilterFlags nMustFlags
,
843 SfxFilterFlags nDontFlags
)
845 uno::Sequence
< beans::PropertyValue
> aFilterProps
;
846 uno::Reference
< container::XEnumeration
> xFilterEnum
=
847 xFilterQuery
->createSubSetEnumerationByProperties( aSearchRequest
);
849 // the first default filter will be taken,
850 // if there is no filter with flag default the first acceptable filter will be taken
851 if ( xFilterEnum
.is() )
853 while ( xFilterEnum
->hasMoreElements() )
855 uno::Sequence
< beans::PropertyValue
> aProps
;
856 if ( xFilterEnum
->nextElement() >>= aProps
)
858 SequenceAsHashMap
aPropsHM( aProps
);
859 SfxFilterFlags nFlags
= static_cast<SfxFilterFlags
>(aPropsHM
.getUnpackedValueOrDefault("Flags",
861 if ( ( ( nFlags
& nMustFlags
) == nMustFlags
) && !( nFlags
& nDontFlags
) )
863 if ( ( nFlags
& SfxFilterFlags::DEFAULT
) == SfxFilterFlags::DEFAULT
)
865 aFilterProps
= aProps
;
868 else if ( !aFilterProps
.hasElements() )
869 aFilterProps
= aProps
;
879 bool MimeConfigurationHelper::ClassIDsEqual( const uno::Sequence
< sal_Int8
>& aClassID1
, const uno::Sequence
< sal_Int8
>& aClassID2
)
881 return aClassID1
== aClassID2
;
885 uno::Sequence
< sal_Int8
> MimeConfigurationHelper::GetSequenceClassID( sal_uInt32 n1
, sal_uInt16 n2
, sal_uInt16 n3
,
886 sal_uInt8 b8
, sal_uInt8 b9
, sal_uInt8 b10
, sal_uInt8 b11
,
887 sal_uInt8 b12
, sal_uInt8 b13
, sal_uInt8 b14
, sal_uInt8 b15
)
889 uno::Sequence
< sal_Int8
> aResult
{ /* [ 0] */ static_cast<sal_Int8
>( n1
>> 24 ),
890 /* [ 1] */ static_cast<sal_Int8
>( ( n1
<< 8 ) >> 24 ),
891 /* [ 2] */ static_cast<sal_Int8
>( ( n1
<< 16 ) >> 24 ),
892 /* [ 3] */ static_cast<sal_Int8
>( ( n1
<< 24 ) >> 24 ),
893 /* [ 4] */ static_cast<sal_Int8
>( n2
>> 8 ),
894 /* [ 5] */ static_cast<sal_Int8
>( ( n2
<< 8 ) >> 8 ),
895 /* [ 6] */ static_cast<sal_Int8
>( n3
>> 8 ),
896 /* [ 7] */ static_cast<sal_Int8
>( ( n3
<< 8 ) >> 8 ),
897 /* [ 8] */ static_cast<sal_Int8
>( b8
),
898 /* [ 9] */ static_cast<sal_Int8
>( b9
),
899 /* [10] */ static_cast<sal_Int8
>( b10
),
900 /* [11] */ static_cast<sal_Int8
>( b11
),
901 /* [12] */ static_cast<sal_Int8
>( b12
),
902 /* [13] */ static_cast<sal_Int8
>( b13
),
903 /* [14] */ static_cast<sal_Int8
>( b14
),
904 /* [15] */ static_cast<sal_Int8
>( b15
) };
909 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */