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_filter.hxx" 26 #include "typedetection.hxx" 27 #include "constant.hxx" 28 29 //_______________________________________________ 30 // includes 31 #include <com/sun/star/document/XExtendedFilterDetection.hpp> 32 #include <com/sun/star/util/XURLTransformer.hpp> 33 34 #ifndef _COM_SUN_STAR_IO_XINPUSTREAM_HPP_ 35 #include <com/sun/star/io/XInputStream.hpp> 36 #endif 37 #include <com/sun/star/io/XSeekable.hpp> 38 #include <com/sun/star/task/XInteractionHandler.hpp> 39 #include <tools/wldcrd.hxx> 40 #include <rtl/ustrbuf.hxx> 41 #include <framework/interaction.hxx> 42 #include <tools/urlobj.hxx> 43 #include <unotools/localfilehelper.hxx> 44 45 //_______________________________________________ 46 // namespace 47 48 namespace filter{ 49 namespace config{ 50 51 namespace css = ::com::sun::star; 52 53 //_______________________________________________ 54 // definitions 55 56 // Use this switch to change the behaviour of preselection DocumentService ... (see using for further informations) 57 #define IGNORE_NON_URLMATCHING_TYPES_FOR_PRESELECTION_DOCUMENTSERVICE 58 59 // enable/disable special handling for CSV/TXT problem 60 #define WORKAROUND_CSV_TXT_BUG_i60158 61 62 /*----------------------------------------------- 63 03.07.2003 11:25 64 -----------------------------------------------*/ 65 TypeDetection::TypeDetection(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 66 { 67 BaseContainer::init(xSMGR , 68 TypeDetection::impl_getImplementationName() , 69 TypeDetection::impl_getSupportedServiceNames(), 70 FilterCache::E_TYPE ); 71 } 72 73 /*----------------------------------------------- 74 03.07.2003 10:36 75 -----------------------------------------------*/ 76 TypeDetection::~TypeDetection() 77 { 78 } 79 80 /*----------------------------------------------- 81 03.11.2003 08:43 82 -----------------------------------------------*/ 83 ::rtl::OUString SAL_CALL TypeDetection::queryTypeByURL(const ::rtl::OUString& sURL) 84 throw (css::uno::RuntimeException) 85 { 86 ::rtl::OUString sType; 87 88 // SAFE -> 89 ::osl::ResettableMutexGuard aLock(m_aLock); 90 91 css::util::URL aURL; 92 aURL.Complete = sURL; 93 css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICE_URLTRANSFORMER), css::uno::UNO_QUERY); 94 xParser->parseStrict(aURL); 95 96 // set std types as minimum requirement first! 97 // Only in case no type was found for given URL, 98 // use optional types too ... 99 FlatDetection lFlatTypes; 100 m_rCache->detectFlatForURL(aURL, lFlatTypes); 101 102 if ( 103 (lFlatTypes.size() < 1 ) && 104 (!m_rCache->isFillState(FilterCache::E_CONTAINS_TYPES)) 105 ) 106 { 107 m_rCache->load(FilterCache::E_CONTAINS_TYPES); 108 m_rCache->detectFlatForURL(aURL, lFlatTypes); 109 } 110 111 // first item is guaranteed as "preferred" one! 112 if (lFlatTypes.size() > 0) 113 { 114 const FlatDetectionInfo& aMatch = *(lFlatTypes.begin()); 115 sType = aMatch.sType; 116 } 117 118 return sType; 119 // <- SAFE 120 } 121 122 /*----------------------------------------------- 123 31.10.2003 09:36 124 -----------------------------------------------*/ 125 ::rtl::OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor, 126 sal_Bool bAllowDeep ) 127 throw (css::uno::RuntimeException) 128 { 129 // make the descriptor more useable :-) 130 ::comphelper::MediaDescriptor stlDescriptor(lDescriptor); 131 132 // SAFE -> ---------------------------------- 133 ::osl::ResettableMutexGuard aLock(m_aLock); 134 135 //******************************************* 136 // parse given URL to split it into e.g. main and jump marks ... 137 ::rtl::OUString sURL = stlDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString()); 138 139 #if OSL_DEBUG_LEVEL > 0 140 if (stlDescriptor.find(::rtl::OUString::createFromAscii("FileName")) != stlDescriptor.end()) 141 OSL_ENSURE(sal_False, "Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!"); 142 #endif 143 144 css::util::URL aURL; 145 aURL.Complete = sURL; 146 css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICE_URLTRANSFORMER), css::uno::UNO_QUERY); 147 xParser->parseStrict(aURL); 148 149 //******************************************* 150 // preselected filter, type or document service? 151 // use it as first "flat" detected type later! 152 FlatDetection lFlatTypes; 153 impl_getPreselection(aURL, stlDescriptor, lFlatTypes); 154 155 //******************************************* 156 // get all types, which match to the given descriptor 157 // That can be true by: extensions/url pattern/mime type etcpp. 158 m_rCache->detectFlatForURL(aURL, lFlatTypes); 159 160 aLock.clear(); 161 // <- SAFE ---------------------------------- 162 163 ::rtl::OUString sType ; 164 ::rtl::OUString sLastChance; 165 166 try 167 { 168 //******************************************* 169 // verify every flat detected (or preselected!) type 170 // by calling its registered deep detection service. 171 // But break this loop if a type match to the given descriptor 172 // by an URL pattern(!) or if deep detection isn't allowed from 173 // outside (bAllowDeep=sal_False) or break the whole detection by 174 // throwing an exception if creation of the might needed input 175 // stream failed by e.g. an IO exception ... 176 OUStringList lUsedDetectors; 177 if (lFlatTypes.size()>0) 178 sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, lUsedDetectors, sLastChance); 179 180 //******************************************* 181 // if no flat detected (nor preselected!) type could be 182 // verified and no error occurred during creation of 183 // the might needed input stream, start detection 184 // which uses all registered deep detection services. 185 if ( 186 (!sType.getLength()) && 187 (bAllowDeep ) 188 ) 189 { 190 sType = impl_detectTypeDeepOnly(stlDescriptor, lUsedDetectors); 191 } 192 193 //******************************************* 194 // flat detection failed 195 // pure deep detection failed 196 // => ask might existing InteractionHandler 197 // means: ask user for it's decision 198 if (!sType.getLength()) 199 sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor); 200 201 //******************************************* 202 // no real detected type - but a might valid one. 203 // update descriptor and set last chance for return. 204 if (!sType.getLength() && sLastChance.getLength()) 205 { 206 OSL_ENSURE(sal_False, "set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!"); 207 sType = sLastChance; 208 } 209 } 210 catch(const css::uno::RuntimeException&) 211 { throw; } 212 catch(const css::uno::Exception&) 213 { sType = ::rtl::OUString(); } 214 215 //******************************************* 216 // adapt media descriptor, so it contains the right values 217 // for type/filter name/document service/ etcpp. 218 impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!! 219 impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType); 220 221 stlDescriptor >> lDescriptor; 222 return sType; 223 } 224 225 /*----------------------------------------------- 226 03.07.2003 10:36 227 -----------------------------------------------*/ 228 void TypeDetection::impl_checkResultsAndAddBestFilter(::comphelper::MediaDescriptor& rDescriptor, 229 ::rtl::OUString& sType ) 230 { 231 // a) 232 // Dont overwrite a might preselected filter! 233 ::rtl::OUString sFilter = rDescriptor.getUnpackedValueOrDefault( 234 ::comphelper::MediaDescriptor::PROP_FILTERNAME(), 235 ::rtl::OUString()); 236 if (sFilter.getLength()) 237 return; 238 239 // b) 240 // check a preselected document service too. 241 // Then we have to search a suitable filter witin this module. 242 ::rtl::OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault( 243 ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), 244 ::rtl::OUString()); 245 if (sDocumentService.getLength()) 246 { 247 try 248 { 249 ::rtl::OUString sRealType = sType; 250 251 #ifdef WORKAROUND_CSV_TXT_BUG_i60158 252 // Workaround for #i60158# 253 // We do not have right filter for Text_Ascii in calc nor a suitable filter for CSV in writer. 254 // So we must overrule our detection and make the right things. Normally we should have 255 // one type TextAscii and two filters registered for these one type. 256 // But then we loose automatic opening of CSV files in calc instead of opening these files 257 // inside writer. 258 if ( 259 (sDocumentService.equalsAscii("com.sun.star.sheet.SpreadsheetDocument")) && 260 ( 261 (sRealType.equalsAscii("writer_Text" )) || 262 (sRealType.equalsAscii("writer_Text_encoded")) 263 ) 264 ) 265 { 266 sRealType = ::rtl::OUString::createFromAscii("calc_Text_txt_csv_StarCalc"); 267 } 268 else 269 if ( 270 (sDocumentService.equalsAscii("com.sun.star.text.TextDocument")) && 271 (sRealType.equalsAscii("calc_Text_txt_csv_StarCalc" )) 272 ) 273 { 274 sRealType = ::rtl::OUString::createFromAscii("writer_Text"); 275 } 276 #endif // WORKAROUND_CSV_TXT_BUG_i60158 277 278 // SAFE -> 279 ::osl::ResettableMutexGuard aLock(m_aLock); 280 281 // Attention: For executing next lines of code, We must be sure that 282 // all filters already loaded :-( 283 // That can disturb our "load on demand feature". But we have no other chance! 284 m_rCache->load(FilterCache::E_CONTAINS_FILTERS); 285 286 CacheItem lIProps; 287 lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService; 288 lIProps[PROPNAME_TYPE ] <<= sRealType; 289 OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); 290 291 aLock.clear(); 292 // <- SAFE 293 294 for ( OUStringList::const_iterator pIt = lFilters.begin(); 295 pIt != lFilters.end() && sFilter.getLength() == 0 ; 296 ++pIt ) 297 { 298 // SAFE -> 299 aLock.reset(); 300 try 301 { 302 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt); 303 sal_Int32 nFlags = 0; 304 aFilter[PROPNAME_FLAGS] >>= nFlags; 305 306 if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT) 307 sFilter = *pIt; 308 } 309 catch(const css::uno::Exception&) {} 310 aLock.clear(); 311 // <- SAFE 312 } 313 314 if (sFilter.getLength() > 0) 315 { 316 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sRealType; 317 rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; 318 sType = sRealType; 319 return; 320 } 321 } 322 catch(const css::uno::Exception&) 323 {} 324 } 325 326 // c) 327 // We can use the preferred filter for the specified type. 328 // Such preferred filter points: 329 // - to the default filter of the preferred application 330 // - or to any other filter if no preferred filter was set. 331 // Note: It's an optimization only! 332 // It's not guaranteed, that such preferred filter exists. 333 sFilter = ::rtl::OUString(); 334 try 335 { 336 // SAFE -> 337 ::osl::ResettableMutexGuard aLock(m_aLock); 338 339 CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType); 340 aType[PROPNAME_PREFERREDFILTER] >>= sFilter; 341 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); 342 343 aLock.clear(); 344 // <- SAFE 345 346 // no exception => found valid type and filter => set it on the given descriptor 347 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sType ; 348 rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; 349 return; 350 } 351 catch(const css::uno::Exception&) 352 {} 353 354 // d) 355 // Search for any import(!) filter, which is registered for this type. 356 sFilter = ::rtl::OUString(); 357 try 358 { 359 // SAFE -> 360 ::osl::ResettableMutexGuard aLock(m_aLock); 361 362 // Attention: For executing next lines of code, We must be sure that 363 // all filters already loaded :-( 364 // That can disturb our "load on demand feature". But we have no other chance! 365 m_rCache->load(FilterCache::E_CONTAINS_FILTERS); 366 367 CacheItem lIProps; 368 lIProps[PROPNAME_TYPE] <<= sType; 369 OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); 370 371 aLock.clear(); 372 // <- SAFE 373 374 OUStringList::const_iterator pIt; 375 for ( pIt = lFilters.begin(); 376 pIt != lFilters.end() ; 377 ++pIt ) 378 { 379 sFilter = *pIt; 380 381 // SAFE -> 382 aLock.reset(); 383 try 384 { 385 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); 386 sal_Int32 nFlags = 0; 387 aFilter[PROPNAME_FLAGS] >>= nFlags; 388 389 if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT) 390 break; 391 } 392 catch(const css::uno::Exception&) 393 { continue; } 394 aLock.clear(); 395 // <- SAFE 396 397 sFilter = ::rtl::OUString(); 398 } 399 400 if (sFilter.getLength()) 401 { 402 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sType ; 403 rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; 404 return; 405 } 406 } 407 catch(const css::uno::Exception&) 408 {} 409 } 410 411 /*----------------------------------------------- 412 14.11.2003 12:06 413 -----------------------------------------------*/ 414 sal_Bool TypeDetection::impl_getPreselectionForType(const ::rtl::OUString& sPreSelType, 415 const css::util::URL& aParsedURL , 416 FlatDetection& rFlatTypes ) 417 { 418 // Can be used to suppress execution of some parts of this method 419 // if its already clear that detected type is valid or not. 420 // Its necessary to use shared code at the end, which update 421 // all return parameters constistency! 422 sal_Bool bBreakDetection = sal_False; 423 424 // Further we must know if it matches by pattern 425 // Every flat detected type by pattern wont be detected deep! 426 sal_Bool bMatchByPattern = sal_False; 427 428 // And we must know if a preselection must be preferred, because 429 // it matches by it's extension too. 430 sal_Bool bMatchByExtension = sal_False; 431 432 // If we e.g. collect all filters of a factory (be a forced factory preselection) 433 // we should preferr all filters of this factory, where the type match the given URL. 434 // All other types (which sorrespond to filters of the same factory - but dont match 435 // the URL) should be "used later" for detection and sorted at the end of our return vector 436 // rFlatTypes! 437 // => bPreferredPreselection = (matchByExtension || matchByURLPattern) 438 sal_Bool bPreferredPreselection = sal_False; 439 440 // validate type 441 ::rtl::OUString sType(sPreSelType); 442 CacheItem aType; 443 try 444 { 445 // SAFE -> -------------------------- 446 ::osl::ResettableMutexGuard aLock(m_aLock); 447 aType = m_rCache->getItem(FilterCache::E_TYPE, sType); 448 aLock.clear(); 449 // <- SAFE -------------------------- 450 } 451 catch(const css::container::NoSuchElementException&) 452 { 453 sType = ::rtl::OUString(); 454 bBreakDetection = sal_True; 455 } 456 457 if (!bBreakDetection) 458 { 459 // We can't check a preselected type for a given stream! 460 // So we must believe, that it can work ... 461 if (aParsedURL.Complete.equalsAsciiL("private:stream", 14)) 462 bBreakDetection = sal_True; 463 } 464 465 if (!bBreakDetection) 466 { 467 // extract extension from URL .. to check it case-insensitive ! 468 INetURLObject aParser (aParsedURL.Main); 469 ::rtl::OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT , 470 sal_True , 471 INetURLObject::DECODE_WITH_CHARSET); 472 sExtension = sExtension.toAsciiLowerCase(); 473 474 // otherwise we must know, if it matches to the given URL really. 475 // especially if it matches by its extension or pattern registration. 476 OUStringList lExtensions(aType[PROPNAME_EXTENSIONS]); 477 OUStringList lURLPattern(aType[PROPNAME_URLPATTERN]); 478 479 for (OUStringList::const_iterator pIt = lExtensions.begin(); 480 pIt != lExtensions.end() ; 481 ++pIt ) 482 { 483 ::rtl::OUString sCheckExtension(pIt->toAsciiLowerCase()); 484 if (sCheckExtension.equals(sExtension)) 485 { 486 bBreakDetection = sal_True; 487 bMatchByExtension = sal_True; 488 bPreferredPreselection = sal_True; 489 break; 490 } 491 } 492 493 if (!bBreakDetection) 494 { 495 for (OUStringList::const_iterator pIt = lURLPattern.begin(); 496 pIt != lURLPattern.end() ; 497 ++pIt ) 498 { 499 WildCard aCheck(*pIt); 500 if (aCheck.Matches(aParsedURL.Main)) 501 { 502 bBreakDetection = sal_True; 503 bMatchByPattern = sal_True; 504 bPreferredPreselection = sal_True; 505 break; 506 } 507 } 508 } 509 510 /* 511 Comment ... why the following line of code should be comened out .-) 512 513 This type does not seem to fit the requirements 514 But its an existing and well known type. 515 At least - [because may be the extension was missing :-( ] 516 we should try to detect this type deep ... 517 So we accept it here :-) 518 519 if (!bBreakDetection) 520 sType = ::rtl::OUString(); 521 */ 522 } 523 524 // if its a valid type - set it on all return values! 525 if (sType.getLength()) 526 { 527 FlatDetectionInfo aInfo; 528 aInfo.sType = sType; 529 aInfo.bMatchByExtension = bMatchByExtension; 530 aInfo.bMatchByPattern = bMatchByPattern; 531 aInfo.bPreselectedAsType = sal_True; 532 533 if (bPreferredPreselection) 534 rFlatTypes.push_front(aInfo); 535 else 536 rFlatTypes.push_back(aInfo); 537 538 return sal_True; 539 } 540 541 // not valid! 542 return sal_False; 543 } 544 545 /*----------------------------------------------- 546 14.11.2003 12:09 547 -----------------------------------------------*/ 548 sal_Bool TypeDetection::impl_getPreselectionForFilter(const ::rtl::OUString& sPreSelFilter, 549 const css::util::URL& aParsedURL , 550 FlatDetection& rFlatTypes ) 551 { 552 // Can be used to suppress execution of some parts of this method 553 // if its already clear that detected filter is valid or not. 554 // Its necessary to use shared code at the end, which update 555 // all return parameters constistency! 556 sal_Bool bBreakDetection = sal_False; 557 558 // validate filter 559 ::rtl::OUString sFilter(sPreSelFilter); 560 CacheItem aFilter; 561 try 562 { 563 // SAFE -> -------------------------- 564 ::osl::ResettableMutexGuard aLock(m_aLock); 565 aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); 566 aLock.clear(); 567 // <- SAFE -------------------------- 568 } 569 catch(const css::container::NoSuchElementException&) 570 { 571 sFilter = ::rtl::OUString(); 572 bBreakDetection = sal_True; 573 } 574 575 if (!bBreakDetection) 576 { 577 // get its type and check if it matches the given URL 578 ::rtl::OUString sType; 579 aFilter[PROPNAME_TYPE] >>= sType; 580 581 bBreakDetection = impl_getPreselectionForType(sType, aParsedURL, rFlatTypes); 582 583 // not a valid type? -> not a valid filter! 584 if (!bBreakDetection) 585 sFilter = ::rtl::OUString(); 586 } 587 588 // We have to mark all retrieved preselection items as "preselected by filter"! 589 FlatDetection::iterator pIt; 590 for ( pIt = rFlatTypes.begin(); 591 pIt != rFlatTypes.end() ; 592 ++pIt ) 593 { 594 FlatDetectionInfo& rInfo = *pIt; 595 rInfo.bPreselectedAsType = sal_False; 596 rInfo.bPreselectedByFilter = sal_True; 597 } 598 599 if (sFilter.getLength()) 600 return sal_True; 601 else 602 return sal_False; 603 } 604 605 /*----------------------------------------------- 606 14.11.2003 12:11 607 -----------------------------------------------*/ 608 sal_Bool TypeDetection::impl_getPreselectionForDocumentService(const ::rtl::OUString& sPreSelDocumentService, 609 const css::util::URL& aParsedURL , 610 FlatDetection& rFlatTypes ) 611 { 612 // get all filters, which match to this doc service 613 OUStringList lFilters; 614 try 615 { 616 // SAFE -> -------------------------- 617 ::osl::ResettableMutexGuard aLock(m_aLock); 618 619 // Attention: For executing next lines of code, We must be sure that 620 // all filters already loaded :-( 621 // That can disturb our "load on demand feature". But we have no other chance! 622 m_rCache->load(FilterCache::E_CONTAINS_FILTERS); 623 624 CacheItem lIProps; 625 lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService; 626 lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); 627 628 aLock.clear(); 629 // <- SAFE -------------------------- 630 } 631 catch(const css::container::NoSuchElementException&) 632 { 633 lFilters.clear(); 634 } 635 636 // step over all filters, and check if its registered type 637 // match the given URL. 638 // But use temp. list of "preselected types" instead of incoming rFlatTypes list! 639 // The reason behind: we must filter the getted results. And copying of stl entries 640 // is an easier job then removing it .-) 641 FlatDetection lPreselections; 642 for (OUStringList::const_iterator pFilter = lFilters.begin(); 643 pFilter != lFilters.end() ; 644 ++pFilter ) 645 { 646 const ::rtl::OUString sFilter = *pFilter; 647 impl_getPreselectionForFilter(sFilter, aParsedURL, lPreselections); 648 } 649 650 // We have to mark all retrieved preselection items as "preselected by document service". 651 // Further we must ignore all preselected items, which does not match the URL! 652 FlatDetection::iterator pIt; 653 for ( pIt = lPreselections.begin(); 654 pIt != lPreselections.end() ; 655 ++pIt ) 656 { 657 FlatDetectionInfo& rInfo = *pIt; 658 659 /* 660 #i60158# 661 Preselection by DocumentService ... 662 How many filters (and corresponding types) must be checked ? 663 All or only the list of filters/types, which match to the given URL too ? 664 There is no final decision about this currently. So we make it "configurable" .-) 665 */ 666 #ifdef IGNORE_NON_URLMATCHING_TYPES_FOR_PRESELECTION_DOCUMENTSERVICE 667 if ( 668 (!rInfo.bMatchByExtension) && 669 (!rInfo.bMatchByPattern ) 670 ) 671 continue; 672 #endif 673 674 rInfo.bPreselectedAsType = sal_False; 675 rInfo.bPreselectedByFilter = sal_False; 676 rInfo.bPreselectedByDocumentService = sal_True ; 677 rFlatTypes.push_back(rInfo); 678 } 679 680 return sal_True; 681 } 682 683 /*----------------------------------------------- 684 14.11.2003 12:21 685 -----------------------------------------------*/ 686 void TypeDetection::impl_getPreselection(const css::util::URL& aParsedURL , 687 ::comphelper::MediaDescriptor& rDescriptor, 688 FlatDetection& rFlatTypes ) 689 { 690 // done to be sure, that only valid results leave this function! 691 rFlatTypes.clear(); 692 693 /* #i55122# 694 Sometimes we must detect files without or with real unknown extensions. 695 If it does not work /which can happen of course .-)/, the user tried to preselect 696 the right format. But some special dialogs (e.g. "Insert->Sheet From File") 697 add it's own preselection too. 698 So we have a combination of preselected values ... 699 700 The we should preferr the most important one - set by the user. 701 And the user normally preselects a filter or type. The preselected 702 document service cames from the dialog. 703 704 Further it doesn't matter if the user preselected a filter or a document service. 705 A filter selection is always more explicit then a document service selection. 706 So it must be pereferred. An order between type and filter selection can't be discussed .-) 707 */ 708 709 ::rtl::OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString()); 710 if (sSelectedType.getLength()) 711 impl_getPreselectionForType(sSelectedType, aParsedURL, rFlatTypes); 712 713 ::rtl::OUString sSelectedFilter = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString()); 714 if (sSelectedFilter.getLength()) 715 impl_getPreselectionForFilter(sSelectedFilter, aParsedURL, rFlatTypes); 716 717 ::rtl::OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), ::rtl::OUString()); 718 if (sSelectedDoc.getLength()) 719 impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes); 720 } 721 722 /*----------------------------------------------- 723 03.11.2003 09:17 724 -----------------------------------------------*/ 725 ::rtl::OUString TypeDetection::impl_detectTypeFlatAndDeep( ::comphelper::MediaDescriptor& rDescriptor , 726 const FlatDetection& lFlatTypes , 727 sal_Bool bAllowDeep , 728 OUStringList& rUsedDetectors, 729 ::rtl::OUString& rLastChance ) 730 { 731 // reset it everytimes, so the outside code can distinguish between 732 // a set and a not set value. 733 rLastChance = ::rtl::OUString(); 734 rUsedDetectors.clear(); 735 736 // step over all possible types for this URL. 737 // solutions: 738 // a) no types => no detection 739 // b) deep detection not allowed => return first valid type of list (because its the preferred or the first valid one) 740 // or(!) match by URLPattern => in such case a deep detection will be suppressed! 741 // c) type has no detect service => safe the first occurred type without a detect service 742 // as "last chance"(!). It will be used outside of this method 743 // if no further type could be detected. 744 // It must be the first one, because it can be a preferred type. 745 // Our types list was sorted by such criteria! 746 // d) detect service return a valid result => return its decision 747 // e) detect service return an invalid result 748 // or any needed information could not be 749 // getted from the cache => ignore it, and continue with search 750 751 for (FlatDetection::const_iterator pFlatIt = lFlatTypes.begin(); 752 pFlatIt != lFlatTypes.end() ; 753 ++pFlatIt ) 754 { 755 const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt; 756 ::rtl::OUString sFlatType = aFlatTypeInfo.sType; 757 758 if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType)) 759 continue; 760 761 // b) 762 if ( 763 (!bAllowDeep ) || 764 (aFlatTypeInfo.bMatchByPattern) 765 ) 766 { 767 return sFlatType; 768 } 769 770 try 771 { 772 // SAFE -> ---------------------------------- 773 ::osl::ResettableMutexGuard aLock(m_aLock); 774 CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType); 775 aLock.clear(); 776 777 ::rtl::OUString sDetectService; 778 aType[PROPNAME_DETECTSERVICE] >>= sDetectService; 779 780 // c) 781 if (!sDetectService.getLength()) 782 { 783 // accept or not accept flat types without deep detection: that's the question :-) 784 // May be there exists some states, where we have to use our LastChance feature instead 785 // of using the flat type directly. 786 // Here the list of task ID's, which wasrelated to these lines of code: 787 // #i47159#, #i43404#, #i46494# 788 789 // a flat detected type without the chance for a deep detection ... but preselected by the user 790 // explicitly (means preselected as type or filter ... not as documentservice!) 791 // should be accepted. So the user can overrule our detection. 792 if ( 793 (aFlatTypeInfo.bPreselectedAsType ) || 794 (aFlatTypeInfo.bPreselectedByFilter) 795 ) 796 return sFlatType; 797 798 // flat detected types without any registered deep detection service and not 799 // preselected by the user can be used as LAST CHANCE in case no other type could 800 // be detected. Of course only the first type without deep detector can be used. 801 // Further ones has to be ignored. 802 if (rLastChance.getLength() < 1) 803 rLastChance = sFlatType; 804 805 continue; 806 } 807 808 // dont forget to add every real asked deep detection service here. 809 // Such detectors will be ignored if may be "impl_detectTypeDeepOnly()" 810 // must be called later! 811 rUsedDetectors.push_back(sDetectService); 812 ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); 813 814 // d) 815 if (sDeepType.getLength()) 816 return sDeepType; 817 } 818 catch(const css::container::NoSuchElementException&) 819 {} 820 // e) 821 } 822 823 return ::rtl::OUString(); 824 // <- SAFE ---------------------------------- 825 } 826 827 /*----------------------------------------------- 828 03.11.2003 09:19 829 -----------------------------------------------*/ 830 ::rtl::OUString TypeDetection::impl_detectTypeDeepOnly( ::comphelper::MediaDescriptor& rDescriptor , 831 const OUStringList& lOutsideUsedDetectors) 832 { 833 // We must know if a detect service was already used: 834 // i) in a combined flat/deep detection scenario outside or 835 // ii) in this method for a deep detection only. 836 // Reason: Such deep detection services work differently in these two modes! 837 OUStringList lInsideUsedDetectors; 838 OUStringList::const_iterator pIt; 839 840 // a) 841 // The list of "already used detect services" correspond to the list 842 // of preselected or flat detected types. But these detect services was called 843 // to check these types explicitly and return black/white ... yes/no only. 844 // Now they are called to return any possible result. But we should preferr 845 // these already used detect services against all other ones! 846 for ( pIt = lOutsideUsedDetectors.begin(); 847 pIt != lOutsideUsedDetectors.end() ; 848 ++pIt ) 849 { 850 const ::rtl::OUString& sDetectService = *pIt; 851 ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); 852 if (sDeepType.getLength()) 853 return sDeepType; 854 lInsideUsedDetectors.push_back(sDetectService); 855 } 856 857 // SAFE -> ---------------------------------- 858 ::osl::ResettableMutexGuard aLock(m_aLock); 859 OUStringList lDetectors = m_rCache->getItemNames(FilterCache::E_DETECTSERVICE); 860 aLock.clear(); 861 // <- SAFE ---------------------------------- 862 863 // b) 864 // Sometimes it would be nice to ask a special set of detect services before 865 // any other detect service is asked. E.g. by using a preselection of a DocumentService. 866 // That's needed to prevent us from asking the "wrong application module" and 867 // opening the files into the "wrong application". 868 ::rtl::OUString sPreselDocumentService = rDescriptor.getUnpackedValueOrDefault( 869 ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), 870 ::rtl::OUString()); 871 if (sPreselDocumentService.getLength()) 872 { 873 for ( pIt = lDetectors.begin(); 874 pIt != lDetectors.end() ; 875 ++pIt ) 876 { 877 const ::rtl::OUString& sDetectService = *pIt; 878 879 OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService); 880 if (pAlreadyUsed != lInsideUsedDetectors.end()) 881 continue; 882 883 // SAFE -> -------------------------------------------------------- 884 aLock.reset(); 885 886 CacheItem lIProps; 887 lIProps[PROPNAME_DETECTSERVICE] <<= sDetectService; 888 OUStringList lTypes = m_rCache->getMatchingItemsByProps(FilterCache::E_TYPE, lIProps); 889 890 aLock.clear(); 891 // <- SAFE -------------------------------------------------------- 892 893 sal_Bool bMatchDetectorToDocumentService = sal_False; 894 OUStringList::const_iterator pIt2; 895 for ( pIt2 = lTypes.begin(); 896 pIt2 != lTypes.end() ; 897 ++pIt2 ) 898 { 899 const ::rtl::OUString& sType = *pIt2; 900 901 try 902 { 903 // SAFE -> ---------------------------------------------------- 904 aLock.reset(); 905 906 CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType); 907 ::rtl::OUString sFilter; 908 aType[PROPNAME_PREFERREDFILTER] >>= sFilter; 909 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); 910 ::rtl::OUString sCheckDocumentService; 911 aFilter[PROPNAME_DOCUMENTSERVICE] >>= sCheckDocumentService; 912 913 aLock.clear(); 914 // <- SAFE 915 916 if (sCheckDocumentService.equals(sPreselDocumentService)) 917 { 918 bMatchDetectorToDocumentService = sal_True; 919 break; 920 } 921 } 922 catch(const css::uno::Exception&) 923 { continue; } 924 } 925 926 if (bMatchDetectorToDocumentService) 927 { 928 ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); 929 if (sDeepType.getLength()) 930 return sDeepType; 931 lInsideUsedDetectors.push_back(sDetectService); 932 } 933 } 934 } 935 936 // c) 937 // Last chance. No "used detectors", no "preselected detectors" ... ask any existing detect services 938 // for this till know unknown format. 939 for ( pIt = lDetectors.begin(); 940 pIt != lDetectors.end() ; 941 ++pIt ) 942 { 943 const ::rtl::OUString& sDetectService = *pIt; 944 945 OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService); 946 if (pAlreadyUsed != lInsideUsedDetectors.end()) 947 continue; 948 949 ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); 950 if (sDeepType.getLength()) 951 return sDeepType; 952 } 953 954 return ::rtl::OUString(); 955 } 956 957 /*----------------------------------------------- 958 07.03.2005 11:13 959 -----------------------------------------------*/ 960 void TypeDetection::impl_seekStreamToZero(comphelper::MediaDescriptor& rDescriptor) 961 { 962 // try to seek to 0 ... 963 // But because XSeekable is an optional interface ... try it only .-) 964 css::uno::Reference< css::io::XInputStream > xStream = rDescriptor.getUnpackedValueOrDefault( 965 ::comphelper::MediaDescriptor::PROP_INPUTSTREAM(), 966 css::uno::Reference< css::io::XInputStream >()); 967 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY); 968 if (xSeek.is()) 969 { 970 try 971 { 972 xSeek->seek(0); 973 } 974 catch(const css::uno::RuntimeException& exRun) 975 { throw exRun; } 976 catch(const css::uno::Exception&) 977 {} 978 } 979 } 980 981 /*----------------------------------------------- 982 30.10.2003 15:12 983 -----------------------------------------------*/ 984 ::rtl::OUString TypeDetection::impl_askDetectService(const ::rtl::OUString& sDetectService, 985 ::comphelper::MediaDescriptor& rDescriptor ) 986 { 987 // Open the stream and add it to the media descriptor if this method is called for the first time. 988 // All following requests to this method will detect, that there already exists a stream .-) 989 // Attention: This method throws an exception if the stream could not be opened. 990 // It's important to break any further detection in such case. 991 // Catch it on the highest detection level only !!! 992 impl_openStream(rDescriptor); 993 994 // seek to 0 is an optional feature to be more robust against 995 // "simple implemented detect services" .-) 996 impl_seekStreamToZero(rDescriptor); 997 998 css::uno::Reference< css::document::XExtendedFilterDetection > xDetector; 999 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR; 1000 1001 // SAFE -> 1002 ::osl::ResettableMutexGuard aLock(m_aLock); 1003 xSMGR = m_xSMGR; 1004 aLock.clear(); 1005 // <- SAFE 1006 1007 // Attention! If e.g. an office module was not installed sometimes we find a 1008 // registered detect service, which is referred inside the configuration ... but not really 1009 // installed. On the other side we use third party components here, which can make trouble anyway. 1010 // So we should handle errors during creation of such services more gracefully .-) 1011 xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >( 1012 xSMGR->createInstance(sDetectService), 1013 css::uno::UNO_QUERY); 1014 1015 if ( ! xDetector.is()) 1016 return ::rtl::OUString(); 1017 1018 ::rtl::OUString sDeepType; 1019 try 1020 { 1021 // start deep detection 1022 // Dont forget to convert stl descriptor to its uno representation. 1023 1024 /* Attention! 1025 You have to use an explicit instance of this uno sequence ... 1026 Because its used as an in out parameter. And in case of a temp. used object 1027 we will run into memory corruptions! 1028 */ 1029 css::uno::Sequence< css::beans::PropertyValue > lDescriptor; 1030 rDescriptor >> lDescriptor; 1031 sDeepType = xDetector->detect(lDescriptor); 1032 rDescriptor << lDescriptor; 1033 } 1034 catch(const css::uno::Exception&) 1035 { 1036 // We should ignore errors here. 1037 // Thrown exceptions mostly will end in crash recovery ... 1038 // But might be we find another deep detection service which can detect the same 1039 // document without a problem .-) 1040 sDeepType = ::rtl::OUString(); 1041 } 1042 1043 // seek to 0 is an optional feature to be more robust against 1044 // "simple implemented detect services" .-) 1045 impl_seekStreamToZero(rDescriptor); 1046 1047 // analyze the results 1048 // a) detect service returns "" => return "" too and remove TYPE/FILTER prop from descriptor 1049 // b) returned type is unknown => return "" too and remove TYPE/FILTER prop from descriptor 1050 // c) returned type is valid => check TYPE/FILTER props inside descriptor and return the type 1051 1052 // this special helper checks for a valid type 1053 // and set right values on the descriptor! 1054 sal_Bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType); 1055 if (bValidType) 1056 return sDeepType; 1057 1058 return ::rtl::OUString(); 1059 } 1060 1061 /*----------------------------------------------- 1062 17.12.2004 13:47 1063 -----------------------------------------------*/ 1064 ::rtl::OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(::comphelper::MediaDescriptor& rDescriptor) 1065 { 1066 // SAFE -> 1067 ::osl::ResettableMutexGuard aLock(m_aLock); 1068 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 1069 aLock.clear(); 1070 // <- SAFE 1071 1072 css::uno::Reference< css::task::XInteractionHandler > xInteraction = 1073 rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(), 1074 css::uno::Reference< css::task::XInteractionHandler >()); 1075 1076 if (!xInteraction.is()) 1077 return ::rtl::OUString(); 1078 1079 ::rtl::OUString sURL = 1080 rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), 1081 ::rtl::OUString()); 1082 1083 css::uno::Reference< css::io::XInputStream > xStream = 1084 rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INPUTSTREAM(), 1085 css::uno::Reference< css::io::XInputStream >()); 1086 1087 // Dont distrub the user for "non existing files - means empty URLs" or 1088 // if we was forced to detect a stream. 1089 // Reason behind: We must be sure to ask user for "unknown contents" only ... 1090 // and not for "missing files". Especially if detection is done by a stream only 1091 // we can't check if the stream points to an "existing content"! 1092 if ( 1093 (!sURL.getLength() ) || // "non existing file" ? 1094 (!xStream.is() ) || // non existing file ! 1095 (sURL.equalsIgnoreAsciiCaseAsciiL("private:stream", 14)) // not a good idea .-) 1096 ) 1097 return ::rtl::OUString(); 1098 1099 try 1100 { 1101 // create a new request to ask user for it's decision about the usable filter 1102 ::framework::RequestFilterSelect aRequest(sURL); 1103 xInteraction->handle(aRequest.GetRequest()); 1104 1105 // "Cancel" pressed? => return with error 1106 if (aRequest.isAbort()) 1107 return ::rtl::OUString(); 1108 1109 // "OK" pressed => verify the selected filter, get it's coressponding 1110 // type and return it. (BTW: We must update the media descriptor here ...) 1111 // The user selected explicitly a filter ... but normally we are interested on 1112 // a type here only. But we must be sure, that the selected filter is used 1113 // too and no ambigous filter registration disturb us .-) 1114 1115 ::rtl::OUString sFilter = aRequest.getFilter(); 1116 if (!impl_validateAndSetFilterOnDescriptor(rDescriptor, sFilter)) 1117 return ::rtl::OUString(); 1118 1119 ::rtl::OUString sType; 1120 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] >>= sType; 1121 return sType; 1122 } 1123 catch(const css::uno::Exception&) 1124 {} 1125 1126 return ::rtl::OUString(); 1127 } 1128 1129 /*----------------------------------------------- 1130 10.03.2004 10:30 1131 -----------------------------------------------*/ 1132 void TypeDetection::impl_openStream(::comphelper::MediaDescriptor& rDescriptor) 1133 throw (css::uno::Exception) 1134 { 1135 sal_Bool bSuccess = sal_False; 1136 ::rtl::OUString sURL = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString() ); 1137 sal_Bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_READONLY(), sal_False ); 1138 if ( sURL.getLength() && ::utl::LocalFileHelper::IsLocalFile( INetURLObject( sURL ).GetMainURL( INetURLObject::NO_DECODE ) ) ) 1139 { 1140 // OOo uses own file locking mechanics in case of local file 1141 bSuccess = rDescriptor.addInputStreamOwnLock(); 1142 } 1143 else 1144 bSuccess = rDescriptor.addInputStream(); 1145 1146 if ( !bSuccess ) 1147 throw css::uno::Exception(_FILTER_CONFIG_FROM_ASCII_("Could not open stream."), static_cast< css::document::XTypeDetection* >(this)); 1148 1149 if ( !bRequestedReadOnly ) 1150 { 1151 // The MediaDescriptor implementation adds ReadOnly argument if the file can not be opened for writing 1152 // this argument should be either removed or an additional argument should be added so that application 1153 // can separate the case when the user explicitly requests readonly document. 1154 // The current solution is to remove it here. 1155 rDescriptor.erase( ::comphelper::MediaDescriptor::PROP_READONLY() ); 1156 } 1157 } 1158 1159 /*----------------------------------------------- 1160 04.07.2003 13:47 1161 -----------------------------------------------*/ 1162 void TypeDetection::impl_removeTypeFilterFromDescriptor(::comphelper::MediaDescriptor& rDescriptor) 1163 { 1164 ::comphelper::MediaDescriptor::iterator pItType = rDescriptor.find(::comphelper::MediaDescriptor::PROP_TYPENAME() ); 1165 ::comphelper::MediaDescriptor::iterator pItFilter = rDescriptor.find(::comphelper::MediaDescriptor::PROP_FILTERNAME()); 1166 if (pItType != rDescriptor.end()) 1167 rDescriptor.erase(pItType); 1168 if (pItFilter != rDescriptor.end()) 1169 rDescriptor.erase(pItFilter); 1170 } 1171 1172 /*----------------------------------------------- 1173 14.10.2003 11:15 1174 -----------------------------------------------*/ 1175 sal_Bool TypeDetection::impl_validateAndSetTypeOnDescriptor( ::comphelper::MediaDescriptor& rDescriptor, 1176 const ::rtl::OUString& sType ) 1177 { 1178 // SAFE -> 1179 ::osl::ResettableMutexGuard aLock(m_aLock); 1180 if (m_rCache->hasItem(FilterCache::E_TYPE, sType)) 1181 { 1182 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType; 1183 return sal_True; 1184 } 1185 aLock.clear(); 1186 // <- SAFE 1187 1188 // remove all related informations from the descriptor 1189 impl_removeTypeFilterFromDescriptor(rDescriptor); 1190 return sal_False; 1191 } 1192 1193 /*----------------------------------------------- 1194 04.07.2003 14:01 1195 -----------------------------------------------*/ 1196 sal_Bool TypeDetection::impl_validateAndSetFilterOnDescriptor( ::comphelper::MediaDescriptor& rDescriptor, 1197 const ::rtl::OUString& sFilter ) 1198 { 1199 try 1200 { 1201 // SAFE -> 1202 ::osl::ResettableMutexGuard aLock(m_aLock); 1203 1204 CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); 1205 ::rtl::OUString sType; 1206 aFilter[PROPNAME_TYPE] >>= sType; 1207 CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType); 1208 1209 aLock.clear(); 1210 // <- SAFE 1211 1212 // found valid type and filter => set it on the given descriptor 1213 rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sType ; 1214 rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; 1215 return sal_True; 1216 } 1217 catch(const css::container::NoSuchElementException&){} 1218 1219 // remove all related informations from the descriptor 1220 impl_removeTypeFilterFromDescriptor(rDescriptor); 1221 return sal_False; 1222 } 1223 1224 /*----------------------------------------------- 1225 03.07.2003 10:36 1226 -----------------------------------------------*/ 1227 ::rtl::OUString TypeDetection::impl_getImplementationName() 1228 { 1229 return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.TypeDetection"); 1230 } 1231 1232 /*----------------------------------------------- 1233 03.07.2003 11:27 1234 -----------------------------------------------*/ 1235 css::uno::Sequence< ::rtl::OUString > TypeDetection::impl_getSupportedServiceNames() 1236 { 1237 css::uno::Sequence< ::rtl::OUString > lServiceNames(1); 1238 lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection"); 1239 return lServiceNames; 1240 } 1241 1242 /*----------------------------------------------- 1243 09.07.2003 08:02 1244 -----------------------------------------------*/ 1245 css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 1246 { 1247 TypeDetection* pNew = new TypeDetection(xSMGR); 1248 return css::uno::Reference< css::uno::XInterface >(static_cast< css::document::XTypeDetection* >(pNew), css::uno::UNO_QUERY); 1249 } 1250 1251 } // namespace config 1252 } // namespace filter 1253