LibreOffice Module comphelper (master)  1
mimeconfighelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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>
26 
27 #include <osl/diagnose.h>
28 
29 #include <comphelper/fileformat.h>
31 #include <comphelper/classids.hxx>
35 #include <rtl/ustrbuf.hxx>
36 
37 
38 using namespace ::com::sun::star;
39 using namespace comphelper;
40 
41 
42 MimeConfigurationHelper::MimeConfigurationHelper( const uno::Reference< uno::XComponentContext >& rxContext )
43 : m_xContext( rxContext )
44 {
45  if ( !m_xContext.is() )
46  throw uno::RuntimeException();
47 }
48 
49 
50 OUString MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Sequence< sal_Int8 >& aClassID )
51 {
52  OUStringBuffer aResult;
53 
54  if ( aClassID.getLength() == 16 )
55  {
56  for ( sal_Int32 nInd = 0; nInd < aClassID.getLength(); nInd++ )
57  {
58  if ( nInd == 4 || nInd == 6 || nInd == 8 || nInd == 10 )
59  aResult.append("-");
60 
61  sal_Int32 nDigit1 = static_cast<sal_Int32>( static_cast<sal_uInt8>(aClassID[nInd]) / 16 );
62  sal_Int32 nDigit2 = static_cast<sal_uInt8>(aClassID[nInd]) % 16;
63  aResult.append( OUString::number(nDigit1, 16) + OUString::number( nDigit2, 16 ) );
64  }
65  }
66 
67  return aResult.makeStringAndClear();
68 }
69 
70 
71 static sal_uInt8 GetDigit_Impl( char aChar )
72 {
73  if ( aChar >= '0' && aChar <= '9' )
74  return aChar - '0';
75  else if ( aChar >= 'a' && aChar <= 'f' )
76  return aChar - 'a' + 10;
77  else if ( aChar >= 'A' && aChar <= 'F' )
78  return aChar - 'A' + 10;
79  else
80  return 16;
81 }
82 
83 
84 uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( std::u16string_view aClassID )
85 {
86  size_t nLength = aClassID.size();
87  if ( nLength == 36 )
88  {
89  OString aCharClassID = OUStringToOString( aClassID, RTL_TEXTENCODING_ASCII_US );
90  uno::Sequence< sal_Int8 > aResult( 16 );
91  auto pResult = aResult.getArray();
92 
93  size_t nStrPointer = 0;
94  sal_Int32 nSeqInd = 0;
95  while( nSeqInd < 16 && nStrPointer + 1U < nLength )
96  {
97  sal_uInt8 nDigit1 = GetDigit_Impl( aCharClassID[nStrPointer++] );
98  sal_uInt8 nDigit2 = GetDigit_Impl( aCharClassID[nStrPointer++] );
99 
100  if ( nDigit1 > 15 || nDigit2 > 15 )
101  break;
102 
103  pResult[nSeqInd++] = static_cast<sal_Int8>( nDigit1 * 16 + nDigit2 );
104 
105  if ( nStrPointer < nLength && aCharClassID[nStrPointer] == '-' )
106  nStrPointer++;
107  }
108 
109  if ( nSeqInd == 16 && nStrPointer == nLength )
110  return aResult;
111  }
112 
113  return uno::Sequence< sal_Int8 >();
114 }
115 
116 
117 uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPathImpl( const OUString& aPath )
118 {
119  uno::Reference< container::XNameAccess > xConfig;
120 
121  try
122  {
123  if ( !m_xConfigProvider.is() )
124  m_xConfigProvider = configuration::theDefaultProvider::get( m_xContext );
125 
126  uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
127  {
128  {"nodepath", uno::Any(aPath)}
129  }));
130  xConfig.set( m_xConfigProvider->createInstanceWithArguments(
131  "com.sun.star.configuration.ConfigurationAccess",
132  aArgs ),
133  uno::UNO_QUERY );
134  }
135  catch( uno::Exception& )
136  {}
137 
138  return xConfig;
139 }
140 
141 
142 uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfiguration()
143 {
144  std::unique_lock aGuard( m_aMutex );
145 
146  if ( !m_xObjectConfig.is() )
148  "/org.openoffice.Office.Embedding/Objects" );
149 
150  return m_xObjectConfig;
151 }
152 
153 
154 uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfiguration()
155 {
156  std::unique_lock aGuard( m_aMutex );
157 
158  if ( !m_xVerbsConfig.is() )
160  "/org.openoffice.Office.Embedding/Verbs");
161 
162  return m_xVerbsConfig;
163 }
164 
165 
166 uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeConfiguration()
167 {
168  std::unique_lock aGuard( m_aMutex );
169 
170  if ( !m_xMediaTypeConfig.is() )
172  "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations");
173 
174  return m_xMediaTypeConfig;
175 }
176 
177 
178 uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetFilterFactory()
179 {
180  std::unique_lock aGuard( m_aMutex );
181 
182  if ( !m_xFilterFactory.is() )
183  m_xFilterFactory.set(
184  m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_xContext),
185  uno::UNO_QUERY );
186 
187  return m_xFilterFactory;
188 }
189 
190 
191 OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString& aFilterName )
192 {
193  OUString aDocServiceName;
194 
195  try
196  {
197  uno::Reference< container::XNameAccess > xFilterFactory(
199  uno::UNO_SET_THROW );
200 
201  uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName );
202  uno::Sequence< beans::PropertyValue > aFilterData;
203  if ( aFilterAnyData >>= aFilterData )
204  {
205  for ( const auto & prop : std::as_const(aFilterData) )
206  if ( prop.Name == "DocumentService" )
207  prop.Value >>= aDocServiceName;
208  }
209  }
210  catch( uno::Exception& )
211  {}
212 
213  return aDocServiceName;
214 }
215 
216 
217 OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString& aMediaType )
218 {
219  uno::Reference< container::XContainerQuery > xTypeCFG(
220  m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext),
221  uno::UNO_QUERY );
222 
223  if ( xTypeCFG.is() )
224  {
225  try
226  {
227  // make query for all types matching the properties
228  uno::Sequence < beans::NamedValue > aSeq { { "MediaType", css::uno::Any(aMediaType) } };
229 
230  uno::Reference < container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
231  while ( xEnum->hasMoreElements() )
232  {
233  uno::Sequence< beans::PropertyValue > aType;
234  if ( xEnum->nextElement() >>= aType )
235  {
236  for ( const auto & prop : std::as_const(aType) )
237  {
238  OUString aFilterName;
239  if ( prop.Name == "PreferredFilter"
240  && ( prop.Value >>= aFilterName ) && !aFilterName.isEmpty() )
241  {
242  OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName );
243  if ( !aDocumentName.isEmpty() )
244  return aDocumentName;
245  }
246  }
247  }
248  }
249  }
250  catch( uno::Exception& )
251  {}
252  }
253 
254  return OUString();
255 }
256 
257 
258 bool MimeConfigurationHelper::GetVerbByShortcut( const OUString& aVerbShortcut,
259  embed::VerbDescriptor& aDescriptor )
260 {
261  bool bResult = false;
262 
263  uno::Reference< container::XNameAccess > xVerbsConfig = GetVerbsConfiguration();
264  uno::Reference< container::XNameAccess > xVerbsProps;
265  try
266  {
267  if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() )
268  {
269  embed::VerbDescriptor aTempDescr;
270  static constexpr OUStringLiteral sVerbID = u"VerbID";
271  static constexpr OUStringLiteral sVerbUIName = u"VerbUIName";
272  static constexpr OUStringLiteral sVerbFlags = u"VerbFlags";
273  static constexpr OUStringLiteral sVerbAttributes = u"VerbAttributes";
274  if ( ( xVerbsProps->getByName(sVerbID) >>= aTempDescr.VerbID )
275  && ( xVerbsProps->getByName(sVerbUIName) >>= aTempDescr.VerbName )
276  && ( xVerbsProps->getByName(sVerbFlags) >>= aTempDescr.VerbFlags )
277  && ( xVerbsProps->getByName(sVerbAttributes) >>= aTempDescr.VerbAttributes ) )
278  {
279  aDescriptor = aTempDescr;
280  bResult = true;
281  }
282  }
283  }
284  catch( uno::Exception& )
285  {
286  }
287 
288  return bResult;
289 }
290 
291 
292 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfigEntry(
293  const uno::Sequence< sal_Int8 >& aClassID,
294  const uno::Reference< container::XNameAccess >& xObjectProps )
295 {
296  uno::Sequence< beans::NamedValue > aResult;
297 
298  if ( aClassID.getLength() == 16 )
299  {
300  try
301  {
302  const uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames();
303 
304  aResult.realloc( aObjPropNames.getLength() + 1 );
305  auto pResult = aResult.getArray();
306  pResult[0].Name = "ClassID";
307  pResult[0].Value <<= aClassID;
308 
309  for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ )
310  {
311  pResult[nInd + 1].Name = aObjPropNames[nInd];
312 
313  if ( aObjPropNames[nInd] == "ObjectVerbs" )
314  {
315  uno::Sequence< OUString > aVerbShortcuts;
316  if ( !(xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts) )
317  throw uno::RuntimeException();
318  uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() );
319  auto aVerbDescriptorsRange = asNonConstRange(aVerbDescriptors);
320  for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ )
321  if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptorsRange[nVerbI] ) )
322  throw uno::RuntimeException();
323 
324  pResult[nInd+1].Value <<= aVerbDescriptors;
325  }
326  else
327  pResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] );
328  }
329  }
330  catch( uno::Exception& )
331  {
332  aResult.realloc( 0 );
333  }
334  }
335 
336  return aResult;
337 }
338 
339 
341 {
342  OUString aStringClassID;
343 
344  uno::Reference< container::XNameAccess > xMediaTypeConfig = GetMediaTypeConfiguration();
345  try
346  {
347  if ( xMediaTypeConfig.is() )
348  xMediaTypeConfig->getByName( aMediaType ) >>= aStringClassID;
349  }
350  catch( uno::Exception& )
351  {
352  }
353 
354  return aStringClassID;
355 
356 }
357 
358 
360  const OUString& aStringClassID )
361 {
362  uno::Sequence< beans::NamedValue > aObjProps;
363 
364  uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID );
365  if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
366  {
367  aObjProps = { { "ObjectFactory",
368  uno::Any(OUString("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) },
369  { "ClassID", uno::Any(aClassID) } };
370  return aObjProps;
371  }
372 
373  if ( aClassID.getLength() == 16 )
374  {
375  uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
376  uno::Reference< container::XNameAccess > xObjectProps;
377  try
378  {
379  // TODO/LATER: allow to provide ClassID string in any format, only digits are counted
380  if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
381  aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps );
382  }
383  catch( uno::Exception& )
384  {
385  }
386  }
387 
388  return aObjProps;
389 }
390 
391 
392 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByClassID(
393  const uno::Sequence< sal_Int8 >& aClassID )
394 {
395  uno::Sequence< beans::NamedValue > aObjProps;
396  if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
397  {
398  aObjProps = { { "ObjectFactory",
399  uno::Any(OUString("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) },
400  { "ClassID", uno::Any(aClassID) } };
401  }
402 
403  OUString aStringClassID = GetStringClassIDRepresentation( aClassID );
404  if ( !aStringClassID.isEmpty() )
405  {
406  uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
407  uno::Reference< container::XNameAccess > xObjectProps;
408  try
409  {
410  if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
411  aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps );
412  }
413  catch( uno::Exception& )
414  {
415  }
416  }
417 
418  return aObjProps;
419 }
420 
421 
422 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByMediaType( const OUString& aMediaType )
423 {
424  uno::Sequence< beans::NamedValue > aObject =
426  if ( aObject.hasElements() )
427  return aObject;
428 
429  OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType );
430  if ( !aDocumentName.isEmpty() )
431  return GetObjectPropsByDocumentName( aDocumentName );
432 
433  return uno::Sequence< beans::NamedValue >();
434 }
435 
436 
437 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByFilter( const OUString& aFilterName )
438 {
439  OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName );
440  if ( !aDocumentName.isEmpty() )
441  return GetObjectPropsByDocumentName( aDocumentName );
442 
443  return uno::Sequence< beans::NamedValue >();
444 }
445 
446 
447 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( std::u16string_view aDocName )
448 {
449  if ( !aDocName.empty() )
450  {
451  uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
452  if ( xObjConfig.is() )
453  {
454  try
455  {
456  const uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
457  for ( const OUString & id : aClassIDs )
458  {
459  uno::Reference< container::XNameAccess > xObjectProps;
460  OUString aEntryDocName;
461 
462  if ( ( xObjConfig->getByName( id ) >>= xObjectProps ) && xObjectProps.is()
463  && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
464  && aEntryDocName == aDocName )
465  {
467  xObjectProps );
468  }
469  }
470  }
471  catch( uno::Exception& )
472  {}
473  }
474  }
475 
476  return uno::Sequence< beans::NamedValue >();
477 }
478 
479 
480 OUString MimeConfigurationHelper::GetFactoryNameByClassID( const uno::Sequence< sal_Int8 >& aClassID )
481 {
483 }
484 
485 
486 OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const OUString& aStringClassID )
487 {
488  OUString aResult;
489 
490  if ( !aStringClassID.isEmpty() )
491  {
492  uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
493  uno::Reference< container::XNameAccess > xObjectProps;
494  try
495  {
496  if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
497  xObjectProps->getByName("ObjectFactory") >>= aResult;
498  }
499  catch( uno::Exception& )
500  {
501  uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID );
502  if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
503  return "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory";
504  }
505  }
506 
507  return aResult;
508 }
509 
510 
511 OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( std::u16string_view aDocName )
512 {
513  OUString aResult;
514 
515  if ( !aDocName.empty() )
516  {
517  uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
518  if ( xObjConfig.is() )
519  {
520  try
521  {
522  const uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
523  for ( const OUString & id : aClassIDs )
524  {
525  uno::Reference< container::XNameAccess > xObjectProps;
526  OUString aEntryDocName;
527 
528  if ( ( xObjConfig->getByName( id ) >>= xObjectProps ) && xObjectProps.is()
529  && ( xObjectProps->getByName( "ObjectDocumentServiceName" ) >>= aEntryDocName )
530  && aEntryDocName == aDocName )
531  {
532  xObjectProps->getByName("ObjectFactory") >>= aResult;
533  break;
534  }
535  }
536  }
537  catch( uno::Exception& )
538  {}
539  }
540  }
541 
542  return aResult;
543 }
544 
545 
546 OUString MimeConfigurationHelper::GetFactoryNameByMediaType( const OUString& aMediaType )
547 {
548  OUString aResult = GetFactoryNameByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) );
549 
550  if ( aResult.isEmpty() )
551  {
552  OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType );
553  if ( !aDocumentName.isEmpty() )
554  aResult = GetFactoryNameByDocumentName( aDocumentName );
555  }
556 
557  return aResult;
558 }
559 
560 
562  uno::Sequence< beans::PropertyValue >& aMediaDescr,
563  bool bIgnoreType )
564 {
565  OUString aFilterName;
566 
567  for ( const auto & prop : std::as_const(aMediaDescr) )
568  if ( prop.Name == "FilterName" )
569  prop.Value >>= aFilterName;
570 
571  if ( aFilterName.isEmpty() )
572  {
573  // filter name is not specified, so type detection should be done
574 
575  uno::Reference< document::XTypeDetection > xTypeDetection(
576  m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext),
577  uno::UNO_QUERY_THROW );
578 
579  // typedetection can change the mode, add a stream and so on, thus a copy should be used
580  uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr );
581 
582  // get TypeName
583  OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD, true );
584 
585  // get FilterName
586  for ( const auto & prop : std::as_const(aTempMD) )
587  if ( prop.Name == "FilterName" )
588  prop.Value >>= aFilterName;
589 
590  if ( !aFilterName.isEmpty() )
591  {
592  sal_Int32 nOldLen = aMediaDescr.getLength();
593  aMediaDescr.realloc( nOldLen + 1 );
594  auto pMediaDescr = aMediaDescr.getArray();
595  pMediaDescr[nOldLen].Name = "FilterName";
596  pMediaDescr[ nOldLen ].Value <<= aFilterName;
597 
598  }
599  else if ( !aTypeName.isEmpty() && !bIgnoreType )
600  {
601  uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY );
602  uno::Sequence< beans::PropertyValue > aTypes;
603 
604  if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
605  {
606  for ( const auto & prop : std::as_const(aTypes) )
607  {
608  if ( prop.Name == "PreferredFilter" && ( prop.Value >>= aFilterName ) )
609  {
610  sal_Int32 nOldLen = aMediaDescr.getLength();
611  aMediaDescr.realloc( nOldLen + 1 );
612  auto pMediaDescr = aMediaDescr.getArray();
613  pMediaDescr[nOldLen].Name = "FilterName";
614  pMediaDescr[ nOldLen ].Value = prop.Value;
615  break;
616  }
617  }
618  }
619  }
620  }
621 
622  return aFilterName;
623 }
624 
626  uno::Sequence< beans::PropertyValue >& aMediaDescr,
627  uno::Sequence< beans::NamedValue >& aObject )
628 {
629  OUString aDocName;
630  for ( const auto & nv : std::as_const(aObject) )
631  if ( nv.Name == "ObjectDocumentServiceName" )
632  {
633  nv.Value >>= aDocName;
634  break;
635  }
636 
637  OSL_ENSURE( !aDocName.isEmpty(), "The name must exist at this point!" );
638 
639 
640  bool bNeedsAddition = true;
641  for ( sal_Int32 nMedInd = 0; nMedInd < aMediaDescr.getLength(); nMedInd++ )
642  if ( aMediaDescr[nMedInd].Name == "DocumentService" )
643  {
644  aMediaDescr.getArray()[nMedInd].Value <<= aDocName;
645  bNeedsAddition = false;
646  break;
647  }
648 
649  if ( bNeedsAddition )
650  {
651  sal_Int32 nOldLen = aMediaDescr.getLength();
652  aMediaDescr.realloc( nOldLen + 1 );
653  auto pMediaDescr = aMediaDescr.getArray();
654  pMediaDescr[nOldLen].Name = "DocumentService";
655  pMediaDescr[nOldLen].Value <<= aDocName;
656  }
657 
658  return UpdateMediaDescriptorWithFilterName( aMediaDescr, true );
659 }
660 
661 #ifdef _WIN32
662 
663 SfxFilterFlags MimeConfigurationHelper::GetFilterFlags( const OUString& aFilterName )
664 {
666  try
667  {
668  if ( !aFilterName.isEmpty() )
669  {
670  uno::Reference< container::XNameAccess > xFilterFactory(
672  uno::UNO_SET_THROW );
673 
674  uno::Any aFilterAny = xFilterFactory->getByName( aFilterName );
675  uno::Sequence< beans::PropertyValue > aData;
676  if ( aFilterAny >>= aData )
677  {
678  SequenceAsHashMap aFilterHM( aData );
679  nFlags = static_cast<SfxFilterFlags>(aFilterHM.getUnpackedValueOrDefault( "Flags", sal_Int32(0) ));
680  }
681  }
682  } catch( uno::Exception& )
683  {}
684 
685  return nFlags;
686 }
687 
688 bool MimeConfigurationHelper::AddFilterNameCheckOwnFile(
689  uno::Sequence< beans::PropertyValue >& aMediaDescr )
690 {
691  OUString aFilterName = UpdateMediaDescriptorWithFilterName( aMediaDescr, false );
692  if ( !aFilterName.isEmpty() )
693  {
694  SfxFilterFlags nFlags = GetFilterFlags( aFilterName );
695  // check the OWN flag
696  return bool(nFlags & SfxFilterFlags::OWN);
697  }
698 
699  return false;
700 }
701 
702 #endif
703 
704 OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUString& aServiceName, sal_Int32 nVersion )
705 {
706  OUString aResult;
707 
708  if ( !aServiceName.isEmpty() && nVersion )
709  try
710  {
711  uno::Reference< container::XContainerQuery > xFilterQuery(
713  uno::UNO_QUERY_THROW );
714 
715  uno::Sequence< beans::NamedValue > aSearchRequest
716  {
717  { "DocumentService", css::uno::Any(aServiceName) },
718  { "FileFormatVersion", css::uno::Any(nVersion) }
719  };
720 
721  uno::Reference< container::XEnumeration > xFilterEnum =
722  xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
723 
724  // use the first filter that is found
725  if ( xFilterEnum.is() )
726  while ( xFilterEnum->hasMoreElements() )
727  {
728  uno::Sequence< beans::PropertyValue > aProps;
729  if ( xFilterEnum->nextElement() >>= aProps )
730  {
732  OUString sName;
733  for (const auto & rPropVal : aProps)
734  {
735  if (rPropVal.Name == "Flags")
736  {
737  sal_Int32 nTmp(0);
738  if (rPropVal.Value >>= nTmp)
739  nFlags = static_cast<SfxFilterFlags>(nTmp);
740  }
741  else if (rPropVal.Name == "Name")
742  rPropVal.Value >>= sName;
743  }
744 
745  // that should be import, export, own filter and not a template filter ( TemplatePath flag )
746  SfxFilterFlags const nRequired = SfxFilterFlags::OWN
747  // fdo#78159 for OOoXML, there is code to convert
748  // to ODF in OCommonEmbeddedObject::store*
749  // so accept it even though there's no export
752  if ( ( ( nFlags & nRequired ) == nRequired ) && !( nFlags & SfxFilterFlags::TEMPLATEPATH ) )
753  {
754  // if there are more than one filter the preferred one should be used
755  // if there is no preferred filter the first one will be used
756  if ( aResult.isEmpty() || ( nFlags & SfxFilterFlags::PREFERED ) )
757  aResult = sName;
758  if ( nFlags & SfxFilterFlags::PREFERED )
759  break; // the preferred filter was found
760  }
761  }
762  }
763  }
764  catch( uno::Exception& )
765  {}
766 
767  return aResult;
768 }
769 
770 
771 OUString MimeConfigurationHelper::GetExportFilterFromImportFilter( const OUString& aImportFilterName )
772 {
773  OUString aExportFilterName;
774 
775  try
776  {
777  if ( !aImportFilterName.isEmpty() )
778  {
779  uno::Reference< container::XNameAccess > xFilterFactory(
781  uno::UNO_SET_THROW );
782 
783  uno::Any aImpFilterAny = xFilterFactory->getByName( aImportFilterName );
784  uno::Sequence< beans::PropertyValue > aImpData;
785  if ( aImpFilterAny >>= aImpData )
786  {
787  SequenceAsHashMap aImpFilterHM( aImpData );
788  SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aImpFilterHM.getUnpackedValueOrDefault( "Flags", sal_Int32(0) ));
789 
790  if ( !( nFlags & SfxFilterFlags::IMPORT ) )
791  {
792  OSL_FAIL( "This is no import filter!" );
793  throw uno::Exception("this is no import filter", nullptr);
794  }
795 
796  if ( nFlags & SfxFilterFlags::EXPORT )
797  {
798  aExportFilterName = aImportFilterName;
799  }
800  else
801  {
802  OUString aDocumentServiceName = aImpFilterHM.getUnpackedValueOrDefault( "DocumentService", OUString() );
803  OUString aTypeName = aImpFilterHM.getUnpackedValueOrDefault( "Type", OUString() );
804 
805  OSL_ENSURE( !aDocumentServiceName.isEmpty() && !aTypeName.isEmpty(), "Incomplete filter data!" );
806  if ( !(aDocumentServiceName.isEmpty() || aTypeName.isEmpty()) )
807  {
808  uno::Sequence< beans::NamedValue > aSearchRequest
809  {
810  { "Type", css::uno::Any(aTypeName) },
811  { "DocumentService", css::uno::Any(aDocumentServiceName) }
812  };
813 
814  uno::Sequence< beans::PropertyValue > aExportFilterProps = SearchForFilter(
815  uno::Reference< container::XContainerQuery >( xFilterFactory, uno::UNO_QUERY_THROW ),
816  aSearchRequest,
817  SfxFilterFlags::EXPORT,
819 
820  if ( aExportFilterProps.hasElements() )
821  {
822  SequenceAsHashMap aExpPropsHM( aExportFilterProps );
823  aExportFilterName = aExpPropsHM.getUnpackedValueOrDefault( "Name", OUString() );
824  }
825  }
826  }
827  }
828  }
829  }
830  catch( uno::Exception& )
831  {}
832 
833  return aExportFilterName;
834 }
835 
836 
837 // static
838 uno::Sequence< beans::PropertyValue > MimeConfigurationHelper::SearchForFilter(
839  const uno::Reference< container::XContainerQuery >& xFilterQuery,
840  const uno::Sequence< beans::NamedValue >& aSearchRequest,
841  SfxFilterFlags nMustFlags,
842  SfxFilterFlags nDontFlags )
843 {
844  uno::Sequence< beans::PropertyValue > aFilterProps;
845  uno::Reference< container::XEnumeration > xFilterEnum =
846  xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
847 
848  // the first default filter will be taken,
849  // if there is no filter with flag default the first acceptable filter will be taken
850  if ( xFilterEnum.is() )
851  {
852  while ( xFilterEnum->hasMoreElements() )
853  {
854  uno::Sequence< beans::PropertyValue > aProps;
855  if ( xFilterEnum->nextElement() >>= aProps )
856  {
857  SequenceAsHashMap aPropsHM( aProps );
858  SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault("Flags",
859  sal_Int32(0) ));
860  if ( ( ( nFlags & nMustFlags ) == nMustFlags ) && !( nFlags & nDontFlags ) )
861  {
862  if ( ( nFlags & SfxFilterFlags::DEFAULT ) == SfxFilterFlags::DEFAULT )
863  {
864  aFilterProps = aProps;
865  break;
866  }
867  else if ( !aFilterProps.hasElements() )
868  aFilterProps = aProps;
869  }
870  }
871  }
872  }
873 
874  return aFilterProps;
875 }
876 
877 
878 bool MimeConfigurationHelper::ClassIDsEqual( const uno::Sequence< sal_Int8 >& aClassID1, const uno::Sequence< sal_Int8 >& aClassID2 )
879 {
880  return aClassID1 == aClassID2;
881 }
882 
883 
884 uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3,
885  sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11,
886  sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 )
887 {
888  uno::Sequence< sal_Int8 > aResult{ /* [ 0] */ static_cast<sal_Int8>( n1 >> 24 ),
889  /* [ 1] */ static_cast<sal_Int8>( ( n1 << 8 ) >> 24 ),
890  /* [ 2] */ static_cast<sal_Int8>( ( n1 << 16 ) >> 24 ),
891  /* [ 3] */ static_cast<sal_Int8>( ( n1 << 24 ) >> 24 ),
892  /* [ 4] */ static_cast<sal_Int8>( n2 >> 8 ),
893  /* [ 5] */ static_cast<sal_Int8>( ( n2 << 8 ) >> 8 ),
894  /* [ 6] */ static_cast<sal_Int8>( n3 >> 8 ),
895  /* [ 7] */ static_cast<sal_Int8>( ( n3 << 8 ) >> 8 ),
896  /* [ 8] */ static_cast<sal_Int8>( b8 ),
897  /* [ 9] */ static_cast<sal_Int8>( b9 ),
898  /* [10] */ static_cast<sal_Int8>( b10 ),
899  /* [11] */ static_cast<sal_Int8>( b11 ),
900  /* [12] */ static_cast<sal_Int8>( b12 ),
901  /* [13] */ static_cast<sal_Int8>( b13 ),
902  /* [14] */ static_cast<sal_Int8>( b14 ),
903  /* [15] */ static_cast<sal_Int8>( b15 ) };
904 
905  return aResult;
906 }
907 
908 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::container::XNameAccess > GetVerbsConfiguration()
const char *const aClassID
OUString GetDefaultFilterFromServiceName(const OUString &aServName, sal_Int32 nVersion)
css::uno::Reference< css::uno::XComponentContext > m_xContext
signed char sal_Int8
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByFilter(const OUString &aFilterName)
bool GetVerbByShortcut(const OUString &aVerbShortcut, css::embed::VerbDescriptor &aDescriptor)
OUString UpdateMediaDescriptorWithFilterName(css::uno::Sequence< css::beans::PropertyValue > &aMediaDescr, bool bIgnoreType)
OUString GetFactoryNameByDocumentName(std::u16string_view aDocName)
OUString GetExportFilterFromImportFilter(const OUString &aImportFilterName)
css::uno::Reference< css::container::XNameAccess > GetFilterFactory()
MimeConfigurationHelper(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
OUString GetFactoryNameByStringClassID(const OUString &aStringClassID)
OUString GetDocServiceNameFromMediaType(const OUString &aMediaType)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::container::XNameAccess > GetMediaTypeConfiguration()
const char * sName
constexpr OUStringLiteral aData
css::uno::Reference< css::container::XNameAccess > m_xVerbsConfig
#define SOFFICE_FILEFORMAT_60
Definition: fileformat.h:28
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...
OUString GetFactoryNameByMediaType(const OUString &aMediaType)
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.
static css::uno::Sequence< sal_Int8 > GetSequenceClassIDRepresentation(std::u16string_view aClassID)
#define SO3_DUMMY_CLASSID
Definition: classids.hxx:312
OUString GetFactoryNameByClassID(const css::uno::Sequence< sal_Int8 > &aClassID)
css::uno::Reference< css::container::XNameAccess > GetConfigurationByPathImpl(const OUString &aPath)
float u
OUString GetExplicitlyRegisteredObjClassID(const OUString &aMediaType)
Object Value
OUString GetDocServiceNameFromFilter(const OUString &aFilterName)
static sal_uInt8 GetDigit_Impl(char aChar)
static bool ClassIDsEqual(const css::uno::Sequence< sal_Int8 > &aClassID1, const css::uno::Sequence< sal_Int8 > &aClassID2)
sal_Int16 nVersion
static OUString GetStringClassIDRepresentation(const css::uno::Sequence< sal_Int8 > &aClassID)
const SvXMLTokenMapEntry aTypes[]
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)
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::Sequence< css::beans::NamedValue > GetObjectPropsByStringClassID(const OUString &aStringClassID)
unsigned char sal_uInt8
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByClassID(const css::uno::Sequence< sal_Int8 > &aClassID)
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByDocumentName(std::u16string_view aDocumentName)
css::uno::Reference< css::container::XNameAccess > GetObjConfiguration()
Sequence< sal_Int8 > aSeq
css::uno::Sequence< css::beans::NamedValue > GetObjectPropsByMediaType(const OUString &aMediaType)
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 > m_xFilterFactory
css::uno::Reference< css::container::XNameAccess > m_xObjectConfig
sal_Int32 nLength
css::uno::Reference< css::lang::XMultiServiceFactory > m_xConfigProvider
Reference< XComponentContext > m_xContext
css::uno::Reference< css::container::XNameAccess > m_xMediaTypeConfig
SfxFilterFlags