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 #include <com/sun/star/xml/xpath/XXPathAPI.hpp> 31 32 #include "updateprotocol.hxx" 33 #include "updatecheckconfig.hxx" 34 35 #ifndef _COM_SUN_STAR_DEPLOYMENT_UPDATEINFORMATINENTRY_HPP_ 36 #include <com/sun/star/deployment/UpdateInformationEntry.hpp> 37 #endif 38 #include <com/sun/star/deployment/XPackageInformationProvider.hpp> 39 40 41 #include <rtl/ref.hxx> 42 #include <rtl/uri.hxx> 43 #include <rtl/strbuf.hxx> 44 #include <rtl/ustrbuf.hxx> 45 #include <rtl/bootstrap.hxx> 46 #include <osl/process.h> 47 48 #include <cppuhelper/implbase1.hxx> 49 50 namespace css = com::sun::star ; 51 namespace container = css::container ; 52 namespace deployment = css::deployment ; 53 namespace lang = css::lang ; 54 namespace uno = css::uno ; 55 namespace task = css::task ; 56 namespace xml = css::xml ; 57 58 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) 59 60 //------------------------------------------------------------------------------ 61 62 static bool 63 getBootstrapData( 64 uno::Sequence< ::rtl::OUString > & rRepositoryList, 65 ::rtl::OUString & rBuildID, 66 ::rtl::OUString & rInstallSetID) 67 { 68 rBuildID = UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":ProductBuildid}" ); 69 rtl::Bootstrap::expandMacros( rBuildID ); 70 if ( ! rBuildID.getLength() ) 71 return false; 72 73 rInstallSetID = UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateID}" ); 74 rtl::Bootstrap::expandMacros( rInstallSetID ); 75 if ( ! rInstallSetID.getLength() ) 76 return false; 77 78 rtl::OUString aValue( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateURL}" ) ); 79 rtl::Bootstrap::expandMacros( aValue ); 80 81 if( aValue.getLength() > 0 ) 82 { 83 rRepositoryList.realloc(1); 84 rRepositoryList[0] = aValue; 85 } 86 87 return true; 88 } 89 90 //------------------------------------------------------------------------------ 91 92 // Returns 'true' if successfully connected to the update server 93 bool 94 checkForUpdates( 95 UpdateInfo& o_rUpdateInfo, 96 uno::Reference< uno::XComponentContext > const & rxContext, 97 uno::Reference< task::XInteractionHandler > const & rxInteractionHandler, 98 const uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider) 99 { 100 OSL_TRACE("checking for updates ..\n"); 101 102 ::rtl::OUString myArch; 103 ::rtl::OUString myOS; 104 105 rtl::Bootstrap::get(UNISTRING("_OS"), myOS); 106 rtl::Bootstrap::get(UNISTRING("_ARCH"), myArch); 107 108 uno::Sequence< ::rtl::OUString > aRepositoryList; 109 ::rtl::OUString aBuildID; 110 ::rtl::OUString aInstallSetID; 111 112 if( ! ( getBootstrapData(aRepositoryList, aBuildID, aInstallSetID) && (aRepositoryList.getLength() > 0) ) ) 113 return false; 114 115 if( !rxContext.is() ) 116 throw uno::RuntimeException( 117 UNISTRING( "checkForUpdates: empty component context" ), uno::Reference< uno::XInterface >() ); 118 119 OSL_ASSERT( rxContext->getServiceManager().is() ); 120 121 // XPath implementation 122 uno::Reference< xml::xpath::XXPathAPI > xXPath( 123 rxContext->getServiceManager()->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), rxContext ), 124 uno::UNO_QUERY_THROW); 125 126 xXPath->registerNS( UNISTRING("inst"), UNISTRING("http://installation.openoffice.org/description") ); 127 128 if( rxInteractionHandler.is() ) 129 rUpdateInfoProvider->setInteractionHandler(rxInteractionHandler); 130 131 try 132 { 133 uno::Reference< container::XEnumeration > aUpdateInfoEnumeration = 134 rUpdateInfoProvider->getUpdateInformationEnumeration( aRepositoryList, aInstallSetID ); 135 136 if ( !aUpdateInfoEnumeration.is() ) 137 return false; // something went wrong .. 138 139 rtl::OUStringBuffer aBuffer; 140 aBuffer.appendAscii("/child::inst:description[inst:os=\'"); 141 aBuffer.append( myOS ); 142 aBuffer.appendAscii("\' and inst:arch=\'"); 143 aBuffer.append( myArch ); 144 aBuffer.appendAscii("\' and inst:buildid>"); 145 aBuffer.append( aBuildID ); 146 aBuffer.appendAscii("]"); 147 148 rtl::OUString aXPathExpression = aBuffer.makeStringAndClear(); 149 150 while( aUpdateInfoEnumeration->hasMoreElements() ) 151 { 152 deployment::UpdateInformationEntry aEntry; 153 154 if( aUpdateInfoEnumeration->nextElement() >>= aEntry ) 155 { 156 uno::Reference< xml::dom::XNode > xNode( aEntry.UpdateDocument.get() ); 157 uno::Reference< xml::dom::XNodeList > xNodeList; 158 try { 159 xNodeList = xXPath->selectNodeList(xNode, aXPathExpression 160 + UNISTRING("/inst:update/attribute::src")); 161 } catch (css::xml::xpath::XPathException &) { 162 // ignore 163 } 164 165 /* 166 o_rUpdateInfo.Sources.push_back( DownloadSource(true, 167 UNISTRING("http://openoffice.bouncer.osuosl.org/?product=OpenOffice.org&os=solarissparcwjre&lang=en-US&version=2.2.1") ) ); 168 */ 169 170 sal_Int32 i, imax = xNodeList->getLength(); 171 for( i = 0; i < imax; ++i ) 172 { 173 uno::Reference< xml::dom::XNode > xNode2( xNodeList->item(i) ); 174 175 if( xNode2.is() ) 176 { 177 uno::Reference< xml::dom::XElement > xParent(xNode2->getParentNode(), uno::UNO_QUERY_THROW); 178 rtl::OUString aType = xParent->getAttribute(UNISTRING("type")); 179 bool bIsDirect = ( sal_False == aType.equalsIgnoreAsciiCaseAscii("text/html") ); 180 181 o_rUpdateInfo.Sources.push_back( DownloadSource(bIsDirect, xNode2->getNodeValue()) ); 182 } 183 } 184 185 uno::Reference< xml::dom::XNode > xNode2; 186 try { 187 xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression 188 + UNISTRING("/inst:version/text()")); 189 } catch (css::xml::xpath::XPathException &) { 190 // ignore 191 } 192 193 if( xNode2.is() ) 194 o_rUpdateInfo.Version = xNode2->getNodeValue(); 195 196 try { 197 xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression 198 + UNISTRING("/inst:buildid/text()")); 199 } catch (css::xml::xpath::XPathException &) { 200 // ignore 201 } 202 203 if( xNode2.is() ) 204 o_rUpdateInfo.BuildId = xNode2->getNodeValue(); 205 206 o_rUpdateInfo.Description = aEntry.Description; 207 208 // Release Notes 209 try { 210 xNodeList = xXPath->selectNodeList(xNode, aXPathExpression 211 + UNISTRING("/inst:relnote")); 212 } catch (css::xml::xpath::XPathException &) { 213 // ignore 214 } 215 imax = xNodeList->getLength(); 216 for( i = 0; i < imax; ++i ) 217 { 218 uno::Reference< xml::dom::XElement > xRelNote(xNodeList->item(i), uno::UNO_QUERY); 219 if( xRelNote.is() ) 220 { 221 sal_Int32 pos = xRelNote->getAttribute(UNISTRING("pos")).toInt32(); 222 223 ReleaseNote aRelNote((sal_uInt8) pos, xRelNote->getAttribute(UNISTRING("src"))); 224 225 if( xRelNote->hasAttribute(UNISTRING("src2")) ) 226 { 227 pos = xRelNote->getAttribute(UNISTRING("pos2")).toInt32(); 228 aRelNote.Pos2 = (sal_Int8) pos; 229 aRelNote.URL2 = xRelNote->getAttribute(UNISTRING("src2")); 230 } 231 232 o_rUpdateInfo.ReleaseNotes.push_back(aRelNote); 233 } 234 } 235 /* 236 o_rUpdateInfo.ReleaseNotes.push_back( 237 ReleaseNote(1, UNISTRING("http://qa.openoffice.org/tests/online_update_test.html")) 238 ); 239 */ 240 241 if( o_rUpdateInfo.Sources.size() > 0 ) 242 return true; 243 } 244 } 245 } 246 catch( ... ) 247 { 248 return false; 249 } 250 251 return true; 252 } 253 254 //------------------------------------------------------------------------------ 255 bool storeExtensionUpdateInfos( const uno::Reference< uno::XComponentContext > & rxContext, 256 const uno::Sequence< uno::Sequence< rtl::OUString > > &rUpdateInfos ) 257 { 258 bool bNotify = false; 259 260 if ( rUpdateInfos.hasElements() ) 261 { 262 rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( rxContext ); 263 264 for ( sal_Int32 i = rUpdateInfos.getLength() - 1; i >= 0; i-- ) 265 { 266 bNotify |= aConfig->storeExtensionVersion( rUpdateInfos[i][0], rUpdateInfos[i][1] ); 267 } 268 } 269 return bNotify; 270 } 271 272 //------------------------------------------------------------------------------ 273 // Returns 'true' if there are updates for any extension 274 275 bool checkForExtensionUpdates( const uno::Reference< uno::XComponentContext > & rxContext ) 276 { 277 uno::Sequence< uno::Sequence< rtl::OUString > > aUpdateList; 278 279 uno::Reference< deployment::XPackageInformationProvider > xInfoProvider; 280 try 281 { 282 uno::Any aValue( rxContext->getValueByName( 283 UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) ); 284 OSL_VERIFY( aValue >>= xInfoProvider ); 285 } 286 catch( const uno::Exception& ) 287 { 288 OSL_ENSURE( false, "checkForExtensionUpdates: could not create the PackageInformationProvider!" ); 289 } 290 291 if ( !xInfoProvider.is() ) return false; 292 293 aUpdateList = xInfoProvider->isUpdateAvailable( ::rtl::OUString() ); 294 bool bNotify = storeExtensionUpdateInfos( rxContext, aUpdateList ); 295 296 return bNotify; 297 } 298 299 //------------------------------------------------------------------------------ 300 // Returns 'true' if there are any pending updates for any extension (offline check) 301 302 bool checkForPendingUpdates( const uno::Reference< uno::XComponentContext > & rxContext ) 303 { 304 uno::Sequence< uno::Sequence< rtl::OUString > > aExtensionList; 305 uno::Reference< deployment::XPackageInformationProvider > xInfoProvider; 306 try 307 { 308 uno::Any aValue( rxContext->getValueByName( 309 UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) ); 310 OSL_VERIFY( aValue >>= xInfoProvider ); 311 } 312 catch( const uno::Exception& ) 313 { 314 OSL_ENSURE( false, "checkForExtensionUpdates: could not create the PackageInformationProvider!" ); 315 } 316 317 if ( !xInfoProvider.is() ) return false; 318 319 bool bPendingUpdateFound = false; 320 321 aExtensionList = xInfoProvider->getExtensionList(); 322 if ( aExtensionList.hasElements() ) 323 { 324 rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( rxContext ); 325 326 for ( sal_Int32 i = aExtensionList.getLength() - 1; i >= 0; i-- ) 327 { 328 bPendingUpdateFound = aConfig->checkExtensionVersion( aExtensionList[i][0], aExtensionList[i][1] ); 329 if ( bPendingUpdateFound ) 330 break; 331 } 332 } 333 334 return bPendingUpdateFound; 335 } 336