1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_extensions.hxx" 30 31 32 #include "updatecheckconfig.hxx" 33 #include <com/sun/star/beans/PropertyValue.hpp> 34 #include <com/sun/star/beans/XPropertyState.hpp> 35 #include <com/sun/star/beans/XPropertySet.hpp> 36 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 37 38 #include <osl/security.hxx> 39 #include <osl/time.h> 40 #include <osl/file.hxx> 41 42 #ifdef WNT 43 #ifdef _MSC_VER 44 #pragma warning(push,1) // disable warnings within system headers 45 #pragma warning(disable: 4917) 46 #endif 47 #include <shlobj.h> 48 #ifdef _MSC_VER 49 #pragma warning(pop) 50 #endif 51 #endif 52 53 namespace container = com::sun::star::container ; 54 namespace beans = com::sun::star::beans ; 55 namespace lang = com::sun::star::lang ; 56 namespace util = com::sun::star::util ; 57 namespace uno = com::sun::star::uno ; 58 59 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) 60 61 #define LAST_CHECK "LastCheck" 62 #define VERSION_FOUND "UpdateVersionFound" 63 #define UPDATE_VERSION "UpdateVersion" 64 #define UPDATE_BUILDID "UpdateBuildId" 65 #define UPDATE_DESCRIPTION "UpdateDescription" 66 #define DOWNLOAD_URL "DownloadURL" 67 #define IS_DIRECT_DOWNLOAD "IsDirectDownload" 68 #define OLD_VERSION "UpdateFoundFor" 69 #define AUTOCHECK_ENABLED "AutoCheckEnabled" 70 #define AUTODOWNLOAD_ENABLED "AutoDownloadEnabled" 71 #define CHECK_INTERVAL "CheckInterval" 72 #define LOCAL_FILE "LocalFile" 73 #define DOWNLOAD_SIZE "DownloadSize" 74 #define DOWNLOAD_PAUSED "DownloadPaused" 75 #define DOWNLOAD_DESTINATION "DownloadDestination" 76 #define RELEASE_NOTE "ReleaseNote" 77 #define EXTENSION_PREFIX "Extension_" 78 79 #define PROPERTY_VERSION UNISTRING("Version") 80 81 static const sal_Char * const aUpdateEntryProperties[] = { 82 UPDATE_VERSION, 83 UPDATE_BUILDID, 84 UPDATE_DESCRIPTION, 85 DOWNLOAD_URL, 86 IS_DIRECT_DOWNLOAD, 87 RELEASE_NOTE"1", 88 RELEASE_NOTE"2", 89 RELEASE_NOTE"3", 90 RELEASE_NOTE"4", 91 RELEASE_NOTE"5", 92 OLD_VERSION 93 }; 94 95 static const sal_uInt32 nUpdateEntryProperties = sizeof(aUpdateEntryProperties) / sizeof(sal_Char *); 96 97 //------------------------------------------------------------------------------ 98 99 NamedValueByNameAccess::~NamedValueByNameAccess() 100 { 101 } 102 103 //------------------------------------------------------------------------------ 104 105 ::com::sun::star::uno::Any 106 NamedValueByNameAccess::getValue(const sal_Char * pName) 107 { 108 const sal_Int32 nLen = m_rValues.getLength(); 109 for( sal_Int32 n=0; n < nLen; ++n ) 110 { 111 if( m_rValues[n].Name.equalsAscii( pName ) ) 112 return m_rValues[n].Value; 113 } 114 return ::com::sun::star::uno::Any(); 115 } 116 117 118 //------------------------------------------------------------------------------ 119 120 bool 121 UpdateCheckROModel::isAutoCheckEnabled() const 122 { 123 return sal_True == m_aNameAccess.getValue(AUTOCHECK_ENABLED).get< sal_Bool >(); 124 } 125 126 //------------------------------------------------------------------------------ 127 128 bool 129 UpdateCheckROModel::isDownloadPaused() const 130 { 131 return sal_True == m_aNameAccess.getValue(DOWNLOAD_PAUSED).get< sal_Bool >(); 132 } 133 134 //------------------------------------------------------------------------------ 135 136 rtl::OUString 137 UpdateCheckROModel::getStringValue(const sal_Char * pStr) const 138 { 139 uno::Any aAny( m_aNameAccess.getValue(pStr) ); 140 rtl::OUString aRet; 141 142 aAny >>= aRet; 143 144 return aRet; 145 } 146 147 //------------------------------------------------------------------------------ 148 149 rtl::OUString UpdateCheckROModel::getLocalFileName() const 150 { 151 return getStringValue(LOCAL_FILE); 152 }; 153 154 //------------------------------------------------------------------------------ 155 156 sal_Int64 UpdateCheckROModel::getDownloadSize() const 157 { 158 uno::Any aAny( m_aNameAccess.getValue(DOWNLOAD_SIZE) ); 159 sal_Int64 nRet = -1; 160 161 aAny >>= nRet; 162 return nRet; 163 }; 164 165 //------------------------------------------------------------------------------ 166 167 rtl::OUString 168 UpdateCheckROModel::getUpdateEntryVersion() const 169 { 170 return getStringValue(OLD_VERSION); 171 } 172 173 //------------------------------------------------------------------------------ 174 175 void 176 UpdateCheckROModel::getUpdateEntry(UpdateInfo& rInfo) const 177 { 178 rInfo.BuildId = getStringValue(UPDATE_BUILDID); 179 rInfo.Version = getStringValue(UPDATE_VERSION); 180 rInfo.Description = getStringValue(UPDATE_DESCRIPTION); 181 182 sal_Bool isDirectDownload = sal_False; 183 m_aNameAccess.getValue(IS_DIRECT_DOWNLOAD) >>= isDirectDownload; 184 185 rInfo.Sources.push_back( DownloadSource( isDirectDownload, getStringValue(DOWNLOAD_URL) ) ); 186 187 rtl::OString aStr(RELEASE_NOTE); 188 for(sal_Int32 n=1; n < 6; ++n ) 189 { 190 rtl::OUString aUStr = getStringValue(aStr + rtl::OString::valueOf(n)); 191 if( aUStr.getLength() > 0 ) 192 rInfo.ReleaseNotes.push_back(ReleaseNote((sal_Int8) n, aUStr)); 193 } 194 } 195 196 197 //------------------------------------------------------------------------------ 198 199 rtl::OUString UpdateCheckConfig::getDesktopDirectory() 200 { 201 rtl::OUString aRet; 202 203 #ifdef WNT 204 WCHAR szPath[MAX_PATH]; 205 206 if( ! FAILED( SHGetSpecialFolderPathW( NULL, szPath, CSIDL_DESKTOPDIRECTORY, true ) ) ) 207 { 208 aRet = rtl::OUString( reinterpret_cast< sal_Unicode * >(szPath) ); 209 osl::FileBase::getFileURLFromSystemPath( aRet, aRet ); 210 } 211 #else 212 // This should become a desktop specific setting in some system backend .. 213 rtl::OUString aHomeDir; 214 osl::Security().getHomeDir( aHomeDir ); 215 aRet = aHomeDir + rtl::OUString::createFromAscii("/Desktop"); 216 217 // Set path to home directory when there is no /Desktop directory 218 osl::Directory aDocumentsDir( aRet ); 219 if( osl::FileBase::E_None != aDocumentsDir.open() ) 220 aRet = aHomeDir; 221 #endif 222 223 return aRet; 224 } 225 226 //------------------------------------------------------------------------------ 227 228 rtl::OUString UpdateCheckConfig::getAllUsersDirectory() 229 { 230 rtl::OUString aRet; 231 232 #ifdef WNT 233 WCHAR szPath[MAX_PATH]; 234 235 if( ! FAILED( SHGetSpecialFolderPathW( NULL, szPath, CSIDL_COMMON_DOCUMENTS, true ) ) ) 236 { 237 aRet = rtl::OUString( reinterpret_cast< sal_Unicode * >(szPath) ); 238 osl::FileBase::RC rc; 239 rc = osl::FileBase::getFileURLFromSystemPath( aRet, aRet ); 240 } 241 #else 242 osl::FileBase::getTempDirURL(aRet); 243 #endif 244 245 return aRet; 246 } 247 248 //------------------------------------------------------------------------------ 249 UpdateCheckConfig::UpdateCheckConfig( const uno::Reference<container::XNameContainer>& xContainer, 250 const uno::Reference<container::XNameContainer>& xAvailableUpdates, 251 const uno::Reference<container::XNameContainer>& xIgnoredUpdates, 252 const ::rtl::Reference< UpdateCheckConfigListener >& rListener ) : 253 m_xContainer( xContainer ), 254 m_xAvailableUpdates( xAvailableUpdates ), 255 m_xIgnoredUpdates( xIgnoredUpdates ), 256 m_rListener( rListener ) 257 {} 258 259 //------------------------------------------------------------------------------ 260 UpdateCheckConfig::~UpdateCheckConfig() 261 {} 262 263 //------------------------------------------------------------------------------ 264 265 ::rtl::Reference< UpdateCheckConfig > 266 UpdateCheckConfig::get( 267 const uno::Reference<uno::XComponentContext>& xContext, 268 const ::rtl::Reference< UpdateCheckConfigListener >& rListener) 269 { 270 if( !xContext.is() ) 271 throw uno::RuntimeException( 272 UNISTRING( "UpdateCheckConfig: empty component context" ), 273 uno::Reference< uno::XInterface >() ); 274 275 uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager()); 276 277 if( !xServiceManager.is() ) 278 throw uno::RuntimeException( 279 UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ), 280 uno::Reference< uno::XInterface >() ); 281 282 uno::Reference< lang::XMultiServiceFactory > xConfigProvider( 283 xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.configuration.ConfigurationProvider" ), xContext ), 284 uno::UNO_QUERY_THROW); 285 286 beans::PropertyValue aProperty; 287 aProperty.Name = UNISTRING( "nodepath" ); 288 aProperty.Value = uno::makeAny( UNISTRING("org.openoffice.Office.Jobs/Jobs/UpdateCheck/Arguments") ); 289 290 uno::Sequence< uno::Any > aArgumentList( 1 ); 291 aArgumentList[0] = uno::makeAny( aProperty ); 292 293 uno::Reference< container::XNameContainer > xContainer( 294 xConfigProvider->createInstanceWithArguments( 295 UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess"), aArgumentList ), 296 uno::UNO_QUERY_THROW ); 297 298 aProperty.Value = uno::makeAny( UNISTRING("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates") ); 299 aArgumentList[0] = uno::makeAny( aProperty ); 300 uno::Reference< container::XNameContainer > xIgnoredExt( xConfigProvider->createInstanceWithArguments( UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess"), aArgumentList ), uno::UNO_QUERY_THROW ); 301 302 aProperty.Value = uno::makeAny( UNISTRING("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/AvailableUpdates") ); 303 aArgumentList[0] = uno::makeAny( aProperty ); 304 uno::Reference< container::XNameContainer > xUpdateAvail( xConfigProvider->createInstanceWithArguments( UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess"), aArgumentList ), uno::UNO_QUERY_THROW ); 305 306 return new UpdateCheckConfig( xContainer, xUpdateAvail, xIgnoredExt, rListener ); 307 } 308 309 //------------------------------------------------------------------------------ 310 311 bool 312 UpdateCheckConfig::isAutoCheckEnabled() const 313 { 314 sal_Bool nValue = sal_False; 315 const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( AUTOCHECK_ENABLED ) ) >>= nValue; 316 return nValue; 317 } 318 319 //------------------------------------------------------------------------------ 320 321 bool 322 UpdateCheckConfig::isAutoDownloadEnabled() const 323 { 324 sal_Bool nValue = sal_False; 325 const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( AUTODOWNLOAD_ENABLED ) ) >>= nValue; 326 return nValue; 327 } 328 329 //------------------------------------------------------------------------------ 330 331 rtl::OUString 332 UpdateCheckConfig::getUpdateEntryVersion() const 333 { 334 rtl::OUString aValue; 335 336 // getByName is defined as non const in XNameAccess 337 const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( OLD_VERSION ) ) >>= aValue; 338 339 return aValue; 340 } 341 342 //------------------------------------------------------------------------------ 343 344 sal_Int64 345 UpdateCheckConfig::getLastChecked() const 346 { 347 sal_Int64 nValue = 0; 348 349 // getByName is defined as non const in XNameAccess 350 const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( LAST_CHECK ) ) >>= nValue; 351 352 return nValue; 353 } 354 355 //------------------------------------------------------------------------------ 356 357 sal_Int64 358 UpdateCheckConfig::getCheckInterval() const 359 { 360 sal_Int64 nValue = 0; 361 362 // getByName is defined as non const in XNameAccess 363 const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( CHECK_INTERVAL ) ) >>= nValue; 364 365 return nValue; 366 } 367 368 //------------------------------------------------------------------------------ 369 370 rtl::OUString 371 UpdateCheckConfig::getLocalFileName() const 372 { 373 rtl::OUString aName = UNISTRING(LOCAL_FILE); 374 rtl::OUString aRet; 375 376 if( m_xContainer->hasByName(aName) ) 377 m_xContainer->getByName(aName) >>= aRet; 378 379 return aRet; 380 } 381 382 //------------------------------------------------------------------------------ 383 384 rtl::OUString 385 UpdateCheckConfig::getDownloadDestination() const 386 { 387 rtl::OUString aName = UNISTRING(DOWNLOAD_DESTINATION); 388 rtl::OUString aRet; 389 390 const_cast <UpdateCheckConfig *> (this)->getByName(aName) >>= aRet; 391 392 return aRet; 393 } 394 395 //------------------------------------------------------------------------------ 396 397 void 398 UpdateCheckConfig::storeLocalFileName(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize) 399 { 400 const sal_uInt8 nItems = 2; 401 const rtl::OUString aNameList[nItems] = { UNISTRING(LOCAL_FILE), UNISTRING(DOWNLOAD_SIZE) }; 402 const uno::Any aValueList[nItems] = { uno::makeAny(rLocalFileName), uno::makeAny(nFileSize) }; 403 404 for( sal_uInt8 i=0; i < nItems; ++i ) 405 { 406 if( m_xContainer->hasByName(aNameList[i]) ) 407 m_xContainer->replaceByName(aNameList[i], aValueList[i]); 408 else 409 m_xContainer->insertByName(aNameList[i], aValueList[i]); 410 } 411 412 commitChanges(); 413 } 414 415 //------------------------------------------------------------------------------ 416 417 void 418 UpdateCheckConfig::clearLocalFileName() 419 { 420 const sal_uInt8 nItems = 2; 421 const rtl::OUString aNameList[nItems] = { UNISTRING(LOCAL_FILE), UNISTRING(DOWNLOAD_SIZE) }; 422 423 for( sal_uInt8 i=0; i < nItems; ++i ) 424 { 425 if( m_xContainer->hasByName(aNameList[i]) ) 426 m_xContainer->removeByName(aNameList[i]); 427 } 428 429 commitChanges(); 430 } 431 432 //------------------------------------------------------------------------------ 433 434 void 435 UpdateCheckConfig::storeDownloadPaused(bool paused) 436 { 437 replaceByName(UNISTRING(DOWNLOAD_PAUSED) , uno::makeAny(paused)); 438 commitChanges(); 439 } 440 441 //------------------------------------------------------------------------------ 442 443 void 444 UpdateCheckConfig::updateLastChecked() 445 { 446 TimeValue systime; 447 osl_getSystemTime(&systime); 448 449 sal_Int64 lastCheck = systime.Seconds; 450 451 replaceByName(UNISTRING(LAST_CHECK), uno::makeAny(lastCheck)); 452 } 453 454 //------------------------------------------------------------------------------ 455 456 void 457 UpdateCheckConfig::storeUpdateFound( const UpdateInfo& rInfo, const rtl::OUString& aCurrentBuild) 458 459 { 460 bool autoDownloadEnabled = isAutoDownloadEnabled(); 461 462 uno::Any aValues[nUpdateEntryProperties] = 463 { 464 uno::makeAny(rInfo.Version), 465 uno::makeAny(rInfo.BuildId), 466 uno::makeAny(rInfo.Description), 467 uno::makeAny(rInfo.Sources[0].URL), 468 uno::makeAny(rInfo.Sources[0].IsDirect ? sal_True : sal_False), 469 uno::makeAny(getReleaseNote(rInfo, 1, autoDownloadEnabled) ), 470 uno::makeAny(getReleaseNote(rInfo, 2, autoDownloadEnabled) ), 471 uno::makeAny(getReleaseNote(rInfo, 3, autoDownloadEnabled) ), 472 uno::makeAny(getReleaseNote(rInfo, 4, autoDownloadEnabled) ), 473 uno::makeAny(getReleaseNote(rInfo, 5, autoDownloadEnabled) ), 474 uno::makeAny(aCurrentBuild) 475 }; 476 477 rtl::OUString aName; 478 for( sal_uInt32 n=0; n < nUpdateEntryProperties; ++n ) 479 { 480 aName = rtl::OUString::createFromAscii(aUpdateEntryProperties[n]); 481 482 if( m_xContainer->hasByName(aName) ) 483 m_xContainer->replaceByName(aName, aValues[n]); 484 else 485 m_xContainer->insertByName(aName,aValues[n]); 486 } 487 488 commitChanges(); 489 } 490 491 //------------------------------------------------------------------------------ 492 493 void 494 UpdateCheckConfig::clearUpdateFound() 495 { 496 rtl::OUString aName; 497 498 for( sal_uInt32 n=0; n < nUpdateEntryProperties; ++n ) 499 { 500 aName = rtl::OUString::createFromAscii(aUpdateEntryProperties[n]); 501 502 try { 503 if( m_xContainer->hasByName(aName) ) 504 m_xContainer->removeByName(aName); 505 } catch(const lang::WrappedTargetException& ) { 506 // Can not remove value, probably in share layer 507 OSL_ASSERT(false); 508 m_xContainer->replaceByName(aName, uno::makeAny(rtl::OUString())); 509 } 510 } 511 512 /* As we have removed UpdateVersionFound from the shared configuration 513 * existing entries in the user layer do not have a oor operation and 514 * thus are completly ignored (which also means they can not be removed). 515 */ 516 517 commitChanges(); 518 } 519 520 //------------------------------------------------------------------------------ 521 522 uno::Sequence< rtl::OUString > 523 UpdateCheckConfig::getServiceNames() 524 { 525 uno::Sequence< rtl::OUString > aServiceList(1); 526 aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheckConfig"); 527 return aServiceList; 528 } 529 530 //------------------------------------------------------------------------------ 531 532 rtl::OUString 533 UpdateCheckConfig::getImplName() 534 { 535 return UNISTRING( "vnd.sun.UpdateCheckConfig"); 536 } 537 538 //------------------------------------------------------------------------------ 539 540 uno::Type SAL_CALL 541 UpdateCheckConfig::getElementType() throw (uno::RuntimeException) 542 { 543 return m_xContainer->getElementType(); 544 } 545 546 //------------------------------------------------------------------------------ 547 548 sal_Bool SAL_CALL 549 UpdateCheckConfig::hasElements() throw (uno::RuntimeException) 550 { 551 return m_xContainer->hasElements(); 552 } 553 554 //------------------------------------------------------------------------------ 555 556 uno::Any SAL_CALL 557 UpdateCheckConfig::getByName( const ::rtl::OUString& aName ) 558 throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 559 { 560 uno::Any aValue = m_xContainer->getByName( aName ); 561 562 // Provide dynamic default value 563 if( aName.equalsAscii(DOWNLOAD_DESTINATION) ) 564 { 565 rtl::OUString aStr; 566 aValue >>= aStr; 567 568 if( aStr.getLength() == 0 ) 569 aValue = uno::makeAny(getDesktopDirectory()); 570 } 571 572 return aValue; 573 } 574 575 //------------------------------------------------------------------------------ 576 577 uno::Sequence< ::rtl::OUString > SAL_CALL 578 UpdateCheckConfig::getElementNames( ) throw (uno::RuntimeException) 579 { 580 return m_xContainer->getElementNames(); 581 } 582 583 //------------------------------------------------------------------------------ 584 585 sal_Bool SAL_CALL 586 UpdateCheckConfig::hasByName( const ::rtl::OUString& aName ) throw (uno::RuntimeException) 587 { 588 return m_xContainer->hasByName( aName ); 589 } 590 591 //------------------------------------------------------------------------------ 592 593 void SAL_CALL 594 UpdateCheckConfig::replaceByName( const ::rtl::OUString& aName, const uno::Any& aElement ) 595 throw (lang::IllegalArgumentException, container::NoSuchElementException, 596 lang::WrappedTargetException, uno::RuntimeException) 597 { 598 return m_xContainer->replaceByName( aName, aElement ); 599 } 600 601 //------------------------------------------------------------------------------ 602 // XChangesBatch 603 604 void SAL_CALL 605 UpdateCheckConfig::commitChanges() 606 throw (lang::WrappedTargetException, uno::RuntimeException) 607 { 608 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY); 609 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() ) 610 { 611 util::ChangesSet aChangesSet = xChangesBatch->getPendingChanges(); 612 xChangesBatch->commitChanges(); 613 614 if( m_rListener.is() ) 615 { 616 const sal_Int32 nChanges = aChangesSet.getLength(); 617 rtl::OUString aString; 618 619 for( sal_Int32 i=0; i<nChanges; ++i ) 620 { 621 aChangesSet[i].Accessor >>= aString; 622 623 // FIXME: use non IgnoreAsciiCase version as soon as it becomes available 624 if( aString.endsWithIgnoreAsciiCaseAsciiL(AUTOCHECK_ENABLED "']", sizeof(AUTOCHECK_ENABLED)+1) ) 625 { 626 sal_Bool bEnabled = sal_False; 627 aChangesSet[i].Element >>= bEnabled; 628 m_rListener->autoCheckStatusChanged(sal_True == bEnabled); 629 } 630 // FIXME: use non IgnoreAsciiCase version as soon as it becomes available 631 else if( aString.endsWithIgnoreAsciiCaseAsciiL(CHECK_INTERVAL "']", sizeof(CHECK_INTERVAL)+1) ) 632 { 633 m_rListener->autoCheckIntervalChanged(); 634 } 635 } 636 } 637 } 638 639 xChangesBatch = uno::Reference< util::XChangesBatch > ( m_xAvailableUpdates, uno::UNO_QUERY ); 640 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() ) 641 { 642 util::ChangesSet aChangesSet = xChangesBatch->getPendingChanges(); 643 xChangesBatch->commitChanges(); 644 } 645 xChangesBatch = uno::Reference< util::XChangesBatch > ( m_xIgnoredUpdates, uno::UNO_QUERY ); 646 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() ) 647 { 648 util::ChangesSet aChangesSet = xChangesBatch->getPendingChanges(); 649 xChangesBatch->commitChanges(); 650 } 651 } 652 653 //------------------------------------------------------------------------------ 654 655 sal_Bool SAL_CALL 656 UpdateCheckConfig::hasPendingChanges( ) throw (uno::RuntimeException) 657 { 658 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY); 659 if( xChangesBatch.is() ) 660 return xChangesBatch->hasPendingChanges(); 661 662 return sal_False; 663 } 664 665 //------------------------------------------------------------------------------ 666 667 uno::Sequence< util::ElementChange > SAL_CALL 668 UpdateCheckConfig::getPendingChanges( ) throw (uno::RuntimeException) 669 { 670 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY); 671 if( xChangesBatch.is() ) 672 return xChangesBatch->getPendingChanges(); 673 674 return uno::Sequence< util::ElementChange >(); 675 } 676 677 //------------------------------------------------------------------------------ 678 bool UpdateCheckConfig::storeExtensionVersion( const rtl::OUString& rExtensionName, 679 const rtl::OUString& rVersion ) 680 { 681 bool bNotify = true; 682 683 if ( m_xAvailableUpdates->hasByName( rExtensionName ) ) 684 uno::Reference< beans::XPropertySet >( m_xAvailableUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->setPropertyValue( PROPERTY_VERSION, uno::Any( rVersion ) ); 685 else 686 { 687 uno::Reference< beans::XPropertySet > elem( uno::Reference< lang::XSingleServiceFactory >( m_xAvailableUpdates, uno::UNO_QUERY_THROW )->createInstance(), uno::UNO_QUERY_THROW ); 688 elem->setPropertyValue( PROPERTY_VERSION, uno::Any( rVersion ) ); 689 m_xAvailableUpdates->insertByName( rExtensionName, uno::Any( elem ) ); 690 } 691 692 if ( m_xIgnoredUpdates->hasByName( rExtensionName ) ) 693 { 694 ::rtl::OUString aIgnoredVersion; 695 uno::Any aValue( uno::Reference< beans::XPropertySet >( m_xIgnoredUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) ); 696 aValue >>= aIgnoredVersion; 697 if ( aIgnoredVersion.getLength() == 0 ) // no version means ignore all updates 698 bNotify = false; 699 else if ( aIgnoredVersion == rVersion ) // the user wanted to ignore this update 700 bNotify = false; 701 } 702 703 commitChanges(); 704 705 return bNotify; 706 } 707 708 //------------------------------------------------------------------------------ 709 bool UpdateCheckConfig::checkExtensionVersion( const rtl::OUString& rExtensionName, 710 const rtl::OUString& rVersion ) 711 { 712 if ( m_xAvailableUpdates->hasByName( rExtensionName ) ) 713 { 714 ::rtl::OUString aStoredVersion; 715 uno::Any aValue( uno::Reference< beans::XPropertySet >( m_xAvailableUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) ); 716 aValue >>= aStoredVersion; 717 718 if ( m_xIgnoredUpdates->hasByName( rExtensionName ) ) 719 { 720 ::rtl::OUString aIgnoredVersion; 721 uno::Any aValue2( uno::Reference< beans::XPropertySet >( m_xIgnoredUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) ); 722 aValue2 >>= aIgnoredVersion; 723 if ( aIgnoredVersion.getLength() == 0 ) // no version means ignore all updates 724 return false; 725 else if ( aIgnoredVersion == aStoredVersion ) // the user wanted to ignore this update 726 return false; 727 // TODO: else delete ignored entry? 728 } 729 if ( isVersionGreater( rVersion, aStoredVersion ) ) 730 return true; 731 else 732 { 733 m_xAvailableUpdates->removeByName( rExtensionName ); 734 commitChanges(); 735 } 736 } 737 738 return false; 739 } 740 741 //------------------------------------------------------------------------------ 742 rtl::OUString UpdateCheckConfig::getSubVersion( const rtl::OUString& rVersion, 743 sal_Int32 *nIndex ) 744 { 745 while ( *nIndex < rVersion.getLength() && rVersion[*nIndex] == '0') 746 { 747 ++*nIndex; 748 } 749 750 return rVersion.getToken( 0, '.', *nIndex ); 751 } 752 753 //------------------------------------------------------------------------------ 754 // checks if the second version string is greater than the first one 755 756 bool UpdateCheckConfig::isVersionGreater( const rtl::OUString& rVersion1, 757 const rtl::OUString& rVersion2 ) 758 { 759 for ( sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0; ) 760 { 761 ::rtl::OUString sSub1( getSubVersion( rVersion1, &i1 ) ); 762 ::rtl::OUString sSub2( getSubVersion( rVersion2, &i2 ) ); 763 764 if ( sSub1.getLength() < sSub2.getLength() ) { 765 return true; 766 } else if ( sSub1.getLength() > sSub2.getLength() ) { 767 return false; 768 } else if ( sSub1 < sSub2 ) { 769 return true; 770 } else if ( sSub1 > sSub2 ) { 771 return false; 772 } 773 } 774 return false; 775 } 776 777 //------------------------------------------------------------------------------ 778 //------------------------------------------------------------------------------ 779 //------------------------------------------------------------------------------ 780 781 rtl::OUString SAL_CALL 782 UpdateCheckConfig::getImplementationName() throw (uno::RuntimeException) 783 { 784 return getImplName(); 785 } 786 787 //------------------------------------------------------------------------------ 788 789 sal_Bool SAL_CALL 790 UpdateCheckConfig::supportsService(rtl::OUString const & serviceName) 791 throw (uno::RuntimeException) 792 { 793 uno::Sequence< rtl::OUString > aServiceNameList = getServiceNames(); 794 795 for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ ) 796 if( aServiceNameList[n].equals(serviceName) ) 797 return sal_True; 798 799 return sal_False; 800 } 801 802 //------------------------------------------------------------------------------ 803 804 uno::Sequence< rtl::OUString > SAL_CALL 805 UpdateCheckConfig::getSupportedServiceNames() throw (uno::RuntimeException) 806 { 807 return getServiceNames(); 808 } 809 810 811