diff options
20 files changed, 367 insertions, 2813 deletions
@@ -402,3 +402,15 @@ af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276 8302fefde6c8f4a64bfc7f04929f8bc85f5c6c7b DRTVWR-279 c296133849d1f103c0e2abc41e6599daed00b67b DRTVWR-280 40a2265058abc9fde4914c10185f916435818621 3.4.5-beta1 +5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281 +7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283 +6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2 +37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282 +6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284 +ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286 +2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287 +e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3 +a676b4d6c037b39fe5b8e42cf8839a9303936089 DRTVWR-289 +28fa8b944a0c1869636ab00cc400f5aa71f6fa3c DRTVWR-290 +7f09bbc28c297f14b67961be7b6575445fa160e8 DRTVWR-291 +b23419a2748483c98f3b84b630468a21c88feba5 DRTVWR-292 diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 24c98bfada..001bb4b935 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -82,8 +82,7 @@ if (VIEWER) if (LINUX) add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) - add_subdirectory(${VIEWER_PREFIX}linux_updater) - add_dependencies(viewer linux-crash-logger-strip-target linux-updater) + add_dependencies(viewer linux-crash-logger-strip-target) elseif (DARWIN) add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) add_subdirectory(${VIEWER_PREFIX}mac_updater) diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt deleted file mode 100644 index 4377a6333c..0000000000 --- a/indra/linux_updater/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -*- cmake -*- - -project(linux_updater) - -include(00-Common) -include(CURL) -include(CARes) -include(OpenSSL) -include(UI) -include(LLCommon) -include(LLVFS) -include(LLXML) -include(LLUI) -include(Linking) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLVFS_INCLUDE_DIRS} - ${LLXML_INCLUDE_DIRS} - ${LLUI_INCLUDE_DIRS} - ${CURL_INCLUDE_DIRS} - ${CARES_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIRS} - ${UI_INCLUDE_DIRS} - ) - -set(linux_updater_SOURCE_FILES linux_updater.cpp) - -set(linux_updater_HEADER_FILES CMakeLists.txt) - -set_source_files_properties(${linux_updater_HEADER_FILES} - PROPERTIES HEADER_FILES_ONLY TRUE) - -list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES}) - -add_executable(linux-updater ${linux_updater_SOURCE_FILES}) - -target_link_libraries(linux-updater - ${CURL_LIBRARIES} - ${CARES_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${CRYPTO_LIBRARIES} - ${UI_LIBRARIES} - ${LLXML_LIBRARIES} - ${LLUI_LIBRARIES} - ${LLVFS_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ) - -add_custom_target(linux-updater-target ALL - DEPENDS linux-updater) diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp deleted file mode 100644 index 991dfd9dce..0000000000 --- a/indra/linux_updater/linux_updater.cpp +++ /dev/null @@ -1,926 +0,0 @@ -/** - * @file linux_updater.cpp - * @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden - * @brief Viewer update program for unix platforms that support GTK+ - * - * $LicenseInfo:firstyear=2008&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 <unistd.h> -#include <signal.h> -#include <errno.h> - -#include "linden_common.h" -#include "llerrorcontrol.h" -#include "llfile.h" -#include "lldir.h" -#include "lldiriterator.h" - -/*==========================================================================*| -// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy. -// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable. -#include "llxmlnode.h" -#include "lltrans.h" -|*==========================================================================*/ - -static class LLTrans -{ -public: - LLTrans(); - static std::string getString(const std::string& key); - -private: - std::string _getString(const std::string& key) const; - - typedef std::map<std::string, std::string> MessageMap; - MessageMap mMessages; -} sLLTransInstance; - -#include <curl/curl.h> -#include <map> -#include <boost/foreach.hpp> - -extern "C" { -#include <gtk/gtk.h> -} - -const guint UPDATE_PROGRESS_TIMEOUT = 100; -const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000; -const guint ROTATE_IMAGE_TIMEOUT = 8000; - -typedef struct _updater_app_state { - std::string app_name; - std::string url; - std::string file; - std::string image_dir; - std::string dest_dir; - std::string strings_dirs; - std::string strings_file; - - LLDirIterator *image_dir_iter; - - GtkWidget *window; - GtkWidget *progress_bar; - GtkWidget *image; - - double progress_value; - bool activity_mode; - - guint image_rotation_timeout_id; - guint progress_update_timeout_id; - guint update_progress_text_timeout_id; - - bool failure; -} UpdaterAppState; - -// List of entries from strings.xml to always replace -static std::set<std::string> default_trans_args; -void init_default_trans_args() -{ - default_trans_args.insert("SECOND_LIFE"); // World - default_trans_args.insert("APP_NAME"); - default_trans_args.insert("SECOND_LIFE_GRID"); - default_trans_args.insert("SUPPORT_SITE"); -} - -bool translate_init(std::string comma_delim_path_list, - std::string base_xml_name) -{ - return true; -/*==========================================================================*| - init_default_trans_args(); - - // extract paths string vector from comma-delimited flat string - std::vector<std::string> paths; - LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ',' - - for(std::vector<std::string>::iterator it = paths.begin(), end_it = paths.end(); - it != end_it; - ++it) - { - (*it) = gDirUtilp->findSkinnedFilename(*it, base_xml_name); - } - - // suck the translation xml files into memory - LLXMLNodePtr root; - bool success = LLXMLNode::getLayeredXMLNode(root, paths); - if (!success) - { - // couldn't load string table XML - return false; - } - else - { - // get those strings out of the XML - LLTrans::parseStrings(root, default_trans_args); - return true; - } -|*==========================================================================*/ -} - - -void updater_app_ui_init(void); -void updater_app_quit(UpdaterAppState *app_state); -void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state); -std::string next_image_filename(std::string& image_path, LLDirIterator& iter); -void display_error(GtkWidget *parent, std::string title, std::string message); -BOOL install_package(std::string package_file, std::string destination); -BOOL spawn_viewer(UpdaterAppState *app_state); - -extern "C" { - void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state); - gpointer worker_thread_cb(gpointer *data); - int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow); - gboolean rotate_image_cb(gpointer data); - gboolean progress_update_timeout(gpointer data); - gboolean update_progress_text_timeout(gpointer data); -} - -void updater_app_ui_init(UpdaterAppState *app_state) -{ - GtkWidget *vbox; - GtkWidget *summary_label; - GtkWidget *description_label; - GtkWidget *frame; - - llassert(app_state != NULL); - - // set up window and main container - std::string window_title = LLTrans::getString("UpdaterWindowTitle"); - app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(app_state->window), - window_title.c_str()); - gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE); - gtk_window_set_position(GTK_WINDOW(app_state->window), - GTK_WIN_POS_CENTER_ALWAYS); - - gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12); - g_signal_connect(G_OBJECT(app_state->window), "delete-event", - G_CALLBACK(on_window_closed), app_state); - - vbox = gtk_vbox_new(FALSE, 6); - gtk_container_add(GTK_CONTAINER(app_state->window), vbox); - - // set top label - std::ostringstream label_ostr; - label_ostr << "<big><b>" - << LLTrans::getString("UpdaterNowUpdating") - << "</b></big>"; - - summary_label = gtk_label_new(NULL); - gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE); - gtk_label_set_markup(GTK_LABEL(summary_label), - label_ostr.str().c_str()); - gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0); - - // create the description label - description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str()); - gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE); - gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0); - - // If an image path has been set, load the background images - if (!app_state->image_dir.empty()) { - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - - // load the first image - app_state->image = gtk_image_new_from_file - (next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str()); - gtk_widget_set_size_request(app_state->image, 340, 310); - gtk_container_add(GTK_CONTAINER(frame), app_state->image); - - // rotate the images every 5 seconds - app_state->image_rotation_timeout_id = g_timeout_add - (ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state); - } - - // set up progress bar, and update it roughly every 1/10 of a second - app_state->progress_bar = gtk_progress_bar_new(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), - LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str()); - gtk_box_pack_start(GTK_BOX(vbox), - app_state->progress_bar, FALSE, TRUE, 0); - app_state->progress_update_timeout_id = g_timeout_add - (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state); - app_state->update_progress_text_timeout_id = g_timeout_add - (UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state); - - gtk_widget_show_all(app_state->window); -} - -gboolean rotate_image_cb(gpointer data) -{ - UpdaterAppState *app_state; - std::string filename; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter); - - gdk_threads_enter(); - gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str()); - gdk_threads_leave(); - - return TRUE; -} - -std::string next_image_filename(std::string& image_path, LLDirIterator& iter) -{ - std::string image_filename; - iter.next(image_filename); - return gDirUtilp->add(image_path, image_filename); -} - -void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - updater_app_quit(app_state); -} - -void updater_app_quit(UpdaterAppState *app_state) -{ - if (app_state != NULL) - { - g_source_remove(app_state->progress_update_timeout_id); - - if (!app_state->image_dir.empty()) - { - g_source_remove(app_state->image_rotation_timeout_id); - } - } - - gtk_main_quit(); -} - -void display_error(GtkWidget *parent, std::string title, std::string message) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new(GTK_WINDOW(parent), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", message.c_str()); - gtk_window_set_title(GTK_WINDOW(dialog), title.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - -gpointer worker_thread_cb(gpointer data) -{ - UpdaterAppState *app_state; - CURL *curl; - CURLcode result; - FILE *package_file; - GError *error = NULL; - int fd; - - //g_return_val_if_fail (data != NULL, NULL); - app_state = (UpdaterAppState *) data; - - try { - - if(!app_state->url.empty()) - { - char* tmp_local_filename = NULL; - // create temporary file to store the package. - fd = g_file_open_tmp - ("secondlife-update-XXXXXX", &tmp_local_filename, &error); - if (error != NULL) - { - llerrs << "Unable to create temporary file: " - << error->message - << llendl; - - g_error_free(error); - throw 0; - } - - if(tmp_local_filename != NULL) - { - app_state->file = tmp_local_filename; - g_free(tmp_local_filename); - } - - package_file = fdopen(fd, "wb"); - if (package_file == NULL) - { - llerrs << "Failed to create temporary file: " - << app_state->file.c_str() - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - - // initialize curl and start downloading the package - llinfos << "Downloading package: " << app_state->url << llendl; - - curl = curl_easy_init(); - if (curl == NULL) - { - llerrs << "Failed to initialize libcurl" << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - - curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str()); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, - &download_progress_cb); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state); - - result = curl_easy_perform(curl); - fclose(package_file); - curl_easy_cleanup(curl); - - if (result) - { - llerrs << "Failed to download update: " - << app_state->url - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - - throw 0; - } - } - - // now pulse the progres bar back and forth while the package is - // being unpacked - gdk_threads_enter(); - std::string installing_msg = LLTrans::getString("UpdaterNowInstalling"); - gtk_progress_bar_set_text( - GTK_PROGRESS_BAR(app_state->progress_bar), - installing_msg.c_str()); - app_state->activity_mode = TRUE; - gdk_threads_leave(); - - // *TODO: if the destination is not writable, terminate this - // thread and show file chooser? - if (!install_package(app_state->file.c_str(), app_state->dest_dir)) - { - llwarns << "Failed to install package to destination: " - << app_state->dest_dir - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailInstallTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - //"Failed to update " + app_state->app_name, - gdk_threads_leave(); - throw 0; - } - - // try to spawn the new viewer - if (!spawn_viewer(app_state)) - { - llwarns << "Viewer was not installed properly in : " - << app_state->dest_dir - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailStartTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - } - catch (...) - { - app_state->failure = TRUE; - } - - gdk_threads_enter(); - updater_app_quit(app_state); - gdk_threads_leave(); - - return NULL; -} - - -gboolean less_anal_gspawnsync(gchar **argv, - gchar **stderr_output, - gint *child_exit_status, - GError **spawn_error) -{ - // store current SIGCHLD handler if there is one, replace with default - // handler to make glib happy - struct sigaction sigchld_backup; - struct sigaction sigchld_appease_glib; - sigchld_appease_glib.sa_handler = SIG_DFL; - sigemptyset(&sigchld_appease_glib.sa_mask); - sigchld_appease_glib.sa_flags = 0; - sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); - - gboolean rtn = g_spawn_sync(NULL, - argv, - NULL, - (GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL), - NULL, - NULL, - NULL, - stderr_output, - child_exit_status, - spawn_error); - - // restore SIGCHLD handler - sigaction(SIGCHLD, &sigchld_backup, NULL); - - return rtn; -} - - -// perform a rename, or perform a (prompted) root rename if that fails -int -rename_with_sudo_fallback(const std::string& filename, const std::string& newname) -{ - int rtncode = ::rename(filename.c_str(), newname.c_str()); - lldebugs << "rename result is: " << rtncode << " / " << errno << llendl; - if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno)) - { - llinfos << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << llendl; - // failed due to permissions, try again as a gksudo or kdesu mv wrapper hack - char *sudo_cmd = NULL; - sudo_cmd = g_find_program_in_path("gksudo"); - if (!sudo_cmd) - { - sudo_cmd = g_find_program_in_path("kdesu"); - } - if (sudo_cmd) - { - char *mv_cmd = NULL; - mv_cmd = g_find_program_in_path("mv"); - if (mv_cmd) - { - char *src_string_copy = g_strdup(filename.c_str()); - char *dst_string_copy = g_strdup(newname.c_str()); - char* argv[] = - { - sudo_cmd, - mv_cmd, - src_string_copy, - dst_string_copy, - NULL - }; - - gchar *stderr_output = NULL; - gint child_exit_status = 0; - GError *spawn_error = NULL; - if (!less_anal_gspawnsync(argv, &stderr_output, - &child_exit_status, &spawn_error)) - { - llwarns << "Failed to spawn child process: " - << spawn_error->message - << llendl; - } - else if (child_exit_status) - { - llwarns << "mv command failed: " - << (stderr_output ? stderr_output : "(no reason given)") - << llendl; - } - else - { - // everything looks good, clear the error code - rtncode = 0; - } - - g_free(src_string_copy); - g_free(dst_string_copy); - if (spawn_error) g_error_free(spawn_error); - } - } - } - return rtncode; -} - -gboolean install_package(std::string package_file, std::string destination) -{ - char *tar_cmd = NULL; - std::ostringstream command; - - // Find the absolute path to the 'tar' command. - tar_cmd = g_find_program_in_path("tar"); - if (!tar_cmd) - { - llerrs << "`tar' was not found in $PATH" << llendl; - return FALSE; - } - llinfos << "Found tar command: " << tar_cmd << llendl; - - // Unpack the tarball in a temporary place first, then move it to - // its final destination - std::string tmp_dest_dir = gDirUtilp->getTempFilename(); - if (LLFile::mkdir(tmp_dest_dir, 0744)) - { - llerrs << "Failed to create directory: " - << destination - << llendl; - - return FALSE; - } - - char *package_file_string_copy = g_strdup(package_file.c_str()); - char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str()); - gchar *argv[8] = { - tar_cmd, - const_cast<gchar*>("--strip"), const_cast<gchar*>("1"), - const_cast<gchar*>("-xjf"), - package_file_string_copy, - const_cast<gchar*>("-C"), tmp_dest_dir_string_copy, - NULL, - }; - - llinfos << "Untarring package: " << package_file << llendl; - - // store current SIGCHLD handler if there is one, replace with default - // handler to make glib happy - struct sigaction sigchld_backup; - struct sigaction sigchld_appease_glib; - sigchld_appease_glib.sa_handler = SIG_DFL; - sigemptyset(&sigchld_appease_glib.sa_mask); - sigchld_appease_glib.sa_flags = 0; - sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); - - gchar *stderr_output = NULL; - gint child_exit_status = 0; - GError *untar_error = NULL; - if (!less_anal_gspawnsync(argv, &stderr_output, - &child_exit_status, &untar_error)) - { - llwarns << "Failed to spawn child process: " - << untar_error->message - << llendl; - return FALSE; - } - - if (child_exit_status) - { - llwarns << "Untar command failed: " - << (stderr_output ? stderr_output : "(no reason given)") - << llendl; - return FALSE; - } - - g_free(tar_cmd); - g_free(package_file_string_copy); - g_free(tmp_dest_dir_string_copy); - g_free(stderr_output); - if (untar_error) g_error_free(untar_error); - - // move the existing package out of the way if it exists - if (gDirUtilp->fileExists(destination)) - { - std::string backup_dir = destination + ".backup"; - int oldcounter = 1; - while (gDirUtilp->fileExists(backup_dir)) - { - // find a foo.backup.N folder name that isn't taken yet - backup_dir = destination + ".backup." + llformat("%d", oldcounter); - ++oldcounter; - } - - if (rename_with_sudo_fallback(destination, backup_dir)) - { - llwarns << "Failed to move directory: '" - << destination << "' -> '" << backup_dir - << llendl; - return FALSE; - } - } - - // The package has been unpacked in a staging directory, now we just - // need to move it to its destination. - if (rename_with_sudo_fallback(tmp_dest_dir, destination)) - { - llwarns << "Failed to move installation to the destination: " - << destination - << llendl; - return FALSE; - } - - // \0/ Success! - return TRUE; -} - -gboolean progress_update_timeout(gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - - app_state = (UpdaterAppState *) data; - - gdk_threads_enter(); - if (app_state->activity_mode) - { - gtk_progress_bar_pulse - (GTK_PROGRESS_BAR(app_state->progress_bar)); - } - else - { - gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar), - app_state->progress_value); - } - gdk_threads_leave(); - - return TRUE; -} - -gboolean update_progress_text_timeout(gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - if (app_state->activity_mode == TRUE) - { - // We no longer need this timeout, it will be removed. - return FALSE; - } - - if (!app_state->progress_value) - { - return TRUE; - } - - std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value); - - gdk_threads_enter(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), - progress_text.c_str()); - gdk_threads_leave(); - - return TRUE; -} - -int download_progress_cb(gpointer data, - double t, - double d, - double utotal, - double ulnow) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - if (t <= 0.0) - { - app_state->progress_value = 0; - } - else - { - app_state->progress_value = d * 100.0 / t; - } - return 0; -} - -BOOL spawn_viewer(UpdaterAppState *app_state) -{ - llassert(app_state != NULL); - - std::string cmd = app_state->dest_dir + "/secondlife"; - GError *error = NULL; - - // We want to spawn the Viewer on the same display as the updater app - gboolean success = gdk_spawn_command_line_on_screen - (gtk_widget_get_screen(app_state->window), cmd.c_str(), &error); - - if (!success) - { - llwarns << "Failed to launch viewer: " << error->message - << llendl; - } - - if (error) g_error_free(error); - - return success; -} - -void show_usage_and_exit() -{ - std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE" - << "[--image-dir PATH]" - << std::endl; - exit(1); -} - -void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) -{ - int i; - - for (i = 1; i < argc; i++) - { - if ((!strcmp(argv[i], "--url")) && (++i < argc)) - { - app_state->url = argv[i]; - } - else if ((!strcmp(argv[i], "--file")) && (++i < argc)) - { - app_state->file = argv[i]; - } - else if ((!strcmp(argv[i], "--name")) && (++i < argc)) - { - app_state->app_name = argv[i]; - } - else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc)) - { - app_state->image_dir = argv[i]; - app_state->image_dir_iter = new LLDirIterator(argv[i], "*.jpg"); - } - else if ((!strcmp(argv[i], "--dest")) && (++i < argc)) - { - app_state->dest_dir = argv[i]; - } - else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc)) - { - app_state->strings_dirs = argv[i]; - } - else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc)) - { - app_state->strings_file = argv[i]; - } - else - { - // show usage, an invalid option was given. - show_usage_and_exit(); - } - } - - if (app_state->app_name.empty() - || (app_state->url.empty() && app_state->file.empty()) - || app_state->dest_dir.empty()) - { - show_usage_and_exit(); - } - - app_state->progress_value = 0.0; - app_state->activity_mode = FALSE; - app_state->failure = FALSE; - - translate_init(app_state->strings_dirs, app_state->strings_file); -} - -int main(int argc, char **argv) -{ - UpdaterAppState* app_state = new UpdaterAppState; - GThread *worker_thread; - - parse_args_and_init(argc, argv, app_state); - - // Initialize logger, and rename old log file - gDirUtilp->initAppDirs("SecondLife"); - LLError::initForApplication - (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - std::string old_log_file = gDirUtilp->getExpandedFilename - (LL_PATH_LOGS, "updater.log.old"); - std::string log_file = - gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); - LLFile::rename(log_file, old_log_file); - LLError::logToFile(log_file); - - // initialize gthreads and gtk+ - if (!g_thread_supported()) - { - g_thread_init(NULL); - gdk_threads_init(); - } - - gtk_init(&argc, &argv); - - // create UI - updater_app_ui_init(app_state); - - //llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl; - - // create download thread - worker_thread = g_thread_create - (GThreadFunc(worker_thread_cb), app_state, FALSE, NULL); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - // Delete the file only if created from url download. - if(!app_state->url.empty() && !app_state->file.empty()) - { - if (gDirUtilp->fileExists(app_state->file)) - { - LLFile::remove(app_state->file); - } - } - - bool success = !app_state->failure; - delete app_state->image_dir_iter; - delete app_state; - return success ? 0 : 1; -} - -/***************************************************************************** -* Dummy LLTrans implementation (IQA-490) -*****************************************************************************/ -static LLTrans sStaticStrings; - -// lookup -std::string LLTrans::_getString(const std::string& key) const -{ - MessageMap::const_iterator found = mMessages.find(key); - if (found != mMessages.end()) - { - return found->second; - } - LL_WARNS("linux_updater") << "No message for key '" << key - << "' -- add to LLTrans::LLTrans() in linux_updater.cpp" - << LL_ENDL; - return key; -} - -// static lookup -std::string LLTrans::getString(const std::string& key) -{ - return sLLTransInstance._getString(key); -} - -// initialization -LLTrans::LLTrans() -{ - typedef std::pair<const char*, const char*> Pair; - static const Pair data[] = - { - Pair("UpdaterFailDownloadTitle", - "Failed to download update"), - Pair("UpdaterFailInstallTitle", - "Failed to install update"), - Pair("UpdaterFailStartTitle", - "Failed to start viewer"), - Pair("UpdaterFailUpdateDescriptive", - "An error occurred while updating Second Life. " - "Please download the latest version from www.secondlife.com."), - Pair("UpdaterNowInstalling", - "Installing Second Life..."), - Pair("UpdaterNowUpdating", - "Now updating Second Life..."), - Pair("UpdaterProgressBarText", - "Downloading update"), - Pair("UpdaterProgressBarTextWithEllipses", - "Downloading update..."), - Pair("UpdaterUpdatingDescriptive", - "Your Second Life Viewer is being updated to the latest release. " - "This may take some time, so please be patient."), - Pair("UpdaterWindowTitle", - "Second Life Update") - }; - - BOOST_FOREACH(Pair pair, data) - { - mMessages[pair.first] = pair.second; - } -} diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 7db19b1841..51a8eaf998 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -580,8 +580,13 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void const size_t body_size(op->mReqBody->size()); if (body_size <= op->mCurlBodyPos) { - LL_WARNS("HttpCore") << "Request body position beyond body size. Aborting request." - << LL_ENDL; + if (body_size < op->mCurlBodyPos) + { + // Warn but continue if the read position moves beyond end-of-body + // for some reason. + LL_WARNS("HttpCore") << "Request body position beyond body size. Truncating request body." + << LL_ENDL; + } return 0; } diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp index 5fb84756ee..0cfb810906 100644 --- a/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ b/indra/media_plugins/webkit/windows_volume_catcher.cpp @@ -48,18 +48,37 @@ private: set_volume_func_t mSetVolumeFunc; set_mute_func_t mSetMuteFunc; + // tests if running on Vista, 7, 8 + once in CTOR + bool isWindowsVistaOrHigher(); + F32 mVolume; F32 mPan; + bool mSystemIsVistaOrHigher; }; + +bool VolumeCatcherImpl::isWindowsVistaOrHigher() +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + return osvi.dwMajorVersion >= 6; +} + VolumeCatcherImpl::VolumeCatcherImpl() -: mVolume(1.0f), // default volume is max - mPan(0.f) // default pan is centered +: mVolume(1.0f), // default volume is max + mPan(0.f) // default pan is centered { - HMODULE handle = ::LoadLibrary(L"winmm.dll"); - if(handle) + mSystemIsVistaOrHigher = isWindowsVistaOrHigher(); + + if ( ! mSystemIsVistaOrHigher ) { - mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); - mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + HMODULE handle = ::LoadLibrary(L"winmm.dll"); + if(handle) + { + mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); + mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + } } } @@ -67,18 +86,29 @@ VolumeCatcherImpl::~VolumeCatcherImpl() { } - void VolumeCatcherImpl::setVolume(F32 volume) { mVolume = volume; - if (mSetMuteFunc) + if ( mSystemIsVistaOrHigher ) { - mSetMuteFunc(volume == 0.f); + // set both left/right to same volume + // TODO: use pan value to set independently + DWORD left_channel = (DWORD)(mVolume * 65535.0f); + DWORD right_channel = (DWORD)(mVolume * 65535.0f); + DWORD hw_volume = left_channel << 16 | right_channel; + ::waveOutSetVolume(NULL, hw_volume); } - if (mSetVolumeFunc) + else { - mSetVolumeFunc(mVolume); + if (mSetMuteFunc) + { + mSetMuteFunc(volume == 0.f); + } + if (mSetVolumeFunc) + { + mSetVolumeFunc(mVolume); + } } } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b860b484dc..3cea13849f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1858,7 +1858,6 @@ if (LINUX) set(COPY_INPUT_DEPENDENCIES ${VIEWER_BINARY_NAME} linux-crash-logger - linux-updater SLPlugin media_plugin_webkit media_plugin_gstreamer010 diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl index da3387e7a5..7f3f84398b 100644 --- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl @@ -23,9 +23,6 @@ * $/LicenseInfo$ */ -float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); - uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; @@ -45,6 +42,42 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +//=================================================================================================== +//declare these here explicitly to separate them from atmospheric lighting elsewhere to work around +//drivers that are picky about functions being declared but not defined even if they aren't called +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float da = clamp(1.0/(la * d), 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} +//==================================================================================================== + + void main() { //transform vertex diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index b7270e696e..d041baea90 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -524,6 +524,7 @@ F32 LLDrawable::updateXform(BOOL undamped) dist_squared = dist_vec_squared(new_pos, target_pos); LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); + // FIXME: This can be negative! It is be possible for some rots to 'cancel out' pos or size changes. dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); @@ -549,7 +550,12 @@ F32 LLDrawable::updateXform(BOOL undamped) } else { - dist_squared = dist_vec_squared(old_pos, target_pos); + // The following fixes MAINT-1742 but breaks vehicles similar to MAINT-2275 + // dist_squared = dist_vec_squared(old_pos, target_pos); + + // The following fixes MAINT-2247 but causes MAINT-2275 + //dist_squared += (1.f - dot(old_rot, target_rot)) * 10.f; + //dist_squared += dist_vec_squared(old_scale, target_scale); } LLVector3 vec = mCurrentScale-target_scale; diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp index 9157389187..9a23d99802 100644 --- a/indra/newview/llfloatertexturefetchdebugger.cpp +++ b/indra/newview/llfloatertexturefetchdebugger.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2012, 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 diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..36234b9536 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -186,8 +186,11 @@ private: // Populate the menu with items like "New Skin", "New Pants", etc. static void populateCreateWearableSubmenus(LLMenuGL* menu) { - LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); - LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); + // MAINT-2276...these menus are created as dummies because they are not available + // when this function is called. This prevents their parent from popping up later. + // + //LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); + //LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { @@ -200,8 +203,11 @@ private: p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); - LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? - menu_clothes : menu_bp; + //LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; + // This is a work-around for MAINT-2276 wherein the parent toggleable menu does not appear + // It puts everything under one menu, but that menu appears, which is better than not. + // + LLView* parent = menu; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); } } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 41bfbae86e..7de66b139f 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -3689,13 +3689,14 @@ public: if (status) { - LL_WARNS("Texture") << "Successfully delivered asset metrics to grid." - << LL_ENDL; + LL_DEBUGS("Texture") << "Successfully delivered asset metrics to grid." + << LL_ENDL; } else { - LL_WARNS("Texture") << "Error delivering asset metrics to grid. Reason: " - << status.toString() << LL_ENDL; + LL_WARNS("Texture") << "Error delivering asset metrics to grid. Status: " + << status.toHex() + << ", Reason: " << status.toString() << LL_ENDL; } } }; // end class AssetReportHandler @@ -3895,11 +3896,15 @@ private: LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) : + LLCore::HttpHandler(), mFetcher(fetcher), mTextureCache(cache), mImageDecodeThread(imagedecodethread), mHttpHeaders(NULL), - mHttpPolicyClass(fetcher->getPolicyClass()) + mHttpPolicyClass(fetcher->getPolicyClass()), + mNbCurlCompleted(0), + mTempIndex(0), + mHistoryListIndex(0) { init(); } @@ -3925,6 +3930,7 @@ void LLTextureFetchDebugger::init() mDecodingTime = -1.f; mHTTPTime = -1.f; mGLCreationTime = -1.f; + mTotalFetchingTime = 0.f; mRefetchVisCacheTime = -1.f; mRefetchVisHTTPTime = -1.f; @@ -3951,6 +3957,9 @@ void LLTextureFetchDebugger::init() mFreezeHistory = FALSE; mStopDebug = FALSE; mClearHistory = FALSE; + mRefetchNonVis = FALSE; + + mNbCurlRequests = 0; if (! mHttpHeaders) { @@ -4024,7 +4033,8 @@ bool LLTextureFetchDebugger::processStartDebug(F32 max_time) S32 pending = 0; pending += LLAppViewer::getTextureCache()->update(1); pending += LLAppViewer::getImageDecodeThread()->update(1); - pending += LLAppViewer::getTextureFetch()->update(1); + // pending += LLAppViewer::getTextureFetch()->update(1); // This causes infinite recursion in some cases + pending += mNbCurlRequests; if(!pending) { break; @@ -4314,7 +4324,6 @@ void LLTextureFetchDebugger::debugHTTP() { mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE; mFetchingHistory[i].mCurlReceivedSize = 0; - mFetchingHistory[i].mHTTPFailCount = 0; mFetchingHistory[i].mFormattedImage = NULL; } mNbCurlRequests = 0; @@ -4338,8 +4347,6 @@ S32 LLTextureFetchDebugger::fillCurlQueue() S32 size = mFetchingHistory.size(); for (S32 i = 0 ; i < size ; i++) { - mNbCurlRequests++; - if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE) { continue; @@ -4365,15 +4372,22 @@ S32 LLTextureFetchDebugger::fillCurlQueue() mFetchingHistory[i].mHttpHandle = handle; mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; mNbCurlRequests++; - // Hack - if (mNbCurlRequests == HTTP_REQUESTS_IN_QUEUE_HIGH_WATER) // emulate normal pipeline + if (mNbCurlRequests >= HTTP_REQUESTS_IN_QUEUE_HIGH_WATER) // emulate normal pipeline { break; } } else { - break; + // Failed to queue request, log it and mark it done. + LLCore::HttpStatus status(mFetcher->getHttpRequest().getStatus()); + + LL_WARNS("Texture") << "Couldn't issue HTTP request in debugger for texture " + << mFetchingHistory[i].mID + << ", status: " << status.toHex() + << " reason: " << status.toString() + << LL_ENDL; + mFetchingHistory[i].mCurlState = FetchEntry::CURL_DONE; } } //llinfos << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << llendl; @@ -4727,14 +4741,13 @@ void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpRespon LLCore::HttpStatus status(response->getStatus()); mNbCurlRequests--; + mNbCurlCompleted++; + fetch.mCurlState = FetchEntry::CURL_DONE; if (status) { const bool partial(par_status == status); LLCore::BufferArray * ba(response->getBody()); // *Not* holding reference to body - fetch.mCurlState = FetchEntry::CURL_DONE; - mNbCurlCompleted++; - S32 data_size = ba ? ba->size() : 0; fetch.mCurlReceivedSize += data_size; //llinfos << "Fetch Debugger : got results for " << fetch.mID << ", data_size = " << data_size << ", received = " << fetch.mCurlReceivedSize << ", requested = " << fetch.mRequestedSize << ", partial = " << partial << llendl; @@ -4766,17 +4779,6 @@ void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpRespon llinfos << "Fetch Debugger : CURL GET FAILED, ID = " << fetch.mID << ", status: " << status.toHex() << " reason: " << status.toString() << llendl; - fetch.mHTTPFailCount++; - if(fetch.mHTTPFailCount < 5) - { - // Fetch will have to be redone - fetch.mCurlState = FetchEntry::CURL_NOT_DONE; - } - else //skip - { - fetch.mCurlState = FetchEntry::CURL_DONE; - mNbCurlCompleted++; - } } } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 1e58ba35d4..5ea3c14e1a 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -451,7 +451,6 @@ private: LLPointer<LLImageRaw> mRawImage; e_curl_state mCurlState; S32 mCurlReceivedSize; - S32 mHTTPFailCount; LLCore::HttpHandle mHttpHandle; FetchEntry() : @@ -467,7 +466,6 @@ private: mFetchedSize(f_size), mDecodedSize(d_size), mNeedsAux(false), - mHTTPFailCount(0), mHttpHandle(LLCORE_HTTP_HANDLE_INVALID) {} }; diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index f5d3341c66..1aa9fd8a45 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -160,11 +160,6 @@ void agent_push_backward( EKeystate s ) camera_move_backward(s); return; } - else if (gAgentAvatarp->isSitting()) - { - gAgentCamera.changeCameraToThirdPerson(); - return; - } agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD); } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 33f632b25d..77e382b8c7 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1540,17 +1540,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // Actually extract the data. if (parcel) { - if (sequence_id == SELECTED_PARCEL_SEQ_ID - && parcel->getLocalID() != INVALID_PARCEL_ID - && parcel->getLocalID() != local_id) - { - // The parcel has a valid parcel ID but it doesn't match the parcel - // for the data received. - llinfos << "Expecting data for parcel " << parcel->getLocalID() \ - << " but got data for parcel " << local_id << llendl; - return; - } - parcel->init(owner_id, FALSE, FALSE, FALSE, claim_date, claim_price_per_meter, rent_price_per_meter, diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 142cb2090d..ba9818946c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2025,11 +2025,11 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { gObjectPreviewProgram.mName = "Simple Shader"; - gObjectPreviewProgram.mFeatures.calculatesLighting = true; + gObjectPreviewProgram.mFeatures.calculatesLighting = false; gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false; - gObjectPreviewProgram.mFeatures.hasGamma = true; + gObjectPreviewProgram.mFeatures.hasGamma = false; gObjectPreviewProgram.mFeatures.hasAtmospherics = false; - gObjectPreviewProgram.mFeatures.hasLighting = true; + gObjectPreviewProgram.mFeatures.hasLighting = false; gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0; gObjectPreviewProgram.mFeatures.disableTextureIndex = true; gObjectPreviewProgram.mShaderFiles.clear(); @@ -2037,6 +2037,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; success = gObjectPreviewProgram.createShader(NULL, NULL); + gObjectPreviewProgram.mFeatures.hasLighting = true; } if (success) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 44c18c2cce..c8f5cbb2b0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8874,14 +8874,6 @@ Cannot save to object contents: This would modify the attachment permissions. <notification icon="alertmodal.tga" - name="NoPermToEdit" - type="notify"> - <tag>fail</tag> -Not permitted to edit this! - </notification> - - <notification - icon="alertmodal.tga" name="TooManyScripts" type="notify"> <tag>fail</tag> @@ -8922,47 +8914,6 @@ You cannot modify the navmesh across region boundaries. <notification icon="alertmodal.tga" - name="NoPermModifyObject" - type="notify"> - <tag>fail</tag> -You don't have permission to modify that object. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysObjContributesToNav" - type="notify"> - <tag>fail</tag> -Can't enable physics for an object that contributes to the navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysKeyframedObj" - type="notify"> - <tag>fail</tag> -Can't enable physics for keyframed objects. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysNotEnoughLandResources" - type="notify"> - <tag>fail</tag> -Can't enable physics for object -- insufficient land resources. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysCostTooGreat" - persist="true" - type="notify"> - <tag>fail</tag> -Can't enable physics for object with physics resource cost greater than [MAX_OBJECTS] - </notification> - - <notification - icon="alertmodal.tga" name="NoSetPhysicsPropertiesOnObjectType" type="notify"> <tag>fail</tag> @@ -9987,1693 +9938,4 @@ An internal error prevented us from properly updating your viewer. The L$ balan Cannot create large prims that intersect other players. Please re-try when other players have moved. </notification> - - <notification - icon="alertmodal.tga" - name="AvatarFrozen" - type="notify"> - <tag>fail</tag> -[AV_FREEZER] has frozen you. You cannot move or interact with the world. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarFrozenDuration" - type="notify"> - <tag>fail</tag> -[AV_FREEZER] has frozen you for [AV_FREEZE_TIME] seconds. You cannot move or interact with the world. - </notification> - - <notification - icon="alertmodal.tga" - name="YouFrozeAvatar" - type="notify"> - <tag>fail</tag> -Avatar frozen. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarHasUnFrozenYou" - type="notify"> - <tag>fail</tag> -[AV_FREEZER] has unfrozen you. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarUnFrozen" - type="notify"> - <tag>fail</tag> -Avatar unfrozen. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarFreezeFailure" - type="notify"> - <tag>fail</tag> -Freeze failed because you don't have admin permission for that parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarFreezeThaw" - type="notify"> - <tag>fail</tag> -Your freeze expired, go about your business. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarCantFreeze" - type="notify"> - <tag>fail</tag> -Sorry, can't freeze that user. - </notification> - - <notification - icon="alertmodal.tga" - name="NowOwnObject" - type="notify"> - <tag>fail</tag> -You are now the owner of object [OBJECT_NAME] - </notification> - - <notification - icon="alertmodal.tga" - name="CantRezOnLand" - type="notify"> - <tag>fail</tag> -Can't rez object at [OBJECT_POS] because the owner of this land does not allow it. Use the land tool to see land ownership. - </notification> - - <notification - icon="alertmodal.tga" - name="RezFailTooManyRequests" - type="notify"> - <tag>fail</tag> -Object can not be rezzed because there are too many requests. - </notification> - - <notification - icon="alertmodal.tga" - name="SitFailCantMove" - type="notify"> - <tag>fail</tag> -You cannot sit because you cannot move at this time. - </notification> - - <notification - icon="alertmodal.tga" - name="SitFailNotAllowedOnLand" - type="notify"> - <tag>fail</tag> -You cannot sit because you are not allowed on that land. - </notification> - - <notification - icon="alertmodal.tga" - name="SitFailNotSameRegion" - type="notify"> - <tag>fail</tag> -Try moving closer. Can't sit on object because -it is not in the same region as you. - </notification> - - <notification - icon="alertmodal.tga" - name="NoNewObjectRegionFull" - type="notify"> - <tag>fail</tag> -Unable to create new object. The region is full. - </notification> - - <notification - icon="alertmodal.tga" - name="FailedToPlaceObject" - type="notify"> - <tag>fail</tag> -Failed to place object at specified location. Please try again. - </notification> - - <notification - icon="alertmodal.tga" - name="NoOwnNoGardening" - type="notify"> - <tag>fail</tag> -You Can't create trees and grass on land you don't own. - </notification> - - <notification - icon="alertmodal.tga" - name="NoCopyPermsNoObject" - type="notify"> - <tag>fail</tag> -Copy failed because you lack permission to copy the object '[OBJ_NAME]'. - </notification> - - <notification - icon="alertmodal.tga" - name="NoTransPermsNoObject" - type="notify"> - <tag>fail</tag> -Copy failed because the object '[OBJ_NAME]' cannot be transferred to you. - </notification> - - <notification - icon="alertmodal.tga" - name="AddToNavMeshNoCopy" - type="notify"> - <tag>fail</tag> -Copy failed because the object '[OBJ_NAME]' contributes to navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="DupeWithNoRootsSelected" - type="notify"> - <tag>fail</tag> -Duplicate with no root objects selected. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDupeCuzRegionIsFull" - type="notify"> - <tag>fail</tag> -Can't duplicate objects because the region is full. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDupeCuzParcelNotFound" - type="notify"> - <tag>fail</tag> -Can't duplicate objects - Can't find the parcel they are on. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateCuzParcelFull" - type="notify"> - <tag>fail</tag> -Can't create object because -the parcel is full. - </notification> - - <notification - icon="alertmodal.tga" - name="RezAttemptFailed" - type="notify"> - <tag>fail</tag> -Attempt to rez an object failed. - </notification> - - <notification - icon="alertmodal.tga" - name="ToxicInvRezAttemptFailed" - type="notify"> - <tag>fail</tag> -Unable to create item that has caused problems on this region. - </notification> - - <notification - icon="alertmodal.tga" - name="InvItemIsBlacklisted" - type="notify"> - <tag>fail</tag> -That inventory item has been blacklisted. - </notification> - - <notification - icon="alertmodal.tga" - name="NoCanRezObjects" - type="notify"> - <tag>fail</tag> -You are not currently allowed to create objects. - </notification> - - <notification - icon="alertmodal.tga" - name="LandSearchBlocked" - type="notify"> - <tag>fail</tag> -Land Search Blocked. -You have performed too many land searches too quickly. -Please try again in a minute. - </notification> - - <notification - icon="alertmodal.tga" - name="NotEnoughResourcesToAttach" - type="notify"> - <tag>fail</tag> -Not enough script resources available to attach object! - </notification> - - <notification - icon="alertmodal.tga" - name="YouDiedAndGotTPHome" - type="notify"> - <tag>fail</tag> -You died and have been teleported to your home location - </notification> - - <notification - icon="alertmodal.tga" - name="EjectComingSoon" - type="notify"> - <tag>fail</tag> -You are no longer allowed here and have [EJECT_TIME] seconds to leave. - </notification> - - <notification - icon="alertmodal.tga" - name="NoEnterServerFull" - type="notify"> - <tag>fail</tag> -You can't enter this region because -the server is full. - </notification> - - <notification - icon="alertmodal.tga" - name="SaveBackToInvDisabled" - type="notify"> - <tag>fail</tag> -Save Back To Inventory has been disabled. - </notification> - - <notification - icon="alertmodal.tga" - name="NoExistNoSaveToContents" - type="notify"> - <tag>fail</tag> -Cannot save '[OBJ_NAME]' to object contents because the object it was rezzed from no longer exists. - </notification> - - <notification - icon="alertmodal.tga" - name="NoModNoSaveToContents" - type="notify"> - <tag>fail</tag> -Cannot save '[OBJ_NAME]' to object contents because you do not have permission to modify the object '[DEST_NAME]'. - </notification> - - <notification - icon="alertmodal.tga" - name="NoSaveBackToInvDisabled" - type="notify"> - <tag>fail</tag> -Cannot save '[OBJ_NAME]' back to inventory -- this operation has been disabled. - </notification> - - <notification - icon="alertmodal.tga" - name="NoCopyNoSelCopy" - type="notify"> - <tag>fail</tag> -You cannot copy your selection because you do not have permission to copy the object '[OBJ_NAME]'. - </notification> - - <notification - icon="alertmodal.tga" - name="NoTransNoSelCopy" - type="notify"> - <tag>fail</tag> -You cannot copy your selection because the object '[OBJ_NAME]' is not transferrable. - </notification> - - <notification - icon="alertmodal.tga" - name="NoTransNoCopy" - type="notify"> - <tag>fail</tag> -You cannot copy your selection because the object '[OBJ_NAME]' is not transferrable. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermsNoRemoval" - type="notify"> - <tag>fail</tag> -Removal of the object '[OBJ_NAME]' from the simulator is disallowed by the permissions system. - </notification> - - <notification - icon="alertmodal.tga" - name="NoModNoSaveSelection" - type="notify"> - <tag>fail</tag> -Cannot save your selection because you do not have permission to modify the object '[OBJ_NAME]'. - </notification> - - <notification - icon="alertmodal.tga" - name="NoCopyNoSaveSelection" - type="notify"> - <tag>fail</tag> -Cannot save your selection because the object '[OBJ_NAME]' is not copyable. - </notification> - - <notification - icon="alertmodal.tga" - name="NoModNoTaking" - type="notify"> - <tag>fail</tag> -You cannot take your selection because you do not have permission to modify the object '[OBJ_NAME]'. - </notification> - - <notification - icon="alertmodal.tga" - name="RezDestInternalError" - type="notify"> - <tag>fail</tag> -Internal Error: Unknown destination type. - </notification> - - <notification - icon="alertmodal.tga" - name="DeleteFailObjNotFound" - type="notify"> - <tag>fail</tag> -Delete failed because object not found - </notification> - - <notification - icon="alertmodal.tga" - name="SorryCantEjectUser" - type="notify"> - <tag>fail</tag> -Sorry, can't eject that user. - </notification> - - <notification - icon="alertmodal.tga" - name="RegionSezNotAHome" - type="notify"> - <tag>fail</tag> -This region does not allow you to set your home location here. - </notification> - - <notification - icon="alertmodal.tga" - name="HomeLocationLimits" - type="notify"> - <tag>fail</tag> -You can only set your 'Home Location' on your land or at a mainland Infohub. - </notification> - - <notification - icon="alertmodal.tga" - name="HomePositionSet" - type="notify"> - <tag>fail</tag> -Home position set. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarEjected" - type="notify"> - <tag>fail</tag> -Avatar ejected. - </notification> - - <notification - icon="alertmodal.tga" - name="AvatarEjectFailed" - type="notify"> - <tag>fail</tag> -Eject failed because you don't have admin permission for that parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="CantMoveObjectParcelFull" - type="notify"> - <tag>fail</tag> -Can't move object '[OBJECT_NAME]' to -[OBJ_POSITION] in region [REGION_NAME] because the parcel is full. - </notification> - - <notification - icon="alertmodal.tga" - name="CantMoveObjectParcelPerms" - type="notify"> - <tag>fail</tag> -Can't move object '[OBJECT_NAME]' to -[OBJ_POSITION] in region [REGION_NAME] because your objects are not allowed on this parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="CantMoveObjectParcelResources" - type="notify"> - <tag>fail</tag> -Can't move object '[OBJECT_NAME]' to -[OBJ_POSITION] in region [REGION_NAME] because there are not enough resources for this object on this parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="CantMoveObjectRegionVersion" - type="notify"> - <tag>fail</tag> -Can't move object '[OBJECT_NAME]' to -[OBJ_POSITION] in region [REGION_NAME] because the other region is running an older version which does not support receiving this object via region crossing. - </notification> - - <notification - icon="alertmodal.tga" - name="CantMoveObjectNavMesh" - type="notify"> - <tag>fail</tag> -Can't move object '[OBJECT_NAME]' to -[OBJ_POSITION] in region [REGION_NAME] because you cannot modify the navmesh across region boundaries. - </notification> - - <notification - icon="alertmodal.tga" - name="CantMoveObjectWTF" - type="notify"> - <tag>fail</tag> -Can't move object '[OBJECT_NAME]' to -[OBJ_POSITION] in region [REGION_NAME] because of an unknown reason. ([FAILURE_TYPE]) - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermModifyObject" - type="notify"> - <tag>fail</tag> -You don't have permission to modify that object - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysObjContributesToNav" - type="notify"> - <tag>fail</tag> -Can't enable physics for an object that contributes to the navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysKeyframedObj" - type="notify"> - <tag>fail</tag> -Can't enable physics for keyframed objects. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysNotEnoughLandResources" - type="notify"> - <tag>fail</tag> -Can't enable physics for object -- insufficient land resources. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysCostTooGreat" - persist="true" - type="notify"> - <tag>fail</tag> -Can't enable physics for object with physics resource cost greater than [MAX_OBJECTS] - </notification> - - <notification - icon="alertmodal.tga" - name="PhantomWithConcavePiece" - type="notify"> - <tag>fail</tag> -This object cannot have a concave piece because it is phantom and contributes to the navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="UnableAddItem" - type="notify"> - <tag>fail</tag> -Unable to add item! - </notification> - - <notification - icon="alertmodal.tga" - name="UnableEditItem" - type="notify"> - <tag>fail</tag> -Unable to edit this! - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermToEdit" - type="notify"> - <tag>fail</tag> -Not permitted to edit this. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermToCopyInventory" - type="notify"> - <tag>fail</tag> -Not permitted to copy that inventory. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSaveItemDoesntExist" - type="notify"> - <tag>fail</tag> -Cannot save to object contents: Item no longer exists. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSaveItemAlreadyExists" - type="notify"> - <tag>fail</tag> -Cannot save to object contents: Item with that name already exists in inventory - </notification> - - <notification - icon="alertmodal.tga" - name="CantSaveModifyAttachment" - type="notify"> - <tag>fail</tag> -Cannot save to object contents: This would modify the attachment permissions. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermToEdit" - type="notify"> - <tag>fail</tag> -Not permitted to edit this! - </notification> - - <notification - icon="alertmodal.tga" - name="TooManyScripts" - type="notify"> - <tag>fail</tag> -Too many scripts. - </notification> - - <notification - icon="alertmodal.tga" - name="UnableAddScript" - type="notify"> - <tag>fail</tag> -Unable to add script! - </notification> - - <notification - icon="alertmodal.tga" - name="AssetServerTimeoutObjReturn" - type="notify"> - <tag>fail</tag> -Asset server didn't respond in a timely fashion. Object returned to sim. - </notification> - - <notification - icon="alertmodal.tga" - name="RegionDisablePhysicsShapes" - type="notify"> - <tag>fail</tag> -This region does not have physics shapes enabled. - </notification> - - <notification - icon="alertmodal.tga" - name="NoModNavmeshAcrossRegions" - type="notify"> - <tag>fail</tag> -You cannot modify the navmesh across region boundaries. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermModifyObject" - type="notify"> - <tag>fail</tag> -You don't have permission to modify that object. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysObjContributesToNav" - type="notify"> - <tag>fail</tag> -Can't enable physics for an object that contributes to the navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysKeyframedObj" - type="notify"> - <tag>fail</tag> -Can't enable physics for keyframed objects. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysNotEnoughLandResources" - type="notify"> - <tag>fail</tag> -Can't enable physics for object -- insufficient land resources. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysCostTooGreat" - persist="true" - type="notify"> - <tag>fail</tag> -Can't enable physics for object with physics resource cost greater than [MAX_OBJECTS] - </notification> - - <notification - icon="alertmodal.tga" - name="NoSetPhysicsPropertiesOnObjectType" - type="notify"> - <tag>fail</tag> -Cannot set physics properties on that object type. - </notification> - - <notification - icon="alertmodal.tga" - name="NoSetRootPrimWithNoShape" - type="notify"> - <tag>fail</tag> -Cannot set root prim to have no shape. - </notification> - - <notification - icon="alertmodal.tga" - name="NoRegionSupportPhysMats" - type="notify"> - <tag>fail</tag> -This region does not have physics materials enabled. - </notification> - - <notification - icon="alertmodal.tga" - name="OnlyRootPrimPhysMats" - type="notify"> - <tag>fail</tag> -Only root prims may have their physics materials adjusted. - </notification> - - <notification - icon="alertmodal.tga" - name="NoSupportCharacterPhysMats" - type="notify"> - <tag>fail</tag> -Setting physics materials on characters is not yet supported. - </notification> - - <notification - icon="alertmodal.tga" - name="InvalidPhysMatProperty" - type="notify"> - <tag>fail</tag> -One or more of the specified physics material properties was invalid. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermsAlterStitchingMeshObj" - type="notify"> - <tag>fail</tag> -You may not alter the stitching type of a mesh object. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPermsAlterShapeMeshObj" - type="notify"> - <tag>fail</tag> -You may not alter the shape of a mesh object - </notification> - - <notification - icon="alertmodal.tga" - name="FullRegionCantEnter" - type="notify"> - <tag>fail</tag> -You can't enter this region because \nthe region is full. - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedOwnersDiffer" - type="notify"> - <tag>fail</tag> -Link failed -- owners differ - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedNoModNavmeshAcrossRegions" - type="notify"> - <tag>fail</tag> -Link failed -- cannot modify the navmesh across region boundaries. - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedNoPermToEdit" - type="notify"> - <tag>fail</tag> -Link failed because you do not have edit permission. - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedTooManyPrims" - type="notify"> - <tag>fail</tag> -Link failed -- too many primitives - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedCantLinkNoCopyNoTrans" - type="notify"> - <tag>fail</tag> -Link failed -- cannot link no-copy with no-transfer - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedNothingLinkable" - type="notify"> - <tag>fail</tag> -Link failed -- nothing linkable. - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedTooManyPathfindingChars" - type="notify"> - <tag>fail</tag> -Link failed -- too many pathfinding characters - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedInsufficientLand" - type="notify"> - <tag>fail</tag> -Link failed -- insufficient land resources - </notification> - - <notification - icon="alertmodal.tga" - name="LinkFailedTooMuchPhysics" - type="notify"> - <tag>fail</tag> -Object uses too many physics resources -- its dynamics have been disabled. - </notification> - - <notification - icon="alertmodal.tga" - name="TeleportedHomeByObjectOnParcel" - persist="true" - type="notify"> - <tag>fail</tag> -You have been teleported home by the object '[OBJECT_NAME]' on the parcel '[PARCEL_NAME]' - </notification> - - <notification - icon="alertmodal.tga" - name="TeleportedHomeByObject" - persist="true" - type="notify"> - <tag>fail</tag> -You have been teleported home by the object '[OBJECT_NAME]' - </notification> - - <notification - icon="alertmodal.tga" - name="TeleportedByAttachment" - type="notify"> - <tag>fail</tag> -You have been teleported by an attachment on [ITEM_ID] - </notification> - - <notification - icon="alertmodal.tga" - name="TeleportedByObjectOnParcel" - type="notify"> - <tag>fail</tag> -You have been teleported by the object '[OBJECT_NAME]' on the parcel '[PARCEL_NAME]' - </notification> - - <notification - icon="alertmodal.tga" - name="TeleportedByObjectOwnedBy" - type="notify"> - <tag>fail</tag> -You have been teleported by the object '[OBJECT_NAME]' owned by [OWNER_ID] - </notification> - - <notification - icon="alertmodal.tga" - name="TeleportedByObjectUnknownUser" - type="notify"> - <tag>fail</tag> -You have been teleported by the object '[OBJECT_NAME]' owned by an unknown user. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateObjectRegionFull" - type="notify"> - <tag>fail</tag> -Unable to create requested object. The region is full. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttackMultipleObjOneSpot" - type="notify"> - <tag>fail</tag> -You can't attach multiple objects to one spot. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateMultipleObjAtLoc" - type="notify"> - <tag>fail</tag> -You can't create multiple objects here. - </notification> - - <notification - icon="alertmodal.tga" - name="UnableToCreateObjTimeOut" - type="notify"> - <tag>fail</tag> -Unable to create requested object. Object is missing from database. - </notification> - - <notification - icon="alertmodal.tga" - name="UnableToCreateObjUnknown" - type="notify"> - <tag>fail</tag> -Unable to create requested object. The request timed out. Please try again. - </notification> - - <notification - icon="alertmodal.tga" - name="UnableToCreateObjMissingFromDB" - type="notify"> - <tag>fail</tag> -Unable to create requested object. Please try again. - </notification> - - <notification - icon="alertmodal.tga" - name="RezFailureTookTooLong" - type="notify"> - <tag>fail</tag> -Rez failed, requested object took too long to load. - </notification> - - <notification - icon="alertmodal.tga" - name="FailedToPlaceObjAtLoc" - type="notify"> - <tag>fail</tag> -Failed to place object at specified location. Please try again. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreatePlantsOnLand" - type="notify"> - <tag>fail</tag> -You cannot create plants on this land. - </notification> - - <notification - icon="alertmodal.tga" - name="CantRestoreObjectNoWorldPos" - type="notify"> - <tag>fail</tag> -Cannot restore object. No world position found. - </notification> - - <notification - icon="alertmodal.tga" - name="CantRezObjectInvalidMeshData" - type="notify"> - <tag>fail</tag> -Unable to rez object because its mesh data is invalid. - </notification> - - <notification - icon="alertmodal.tga" - name="CantRezObjectTooManyScripts" - type="notify"> - <tag>fail</tag> -Unable to rez object because there are already too many scripts in this region. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateObjectNoAccess" - type="notify"> - <tag>fail</tag> -Your access privileges don't allow you to create objects there. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateObject" - type="notify"> - <tag>fail</tag> -You are not currently allowed to create objects. - </notification> - - <notification - icon="alertmodal.tga" - name="InvalidObjectParams" - type="notify"> - <tag>fail</tag> -Invalid object parameters - </notification> - - <notification - icon="alertmodal.tga" - name="CantDuplicateObjectNoAcess" - type="notify"> - <tag>fail</tag> -Your access privileges don't allow you to duplicate objects here. - </notification> - - <notification - icon="alertmodal.tga" - name="CantChangeShape" - type="notify"> - <tag>fail</tag> -You are not allowed to change this shape. - </notification> - - <notification - icon="alertmodal.tga" - name="NoAccessToClaimObjects" - type="notify"> - <tag>fail</tag> -Your access privileges don't allow you to claim objects here. - </notification> - - <notification - icon="alertmodal.tga" - name="DeedFailedNoPermToDeedForGroup" - type="notify"> - <tag>fail</tag> -Deed failed because you do not have permission to deed objects for your group. - </notification> - - <notification - icon="alertmodal.tga" - name="NoPrivsToBuyObject" - type="notify"> - <tag>fail</tag> -Your access privileges don't allow you to buy objects here. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttachObjectAvatarSittingOnIt" - type="notify"> - <tag>fail</tag> -Cannot attach object because an avatar is sitting on it. - </notification> - - <notification - icon="alertmodal.tga" - name="WhyAreYouTryingToWearShrubbery" - type="notify"> - <tag>fail</tag> -Trees and grasses cannot be worn as attachments. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttachGroupOwnedObjs" - type="notify"> - <tag>fail</tag> -Cannot attach group-owned objects. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttachObjectsNotOwned" - type="notify"> - <tag>fail</tag> -Cannot attach objects that you don't own. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttachNavmeshObjects" - type="notify"> - <tag>fail</tag> -Cannot attach objects that contribute to navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttachObjectNoMovePermissions" - type="notify"> - <tag>fail</tag> -Cannot attach object because you do not have permission to move it. - </notification> - - <notification - icon="alertmodal.tga" - name="CantAttachNotEnoughScriptResources" - type="notify"> - <tag>fail</tag> -Not enough script resources available to attach object! - </notification> - - <notification - icon="alertmodal.tga" - name="CantDropItemTrialUser" - type="notify"> - <tag>fail</tag> -You can't drop objects here; try the Free Trial area. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDropMeshAttachment" - type="notify"> - <tag>fail</tag> -You can't drop mesh attachments. Detach to inventory and then rez in world. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDropAttachmentNoPermission" - type="notify"> - <tag>fail</tag> -Failed to drop attachment: you don't have permission to drop there. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDropAttachmentInsufficientLandResources" - type="notify"> - <tag>fail</tag> -Failed to drop attachment: insufficient available land resource. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDropAttachmentInsufficientResources" - type="notify"> - <tag>fail</tag> -Failed to drop attachments: insufficient available resources. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDropObjectFullParcel" - type="notify"> - <tag>fail</tag> -Cannot drop object here. Parcel is full. - </notification> - - <notification - icon="alertmodal.tga" - name="CantTouchObjectBannedFromParcel" - type="notify"> - <tag>fail</tag> -Can't touch/grab this object because you are banned from the land parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="PlzNarrowDeleteParams" - type="notify"> - <tag>fail</tag> -Please narrow your delete parameters. - </notification> - - <notification - icon="alertmodal.tga" - name="UnableToUploadAsset" - type="notify"> - <tag>fail</tag> -Unable to upload asset. - </notification> - - <notification - icon="alertmodal.tga" - name="CantTeleportCouldNotFindUser" - type="notify"> - <tag>fail</tag> -Could not find user to teleport home - </notification> - - <notification - icon="alertmodal.tga" - name="GodlikeRequestFailed" - type="notify"> - <tag>fail</tag> -godlike request failed - </notification> - - <notification - icon="alertmodal.tga" - name="GenericRequestFailed" - type="notify"> - <tag>fail</tag> -generic request failed - </notification> - - <notification - icon="alertmodal.tga" - name="CantUploadPostcard" - type="notify"> - <tag>fail</tag> -Unable to upload postcard. Try again later. - </notification> - - <notification - icon="alertmodal.tga" - name="CantFetchInventoryForGroupNotice" - type="notify"> - <tag>fail</tag> -Unable to fetch inventory details for the group notice. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSendGroupNoticeNotPermitted" - type="notify"> - <tag>fail</tag> -Unable to send group notice -- not permitted. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSendGroupNoticeCantConstructInventory" - type="notify"> - <tag>fail</tag> -Unable to send group notice -- could not construct inventory. - </notification> - - <notification - icon="alertmodal.tga" - name="CantParceInventoryInNotice" - type="notify"> - <tag>fail</tag> -Unable to parse inventory in notice. - </notification> - - <notification - icon="alertmodal.tga" - name="TerrainUploadFailed" - type="notify"> - <tag>fail</tag> -Terrain upload failed. - </notification> - - <notification - icon="alertmodal.tga" - name="TerrainFileWritten" - type="notify"> - <tag>fail</tag> -Terrain file written. - </notification> - - <notification - icon="alertmodal.tga" - name="TerrainFileWrittenStartingDownload" - type="notify"> - <tag>fail</tag> -Terrain file written, starting download... - </notification> - - <notification - icon="alertmodal.tga" - name="TerrainBaked" - type="notify"> - <tag>fail</tag> -Terrain baked. - </notification> - - <notification - icon="alertmodal.tga" - name="TenObjectsDisabledPlzRefresh" - type="notify"> - <tag>fail</tag> -Only the first 10 selected objects have been disabled. Refresh and make additional selections if required. - </notification> - - <notification - icon="alertmodal.tga" - name="UpdateViewerBuyParcel" - type="notify"> - <tag>fail</tag> -You need to update your viewer to buy this parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="LandBuyAccessBlocked" - type="notify"> - <tag>fail</tag> -You can't buy this land due to your maturity Rating. You may need to validate your age and/or install the latest Viewer. Please go to the Knowledge Base for details on accessing areas with this maturity Rating. - </notification> - - <notification - icon="alertmodal.tga" - name="CantBuyParcelNotForSale" - type="notify"> - <tag>fail</tag> -Unable to buy, this parcel is not for sale. - </notification> - - <notification - icon="alertmodal.tga" - name="CantBuySalePriceOrLandAreaChanged" - type="notify"> - <tag>fail</tag> -Unable to buy, the sale price or land area has changed. - </notification> - - <notification - icon="alertmodal.tga" - name="CantBuyParcelNotAuthorized" - type="notify"> - <tag>fail</tag> -You are not the authorized buyer for this parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="CantBuyParcelAwaitingPurchaseAuth" - type="notify"> - <tag>fail</tag> -You cannot purchase this parcel because it is already awaiting purchase aut - </notification> - - <notification - icon="alertmodal.tga" - name="CantBuildOverflowParcel" - type="notify"> - <tag>fail</tag> -You cannot build objects here because doing so would overflow the parcel. - </notification> - - <notification - icon="alertmodal.tga" - name="SelectedMultipleOwnedLand" - type="notify"> - <tag>fail</tag> -You selected land with different owners. Please select a smaller area and try again. - </notification> - - <notification - icon="alertmodal.tga" - name="CantJoinTooFewLeasedParcels" - type="notify"> - <tag>fail</tag> -Not enough leased parcels in selection to join. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDivideLandMultipleParcelsSelected" - type="notify"> - <tag>fail</tag> -Can't divide land.\nThere is more than one parcel selected.\nTry selecting a smaller piece of land. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDivideLandCantFindParcel" - type="notify"> - <tag>fail</tag> -Can't divide land.\nCan't find the parcel.\nPlease report with Help -> Reprt Bug... - </notification> - - <notification - icon="alertmodal.tga" - name="CantDivideLandWholeParcelSelected" - type="notify"> - <tag>fail</tag> -Can't divide land. Whole parcel is selected.\nTry selecting a smaller piece of land. - </notification> - - <notification - icon="alertmodal.tga" - name="LandHasBeenDivided" - type="notify"> - <tag>fail</tag> -Land has been divided. - </notification> - - <notification - icon="alertmodal.tga" - name="PassPurchased" - type="notify"> - <tag>fail</tag> -You purchased a pass. - </notification> - - <notification - icon="alertmodal.tga" - name="RegionDisallowsClassifieds" - type="notify"> - <tag>fail</tag> -Region does not allow classified advertisements. - </notification> - - <notification - icon="alertmodal.tga" - name="LandPassExpireSoon" - type="notify"> - <tag>fail</tag> -Your pass to this land is about to expire. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSitNoSuitableSurface" - type="notify"> - <tag>fail</tag> -There is no suitable surface to sit on, try another spot. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSitNoRoom" - type="notify"> - <tag>fail</tag> -No room to sit here, try another spot. - </notification> - - <notification - icon="alertmodal.tga" - name="AutopilotCanceled" - type="notify"> - <tag>fail</tag> -Autopilot canceled - </notification> - - <notification - icon="alertmodal.tga" - name="ClaimObjectFailedNoPermission" - type="notify"> - <tag>fail</tag> -Claim object failed because you don't have permission - </notification> - - <notification - icon="alertmodal.tga" - name="ClaimObjectFailedNoMoney" - type="notify"> - <tag>fail</tag> -Claim object failed because you don't have enough L$. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDeedGroupLand" - type="notify"> - <tag>fail</tag> -Cannot deed group-owned land. - </notification> - - <notification - icon="alertmodal.tga" - name="BuyObjectFailedNoMoney" - type="notify"> - <tag>fail</tag> -Buy object failed because you don't have enough L$. - </notification> - - <notification - icon="alertmodal.tga" - name="BuyInventoryFailedNoMoney" - type="notify"> - <tag>fail</tag> -Buy inventory failed because you do not have enough L$ - </notification> - - <notification - icon="alertmodal.tga" - name="BuyPassFailedNoMoney" - type="notify"> - <tag>fail</tag> -You don't have enough L$ to buy a pass to this land. - </notification> - - <notification - icon="alertmodal.tga" - name="CantBuyPassTryAgain" - type="notify"> - <tag>fail</tag> -Unable to buy pass right now. Try again later. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateObjectParcelFull" - type="notify"> - <tag>fail</tag> -Can't create object because \nthe parcel is full. - </notification> - - <notification - icon="alertmodal.tga" - name="FailedPlacingObject" - type="notify"> - <tag>fail</tag> -Failed to place object at specified location. Please try again. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateLandmarkForEvent" - type="notify"> - <tag>fail</tag> -Unable to create landmark for event. - </notification> - - <notification - icon="alertmodal.tga" - name="GodBeatsFreeze" - type="notify"> - <tag>fail</tag> -Your godlike powers break the freeze! - </notification> - - <notification - icon="alertmodal.tga" - name="SpecialPowersRequestFailedLogged" - type="notify"> - <tag>fail</tag> -Request for special powers failed. This request has been logged. - </notification> - - <notification - icon="alertmodal.tga" - name="ExpireExplanation" - type="notify"> - <tag>fail</tag> -The system is currently unable to process your request. The request timed out. - </notification> - - <notification - icon="alertmodal.tga" - name="DieExplanation" - type="notify"> - <tag>fail</tag> -The system is unable to process your request. - </notification> - - <notification - icon="alertmodal.tga" - name="AddPrimitiveFailure" - type="notify"> - <tag>fail</tag> -Insufficient funds to create primitve. - </notification> - - <notification - icon="alertmodal.tga" - name="RezObjectFailure" - type="notify"> - <tag>fail</tag> -Insufficient funds to create object. - </notification> - - <notification - icon="alertmodal.tga" - name="ResetHomePositionNotLegal" - type="notify"> - <tag>fail</tag> -Reset Home position since Home wasn't legal. - </notification> - - <notification - icon="alertmodal.tga" - name="CantInviteRegionFull" - type="notify"> - <tag>fail</tag> -You cannot currently invite anyone to your location because the region is full. Try again later. - </notification> - - <notification - icon="alertmodal.tga" - name="CantSetHomeAtRegion" - type="notify"> - <tag>fail</tag> -This region does not allow you to set your home location here. - </notification> - - <notification - icon="alertmodal.tga" - name="ListValidHomeLocations" - type="notify"> - <tag>fail</tag> -You can only set your 'Home Location' on your land or at a mainland Infohub. - </notification> - - <notification - icon="alertmodal.tga" - name="SetHomePosition" - type="notify"> - <tag>fail</tag> -Home position set. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDerezInventoryError" - type="notify"> - <tag>fail</tag> -Cannot derez object due to inventory fault. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateRequestedInv" - type="notify"> - <tag>fail</tag> -Cannot create requested inventory. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateRequestedInvFolder" - type="notify"> - <tag>fail</tag> -Cannot create requested inventory folder. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateInventory" - type="notify"> - <tag>fail</tag> -Cannot create that inventory. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateLandmark" - type="notify"> - <tag>fail</tag> -Cannot create landmark. - </notification> - - <notification - icon="alertmodal.tga" - name="CantCreateOutfit" - type="notify"> - <tag>fail</tag> -Cannot create outfit right now. Try again in a minute. - </notification> - - <notification - icon="alertmodal.tga" - name="InventoryNotForSale" - type="notify"> - <tag>fail</tag> -Inventory is not for sale. - </notification> - - <notification - icon="alertmodal.tga" - name="CantFindInvItem" - type="notify"> - <tag>fail</tag> -Unable to find inventory item. - </notification> - - <notification - icon="alertmodal.tga" - name="CantFindObject" - type="notify"> - <tag>fail</tag> -Unable to find object. - </notification> - - <notification - icon="alertmodal.tga" - name="CantTransfterMoneyRegionDisabled" - type="notify"> - <tag>fail</tag> -Money transfers to objects are currently disabled in this region. - </notification> - - <notification - icon="alertmodal.tga" - name="CantPayNoAgent" - type="notify"> - <tag>fail</tag> -Could not figure out who to pay. - </notification> - - <notification - icon="alertmodal.tga" - name="CantDonateToPublicObjects" - type="notify"> - <tag>fail</tag> -You cannot give L$ to public objects. - </notification> - - <notification - icon="alertmodal.tga" - name="InventoryCreationInWorldObjectFailed" - type="notify"> - <tag>fail</tag> -Inventory creation on in-world object failed. - </notification> - - <notification - icon="alertmodal.tga" - name="UserBalanceOrLandUsageError" - type="notify"> - <tag>fail</tag> -An internal error prevented us from properly updating your viewer. The L$ balance or parcel holdings displayed in your viewer may not reflect your actual balance on the servers. - </notification> - - </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 849f3ef73d..7eb0fac2be 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -152,19 +152,6 @@ width="80"> Mid </text> - <text - type="string" - length="1" - follows="left|top" - halign="center" - height="12" - layout="topleft" - left_delta="87" - name="ShadersPrefText3" - top_delta="0" - width="80"> - High - </text> <text type="string" length="1" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 6333c65047..2211a3bdf6 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -969,7 +969,6 @@ class LinuxManifest(ViewerManifest): if self.prefix(src="", dst="bin"): self.path("secondlife-bin","do-not-directly-run-secondlife-bin") self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") - self.path("../linux_updater/linux-updater", "linux-updater.bin") self.path2basename("../llplugin/slplugin", "SLPlugin") self.path2basename("../viewer_components/updater/scripts/linux", "update_install") self.end_prefix("bin") @@ -1018,9 +1017,7 @@ class LinuxManifest(ViewerManifest): else: installer_name += '_' + self.channel_oneword().upper() - if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): - print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" - self.run_command("find %(d)r/bin %(d)r/lib -type f \\! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure + self.strip_binaries() # Fix access permissions self.run_command(""" @@ -1055,6 +1052,11 @@ class LinuxManifest(ViewerManifest): 'dst': self.get_dst_prefix(), 'inst': self.build_path_of(installer_name)}) + def strip_binaries(self): + if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): + print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" + self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure + class Linux_i686Manifest(LinuxManifest): def construct(self): super(Linux_i686Manifest, self).construct() @@ -1142,9 +1144,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxplatform.so") self.end_prefix("lib") - if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): - print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" - self.run_command("find %(d)r/bin %(d)r/lib -type f \\! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure + self.strip_binaries() class Linux_x86_64Manifest(LinuxManifest): 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- & |