/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_extensions.hxx" #include #include "updateprotocol.hxx" #include "updatecheckconfig.hxx" #ifndef _COM_SUN_STAR_DEPLOYMENT_UPDATEINFORMATINENTRY_HPP_ #include #endif #include #include #include #include #include #include #include #include namespace css = com::sun::star ; namespace container = css::container ; namespace deployment = css::deployment ; namespace lang = css::lang ; namespace uno = css::uno ; namespace task = css::task ; namespace xml = css::xml ; #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) //------------------------------------------------------------------------------ static bool getBootstrapData( uno::Sequence< ::rtl::OUString > & rRepositoryList, ::rtl::OUString & rBuildID, ::rtl::OUString & rInstallSetID) { rBuildID = UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":ProductBuildid}" ); rtl::Bootstrap::expandMacros( rBuildID ); if ( ! rBuildID.getLength() ) return false; rInstallSetID = UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateID}" ); rtl::Bootstrap::expandMacros( rInstallSetID ); if ( ! rInstallSetID.getLength() ) return false; rtl::OUString aValue( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateURL}" ) ); rtl::Bootstrap::expandMacros( aValue ); if( aValue.getLength() > 0 ) { rRepositoryList.realloc(1); rRepositoryList[0] = aValue; } return true; } //------------------------------------------------------------------------------ // Returns 'true' if successfully connected to the update server bool checkForUpdates( UpdateInfo& o_rUpdateInfo, uno::Reference< uno::XComponentContext > const & rxContext, uno::Reference< task::XInteractionHandler > const & rxInteractionHandler, const uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider) { OSL_TRACE("checking for updates ..\n"); ::rtl::OUString myArch; ::rtl::OUString myOS; rtl::Bootstrap::get(UNISTRING("_OS"), myOS); rtl::Bootstrap::get(UNISTRING("_ARCH"), myArch); uno::Sequence< ::rtl::OUString > aRepositoryList; ::rtl::OUString aBuildID; ::rtl::OUString aInstallSetID; if( ! ( getBootstrapData(aRepositoryList, aBuildID, aInstallSetID) && (aRepositoryList.getLength() > 0) ) ) return false; if( !rxContext.is() ) throw uno::RuntimeException( UNISTRING( "checkForUpdates: empty component context" ), uno::Reference< uno::XInterface >() ); OSL_ASSERT( rxContext->getServiceManager().is() ); // XPath implementation uno::Reference< xml::xpath::XXPathAPI > xXPath( rxContext->getServiceManager()->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), rxContext ), uno::UNO_QUERY_THROW); xXPath->registerNS( UNISTRING("inst"), UNISTRING("http://installation.openoffice.org/description") ); if( rxInteractionHandler.is() ) rUpdateInfoProvider->setInteractionHandler(rxInteractionHandler); try { uno::Reference< container::XEnumeration > aUpdateInfoEnumeration = rUpdateInfoProvider->getUpdateInformationEnumeration( aRepositoryList, aInstallSetID ); if ( !aUpdateInfoEnumeration.is() ) return false; // something went wrong .. rtl::OUStringBuffer aBuffer; aBuffer.appendAscii("/child::inst:description[inst:os=\'"); aBuffer.append( myOS ); aBuffer.appendAscii("\' and inst:arch=\'"); aBuffer.append( myArch ); aBuffer.appendAscii("\' and inst:buildid>"); aBuffer.append( aBuildID ); aBuffer.appendAscii("]"); rtl::OUString aXPathExpression = aBuffer.makeStringAndClear(); while( aUpdateInfoEnumeration->hasMoreElements() ) { deployment::UpdateInformationEntry aEntry; if( aUpdateInfoEnumeration->nextElement() >>= aEntry ) { uno::Reference< xml::dom::XNode > xNode( aEntry.UpdateDocument.get() ); uno::Reference< xml::dom::XNodeList > xNodeList; try { xNodeList = xXPath->selectNodeList(xNode, aXPathExpression + UNISTRING("/inst:update/attribute::src")); } catch (css::xml::xpath::XPathException &) { // ignore } /* o_rUpdateInfo.Sources.push_back( DownloadSource(true, UNISTRING("http://openoffice.bouncer.osuosl.org/?product=OpenOffice.org&os=solarissparcwjre&lang=en-US&version=2.2.1") ) ); */ sal_Int32 i, imax = xNodeList->getLength(); for( i = 0; i < imax; ++i ) { uno::Reference< xml::dom::XNode > xNode2( xNodeList->item(i) ); if( xNode2.is() ) { uno::Reference< xml::dom::XElement > xParent(xNode2->getParentNode(), uno::UNO_QUERY_THROW); rtl::OUString aType = xParent->getAttribute(UNISTRING("type")); bool bIsDirect = ( sal_False == aType.equalsIgnoreAsciiCaseAscii("text/html") ); o_rUpdateInfo.Sources.push_back( DownloadSource(bIsDirect, xNode2->getNodeValue()) ); } } uno::Reference< xml::dom::XNode > xNode2; try { xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression + UNISTRING("/inst:version/text()")); } catch (css::xml::xpath::XPathException &) { // ignore } if( xNode2.is() ) o_rUpdateInfo.Version = xNode2->getNodeValue(); try { xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression + UNISTRING("/inst:buildid/text()")); } catch (css::xml::xpath::XPathException &) { // ignore } if( xNode2.is() ) o_rUpdateInfo.BuildId = xNode2->getNodeValue(); o_rUpdateInfo.Description = aEntry.Description; // Release Notes try { xNodeList = xXPath->selectNodeList(xNode, aXPathExpression + UNISTRING("/inst:relnote")); } catch (css::xml::xpath::XPathException &) { // ignore } imax = xNodeList->getLength(); for( i = 0; i < imax; ++i ) { uno::Reference< xml::dom::XElement > xRelNote(xNodeList->item(i), uno::UNO_QUERY); if( xRelNote.is() ) { sal_Int32 pos = xRelNote->getAttribute(UNISTRING("pos")).toInt32(); ReleaseNote aRelNote((sal_uInt8) pos, xRelNote->getAttribute(UNISTRING("src"))); if( xRelNote->hasAttribute(UNISTRING("src2")) ) { pos = xRelNote->getAttribute(UNISTRING("pos2")).toInt32(); aRelNote.Pos2 = (sal_Int8) pos; aRelNote.URL2 = xRelNote->getAttribute(UNISTRING("src2")); } o_rUpdateInfo.ReleaseNotes.push_back(aRelNote); } } /* o_rUpdateInfo.ReleaseNotes.push_back( ReleaseNote(1, UNISTRING("http://qa.openoffice.org/tests/online_update_test.html")) ); */ if( o_rUpdateInfo.Sources.size() > 0 ) return true; } } } catch( ... ) { return false; } return true; } //------------------------------------------------------------------------------ bool storeExtensionUpdateInfos( const uno::Reference< uno::XComponentContext > & rxContext, const uno::Sequence< uno::Sequence< rtl::OUString > > &rUpdateInfos ) { bool bNotify = false; if ( rUpdateInfos.hasElements() ) { rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( rxContext ); for ( sal_Int32 i = rUpdateInfos.getLength() - 1; i >= 0; i-- ) { bNotify |= aConfig->storeExtensionVersion( rUpdateInfos[i][0], rUpdateInfos[i][1] ); } } return bNotify; } //------------------------------------------------------------------------------ // Returns 'true' if there are updates for any extension bool checkForExtensionUpdates( const uno::Reference< uno::XComponentContext > & rxContext ) { uno::Sequence< uno::Sequence< rtl::OUString > > aUpdateList; uno::Reference< deployment::XPackageInformationProvider > xInfoProvider; try { uno::Any aValue( rxContext->getValueByName( UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) ); OSL_VERIFY( aValue >>= xInfoProvider ); } catch( const uno::Exception& ) { OSL_ENSURE( false, "checkForExtensionUpdates: could not create the PackageInformationProvider!" ); } if ( !xInfoProvider.is() ) return false; aUpdateList = xInfoProvider->isUpdateAvailable( ::rtl::OUString() ); bool bNotify = storeExtensionUpdateInfos( rxContext, aUpdateList ); return bNotify; } //------------------------------------------------------------------------------ // Returns 'true' if there are any pending updates for any extension (offline check) bool checkForPendingUpdates( const uno::Reference< uno::XComponentContext > & rxContext ) { uno::Sequence< uno::Sequence< rtl::OUString > > aExtensionList; uno::Reference< deployment::XPackageInformationProvider > xInfoProvider; try { uno::Any aValue( rxContext->getValueByName( UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) ); OSL_VERIFY( aValue >>= xInfoProvider ); } catch( const uno::Exception& ) { OSL_ENSURE( false, "checkForExtensionUpdates: could not create the PackageInformationProvider!" ); } if ( !xInfoProvider.is() ) return false; bool bPendingUpdateFound = false; aExtensionList = xInfoProvider->getExtensionList(); if ( aExtensionList.hasElements() ) { rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( rxContext ); for ( sal_Int32 i = aExtensionList.getLength() - 1; i >= 0; i-- ) { bPendingUpdateFound = aConfig->checkExtensionVersion( aExtensionList[i][0], aExtensionList[i][1] ); if ( bPendingUpdateFound ) break; } } return bPendingUpdateFound; }