summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-xindra/lib/python/indra/util/llmanifest.py33
-rwxr-xr-xindra/newview/CMakeLists.txt5
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/installers/windows/installer_template.nsi28
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp11
-rwxr-xr-xindra/newview/llfloaterworldmap.cpp6
-rwxr-xr-xindra/newview/llinventorybridge.cpp34
-rwxr-xr-xindra/newview/llinventorybridge.h4
-rwxr-xr-xindra/newview/lltracker.cpp152
-rwxr-xr-xindra/newview/lltracker.h2
-rwxr-xr-xindra/newview/skins/default/colors.xml3
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_inventory.xml8
-rwxr-xr-xindra/newview/viewer_manifest.py257
-rwxr-xr-xindra/viewer_components/updater/llupdatedownloader.cpp52
-rwxr-xr-xindra/viewer_components/updater/llupdaterservice.cpp56
-rwxr-xr-xindra/viewer_components/updater/scripts/darwin/update_install.py12
16 files changed, 372 insertions, 293 deletions
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 52b4acbc94..1d85aa2978 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -85,7 +85,8 @@ def get_default_platform(dummy):
}[sys.platform]
DEFAULT_SRCTREE = os.path.dirname(sys.argv[0])
-RELEASE_CHANNEL = 'Second Life Release'
+CHANNEL_VENDOR_BASE = 'Second Life'
+RELEASE_CHANNEL = CHANNEL_VENDOR_BASE + ' Release'
ARGUMENTS=[
dict(name='actions',
@@ -112,13 +113,14 @@ ARGUMENTS=[
default="Release"),
dict(name='dest', description='Destination directory.', default=DEFAULT_SRCTREE),
dict(name='grid',
- description="""Which grid the client will try to connect to. Even
- though it's not strictly a grid, 'firstlook' is also an acceptable
- value for this parameter.""",
- default=""),
+ description="""Which grid the client will try to connect to.""",
+ default=None),
dict(name='channel',
description="""The channel to use for updates, packaging, settings name, etc.""",
default='CHANNEL UNSET'),
+ dict(name='channel_suffix',
+ description="""Addition to the channel for packaging and channel value, but not application name (used internally)""",
+ default=None),
dict(name='installer_name',
description=""" The name of the file that the installer should be
packaged up into. Only used on Linux at the moment.""",
@@ -213,9 +215,9 @@ def main():
print "Unable to read versionfile '%s'" % args['versionfile']
raise
- # default and agni are default
- if args['grid'] in ['default', 'agni']:
- args['grid'] = ''
+ # unspecified, default, and agni are default
+ if args['grid'] in ['', 'default', 'agni']:
+ args['grid'] = None
if 'actions' in args:
args['actions'] = args['actions'].split()
@@ -286,21 +288,24 @@ def main():
base_channel_name = args['channel']
# Build each additional package.
package_id_list = additional_packages.split(" ")
+ args['channel'] = base_channel_name
for package_id in package_id_list:
try:
- args['package_id'] = package_id
- args['channel'] = base_channel_name + os.environ[package_id + "_viewer_channel_suffix"]
+ if package_id + "_viewer_channel_suffix" in os.environ:
+ args['channel_suffix'] = os.environ[package_id + "_viewer_channel_suffix"]
+ else:
+ args['channel_suffix'] = None
if package_id + "_sourceid" in os.environ:
args['sourceid'] = os.environ[package_id + "_sourceid"]
else:
- args['sourceid'] = ""
+ args['sourceid'] = None
args['dest'] = base_dest_prefix + os.sep + package_id + os.sep + base_dest_postfix
except KeyError:
sys.stderr.write("Failed to create package for package_id: %s" % package_id)
sys.stderr.flush()
continue
if touch:
- print 'Creating additional package for ', package_id, ' in ', args['dest']
+ print 'Creating additional package for "', package_id, '" in ', args['dest']
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
wm.do(*args['actions'])
if touch:
@@ -332,7 +337,7 @@ class LLManifest(object):
manifests = {}
def for_platform(self, platform, arch = None):
if arch:
- platform = platform + '_' + arch
+ platform = platform + '_' + arch + '_'
return self.manifests[platform.lower()]
for_platform = classmethod(for_platform)
@@ -349,8 +354,6 @@ class LLManifest(object):
self.created_paths = []
self.package_name = "Unknown"
- def default_grid(self):
- return self.args.get('grid', None) == ''
def default_channel(self):
return self.args.get('channel', None) == RELEASE_CHANNEL
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1fea6dea9f..c5e1cde4e6 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1748,6 +1748,7 @@ if (WINDOWS)
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--actions=copy
+ --arch=${ARCH}
--artwork=${ARTWORK_DIR}
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
@@ -1815,6 +1816,7 @@ if (WINDOWS)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ --arch=${ARCH}
--artwork=${ARTWORK_DIR}
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
@@ -1939,7 +1941,6 @@ if (LINUX)
--configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/packaged
--grid=${GRID}
- --installer_name=${product}
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
DEPENDS
@@ -2017,6 +2018,7 @@ if (DARWIN)
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--actions=copy
+ --arch=${ARCH}
--artwork=${ARTWORK_DIR}
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
@@ -2049,6 +2051,7 @@ if (DARWIN)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ --arch=${ARCH}
--artwork=${ARTWORK_DIR}
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 8b7b0b52e5..3609cf7707 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.6.12
+3.6.13
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index 8a6114f0d5..dd316cdbdf 100755
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -72,16 +72,8 @@ LangString LanguageCode ${LANG_RUSSIAN} "ru"
LangString LanguageCode ${LANG_TURKISH} "tr"
LangString LanguageCode ${LANG_TRADCHINESE} "zh"
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tweak for different servers/builds (this placeholder is replaced by viewer_manifest.py)
-;; For example:
-;; !define INSTFLAGS "%(flags)s"
-;; !define INSTNAME "SecondLife%(grid_caps)s"
-;; !define SHORTCUT "Second Life (%(grid_caps)s)"
-;; !define URLNAME "secondlife%(grid)s"
-;; !define UNINSTALL_SETTINGS 1
-
-%%GRID_VARS%%
+;; this placeholder is replaced by viewer_manifest.py
+%%INST_VARS%%
Name ${INSTNAME}
@@ -109,7 +101,6 @@ Page instfiles
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Var INSTPROG
Var INSTEXE
-Var INSTFLAGS
Var INSTSHORTCUT
Var COMMANDLINE ; command line passed to this installer, set in .onInit
Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer
@@ -147,7 +138,7 @@ label_ask_launch:
label_launch:
# Assumes SetOutPath $INSTDIR
- Exec '"$INSTDIR\$INSTEXE" $INSTFLAGS $SHORTCUT_LANG_PARAM'
+ Exec '"$INSTDIR\$INSTEXE" $SHORTCUT_LANG_PARAM'
label_no_launch:
Pop $R0
FunctionEnd
@@ -720,7 +711,6 @@ ShowUninstDetails show
Section Uninstall
; Start with some default values.
-StrCpy $INSTFLAGS ""
StrCpy $INSTPROG "${INSTNAME}"
StrCpy $INSTEXE "${INSTEXE}"
StrCpy $INSTSHORTCUT "${SHORTCUT}"
@@ -919,7 +909,6 @@ Section "" ; (default section)
SetShellVarContext all ; install for all users (if you change this, change it in the uninstall as well)
; Start with some default values.
-StrCpy $INSTFLAGS "${INSTFLAGS}"
StrCpy $INSTPROG "${INSTNAME}"
StrCpy $INSTEXE "${INSTEXE}"
StrCpy $INSTSHORTCUT "${SHORTCUT}"
@@ -966,7 +955,7 @@ StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"
CreateDirectory "$SMPROGRAMS\$INSTSHORTCUT"
SetOutPath "$INSTDIR"
CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \
- "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM"
+ "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM"
WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \
@@ -985,9 +974,9 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \
; Other shortcuts
SetOutPath "$INSTDIR"
CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
- "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM"
+ "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM"
CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \
- "$INSTDIR\$INSTEXE" "$INSTFLAGS $SHORTCUT_LANG_PARAM"
+ "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM"
CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
'"$INSTDIR\uninst.exe"' ''
@@ -996,7 +985,6 @@ CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
; Write registry
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" "$INSTDIR"
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" "${VERSION_LONG}"
-WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Flags" "$INSTFLAGS"
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" "$INSTSHORTCUT"
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$INSTEXE"
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayName" "$INSTPROG (remove only)"
@@ -1009,13 +997,13 @@ WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" ""
WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" '"$INSTDIR\$INSTEXE"'
;; URL param must be last item passed to viewer, it ignores subsequent params
;; to avoid parameter injection attacks.
-WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"'
+WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" -url "%1"'
WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info"(default)" "URL:Second Life"
WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" ""
WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$INSTEXE"'
;; URL param must be last item passed to viewer, it ignores subsequent params
;; to avoid parameter injection attacks.
-WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"'
+WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$INSTEXE" -url "%1"'
; write out uninstaller
WriteUninstaller "$INSTDIR\uninst.exe"
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 19cec55837..855836af7a 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -535,9 +535,16 @@ BOOL LLFloaterModelPreview::postBuild()
mUploadBtn = getChild<LLButton>("ok_btn");
mCalculateBtn = getChild<LLButton>("calculate_btn");
- mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this));
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this));
- toggleCalculateButton(true);
+ toggleCalculateButton(true);
+ }
+ else
+ {
+ mCalculateBtn->setEnabled(false);
+ }
return TRUE;
}
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 137b5446cf..cb637c7162 100755
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -627,8 +627,8 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
if (!sim_info)
{
// We haven't found a region for that point yet, leave the tracking to the world map
- LLWorldMap::getInstance()->setTracking(pos_global);
LLTracker::stopTracking(NULL);
+ LLWorldMap::getInstance()->setTracking(pos_global);
S32 world_x = S32(pos_global.mdV[0] / 256);
S32 world_y = S32(pos_global.mdV[1] / 256);
LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
@@ -643,9 +643,9 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
{
// Down region. Show the blue circle of death!
// i.e. let the world map that this and tell it it's invalid
+ LLTracker::stopTracking(NULL);
LLWorldMap::getInstance()->setTracking(pos_global);
LLWorldMap::getInstance()->setTrackingInvalid();
- LLTracker::stopTracking(NULL);
setDefaultBtn("");
// clicked on a down region - turn off coord display
@@ -665,8 +665,8 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
std::string tooltip("");
mTrackedStatus = LLTracker::TRACKING_LOCATION;
- LLTracker::trackLocation(pos_global, full_name, tooltip);
LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking
+ LLTracker::trackLocation(pos_global, full_name, tooltip);
LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
updateTeleportCoordsDisplay( coord_pos );
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 80ef506272..44943d8722 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -74,6 +74,7 @@
#include "llvoavatarself.h"
#include "llwearablelist.h"
#include "lllandmarkactions.h"
+#include "llpanellandmarks.h"
void copy_slurl_to_clipboard_callback_inv(const std::string& slurl);
@@ -1449,6 +1450,38 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
}
}
}
+ else if ("show_on_map" == action)
+ {
+ doActionOnCurSelectedLandmark(boost::bind(&LLItemBridge::doShowOnMap, this, _1));
+ }
+}
+
+void LLItemBridge::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)
+{
+ LLViewerInventoryItem* cur_item = getItem();
+ if(cur_item && cur_item->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getUUID(), cb);
+ if (landmark)
+ {
+ cb(landmark);
+ }
+ }
+}
+
+void LLItemBridge::doShowOnMap(LLLandmark* landmark)
+{
+ LLVector3d landmark_global_pos;
+ // landmark has already been tested for NULL by calling routine
+ if (landmark->getGlobalPos(landmark_global_pos))
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
+ {
+ worldmap_instance->trackLocation(landmark_global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
}
void copy_slurl_to_clipboard_callback_inv(const std::string& slurl)
@@ -4580,6 +4613,7 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Landmark Separator"));
items.push_back(std::string("url_copy"));
items.push_back(std::string("About Landmark"));
+ items.push_back(std::string("show_on_map"));
}
// Disable "About Landmark" menu item for
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 517153e171..bc875e8f37 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -36,6 +36,7 @@
#include "llviewercontrol.h"
#include "llviewerwearable.h"
#include "lltooldraganddrop.h"
+#include "lllandmarklist.h"
class LLInventoryFilter;
class LLInventoryPanel;
@@ -239,7 +240,10 @@ protected:
BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response);
virtual BOOL isItemPermissive() const;
virtual void buildDisplayName() const;
+ void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);
+private:
+ void doShowOnMap(LLLandmark* landmark);
};
class LLFolderBridge : public LLInvFVBridge
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index cbd16e873d..73ceb783b5 100755
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -167,6 +167,7 @@ void LLTracker::render3D()
}
static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
+ static LLUIColor map_track_color_under = LLUIColorTable::instance().getColor("MapTrackColorUnder", LLColor4::white);
// Arbitary location beacon
if( instance()->mIsTrackingLocation )
@@ -187,7 +188,7 @@ void LLTracker::render3D()
}
else
{
- renderBeacon( instance()->mTrackedPositionGlobal, map_track_color,
+ renderBeacon( instance()->mTrackedPositionGlobal, map_track_color, map_track_color_under,
instance()->mBeaconText, instance()->mTrackedLocationName );
}
}
@@ -229,7 +230,7 @@ void LLTracker::render3D()
// and back again
instance()->mHasReachedLandmark = FALSE;
}
- renderBeacon( instance()->mTrackedPositionGlobal, map_track_color,
+ renderBeacon( instance()->mTrackedPositionGlobal, map_track_color, map_track_color_under,
instance()->mBeaconText, instance()->mTrackedLandmarkName );
}
}
@@ -258,7 +259,7 @@ void LLTracker::render3D()
}
else
{
- renderBeacon( av_tracker.getGlobalPos(), map_track_color,
+ renderBeacon( av_tracker.getGlobalPos(), map_track_color, map_track_color_under,
instance()->mBeaconText, av_tracker.getName() );
}
}
@@ -412,7 +413,7 @@ const std::string& LLTracker::getTrackedLocationName()
return instance()->mTrackedLocationName;
}
-F32 pulse_func(F32 t, F32 z)
+F32 pulse_func(F32 t, F32 z, bool tracking_avatar, std::string direction)
{
if (!LLTracker::sCheesyBeacon)
{
@@ -420,8 +421,15 @@ F32 pulse_func(F32 t, F32 z)
}
t *= F_PI;
- z -= t*64.f - 256.f;
-
+ if ("DOWN" == direction)
+ {
+ z += t*64.f - 256.f;
+ }
+ else
+ {
+ z -= t*64.f - 256.f;
+ }
+
F32 a = cosf(z*F_PI/512.f)*10.0f;
a = llmax(a, 9.9f);
a -= 9.9f;
@@ -474,10 +482,78 @@ void draw_shockwave(F32 center_z, F32 t, S32 steps, LLColor4 color)
gGL.end();
}
+void LLTracker::drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 fogged_color, F32 dist)
+{
+ const U32 BEACON_VERTS = 256;
+ F32 step;
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+
+ if ("DOWN" == direction)
+ {
+ gGL.translatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
+ draw_shockwave(1024.f, gRenderStartTime.getElapsedTimeF32(), 32, fogged_color);
+ step = (5020.0f - pos_agent.mV[2]) / BEACON_VERTS;
+ }
+ else
+ {
+ gGL.translatef(pos_agent.mV[0], pos_agent.mV[1], 0);
+ step = pos_agent.mV[2] / BEACON_VERTS;
+ }
+
+ gGL.color4fv(fogged_color.mV);
+
+ LLVector3 x_axis = LLViewerCamera::getInstance()->getLeftAxis();
+ F32 t = gRenderStartTime.getElapsedTimeF32();
+
+ for (U32 i = 0; i < BEACON_VERTS; i++)
+ {
+ F32 x = x_axis.mV[0];
+ F32 y = x_axis.mV[1];
+
+ F32 z = i * step;
+ F32 z_next = (i+1)*step;
+
+ bool tracking_avatar = getTrackingStatus() == TRACKING_AVATAR;
+ F32 a = pulse_func(t, z, tracking_avatar, direction);
+ F32 an = pulse_func(t, z_next, tracking_avatar, direction);
+
+ LLColor4 c_col = fogged_color + LLColor4(a,a,a,a);
+ LLColor4 col_next = fogged_color + LLColor4(an,an,an,an);
+ LLColor4 col_edge = fogged_color * LLColor4(a,a,a,0.0f);
+ LLColor4 col_edge_next = fogged_color * LLColor4(an,an,an,0.0f);
+
+ a *= 2.f;
+ a += 1.0f;
+
+ an *= 2.f;
+ an += 1.0f;
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.color4fv(col_edge.mV);
+ gGL.vertex3f(-x*a, -y*a, z);
+ gGL.color4fv(col_edge_next.mV);
+ gGL.vertex3f(-x*an, -y*an, z_next);
+
+ gGL.color4fv(c_col.mV);
+ gGL.vertex3f(0, 0, z);
+ gGL.color4fv(col_next.mV);
+ gGL.vertex3f(0, 0, z_next);
+
+ gGL.color4fv(col_edge.mV);
+ gGL.vertex3f(x*a,y*a,z);
+ gGL.color4fv(col_edge_next.mV);
+ gGL.vertex3f(x*an,y*an,z_next);
+ gGL.end();
+ }
+ gGL.popMatrix();
+}
// static
void LLTracker::renderBeacon(LLVector3d pos_global,
- const LLColor4& color,
+ const LLColor4& color,
+ const LLColor4& color_under,
LLHUDText* hud_textp,
const std::string& label )
{
@@ -497,9 +573,11 @@ void LLTracker::renderBeacon(LLVector3d pos_global,
}
LLColor4 fogged_color = color_frac * color + (1 - color_frac)*gSky.getFogColor();
+ LLColor4 fogged_color_under = color_frac * color_under + (1 - color_frac) * gSky.getFogColor();
F32 FADE_DIST = 3.f;
fogged_color.mV[3] = llmax(0.2f, llmin(0.5f,(dist-FADE_DIST)/FADE_DIST));
+ fogged_color_under.mV[3] = llmax(0.2f, llmin(0.5f,(dist-FADE_DIST)/FADE_DIST));
LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(pos_global);
@@ -508,64 +586,8 @@ void LLTracker::renderBeacon(LLVector3d pos_global,
LLGLDisable cull_face(GL_CULL_FACE);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- {
- gGL.translatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
-
- draw_shockwave(1024.f, gRenderStartTime.getElapsedTimeF32(), 32, fogged_color);
-
- gGL.color4fv(fogged_color.mV);
- const U32 BEACON_VERTS = 256;
- const F32 step = 1024.0f/BEACON_VERTS;
-
- LLVector3 x_axis = LLViewerCamera::getInstance()->getLeftAxis();
- F32 t = gRenderStartTime.getElapsedTimeF32();
- F32 dr = dist/LLViewerCamera::getInstance()->getFar();
-
- for (U32 i = 0; i < BEACON_VERTS; i++)
- {
- F32 x = x_axis.mV[0];
- F32 y = x_axis.mV[1];
-
- F32 z = i * step;
- F32 z_next = (i+1)*step;
-
- F32 a = pulse_func(t, z);
- F32 an = pulse_func(t, z_next);
-
- LLColor4 c_col = fogged_color + LLColor4(a,a,a,a);
- LLColor4 col_next = fogged_color + LLColor4(an,an,an,an);
- LLColor4 col_edge = fogged_color * LLColor4(a,a,a,0.0f);
- LLColor4 col_edge_next = fogged_color * LLColor4(an,an,an,0.0f);
-
- a *= 2.f;
- a += 1.0f+dr;
-
- an *= 2.f;
- an += 1.0f+dr;
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.color4fv(col_edge.mV);
- gGL.vertex3f(-x*a, -y*a, z);
- gGL.color4fv(col_edge_next.mV);
- gGL.vertex3f(-x*an, -y*an, z_next);
-
- gGL.color4fv(c_col.mV);
- gGL.vertex3f(0, 0, z);
- gGL.color4fv(col_next.mV);
- gGL.vertex3f(0, 0, z_next);
-
- gGL.color4fv(col_edge.mV);
- gGL.vertex3f(x*a,y*a,z);
- gGL.color4fv(col_edge_next.mV);
- gGL.vertex3f(x*an,y*an,z_next);
-
- gGL.end();
- }
- }
- gGL.popMatrix();
+ LLTracker::drawBeacon(pos_agent, "DOWN", fogged_color, dist);
+ LLTracker::drawBeacon(pos_agent, "UP", fogged_color_under, dist);
std::string text;
text = llformat( "%.0f m", to_vec.magVec());
diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h
index 8e916af315..d8d5803787 100755
--- a/indra/newview/lltracker.h
+++ b/indra/newview/lltracker.h
@@ -108,8 +108,10 @@ protected:
LLTracker();
~LLTracker();
+ static void drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 fogged_color, F32 dist);
static void renderBeacon( LLVector3d pos_global,
const LLColor4& color,
+ const LLColor4& color_under,
LLHUDText* hud_textp,
const std::string& label );
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index f53995732f..6f1a24d7f8 100755
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -511,6 +511,9 @@
name="MapTrackColor"
reference="Red" />
<color
+ name="MapTrackColorUnder"
+ reference="Blue" />
+ <color
name="MapTrackDisabledColor"
value="0.5 0 0 1" />
<color
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 512205ba43..6fa45d7d66 100755
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -552,6 +552,14 @@
function="Inventory.DoToSelected"
parameter="about" />
</menu_item_call>
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="show_on_map" />
+ </menu_item_call>
<menu_item_separator
layout="topleft"
name="Animation Separator" />
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 894e368427..9e8623c1f9 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -38,7 +38,7 @@ viewer_dir = os.path.dirname(__file__)
# Put it FIRST because some of our build hosts have an ancient install of
# indra.util.llmanifest under their system Python!
sys.path.insert(0, os.path.join(viewer_dir, os.pardir, "lib", "python"))
-from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors
+from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors, CHANNEL_VENDOR_BASE, RELEASE_CHANNEL
try:
from llbase import llsd
except ImportError:
@@ -112,21 +112,29 @@ class ViewerManifest(LLManifest):
Persist=1,
Type='String',
Value=''),
+ CmdLineGridChoice=dict(Comment='Default grid',
+ Persist=0,
+ Type='String',
+ Value=''),
CmdLineChannel=dict(Comment='Command line specified channel name',
Persist=0,
Type='String',
Value=''))
settings_install = {}
- for key, setting in (("sourceid", "sourceid"),
- ("channel", "CmdLineChannel")):
- if key in self.args:
- # only set if value is non-empty
- if self.args[key]:
- # copy corresponding setting from settings_template
- settings_install[setting] = settings_template[setting].copy()
- # then fill in Value
- settings_install[setting]["Value"] = self.args[key]
- print "Put %s '%s' in settings_install.xml" % (setting, self.args[key])
+ if 'sourceid' in self.args and self.args['sourceid']:
+ settings_install['sourceid'] = settings_template['sourceid'].copy()
+ settings_install['sourceid']['Value'] = self.args['sourceid']
+ print "Set sourceid in settings_install.xml to '%s'" % self.args['sourceid']
+
+ if 'channel_suffix' in self.args and self.args['channel_suffix']:
+ settings_install['CmdLineChannel'] = settings_template['CmdLineChannel'].copy()
+ settings_install['CmdLineChannel']['Value'] = self.channel_with_pkg_suffix()
+ print "Set CmdLineChannel in settings_install.xml to '%s'" % self.channel_with_pkg_suffix()
+
+ if 'grid' in self.args and self.args['grid']:
+ settings_install['CmdLineGridChoice'] = settings_template['CmdLineGridChoice'].copy()
+ settings_install['CmdLineGridChoice']['Value'] = self.grid()
+ print "Set CmdLineGridChoice in settings_install.xml to '%s'" % self.grid()
# did we actually copy anything into settings_install dict?
if settings_install:
@@ -197,62 +205,72 @@ class ViewerManifest(LLManifest):
def grid(self):
return self.args['grid']
+
def channel(self):
return self.args['channel']
- def channel_unique(self):
- return self.channel().replace("Second Life", "").strip()
- def channel_oneword(self):
- return "".join(self.channel_unique().split())
- def channel_lowerword(self):
- return self.channel_oneword().lower()
+
+ def channel_with_pkg_suffix(self):
+ fullchannel=self.channel()
+ if 'channel_suffix' in self.args and self.args['channel_suffix']:
+ fullchannel+=' '+self.args['channel_suffix']
+ return fullchannel
+
+ def channel_variant(self):
+ global CHANNEL_VENDOR_BASE
+ return self.channel().replace(CHANNEL_VENDOR_BASE, "").strip()
+
+ def channel_type(self): # returns 'release', 'beta', 'project', or 'test'
+ global CHANNEL_VENDOR_BASE
+ channel_qualifier=self.channel().replace(CHANNEL_VENDOR_BASE, "").lower().strip()
+ if channel_qualifier.startswith('release'):
+ channel_type='release'
+ elif channel_qualifier.startswith('beta'):
+ channel_type='beta'
+ elif channel_qualifier.startswith('project'):
+ channel_type='project'
+ else:
+ channel_type='test'
+ return channel_type
+
+ def channel_variant_app_suffix(self):
+ # get any part of the compiled channel name after the CHANNEL_VENDOR_BASE
+ suffix=self.channel_variant()
+ # by ancient convention, we don't use Release in the app name
+ if self.channel_type() == 'release':
+ suffix=suffix.replace('Release', '').strip()
+ # for the base release viewer, suffix will now be null - for any other, append what remains
+ if len(suffix) > 0:
+ suffix = "_"+ ("_".join(suffix.split()))
+ # the additional_packages mechanism adds more to the installer name (but not to the app name itself)
+ if 'channel_suffix' in self.args and self.args['channel_suffix']:
+ suffix+='_'+("_".join(self.args['channel_suffix'].split()))
+ return suffix
+
+ def installer_base_name(self):
+ global CHANNEL_VENDOR_BASE
+ # a standard map of strings for replacing in the templates
+ substitution_strings = {
+ 'channel_vendor_base' : '_'.join(CHANNEL_VENDOR_BASE.split()),
+ 'channel_variant_underscores':self.channel_variant_app_suffix(),
+ 'version_underscores' : '_'.join(self.args['version']),
+ 'arch':self.args['arch']
+ }
+ return "%(channel_vendor_base)s%(channel_variant_underscores)s_%(version_underscores)s_%(arch)s" % substitution_strings
def app_name(self):
- app_suffix='Test'
- channel_type=self.channel_lowerword()
- if channel_type.startswith('release') :
+ global CHANNEL_VENDOR_BASE
+ channel_type=self.channel_type()
+ if channel_type == 'release':
app_suffix='Viewer'
- elif re.match('^(beta|project).*',channel_type) :
- app_suffix=self.channel_unique()
- return "Second Life "+app_suffix
-
+ else:
+ app_suffix=self.channel_variant()
+ return CHANNEL_VENDOR_BASE + ' ' + app_suffix
+
+ def app_name_oneword(self):
+ return ''.join(self.app_name().split())
+
def icon_path(self):
- icon_path="icons/"
- channel_type=self.channel_lowerword()
- print "Icon channel type '%s'" % channel_type
- if channel_type.startswith('release') :
- icon_path += 'release'
- elif re.match('^beta.*',channel_type) :
- icon_path += 'beta'
- elif re.match('^project.*',channel_type) :
- icon_path += 'project'
- else :
- icon_path += 'test'
- return icon_path
-
- def flags_list(self):
- """ Convenience function that returns the command-line flags
- for the grid"""
-
- # The original role of this method seems to have been to build a
- # grid-specific viewer: one that would, on launch, preselect a
- # particular grid. (Apparently that dates back to when the protocol
- # between viewer and simulator required them to be updated in
- # lockstep, so that "the beta grid" required "a beta viewer.") But
- # those viewer command-line switches no longer work without tweaking
- # user_settings/grids.xml. In fact, going forward, it's unclear what
- # use case that would address.
-
- # This method also set a channel-specific (or grid-and-channel-
- # specific) user_settings/settings_something.xml file. It has become
- # clear that saving user settings in a channel-specific file causes
- # more problems (confusion) than it solves, so we've discontinued that.
-
- # In fact we now avoid forcing viewer command-line switches at all,
- # instead introducing a settings_install.xml file. Command-line
- # switches don't aggregate well; for instance the generated --channel
- # switch actually prevented the user specifying --channel on the
- # command line. Settings files have well-defined override semantics.
- return None
+ return "icons/" + self.channel_type()
def extract_names(self,src):
try:
@@ -277,15 +295,9 @@ class ViewerManifest(LLManifest):
random.shuffle(names)
return ', '.join(names)
-class WindowsManifest(ViewerManifest):
+class Windows_i686_Manifest(ViewerManifest):
def final_exe(self):
- app_suffix="Test"
- channel_type=self.channel_lowerword()
- if channel_type.startswith('release') :
- app_suffix=''
- elif re.match('^(beta|project).*',channel_type) :
- app_suffix=''.join(self.channel_unique().split())
- return "SecondLife"+app_suffix+".exe"
+ return self.app_name_oneword()+".exe"
def test_msvcrt_and_copy_action(self, src, dst):
# This is used to test a dll manifest.
@@ -334,7 +346,7 @@ class WindowsManifest(ViewerManifest):
print "Doesn't exist:", src
def construct(self):
- super(WindowsManifest, self).construct()
+ super(Windows_i686_Manifest, self).construct()
if self.is_packaging_viewer():
# Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
@@ -567,65 +579,33 @@ class WindowsManifest(ViewerManifest):
'version_short' : '.'.join(self.args['version'][:-1]),
'version_dashes' : '-'.join(self.args['version']),
'final_exe' : self.final_exe(),
- 'grid':self.args['grid'],
- 'grid_caps':self.args['grid'].upper(),
'flags':'',
- 'channel':self.channel(),
- 'channel_oneword':self.channel_oneword(),
- 'channel_unique':self.channel_unique(),
- 'subchannel_underscores':'_'.join(self.channel_unique().split())
+ 'app_name':self.app_name(),
+ 'app_name_oneword':self.app_name_oneword()
}
+ installer_file = self.installer_base_name() + '_Setup.exe'
+ substitution_strings['installer_file'] = installer_file
+
version_vars = """
!define INSTEXE "%(final_exe)s"
!define VERSION "%(version_short)s"
!define VERSION_LONG "%(version)s"
!define VERSION_DASHES "%(version_dashes)s"
""" % substitution_strings
- if self.default_channel():
- if self.default_grid():
- # release viewer
- installer_file = "Second_Life_%(version_dashes)s_Setup.exe"
- grid_vars_template = """
- OutFile "%(installer_file)s"
- !define INSTFLAGS "%(flags)s"
- !define INSTNAME "SecondLifeViewer"
- !define SHORTCUT "Second Life Viewer"
- !define URLNAME "secondlife"
- Caption "Second Life"
- """
- else:
- # alternate grid viewer
- installer_file = "Second_Life_%(version_dashes)s_(%(grid_caps)s)_Setup.exe"
- grid_vars_template = """
- OutFile "%(installer_file)s"
- !define INSTFLAGS "%(flags)s"
- !define INSTNAME "SecondLife%(grid_caps)s"
- !define SHORTCUT "Second Life (%(grid_caps)s)"
- !define URLNAME "secondlife%(grid)s"
- !define UNINSTALL_SETTINGS 1
- Caption "Second Life %(grid)s ${VERSION}"
- """
+
+ if self.channel_type() == 'release':
+ substitution_strings['caption'] = CHANNEL_VENDOR_BASE
else:
- # some other channel (grid name not used)
- installer_file = "Second_Life_%(version_dashes)s_%(subchannel_underscores)s_Setup.exe"
- grid_vars_template = """
+ substitution_strings['caption'] = self.app_name() + ' ${VERSION}'
+
+ inst_vars_template = """
OutFile "%(installer_file)s"
- !define INSTFLAGS "%(flags)s"
- !define INSTNAME "SecondLife%(channel_oneword)s"
- !define SHORTCUT "%(channel)s"
+ !define INSTNAME "%(app_name_oneword)s"
+ !define SHORTCUT "%(app_name)s"
!define URLNAME "secondlife"
- !define UNINSTALL_SETTINGS 1
- Caption "%(channel)s ${VERSION}"
+ Caption "%(caption)s"
"""
- if 'installer_name' in self.args:
- installer_file = self.args['installer_name']
- else:
- installer_file = installer_file % substitution_strings
- if len(self.args['package_id']) > 0:
- installer_file = installer_file.replace(self.args['package_id'], "")
- installer_file = installer_file.replace(".exe", self.args['package_id'] + ".exe")
- substitution_strings['installer_file'] = installer_file
tempfile = "secondlife_setup_tmp.nsi"
# the following replaces strings in the nsi template
@@ -633,7 +613,7 @@ class WindowsManifest(ViewerManifest):
self.replace_in("installers/windows/installer_template.nsi", tempfile, {
"%%VERSION%%":version_vars,
"%%SOURCE%%":self.get_src_prefix(),
- "%%GRID_VARS%%":grid_vars_template % substitution_strings,
+ "%%INST_VARS%%":inst_vars_template % substitution_strings,
"%%INSTALL_FILES%%":self.nsi_file_commands(True),
"%%DELETE_FILES%%":self.nsi_file_commands(False)})
@@ -663,7 +643,7 @@ class WindowsManifest(ViewerManifest):
self.package_file = installer_file
-class DarwinManifest(ViewerManifest):
+class Darwin_i386_Manifest(ViewerManifest):
def is_packaging_viewer(self):
# darwin requires full app bundle packaging even for debugging.
return True
@@ -685,7 +665,7 @@ class DarwinManifest(ViewerManifest):
# most everything goes in the Resources directory
if self.prefix(src="", dst="Resources"):
- super(DarwinManifest, self).construct()
+ super(Darwin_i386_Manifest, self).construct()
if self.prefix("cursors_mac"):
self.path("*.tif")
@@ -821,6 +801,7 @@ class DarwinManifest(ViewerManifest):
self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
def package_finish(self):
+ global CHANNEL_VENDOR_BASE
# Sign the app if requested.
if 'signature' in self.args:
identity = self.args['signature']
@@ -850,17 +831,9 @@ class DarwinManifest(ViewerManifest):
# MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning.
# If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick.
- volname="Second Life Installer" # DO NOT CHANGE without understanding comment above
+ volname=CHANNEL_VENDOR_BASE+" Installer" # DO NOT CHANGE without understanding comment above
- if len(self.args['package_id']) > 0:
- imagename = imagename + self.args['package_id']
- elif self.default_channel():
- if not self.default_grid():
- # beta case
- imagename = imagename + '_' + self.args['grid'].upper()
- else:
- # first look, etc
- imagename = imagename + '_' + self.channel_oneword().upper()
+ imagename = self.installer_base_name()
sparsename = imagename + ".sparseimage"
finalname = imagename + ".dmg"
@@ -894,7 +867,7 @@ class DarwinManifest(ViewerManifest):
# will use the release .DS_Store, and will look broken.
# - Ambroff 2008-08-20
dmg_template = os.path.join(
- 'installers', 'darwin', '%s-dmg' % self.channel_lowerword())
+ 'installers', 'darwin', '%s-dmg' % self.channel_type())
if not os.path.exists (self.src_path_of(dmg_template)):
dmg_template = os.path.join ('installers', 'darwin', 'release-dmg')
@@ -977,8 +950,9 @@ class LinuxManifest(ViewerManifest):
# recurse
self.end_prefix("res-sdl")
- # Get the icons based on the channel
+ # Get the icons based on the channel type
icon_path = self.icon_path()
+ print "DEBUG: icon_path '%s'" % icon_path
if self.prefix(src=icon_path, dst="") :
self.path("secondlife_256.png","secondlife_icon.png")
if self.prefix(src="",dst="res-sdl") :
@@ -1004,18 +978,7 @@ class LinuxManifest(ViewerManifest):
self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
def package_finish(self):
- if 'installer_name' in self.args:
- installer_name = self.args['installer_name']
- else:
- installer_name_components = ['SecondLife_', self.args.get('arch')]
- installer_name_components.extend(self.args['version'])
- installer_name = "_".join(installer_name_components)
- if self.default_channel():
- if not self.default_grid():
- installer_name += '_' + self.args['grid'].upper()
- else:
- installer_name += '_' + self.channel_oneword().upper()
- installer_name = installer_name + self.args['package_id']
+ installer_name = self.installer_base_name()
self.strip_binaries()
@@ -1057,9 +1020,9 @@ class LinuxManifest(ViewerManifest):
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):
+class Linux_i686_Manifest(LinuxManifest):
def construct(self):
- super(Linux_i686Manifest, self).construct()
+ super(Linux_i686_Manifest, self).construct()
if self.prefix("../packages/lib/release", dst="lib"):
self.path("libapr-1.so")
@@ -1145,9 +1108,9 @@ class Linux_i686Manifest(LinuxManifest):
self.strip_binaries()
-class Linux_x86_64Manifest(LinuxManifest):
+class Linux_x86_64_Manifest(LinuxManifest):
def construct(self):
- super(Linux_x86_64Manifest, self).construct()
+ super(Linux_x86_64_Manifest, self).construct()
# support file for valgrind debug tool
self.path("secondlife-i686.supp")
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index c28ad76c77..c42112af80 100755
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -77,7 +77,8 @@ private:
void run(void);
void startDownloading(LLURI const & uri, std::string const & hash);
void throwOnCurlError(CURLcode code);
- bool validateDownload(void);
+ bool validateDownload(const std::string& filePath);
+ bool validateOrRemove(const std::string& filePath);
LOG_CLASS(LLUpdateDownloader::Implementation);
};
@@ -295,9 +296,8 @@ void LLUpdateDownloader::Implementation::resume(void)
{
resumeDownloading(fileStatus.st_size);
}
- else if(!validateDownload())
+ else if(!validateOrRemove(filePath))
{
- LLFile::remove(filePath);
download(LLURI(mDownloadData["url"].asString()),
mDownloadData["hash"].asString(),
mDownloadData["update_channel"].asString(),
@@ -421,19 +421,13 @@ void LLUpdateDownloader::Implementation::run(void)
if(code == CURLE_OK)
{
LLFile::remove(mDownloadRecordPath);
- if(validateDownload())
+ if(validateOrRemove(mDownloadData["path"]))
{
LL_INFOS("UpdaterService") << "download successful" << LL_ENDL;
mClient.downloadComplete(mDownloadData);
}
else
{
- LL_INFOS("UpdaterService") << "download failed hash check" << LL_ENDL;
- std::string filePath = mDownloadData["path"].asString();
- if(filePath.size() != 0)
- {
- LLFile::remove(filePath);
- }
mClient.downloadError("failed hash check");
}
}
@@ -449,7 +443,9 @@ void LLUpdateDownloader::Implementation::run(void)
LLFile::remove(mDownloadRecordPath);
if(mDownloadData.has("path"))
{
- LLFile::remove(mDownloadData["path"].asString());
+ std::string filePath = mDownloadData["path"].asString();
+ LL_INFOS("UpdaterService") << "removing " << filePath << LL_ENDL;
+ LLFile::remove(filePath);
}
mClient.downloadError("curl error");
}
@@ -561,31 +557,49 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
}
}
+bool LLUpdateDownloader::Implementation::validateOrRemove(const std::string& filePath)
+{
+ bool valid = validateDownload(filePath);
+ if (! valid)
+ {
+ LL_INFOS("UpdaterService") << "removing " << filePath << LL_ENDL;
+ LLFile::remove(filePath);
+ }
+ return valid;
+}
-bool LLUpdateDownloader::Implementation::validateDownload(void)
+bool LLUpdateDownloader::Implementation::validateDownload(const std::string& filePath)
{
- std::string filePath = mDownloadData["path"].asString();
llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);
if(!fileStream)
{
+ LL_INFOS("UpdaterService") << "can't open " << filePath << ", invalid" << LL_ENDL;
return false;
}
std::string hash = mDownloadData["hash"].asString();
- if(hash.size() != 0)
+ if (! hash.empty())
{
- LL_INFOS("UpdaterService") << "checking hash..." << LL_ENDL;
char digest[33];
LLMD5(fileStream).hex_digest(digest);
- if(hash != digest)
+ if (hash == digest)
+ {
+ LL_INFOS("UpdaterService") << "verified hash " << hash
+ << " for downloaded " << filePath << LL_ENDL;
+ return true;
+ }
+ else
{
- LL_WARNS("UpdaterService") << "download hash mismatch; expected " << hash <<
- " but download is " << digest << LL_ENDL;
+ LL_WARNS("UpdaterService") << "download hash mismatch for "
+ << filePath << ": expected " << hash
+ << " but computed " << digest << LL_ENDL;
+ return false;
}
- return hash == digest;
}
else
{
+ LL_INFOS("UpdaterService") << "no hash specified for " << filePath
+ << ", unverified" << LL_ENDL;
return true; // No hash check provided.
}
}
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 16950e1d62..cb3be5bbdc 100755
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -296,37 +296,49 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
update_marker.close();
// Get the path to the installer file.
- LLSD path = update_info.get("path");
- if(update_info["current_version"].asString() != ll_get_version())
+ std::string path(update_info.get("path"));
+ std::string downloader_version(update_info["current_version"]);
+ if (downloader_version != ll_get_version())
{
// This viewer is not the same version as the one that downloaded
- // the update. Do not install this update.
- if(!path.asString().empty())
+ // the update. Do not install this update.
+ LL_INFOS("UpdaterService") << "ignoring update downloaded by "
+ << "different viewer version "
+ << downloader_version << LL_ENDL;
+ if (! path.empty())
{
- LL_INFOS("UpdaterService") << "ignoring update dowloaded by different client version" << LL_ENDL;;
- LLFile::remove(path.asString());
+ LL_INFOS("UpdaterService") << "removing " << path << LL_ENDL;
+ LLFile::remove(path);
LLFile::remove(update_marker_path());
}
- else
- {
- ; // Nothing to clean up.
- }
-
+
foundInstall = false;
}
- else if(path.isDefined() && !path.asString().empty())
+ else if (path.empty())
+ {
+ LL_WARNS("UpdaterService") << "Marker file " << update_marker_path()
+ << " 'path' entry empty, ignoring" << LL_ENDL;
+ foundInstall = false;
+ }
+ else if (! LLFile::isfile(path))
+ {
+ LL_WARNS("UpdaterService") << "Nonexistent installer " << path
+ << ", ignoring" << LL_ENDL;
+ foundInstall = false;
+ }
+ else
{
if(launchInstaller)
{
setState(LLUpdaterService::INSTALLING);
-
+
LLFile::remove(update_marker_path());
int result = ll_install_update(install_script_path(),
- update_info["path"].asString(),
+ path,
update_info["required"].asBoolean(),
install_script_mode());
-
+
if((result == 0) && mAppExitCallback)
{
mAppExitCallback();
@@ -360,7 +372,8 @@ bool LLUpdaterServiceImpl::checkForResume()
LLSD download_info;
LLSDSerialize::fromXMLDocument(download_info, download_marker_stream);
download_marker_stream.close();
- if(download_info["current_version"].asString() == ll_get_version())
+ std::string downloader_version(download_info["current_version"]);
+ if (downloader_version == ll_get_version())
{
mIsDownloading = true;
mNewVersion = download_info["update_version"].asString();
@@ -371,10 +384,13 @@ bool LLUpdaterServiceImpl::checkForResume()
else
{
// The viewer that started this download is not the same as this viewer; ignore.
- LL_INFOS("UpdaterService") << "ignoring partial download from different viewer version" << LL_ENDL;;
+ LL_INFOS("UpdaterService") << "ignoring partial download "
+ << "from different viewer version "
+ << downloader_version << LL_ENDL;
std::string path = download_info["path"].asString();
if(!path.empty())
{
+ LL_INFOS("UpdaterService") << "removing " << path << LL_ENDL;
LLFile::remove(path);
}
LLFile::remove(download_marker_path);
@@ -539,7 +555,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
// Check for failed install.
if(LLFile::isfile(ll_install_failed_marker_path()))
{
- LL_DEBUGS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;;
+ LL_DEBUGS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;
int requiredValue = 0;
{
llifstream stream(ll_install_failed_marker_path());
@@ -552,12 +568,12 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
// TODO: notify the user.
LL_WARNS("UpdaterService") << "last install attempt failed" << LL_ENDL;;
LLFile::remove(ll_install_failed_marker_path());
-
+
LLSD event;
event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR);
event["required"] = LLSD(requiredValue);
LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event);
-
+
setState(LLUpdaterService::TERMINAL);
}
else
diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py
index 10d507c9ef..08f4f0ebb9 100755
--- a/indra/viewer_components/updater/scripts/darwin/update_install.py
+++ b/indra/viewer_components/updater/scripts/darwin/update_install.py
@@ -199,6 +199,11 @@ def main(dmgfile, markerfile, markertext):
# prepare for other cleanup
with Janitor(LOGF) as janitor:
+ # Under some circumstances, this script seems to be invoked with a
+ # nonexistent pathname. Check for that.
+ if not os.path.isfile(dmgfile):
+ fail(dmgfile + " has been deleted")
+
# Try to derive the name of the running viewer app bundle from our
# own pathname. (Hopefully the old viewer won't copy this script
# to a temp dir before running!)
@@ -376,6 +381,13 @@ def main(dmgfile, markerfile, markertext):
log(' '.join(command))
subprocess.check_call(command, stdout=LOGF, stderr=subprocess.STDOUT)
+ # If all the above succeeded, delete the .dmg file. We don't do this
+ # as a janitor.later() operation because we only want to do it if we
+ # get this far successfully. Note that this is out of the scope of the
+ # Janitor: we must detach the .dmg before removing it!
+ log("rm " + dmgfile)
+ os.remove(dmgfile)
+
except Exception, err:
# Because we carefully set sys.excepthook -- and even modify it to log
# the problem once we have our log file open -- you might think we