/** * Gets the package_update.xml from an update server. * * @param \wcf\data\package\update\server\PackageUpdateServer $updateServer * @param boolean $forceHTTP */ protected function getPackageUpdateXML(PackageUpdateServer $updateServer, $forceHTTP = false) { $settings = array(); $authData = $updateServer->getAuthData(); if ($authData) { $settings['auth'] = $authData; } $secureConnection = $updateServer->attemptSecureConnection(); if ($secureConnection && !$forceHTTP) { $settings['timeout'] = 5; } $request = new HTTPRequest($updateServer->getListURL($forceHTTP), $settings); if ($updateServer->apiVersion == '2.1') { $metaData = $updateServer->getMetaData(); if (isset($metaData['list']['etag'])) { $request->addHeader('if-none-match', $metaData['list']['etag']); } if (isset($metaData['list']['lastModified'])) { $request->addHeader('if-modified-since', $metaData['list']['lastModified']); } } try { $request->execute(); $reply = $request->getReply(); } catch (HTTPUnauthorizedException $e) { throw new PackageUpdateUnauthorizedException($request, $updateServer); } catch (SystemException $e) { $reply = $request->getReply(); $statusCode = is_array($reply['statusCode']) ? reset($reply['statusCode']) : $reply['statusCode']; // status code 0 is a connection timeout if (!$statusCode && $secureConnection) { if (preg_match('~https?://(?:update|store)\\.woltlab\\.com~', $updateServer->serverURL)) { // woltlab.com servers are most likely to be available, thus we assume that SSL connections are dropped RemoteFile::disableSSL(); } // retry via http $this->getPackageUpdateXML($updateServer, true); return; } throw new SystemException(WCF::getLanguage()->get('wcf.acp.package.update.error.listNotFound') . ' (' . $statusCode . ')'); } // parse given package update xml $allNewPackages = false; if ($updateServer->apiVersion == '2.0' || $reply['statusCode'] != 304) { $allNewPackages = $this->parsePackageUpdateXML($reply['body']); } $data = array('lastUpdateTime' => TIME_NOW, 'status' => 'online', 'errorMessage' => ''); // check if server indicates support for a newer API if ($updateServer->apiVersion == '2.0' && !empty($reply['httpHeaders']['wcf-update-server-api'])) { $apiVersions = explode(' ', reset($reply['httpHeaders']['wcf-update-server-api'])); if (in_array('2.1', $apiVersions)) { $data['apiVersion'] = '2.1'; } } $metaData = array(); if ($updateServer->apiVersion == '2.1' || isset($data['apiVersion']) && $data['apiVersion'] == '2.1') { if (empty($reply['httpHeaders']['etag']) && empty($reply['httpHeaders']['last-modified'])) { throw new SystemException("Missing required HTTP headers 'etag' and 'last-modified'."); } else { if (empty($reply['httpHeaders']['wcf-update-server-ssl'])) { throw new SystemException("Missing required HTTP header 'wcf-update-server-ssl'."); } } $metaData['list'] = array(); if (!empty($reply['httpHeaders']['etag'])) { $metaData['list']['etag'] = reset($reply['httpHeaders']['etag']); } if (!empty($reply['httpHeaders']['last-modified'])) { $metaData['list']['lastModified'] = reset($reply['httpHeaders']['last-modified']); } $metaData['ssl'] = reset($reply['httpHeaders']['wcf-update-server-ssl']) == 'true' ? true : false; } $data['metaData'] = serialize($metaData); unset($request, $reply); if ($allNewPackages !== false) { // purge package list $sql = "DELETE FROM\twcf" . WCF_N . "_package_update\n\t\t\t\tWHERE\t\tpackageUpdateServerID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($updateServer->packageUpdateServerID)); // save packages if (!empty($allNewPackages)) { $this->savePackageUpdates($allNewPackages, $updateServer->packageUpdateServerID); } unset($allNewPackages); } // update server status $updateServerEditor = new PackageUpdateServerEditor($updateServer); $updateServerEditor->update($data); }