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_starmath.hxx" 26 27 #include "smdetect.hxx" 28 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 29 #include <com/sun/star/beans/PropertyValue.hpp> 30 #include <com/sun/star/frame/XFrame.hpp> 31 #include <com/sun/star/frame/XModel.hpp> 32 #include <com/sun/star/awt/XWindow.hpp> 33 #include <com/sun/star/lang/XUnoTunnel.hpp> 34 #include <comphelper/processfactory.hxx> 35 #include <com/sun/star/beans/PropertyValue.hpp> 36 #include <com/sun/star/io/XInputStream.hpp> 37 #include <com/sun/star/task/XInteractionHandler.hpp> 38 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> 39 #include <com/sun/star/ucb/CommandAbortedException.hpp> 40 #include <com/sun/star/ucb/InteractiveAppException.hpp> 41 #include <com/sun/star/ucb/XContent.hpp> 42 #include <com/sun/star/packages/zip/ZipIOException.hpp> 43 #include <framework/interaction.hxx> 44 #include <toolkit/helper/vclunohelper.hxx> 45 #include <ucbhelper/simpleinteractionrequest.hxx> 46 #include <rtl/ustring.h> 47 #include <rtl/logfile.hxx> 48 #include <svl/itemset.hxx> 49 #include <vcl/window.hxx> 50 #include <svl/eitem.hxx> 51 #include <svl/stritem.hxx> 52 #include <tools/urlobj.hxx> 53 #include <vos/mutex.hxx> 54 #include <svtools/sfxecode.hxx> 55 #include <svtools/ehdl.hxx> 56 #include <sot/storinfo.hxx> 57 #include <vcl/svapp.hxx> 58 #include <sfx2/app.hxx> 59 #include <sfx2/sfxsids.hrc> 60 #include <sfx2/request.hxx> 61 #include <sfx2/docfile.hxx> 62 #include <sfx2/docfilt.hxx> 63 #include <sfx2/fcontnr.hxx> 64 #include <sfx2/brokenpackageint.hxx> 65 66 #include "document.hxx" 67 #include "eqnolefilehdr.hxx" 68 69 using namespace ::com::sun::star; 70 using namespace ::com::sun::star::uno; 71 using namespace ::com::sun::star::io; 72 using namespace ::com::sun::star::frame; 73 using namespace ::com::sun::star::task; 74 using namespace ::com::sun::star::beans; 75 using namespace ::com::sun::star::lang; 76 using namespace ::com::sun::star::ucb; 77 using namespace ::rtl; 78 79 SmFilterDetect::SmFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& /*xFactory*/ ) 80 { 81 } 82 83 SmFilterDetect::~SmFilterDetect() 84 { 85 } 86 87 ::rtl::OUString SAL_CALL SmFilterDetect::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( ::com::sun::star::uno::RuntimeException ) 88 { 89 REFERENCE< XInputStream > xStream; 90 REFERENCE< XContent > xContent; 91 REFERENCE< XInteractionHandler > xInteraction; 92 String aURL; 93 ::rtl::OUString sTemp; 94 String aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection) 95 String aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action) 96 97 ::rtl::OUString aDocumentTitle; // interesting only if set in this method 98 99 // opening as template is done when a parameter tells to do so and a template filter can be detected 100 // (otherwise no valid filter would be found) or if the detected filter is a template filter and 101 // there is no parameter that forbids to open as template 102 sal_Bool bOpenAsTemplate = sal_False; 103 sal_Bool bWasReadOnly = sal_False, bReadOnly = sal_False; 104 105 sal_Bool bRepairPackage = sal_False; 106 sal_Bool bRepairAllowed = sal_False; 107 108 // now some parameters that can already be in the array, but may be overwritten or new inserted here 109 // remember their indices in the case new values must be added to the array 110 sal_Int32 nPropertyCount = lDescriptor.getLength(); 111 sal_Int32 nIndexOfFilterName = -1; 112 sal_Int32 nIndexOfInputStream = -1; 113 sal_Int32 nIndexOfContent = -1; 114 sal_Int32 nIndexOfReadOnlyFlag = -1; 115 sal_Int32 nIndexOfTemplateFlag = -1; 116 sal_Int32 nIndexOfDocumentTitle = -1; 117 118 for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty ) 119 { 120 // extract properties 121 if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("URL")) ) 122 { 123 lDescriptor[nProperty].Value >>= sTemp; 124 aURL = sTemp; 125 } 126 else if( !aURL.Len() && lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")) ) 127 { 128 lDescriptor[nProperty].Value >>= sTemp; 129 aURL = sTemp; 130 } 131 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")) ) 132 { 133 lDescriptor[nProperty].Value >>= sTemp; 134 aTypeName = sTemp; 135 } 136 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName")) ) 137 { 138 lDescriptor[nProperty].Value >>= sTemp; 139 aPreselectedFilterName = sTemp; 140 141 // if the preselected filter name is not correct, it must be erased after detection 142 // remember index of property to get access to it later 143 nIndexOfFilterName = nProperty; 144 } 145 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream")) ) 146 nIndexOfInputStream = nProperty; 147 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")) ) 148 nIndexOfReadOnlyFlag = nProperty; 149 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("UCBContent")) ) 150 nIndexOfContent = nProperty; 151 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("AsTemplate")) ) 152 { 153 lDescriptor[nProperty].Value >>= bOpenAsTemplate; 154 nIndexOfTemplateFlag = nProperty; 155 } 156 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler")) ) 157 lDescriptor[nProperty].Value >>= xInteraction; 158 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("RepairPackage")) ) 159 lDescriptor[nProperty].Value >>= bRepairPackage; 160 else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle")) ) 161 nIndexOfDocumentTitle = nProperty; 162 } 163 164 // can't check the type for external filters, so set the "dont" flag accordingly 165 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 166 //SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED; 167 168 SfxApplication* pApp = SFX_APP(); 169 SfxAllItemSet *pSet = new SfxAllItemSet( pApp->GetPool() ); 170 TransformParameters( SID_OPENDOC, lDescriptor, *pSet ); 171 SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, sal_False ); 172 173 bWasReadOnly = pItem && pItem->GetValue(); 174 175 String aFilterName; 176 String aPrefix = String::CreateFromAscii( "private:factory/" ); 177 if( aURL.Match( aPrefix ) == aPrefix.Len() ) 178 { 179 const SfxFilter* pFilter = 0; 180 String aPattern( aPrefix ); 181 aPattern += String::CreateFromAscii("smath"); 182 if ( aURL.Match( aPattern ) >= aPattern.Len() ) 183 { 184 pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL ); 185 aTypeName = pFilter->GetTypeName(); 186 aFilterName = pFilter->GetName(); 187 } 188 } 189 else 190 { 191 // ctor of SfxMedium uses owner transition of ItemSet 192 SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, sal_False, NULL, pSet ); 193 aMedium.UseInteractionHandler( sal_True ); 194 195 sal_Bool bIsStorage = aMedium.IsStorage(); 196 if ( aMedium.GetErrorCode() == ERRCODE_NONE ) 197 { 198 // remember input stream and content and put them into the descriptor later 199 // should be done here since later the medium can switch to a version 200 xStream = aMedium.GetInputStream(); 201 xContent = aMedium.GetContent(); 202 bReadOnly = aMedium.IsReadOnly(); 203 204 if ( bIsStorage ) 205 { 206 //TODO/LATER: factor this out! 207 uno::Reference < embed::XStorage > xStorage = aMedium.GetStorage( sal_False ); 208 if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE ) 209 { 210 // error during storage creation means _here_ that the medium 211 // is broken, but we can not handle it in medium since unpossibility 212 // to create a storage does not _always_ means that the medium is broken 213 aMedium.SetError( aMedium.GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 214 if ( xInteraction.is() ) 215 { 216 OUString empty; 217 try 218 { 219 InteractiveAppException xException( empty, 220 REFERENCE< XInterface >(), 221 InteractionClassification_ERROR, 222 aMedium.GetError() ); 223 224 REFERENCE< XInteractionRequest > xRequest( 225 new ucbhelper::SimpleInteractionRequest( makeAny( xException ), 226 ucbhelper::CONTINUATION_APPROVE ) ); 227 xInteraction->handle( xRequest ); 228 } 229 catch ( Exception & ) {}; 230 } 231 } 232 else 233 { 234 aFilterName.Erase(); 235 236 try 237 { 238 const SfxFilter* pFilter = aPreselectedFilterName.Len() ? 239 SfxFilterMatcher().GetFilter4FilterName( aPreselectedFilterName ) : aTypeName.Len() ? 240 SfxFilterMatcher(String::CreateFromAscii("smath")).GetFilter4EA( aTypeName ) : 0; 241 String aTmpFilterName; 242 if ( pFilter ) 243 aTmpFilterName = pFilter->GetName(); 244 aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsAllowedAsTemplate() : sal_False, &aTmpFilterName ); 245 } 246 catch( lang::WrappedTargetException& aWrap ) 247 { 248 packages::zip::ZipIOException aZipException; 249 250 // repairing is done only if this type is requested from outside 251 if ( ( aWrap.TargetException >>= aZipException ) && aTypeName.Len() ) 252 { 253 if ( xInteraction.is() ) 254 { 255 // the package is broken one 256 aDocumentTitle = aMedium.GetURLObject().getName( 257 INetURLObject::LAST_SEGMENT, 258 true, 259 INetURLObject::DECODE_WITH_CHARSET ); 260 261 if ( !bRepairPackage ) 262 { 263 // ask the user whether he wants to try to repair 264 RequestPackageReparation aRequest( aDocumentTitle ); 265 xInteraction->handle( aRequest.GetRequest() ); 266 bRepairAllowed = aRequest.isApproved(); 267 } 268 269 if ( !bRepairAllowed ) 270 { 271 // repair either not allowed or not successful 272 NotifyBrokenPackage aNotifyRequest( aDocumentTitle ); 273 xInteraction->handle( aNotifyRequest.GetRequest() ); 274 } 275 } 276 277 if ( !bRepairAllowed ) 278 aTypeName.Erase(); 279 } 280 } 281 catch( uno::RuntimeException& ) 282 { 283 throw; 284 } 285 catch( uno::Exception& ) 286 { 287 aTypeName.Erase(); 288 } 289 290 if ( aTypeName.Len() ) 291 { 292 const SfxFilter* pFilter = 293 SfxFilterMatcher( String::CreateFromAscii("smath") ).GetFilter4EA( aTypeName ); 294 if ( pFilter ) 295 aFilterName = pFilter->GetName(); 296 } 297 } 298 } 299 else 300 { 301 // DesignScience Equation Editor MathType 3.0 ? 302 SvStream *pStrm = aMedium.GetInStream(); 303 aTypeName.Erase(); 304 if (pStrm && !pStrm->GetError()) 305 { 306 SotStorageRef aStorage = new SotStorage ( pStrm, sal_False ); 307 if ( !aStorage->GetError() ) 308 { 309 if ( aStorage->IsStream( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Equation Native" ) ) ) ) 310 { 311 sal_uInt8 nVersion; 312 if (GetMathTypeVersion( aStorage, nVersion ) && nVersion <=3) 313 aTypeName.AssignAscii( "math_MathType_3x" ); 314 } 315 } 316 else 317 { 318 // MathML? The SAX parser expects the 'math' root element incl. 319 // the namespace URL. Neither '<?xml' prolog nor <!doctype is needed. 320 // If the math element has a prefix (e.g. <bla:math), the 321 // prefix has to be defined in the namespace attribut 322 // (e.g. xmlns:bla="http://www.w3.org/1998/Math/MathML") 323 // #124636 is fixed too. 324 pStrm->Seek( STREAM_SEEK_TO_BEGIN ); 325 const size_t nBufSize=2048; 326 sal_uInt16 aBuffer[nBufSize]; // will be casted to an Unicode-Array below 327 sal_uInt8* pByte = reinterpret_cast<sal_uInt8*>(aBuffer); 328 const sal_uLong nBytesRead(pStrm->Read( pByte, nBufSize * 2 ) ); 329 const sal_uLong nUnicodeCharsRead (nBytesRead / 2 ); 330 331 // For backwards searching an OUString is used. The conversion needs an 332 // encoding information. Default encoding is UTF-8, UTF-16 is possible 333 // (e.g. from MS "Math Input Control"), others are unlikely. 334 // Looking for Byte Order Mark 335 rtl_TextEncoding aEncoding = RTL_TEXTENCODING_UTF8; 336 bool bIsUnicode = false; 337 if (nBytesRead >= 2 && (aBuffer[0]==0xfffe || aBuffer[0]==0xfeff) ) 338 { 339 aEncoding = RTL_TEXTENCODING_UNICODE; 340 bIsUnicode = true; 341 if ( aBuffer[0] == 0xfffe) 342 { //swap bytes to make Big Endian 343 for (size_t i=0; i < nUnicodeCharsRead; ++i) 344 { 345 aBuffer[i] = (aBuffer[i]>>8) | (aBuffer[i]<<8) ; 346 } 347 } 348 } 349 350 bool isMathFile(false); 351 if ( nBytesRead > 56) // minimal <math xmlns="http://www.w3.org/1998/Math/MathML"></math> 352 { 353 const sal_Char* pChar = reinterpret_cast<sal_Char*>(aBuffer); 354 sal_Unicode* pUnicode = (sal_Unicode*) aBuffer; 355 356 const OUString sFragment( (bIsUnicode) 357 ? OUString( pUnicode , nUnicodeCharsRead ) 358 : OUString( pChar, nBytesRead, aEncoding) ); 359 const sal_Int32 nFragmentLength(sFragment.getLength()); 360 361 // look for MathML URL http://www.w3.org/1998/Math/MathML 362 // #i53509 A MathML URL can be value of a namespace attribute, but can be as well 363 // inside a doctype e.g. [<!ENTITY mathml 'http://www.w3.org/1998/Math/MathML'>] 364 // or inside a schema reference e.g. s:schemaLocation="http://www.w3.org/1998/Math/MathML" 365 // Use a loop to get the correct one. 366 const OUString sURL( OUString::createFromAscii("http://www.w3.org/1998/Math/MathML")); 367 const sal_Int32 nURLLength = sURL.getLength(); 368 const OUString sEQ( OUString::createFromAscii("=") ); 369 const OUString sXMLNS( OUString::createFromAscii("xmlns") ); 370 sal_Int32 nPosURL = -1; // for index of first character of URL 371 sal_Int32 nPosURLSearchStart = 0; 372 sal_Int32 nPosEQ = -1; // for index of equal sign 373 sal_Int32 nPosXMLNS = -1; // for index of first character of string "xmlns" 374 do 375 { 376 nPosURL = sFragment.indexOf(sURL,nPosURLSearchStart); 377 if( nPosURL < 0 ) 378 { 379 break; // no MathML URL, cannot be parsed 380 } 381 // need 'xmlns:prefix =' or 'xmlns =', look backwards, first for equal sign 382 nPosEQ = sFragment.lastIndexOf(sEQ,nPosURL); 383 if (nPosEQ >= 0 && nPosEQ >= nPosURLSearchStart) 384 { 385 nPosXMLNS = sFragment.lastIndexOf(sXMLNS,nPosEQ); 386 if( nPosXMLNS >= nPosURLSearchStart ) 387 { // an xmlns attribute is found, but it might belong to a schema 388 // get prefix if present 389 const OUString sPrefix = (sFragment.copy(nPosXMLNS+5,nPosEQ-(nPosXMLNS+5))).trim(); 390 // such prefix definition must start with colon (will be removed below) 391 bool bHasPrefix( (sPrefix.isEmpty()) ? false : sPrefix.toChar() == sal_Unicode(':') ); 392 // the math element starts either with '<prefix:math' or '<math' 393 const OUString sMathStart( (bHasPrefix) 394 ? OUString::createFromAscii("<") + sPrefix.copy(1,sPrefix.getLength()-1) + OUString::createFromAscii(":math") 395 : OUString::createFromAscii("<math") ); 396 sal_Int32 nPosMath (sFragment.lastIndexOf(sMathStart,nPosXMLNS)); 397 if( nPosMath >= 0) 398 { // xmlns attribute belongs to math element 399 isMathFile = true; 400 break; 401 } 402 } 403 } 404 // MathML URL was wrong one, look for next 405 nPosURLSearchStart = nPosURL + nURLLength; 406 } 407 while ( nPosURLSearchStart + nURLLength <= nFragmentLength); 408 409 if(isMathFile) 410 { 411 static const sal_Char sFltrNm_2[] = MATHML_XML; 412 static const sal_Char sTypeNm_2[] = "math_MathML_XML_Math"; 413 414 aFilterName.AssignAscii( sFltrNm_2 ); 415 aTypeName.AssignAscii( sTypeNm_2 ); 416 } 417 } 418 } 419 420 if ( aTypeName.Len() ) 421 { 422 const SfxFilter* pFilt = SfxFilterMatcher( String::CreateFromAscii("smath") ).GetFilter4EA( aTypeName ); 423 if ( pFilt ) 424 aFilterName = pFilt->GetName(); 425 } 426 } 427 } 428 } 429 } 430 431 if ( nIndexOfInputStream == -1 && xStream.is() ) 432 { 433 // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice 434 lDescriptor.realloc( nPropertyCount + 1 ); 435 lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("InputStream"); 436 lDescriptor[nPropertyCount].Value <<= xStream; 437 nPropertyCount++; 438 } 439 440 if ( nIndexOfContent == -1 && xContent.is() ) 441 { 442 // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice 443 lDescriptor.realloc( nPropertyCount + 1 ); 444 lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("UCBContent"); 445 lDescriptor[nPropertyCount].Value <<= xContent; 446 nPropertyCount++; 447 } 448 449 if ( bReadOnly != bWasReadOnly ) 450 { 451 if ( nIndexOfReadOnlyFlag == -1 ) 452 { 453 lDescriptor.realloc( nPropertyCount + 1 ); 454 lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("ReadOnly"); 455 lDescriptor[nPropertyCount].Value <<= bReadOnly; 456 nPropertyCount++; 457 } 458 else 459 lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly; 460 } 461 462 if ( !bRepairPackage && bRepairAllowed ) 463 { 464 lDescriptor.realloc( nPropertyCount + 1 ); 465 lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("RepairPackage"); 466 lDescriptor[nPropertyCount].Value <<= bRepairAllowed; 467 nPropertyCount++; 468 469 bOpenAsTemplate = sal_True; 470 471 // TODO/LATER: set progress bar that should be used 472 } 473 474 if ( bOpenAsTemplate ) 475 { 476 if ( nIndexOfTemplateFlag == -1 ) 477 { 478 lDescriptor.realloc( nPropertyCount + 1 ); 479 lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("AsTemplate"); 480 lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate; 481 nPropertyCount++; 482 } 483 else 484 lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate; 485 } 486 487 if ( aDocumentTitle.getLength() ) 488 { 489 // the title was set here 490 if ( nIndexOfDocumentTitle == -1 ) 491 { 492 lDescriptor.realloc( nPropertyCount + 1 ); 493 lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("DocumentTitle"); 494 lDescriptor[nPropertyCount].Value <<= aDocumentTitle; 495 nPropertyCount++; 496 } 497 else 498 lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle; 499 } 500 501 if ( !aFilterName.Len() ) 502 aTypeName.Erase(); 503 504 return aTypeName; 505 } 506 507 SFX_IMPL_SINGLEFACTORY( SmFilterDetect ) 508 509 /* XServiceInfo */ 510 UNOOUSTRING SAL_CALL SmFilterDetect::getImplementationName() throw( UNORUNTIMEEXCEPTION ) 511 { 512 return impl_getStaticImplementationName(); 513 } 514 \ 515 /* XServiceInfo */ 516 sal_Bool SAL_CALL SmFilterDetect::supportsService( const UNOOUSTRING& sServiceName ) throw( UNORUNTIMEEXCEPTION ) 517 { 518 UNOSEQUENCE< UNOOUSTRING > seqServiceNames = getSupportedServiceNames(); 519 const UNOOUSTRING* pArray = seqServiceNames.getConstArray(); 520 for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ ) 521 { 522 if ( pArray[nCounter] == sServiceName ) 523 { 524 return sal_True ; 525 } 526 } 527 return sal_False ; 528 } 529 530 /* XServiceInfo */ 531 UNOSEQUENCE< UNOOUSTRING > SAL_CALL SmFilterDetect::getSupportedServiceNames() throw( UNORUNTIMEEXCEPTION ) 532 { 533 return impl_getStaticSupportedServiceNames(); 534 } 535 536 /* Helper for XServiceInfo */ 537 UNOSEQUENCE< UNOOUSTRING > SmFilterDetect::impl_getStaticSupportedServiceNames() 538 { 539 UNOMUTEXGUARD aGuard( UNOMUTEX::getGlobalMutex() ); 540 UNOSEQUENCE< UNOOUSTRING > seqServiceNames( 1 ); 541 seqServiceNames.getArray() [0] = UNOOUSTRING::createFromAscii( "com.sun.star.frame.ExtendedTypeDetection" ); 542 return seqServiceNames ; 543 } 544 545 /* Helper for XServiceInfo */ 546 UNOOUSTRING SmFilterDetect::impl_getStaticImplementationName() 547 { 548 return UNOOUSTRING::createFromAscii( "com.sun.star.comp.math.FormatDetector" ); 549 } 550 551 /* Helper for registry */ 552 UNOREFERENCE< UNOXINTERFACE > SAL_CALL SmFilterDetect::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION ) 553 { 554 return UNOREFERENCE< UNOXINTERFACE >( *new SmFilterDetect( xServiceManager ) ); 555 } 556