diff options
Diffstat (limited to 'indra/viewer_components/updater')
15 files changed, 0 insertions, 3198 deletions
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt deleted file mode 100644 index 73e18aacb3..0000000000 --- a/indra/viewer_components/updater/CMakeLists.txt +++ /dev/null @@ -1,106 +0,0 @@ -# -*- cmake -*- - -project(updater_service) - -include(00-Common) -if(LL_TESTS) - include(LLAddBuildTest) -endif(LL_TESTS) -include(Boost) -include(CMakeCopyIfDifferent) -include(CURL) -include(LLCommon) -include(LLCoreHttp) -include(LLMessage) -include(LLPlugin) -include(LLVFS) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLCOREHTTP_INCLUDE_DIRS} - ${LLMESSAGE_INCLUDE_DIRS} - ${LLPLUGIN_INCLUDE_DIRS} - ${LLVFS_INCLUDE_DIRS} - ${CURL_INCLUDE_DIRS} - ${CMAKE_SOURCE_DIR}/newview - ) -include_directories(SYSTEM - ${LLCOMMON_SYSTEM_INCLUDE_DIRS} - ) - -set(updater_service_SOURCE_FILES - llupdaterservice.cpp - llupdatechecker.cpp - llupdatedownloader.cpp - llupdateinstaller.cpp - ) - -set(updater_service_HEADER_FILES - llupdaterservice.h - llupdatechecker.h - llupdatedownloader.h - llupdateinstaller.h - ) - -set_source_files_properties(${updater_service_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -set_source_files_properties( - llupdaterservice.cpp - PROPERTIES - COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake - ) - -list(APPEND - updater_service_SOURCE_FILES - ${updater_service_HEADER_FILES} - ) - -add_library(llupdaterservice - ${updater_service_SOURCE_FILES} - ) - -target_link_libraries(llupdaterservice - ${LLCOMMON_LIBRARIES} - ${LLMESSAGE_LIBRARIES} - ${LLCOREHTTP_LIBRARIES} - ${LLPLUGIN_LIBRARIES} - ${LLVFS_LIBRARIES} - ) - -if(LL_TESTS) -if (NOT LINUX) - SET(llupdater_service_TEST_SOURCE_FILES - llupdaterservice.cpp - ) - -set(test_libs - ${LLCOMMON_LIBRARIES} - ${BOOST_COROUTINE_LIBRARY} - ${BOOST_CONTEXT_LIBRARY} - ${BOOST_THREAD_LIBRARY} - ${BOOST_SYSTEM_LIBRARY}) - -set_source_files_properties( - llupdaterservice.cpp - PROPERTIES - LL_TEST_ADDITIONAL_LIBRARIES ${test_libs} -# *NOTE:Mani - I was trying to use the preprocessor seam to mock out -# llifstream (and other) llcommon classes. It didn't work -# because of the windows declspec(dllimport)attribute. -# LL_TEST_ADDITIONAL_CFLAGS "-Dllifstream=llus_mock_llifstream" - ) - - LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}" ${test_libs}) -endif (NOT LINUX) -endif(LL_TESTS) - -set(UPDATER_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/viewer_components/updater - CACHE INTERNAL "" -) - -set(UPDATER_LIBRARIES - llupdaterservice - CACHE INTERNAL "" -) diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp deleted file mode 100644 index 1bb5e95740..0000000000 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/** - * @file llupdaterservice.cpp - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include <stdexcept> -#include <boost/format.hpp> -#include "llsd.h" -#include "llupdatechecker.h" -#include "lluri.h" -#include "llcorehttputil.h" -#if LL_DARWIN -#include <CoreServices/CoreServices.h> -#endif - -#if LL_WINDOWS -#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally -#endif - - -class LLUpdateChecker::CheckError: - public std::runtime_error -{ -public: - CheckError(const char * message): - std::runtime_error(message) - { - ; // No op. - } -}; - - -// LLUpdateChecker -//----------------------------------------------------------------------------- -LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client): - mImplementation(new LLUpdateChecker::Implementation(client)) -{ - ; // No op. -} - -void LLUpdateChecker::checkVersion(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test) -{ - mImplementation->checkVersion(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test); -} - - -// LLUpdateChecker::Implementation -//----------------------------------------------------------------------------- -const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1"; - - -LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client): - mClient(client), - mInProgress(false), - mProtocol(sProtocolVersion) -{ - ; // No op. -} - - -LLUpdateChecker::Implementation::~Implementation() -{ - ; // No op. -} - - -void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test) -{ - if (!mInProgress) - { - mInProgress = true; - - mUrlBase = urlBase; - mChannel = channel; - mVersion = version; - mPlatform = platform; - mPlatformVersion = platform_version; - memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); - mWillingToTest = willing_to_test; - - mProtocol = sProtocolVersion; - - std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test); - LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; - - LLCoros::instance().launch("LLUpdateChecker::Implementation::checkVersionCoro", - boost::bind(&Implementation::checkVersionCoro, this, checkUrl)); - - } - else - { - LL_WARNS("UpdaterService") << "attempting to restart a check when one is in progress; ignored" << LL_ENDL; - } -} - -void LLUpdateChecker::Implementation::checkVersionCoro(std::string url) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("checkVersionCoro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - LL_INFOS("checkVersionCoro") << "Getting update information from " << url << LL_ENDL; - - LLSD result = httpAdapter->getAndSuspend(httpRequest, url); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - mInProgress = false; - - if (status != LLCore::HttpStatus(HTTP_OK)) - { - std::string server_error; - if (result.has("error_code")) - { - server_error += result["error_code"].asString(); - } - if (result.has("error_text")) - { - server_error += server_error.empty() ? "" : ": "; - server_error += result["error_text"].asString(); - } - - LL_WARNS("UpdaterService") << "response error " << status.getStatus() - << " " << status.toString() - << " (" << server_error << ")" - << LL_ENDL; - mClient.error(status.toString()); - return; - } - - result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); - mClient.response(result); -} - -std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test) -{ - LLSD path; - path.append(mProtocol); - path.append(channel); - path.append(version); - path.append(platform); - path.append(platform_version); - path.append(willing_to_test ? "testok" : "testno"); - path.append((char*)uniqueid); - return LLURI::buildHTTP(urlBase, path).asString(); -} diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h deleted file mode 100644 index d10ea4cf42..0000000000 --- a/indra/viewer_components/updater/llupdatechecker.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @file llupdatechecker.h - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_UPDATERCHECKER_H -#define LL_UPDATERCHECKER_H - - -#include <boost/shared_ptr.hpp> - -#include "llmd5.h" -#include "lleventcoro.h" -#include "llcoros.h" - -// -// Implements asynchronous checking for updates. -// -class LLUpdateChecker { -public: - // - // The client interface implemented by a requestor checking for an update. - // - class Client - { - public: - // An error occurred while checking for an update. - virtual void error(std::string const & message) = 0; - - // A successful response was received from the viewer version manager - virtual void response(LLSD const & content) = 0; - }; - - // An exception that may be raised on check errors. - class CheckError; - - LLUpdateChecker(Client & client); - - // Check status of current app on the given host for the channel and version provided. - void checkVersion(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test); - -private: - class Implementation - { - public: - typedef boost::shared_ptr<Implementation> ptr_t; - - Implementation(Client & client); - ~Implementation(); - void checkVersion(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test - ); - - - private: - static const char * sLegacyProtocolVersion; - static const char * sProtocolVersion; - const char* mProtocol; - - Client & mClient; - bool mInProgress; - std::string mVersion; - std::string mUrlBase; - std::string mChannel; - std::string mPlatform; - std::string mPlatformVersion; - unsigned char mUniqueId[MD5HEX_STR_SIZE]; - bool mWillingToTest; - - std::string buildUrl(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test); - - void checkVersionCoro(std::string url); - - LOG_CLASS(LLUpdateChecker::Implementation); - }; - - - Implementation::ptr_t mImplementation; - //LLPointer<Implementation> mImplementation; -}; - -#endif diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp deleted file mode 100644 index 04e0395c50..0000000000 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/** - * @file llupdatedownloader.cpp - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llupdatedownloader.h" -#include "httpcommon.h" -#include "llexception.h" -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> -#include <curl/curl.h> -#include "lldir.h" -#include "llevents.h" -#include "llfile.h" -#include "llmd5.h" -#include "llsd.h" -#include "llsdserialize.h" -#include "llthread.h" -#include "llupdaterservice.h" - -class LLUpdateDownloader::Implementation: - public LLThread -{ -public: - Implementation(LLUpdateDownloader::Client & client); - ~Implementation(); - void cancel(void); - void download(LLURI const & uri, - std::string const & hash, - std::string const & updateChannel, - std::string const & updateVersion, - std::string const & info_url, - bool required); - bool isDownloading(void); - size_t onHeader(void * header, size_t size); - size_t onBody(void * header, size_t size); - int onProgress(curl_off_t downloadSize, curl_off_t bytesDownloaded); - void resume(void); - void setBandwidthLimit(U64 bytesPerSecond); - -private: - curl_off_t mBandwidthLimit; - bool mCancelled; - LLUpdateDownloader::Client & mClient; - LLCore::LLHttp::CURL_ptr mCurl; - LLSD mDownloadData; - llofstream mDownloadStream; - unsigned char mDownloadPercent; - std::string mDownloadRecordPath; - curl_slist * mHeaderList; - - void initializeCurlGet(std::string const & url, bool processHeader); - void resumeDownloading(size_t startByte); - void run(void); - void startDownloading(LLURI const & uri, std::string const & hash); - void throwOnCurlError(CURLcode code); - bool validateDownload(const std::string& filePath); - bool validateOrRemove(const std::string& filePath); - - LOG_CLASS(LLUpdateDownloader::Implementation); -}; - - -namespace { - class DownloadError: - public LLException - { - public: - DownloadError(const char * message): - LLException(message) - { - ; // No op. - } - }; - - - const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml"; -}; - - - -// LLUpdateDownloader -//----------------------------------------------------------------------------- - - - -std::string LLUpdateDownloader::downloadMarkerPath(void) -{ - return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, gSecondLifeUpdateRecord); -} - - -LLUpdateDownloader::LLUpdateDownloader(Client & client): - mImplementation(new LLUpdateDownloader::Implementation(client)) -{ - ; // No op. -} - - -void LLUpdateDownloader::cancel(void) -{ - mImplementation->cancel(); -} - - -void LLUpdateDownloader::download(LLURI const & uri, - std::string const & hash, - std::string const & updateChannel, - std::string const & updateVersion, - std::string const & info_url, - bool required) -{ - mImplementation->download(uri, hash, updateChannel, updateVersion, info_url, required); -} - - -bool LLUpdateDownloader::isDownloading(void) -{ - return mImplementation->isDownloading(); -} - - -void LLUpdateDownloader::resume(void) -{ - mImplementation->resume(); -} - - -void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) -{ - mImplementation->setBandwidthLimit(bytesPerSecond); -} - - - -// LLUpdateDownloader::Implementation -//----------------------------------------------------------------------------- - - -namespace { - size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader) - { - size_t bytes = blockSize * blocks; - return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onBody(data, bytes); - } - - - size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader) - { - size_t bytes = blockSize * blocks; - return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes); - } - - - int xferinfo_callback(void * downloader, - curl_off_t dowloadTotal, - curl_off_t downloadNow, - curl_off_t uploadTotal, - curl_off_t uploadNow) - { - return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)-> - onProgress(dowloadTotal, downloadNow); - } -} - - -LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): - LLThread("LLUpdateDownloader"), - mBandwidthLimit(0), - mCancelled(false), - mClient(client), - mCurl(), - mDownloadPercent(0), - mHeaderList(0) -{ - CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. - llverify(code == CURLE_OK); // TODO: real error handling here. -} - - -LLUpdateDownloader::Implementation::~Implementation() -{ - if(isDownloading()) - { - cancel(); - shutdown(); - } - else - { - ; // No op. - } - mCurl.reset(); -} - - -void LLUpdateDownloader::Implementation::cancel(void) -{ - mCancelled = true; -} - - -void LLUpdateDownloader::Implementation::download(LLURI const & uri, - std::string const & hash, - std::string const & updateChannel, - std::string const & updateVersion, - std::string const & info_url, - bool required) -{ - if(isDownloading()) mClient.downloadError("download in progress"); - - mDownloadRecordPath = downloadMarkerPath(); - mDownloadData = LLSD(); - mDownloadData["required"] = required; - mDownloadData["update_channel"] = updateChannel; - mDownloadData["update_version"] = updateVersion; - if (!info_url.empty()) - { - mDownloadData["info_url"] = info_url; - } - try - { - startDownloading(uri, hash); - } - catch(DownloadError const & e) - { - mClient.downloadError(e.what()); - } -} - - -bool LLUpdateDownloader::Implementation::isDownloading(void) -{ - return !isStopped(); -} - - -void LLUpdateDownloader::Implementation::resume(void) -{ - mCancelled = false; - - if(isDownloading()) - { - mClient.downloadError("download in progress"); - } - - mDownloadRecordPath = downloadMarkerPath(); - llifstream dataStream(mDownloadRecordPath.c_str()); - if(!dataStream) - { - mClient.downloadError("no download marker"); - return; - } - - LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); - - if(!mDownloadData.asBoolean()) - { - mClient.downloadError("no download information in marker"); - return; - } - - std::string filePath = mDownloadData["path"].asString(); - try - { - if(LLFile::isfile(filePath)) - { - llstat fileStatus; - LLFile::stat(filePath, &fileStatus); - if(fileStatus.st_size != mDownloadData["size"].asInteger()) - { - resumeDownloading(fileStatus.st_size); - } - else if(!validateOrRemove(filePath)) - { - download(LLURI(mDownloadData["url"].asString()), - mDownloadData["hash"].asString(), - mDownloadData["update_channel"].asString(), - mDownloadData["update_version"].asString(), - mDownloadData["info_url"].asString(), - mDownloadData["required"].asBoolean()); - } - else - { - mClient.downloadComplete(mDownloadData); - } - } - else - { - download(LLURI(mDownloadData["url"].asString()), - mDownloadData["hash"].asString(), - mDownloadData["update_channel"].asString(), - mDownloadData["update_version"].asString(), - mDownloadData["info_url"].asString(), - mDownloadData["required"].asBoolean()); - } - } - catch(DownloadError & e) - { - mClient.downloadError(e.what()); - } -} - - -void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) -{ - if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) - { - llassert(static_cast<bool>(mCurl)); - mBandwidthLimit = bytesPerSecond; - CURLcode code = curl_easy_setopt(mCurl.get(), CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); - if(code != CURLE_OK) - { - LL_WARNS("UpdaterService") << "unable to change dowload bandwidth" << LL_ENDL; - } - } - else - { - mBandwidthLimit = bytesPerSecond; - } -} - - -size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) -{ - char const * headerPtr = reinterpret_cast<const char *> (buffer); - std::string header(headerPtr, headerPtr + size); - size_t colonPosition = header.find(':'); - if(colonPosition == std::string::npos) return size; // HTML response; ignore. - - if(header.substr(0, colonPosition) == "Content-Length") { - try { - size_t firstDigitPos = header.find_first_of("0123456789", colonPosition); - size_t lastDigitPos = header.find_last_of("0123456789"); - std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); - size_t size = boost::lexical_cast<size_t>(contentLength); - LL_INFOS("UpdaterService") << "download size is " << size << LL_ENDL; - - mDownloadData["size"] = LLSD(LLSD::Integer(size)); - llofstream odataStream(mDownloadRecordPath.c_str()); - LLSDSerialize::toPrettyXML(mDownloadData, odataStream); - } catch (std::exception const & e) { - LL_WARNS("UpdaterService") << "unable to read content length (" - << e.what() << ")" << LL_ENDL; - } - } else { - ; // No op. - } - - return size; -} - - -size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) -{ - if(mCancelled) return 0; // Forces a write error which will halt curl thread. - if((size == 0) || (buffer == 0)) return 0; - - mDownloadStream.write(static_cast<const char *>(buffer), size); - if(mDownloadStream.bad()) { - return 0; - } else { - return size; - } -} - - -int LLUpdateDownloader::Implementation::onProgress(curl_off_t downloadSize, curl_off_t bytesDownloaded) -{ - int downloadPercent = static_cast<int>(100.0 * ((double) bytesDownloaded / (double) downloadSize)); - if(downloadPercent > mDownloadPercent) { - mDownloadPercent = downloadPercent; - - LLSD event; - event["pump"] = LLUpdaterService::pumpName(); - LLSD payload; - payload["type"] = LLSD(LLUpdaterService::PROGRESS); - payload["download_size"] = (LLSD::Integer) downloadSize; - payload["bytes_downloaded"] = (LLSD::Integer) bytesDownloaded; - event["payload"] = payload; - LLEventPumps::instance().obtain("mainlooprepeater").post(event); - - LL_INFOS("UpdaterService") << "progress event " << payload << LL_ENDL; - } else { - ; // Keep events to a reasonalbe number. - } - - return 0; -} - - -void LLUpdateDownloader::Implementation::run(void) -{ - CURLcode code = curl_easy_perform(mCurl.get()); - mDownloadStream.close(); - if(code == CURLE_OK) - { - LLFile::remove(mDownloadRecordPath); - if(validateOrRemove(mDownloadData["path"])) - { - LL_INFOS("UpdaterService") << "download successful" << LL_ENDL; - mClient.downloadComplete(mDownloadData); - } - else - { - mClient.downloadError("failed hash check"); - } - } - else if(mCancelled && (code == CURLE_WRITE_ERROR)) - { - LL_INFOS("UpdaterService") << "download canceled by user" << LL_ENDL; - // Do not call back client. - } - else - { - LL_WARNS("UpdaterService") << "download failed with error '" << - curl_easy_strerror(code) << "'" << LL_ENDL; - LLFile::remove(mDownloadRecordPath); - if(mDownloadData.has("path")) - { - std::string filePath = mDownloadData["path"].asString(); - LL_INFOS("UpdaterService") << "removing " << filePath << LL_ENDL; - LLFile::remove(filePath); - } - mClient.downloadError("curl error"); - } - - if(mHeaderList) - { - curl_slist_free_all(mHeaderList); - mHeaderList = 0; - } -} - - -void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) -{ - if(!mCurl) - { - mCurl = LLCore::LLHttp::createEasyHandle(); - } - else - { - curl_easy_reset(mCurl.get()); - } - - if(!mCurl) - { - LLTHROW(DownloadError("failed to initialize curl")); - } - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_WRITEFUNCTION, &write_function)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_WRITEDATA, this)); - if(processHeader) - { - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HEADERFUNCTION, &header_function)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HEADERDATA, this)); - } - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPGET, true)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_URL, url.c_str())); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_XFERINFOFUNCTION, &xferinfo_callback)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_XFERINFODATA, this)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOPROGRESS, 0)); - // if it's a required update set the bandwidth limit to 0 (unlimited) - curl_off_t limit = mDownloadData["required"].asBoolean() ? 0 : mBandwidthLimit; - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_MAX_RECV_SPEED_LARGE, limit)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str())); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_SSL_VERIFYHOST, 2)); - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_SSL_VERIFYPEER, 1)); - - mDownloadPercent = 0; -} - - -void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) -{ - LL_INFOS("UpdaterService") << "resuming download from " << mDownloadData["url"].asString() - << " at byte " << startByte << LL_ENDL; - - initializeCurlGet(mDownloadData["url"].asString(), false); - - // The header 'Range: bytes n-' will request the bytes remaining in the - // source begining with byte n and ending with the last byte. - boost::format rangeHeaderFormat("Range: bytes=%u-"); - rangeHeaderFormat % startByte; - mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); - if(mHeaderList == 0) - { - LLTHROW(DownloadError("cannot add Range header")); - } - throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList)); - - mDownloadStream.open(mDownloadData["path"].asString().c_str(), - std::ios_base::out | std::ios_base::binary | std::ios_base::app); - start(); -} - - -void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std::string const & hash) -{ - mDownloadData["url"] = uri.asString(); - mDownloadData["hash"] = hash; - mDownloadData["current_version"] = ll_get_version(); - LLSD path = uri.pathArray(); - if(path.size() == 0) LLTHROW(DownloadError("no file path")); - std::string fileName = path[path.size() - 1].asString(); - std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); - mDownloadData["path"] = filePath; - - LL_INFOS("UpdaterService") << "downloading " << filePath - << " from " << uri.asString() << LL_ENDL; - LL_INFOS("UpdaterService") << "hash of file is " << hash << LL_ENDL; - - llofstream dataStream(mDownloadRecordPath.c_str()); - LLSDSerialize::toPrettyXML(mDownloadData, dataStream); - - mDownloadStream.open(filePath.c_str(), std::ios_base::out | std::ios_base::binary); - initializeCurlGet(uri.asString(), true); - start(); -} - - -void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) -{ - if(code != CURLE_OK) { - const char * errorString = curl_easy_strerror(code); - if(errorString != 0) { - LLTHROW(DownloadError(curl_easy_strerror(code))); - } else { - LLTHROW(DownloadError("unknown curl error")); - } - } else { - ; // No op. - } -} - -bool LLUpdateDownloader::Implementation::validateOrRemove(const std::string& filePath) -{ - bool valid = validateDownload(filePath); - if (! valid) - { - LL_INFOS("UpdaterService") << "removing " << filePath << LL_ENDL; - LLFile::remove(filePath); - } - return valid; -} - -bool LLUpdateDownloader::Implementation::validateDownload(const std::string& filePath) -{ - llifstream fileStream(filePath.c_str(), std::ios_base::in | std::ios_base::binary); - if(!fileStream) - { - LL_INFOS("UpdaterService") << "can't open " << filePath << ", invalid" << LL_ENDL; - return false; - } - - std::string hash = mDownloadData["hash"].asString(); - if (! hash.empty()) - { - char digest[33]; - LLMD5(fileStream).hex_digest(digest); - if (hash == digest) - { - LL_INFOS("UpdaterService") << "verified hash " << hash - << " for downloaded " << filePath << LL_ENDL; - return true; - } - else - { - LL_WARNS("UpdaterService") << "download hash mismatch for " - << filePath << ": expected " << hash - << " but computed " << digest << LL_ENDL; - return false; - } - } - else - { - LL_INFOS("UpdaterService") << "no hash specified for " << filePath - << ", unverified" << LL_ENDL; - return true; // No hash check provided. - } -} diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h deleted file mode 100644 index f759988f12..0000000000 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @file llupdatedownloader.h - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_UPDATE_DOWNLOADER_H -#define LL_UPDATE_DOWNLOADER_H - - -#include <string> -#include <boost/shared_ptr.hpp> -#include "lluri.h" - - -// -// An asynchronous download service for fetching updates. -// -class LLUpdateDownloader -{ -public: - class Client; - class Implementation; - - // Returns the path to the download marker file containing details of the - // latest download. - static std::string downloadMarkerPath(void); - - LLUpdateDownloader(Client & client); - - // Cancel any in progress download; a no op if none is in progress. The - // client will not receive a complete or error callback. - void cancel(void); - - // Start a new download. - void download(LLURI const & uri, - std::string const & hash, - std::string const & updateChannel, - std::string const & updateVersion, - std::string const & info_url, - bool required=false); - - // Returns true if a download is in progress. - bool isDownloading(void); - - // Resume a partial download. - void resume(void); - - // Set a limit on the dowload rate. - void setBandwidthLimit(U64 bytesPerSecond); - -private: - boost::shared_ptr<Implementation> mImplementation; -}; - - -// -// An interface to be implemented by clients initiating a update download. -// -class LLUpdateDownloader::Client { -public: - - // The download has completed successfully. - // data is a map containing the following items: - // url - source (remote) location - // hash - the md5 sum that should match the installer file. - // path - destination (local) location - // required - boolean indicating if this is a required update. - // size - the size of the installer in bytes - virtual void downloadComplete(LLSD const & data) = 0; - - // The download failed. - virtual void downloadError(std::string const & message) = 0; -}; - - -#endif diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp deleted file mode 100644 index 1c7629da23..0000000000 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file llupdateinstaller.cpp - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include <apr_file_io.h> -#include "llapr.h" -#include "llprocess.h" -#include "llupdateinstaller.h" -#include "lldir.h" -#include "llsd.h" -#include "llexception.h" - -#if defined(LL_WINDOWS) -#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). -#endif -#include <boost/lexical_cast.hpp> - -namespace { - struct RelocateError: public LLException - { - RelocateError(): LLException("llupdateinstaller: RelocateError") {} - }; - - std::string copy_to_temp(std::string const & path) - { - std::string scriptFile = gDirUtilp->getBaseFileName(path); - std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile); - apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp); - if(status != APR_SUCCESS) LLTHROW(RelocateError()); - - return newPath; - } -} - - -int ll_install_update(std::string const & script, - std::string const & updatePath, - bool required, - LLInstallScriptMode mode) -{ - std::string actualScriptPath; - switch(mode) { - case LL_COPY_INSTALL_SCRIPT_TO_TEMP: - try { - actualScriptPath = copy_to_temp(script); - } - catch (RelocateError &) { - return -1; - } - break; - case LL_RUN_INSTALL_SCRIPT_IN_PLACE: - actualScriptPath = script; - break; - default: - llassert(!"unpossible copy mode"); - } - - LL_INFOS("Updater") << "UpdateInstaller: installing " << updatePath << " using " << - actualScriptPath << LL_ENDL; - - LLProcess::Params params; - params.executable = actualScriptPath; - params.args.add(updatePath); - params.args.add(ll_install_failed_marker_path()); - params.args.add(boost::lexical_cast<std::string>(required)); - params.autokill = false; - return LLProcess::create(params)? 0 : -1; -} - - -std::string const & ll_install_failed_marker_path(void) -{ - static std::string path; - if(path.empty()) { - path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeInstallFailed.marker"); - } - return path; -} diff --git a/indra/viewer_components/updater/llupdateinstaller.h b/indra/viewer_components/updater/llupdateinstaller.h deleted file mode 100644 index fe5b1d19b5..0000000000 --- a/indra/viewer_components/updater/llupdateinstaller.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file llupdateinstaller.h - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_UPDATE_INSTALLER_H -#define LL_UPDATE_INSTALLER_H - - -#include <string> - - -enum LLInstallScriptMode { - LL_RUN_INSTALL_SCRIPT_IN_PLACE, - LL_COPY_INSTALL_SCRIPT_TO_TEMP -}; - -// -// Launch the installation script. -// -// The updater will overwrite the current installation, so it is highly recommended -// that the current application terminate once this function is called. -// -int ll_install_update( - std::string const & script, // Script to execute. - std::string const & updatePath, // Path to update file. - bool required, // Is the update required. - LLInstallScriptMode mode=LL_COPY_INSTALL_SCRIPT_TO_TEMP); // Run in place or copy to temp? - - -// -// Returns the path which points to the failed install marker file, should it -// exist. -// -std::string const & ll_install_failed_marker_path(void); - - -#endif diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp deleted file mode 100644 index 1665e41e70..0000000000 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ /dev/null @@ -1,761 +0,0 @@ -/** - * @file llupdaterservice.cpp - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llupdaterservice.h" - -#include "llupdatedownloader.h" -#include "llevents.h" -#include "lltimer.h" -#include "llupdatechecker.h" -#include "llupdateinstaller.h" -#include "llexception.h" - -#include <boost/scoped_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include "lldir.h" -#include "llsdserialize.h" -#include "llfile.h" -#include "llviewernetwork.h" - -#if LL_WINDOWS -#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally -#endif - -#if ! defined(LL_VIEWER_VERSION_MAJOR) \ - || ! defined(LL_VIEWER_VERSION_MINOR) \ - || ! defined(LL_VIEWER_VERSION_PATCH) \ - || ! defined(LL_VIEWER_VERSION_BUILD) -#error "Version information is undefined" -#endif - -namespace -{ - boost::weak_ptr<LLUpdaterServiceImpl> gUpdater; - - const std::string UPDATE_MARKER_FILENAME("SecondLifeUpdateReady.xml"); - std::string update_marker_path() - { - return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - UPDATE_MARKER_FILENAME); - } - - std::string install_script_path(void) - { -#ifdef LL_WINDOWS - std::string scriptFile = "update_install.bat"; -#elif LL_DARWIN - std::string scriptFile = "update_install.py"; -#else - std::string scriptFile = "update_install"; -#endif - return gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, scriptFile); - } - - LLInstallScriptMode install_script_mode(void) - { -#ifdef LL_WINDOWS - return LL_COPY_INSTALL_SCRIPT_TO_TEMP; -#else - // This is important on Mac because update_install.py looks at its own - // script pathname to discover the viewer app bundle to update. - return LL_RUN_INSTALL_SCRIPT_IN_PLACE; -#endif - }; - -} - -class LLUpdaterServiceImpl : - public LLUpdateChecker::Client, - public LLUpdateDownloader::Client -{ - static const std::string sListenerName; - - std::string mProtocolVersion; - std::string mChannel; - std::string mVersion; - std::string mPlatform; - std::string mPlatformVersion; - unsigned char mUniqueId[MD5HEX_STR_SIZE]; - bool mWillingToTest; - - unsigned int mCheckPeriod; - bool mIsChecking; - bool mIsDownloading; - - LLUpdateChecker mUpdateChecker; - LLUpdateDownloader mUpdateDownloader; - LLTimer mTimer; - - LLUpdaterService::app_exit_callback_t mAppExitCallback; - - LLUpdaterService::eUpdaterState mState; - - LOG_CLASS(LLUpdaterServiceImpl); - -public: - LLUpdaterServiceImpl(); - virtual ~LLUpdaterServiceImpl(); - - void initialize(const std::string& channel, - const std::string& version, - const std::string& platform, - const std::string& platform_version, - const unsigned char uniqueid[MD5HEX_STR_SIZE], - const bool& willing_to_test - ); - - void setCheckPeriod(unsigned int seconds); - void setBandwidthLimit(U64 bytesPerSecond); - - void startChecking(bool install_if_ready); - void stopChecking(); - bool forceCheck(); - bool isChecking(); - LLUpdaterService::eUpdaterState getState(); - - void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;} - std::string updatedVersion(void); - - bool checkForInstall(bool launchInstaller); // Test if a local install is ready. - bool checkForResume(); // Test for resumeable d/l. - - // LLUpdateChecker::Client: - virtual void error(std::string const & message); - - // A successful response was received from the viewer version manager - virtual void response(LLSD const & content); - - // LLUpdateDownloader::Client - void downloadComplete(LLSD const & data); - void downloadError(std::string const & message); - - bool onMainLoop(LLSD const & event); - -private: - std::string mNewChannel; - std::string mNewVersion; - - void restartTimer(unsigned int seconds); - void setState(LLUpdaterService::eUpdaterState state); - void stopTimer(); -}; - -const std::string LLUpdaterServiceImpl::sListenerName = "LLUpdaterServiceImpl"; - -LLUpdaterServiceImpl::LLUpdaterServiceImpl() : - mIsChecking(false), - mIsDownloading(false), - mCheckPeriod(0), - mUpdateChecker(*this), - mUpdateDownloader(*this), - mState(LLUpdaterService::INITIAL) -{ -} - -LLUpdaterServiceImpl::~LLUpdaterServiceImpl() -{ - LL_INFOS("UpdaterService") << "shutting down updater service" << LL_ENDL; - LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); -} - -void LLUpdaterServiceImpl::initialize(const std::string& channel, - const std::string& version, - const std::string& platform, - const std::string& platform_version, - const unsigned char uniqueid[MD5HEX_STR_SIZE], - const bool& willing_to_test) -{ - if(mIsChecking || mIsDownloading) - { - LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call " - "while updater is running.")); - } - - mChannel = channel; - mVersion = version; - mPlatform = platform; - mPlatformVersion = platform_version; - memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); - mWillingToTest = willing_to_test; - LL_DEBUGS("UpdaterService") - << "\n channel: " << mChannel - << "\n version: " << mVersion - << "\n uniqueid: " << mUniqueId - << "\n willing: " << ( mWillingToTest ? "testok" : "testno" ) - << LL_ENDL; -} - -void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds) -{ - mCheckPeriod = seconds; -} - -void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond) -{ - mUpdateDownloader.setBandwidthLimit(bytesPerSecond); -} - -void LLUpdaterServiceImpl::startChecking(bool install_if_ready) -{ - if(mChannel.empty() || mVersion.empty()) - { - LLTHROW(LLUpdaterService::UsageError("Set params before call to " - "LLUpdaterService::startCheck().")); - } - - mIsChecking = true; - - // Check to see if an install is ready. - bool has_install = checkForInstall(install_if_ready); - if(!has_install) - { - checkForResume(); // will set mIsDownloading to true if resuming - - if(!mIsDownloading) - { - setState(LLUpdaterService::CHECKING_FOR_UPDATE); - - // Checking can only occur during the mainloop. - // reset the timer to 0 so that the next mainloop event - // triggers a check; - restartTimer(0); - } - else - { - setState(LLUpdaterService::DOWNLOADING); - } - } -} - -void LLUpdaterServiceImpl::stopChecking() -{ - if(mIsChecking) - { - mIsChecking = false; - stopTimer(); - } - - if(mIsDownloading) - { - mUpdateDownloader.cancel(); - mIsDownloading = false; - } - - setState(LLUpdaterService::TERMINAL); -} - -bool LLUpdaterServiceImpl::forceCheck() -{ - if (!mIsDownloading && getState() != LLUpdaterService::CHECKING_FOR_UPDATE) - { - if (mIsChecking) - { - // Service is running, just reset the timer - if (mTimer.getStarted()) - { - mTimer.setTimerExpirySec(0); - setState(LLUpdaterService::CHECKING_FOR_UPDATE); - return true; - } - } - else if (!mChannel.empty() && !mVersion.empty()) - { - // one time check - bool has_install = checkForInstall(false); - if (!has_install) - { - std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL(); - if (!query_url.empty()) - { - setState(LLUpdaterService::CHECKING_FOR_UPDATE); - mUpdateChecker.checkVersion(query_url, mChannel, mVersion, - mPlatform, mPlatformVersion, mUniqueId, - mWillingToTest); - return true; - } - else - { - LL_WARNS("UpdaterService") - << "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid() << LL_ENDL; - } - } - } - } - return false; -} - -bool LLUpdaterServiceImpl::isChecking() -{ - return mIsChecking; -} - -LLUpdaterService::eUpdaterState LLUpdaterServiceImpl::getState() -{ - return mState; -} - -std::string LLUpdaterServiceImpl::updatedVersion(void) -{ - return mNewVersion; -} - -bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) -{ - bool foundInstall = false; // return true if install is found. - - llifstream update_marker(update_marker_path().c_str(), - std::ios::in | std::ios::binary); - - if(update_marker.is_open()) - { - // Found an update info - now lets see if its valid. - LLSD update_info; - LLSDSerialize::fromXMLDocument(update_info, update_marker); - update_marker.close(); - - // Get the path to the installer file. - std::string path(update_info.get("path")); - std::string downloader_version(update_info["current_version"]); - if (downloader_version != ll_get_version()) - { - // This viewer is not the same version as the one that downloaded - // the update. Do not install this update. - LL_INFOS("UpdaterService") << "ignoring update downloaded by " - << "different viewer version " - << downloader_version << LL_ENDL; - if (! path.empty()) - { - LL_INFOS("UpdaterService") << "removing " << path << LL_ENDL; - LLFile::remove(path); - LLFile::remove(update_marker_path()); - } - - foundInstall = false; - } - else if (path.empty()) - { - LL_WARNS("UpdaterService") << "Marker file " << update_marker_path() - << " 'path' entry empty, ignoring" << LL_ENDL; - foundInstall = false; - } - else if (! LLFile::isfile(path)) - { - LL_WARNS("UpdaterService") << "Nonexistent installer " << path - << ", ignoring" << LL_ENDL; - foundInstall = false; - } - else - { - if(launchInstaller) - { - setState(LLUpdaterService::INSTALLING); - - LLFile::remove(update_marker_path()); - - int result = ll_install_update(install_script_path(), - path, - update_info["required"].asBoolean(), - install_script_mode()); - - if((result == 0) && mAppExitCallback) - { - mAppExitCallback(); - } - else if(result != 0) - { - LL_WARNS("UpdaterService") << "failed to run update install script" << LL_ENDL; - } - else - { - ; // No op. - } - } - - foundInstall = true; - } - } - return foundInstall; -} - -bool LLUpdaterServiceImpl::checkForResume() -{ - bool result = false; - std::string download_marker_path = mUpdateDownloader.downloadMarkerPath(); - if(LLFile::isfile(download_marker_path)) - { - llifstream download_marker_stream(download_marker_path.c_str(), - std::ios::in | std::ios::binary); - if(download_marker_stream.is_open()) - { - LLSD download_info; - LLSDSerialize::fromXMLDocument(download_info, download_marker_stream); - download_marker_stream.close(); - std::string downloader_version(download_info["current_version"]); - if (downloader_version == ll_get_version()) - { - mIsDownloading = true; - mNewVersion = download_info["update_version"].asString(); - mNewChannel = download_info["update_channel"].asString(); - mUpdateDownloader.resume(); - result = true; - } - else - { - // The viewer that started this download is not the same as this viewer; ignore. - LL_INFOS("UpdaterService") << "ignoring partial download " - << "from different viewer version " - << downloader_version << LL_ENDL; - std::string path = download_info["path"].asString(); - if(!path.empty()) - { - LL_INFOS("UpdaterService") << "removing " << path << LL_ENDL; - LLFile::remove(path); - } - LLFile::remove(download_marker_path); - } - } - } - return result; -} - -void LLUpdaterServiceImpl::error(std::string const & message) -{ - setState(LLUpdaterService::TEMPORARY_ERROR); - if(mIsChecking) - { - restartTimer(mCheckPeriod); - } -} - -// A successful response was received from the viewer version manager -void LLUpdaterServiceImpl::response(LLSD const & content) -{ - if(!content.asBoolean()) // an empty response means "no update" - { - LL_INFOS("UpdaterService") << "up to date" << LL_ENDL; - if(mIsChecking) - { - restartTimer(mCheckPeriod); - } - - setState(LLUpdaterService::UP_TO_DATE); - } - else if ( content.isMap() && content.has("url") ) - { - // there is an update available... - stopTimer(); - mNewChannel = content["channel"].asString(); - if (mNewChannel.empty()) - { - LL_INFOS("UpdaterService") << "no channel supplied, assuming current channel" << LL_ENDL; - mNewChannel = mChannel; - } - mNewVersion = content["version"].asString(); - mIsDownloading = true; - setState(LLUpdaterService::DOWNLOADING); - BOOL required = content["required"].asBoolean(); - LLURI url(content["url"].asString()); - std::string more_info = content["more_info"].asString(); - LL_DEBUGS("UpdaterService") - << "Starting download of " - << ( required ? "required" : "optional" ) << " update" - << " to channel '" << mNewChannel << "' version " << mNewVersion - << " more info '" << more_info << "'" - << LL_ENDL; - mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required); - } - else - { - LL_WARNS("UpdaterService") << "Invalid update query response ignored; retry in " - << mCheckPeriod << " seconds" << LL_ENDL; - setState(LLUpdaterService::TEMPORARY_ERROR); - if (mIsChecking) - { - restartTimer(mCheckPeriod); - } - } -} - -void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) -{ - mIsDownloading = false; - - // Save out the download data to the SecondLifeUpdateReady - // marker file. - llofstream update_marker(update_marker_path().c_str()); - LLSDSerialize::toPrettyXML(data, update_marker); - - LLSD event; - event["pump"] = LLUpdaterService::pumpName(); - LLSD payload; - payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE); - payload["required"] = data["required"]; - payload["version"] = mNewVersion; - payload["channel"] = mNewChannel; - payload["info_url"] = data["info_url"]; - event["payload"] = payload; - LL_DEBUGS("UpdaterService") - << "Download complete " - << ( data["required"].asBoolean() ? "required" : "optional" ) - << " channel " << mNewChannel - << " version " << mNewVersion - << " info " << data["info_url"].asString() - << LL_ENDL; - - LLEventPumps::instance().obtain("mainlooprepeater").post(event); - - setState(LLUpdaterService::TERMINAL); -} - -void LLUpdaterServiceImpl::downloadError(std::string const & message) -{ - LL_INFOS("UpdaterService") << "Error downloading: " << message << LL_ENDL; - - mIsDownloading = false; - - // Restart the timer on error - if(mIsChecking) - { - restartTimer(mCheckPeriod); - } - - LLSD event; - event["pump"] = LLUpdaterService::pumpName(); - LLSD payload; - payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_ERROR); - payload["message"] = message; - event["payload"] = payload; - LLEventPumps::instance().obtain("mainlooprepeater").post(event); - - setState(LLUpdaterService::FAILURE); -} - -void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) -{ - LL_INFOS("UpdaterService") << "will check for update again in " << - seconds << " seconds" << LL_ENDL; - mTimer.start(); - mTimer.setTimerExpirySec((F32)seconds); - LLEventPumps::instance().obtain("mainloop").listen( - sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1)); -} - -void LLUpdaterServiceImpl::setState(LLUpdaterService::eUpdaterState state) -{ - if(state != mState) - { - mState = state; - - LLSD event; - event["pump"] = LLUpdaterService::pumpName(); - LLSD payload; - payload["type"] = LLSD(LLUpdaterService::STATE_CHANGE); - payload["state"] = state; - event["payload"] = payload; - LLEventPumps::instance().obtain("mainlooprepeater").post(event); - - LL_INFOS("UpdaterService") << "setting state to " << state << LL_ENDL; - } - else - { - ; // State unchanged; noop. - } -} - -void LLUpdaterServiceImpl::stopTimer() -{ - mTimer.stop(); - LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); -} - -bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) -{ - if(mTimer.getStarted() && mTimer.hasExpired()) - { - stopTimer(); - - // Check for failed install. - if(LLFile::isfile(ll_install_failed_marker_path())) - { - LL_DEBUGS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL; - int requiredValue = 0; - { - llifstream stream(ll_install_failed_marker_path().c_str()); - stream >> requiredValue; - if(stream.fail()) - { - requiredValue = 0; - } - } - // TODO: notify the user. - LL_WARNS("UpdaterService") << "last install attempt failed" << LL_ENDL;; - LLFile::remove(ll_install_failed_marker_path()); - - LLSD event; - event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR); - event["required"] = LLSD(requiredValue); - LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event); - - setState(LLUpdaterService::TERMINAL); - } - else - { - std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL(); - if ( !query_url.empty() ) - { - mUpdateChecker.checkVersion(query_url, mChannel, mVersion, - mPlatform, mPlatformVersion, mUniqueId, - mWillingToTest); - setState(LLUpdaterService::CHECKING_FOR_UPDATE); - } - else - { - LL_WARNS("UpdaterService") - << "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid() - << "' will check again in " << mCheckPeriod << " seconds" - << LL_ENDL; - // Because the grid can be changed after the viewer is started (when the first check takes place) - // but before the user logs in, the next check may be on a different grid, so set the retry timer - // even though this check did not happen. The default time is once an hour, and if we're not - // doing the check anyway the performance impact is completely insignificant. - restartTimer(mCheckPeriod); - } - } - } - else - { - // Keep on waiting... - } - - return false; -} - - -//----------------------------------------------------------------------- -// Facade interface - -std::string const & LLUpdaterService::pumpName(void) -{ - static std::string name("updater_service"); - return name; -} - -bool LLUpdaterService::updateReadyToInstall(void) -{ - return LLFile::isfile(update_marker_path()); -} - -LLUpdaterService::LLUpdaterService() -{ - if(gUpdater.expired()) - { - mImpl = - boost::shared_ptr<LLUpdaterServiceImpl>(new LLUpdaterServiceImpl()); - gUpdater = mImpl; - } - else - { - mImpl = gUpdater.lock(); - } -} - -LLUpdaterService::~LLUpdaterService() -{ -} - -void LLUpdaterService::initialize(const std::string& channel, - const std::string& version, - const std::string& platform, - const std::string& platform_version, - const unsigned char uniqueid[MD5HEX_STR_SIZE], - const bool& willing_to_test -) -{ - mImpl->initialize(channel, version, platform, platform_version, uniqueid, willing_to_test); -} - -void LLUpdaterService::setCheckPeriod(unsigned int seconds) -{ - mImpl->setCheckPeriod(seconds); -} - -void LLUpdaterService::setBandwidthLimit(U64 bytesPerSecond) -{ - mImpl->setBandwidthLimit(bytesPerSecond); -} - -void LLUpdaterService::startChecking(bool install_if_ready) -{ - mImpl->startChecking(install_if_ready); -} - -void LLUpdaterService::stopChecking() -{ - mImpl->stopChecking(); -} - -bool LLUpdaterService::forceCheck() -{ - return mImpl->forceCheck(); -} - -bool LLUpdaterService::isChecking() -{ - return mImpl->isChecking(); -} - -LLUpdaterService::eUpdaterState LLUpdaterService::getState() -{ - return mImpl->getState(); -} - -void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) -{ - return mImpl->setAppExitCallback(aecb); -} - -std::string LLUpdaterService::updatedVersion(void) -{ - return mImpl->updatedVersion(); -} - - -std::string const & ll_get_version(void) { - static std::string version(""); - - if (version.empty()) { - std::ostringstream stream; - stream << LL_VIEWER_VERSION_MAJOR << "." - << LL_VIEWER_VERSION_MINOR << "." - << LL_VIEWER_VERSION_PATCH << "." - << LL_VIEWER_VERSION_BUILD; - version = stream.str(); - } - - return version; -} - diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h deleted file mode 100644 index 78e8c6b290..0000000000 --- a/indra/viewer_components/updater/llupdaterservice.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file llupdaterservice.h - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_UPDATERSERVICE_H -#define LL_UPDATERSERVICE_H - -#include <boost/shared_ptr.hpp> -#include <boost/function.hpp> -#include "llhasheduniqueid.h" -#include "llexception.h" - -class LLUpdaterServiceImpl; - -class LLUpdaterService -{ -public: - class UsageError: public LLException - { - public: - UsageError(const std::string& msg) : LLException(msg) {} - }; - - // Name of the event pump through which update events will be delivered. - static std::string const & pumpName(void); - - // Returns true if an update has been completely downloaded and is now ready to install. - static bool updateReadyToInstall(void); - - // Type codes for events posted by this service. Stored the event's 'type' element. - enum eUpdaterEvent { - INVALID, - DOWNLOAD_COMPLETE, - DOWNLOAD_ERROR, - INSTALL_ERROR, - PROGRESS, - STATE_CHANGE - }; - - enum eUpdaterState { - INITIAL, - CHECKING_FOR_UPDATE, - TEMPORARY_ERROR, - DOWNLOADING, - INSTALLING, - UP_TO_DATE, - TERMINAL, - FAILURE - }; - - LLUpdaterService(); - ~LLUpdaterService(); - - void initialize(const std::string& channel, - const std::string& version, - const std::string& platform, - const std::string& platform_version, - const unsigned char uniqueid[MD5HEX_STR_SIZE], - const bool& willing_to_test - ); - - void setCheckPeriod(unsigned int seconds); - void setBandwidthLimit(U64 bytesPerSecond); - - void startChecking(bool install_if_ready = false); - void stopChecking(); - bool forceCheck(); - bool isChecking(); - eUpdaterState getState(); - - typedef boost::function<void (void)> app_exit_callback_t; - template <typename F> - void setAppExitCallback(F const &callable) - { - app_exit_callback_t aecb = callable; - setImplAppExitCallback(aecb); - } - - // If an update is or has been downloaded, this method will return the - // version string for that update. An empty string will be returned - // otherwise. - std::string updatedVersion(void); - -private: - boost::shared_ptr<LLUpdaterServiceImpl> mImpl; - void setImplAppExitCallback(app_exit_callback_t aecb); -}; - -// Returns the full version as a string. -std::string const & ll_get_version(void); - -#endif // LL_UPDATERSERVICE_H diff --git a/indra/viewer_components/updater/scripts/darwin/janitor.py b/indra/viewer_components/updater/scripts/darwin/janitor.py deleted file mode 100644 index cdf33df731..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/janitor.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/python -"""\ -@file janitor.py -@author Nat Goodspeed -@date 2011-09-14 -@brief Janitor class to clean up arbitrary resources - -2013-01-04 cloned from vita because it's exactly what update_install.py needs. - -$LicenseInfo:firstyear=2011&license=viewerlgpl$ -Copyright (c) 2011, Linden Research, Inc. -$/LicenseInfo$ -""" - -import sys -import functools -import itertools - -class Janitor(object): - """ - Usage: - - Basic: - self.janitor = Janitor(sys.stdout) # report cleanup actions on stdout - ... - self.janitor.later(os.remove, some_temp_file) - self.janitor.later(os.remove, some_other_file) - ... - self.janitor.cleanup() # perform cleanup actions - - Context Manager: - with Janitor() as janitor: # clean up quietly - ... - janitor.later(shutil.rmtree, some_temp_directory) - ... - # exiting 'with' block performs cleanup - - Test Class: - class TestMySoftware(unittest.TestCase, Janitor): - def __init__(self): - Janitor.__init__(self) # quiet cleanup - ... - - def setUp(self): - ... - self.later(os.rename, saved_file, original_location) - ... - - def tearDown(self): - Janitor.tearDown(self) # calls cleanup() - ... - # Or, if you have no other tearDown() logic for - # TestMySoftware, you can omit the TestMySoftware.tearDown() - # def entirely and let it inherit Janitor.tearDown(). - """ - def __init__(self, stream=None): - """ - If you pass stream= (e.g.) sys.stdout or sys.stderr, Janitor will - report its cleanup operations as it performs them. If you don't, it - will perform them quietly -- unless one or more of the actions throws - an exception, in which case you'll get output on stderr. - """ - self.stream = stream - self.cleanups = [] - - def later(self, func, *args, **kwds): - """ - Pass the callable you want to call at cleanup() time, plus any - positional or keyword args you want to pass it. - """ - # Get a name string for 'func' - try: - # A free function has a __name__ - name = func.__name__ - except AttributeError: - try: - # A class object (even builtin objects like ints!) support - # __class__.__name__ - name = func.__class__.__name__ - except AttributeError: - # Shrug! Just use repr() to get a string describing this func. - name = repr(func) - # Construct a description of this operation in Python syntax from - # args, kwds. - desc = "%s(%s)" % \ - (name, ", ".join(itertools.chain((repr(a) for a in args), - ("%s=%r" % (k, v) for (k, v) in kwds.iteritems())))) - # Use functools.partial() to bind passed args and keywords to the - # passed func so we get a nullary callable that does what caller - # wants. - bound = functools.partial(func, *args, **kwds) - self.cleanups.append((desc, bound)) - - def cleanup(self): - """ - Perform all the actions saved with later() calls. - """ - # Typically one allocates resource A, then allocates resource B that - # depends on it. In such a scenario it's appropriate to delete B - # before A -- so perform cleanup actions in reverse order. (This is - # the same strategy used by atexit().) - while self.cleanups: - # Until our list is empty, pop the last pair. - desc, bound = self.cleanups.pop(-1) - - # If requested, report the action. - if self.stream is not None: - print >>self.stream, desc - - try: - # Call the bound callable - bound() - except Exception, err: - # This is cleanup. Report the problem but continue. - print >>(self.stream or sys.stderr), "Calling %s\nraised %s: %s" % \ - (desc, err.__class__.__name__, err) - - def tearDown(self): - """ - If a unittest.TestCase subclass (or a nose test class) adds Janitor as - one of its base classes, and has no other tearDown() logic, let it - inherit Janitor.tearDown(). - """ - self.cleanup() - - def __enter__(self): - return self - - def __exit__(self, type, value, tb): - # Perform cleanup no matter how we exit this 'with' statement - self.cleanup() - # Propagate any exception from the 'with' statement, don't swallow it - return False diff --git a/indra/viewer_components/updater/scripts/darwin/messageframe.py b/indra/viewer_components/updater/scripts/darwin/messageframe.py deleted file mode 100644 index 8f58848882..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/messageframe.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python -"""\ -@file messageframe.py -@author Nat Goodspeed -@date 2013-01-03 -@brief Define MessageFrame class for popping up messages from a command-line - script. - -$LicenseInfo:firstyear=2013&license=viewerlgpl$ -Copyright (c) 2013, Linden Research, Inc. -$/LicenseInfo$ -""" - -import Tkinter as tk -import os - -# Tricky way to obtain the filename of the main script (default title string) -import __main__ - -# This class is intended for displaying messages from a command-line script. -# Getting the base class right took a bit of trial and error. -# If you derive from tk.Frame, the destroy() method doesn't actually close it. -# If you derive from tk.Toplevel, it pops up a separate Tk frame too. destroy() -# closes this frame, but not that one. -# Deriving from tk.Tk appears to do the right thing. -class MessageFrame(tk.Tk): - def __init__(self, text="", title=os.path.splitext(os.path.basename(__main__.__file__))[0], - width=320, height=120): - tk.Tk.__init__(self) - self.grid() - self.title(title) - self.var = tk.StringVar() - self.var.set(text) - self.msg = tk.Label(self, textvariable=self.var) - self.msg.grid() - # from http://stackoverflow.com/questions/3352918/how-to-center-a-window-on-the-screen-in-tkinter : - self.update_idletasks() - - # The constants below are to adjust for typical overhead from the - # frame borders. - xp = (self.winfo_screenwidth() / 2) - (width / 2) - 8 - yp = (self.winfo_screenheight() / 2) - (height / 2) - 20 - self.geometry('{0}x{1}+{2}+{3}'.format(width, height, xp, yp)) - self.update() - - def set(self, text): - self.var.set(text) - self.update() - -if __name__ == "__main__": - # When run as a script, just test the MessageFrame. - import sys - import time - - frame = MessageFrame("something in the way she moves....") - time.sleep(3) - frame.set("smaller") - time.sleep(3) - frame.set("""this has -several -lines""") - time.sleep(3) - frame.destroy() - print "Destroyed!" - sys.stdout.flush() - time.sleep(3) diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py deleted file mode 100755 index 08f4f0ebb9..0000000000 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/python -"""\ -@file update_install.py -@author Nat Goodspeed -@date 2012-12-20 -@brief Update the containing Second Life application bundle to the version in - the specified disk image file. - - This Python implementation is derived from the previous mac-updater - application, a funky mix of C++, classic C and Objective-C. - -$LicenseInfo:firstyear=2012&license=viewerlgpl$ -Copyright (c) 2012, Linden Research, Inc. -$/LicenseInfo$ -""" - -import os -import sys -import cgitb -from contextlib import contextmanager -import errno -import glob -import plistlib -import re -import shutil -import subprocess -import tempfile -import time -from janitor import Janitor -from messageframe import MessageFrame -import Tkinter, tkMessageBox - -TITLE = "Second Life Viewer Updater" -# Magic bundle identifier used by all Second Life viewer bundles -BUNDLE_IDENTIFIER = "com.secondlife.indra.viewer" -# Magic OS directory name that causes Cocoa viewer to crash on OS X 10.7.5 -# (see MAINT-3331) -STATE_DIR = os.path.join( - os.environ["HOME"], "Library", "Saved Application State", - BUNDLE_IDENTIFIER + ".savedState") - -# Global handle to the MessageFrame so we can update message -FRAME = None -# Global handle to logfile, once it's open -LOGF = None - -# **************************************************************************** -# Logging and messaging -# -# This script is normally run implicitly by the old viewer to update to the -# new viewer. Its UI consists of a MessageFrame and possibly a Tk error box. -# Log details to updater.log -- especially uncaught exceptions! -# **************************************************************************** -def log(message): - """write message only to LOGF (also called by status() and fail())""" - # If we don't even have LOGF open yet, at least write to Console log - logf = LOGF or sys.stderr - logf.writelines((time.strftime("%Y-%m-%dT%H:%M:%SZ ", time.gmtime()), message, '\n')) - logf.flush() - -def status(message): - """display and log normal progress message""" - log(message) - - global FRAME - if not FRAME: - FRAME = MessageFrame(message, TITLE) - else: - FRAME.set(message) - -def fail(message): - """log message, produce error box, then terminate with nonzero rc""" - log(message) - - # If we haven't yet called status() (we don't yet have a FRAME), perform a - # bit of trickery to bypass the spurious "main window" that Tkinter would - # otherwise pop up if the first call is showerror(). - if not FRAME: - root = Tkinter.Tk() - root.withdraw() - - # If we do have a LOGF available, mention it in the error box. - if LOGF: - message = "%s\n(Updater log in %s)" % (message, LOGF.name) - - # We explicitly specify the WARNING icon because, at least on the Tkinter - # bundled with the system-default Python 2.7 on Mac OS X 10.7.4, the - # ERROR, QUESTION and INFO icons are all the silly Tk rocket ship. At - # least WARNING has an exclamation in a yellow triangle, even though - # overlaid by a smaller image of the rocket ship. - tkMessageBox.showerror(TITLE, -"""An error occurred while updating Second Life: -%s -Please download the latest viewer from www.secondlife.com.""" % message, - icon=tkMessageBox.WARNING) - sys.exit(1) - -def exception(err): - """call fail() with an exception instance""" - fail("%s exception: %s" % (err.__class__.__name__, str(err))) - -def excepthook(type, value, traceback): - """ - Store this hook function into sys.excepthook until we have a logfile. - """ - # At least in older Python versions, it could be tricky to produce a - # string from 'type' and 'value'. For instance, an OSError exception would - # pass type=OSError and value=some_tuple. Empirically, this funky - # expression seems to work. - exception(type(*value)) -sys.excepthook = excepthook - -class ExceptHook(object): - """ - Store an instance of this class into sys.excepthook once we have a logfile - open. - """ - def __init__(self, logfile): - # There's no magic to the cgitb.enable() function -- it merely stores - # an instance of cgitb.Hook into sys.excepthook, passing enable()'s - # params into Hook.__init__(). Sadly, enable() doesn't forward all its - # params using (*args, **kwds) syntax -- another story. But the point - # is that all the goodness is in the cgitb.Hook class. Capture an - # instance. - self.hook = cgitb.Hook(file=logfile, format="text") - - def __call__(self, type, value, traceback): - # produce nice text traceback to logfile - self.hook(type, value, traceback) - # Now display an error box. - excepthook(type, value, traceback) - -def write_marker(markerfile, markertext): - log("writing %r to %s" % (markertext, markerfile)) - try: - with open(markerfile, "w") as markerf: - markerf.write(markertext) - except IOError, err: - # write_marker() is invoked by fail(), and fail() is invoked by other - # error-handling functions. If we try to invoke any of those, we'll - # get infinite recursion. If for any reason we can't write markerfile, - # try to log it -- otherwise shrug. - log("%s exception: %s" % (err.__class__.__name__, err)) - -# **************************************************************************** -# Utility -# **************************************************************************** -@contextmanager -def allow_errno(errn): - """ - Execute body of 'with' statement, accepting OSError with specific errno - 'errn'. Propagate any other exception, or an OSError with any other errno. - """ - try: - # run the body of the 'with' statement - yield - except OSError, err: - # unless errno == passed errn, re-raise the exception - if err.errno != errn: - raise - -# **************************************************************************** -# Main script logic -# **************************************************************************** -def main(dmgfile, markerfile, markertext): - # Should we fail, we're supposed to write 'markertext' to 'markerfile'. - # Wrap the fail() function so we do that. - global fail - oldfail = fail - def fail(message): - write_marker(markerfile, markertext) - oldfail(message) - - try: - # Starting with the Cocoafied viewer, we'll find viewer logs in - # ~/Library/Application Support/$CFBundleIdentifier/logs rather than in - # ~/Library/Application Support/SecondLife/logs as before. This could be - # obnoxious -- but we Happen To Know that markerfile is a path specified - # within the viewer's logs directory. Use that. - logsdir = os.path.dirname(markerfile) - - # Move the old updater.log file out of the way - logname = os.path.join(logsdir, "updater.log") - # Nonexistence is okay. Anything else, not so much. - with allow_errno(errno.ENOENT): - os.rename(logname, logname + ".old") - - # Open new updater.log. - global LOGF - LOGF = open(logname, "w") - - # Now that LOGF is in fact open for business, use it to log any further - # uncaught exceptions. - sys.excepthook = ExceptHook(LOGF) - - # log how this script was invoked - log(' '.join(repr(arg) for arg in sys.argv)) - - # prepare for other cleanup - with Janitor(LOGF) as janitor: - - # Under some circumstances, this script seems to be invoked with a - # nonexistent pathname. Check for that. - if not os.path.isfile(dmgfile): - fail(dmgfile + " has been deleted") - - # Try to derive the name of the running viewer app bundle from our - # own pathname. (Hopefully the old viewer won't copy this script - # to a temp dir before running!) - # Somewhat peculiarly, this script is currently packaged in - # Appname.app/Contents/MacOS with the viewer executable. But even - # if we decide to move it to Appname.app/Contents/Resources, we'll - # still find Appname.app two levels up from dirname(__file__). - appdir = os.path.abspath(os.path.join(os.path.dirname(__file__), - os.pardir, os.pardir)) - if not appdir.endswith(".app"): - # This can happen if either this script has been copied before - # being executed, or if it's in an unexpected place in the app - # bundle. - fail(appdir + " is not an application directory") - - # We need to install into appdir's parent directory -- can we? - installdir = os.path.abspath(os.path.join(appdir, os.pardir)) - if not os.access(installdir, os.W_OK): - fail("Can't modify " + installdir) - - # invent a temporary directory - tempdir = tempfile.mkdtemp() - log("created " + tempdir) - # clean it up when we leave - janitor.later(shutil.rmtree, tempdir) - - status("Mounting image...") - - mntdir = os.path.join(tempdir, "mnt") - log("mkdir " + mntdir) - os.mkdir(mntdir) - command = ["hdiutil", "attach", dmgfile, "-mountpoint", mntdir] - log(' '.join(command)) - # Instantiating subprocess.Popen launches a child process with the - # specified command line. stdout=PIPE passes a pipe to its stdout. - hdiutil = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=LOGF) - # Popen.communicate() reads that pipe until the child process - # terminates, returning (stdout, stderr) output. Select just stdout. - hdiutil_out = hdiutil.communicate()[0] - if hdiutil.returncode != 0: - fail("Couldn't mount " + dmgfile) - # hdiutil should report the devnode. Find that. - found = re.search(r"/dev/[^ ]*\b", hdiutil_out) - if not found: - # If we don't spot the devnode, log it and continue -- we only - # use it to detach it. Don't fail the whole update if we can't - # clean up properly. - log("Couldn't spot devnode in hdiutil output:\n" + hdiutil_out) - else: - # If we do spot the devnode, detach it when done. - janitor.later(subprocess.call, ["hdiutil", "detach", found.group(0)], - stdout=LOGF, stderr=subprocess.STDOUT) - - status("Searching for app bundle...") - - for candidate in glob.glob(os.path.join(mntdir, "*.app")): - log("Considering " + candidate) - try: - # By convention, a valid Mac app bundle has a - # Contents/Info.plist file containing at least - # CFBundleIdentifier. - CFBundleIdentifier = \ - plistlib.readPlist(os.path.join(candidate, "Contents", - "Info.plist"))["CFBundleIdentifier"] - except Exception, err: - # might be IOError, xml.parsers.expat.ExpatError, KeyError - # Any of these means it's not a valid app bundle. Instead - # of aborting, just skip this candidate and continue. - log("%s not a valid app bundle: %s: %s" % - (candidate, err.__class__.__name__, err)) - continue - - if CFBundleIdentifier == BUNDLE_IDENTIFIER: - break - - log("unrecognized CFBundleIdentifier: " + CFBundleIdentifier) - - else: - fail("Could not find Second Life viewer in " + dmgfile) - - # Here 'candidate' is the new viewer to install - log("Found " + candidate) - - # This logic was changed to make Mac updates behave more like - # Windows. Most of the time, the user doesn't change the name of - # the app bundle on our .dmg installer (e.g. "Second Life Beta - # Viewer.app"). Most of the time, the version manager directs a - # given viewer to update to another .dmg containing an app bundle - # with THE SAME name. In that case, everything behaves as usual. - - # The case that was changed is when the version manager offers (or - # mandates) an update to a .dmg containing a different app bundle - # name. This can happen, for instance, to a user who's downloaded - # a "project beta" viewer, and the project subsequently publishes - # a Release Candidate viewer. Say the project beta's app bundle - # name is something like "Second Life Beta Neato.app". Anyone - # launching that viewer will be offered an update to the - # corresponding Release Candidate viewer -- which will be built as - # a release viewer, with app bundle name "Second Life Viewer.app". - - # On Windows, we run the NSIS installer, which will update/replace - # the embedded install directory name, e.g. Second Life Viewer. - # But the Mac installer used to locate the app bundle name in the - # mounted .dmg file, then ignore that name, copying its contents - # into the app bundle directory of the running viewer. That is, - # we'd install the Release Candidate from the .dmg's "Second - # Life.app" into "/Applications/Second Life Beta Neato.app". This - # is undesired behavior. - - # Instead, having found the app bundle name on the mounted .dmg, - # we try to install that app bundle name into the parent directory - # of the running app bundle. - - # Are we installing a different app bundle name? If so, call it - # out, both in the log and for the user -- this is an odd case. - # (Presumably they've already agreed to a similar notification in - # the viewer before the viewer launched this script, but still.) - bundlename = os.path.basename(candidate) - if os.path.basename(appdir) == bundlename: - # updating the running app bundle, which we KNOW exists - appexists = True - else: - # installing some other app bundle - newapp = os.path.join(installdir, bundlename) - appexists = os.path.exists(newapp) - message = "Note: %s %s %s" % \ - (appdir, "updating" if appexists else "installing new", newapp) - status(message) - # okay, we have no further need of the name of the running app - # bundle. - appdir = newapp - - status("Preparing to copy files...") - - if appexists: - # move old viewer to temp location in case copy from .dmg fails - aside = os.path.join(tempdir, os.path.basename(appdir)) - log("mv %r %r" % (appdir, aside)) - # Use shutil.move() instead of os.rename(). move() first tries - # os.rename(), but falls back to shutil.copytree() if the dest is - # on a different filesystem. - shutil.move(appdir, aside) - - status("Copying files...") - - # shutil.copytree()'s target must not already exist. But we just - # moved appdir out of the way. - log("cp -p %r %r" % (candidate, appdir)) - try: - # The viewer app bundle does include internal symlinks. Keep them - # as symlinks. - shutil.copytree(candidate, appdir, symlinks=True) - except Exception, err: - # copy failed -- try to restore previous viewer before crumping - type, value, traceback = sys.exc_info() - if appexists: - log("exception response: mv %r %r" % (aside, appdir)) - shutil.move(aside, appdir) - # let our previously-set sys.excepthook handle this - raise type, value, traceback - - status("Cleaning up...") - - log("touch " + appdir) - os.utime(appdir, None) # set to current time - - # MAINT-3331: remove STATE_DIR. Empirically, this resolves a - # persistent, mysterious crash after updating our viewer on an OS - # X 10.7.5 system. - log("rm -rf '%s'" % STATE_DIR) - with allow_errno(errno.ENOENT): - shutil.rmtree(STATE_DIR) - - command = ["open", appdir] - log(' '.join(command)) - subprocess.check_call(command, stdout=LOGF, stderr=subprocess.STDOUT) - - # If all the above succeeded, delete the .dmg file. We don't do this - # as a janitor.later() operation because we only want to do it if we - # get this far successfully. Note that this is out of the scope of the - # Janitor: we must detach the .dmg before removing it! - log("rm " + dmgfile) - os.remove(dmgfile) - - except Exception, err: - # Because we carefully set sys.excepthook -- and even modify it to log - # the problem once we have our log file open -- you might think we - # could just let exceptions propagate. But when we do that, on - # exception in this block, we FIRST restore the no-side-effects fail() - # and THEN implicitly call sys.excepthook(), which calls the (no-side- - # effects) fail(). Explicitly call sys.excepthook() BEFORE restoring - # fail(). Only then do we get the enriched fail() behavior. - sys.excepthook(*sys.exc_info()) - - finally: - # When we leave main() -- for whatever reason -- reset fail() the way - # it was before, because the bound markerfile, markertext params - # passed to this main() call are no longer applicable. - fail = oldfail - -if __name__ == "__main__": - # We expect this script to be invoked with: - # - the pathname to the .dmg we intend to install; - # - the pathname to an update-error marker file to create on failure; - # - the content to write into the marker file. - main(*sys.argv[1:]) diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install deleted file mode 100755 index 03089f192e..0000000000 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ /dev/null @@ -1,220 +0,0 @@ -#! /bin/bash - -# @file update_install -# @author Nat Goodspeed -# @date 2013-01-09 -# @brief Update the containing Second Life application bundle to the version in -# the specified tarball. -# -# This bash implementation is derived from the previous linux-updater.bin -# application. -# -# $LicenseInfo:firstyear=2013&license=viewerlgpl$ -# Copyright (c) 2013, Linden Research, Inc. -# $/LicenseInfo$ - -# **************************************************************************** -# script parameters -# **************************************************************************** -tarball="$1" # the file to install -markerfile="$2" # create this file on failure -mandatory="$3" # what to write to markerfile on failure - -# **************************************************************************** -# helper functions -# **************************************************************************** -# empty array -cleanups=() - -# add a cleanup action to execute on exit -function cleanup { - # wacky bash syntax for appending to array - cleanups[${#cleanups[*]}]="$*" -} - -# called implicitly on exit -function onexit { - for action in "${cleanups[@]}" - do # don't quote, support actions consisting of multiple words - $action - done -} -trap 'onexit' EXIT - -# write to log file -function log { - # our log file will be open as stderr -- but until we set up that - # redirection, logging to stderr is better than nothing - echo "$*" 1>&2 -} - -# We display status by leaving one background xmessage process running. This -# is the pid of that process. -statuspid="" - -function clear_message { - [ -n "$statuspid" ] && kill $statuspid - statuspid="" -} - -# make sure we remove any message box we might have put up -cleanup clear_message - -# can we use zenity, or must we fall back to xmessage? -zenpath="$(which zenity)" -if [ -n "$zenpath" ] -then # zenity on PATH and is executable - # display a message box and continue - function status { - # clear any previous message - clear_message - # put up a new zenity box and capture its pid -## "$zenpath" --info --title "Second Life Viewer Updater" \ -## --width=320 --height=120 --text="$*" & - # MAINT-2333: use bouncing progress bar - "$zenpath" --progress --pulsate --no-cancel --title "Second Life Viewer Updater" \ - --width=320 --height=120 --text "$*" </dev/null & - statuspid=$! - } - - # display an error box and wait for user - function errorbox { - "$zenpath" --error --title "Second Life Viewer Updater" \ - --width=320 --height=120 --text="$*" - } - -else # no zenity, use xmessage instead - # display a message box and continue - function status { - # clear any previous message - clear_message - # put up a new xmessage and capture its pid - xmessage -buttons OK:2 -center "$*" & - statuspid=$! - } - - # display an error box and wait for user - function errorbox { - xmessage -buttons OK:2 -center "$*" - } -fi - -# display an error box and terminate -function fail { - # Log the message - log "$@" - # tell subsequent viewer things went south - echo "$mandatory" > "$markerfile" - # add boilerplate - errorbox "An error occurred while updating Second Life: -$* -Please download the latest viewer from www.secondlife.com." - exit 1 -} - -# Find a graphical sudo program and define mysudo function. On error, $? is -# nonzero; output is in $err instead of being written to stdout/stderr. -gksudo="$(which gksudo)" -kdesu="$(which kdesu)" -if [ -n "$gksudo" ] -then function mysudo { - # gksudo allows you to specify description - err="$("$gksudo" --description "Second Life Viewer Updater" "$@" 2>&1)" - } -elif [ -n "$kdesu" ] -then function mysudo { - err="$("$kdesu" "$@" 2>&1)" - } -else # couldn't find either one, just try it anyway - function mysudo { - err="$("$@" 2>&1)" - } -fi - -# Move directories, using mysudo if we think it necessary. On error, $? is -# nonzero; output is in $err instead of being written to stdout/stderr. -function sudo_mv { - # If we have write permission to both parent directories, shouldn't need - # sudo. - if [ -w "$(dirname "$1")" -a -w "$(dirname "$2")" ] - then err="$(mv "$@" 2>&1)" - else # use available sudo program; mysudo sets $? and $err - mysudo mv "$@" - fi -} - -# **************************************************************************** -# main script logic -# **************************************************************************** -mydir="$(dirname "$0")" -# We happen to know that the viewer specifies a marker-file pathname within -# the logs directory. -logsdir="$(dirname "$markerfile")" -logname="$logsdir/updater.log" - -# move aside old updater.log; we're about to create a new one -[ -f "$logname" ] && mv "$logname" "$logname.old" - -# Set up redirections for this script such that stderr is logged. (But first -# move the previous stderr to file descriptor 3.) -exec 3>&2- 2> "$logname" - -# Rather than setting up a special pipeline to timestamp every line of stderr, -# produce header lines into log file indicating timestamp and the arguments -# with which we were invoked. -date 1>&2 -log "$0 $*" - -# Log every command we execute, along with any stderr it might produce -set -x - -status 'Installing Second Life...' - -# Creating tempdir under /tmp means it's possible that tempdir is on a -# different filesystem than INSTALL_DIR. One is tempted to create tempdir on a -# path derived from `dirname INSTALL_DIR` -- but it seems modern 'mv' can -# handle moving across filesystems?? -tempdir="$(mktemp -d)" -tempinstall="$tempdir/install" -# capture the actual error message, if any -err="$(mkdir -p "$tempinstall" 2>&1)" || fail "$err" -cleanup rm -rf "$tempdir" - -# If we already knew the name of the tarball's top-level directory, we could -# just move that when all was said and done. Since we don't, untarring to the -# 'install' subdir with --strip 1 effectively renames that top-level -# directory. -# untar failures tend to be voluminous -- don't even try to capture, just log -tar --strip 1 -xjf "$tarball" -C "$tempinstall" || fail "Untar command failed" - -INSTALL_DIR="$(cd "$mydir/.." ; pwd)" - -# Considering we're launched from a subdirectory of INSTALL_DIR, would be -# surprising if it did NOT already exist... -if [ -e "$INSTALL_DIR" ] -then backup="$INSTALL_DIR.backup" - backupn=1 - while [ -e "$backup" ] - do backup="$INSTALL_DIR.backup.$backupn" - ((backupn += 1)) - done - # on error, fail with actual error message from sudo_mv: permissions, - # cross-filesystem mv, ...? - sudo_mv "$INSTALL_DIR" "$backup" || fail "$err" -fi -# We unpacked the tarball into tempinstall. Move that. -if ! sudo_mv "$tempinstall" "$INSTALL_DIR" -then # If we failed to move the temp install to INSTALL_DIR, try to restore - # INSTALL_DIR from backup. Save $err because next sudo_mv will trash it! - realerr="$err" - sudo_mv "$backup" "$INSTALL_DIR" - fail "$realerr" -fi - -# Removing the tarball here, rather than with a 'cleanup' action, means we -# only remove it if we succeeded. -rm -f "$tarball" - -# Launch the updated viewer. Restore original stderr from file descriptor 3, -# though -- otherwise updater.log gets cluttered with the viewer log! -"$INSTALL_DIR/secondlife" 2>&3- & diff --git a/indra/viewer_components/updater/scripts/windows/update_install.bat b/indra/viewer_components/updater/scripts/windows/update_install.bat deleted file mode 100644 index 96687226a8..0000000000 --- a/indra/viewer_components/updater/scripts/windows/update_install.bat +++ /dev/null @@ -1,3 +0,0 @@ -start /WAIT %1 /SKIP_DIALOGS
-IF ERRORLEVEL 1 ECHO %3 > %2
-DEL %1
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp deleted file mode 100644 index 759e41ef4c..0000000000 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file llupdaterservice_test.cpp - * @brief Tests of llupdaterservice.cpp. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Precompiled header -#include "linden_common.h" -// associated header -#include "../llupdaterservice.h" -#include "../llupdatechecker.h" -#include "../llupdatedownloader.h" -#include "../llupdateinstaller.h" - -#include "../../../test/lltut.h" -//#define DEBUG_ON -#include "../../../test/debug.h" - -#include "llevents.h" -#include "lldir.h" - -/***************************************************************************** -* MOCK'd -*****************************************************************************/ -LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) -{} -void LLUpdateChecker::checkVersion(std::string const & urlBase, - std::string const & channel, - std::string const & version, - std::string const & platform, - std::string const & platform_version, - unsigned char uniqueid[MD5HEX_STR_SIZE], - bool willing_to_test) -{} -LLUpdateDownloader::LLUpdateDownloader(Client & ) {} -void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, std::string const &, std::string const &, bool){} - -class LLDir_Mock : public LLDir -{ - void initAppDirs(const std::string &app_name, - const std::string& app_read_only_data_dir = "") {} - U32 countFilesInDir(const std::string &dirname, const std::string &mask) - { - return 0; - } - - void getRandomFileInDir(const std::string &dirname, - const std::string &mask, - std::string &fname) {} - std::string getCurPath() { return ""; } - bool fileExists(const std::string &filename) const { return false; } - std::string getLLPluginLauncher() { return ""; } - std::string getLLPluginFilename(std::string base_name) { return ""; } - -} gDirUtil; -LLDir* gDirUtilp = &gDirUtil; -LLDir::LLDir() {} -LLDir::~LLDir() {} -S32 LLDir::deleteFilesInDir(const std::string &dirname, - const std::string &mask) -{ return 0; } - -void LLDir::setChatLogsDir(const std::string &path){} -void LLDir::setPerAccountChatLogsDir(const std::string &username){} -void LLDir::setLindenUserDir(const std::string &username){} -void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language){} -std::string LLDir::getSkinFolder() const { return "default"; } -std::string LLDir::getLanguage() const { return "en"; } -bool LLDir::setCacheDir(const std::string &path){ return true; } -void LLDir::dumpCurrentDirectories() {} -void LLDir::updatePerAccountChatLogsDir() {} - -#include "llviewernetwork.h" -LLGridManager::LLGridManager() : - mGrid("test.grid.lindenlab.com"), - mIsInProductionGrid(false) -{ -} -std::string LLGridManager::getUpdateServiceURL() -{ - return "https://update.secondlife.com/update"; -} -LLGridManager::~LLGridManager() -{ -} - - -std::string LLDir::getExpandedFilename(ELLPath location, - const std::string &filename) const -{ - return ""; -} - -std::string LLUpdateDownloader::downloadMarkerPath(void) -{ - return ""; -} - -void LLUpdateDownloader::resume(void) {} -void LLUpdateDownloader::cancel(void) {} -void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {} - -int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode) -{ - return 0; -} - -std::string const & ll_install_failed_marker_path() -{ - static std::string wubba; - return wubba; -} - -/* -#pragma warning(disable: 4273) -llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename, - ios_base::openmode _Mode, - int _Prot) : - std::basic_istream<char,std::char_traits< char > >(NULL,true) -{} - -llus_mock_llifstream::~llus_mock_llifstream() {} -bool llus_mock_llifstream::is_open() const {return true;} -void llus_mock_llifstream::close() {} -*/ - -/***************************************************************************** -* TUT -*****************************************************************************/ -namespace tut -{ - struct llupdaterservice_data - { - llupdaterservice_data() : - pumps(LLEventPumps::instance()), - test_url("dummy_url"), - test_channel("dummy_channel"), - test_version("dummy_version") - {} - LLEventPumps& pumps; - std::string test_url; - std::string test_channel; - std::string test_version; - }; - - typedef test_group<llupdaterservice_data> llupdaterservice_group; - typedef llupdaterservice_group::object llupdaterservice_object; - llupdaterservice_group llupdaterservicegrp("LLUpdaterService"); - - template<> template<> - void llupdaterservice_object::test<1>() - { - DEBUG; - LLUpdaterService updater; - bool got_usage_error = false; - try - { - updater.startChecking(); - } - catch(LLUpdaterService::UsageError) - { - got_usage_error = true; - } - ensure("Caught start before params", got_usage_error); - } - - template<> template<> - void llupdaterservice_object::test<2>() - { - DEBUG; - LLUpdaterService updater; - bool got_usage_error = false; - try - { - unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111"; - updater.initialize(test_channel, test_version, "win", "1.2.3", id1, true); - updater.startChecking(); - unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222"; - updater.initialize(test_channel, test_version, "win", "4.5.6", id2, true); - } - catch(LLUpdaterService::UsageError) - { - got_usage_error = true; - } - ensure("Caught params while running", got_usage_error); - } - - template<> template<> - void llupdaterservice_object::test<3>() - { - DEBUG; - LLUpdaterService updater; - unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333"; - updater.initialize(test_channel, test_version, "win", "7.8.9", id, true); - updater.startChecking(); - ensure(updater.isChecking()); - updater.stopChecking(); - ensure(!updater.isChecking()); - } -} |