summaryrefslogtreecommitdiff
path: root/indra/viewer_components
diff options
context:
space:
mode:
Diffstat (limited to 'indra/viewer_components')
-rw-r--r--indra/viewer_components/login/lllogin.cpp10
-rw-r--r--indra/viewer_components/updater/llupdatechecker.cpp62
-rw-r--r--indra/viewer_components/updater/llupdatechecker.h36
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.cpp95
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.cpp20
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp4
-rw-r--r--indra/viewer_components/updater/scripts/linux/update_install219
-rw-r--r--indra/viewer_components/updater/tests/llupdaterservice_test.cpp11
8 files changed, 345 insertions, 112 deletions
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index d480b63094..bdcb068200 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -271,6 +271,16 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
}
return; // Done!
}
+
+ /* Sometimes we end with "Started" here. Slightly slow server?
+ * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
+ */
+ if( status == "Started")
+ {
+ LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
+ continue;
+ }
+
// If we don't recognize status at all, trouble
if (! (status == "CURLError"
|| status == "XMLRPCError"
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index c6aa9b0f11..5edbbf9914 100644
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -30,7 +30,9 @@
#include "llsd.h"
#include "llupdatechecker.h"
#include "lluri.h"
-
+#if LL_DARWIN
+#include <CoreServices/CoreServices.h>
+#endif
#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
@@ -49,37 +51,6 @@ public:
};
-class LLUpdateChecker::Implementation:
- public LLHTTPClient::Responder
-{
-public:
- Implementation(Client & client);
- ~Implementation();
- void check(std::string const & protocolVersion, std::string const & hostUrl,
- std::string const & servicePath, std::string channel, std::string version);
-
- // Responder:
- virtual void completed(U32 status,
- const std::string & reason,
- const LLSD& content);
- virtual void error(U32 status, const std::string & reason);
-
-private:
- static const char * sProtocolVersion;
-
- Client & mClient;
- LLHTTPClient mHttpClient;
- bool mInProgress;
- std::string mVersion;
-
- std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl,
- std::string const & servicePath, std::string channel, std::string version);
-
- LOG_CLASS(LLUpdateChecker::Implementation);
-};
-
-
-
// LLUpdateChecker
//-----------------------------------------------------------------------------
@@ -91,10 +62,10 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
}
-void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,
+void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl,
std::string const & servicePath, std::string channel, std::string version)
{
- mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version);
+ mImplementation->checkVersion(protocolVersion, hostUrl, servicePath, channel, version);
}
@@ -120,7 +91,7 @@ LLUpdateChecker::Implementation::~Implementation()
}
-void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl,
+void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolVersion, std::string const & hostUrl,
std::string const & servicePath, std::string channel, std::string version)
{
llassert(!mInProgress);
@@ -132,13 +103,7 @@ void LLUpdateChecker::Implementation::check(std::string const & protocolVersion,
std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version);
LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
- // The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the
- // passed object to be silently and automatically deleted. We pass a self-
- // referential intrusive pointer to which we add a reference to keep the
- // client from deleting the update checker implementation instance.
- LLHTTPClient::ResponderPtr temporaryPtr(this);
- boost::intrusive_ptr_add_ref(temporaryPtr.get());
- mHttpClient.get(checkUrl, temporaryPtr);
+ mHttpClient.get(checkUrl, this);
}
void LLUpdateChecker::Implementation::completed(U32 status,
@@ -179,7 +144,18 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protoc
#ifdef LL_WINDOWS
static const char * platform = "win";
#elif LL_DARWIN
- static const char * platform = "mac";
+ long versMin;
+ Gestalt(gestaltSystemVersionMinor, &versMin);
+
+ static const char *platform;
+ if (versMin == 5) //OS 10.5
+ {
+ platform = "mac_legacy";
+ }
+ else
+ {
+ platform = "mac";
+ }
#else
static const char * platform = "lnx";
#endif
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
index cea1f13647..23f62a7c5e 100644
--- a/indra/viewer_components/updater/llupdatechecker.h
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -29,6 +29,7 @@
#include <boost/shared_ptr.hpp>
+#include "llhttpclient.h"
//
// Implements asynchronous checking for updates.
@@ -36,7 +37,36 @@
class LLUpdateChecker {
public:
class Client;
- class Implementation;
+ class Implementation:
+
+ public LLHTTPClient::Responder
+ {
+ public:
+ Implementation(Client & client);
+ ~Implementation();
+ void checkVersion(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version);
+
+ // Responder:
+ virtual void completed(U32 status,
+ const std::string & reason,
+ const LLSD& content);
+ virtual void error(U32 status, const std::string & reason);
+
+ private:
+ static const char * sProtocolVersion;
+
+ Client & mClient;
+ LLHTTPClient mHttpClient;
+ bool mInProgress;
+ std::string mVersion;
+
+ std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version);
+
+ LOG_CLASS(LLUpdateChecker::Implementation);
+ };
+
// An exception that may be raised on check errors.
class CheckError;
@@ -44,11 +74,11 @@ public:
LLUpdateChecker(Client & client);
// Check status of current app on the given host for the channel and version provided.
- void check(std::string const & protocolVersion, std::string const & hostUrl,
+ void checkVersion(std::string const & protocolVersion, std::string const & hostUrl,
std::string const & servicePath, std::string channel, std::string version);
private:
- boost::shared_ptr<Implementation> mImplementation;
+ LLPointer<Implementation> mImplementation;
};
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index e88d1bf811..75e455e3f6 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @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$
*/
@@ -39,7 +39,7 @@
#include "llsdserialize.h"
#include "llthread.h"
#include "llupdaterservice.h"
-
+#include "llcurl.h"
class LLUpdateDownloader::Implementation:
public LLThread
@@ -58,7 +58,7 @@ public:
int onProgress(double downloadSize, double bytesDownloaded);
void resume(void);
void setBandwidthLimit(U64 bytesPerSecond);
-
+
private:
curl_off_t mBandwidthLimit;
bool mCancelled;
@@ -69,7 +69,7 @@ private:
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);
@@ -93,7 +93,7 @@ namespace {
}
};
-
+
const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml";
};
@@ -192,19 +192,25 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client &
mHeaderList(0)
{
CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case.
- llverify(code == CURLE_OK); // TODO: real error handling here.
+ llverify(code == CURLE_OK); // TODO: real error handling here.
}
LLUpdateDownloader::Implementation::~Implementation()
{
- if(isDownloading()) {
+ if(isDownloading())
+ {
cancel();
shutdown();
- } else {
+ }
+ else
+ {
; // No op.
}
- if(mCurl) curl_easy_cleanup(mCurl);
+ if(mCurl)
+ {
+ LLCurl::deleteEasyHandle(mCurl);
+ }
}
@@ -212,7 +218,7 @@ void LLUpdateDownloader::Implementation::cancel(void)
{
mCancelled = true;
}
-
+
void LLUpdateDownloader::Implementation::download(LLURI const & uri,
std::string const & hash,
@@ -253,24 +259,24 @@ void LLUpdateDownloader::Implementation::resume(void)
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)) {
+ if(LLFile::isfile(filePath)) {
llstat fileStatus;
LLFile::stat(filePath, &fileStatus);
if(fileStatus.st_size != mDownloadData["size"].asInteger()) {
resumeDownloading(fileStatus.st_size);
} else if(!validateDownload()) {
LLFile::remove(filePath);
- download(LLURI(mDownloadData["url"].asString()),
+ download(LLURI(mDownloadData["url"].asString()),
mDownloadData["hash"].asString(),
mDownloadData["update_version"].asString(),
mDownloadData["required"].asBoolean());
@@ -278,7 +284,7 @@ void LLUpdateDownloader::Implementation::resume(void)
mClient.downloadComplete(mDownloadData);
}
} else {
- download(LLURI(mDownloadData["url"].asString()),
+ download(LLURI(mDownloadData["url"].asString()),
mDownloadData["hash"].asString(),
mDownloadData["update_version"].asString(),
mDownloadData["required"].asBoolean());
@@ -295,7 +301,7 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond)
llassert(mCurl != 0);
mBandwidthLimit = bytesPerSecond;
CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit);
- if(code != CURLE_OK) LL_WARNS("UpdateDownload") <<
+ if(code != CURLE_OK) LL_WARNS("UpdateDownload") <<
"unable to change dowload bandwidth" << LL_ENDL;
} else {
mBandwidthLimit = bytesPerSecond;
@@ -309,7 +315,7 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
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);
@@ -317,18 +323,18 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1);
size_t size = boost::lexical_cast<size_t>(contentLength);
LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL;
-
+
mDownloadData["size"] = LLSD(LLSD::Integer(size));
llofstream odataStream(mDownloadRecordPath);
LLSDSerialize::toPrettyXML(mDownloadData, odataStream);
} catch (std::exception const & e) {
- LL_WARNS("UpdateDownload") << "unable to read content length ("
+ LL_WARNS("UpdateDownload") << "unable to read content length ("
<< e.what() << ")" << LL_ENDL;
}
} else {
; // No op.
}
-
+
return size;
}
@@ -336,9 +342,9 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t 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(reinterpret_cast<const char *>(buffer), size);
+ if((size == 0) || (buffer == 0)) return 0;
+
+ mDownloadStream.write(static_cast<const char *>(buffer), size);
if(mDownloadStream.bad()) {
return 0;
} else {
@@ -352,7 +358,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b
int downloadPercent = static_cast<int>(100. * (bytesDownloaded / downloadSize));
if(downloadPercent > mDownloadPercent) {
mDownloadPercent = downloadPercent;
-
+
LLSD event;
event["pump"] = LLUpdaterService::pumpName();
LLSD payload;
@@ -361,12 +367,12 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b
payload["bytes_downloaded"] = bytesDownloaded;
event["payload"] = payload;
LLEventPumps::instance().obtain("mainlooprepeater").post(event);
-
+
LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL;
} else {
; // Keep events to a reasonalbe number.
}
-
+
return 0;
}
@@ -390,13 +396,13 @@ void LLUpdateDownloader::Implementation::run(void)
LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL;
// Do not call back client.
} else {
- LL_WARNS("UpdateDownload") << "download failed with error '" <<
+ LL_WARNS("UpdateDownload") << "download failed with error '" <<
curl_easy_strerror(code) << "'" << LL_ENDL;
LLFile::remove(mDownloadRecordPath);
if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString());
mClient.downloadError("curl error");
}
-
+
if(mHeaderList) {
curl_slist_free_all(mHeaderList);
mHeaderList = 0;
@@ -406,14 +412,17 @@ void LLUpdateDownloader::Implementation::run(void)
void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)
{
- if(mCurl == 0) {
- mCurl = curl_easy_init();
- } else {
+ if(mCurl == 0)
+ {
+ mCurl = LLCurl::newEasyHandle();
+ }
+ else
+ {
curl_easy_reset(mCurl);
}
-
+
if(mCurl == 0) throw DownloadError("failed to initialize curl");
-
+
throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true));
throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true));
throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function));
@@ -430,7 +439,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
// 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, CURLOPT_MAX_RECV_SPEED_LARGE, limit));
-
+
mDownloadPercent = 0;
}
@@ -441,7 +450,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
<< " 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-");
@@ -449,7 +458,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
if(mHeaderList == 0) throw DownloadError("cannot add Range header");
throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList));
-
+
mDownloadStream.open(mDownloadData["path"].asString(),
std::ios_base::out | std::ios_base::binary | std::ios_base::app);
start();
@@ -470,10 +479,10 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std
LL_INFOS("UpdateDownload") << "downloading " << filePath
<< " from " << uri.asString() << LL_ENDL;
LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL;
-
+
llofstream dataStream(mDownloadRecordPath);
LLSDSerialize::toPrettyXML(mDownloadData, dataStream);
-
+
mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary);
initializeCurlGet(uri.asString(), true);
start();
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index c7b70c2de8..2f87d59373 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -26,10 +26,10 @@
#include "linden_common.h"
#include <apr_file_io.h>
#include "llapr.h"
-#include "llprocesslauncher.h"
+#include "llprocess.h"
#include "llupdateinstaller.h"
#include "lldir.h"
-
+#include "llsd.h"
#if defined(LL_WINDOWS)
#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!).
@@ -78,15 +78,13 @@ int ll_install_update(std::string const & script,
llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
actualScriptPath << LL_ENDL;
- LLProcessLauncher launcher;
- launcher.setExecutable(actualScriptPath);
- launcher.addArgument(updatePath);
- launcher.addArgument(ll_install_failed_marker_path().c_str());
- launcher.addArgument(boost::lexical_cast<std::string>(required));
- int result = launcher.launch();
- launcher.orphan();
-
- return result;
+ 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;
}
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 1888f191e2..bc73c72ddc 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -447,7 +447,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
LL_INFOS("UpdaterService") << "will check for update again in " <<
seconds << " seconds" << LL_ENDL;
mTimer.start();
- mTimer.setTimerExpirySec(seconds);
+ mTimer.setTimerExpirySec((F32)seconds);
LLEventPumps::instance().obtain("mainloop").listen(
sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
}
@@ -509,7 +509,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
}
else
{
- mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
+ mUpdateChecker.checkVersion(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
setState(LLUpdaterService::CHECKING_FOR_UPDATE);
}
}
diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install
index e0505a9f72..a9df9042fd 100644
--- a/indra/viewer_components/updater/scripts/linux/update_install
+++ b/indra/viewer_components/updater/scripts/linux/update_install
@@ -1,10 +1,217 @@
#! /bin/bash
-INSTALL_DIR=$(cd "$(dirname "$0")/.." ; pwd)
-export LD_LIBRARY_PATH="$INSTALL_DIR/lib"
-bin/linux-updater.bin --file "$1" --dest "$INSTALL_DIR" --name "Second Life Viewer" --stringsdir "$INSTALL_DIR/skins/default/xui/en" --stringsfile "strings.xml"
-if [ $? -ne 0 ]
- then echo $3 >> "$2"
+# @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="$*" &
+ 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
-rm -f "$1"
+# 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/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index e19d5724f1..de07beee7c 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llupdaterservice_test.cpp
* @brief Tests of llupdaterservice.cpp.
*
@@ -44,7 +44,7 @@
*****************************************************************************/
LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
{}
-void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,
+void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl,
std::string const & servicePath, std::string channel, std::string version)
{}
LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
@@ -63,7 +63,7 @@ class LLDir_Mock : public LLDir
const std::string &mask,
std::string &fname) {}
std::string getCurPath() { return ""; }
- BOOL fileExists(const std::string &filename) const { return false; }
+ bool fileExists(const std::string &filename) const { return false; }
std::string getLLPluginLauncher() { return ""; }
std::string getLLPluginFilename(std::string base_name) { return ""; }
@@ -78,9 +78,12 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname,
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){}
+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() {}
std::string LLDir::getExpandedFilename(ELLPath location,
const std::string &filename) const