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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 202 sal_Int32 MimeConfigurationHelper::GetFilterFlags( const ::rtl::OUString& aFilterName ) 203 { 204 sal_Int32 nFlags = 0; 205 try 206 { 207 if ( aFilterName.getLength() ) 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 //------------------------------------------------------------------------- 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 //------------------------------------------------------------------------- 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.getLength() ) 281 { 282 ::rtl::OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName ); 283 if ( aDocumentName.getLength() ) 284 return aDocumentName; 285 } 286 } 287 } 288 } 289 } 290 catch( uno::Exception& ) 291 {} 292 } 293 294 return ::rtl::OUString(); 295 } 296 297 //------------------------------------------------------------------------- 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 //------------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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 //----------------------------------------------------------------------- 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.getLength() ) 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 //----------------------------------------------------------------------- 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.getLength() ) 472 return GetObjectPropsByDocumentName( aDocumentName ); 473 474 return uno::Sequence< beans::NamedValue >(); 475 } 476 477 //----------------------------------------------------------------------- 478 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByFilter( const ::rtl::OUString& aFilterName ) 479 { 480 ::rtl::OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName ); 481 if ( aDocumentName.getLength() ) 482 return GetObjectPropsByDocumentName( aDocumentName ); 483 484 return uno::Sequence< beans::NamedValue >(); 485 } 486 487 //----------------------------------------------------------------------- 488 uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( const ::rtl::OUString& aDocName ) 489 { 490 if ( aDocName.getLength() ) 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 //----------------------------------------------------------------------- 522 ::rtl::OUString MimeConfigurationHelper::GetFactoryNameByClassID( const uno::Sequence< sal_Int8 >& aClassID ) 523 { 524 return GetFactoryNameByStringClassID( GetStringClassIDRepresentation( aClassID ) ); 525 } 526 527 //----------------------------------------------------------------------- 528 ::rtl::OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const ::rtl::OUString& aStringClassID ) 529 { 530 ::rtl::OUString aResult; 531 532 if ( aStringClassID.getLength() ) 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 //----------------------------------------------------------------------- 553 ::rtl::OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( const ::rtl::OUString& aDocName ) 554 { 555 ::rtl::OUString aResult; 556 557 if ( aDocName.getLength() ) 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 //----------------------------------------------------------------------- 590 ::rtl::OUString MimeConfigurationHelper::GetFactoryNameByMediaType( const ::rtl::OUString& aMediaType ) 591 { 592 ::rtl::OUString aResult = GetFactoryNameByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) ); 593 594 if ( !aResult.getLength() ) 595 { 596 ::rtl::OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType ); 597 if ( aDocumentName.getLength() ) 598 aResult = GetFactoryNameByDocumentName( aDocumentName ); 599 } 600 601 return aResult; 602 } 603 604 //----------------------------------------------------------------------- 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.getLength() ) 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.getLength() ) 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.getLength() && !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 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.getLength(), "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 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.getLength() ) 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 //----------------------------------------------------------- 722 ::rtl::OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const ::rtl::OUString& aServiceName, sal_Int32 nVersion ) 723 { 724 rtl::OUString aResult; 725 726 if ( aServiceName.getLength() && 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.getLength() || ( 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 //------------------------------------------------------------------------- 776 ::rtl::OUString MimeConfigurationHelper::GetExportFilterFromImportFilter( const ::rtl::OUString& aImportFilterName ) 777 { 778 ::rtl::OUString aExportFilterName; 779 780 try 781 { 782 if ( aImportFilterName.getLength() ) 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.getLength() && aTypeName.getLength(), "Incomplete filter data!" ); 812 if ( aDocumentServiceName.getLength() && aTypeName.getLength() ) 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 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 //------------------------------------------------------------------------- 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 //------------------------------------------------------------------------- 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 //------------------------------------------------------------------------- 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