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