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