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