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