From 34fe6ad59161e0dcd57dfdc1feb6cfd1fcaa4794 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Tue, 12 Mar 2013 22:34:15 +0000
Subject: SH-3944 WIP CHUI merge fixing

re-introduced don's refactor of low-level openGL calls pulling out of llui
and putting them into llrender. Took the new code from their updated versions
from the CHUI merge, but put them in a place accessible to appearance utility.
---
 indra/llrender/CMakeLists.txt      |    4 +
 indra/llrender/llrender2dutils.cpp | 1608 ++++++++++++++++++++++++++++++++++++
 indra/llrender/llrender2dutils.h   |  163 ++++
 indra/llrender/lluiimage.cpp       |  243 ++++++
 indra/llrender/lluiimage.h         |  126 +++
 indra/llui/CMakeLists.txt          |    2 -
 indra/llui/llcombobox.cpp          |    2 +-
 indra/llui/lllineeditor.cpp        |    6 +-
 indra/llui/lllocalcliprect.cpp     |    8 +-
 indra/llui/lltextbase.cpp          |    4 +-
 indra/llui/lltexteditor.cpp        |    2 +-
 indra/llui/llui.cpp                | 1567 +----------------------------------
 indra/llui/llui.h                  |  130 +--
 indra/llui/lluiimage.cpp           |  243 ------
 indra/llui/lluiimage.h             |  126 ---
 indra/newview/llappviewer.cpp      |    2 +-
 indra/newview/llglsandbox.cpp      |    8 +-
 indra/newview/llmediactrl.cpp      |   18 +-
 indra/newview/llviewerdisplay.cpp  |   10 +-
 indra/newview/llviewerwindow.cpp   |   12 +-
 indra/newview/llworldmapview.cpp   |    4 +-
 21 files changed, 2210 insertions(+), 2078 deletions(-)
 create mode 100644 indra/llrender/llrender2dutils.cpp
 create mode 100644 indra/llrender/llrender2dutils.h
 create mode 100644 indra/llrender/lluiimage.cpp
 create mode 100644 indra/llrender/lluiimage.h
 delete mode 100644 indra/llui/lluiimage.cpp
 delete mode 100644 indra/llui/lluiimage.h

diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 904f5587b7..669b70aa43 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -43,11 +43,13 @@ set(llrender_SOURCE_FILES
     llimagegl.cpp
     llpostprocess.cpp
     llrender.cpp
+    llrender2dutils.cpp
     llrendernavprim.cpp
     llrendersphere.cpp
     llrendertarget.cpp
     llshadermgr.cpp
     lltexture.cpp
+    lluiimage.cpp
     llvertexbuffer.cpp
     )
     
@@ -69,10 +71,12 @@ set(llrender_HEADER_FILES
     llimagegl.h
     llpostprocess.h
     llrender.h
+    llrender2dutils.h
     llrendernavprim.h
     llrendersphere.h
     llshadermgr.h
     lltexture.h
+    lluiimage.h
     llvertexbuffer.h
     )
 
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
new file mode 100644
index 0000000000..d3cfbaf03a
--- /dev/null
+++ b/indra/llrender/llrender2dutils.cpp
@@ -0,0 +1,1608 @@
+/** 
+ * @file llrender2dutils.cpp
+ * @brief GL function implementations for immediate-mode gl drawing.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// Linden library includes
+#include "v2math.h"
+#include "m3math.h"
+#include "v4color.h"
+#include "llfontgl.h"
+#include "llrender.h"
+#include "llrect.h"
+#include "llgl.h"
+#include "lltexture.h"
+
+// Project includes
+#include "llrender2dutils.h"
+#include "lluiimage.h"
+
+
+//
+// Globals
+//
+const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
+/*static*/ LLVector2		LLRender2D::sGLScaleFactor(1.f, 1.f);
+/*static*/ LLImageProviderInterface* LLRender2D::sImageProvider = NULL;
+
+//
+// Functions
+//
+
+BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
+{
+	if (x < left || right < x) return FALSE;
+	if (y < bottom || top < y) return FALSE;
+	return TRUE;
+}
+
+
+// Puts GL into 2D drawing mode by turning off lighting, setting to an
+// orthographic projection, etc.
+void gl_state_for_2d(S32 width, S32 height)
+{
+	stop_glerror();
+	F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
+	F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
+
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.loadIdentity();
+	gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.loadIdentity();
+	stop_glerror();
+}
+
+
+void gl_draw_x(const LLRect& rect, const LLColor4& color)
+{
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	gGL.color4fv( color.mV );
+
+	gGL.begin( LLRender::LINES );
+		gGL.vertex2i( rect.mLeft,		rect.mTop );
+		gGL.vertex2i( rect.mRight,	rect.mBottom );
+		gGL.vertex2i( rect.mLeft,		rect.mBottom );
+		gGL.vertex2i( rect.mRight,	rect.mTop );
+	gGL.end();
+}
+
+
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled)
+{
+	gGL.color4fv(color.mV);
+	gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
+}
+
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
+{
+	gGL.pushUIMatrix();
+	left += LLFontGL::sCurOrigin.mX;
+	right += LLFontGL::sCurOrigin.mX;
+	bottom += LLFontGL::sCurOrigin.mY;
+	top += LLFontGL::sCurOrigin.mY;
+
+	gGL.loadUIIdentity();
+	gl_rect_2d(llfloor((F32)left * LLRender2D::sGLScaleFactor.mV[VX]) - pixel_offset,
+				llfloor((F32)top * LLRender2D::sGLScaleFactor.mV[VY]) + pixel_offset,
+				llfloor((F32)right * LLRender2D::sGLScaleFactor.mV[VX]) + pixel_offset,
+				llfloor((F32)bottom * LLRender2D::sGLScaleFactor.mV[VY]) - pixel_offset,
+				filled);
+	gGL.popUIMatrix();
+}
+
+
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
+{
+	stop_glerror();
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	// Counterclockwise quad will face the viewer
+	if( filled )
+	{ 
+		gGL.begin( LLRender::QUADS );
+			gGL.vertex2i(left, top);
+			gGL.vertex2i(left, bottom);
+			gGL.vertex2i(right, bottom);
+			gGL.vertex2i(right, top);
+		gGL.end();
+	}
+	else
+	{
+		if( gGLManager.mATIOffsetVerticalLines )
+		{
+			// Work around bug in ATI driver: vertical lines are offset by (-1,-1)
+			gGL.begin( LLRender::LINES );
+
+				// Verticals 
+				gGL.vertex2i(left + 1, top);
+				gGL.vertex2i(left + 1, bottom);
+
+				gGL.vertex2i(right, bottom);
+				gGL.vertex2i(right, top);
+
+				// Horizontals
+				top--;
+				right--;
+				gGL.vertex2i(left, bottom);
+				gGL.vertex2i(right, bottom);
+
+				gGL.vertex2i(left, top);
+				gGL.vertex2i(right, top);
+			gGL.end();
+		}
+		else
+		{
+			top--;
+			right--;
+			gGL.begin( LLRender::LINE_STRIP );
+				gGL.vertex2i(left, top);
+				gGL.vertex2i(left, bottom);
+				gGL.vertex2i(right, bottom);
+				gGL.vertex2i(right, top);
+				gGL.vertex2i(left, top);
+			gGL.end();
+		}
+	}
+	stop_glerror();
+}
+
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
+{
+	gGL.color4fv( color.mV );
+	gl_rect_2d( left, top, right, bottom, filled );
+}
+
+
+void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
+{
+	gGL.color4fv( color.mV );
+	gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
+}
+
+// Given a rectangle on the screen, draws a drop shadow _outside_
+// the right and bottom edges of it.  Along the right it has width "lines"
+// and along the bottom it has height "lines".
+void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines)
+{
+	stop_glerror();
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	
+	// HACK: Overlap with the rectangle by a single pixel.
+	right--;
+	bottom++;
+	lines++;
+
+	LLColor4 end_color = start_color;
+	end_color.mV[VALPHA] = 0.f;
+
+	gGL.begin(LLRender::QUADS);
+
+	// Right edge, CCW faces screen
+	gGL.color4fv(start_color.mV);
+	gGL.vertex2i(right,		top-lines);
+	gGL.vertex2i(right,		bottom);
+	gGL.color4fv(end_color.mV);
+	gGL.vertex2i(right+lines, bottom);
+	gGL.vertex2i(right+lines, top-lines);
+
+	// Bottom edge, CCW faces screen
+	gGL.color4fv(start_color.mV);
+	gGL.vertex2i(right,		bottom);
+	gGL.vertex2i(left+lines,	bottom);
+	gGL.color4fv(end_color.mV);
+	gGL.vertex2i(left+lines,	bottom-lines);
+	gGL.vertex2i(right,		bottom-lines);
+
+	// bottom left Corner
+	gGL.color4fv(start_color.mV);
+	gGL.vertex2i(left+lines,	bottom);
+	gGL.color4fv(end_color.mV);
+	gGL.vertex2i(left,		bottom);
+	// make the bottom left corner not sharp
+	gGL.vertex2i(left+1,		bottom-lines+1);
+	gGL.vertex2i(left+lines,	bottom-lines);
+
+	// bottom right corner
+	gGL.color4fv(start_color.mV);
+	gGL.vertex2i(right,		bottom);
+	gGL.color4fv(end_color.mV);
+	gGL.vertex2i(right,		bottom-lines);
+	// make the rightmost corner not sharp
+	gGL.vertex2i(right+lines-1,	bottom-lines+1);
+	gGL.vertex2i(right+lines,	bottom);
+
+	// top right corner
+	gGL.color4fv(start_color.mV);
+	gGL.vertex2i( right,			top-lines );
+	gGL.color4fv(end_color.mV);
+	gGL.vertex2i( right+lines,	top-lines );
+	// make the corner not sharp
+	gGL.vertex2i( right+lines-1,	top-1 );
+	gGL.vertex2i( right,			top );
+
+	gGL.end();
+	stop_glerror();
+}
+
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 )
+{
+	// Work around bug in ATI driver: vertical lines are offset by (-1,-1)
+	if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
+	{
+		x1++;
+		x2++;
+		y1++;
+		y2++;
+	}
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	
+	gGL.begin(LLRender::LINES);
+		gGL.vertex2i(x1, y1);
+		gGL.vertex2i(x2, y2);
+	gGL.end();
+}
+
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color )
+{
+	// Work around bug in ATI driver: vertical lines are offset by (-1,-1)
+	if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
+	{
+		x1++;
+		x2++;
+		y1++;
+		y2++;
+	}
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	gGL.color4fv( color.mV );
+
+	gGL.begin(LLRender::LINES);
+		gGL.vertex2i(x1, y1);
+		gGL.vertex2i(x2, y2);
+	gGL.end();
+}
+
+void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled)
+{
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	gGL.color4fv(color.mV);
+
+	if (filled)
+	{
+		gGL.begin(LLRender::TRIANGLES);
+	}
+	else
+	{
+		gGL.begin(LLRender::LINE_LOOP);
+	}
+	gGL.vertex2i(x1, y1);
+	gGL.vertex2i(x2, y2);
+	gGL.vertex2i(x3, y3);
+	gGL.end();
+}
+
+void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac)
+{
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	length = llmin((S32)(max_frac*(right - left)), length);
+	length = llmin((S32)(max_frac*(top - bottom)), length);
+	gGL.begin(LLRender::LINES);
+	gGL.vertex2i(left, top);
+	gGL.vertex2i(left + length, top);
+	
+	gGL.vertex2i(left, top);
+	gGL.vertex2i(left, top - length);
+
+	gGL.vertex2i(left, bottom);
+	gGL.vertex2i(left + length, bottom);
+	
+	gGL.vertex2i(left, bottom);
+	gGL.vertex2i(left, bottom + length);
+
+	gGL.vertex2i(right, top);
+	gGL.vertex2i(right - length, top);
+
+	gGL.vertex2i(right, top);
+	gGL.vertex2i(right, top - length);
+
+	gGL.vertex2i(right, bottom);
+	gGL.vertex2i(right - length, bottom);
+
+	gGL.vertex2i(right, bottom);
+	gGL.vertex2i(right, bottom + length);
+	gGL.end();
+}
+
+
+void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect )
+{
+	if (NULL == image)
+	{
+		llwarns << "image == NULL; aborting function" << llendl;
+		return;
+	}
+	gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
+}
+
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
+{
+	if (NULL == image)
+	{
+		llwarns << "image == NULL; aborting function" << llendl;
+		return;
+	}
+	gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
+}
+
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
+{
+	if (NULL == image)
+	{
+		llwarns << "image == NULL; aborting function" << llendl;
+		return;
+	}
+
+	// scale screen size of borders down
+	F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
+	F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
+
+	LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
+	gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
+}
+
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect)
+{
+	stop_glerror();
+
+	if (NULL == image)
+	{
+		llwarns << "image == NULL; aborting function" << llendl;
+		return;
+	}
+
+	// add in offset of current image to current UI translation
+	const LLVector3 ui_scale = gGL.getUIScale();
+	const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
+
+	F32 uv_width = uv_outer_rect.getWidth();
+	F32 uv_height = uv_outer_rect.getHeight();
+
+	// shrink scaling region to be proportional to clipped image region
+	LLRectf uv_center_rect(
+		uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
+		uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
+		uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
+		uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
+
+	F32 image_width = image->getWidth(0);
+	F32 image_height = image->getHeight(0);
+
+	S32 image_natural_width = llround(image_width * uv_width);
+	S32 image_natural_height = llround(image_height * uv_height);
+
+	LLRectf draw_center_rect(	uv_center_rect.mLeft * image_width,
+								uv_center_rect.mTop * image_height,
+								uv_center_rect.mRight * image_width,
+								uv_center_rect.mBottom * image_height);
+
+	{	// scale fixed region of image to drawn region
+		draw_center_rect.mRight += width - image_natural_width;
+		draw_center_rect.mTop += height - image_natural_height;
+
+		F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
+		F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
+
+		F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
+		F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
+
+		F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
+
+		draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]);
+		draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]);
+		draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]);
+		draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]);
+	}
+
+	LLRectf draw_outer_rect(ui_translation.mV[VX], 
+							ui_translation.mV[VY] + height * ui_scale.mV[VY], 
+							ui_translation.mV[VX] + width * ui_scale.mV[VX], 
+							ui_translation.mV[VY]);
+
+	LLGLSUIDefault gls_ui;
+	
+	if (solid_color)
+	{
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gSolidColorProgram.bind();
+		}
+		else
+		{
+			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
+			gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
+		}
+	}
+
+	gGL.getTexUnit(0)->bind(image, true);
+
+	gGL.color4fv(color.mV);
+	
+	const S32 NUM_VERTICES = 9 * 4; // 9 quads
+	LLVector2 uv[NUM_VERTICES];
+	LLVector3 pos[NUM_VERTICES];
+
+	S32 index = 0;
+
+	gGL.begin(LLRender::QUADS);
+	{
+		// draw bottom left
+		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
+		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		// draw bottom middle
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		// draw bottom right
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
+		pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		// draw left 
+		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+		index++;
+
+		// draw middle
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+		index++;
+
+		// draw right 
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+		index++;
+
+		// draw top left
+		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
+		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
+		index++;
+
+		// draw top middle
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+		index++;
+
+		// draw top right
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
+		pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
+		index++;
+
+		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+		index++;
+
+		gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+	}
+	gGL.end();
+
+	if (solid_color)
+	{
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.bind();
+		}
+		else
+		{
+			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		}
+	}
+}
+
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
+{
+	gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
+}
+
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
+{
+	if (NULL == image)
+	{
+		llwarns << "image == NULL; aborting function" << llendl;
+		return;
+	}
+
+	LLGLSUIDefault gls_ui;
+
+
+	gGL.getTexUnit(0)->bind(image, true);
+
+	gGL.color4fv(color.mV);
+
+	if (degrees == 0.f)
+	{
+		const S32 NUM_VERTICES = 4; // 9 quads
+		LLVector2 uv[NUM_VERTICES];
+		LLVector3 pos[NUM_VERTICES];
+
+		gGL.begin(LLRender::QUADS);
+		{
+			LLVector3 ui_scale = gGL.getUIScale();
+			LLVector3 ui_translation = gGL.getUITranslation();
+			ui_translation.mV[VX] += x;
+			ui_translation.mV[VY] += y;
+			ui_translation.scaleVec(ui_scale);
+			S32 index = 0;
+			S32 scaled_width = llround(width * ui_scale.mV[VX]);
+			S32 scaled_height = llround(height * ui_scale.mV[VY]);
+
+			uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+			pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
+			index++;
+
+			uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+			pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
+			index++;
+
+			uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+			pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
+			index++;
+
+			uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+			pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
+			index++;
+
+			gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+		}
+		gGL.end();
+	}
+	else
+	{
+		gGL.pushUIMatrix();
+		gGL.translateUI((F32)x, (F32)y, 0.f);
+	
+		F32 offset_x = F32(width/2);
+		F32 offset_y = F32(height/2);
+
+		gGL.translateUI(offset_x, offset_y, 0.f);
+
+		LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
+		
+		gGL.getTexUnit(0)->bind(image, true);
+
+		gGL.color4fv(color.mV);
+		
+		gGL.begin(LLRender::QUADS);
+		{
+			LLVector3 v;
+
+			v = LLVector3(offset_x, offset_y, 0.f) * quat;
+			gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
+			gGL.vertex2f(v.mV[0], v.mV[1] );
+
+			v = LLVector3(-offset_x, offset_y, 0.f) * quat;
+			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
+			gGL.vertex2f(v.mV[0], v.mV[1] );
+
+			v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
+			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+			gGL.vertex2f(v.mV[0], v.mV[1] );
+
+			v = LLVector3(offset_x, -offset_y, 0.f) * quat;
+			gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
+			gGL.vertex2f(v.mV[0], v.mV[1] );
+		}
+		gGL.end();
+		gGL.popUIMatrix();
+	}
+}
+
+
+void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
+{
+	phase = fmod(phase, 1.f);
+
+	S32 shift = S32(phase * 4.f) % 4;
+
+	// Stippled line
+	LLGLEnable stipple(GL_LINE_STIPPLE);
+	
+	gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
+
+	gGL.flush();
+	glLineWidth(2.5f);
+
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		glLineStipple(2, 0x3333 << shift);
+	}
+
+	gGL.begin(LLRender::LINES);
+	{
+		gGL.vertex3fv( start.mV );
+		gGL.vertex3fv( end.mV );
+	}
+	gGL.end();
+
+	LLRender2D::setLineWidth(1.f);
+}
+
+void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
+{
+	if (end_angle < start_angle)
+	{
+		end_angle += F_TWO_PI;
+	}
+
+	gGL.pushUIMatrix();
+	{
+		gGL.translateUI(center_x, center_y, 0.f);
+
+		// Inexact, but reasonably fast.
+		F32 delta = (end_angle - start_angle) / steps;
+		F32 sin_delta = sin( delta );
+		F32 cos_delta = cos( delta );
+		F32 x = cosf(start_angle) * radius;
+		F32 y = sinf(start_angle) * radius;
+
+		if (filled)
+		{
+			gGL.begin(LLRender::TRIANGLE_FAN);
+			gGL.vertex2f(0.f, 0.f);
+			// make sure circle is complete
+			steps += 1;
+		}
+		else
+		{
+			gGL.begin(LLRender::LINE_STRIP);
+		}
+
+		while( steps-- )
+		{
+			// Successive rotations
+			gGL.vertex2f( x, y );
+			F32 x_new = x * cos_delta - y * sin_delta;
+			y = x * sin_delta +  y * cos_delta;
+			x = x_new;
+		}
+		gGL.end();
+	}
+	gGL.popUIMatrix();
+}
+
+void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
+{
+	gGL.pushUIMatrix();
+	{
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		gGL.translateUI(center_x, center_y, 0.f);
+
+		// Inexact, but reasonably fast.
+		F32 delta = F_TWO_PI / steps;
+		F32 sin_delta = sin( delta );
+		F32 cos_delta = cos( delta );
+		F32 x = radius;
+		F32 y = 0.f;
+
+		if (filled)
+		{
+			gGL.begin(LLRender::TRIANGLE_FAN);
+			gGL.vertex2f(0.f, 0.f);
+			// make sure circle is complete
+			steps += 1;
+		}
+		else
+		{
+			gGL.begin(LLRender::LINE_LOOP);
+		}
+
+		while( steps-- )
+		{
+			// Successive rotations
+			gGL.vertex2f( x, y );
+			F32 x_new = x * cos_delta - y * sin_delta;
+			y = x * sin_delta +  y * cos_delta;
+			x = x_new;
+		}
+		gGL.end();
+	}
+	gGL.popUIMatrix();
+}
+
+// Renders a ring with sides (tube shape)
+void gl_deep_circle( F32 radius, F32 depth, S32 steps )
+{
+	F32 x = radius;
+	F32 y = 0.f;
+	F32 angle_delta = F_TWO_PI / (F32)steps;
+	gGL.begin( LLRender::TRIANGLE_STRIP  );
+	{
+		S32 step = steps + 1; // An extra step to close the circle.
+		while( step-- )
+		{
+			gGL.vertex3f( x, y, depth );
+			gGL.vertex3f( x, y, 0.f );
+
+			F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
+			y = x * sinf(angle_delta) +  y * cosf(angle_delta);
+			x = x_new;
+		}
+	}
+	gGL.end();
+}
+
+void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
+{
+	gGL.pushUIMatrix();
+	{
+		gGL.translateUI(0.f, 0.f, -width / 2);
+		if( render_center )
+		{
+			gGL.color4fv(center_color.mV);
+			gGL.diffuseColor4fv(center_color.mV);
+			gl_deep_circle( radius, width, steps );
+		}
+		else
+		{
+			gGL.diffuseColor4fv(side_color.mV);
+			gl_washer_2d(radius, radius - width, steps, side_color, side_color);
+			gGL.translateUI(0.f, 0.f, width);
+			gl_washer_2d(radius - width, radius, steps, side_color, side_color);
+		}
+	}
+	gGL.popUIMatrix();
+}
+
+// Draw gray and white checkerboard with black border
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
+{
+	if (!LLGLSLShader::sNoFixedFunction)
+	{ 
+	// Initialize the first time this is called.
+	const S32 PIXELS = 32;
+	static GLubyte checkerboard[PIXELS * PIXELS];
+	static BOOL first = TRUE;
+	if( first )
+	{
+		for( S32 i = 0; i < PIXELS; i++ )
+		{
+			for( S32 j = 0; j < PIXELS; j++ )
+			{
+				checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
+			}
+		}
+		first = FALSE;
+	}
+	
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	// ...white squares
+	gGL.color4f( 1.f, 1.f, 1.f, alpha );
+	gl_rect_2d(rect);
+
+	// ...gray squares
+	gGL.color4f( .7f, .7f, .7f, alpha );
+	gGL.flush();
+
+		glPolygonStipple( checkerboard );
+
+		LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
+		gl_rect_2d(rect);
+	}
+	else
+	{ //polygon stipple is deprecated, use "Checker" texture
+		LLPointer<LLUIImage> img = LLRender2D::getUIImage("Checker");
+		gGL.getTexUnit(0)->bind(img->getImage());
+		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+
+		LLColor4 color(1.f, 1.f, 1.f, alpha);
+		LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f);
+
+		gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(),
+			img->getImage(), color, uv_rect);
+	}
+	
+	gGL.flush();
+}
+
+
+// Draws the area between two concentric circles, like
+// a doughnut or washer.
+void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
+{
+	const F32 DELTA = F_TWO_PI / steps;
+	const F32 SIN_DELTA = sin( DELTA );
+	const F32 COS_DELTA = cos( DELTA );
+
+	F32 x1 = outer_radius;
+	F32 y1 = 0.f;
+	F32 x2 = inner_radius;
+	F32 y2 = 0.f;
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	gGL.begin( LLRender::TRIANGLE_STRIP  );
+	{
+		steps += 1; // An extra step to close the circle.
+		while( steps-- )
+		{
+			gGL.color4fv(outer_color.mV);
+			gGL.vertex2f( x1, y1 );
+			gGL.color4fv(inner_color.mV);
+			gGL.vertex2f( x2, y2 );
+
+			F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
+			y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
+			x1 = x1_new;
+
+			F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
+			y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
+			x2 = x2_new;
+		}
+	}
+	gGL.end();
+}
+
+// Draws the area between two concentric circles, like
+// a doughnut or washer.
+void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
+{
+	const F32 DELTA = (end_radians - start_radians) / steps;
+	const F32 SIN_DELTA = sin( DELTA );
+	const F32 COS_DELTA = cos( DELTA );
+
+	F32 x1 = outer_radius * cos( start_radians );
+	F32 y1 = outer_radius * sin( start_radians );
+	F32 x2 = inner_radius * cos( start_radians );
+	F32 y2 = inner_radius * sin( start_radians );
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	gGL.begin( LLRender::TRIANGLE_STRIP  );
+	{
+		steps += 1; // An extra step to close the circle.
+		while( steps-- )
+		{
+			gGL.color4fv(outer_color.mV);
+			gGL.vertex2f( x1, y1 );
+			gGL.color4fv(inner_color.mV);
+			gGL.vertex2f( x2, y2 );
+
+			F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
+			y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
+			x1 = x1_new;
+
+			F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
+			y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
+			x2 = x2_new;
+		}
+	}
+	gGL.end();
+}
+
+void gl_rect_2d_simple_tex( S32 width, S32 height )
+{
+	gGL.begin( LLRender::QUADS );
+
+		gGL.texCoord2f(1.f, 1.f);
+		gGL.vertex2i(width, height);
+
+		gGL.texCoord2f(0.f, 1.f);
+		gGL.vertex2i(0, height);
+
+		gGL.texCoord2f(0.f, 0.f);
+		gGL.vertex2i(0, 0);
+
+		gGL.texCoord2f(1.f, 0.f);
+		gGL.vertex2i(width, 0);
+	
+	gGL.end();
+}
+
+void gl_rect_2d_simple( S32 width, S32 height )
+{
+	gGL.begin( LLRender::QUADS );
+		gGL.vertex2i(width, height);
+		gGL.vertex2i(0, height);
+		gGL.vertex2i(0, 0);
+		gGL.vertex2i(width, 0);
+	gGL.end();
+}
+
+void gl_segmented_rect_2d_tex(const S32 left, 
+							  const S32 top, 
+							  const S32 right, 
+							  const S32 bottom, 
+							  const S32 texture_width, 
+							  const S32 texture_height, 
+							  const S32 border_size, 
+							  const U32 edges)
+{
+	S32 width = llabs(right - left);
+	S32 height = llabs(top - bottom);
+
+	gGL.pushUIMatrix();
+
+	gGL.translateUI((F32)left, (F32)bottom, 0.f);
+	LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
+
+	if (border_uv_scale.mV[VX] > 0.5f)
+	{
+		border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
+	}
+	if (border_uv_scale.mV[VY] > 0.5f)
+	{
+		border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
+	}
+
+	F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
+	LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+	LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+	LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+	LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+	LLVector2 width_vec((F32)width, 0.f);
+	LLVector2 height_vec(0.f, (F32)height);
+
+	gGL.begin(LLRender::QUADS);
+	{
+		// draw bottom left
+		gGL.texCoord2f(0.f, 0.f);
+		gGL.vertex2f(0.f, 0.f);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+		gGL.vertex2fv(border_width_left.mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+		gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
+		gGL.vertex2fv(border_height_bottom.mV);
+
+		// draw bottom middle
+		gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+		gGL.vertex2fv(border_width_left.mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+		gGL.vertex2fv((width_vec - border_width_right).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+		// draw bottom right
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+		gGL.vertex2fv((width_vec - border_width_right).mV);
+
+		gGL.texCoord2f(1.f, 0.f);
+		gGL.vertex2fv(width_vec.mV);
+
+		gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec + border_height_bottom).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+		// draw left 
+		gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
+		gGL.vertex2fv(border_height_bottom.mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((height_vec - border_height_top).mV);
+
+		// draw middle
+		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+		// draw right 
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+		gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec + border_height_bottom).mV);
+
+		gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+		// draw top left
+		gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+		gGL.vertex2fv((border_width_left + height_vec).mV);
+
+		gGL.texCoord2f(0.f, 1.f);
+		gGL.vertex2fv((height_vec).mV);
+
+		// draw top middle
+		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+		gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
+
+		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+		gGL.vertex2fv((border_width_left + height_vec).mV);
+
+		// draw top right
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
+		gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
+
+		gGL.texCoord2f(1.f, 1.f);
+		gGL.vertex2fv((width_vec + height_vec).mV);
+
+		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+		gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
+	}
+	gGL.end();
+
+	gGL.popUIMatrix();
+}
+
+//FIXME: rewrite to use scissor?
+void gl_segmented_rect_2d_fragment_tex(const S32 left, 
+									   const S32 top, 
+									   const S32 right, 
+									   const S32 bottom, 
+									   const S32 texture_width, 
+									   const S32 texture_height, 
+									   const S32 border_size, 
+									   const F32 start_fragment, 
+									   const F32 end_fragment, 
+									   const U32 edges)
+{
+	S32 width = llabs(right - left);
+	S32 height = llabs(top - bottom);
+
+	gGL.pushUIMatrix();
+
+	gGL.translateUI((F32)left, (F32)bottom, 0.f);
+	LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
+
+	if (border_uv_scale.mV[VX] > 0.5f)
+	{
+		border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
+	}
+	if (border_uv_scale.mV[VY] > 0.5f)
+	{
+		border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
+	}
+
+	F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
+	LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+	LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+	LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+	LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+	LLVector2 width_vec((F32)width, 0.f);
+	LLVector2 height_vec(0.f, (F32)height);
+
+	F32 middle_start = border_scale / (F32)width;
+	F32 middle_end = 1.f - middle_start;
+
+	F32 u_min;
+	F32 u_max;
+	LLVector2 x_min;
+	LLVector2 x_max;
+
+	gGL.begin(LLRender::QUADS);
+	{
+		if (start_fragment < middle_start)
+		{
+			u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
+			u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
+			x_min = (start_fragment / middle_start) * border_width_left;
+			x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
+
+			// draw bottom left
+			gGL.texCoord2f(u_min, 0.f);
+			gGL.vertex2fv(x_min.mV);
+
+			gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+			gGL.vertex2fv(x_max.mV);
+
+			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+			// draw left 
+			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+			
+			// draw top left
+			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(u_max, 1.f);
+			gGL.vertex2fv((x_max + height_vec).mV);
+
+			gGL.texCoord2f(u_min, 1.f);
+			gGL.vertex2fv((x_min + height_vec).mV);
+		}
+
+		if (end_fragment > middle_start || start_fragment < middle_end)
+		{
+			x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
+			x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
+
+			// draw bottom middle
+			gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+			gGL.vertex2fv(x_min.mV);
+
+			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+			gGL.vertex2fv((x_max).mV);
+
+			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+			gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+			// draw middle
+			gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+			// draw top middle
+			gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+			gGL.vertex2fv((x_max + height_vec).mV);
+
+			gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+			gGL.vertex2fv((x_min + height_vec).mV);
+		}
+
+		if (end_fragment > middle_end)
+		{
+			u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX];
+			u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX];
+			x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right);
+			x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
+
+			// draw bottom right
+			gGL.texCoord2f(u_min, 0.f);
+			gGL.vertex2fv((x_min).mV);
+
+			gGL.texCoord2f(u_max, 0.f);
+			gGL.vertex2fv(x_max.mV);
+
+			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+			// draw right 
+			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+			// draw top right
+			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+			gGL.texCoord2f(u_max, 1.f);
+			gGL.vertex2fv((x_max + height_vec).mV);
+
+			gGL.texCoord2f(u_min, 1.f);
+			gGL.vertex2fv((x_min + height_vec).mV);
+		}
+	}
+	gGL.end();
+
+	gGL.popUIMatrix();
+}
+
+void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, 
+							 const LLVector3& width_vec, const LLVector3& height_vec)
+{
+	gGL.begin(LLRender::QUADS);
+	{
+		// draw bottom left
+		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);
+		gGL.vertex3f(0.f, 0.f, 0.f);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
+
+		// draw bottom middle
+		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		// draw bottom right
+		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);
+		gGL.vertex3fv(width_vec.mV);
+
+		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
+		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		// draw left 
+		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
+
+		// draw middle
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		// draw right 
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
+		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
+		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		// draw top left
+		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);
+		gGL.vertex3fv((height_vec).mV);
+
+		// draw top middle
+		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
+
+		// draw top right
+		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
+		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
+
+		gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);
+		gGL.vertex3fv((width_vec + height_vec).mV);
+
+		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
+		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
+	}
+	gGL.end();
+
+}
+
+// static
+void LLRender2D::initClass(LLImageProviderInterface* image_provider,
+						   const LLVector2* scale_factor)
+{
+	sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
+	sImageProvider = image_provider;
+}
+
+// static
+void LLRender2D::cleanupClass()
+{
+	if(sImageProvider)
+	{
+		sImageProvider->cleanUp();
+	}
+}
+
+
+//static
+void LLRender2D::translate(F32 x, F32 y, F32 z)
+{
+	gGL.translateUI(x,y,z);
+	LLFontGL::sCurOrigin.mX += (S32) x;
+	LLFontGL::sCurOrigin.mY += (S32) y;
+	LLFontGL::sCurDepth += z;
+}
+
+//static
+void LLRender2D::pushMatrix()
+{
+	gGL.pushUIMatrix();
+	LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
+}
+
+//static
+void LLRender2D::popMatrix()
+{
+	gGL.popUIMatrix();
+	LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first;
+	LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;
+	LLFontGL::sOriginStack.pop_back();
+}
+
+//static 
+void LLRender2D::loadIdentity()
+{
+	gGL.loadUIIdentity(); 
+	LLFontGL::sCurOrigin.mX = 0;
+	LLFontGL::sCurOrigin.mY = 0;
+	LLFontGL::sCurDepth = 0.f;
+}
+
+//static
+void LLRender2D::setScaleFactor(const LLVector2 &scale_factor)
+{
+	sGLScaleFactor = scale_factor;
+}
+
+//static
+void LLRender2D::setLineWidth(F32 width)
+{
+	gGL.flush();
+	glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f));
+}
+
+//static
+LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
+{
+	if (sImageProvider)
+	{
+		return sImageProvider->getUIImageByID(image_id, priority);
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
+//static 
+LLPointer<LLUIImage> LLRender2D::getUIImage(const std::string& name, S32 priority)
+{
+	if (!name.empty() && sImageProvider)
+		return sImageProvider->getUIImage(name, priority);
+	else
+		return NULL;
+}
+
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
new file mode 100644
index 0000000000..4884422c58
--- /dev/null
+++ b/indra/llrender/llrender2dutils.h
@@ -0,0 +1,163 @@
+/** 
+ * @file llrender2dutils.h
+ * @brief GL function declarations for immediate-mode gl drawing.
+ *
+ * $LicenseInfo:firstyear=2012&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$
+ */
+
+// All immediate-mode gl drawing should happen here.
+
+
+#ifndef LL_RENDER2DUTILS_H
+#define LL_RENDER2DUTILS_H
+
+#include "llpointer.h"		// LLPointer<>
+#include "llrect.h"
+#include "llglslshader.h"
+
+class LLColor4; 
+class LLVector3;
+class LLVector2;
+class LLUIImage;
+class LLUUID;
+
+extern const LLColor4 UI_VERTEX_COLOR;
+
+BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom);
+void gl_state_for_2d(S32 width, S32 height);
+
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2);
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color );
+void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled);
+void gl_rect_2d_simple( S32 width, S32 height );
+
+void gl_draw_x(const LLRect& rect, const LLColor4& color);
+
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE );
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE );
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE );
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE );
+void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE );
+void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE );
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
+
+void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
+
+void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled);
+void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle);
+void gl_deep_circle( F32 radius, F32 depth );
+void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center );
+void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
+void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
+void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
+
+void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+
+void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); 
+
+void gl_rect_2d_simple_tex( S32 width, S32 height );
+
+// segmented rectangles
+
+/*
+   TL |______TOP_________| TR 
+     /|                  |\  
+   _/_|__________________|_\_
+   L| |    MIDDLE        | |R
+   _|_|__________________|_|_
+    \ |    BOTTOM        | /  
+   BL\|__________________|/ BR
+      |                  |    
+*/
+
+typedef enum e_rounded_edge
+{
+	ROUNDED_RECT_LEFT	= 0x1, 
+	ROUNDED_RECT_TOP	= 0x2, 
+	ROUNDED_RECT_RIGHT	= 0x4, 
+	ROUNDED_RECT_BOTTOM	= 0x8,
+	ROUNDED_RECT_ALL	= 0xf
+}ERoundedEdge;
+
+
+void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
+void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
+void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);
+
+inline void gl_rect_2d( const LLRect& rect, BOOL filled )
+{
+	gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
+}
+
+inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled)
+{
+	gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
+}
+
+class LLImageProviderInterface;
+
+class LLRender2D
+{
+	LOG_CLASS(LLRender2D);
+public:
+	static void initClass(LLImageProviderInterface* image_provider,
+						  const LLVector2* scale_factor);
+	static void cleanupClass();
+
+	static void pushMatrix();
+	static void popMatrix();
+	static void loadIdentity();
+	static void translate(F32 x, F32 y, F32 z = 0.0f);
+
+	static void setLineWidth(F32 width);
+	static void setScaleFactor(const LLVector2& scale_factor);
+
+	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
+	static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
+
+	static LLVector2		sGLScaleFactor;
+private:
+	static LLImageProviderInterface* sImageProvider;
+};
+
+class LLImageProviderInterface
+{
+protected:
+	LLImageProviderInterface() {};
+	virtual ~LLImageProviderInterface() {};
+public:
+	virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
+	virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
+	virtual void cleanUp() = 0;
+};
+
+
+extern LLGLSLShader gSolidColorProgram;
+extern LLGLSLShader gUIProgram;
+
+#endif // LL_RENDER2DUTILS_H
+
diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp
new file mode 100644
index 0000000000..b954b66350
--- /dev/null
+++ b/indra/llrender/lluiimage.cpp
@@ -0,0 +1,243 @@
+/** 
+ * @file lluiimage.cpp
+ * @brief UI implementation
+ *
+ * $LicenseInfo:firstyear=2007&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$
+ */
+
+// Utilities functions the user interface needs
+
+//#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+// Project includes
+#include "lluiimage.h"
+#include "llrender2dutils.h"
+
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+:	mName(name),
+	mImage(image),
+	mScaleRegion(0.f, 1.f, 1.f, 0.f),
+	mClipRegion(0.f, 1.f, 1.f, 0.f),
+	mUniformScaling(TRUE),
+	mNoClip(TRUE),
+	mImageLoaded(NULL)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+	delete mImageLoaded;
+}
+
+void LLUIImage::setClipRegion(const LLRectf& region) 
+{ 
+	mClipRegion = region; 
+	mNoClip = mClipRegion.mLeft == 0.f
+				&& mClipRegion.mRight == 1.f
+				&& mClipRegion.mBottom == 0.f
+				&& mClipRegion.mTop == 1.f;
+}
+
+void LLUIImage::setScaleRegion(const LLRectf& region) 
+{ 
+	mScaleRegion = region; 
+	mUniformScaling = mScaleRegion.mLeft == 0.f
+					&& mScaleRegion.mRight == 1.f
+					&& mScaleRegion.mBottom == 0.f
+					&& mScaleRegion.mTop == 1.f;
+}
+
+//TODO: move drawing implementation inside class
+void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
+{
+	gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion);
+}
+
+void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
+{
+	if (mUniformScaling)
+	{
+		gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion);
+	}
+	else
+	{
+		gl_draw_scaled_image_with_border(
+			x, y, 
+			width, height, 
+			mImage, 
+			color,
+			FALSE,
+			mClipRegion,
+			mScaleRegion);
+	}
+}
+
+void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
+{
+	gl_draw_scaled_image_with_border(
+		x, y, 
+		width, height, 
+		mImage, 
+		color, 
+		TRUE,
+		mClipRegion,
+		mScaleRegion);
+}
+
+void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
+{
+	LLRect border_rect;
+	border_rect.setOriginAndSize(x, y, width, height);
+	border_rect.stretch(border_width, border_width);
+	drawSolid(border_rect, color);
+}
+
+void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, 
+						const LLRect& rect, const LLColor4& color)
+{
+	F32 border_scale = 1.f;
+	F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
+	F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
+	if (rect.getHeight() < border_height || rect.getWidth() < border_width)
+	{
+		 if(border_height - rect.getHeight() > border_width - rect.getWidth())
+		 {
+			 border_scale = (F32)rect.getHeight() / border_height;
+		 }
+		 else
+		 {
+			border_scale = (F32)rect.getWidth() / border_width;
+		 }
+	}
+
+	LLRender2D::pushMatrix();
+	{ 
+		LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); 
+		LLRender2D::translate(rect_origin.mV[VX],
+						rect_origin.mV[VY], 
+						rect_origin.mV[VZ]);
+		gGL.getTexUnit(0)->bind(getImage());
+		gGL.color4fv(color.mV);
+
+		LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
+							mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
+							mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
+							mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
+		gl_segmented_rect_3d_tex(mClipRegion,
+								center_uv_rect,
+								LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
+										(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
+										(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
+										(border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
+								rect.getWidth() * x_axis, 
+								rect.getHeight() * y_axis);
+		
+	} LLRender2D::popMatrix();
+}
+
+
+S32 LLUIImage::getWidth() const
+{ 
+	// return clipped dimensions of actual image area
+	return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); 
+}
+
+S32 LLUIImage::getHeight() const
+{ 
+	// return clipped dimensions of actual image area
+	return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); 
+}
+
+S32 LLUIImage::getTextureWidth() const
+{
+	return mImage->getWidth(0);
+}
+
+S32 LLUIImage::getTextureHeight() const
+{
+	return mImage->getHeight(0);
+}
+
+boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb ) 
+{
+	if (!mImageLoaded) 
+	{
+		mImageLoaded = new image_loaded_signal_t();
+	}
+	return mImageLoaded->connect(cb);
+}
+
+
+void LLUIImage::onImageLoaded()
+{
+	if (mImageLoaded)
+	{
+		(*mImageLoaded)();
+	}
+}
+
+
+namespace LLInitParam
+{
+	void ParamValue<LLUIImage*>::updateValueFromBlock()
+	{
+		// The keyword "none" is specifically requesting a null image
+		// do not default to current value. Used to overwrite template images. 
+		if (name() == "none")
+		{
+			updateValue(NULL);
+			return;
+		}
+
+		LLUIImage* imagep =  LLRender2D::getUIImage(name());
+		if (imagep)
+		{
+			updateValue(imagep);
+		}
+	}
+	
+	void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)
+	{
+		if (getValue() == NULL)
+		{
+			name.set("none", make_block_authoritative);
+		}
+		else
+		{
+			name.set(getValue()->getName(), make_block_authoritative);
+		}
+	}
+
+	
+	bool ParamCompare<LLUIImage*, false>::equals(
+		LLUIImage* const &a,
+		LLUIImage* const &b)
+	{
+		// force all LLUIImages for XML UI export to be "non-default"
+		if (!a && !b)
+			return false;
+		else
+			return (a == b);
+	}
+}
+
diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h
new file mode 100644
index 0000000000..7817ba1c7b
--- /dev/null
+++ b/indra/llrender/lluiimage.h
@@ -0,0 +1,126 @@
+/** 
+ * @file lluiimage.h
+ * @brief wrapper for images used in the UI that handles smart scaling, etc.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUIIMAGE_H
+#define LL_LLUIIMAGE_H
+
+#include "v4color.h"
+#include "llpointer.h"
+#include "llrefcount.h"
+#include "llrefcount.h"
+#include "llrect.h"
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+#include "llinitparam.h"
+#include "lltexture.h"
+
+extern const LLColor4 UI_VERTEX_COLOR;
+
+class LLUIImage : public LLRefCount
+{
+public:
+	typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
+
+	LLUIImage(const std::string& name, LLPointer<LLTexture> image);
+	virtual ~LLUIImage();
+
+	void setClipRegion(const LLRectf& region);
+	void setScaleRegion(const LLRectf& region);
+
+	LLPointer<LLTexture> getImage() { return mImage; }
+	const LLPointer<LLTexture>& getImage() const { return mImage; }
+
+	void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
+	void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
+	void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+	
+	void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
+	void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+	void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
+
+	void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
+	void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
+	void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
+
+	void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
+
+	const std::string& getName() const { return mName; }
+
+	virtual S32 getWidth() const;
+	virtual S32 getHeight() const;
+
+	// returns dimensions of underlying textures, which might not be equal to ui image portion
+	S32 getTextureWidth() const;
+	S32 getTextureHeight() const;
+
+	boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
+
+	void onImageLoaded();
+
+protected:
+	image_loaded_signal_t* mImageLoaded;
+
+	std::string			mName;
+	LLRectf				mScaleRegion;
+	LLRectf				mClipRegion;
+	LLPointer<LLTexture> mImage;
+	BOOL				mUniformScaling;
+	BOOL				mNoClip;
+};
+
+namespace LLInitParam
+{
+	template<>
+	class ParamValue<LLUIImage*> 
+	:	public CustomParamValue<LLUIImage*>
+	{
+		typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type	T_const_ref;
+		typedef CustomParamValue<LLUIImage*> super_t;
+	public:
+		Optional<std::string> name;
+
+		ParamValue(LLUIImage* const& image = NULL)
+		:	super_t(image)
+		{
+			updateBlockFromValue(false);
+			addSynonym(name, "name");
+		}
+
+		void updateValueFromBlock();
+		void updateBlockFromValue(bool make_block_authoritative);
+	};
+
+	// Need custom comparison function for our test app, which only loads
+	// LLUIImage* as NULL.
+	template<>
+	struct ParamCompare<LLUIImage*, false>
+	{
+		static bool equals(LLUIImage* const &a, LLUIImage* const &b);
+	};
+}
+
+typedef LLPointer<LLUIImage> LLUIImagePtr;
+#endif
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 01c42e07a2..34a08603fa 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -117,7 +117,6 @@ set(llui_SOURCE_FILES
     lluicolortable.cpp
     lluictrl.cpp
     lluictrlfactory.cpp
-	lluiimage.cpp
     lluistring.cpp
     llundo.cpp
     llurlaction.cpp
@@ -231,7 +230,6 @@ set(llui_HEADER_FILES
     lluifwd.h
     llui.h
     lluicolor.h
-	lluiimage.h
     lluistring.h
     llundo.h
     llurlaction.h
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 41e5d74042..d4e14d9419 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -551,7 +551,7 @@ void LLComboBox::showList()
 	LLCoordWindow window_size;
 	getWindow()->getSize(&window_size);
 	//HACK: shouldn't have to know about scale here
-	mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
+	mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 );
 
 	// Make sure that we can see the whole list
 	LLRect root_view_local;
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 2e64be89fa..f8b84e39b5 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2015,8 +2015,8 @@ void LLLineEditor::draw()
 				LLRect screen_pos = calcScreenRect();
 				LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad );
 
-				ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
-				ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
+				ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]);
+				ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]);
 				getWindow()->setLanguageTextInput( ime_pos );
 			}
 		}
@@ -2563,7 +2563,7 @@ void LLLineEditor::markAsPreedit(S32 position, S32 length)
 
 S32 LLLineEditor::getPreeditFontSize() const
 {
-	return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
+	return llround(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
 }
 
 void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace)
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
index 31ceb0766a..0620e0f52d 100644
--- a/indra/llui/lllocalcliprect.cpp
+++ b/indra/llui/lllocalcliprect.cpp
@@ -88,10 +88,10 @@ void LLScreenClipRect::updateScissorRegion()
 	LLRect rect = sClipRectStack.top();
 	stop_glerror();
 	S32 x,y,w,h;
-	x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
-	y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
-	w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
-	h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
+	x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]);
+	y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]);
+	w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1;
+	h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1;
 	glScissor( x,y,w,h );
 	stop_glerror();
 }
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 7cee9f5b46..e22b806a74 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -521,8 +521,8 @@ void LLTextBase::drawCursor()
 			LLRect screen_pos = calcScreenRect();
 			LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) );
 
-			ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
-			ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
+			ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]);
+			ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]);
 			getWindow()->setLanguageTextInput( ime_pos );
 		}
 	}
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index d5e08fa29b..3dc1b99edb 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2911,7 +2911,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)
 
 S32 LLTextEditor::getPreeditFontSize() const
 {
-	return llround((F32)mFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
+	return llround((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
 }
 
 BOOL LLTextEditor::isDirty() const
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 2a774d54a3..0ddb149738 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -39,6 +39,7 @@
 #include "llrect.h"
 #include "lldir.h"
 #include "llgl.h"
+#include "llsd.h"
 
 // Project includes
 #include "llcommandmanager.h"
@@ -69,16 +70,13 @@
 //
 // Globals
 //
-const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
 
 // Language for UI construction
 std::map<std::string, std::string> gTranslation;
 std::list<std::string> gUntranslated;
 /*static*/ LLUI::settings_map_t LLUI::sSettingGroups;
-/*static*/ LLImageProviderInterface* LLUI::sImageProvider = NULL;
 /*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL;
 /*static*/ LLUIAudioCallback LLUI::sDeferredAudioCallback = NULL;
-/*static*/ LLVector2		LLUI::sGLScaleFactor(1.f, 1.f);
 /*static*/ LLWindow*		LLUI::sWindow = NULL;
 /*static*/ LLView*			LLUI::sRootView = NULL;
 /*static*/ BOOL                         LLUI::sDirty = FALSE;
@@ -158,1474 +156,6 @@ void make_ui_sound_deferred(const char* namep)
 	}
 }
 
-BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
-{
-	if (x < left || right < x) return FALSE;
-	if (y < bottom || top < y) return FALSE;
-	return TRUE;
-}
-
-
-// Puts GL into 2D drawing mode by turning off lighting, setting to an
-// orthographic projection, etc.
-void gl_state_for_2d(S32 width, S32 height)
-{
-	stop_glerror();
-	F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
-	F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.loadIdentity();
-	gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.loadIdentity();
-	stop_glerror();
-}
-
-
-void gl_draw_x(const LLRect& rect, const LLColor4& color)
-{
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	gGL.color4fv( color.mV );
-
-	gGL.begin( LLRender::LINES );
-		gGL.vertex2i( rect.mLeft,		rect.mTop );
-		gGL.vertex2i( rect.mRight,	rect.mBottom );
-		gGL.vertex2i( rect.mLeft,		rect.mBottom );
-		gGL.vertex2i( rect.mRight,	rect.mTop );
-	gGL.end();
-}
-
-
-void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled)
-{
-	gGL.color4fv(color.mV);
-	gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
-}
-
-void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
-{
-	gGL.pushUIMatrix();
-	left += LLFontGL::sCurOrigin.mX;
-	right += LLFontGL::sCurOrigin.mX;
-	bottom += LLFontGL::sCurOrigin.mY;
-	top += LLFontGL::sCurOrigin.mY;
-
-	gGL.loadUIIdentity();
-	gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset,
-				llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset,
-				llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset,
-				llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset,
-				filled);
-	gGL.popUIMatrix();
-}
-
-
-void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
-{
-	stop_glerror();
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	// Counterclockwise quad will face the viewer
-	if( filled )
-	{ 
-		gGL.begin( LLRender::QUADS );
-			gGL.vertex2i(left, top);
-			gGL.vertex2i(left, bottom);
-			gGL.vertex2i(right, bottom);
-			gGL.vertex2i(right, top);
-		gGL.end();
-	}
-	else
-	{
-		if( gGLManager.mATIOffsetVerticalLines )
-		{
-			// Work around bug in ATI driver: vertical lines are offset by (-1,-1)
-			gGL.begin( LLRender::LINES );
-
-				// Verticals 
-				gGL.vertex2i(left + 1, top);
-				gGL.vertex2i(left + 1, bottom);
-
-				gGL.vertex2i(right, bottom);
-				gGL.vertex2i(right, top);
-
-				// Horizontals
-				top--;
-				right--;
-				gGL.vertex2i(left, bottom);
-				gGL.vertex2i(right, bottom);
-
-				gGL.vertex2i(left, top);
-				gGL.vertex2i(right, top);
-			gGL.end();
-		}
-		else
-		{
-			top--;
-			right--;
-			gGL.begin( LLRender::LINE_STRIP );
-				gGL.vertex2i(left, top);
-				gGL.vertex2i(left, bottom);
-				gGL.vertex2i(right, bottom);
-				gGL.vertex2i(right, top);
-				gGL.vertex2i(left, top);
-			gGL.end();
-		}
-	}
-	stop_glerror();
-}
-
-void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
-{
-	gGL.color4fv( color.mV );
-	gl_rect_2d( left, top, right, bottom, filled );
-}
-
-
-void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
-{
-	gGL.color4fv( color.mV );
-	gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
-}
-
-// Given a rectangle on the screen, draws a drop shadow _outside_
-// the right and bottom edges of it.  Along the right it has width "lines"
-// and along the bottom it has height "lines".
-void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines)
-{
-	stop_glerror();
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	
-	// HACK: Overlap with the rectangle by a single pixel.
-	right--;
-	bottom++;
-	lines++;
-
-	LLColor4 end_color = start_color;
-	end_color.mV[VALPHA] = 0.f;
-
-	gGL.begin(LLRender::QUADS);
-
-	// Right edge, CCW faces screen
-	gGL.color4fv(start_color.mV);
-	gGL.vertex2i(right,		top-lines);
-	gGL.vertex2i(right,		bottom);
-	gGL.color4fv(end_color.mV);
-	gGL.vertex2i(right+lines, bottom);
-	gGL.vertex2i(right+lines, top-lines);
-
-	// Bottom edge, CCW faces screen
-	gGL.color4fv(start_color.mV);
-	gGL.vertex2i(right,		bottom);
-	gGL.vertex2i(left+lines,	bottom);
-	gGL.color4fv(end_color.mV);
-	gGL.vertex2i(left+lines,	bottom-lines);
-	gGL.vertex2i(right,		bottom-lines);
-
-	// bottom left Corner
-	gGL.color4fv(start_color.mV);
-	gGL.vertex2i(left+lines,	bottom);
-	gGL.color4fv(end_color.mV);
-	gGL.vertex2i(left,		bottom);
-	// make the bottom left corner not sharp
-	gGL.vertex2i(left+1,		bottom-lines+1);
-	gGL.vertex2i(left+lines,	bottom-lines);
-
-	// bottom right corner
-	gGL.color4fv(start_color.mV);
-	gGL.vertex2i(right,		bottom);
-	gGL.color4fv(end_color.mV);
-	gGL.vertex2i(right,		bottom-lines);
-	// make the rightmost corner not sharp
-	gGL.vertex2i(right+lines-1,	bottom-lines+1);
-	gGL.vertex2i(right+lines,	bottom);
-
-	// top right corner
-	gGL.color4fv(start_color.mV);
-	gGL.vertex2i( right,			top-lines );
-	gGL.color4fv(end_color.mV);
-	gGL.vertex2i( right+lines,	top-lines );
-	// make the corner not sharp
-	gGL.vertex2i( right+lines-1,	top-1 );
-	gGL.vertex2i( right,			top );
-
-	gGL.end();
-	stop_glerror();
-}
-
-void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 )
-{
-	// Work around bug in ATI driver: vertical lines are offset by (-1,-1)
-	if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
-	{
-		x1++;
-		x2++;
-		y1++;
-		y2++;
-	}
-
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	
-	gGL.begin(LLRender::LINES);
-		gGL.vertex2i(x1, y1);
-		gGL.vertex2i(x2, y2);
-	gGL.end();
-}
-
-void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color )
-{
-	// Work around bug in ATI driver: vertical lines are offset by (-1,-1)
-	if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
-	{
-		x1++;
-		x2++;
-		y1++;
-		y2++;
-	}
-
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	gGL.color4fv( color.mV );
-
-	gGL.begin(LLRender::LINES);
-		gGL.vertex2i(x1, y1);
-		gGL.vertex2i(x2, y2);
-	gGL.end();
-}
-
-void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled)
-{
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	gGL.color4fv(color.mV);
-
-	if (filled)
-	{
-		gGL.begin(LLRender::TRIANGLES);
-	}
-	else
-	{
-		gGL.begin(LLRender::LINE_LOOP);
-	}
-	gGL.vertex2i(x1, y1);
-	gGL.vertex2i(x2, y2);
-	gGL.vertex2i(x3, y3);
-	gGL.end();
-}
-
-void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac)
-{
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	length = llmin((S32)(max_frac*(right - left)), length);
-	length = llmin((S32)(max_frac*(top - bottom)), length);
-	gGL.begin(LLRender::LINES);
-	gGL.vertex2i(left, top);
-	gGL.vertex2i(left + length, top);
-	
-	gGL.vertex2i(left, top);
-	gGL.vertex2i(left, top - length);
-
-	gGL.vertex2i(left, bottom);
-	gGL.vertex2i(left + length, bottom);
-	
-	gGL.vertex2i(left, bottom);
-	gGL.vertex2i(left, bottom + length);
-
-	gGL.vertex2i(right, top);
-	gGL.vertex2i(right - length, top);
-
-	gGL.vertex2i(right, top);
-	gGL.vertex2i(right, top - length);
-
-	gGL.vertex2i(right, bottom);
-	gGL.vertex2i(right - length, bottom);
-
-	gGL.vertex2i(right, bottom);
-	gGL.vertex2i(right, bottom + length);
-	gGL.end();
-}
-
-
-void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect )
-{
-	if (NULL == image)
-	{
-		llwarns << "image == NULL; aborting function" << llendl;
-		return;
-	}
-	gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
-}
-
-void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
-{
-	if (NULL == image)
-	{
-		llwarns << "image == NULL; aborting function" << llendl;
-		return;
-	}
-	gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
-}
-
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
-{
-	if (NULL == image)
-	{
-		llwarns << "image == NULL; aborting function" << llendl;
-		return;
-	}
-
-	// scale screen size of borders down
-	F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
-	F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
-
-	LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
-	gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
-}
-
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect)
-{
-	stop_glerror();
-
-	if (NULL == image)
-	{
-		llwarns << "image == NULL; aborting function" << llendl;
-		return;
-	}
-
-	// add in offset of current image to current UI translation
-	const LLVector3 ui_scale = gGL.getUIScale();
-	const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
-
-	F32 uv_width = uv_outer_rect.getWidth();
-	F32 uv_height = uv_outer_rect.getHeight();
-
-	// shrink scaling region to be proportional to clipped image region
-	LLRectf uv_center_rect(
-		uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
-		uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
-		uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
-		uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
-
-	F32 image_width = image->getWidth(0);
-	F32 image_height = image->getHeight(0);
-
-	S32 image_natural_width = llround(image_width * uv_width);
-	S32 image_natural_height = llround(image_height * uv_height);
-
-	LLRectf draw_center_rect(	uv_center_rect.mLeft * image_width,
-								uv_center_rect.mTop * image_height,
-								uv_center_rect.mRight * image_width,
-								uv_center_rect.mBottom * image_height);
-
-	{	// scale fixed region of image to drawn region
-		draw_center_rect.mRight += width - image_natural_width;
-		draw_center_rect.mTop += height - image_natural_height;
-
-		F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
-		F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
-
-		F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
-		F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
-
-		F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
-
-		draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]);
-		draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]);
-		draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]);
-		draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]);
-	}
-
-	LLRectf draw_outer_rect(ui_translation.mV[VX], 
-							ui_translation.mV[VY] + height * ui_scale.mV[VY], 
-							ui_translation.mV[VX] + width * ui_scale.mV[VX], 
-							ui_translation.mV[VY]);
-
-	LLGLSUIDefault gls_ui;
-	
-	if (solid_color)
-	{
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gSolidColorProgram.bind();
-		}
-		else
-		{
-			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
-			gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
-		}
-	}
-
-	gGL.getTexUnit(0)->bind(image, true);
-
-	gGL.color4fv(color.mV);
-	
-	const S32 NUM_VERTICES = 9 * 4; // 9 quads
-	LLVector2 uv[NUM_VERTICES];
-	LLVector3 pos[NUM_VERTICES];
-
-	S32 index = 0;
-
-	gGL.begin(LLRender::QUADS);
-	{
-		// draw bottom left
-		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
-		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		// draw bottom middle
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		// draw bottom right
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
-		pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		// draw left 
-		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
-		index++;
-
-		// draw middle
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
-		index++;
-
-		// draw right 
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
-		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
-		index++;
-
-		// draw top left
-		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
-		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
-		index++;
-
-		// draw top middle
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
-		index++;
-
-		// draw top right
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
-		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
-		pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
-		index++;
-
-		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
-		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
-		index++;
-
-		gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
-	}
-	gGL.end();
-
-	if (solid_color)
-	{
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gUIProgram.bind();
-		}
-		else
-		{
-			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-		}
-	}
-}
-
-void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
-{
-	gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
-}
-
-void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
-{
-	if (NULL == image)
-	{
-		llwarns << "image == NULL; aborting function" << llendl;
-		return;
-	}
-
-	LLGLSUIDefault gls_ui;
-
-
-	gGL.getTexUnit(0)->bind(image, true);
-
-	gGL.color4fv(color.mV);
-
-	if (degrees == 0.f)
-	{
-		const S32 NUM_VERTICES = 4; // 9 quads
-		LLVector2 uv[NUM_VERTICES];
-		LLVector3 pos[NUM_VERTICES];
-
-		gGL.begin(LLRender::QUADS);
-		{
-			LLVector3 ui_scale = gGL.getUIScale();
-			LLVector3 ui_translation = gGL.getUITranslation();
-			ui_translation.mV[VX] += x;
-			ui_translation.mV[VY] += y;
-			ui_translation.scaleVec(ui_scale);
-			S32 index = 0;
-			S32 scaled_width = llround(width * ui_scale.mV[VX]);
-			S32 scaled_height = llround(height * ui_scale.mV[VY]);
-
-			uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
-			pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
-			index++;
-
-			uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
-			pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
-			index++;
-
-			uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
-			pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
-			index++;
-
-			uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
-			pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
-			index++;
-
-			gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
-		}
-		gGL.end();
-	}
-	else
-	{
-		gGL.pushUIMatrix();
-		gGL.translateUI((F32)x, (F32)y, 0.f);
-	
-		F32 offset_x = F32(width/2);
-		F32 offset_y = F32(height/2);
-
-		gGL.translateUI(offset_x, offset_y, 0.f);
-
-		LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
-		
-		gGL.getTexUnit(0)->bind(image, true);
-
-		gGL.color4fv(color.mV);
-		
-		gGL.begin(LLRender::QUADS);
-		{
-			LLVector3 v;
-
-			v = LLVector3(offset_x, offset_y, 0.f) * quat;
-			gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
-			gGL.vertex2f(v.mV[0], v.mV[1] );
-
-			v = LLVector3(-offset_x, offset_y, 0.f) * quat;
-			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
-			gGL.vertex2f(v.mV[0], v.mV[1] );
-
-			v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
-			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
-			gGL.vertex2f(v.mV[0], v.mV[1] );
-
-			v = LLVector3(offset_x, -offset_y, 0.f) * quat;
-			gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
-			gGL.vertex2f(v.mV[0], v.mV[1] );
-		}
-		gGL.end();
-		gGL.popUIMatrix();
-	}
-}
-
-
-void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
-{
-	phase = fmod(phase, 1.f);
-
-	S32 shift = S32(phase * 4.f) % 4;
-
-	// Stippled line
-	LLGLEnable stipple(GL_LINE_STIPPLE);
-	
-	gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
-
-	gGL.flush();
-	glLineWidth(2.5f);
-
-	if (!LLGLSLShader::sNoFixedFunction)
-	{
-		glLineStipple(2, 0x3333 << shift);
-	}
-
-	gGL.begin(LLRender::LINES);
-	{
-		gGL.vertex3fv( start.mV );
-		gGL.vertex3fv( end.mV );
-	}
-	gGL.end();
-
-	LLUI::setLineWidth(1.f);
-}
-
-void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
-{
-	if (end_angle < start_angle)
-	{
-		end_angle += F_TWO_PI;
-	}
-
-	gGL.pushUIMatrix();
-	{
-		gGL.translateUI(center_x, center_y, 0.f);
-
-		// Inexact, but reasonably fast.
-		F32 delta = (end_angle - start_angle) / steps;
-		F32 sin_delta = sin( delta );
-		F32 cos_delta = cos( delta );
-		F32 x = cosf(start_angle) * radius;
-		F32 y = sinf(start_angle) * radius;
-
-		if (filled)
-		{
-			gGL.begin(LLRender::TRIANGLE_FAN);
-			gGL.vertex2f(0.f, 0.f);
-			// make sure circle is complete
-			steps += 1;
-		}
-		else
-		{
-			gGL.begin(LLRender::LINE_STRIP);
-		}
-
-		while( steps-- )
-		{
-			// Successive rotations
-			gGL.vertex2f( x, y );
-			F32 x_new = x * cos_delta - y * sin_delta;
-			y = x * sin_delta +  y * cos_delta;
-			x = x_new;
-		}
-		gGL.end();
-	}
-	gGL.popUIMatrix();
-}
-
-void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
-{
-	gGL.pushUIMatrix();
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		gGL.translateUI(center_x, center_y, 0.f);
-
-		// Inexact, but reasonably fast.
-		F32 delta = F_TWO_PI / steps;
-		F32 sin_delta = sin( delta );
-		F32 cos_delta = cos( delta );
-		F32 x = radius;
-		F32 y = 0.f;
-
-		if (filled)
-		{
-			gGL.begin(LLRender::TRIANGLE_FAN);
-			gGL.vertex2f(0.f, 0.f);
-			// make sure circle is complete
-			steps += 1;
-		}
-		else
-		{
-			gGL.begin(LLRender::LINE_LOOP);
-		}
-
-		while( steps-- )
-		{
-			// Successive rotations
-			gGL.vertex2f( x, y );
-			F32 x_new = x * cos_delta - y * sin_delta;
-			y = x * sin_delta +  y * cos_delta;
-			x = x_new;
-		}
-		gGL.end();
-	}
-	gGL.popUIMatrix();
-}
-
-// Renders a ring with sides (tube shape)
-void gl_deep_circle( F32 radius, F32 depth, S32 steps )
-{
-	F32 x = radius;
-	F32 y = 0.f;
-	F32 angle_delta = F_TWO_PI / (F32)steps;
-	gGL.begin( LLRender::TRIANGLE_STRIP  );
-	{
-		S32 step = steps + 1; // An extra step to close the circle.
-		while( step-- )
-		{
-			gGL.vertex3f( x, y, depth );
-			gGL.vertex3f( x, y, 0.f );
-
-			F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
-			y = x * sinf(angle_delta) +  y * cosf(angle_delta);
-			x = x_new;
-		}
-	}
-	gGL.end();
-}
-
-void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
-{
-	gGL.pushUIMatrix();
-	{
-		gGL.translateUI(0.f, 0.f, -width / 2);
-		if( render_center )
-		{
-			gGL.color4fv(center_color.mV);
-			gGL.diffuseColor4fv(center_color.mV);
-			gl_deep_circle( radius, width, steps );
-		}
-		else
-		{
-			gGL.diffuseColor4fv(side_color.mV);
-			gl_washer_2d(radius, radius - width, steps, side_color, side_color);
-			gGL.translateUI(0.f, 0.f, width);
-			gl_washer_2d(radius - width, radius, steps, side_color, side_color);
-		}
-	}
-	gGL.popUIMatrix();
-}
-
-// Draw gray and white checkerboard with black border
-void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
-{
-	if (!LLGLSLShader::sNoFixedFunction)
-	{ 
-	// Initialize the first time this is called.
-	const S32 PIXELS = 32;
-	static GLubyte checkerboard[PIXELS * PIXELS];
-	static BOOL first = TRUE;
-	if( first )
-	{
-		for( S32 i = 0; i < PIXELS; i++ )
-		{
-			for( S32 j = 0; j < PIXELS; j++ )
-			{
-				checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
-			}
-		}
-		first = FALSE;
-	}
-	
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	// ...white squares
-	gGL.color4f( 1.f, 1.f, 1.f, alpha );
-	gl_rect_2d(rect);
-
-	// ...gray squares
-	gGL.color4f( .7f, .7f, .7f, alpha );
-	gGL.flush();
-
-		glPolygonStipple( checkerboard );
-
-		LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
-		gl_rect_2d(rect);
-	}
-	else
-	{ //polygon stipple is deprecated, use "Checker" texture
-		LLPointer<LLUIImage> img = LLUI::getUIImage("Checker");
-		gGL.getTexUnit(0)->bind(img->getImage());
-		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
-		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-
-		LLColor4 color(1.f, 1.f, 1.f, alpha);
-		LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f);
-
-		gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(),
-			img->getImage(), color, uv_rect);
-	}
-	
-	gGL.flush();
-}
-
-
-// Draws the area between two concentric circles, like
-// a doughnut or washer.
-void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
-{
-	const F32 DELTA = F_TWO_PI / steps;
-	const F32 SIN_DELTA = sin( DELTA );
-	const F32 COS_DELTA = cos( DELTA );
-
-	F32 x1 = outer_radius;
-	F32 y1 = 0.f;
-	F32 x2 = inner_radius;
-	F32 y2 = 0.f;
-
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	gGL.begin( LLRender::TRIANGLE_STRIP  );
-	{
-		steps += 1; // An extra step to close the circle.
-		while( steps-- )
-		{
-			gGL.color4fv(outer_color.mV);
-			gGL.vertex2f( x1, y1 );
-			gGL.color4fv(inner_color.mV);
-			gGL.vertex2f( x2, y2 );
-
-			F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
-			y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
-			x1 = x1_new;
-
-			F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
-			y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
-			x2 = x2_new;
-		}
-	}
-	gGL.end();
-}
-
-// Draws the area between two concentric circles, like
-// a doughnut or washer.
-void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
-{
-	const F32 DELTA = (end_radians - start_radians) / steps;
-	const F32 SIN_DELTA = sin( DELTA );
-	const F32 COS_DELTA = cos( DELTA );
-
-	F32 x1 = outer_radius * cos( start_radians );
-	F32 y1 = outer_radius * sin( start_radians );
-	F32 x2 = inner_radius * cos( start_radians );
-	F32 y2 = inner_radius * sin( start_radians );
-
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.begin( LLRender::TRIANGLE_STRIP  );
-	{
-		steps += 1; // An extra step to close the circle.
-		while( steps-- )
-		{
-			gGL.color4fv(outer_color.mV);
-			gGL.vertex2f( x1, y1 );
-			gGL.color4fv(inner_color.mV);
-			gGL.vertex2f( x2, y2 );
-
-			F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
-			y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
-			x1 = x1_new;
-
-			F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
-			y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
-			x2 = x2_new;
-		}
-	}
-	gGL.end();
-}
-
-void gl_rect_2d_simple_tex( S32 width, S32 height )
-{
-	gGL.begin( LLRender::QUADS );
-
-		gGL.texCoord2f(1.f, 1.f);
-		gGL.vertex2i(width, height);
-
-		gGL.texCoord2f(0.f, 1.f);
-		gGL.vertex2i(0, height);
-
-		gGL.texCoord2f(0.f, 0.f);
-		gGL.vertex2i(0, 0);
-
-		gGL.texCoord2f(1.f, 0.f);
-		gGL.vertex2i(width, 0);
-	
-	gGL.end();
-}
-
-void gl_rect_2d_simple( S32 width, S32 height )
-{
-	gGL.begin( LLRender::QUADS );
-		gGL.vertex2i(width, height);
-		gGL.vertex2i(0, height);
-		gGL.vertex2i(0, 0);
-		gGL.vertex2i(width, 0);
-	gGL.end();
-}
-
-void gl_segmented_rect_2d_tex(const S32 left, 
-							  const S32 top, 
-							  const S32 right, 
-							  const S32 bottom, 
-							  const S32 texture_width, 
-							  const S32 texture_height, 
-							  const S32 border_size, 
-							  const U32 edges)
-{
-	S32 width = llabs(right - left);
-	S32 height = llabs(top - bottom);
-
-	gGL.pushUIMatrix();
-
-	gGL.translateUI((F32)left, (F32)bottom, 0.f);
-	LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
-
-	if (border_uv_scale.mV[VX] > 0.5f)
-	{
-		border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
-	}
-	if (border_uv_scale.mV[VY] > 0.5f)
-	{
-		border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
-	}
-
-	F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
-	LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
-	LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
-	LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
-	LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
-	LLVector2 width_vec((F32)width, 0.f);
-	LLVector2 height_vec(0.f, (F32)height);
-
-	gGL.begin(LLRender::QUADS);
-	{
-		// draw bottom left
-		gGL.texCoord2f(0.f, 0.f);
-		gGL.vertex2f(0.f, 0.f);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
-		gGL.vertex2fv(border_width_left.mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
-
-		gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
-		gGL.vertex2fv(border_height_bottom.mV);
-
-		// draw bottom middle
-		gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
-		gGL.vertex2fv(border_width_left.mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
-		gGL.vertex2fv((width_vec - border_width_right).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
-
-		// draw bottom right
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
-		gGL.vertex2fv((width_vec - border_width_right).mV);
-
-		gGL.texCoord2f(1.f, 0.f);
-		gGL.vertex2fv(width_vec.mV);
-
-		gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec + border_height_bottom).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
-
-		// draw left 
-		gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
-		gGL.vertex2fv(border_height_bottom.mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((height_vec - border_height_top).mV);
-
-		// draw middle
-		gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + border_height_bottom).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
-
-		// draw right 
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
-
-		gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec + border_height_bottom).mV);
-
-		gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
-
-		// draw top left
-		gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
-		gGL.vertex2fv((border_width_left + height_vec).mV);
-
-		gGL.texCoord2f(0.f, 1.f);
-		gGL.vertex2fv((height_vec).mV);
-
-		// draw top middle
-		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
-		gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
-
-		gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
-		gGL.vertex2fv((border_width_left + height_vec).mV);
-
-		// draw top right
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
-		gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
-
-		gGL.texCoord2f(1.f, 1.f);
-		gGL.vertex2fv((width_vec + height_vec).mV);
-
-		gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
-		gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
-	}
-	gGL.end();
-
-	gGL.popUIMatrix();
-}
-
-//FIXME: rewrite to use scissor?
-void gl_segmented_rect_2d_fragment_tex(const S32 left, 
-									   const S32 top, 
-									   const S32 right, 
-									   const S32 bottom, 
-									   const S32 texture_width, 
-									   const S32 texture_height, 
-									   const S32 border_size, 
-									   const F32 start_fragment, 
-									   const F32 end_fragment, 
-									   const U32 edges)
-{
-	S32 width = llabs(right - left);
-	S32 height = llabs(top - bottom);
-
-	gGL.pushUIMatrix();
-
-	gGL.translateUI((F32)left, (F32)bottom, 0.f);
-	LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
-
-	if (border_uv_scale.mV[VX] > 0.5f)
-	{
-		border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
-	}
-	if (border_uv_scale.mV[VY] > 0.5f)
-	{
-		border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
-	}
-
-	F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
-	LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
-	LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
-	LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
-	LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
-	LLVector2 width_vec((F32)width, 0.f);
-	LLVector2 height_vec(0.f, (F32)height);
-
-	F32 middle_start = border_scale / (F32)width;
-	F32 middle_end = 1.f - middle_start;
-
-	F32 u_min;
-	F32 u_max;
-	LLVector2 x_min;
-	LLVector2 x_max;
-
-	gGL.begin(LLRender::QUADS);
-	{
-		if (start_fragment < middle_start)
-		{
-			u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
-			u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
-			x_min = (start_fragment / middle_start) * border_width_left;
-			x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
-
-			// draw bottom left
-			gGL.texCoord2f(u_min, 0.f);
-			gGL.vertex2fv(x_min.mV);
-
-			gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
-			gGL.vertex2fv(x_max.mV);
-
-			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + border_height_bottom).mV);
-
-			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + border_height_bottom).mV);
-
-			// draw left 
-			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + border_height_bottom).mV);
-
-			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + border_height_bottom).mV);
-
-			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
-			
-			// draw top left
-			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(u_max, 1.f);
-			gGL.vertex2fv((x_max + height_vec).mV);
-
-			gGL.texCoord2f(u_min, 1.f);
-			gGL.vertex2fv((x_min + height_vec).mV);
-		}
-
-		if (end_fragment > middle_start || start_fragment < middle_end)
-		{
-			x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
-			x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
-
-			// draw bottom middle
-			gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
-			gGL.vertex2fv(x_min.mV);
-
-			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
-			gGL.vertex2fv((x_max).mV);
-
-			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + border_height_bottom).mV);
-
-			gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + border_height_bottom).mV);
-
-			// draw middle
-			gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + border_height_bottom).mV);
-
-			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + border_height_bottom).mV);
-
-			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
-
-			// draw top middle
-			gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
-			gGL.vertex2fv((x_max + height_vec).mV);
-
-			gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
-			gGL.vertex2fv((x_min + height_vec).mV);
-		}
-
-		if (end_fragment > middle_end)
-		{
-			u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX];
-			u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX];
-			x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right);
-			x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
-
-			// draw bottom right
-			gGL.texCoord2f(u_min, 0.f);
-			gGL.vertex2fv((x_min).mV);
-
-			gGL.texCoord2f(u_max, 0.f);
-			gGL.vertex2fv(x_max.mV);
-
-			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + border_height_bottom).mV);
-
-			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + border_height_bottom).mV);
-
-			// draw right 
-			gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + border_height_bottom).mV);
-
-			gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + border_height_bottom).mV);
-
-			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
-
-			// draw top right
-			gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
-			gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
-
-			gGL.texCoord2f(u_max, 1.f);
-			gGL.vertex2fv((x_max + height_vec).mV);
-
-			gGL.texCoord2f(u_min, 1.f);
-			gGL.vertex2fv((x_min + height_vec).mV);
-		}
-	}
-	gGL.end();
-
-	gGL.popUIMatrix();
-}
-
-void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, 
-							 const LLVector3& width_vec, const LLVector3& height_vec)
-{
-	gGL.begin(LLRender::QUADS);
-	{
-		// draw bottom left
-		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);
-		gGL.vertex3f(0.f, 0.f, 0.f);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
-
-		// draw bottom middle
-		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		// draw bottom right
-		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);
-		gGL.vertex3fv(width_vec.mV);
-
-		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
-		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		// draw left 
-		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
-
-		// draw middle
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		// draw right 
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
-		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
-		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		// draw top left
-		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);
-		gGL.vertex3fv((height_vec).mV);
-
-		// draw top middle
-		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
-
-		// draw top right
-		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
-		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
-
-		gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);
-		gGL.vertex3fv((width_vec + height_vec).mV);
-
-		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
-		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
-	}
-	gGL.end();
-
-}
-
-
 void LLUI::initClass(const settings_map_t& settings,
 					 LLImageProviderInterface* image_provider,
 					 LLUIAudioCallback audio_callback,
@@ -1633,6 +163,7 @@ void LLUI::initClass(const settings_map_t& settings,
 					 const LLVector2* scale_factor,
 					 const std::string& language)
 {
+	LLRender2D::initClass(image_provider,scale_factor);
 	sSettingGroups = settings;
 
 	if ((get_ptr_in_map(sSettingGroups, std::string("config")) == NULL) ||
@@ -1642,10 +173,8 @@ void LLUI::initClass(const settings_map_t& settings,
 		llerrs << "Failure to initialize configuration groups" << llendl;
 	}
 
-	sImageProvider = image_provider;
 	sAudioCallback = audio_callback;
 	sDeferredAudioCallback = deferred_audio_callback;
-	sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
 	sWindow = NULL; // set later in startup
 	LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow");
 
@@ -1679,10 +208,7 @@ void LLUI::initClass(const settings_map_t& settings,
 
 void LLUI::cleanupClass()
 {
-	if(sImageProvider)
-	{
-	sImageProvider->cleanUp();
-}
+	LLRender2D::cleanupClass();
 }
 
 void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup,  const clear_popups_t& clear_popups)
@@ -1706,60 +232,12 @@ void LLUI::dirtyRect(LLRect rect)
 	}		
 }
  
-
-//static
-void LLUI::translate(F32 x, F32 y, F32 z)
-{
-	gGL.translateUI(x,y,z);
-	LLFontGL::sCurOrigin.mX += (S32) x;
-	LLFontGL::sCurOrigin.mY += (S32) y;
-	LLFontGL::sCurDepth += z;
-}
-
-//static
-void LLUI::pushMatrix()
-{
-	gGL.pushUIMatrix();
-	LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
-}
-
-//static
-void LLUI::popMatrix()
-{
-	gGL.popUIMatrix();
-	LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first;
-	LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;
-	LLFontGL::sOriginStack.pop_back();
-}
-
-//static 
-void LLUI::loadIdentity()
-{
-	gGL.loadUIIdentity(); 
-	LLFontGL::sCurOrigin.mX = 0;
-	LLFontGL::sCurOrigin.mY = 0;
-	LLFontGL::sCurDepth = 0.f;
-}
-
-//static
-void LLUI::setScaleFactor(const LLVector2 &scale_factor)
-{
-	sGLScaleFactor = scale_factor;
-}
-
-//static
-void LLUI::setLineWidth(F32 width)
-{
-	gGL.flush();
-	glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f));
-}
-
 //static 
 void LLUI::setMousePositionScreen(S32 x, S32 y)
 {
 	S32 screen_x, screen_y;
-	screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
-	screen_y = llround((F32)y * sGLScaleFactor.mV[VY]);
+	screen_x = llround((F32)x * getScaleFactor().mV[VX]);
+	screen_y = llround((F32)y * getScaleFactor().mV[VY]);
 	
 	LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert());
 }
@@ -1770,8 +248,8 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y)
 	LLCoordWindow cursor_pos_window;
 	getWindow()->getCursorPosition(&cursor_pos_window);
 	LLCoordGL cursor_pos_gl(cursor_pos_window.convert());
-	*x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]);
-	*y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]);
+	*x = llround((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]);
+	*y = llround((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]);
 }
 
 //static 
@@ -1885,21 +363,21 @@ LLVector2 LLUI::getWindowSize()
 	LLCoordWindow window_rect;
 	sWindow->getSize(&window_rect);
 
-	return LLVector2(window_rect.mX / sGLScaleFactor.mV[VX], window_rect.mY / sGLScaleFactor.mV[VY]);
+	return LLVector2(window_rect.mX / getScaleFactor().mV[VX], window_rect.mY / getScaleFactor().mV[VY]);
 }
 
 //static
 void LLUI::screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y)
 {
-	*gl_x = llround((F32)screen_x * sGLScaleFactor.mV[VX]);
-	*gl_y = llround((F32)screen_y * sGLScaleFactor.mV[VY]);
+	*gl_x = llround((F32)screen_x * getScaleFactor().mV[VX]);
+	*gl_y = llround((F32)screen_y * getScaleFactor().mV[VY]);
 }
 
 //static
 void LLUI::glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y)
 {
-	*screen_x = llround((F32)gl_x / sGLScaleFactor.mV[VX]);
-	*screen_y = llround((F32)gl_y / sGLScaleFactor.mV[VY]);
+	*screen_x = llround((F32)gl_x / getScaleFactor().mV[VX]);
+	*screen_y = llround((F32)gl_y / getScaleFactor().mV[VY]);
 }
 
 //static
@@ -1916,27 +394,6 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen)
 	glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom);
 }
 
-//static
-LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id, S32 priority)
-{
-	if (sImageProvider)
-	{
-		return sImageProvider->getUIImageByID(image_id, priority);
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-//static 
-LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name, S32 priority)
-{
-	if (!name.empty() && sImageProvider)
-		return sImageProvider->getUIImage(name, priority);
-	else
-		return NULL;
-}
 
 LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname)
 {
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 4c1703392a..83831e4799 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -1,6 +1,6 @@
 /** 
  * @file llui.h
- * @brief GL function declarations and other general static UI services.
+ * @brief General static UI services.
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -24,122 +24,38 @@
  * $/LicenseInfo$
  */
 
-// All immediate-mode gl drawing should happen here.
 
 #ifndef LL_LLUI_H
 #define LL_LLUI_H
 
-#include "llpointer.h"		// LLPointer<>
 #include "llrect.h"
 #include "llcontrol.h"
 #include "llcoord.h"
-#include "llglslshader.h"
+#include "v2math.h"
 #include "llinitparam.h"
 #include "llregistry.h"
+#include "llrender2dutils.h"
+#include "llpointer.h"
 #include "lluicolor.h"
 #include "lluicolortable.h"
+#include "lluiimage.h"
 #include <boost/signals2.hpp>
 #include "lllazyvalue.h"
 #include "llframetimer.h"
 #include <limits>
 
-// LLUIFactory
-#include "llsd.h"
-
 // for initparam specialization
 #include "llfontgl.h"
 
 
-class LLColor4; 
-class LLVector3;
-class LLVector2;
-class LLUIImage;
 class LLUUID;
 class LLWindow;
 class LLView;
 class LLHelp;
 
-// UI colors
-extern const LLColor4 UI_VERTEX_COLOR;
 void make_ui_sound(const char* name);
 void make_ui_sound_deferred(const char * name);
 
-BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom);
-void gl_state_for_2d(S32 width, S32 height);
-
-void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2);
-void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color );
-void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled);
-void gl_rect_2d_simple( S32 width, S32 height );
-
-void gl_draw_x(const LLRect& rect, const LLColor4& color);
-
-void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE );
-void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE );
-void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE );
-void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE );
-void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE );
-void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE );
-void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
-
-void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
-
-void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled);
-void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle);
-void gl_deep_circle( F32 radius, F32 depth );
-void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center );
-void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
-void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
-void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
-
-void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-
-void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); 
-
-void gl_rect_2d_simple_tex( S32 width, S32 height );
-
-// segmented rectangles
-
-/*
-   TL |______TOP_________| TR 
-     /|                  |\  
-   _/_|__________________|_\_
-   L| |    MIDDLE        | |R
-   _|_|__________________|_|_
-    \ |    BOTTOM        | /  
-   BL\|__________________|/ BR
-      |                  |    
-*/
-
-typedef enum e_rounded_edge
-{
-	ROUNDED_RECT_LEFT	= 0x1, 
-	ROUNDED_RECT_TOP	= 0x2, 
-	ROUNDED_RECT_RIGHT	= 0x4, 
-	ROUNDED_RECT_BOTTOM	= 0x8,
-	ROUNDED_RECT_ALL	= 0xf
-}ERoundedEdge;
-
-
-void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
-void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
-void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);
-
-inline void gl_rect_2d( const LLRect& rect, BOOL filled )
-{
-	gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
-}
-
-inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled)
-{
-	gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
-}
-
 class LLImageProviderInterface;
 
 typedef	void (*LLUIAudioCallback)(const LLUUID& uuid);
@@ -281,10 +197,10 @@ public:
 	static void cleanupClass();
 	static void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& );
 
-	static void pushMatrix();
-	static void popMatrix();
-	static void loadIdentity();
-	static void translate(F32 x, F32 y, F32 z = 0.0f);
+	static void pushMatrix() { LLRender2D::pushMatrix(); }
+	static void popMatrix() { LLRender2D::popMatrix(); }
+	static void loadIdentity() { LLRender2D::loadIdentity(); }
+	static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); }
 
 	static LLRect	sDirtyRect;
 	static BOOL		sDirty;
@@ -329,10 +245,13 @@ public:
 	static void getMousePositionScreen(S32 *x, S32 *y);
 	static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y);
 	static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
-	static void setScaleFactor(const LLVector2& scale_factor);
-	static void setLineWidth(F32 width);
-	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
-	static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
+	static LLVector2& getScaleFactor() { return LLRender2D::sGLScaleFactor; }
+	static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::setScaleFactor(scale_factor); }
+	static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); }
+	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0)
+		{ return LLRender2D::getUIImageByID(image_id, priority); }
+	static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0)
+		{ return LLRender2D::getUIImage(name, priority); }
 	static LLVector2 getWindowSize();
 	static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y);
 	static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y);
@@ -362,12 +281,10 @@ public:
 	static settings_map_t sSettingGroups;
 	static LLUIAudioCallback sAudioCallback;
 	static LLUIAudioCallback sDeferredAudioCallback;
-	static LLVector2		sGLScaleFactor;
 	static LLWindow*		sWindow;
 	static LLView*			sRootView;
 	static LLHelp*			sHelpImpl;
 private:
-	static LLImageProviderInterface* sImageProvider;
 	static std::vector<std::string> sXUIPaths;
 	static LLFrameTimer		sMouseIdleTimer;
 	static add_popup_t		sAddPopupFunc;
@@ -378,18 +295,6 @@ private:
 
 // Moved LLLocalClipRect to lllocalcliprect.h
 
-//RN: maybe this needs to moved elsewhere?
-class LLImageProviderInterface
-{
-protected:
-	LLImageProviderInterface() {};
-	virtual ~LLImageProviderInterface() {};
-public:
-	virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
-	virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
-	virtual void cleanUp() = 0;
-};
-
 class LLCallbackRegistry
 {
 public:
@@ -600,7 +505,4 @@ namespace LLInitParam
 	};
 }
 
-extern LLGLSLShader gSolidColorProgram;
-extern LLGLSLShader gUIProgram;
-
 #endif
diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp
deleted file mode 100644
index 9ed98f941f..0000000000
--- a/indra/llui/lluiimage.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-/** 
- * @file lluiimage.cpp
- * @brief UI implementation
- *
- * $LicenseInfo:firstyear=2007&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$
- */
-
-// Utilities functions the user interface needs
-
-//#include "llviewerprecompiledheaders.h"
-#include "linden_common.h"
-
-// Project includes
-#include "lluiimage.h"
-#include "llui.h"
-
-LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
-:	mName(name),
-	mImage(image),
-	mScaleRegion(0.f, 1.f, 1.f, 0.f),
-	mClipRegion(0.f, 1.f, 1.f, 0.f),
-	mUniformScaling(TRUE),
-	mNoClip(TRUE),
-	mImageLoaded(NULL)
-{
-}
-
-LLUIImage::~LLUIImage()
-{
-	delete mImageLoaded;
-}
-
-void LLUIImage::setClipRegion(const LLRectf& region) 
-{ 
-	mClipRegion = region; 
-	mNoClip = mClipRegion.mLeft == 0.f
-				&& mClipRegion.mRight == 1.f
-				&& mClipRegion.mBottom == 0.f
-				&& mClipRegion.mTop == 1.f;
-}
-
-void LLUIImage::setScaleRegion(const LLRectf& region) 
-{ 
-	mScaleRegion = region; 
-	mUniformScaling = mScaleRegion.mLeft == 0.f
-					&& mScaleRegion.mRight == 1.f
-					&& mScaleRegion.mBottom == 0.f
-					&& mScaleRegion.mTop == 1.f;
-}
-
-//TODO: move drawing implementation inside class
-void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
-{
-	gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion);
-}
-
-void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
-{
-	if (mUniformScaling)
-	{
-		gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion);
-	}
-	else
-	{
-		gl_draw_scaled_image_with_border(
-			x, y, 
-			width, height, 
-			mImage, 
-			color,
-			FALSE,
-			mClipRegion,
-			mScaleRegion);
-	}
-}
-
-void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
-{
-	gl_draw_scaled_image_with_border(
-		x, y, 
-		width, height, 
-		mImage, 
-		color, 
-		TRUE,
-		mClipRegion,
-		mScaleRegion);
-}
-
-void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
-{
-	LLRect border_rect;
-	border_rect.setOriginAndSize(x, y, width, height);
-	border_rect.stretch(border_width, border_width);
-	drawSolid(border_rect, color);
-}
-
-void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, 
-						const LLRect& rect, const LLColor4& color)
-{
-	F32 border_scale = 1.f;
-	F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
-	F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
-	if (rect.getHeight() < border_height || rect.getWidth() < border_width)
-	{
-		 if(border_height - rect.getHeight() > border_width - rect.getWidth())
-		 {
-			 border_scale = (F32)rect.getHeight() / border_height;
-		 }
-		 else
-		 {
-			border_scale = (F32)rect.getWidth() / border_width;
-		 }
-	}
-
-	LLUI::pushMatrix();
-	{ 
-		LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); 
-		LLUI::translate(rect_origin.mV[VX],
-						rect_origin.mV[VY], 
-						rect_origin.mV[VZ]);
-		gGL.getTexUnit(0)->bind(getImage());
-		gGL.color4fv(color.mV);
-
-		LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
-							mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
-							mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
-							mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
-		gl_segmented_rect_3d_tex(mClipRegion,
-								center_uv_rect,
-								LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
-										(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
-										(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
-										(border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
-								rect.getWidth() * x_axis, 
-								rect.getHeight() * y_axis);
-		
-	} LLUI::popMatrix();
-}
-
-
-S32 LLUIImage::getWidth() const
-{ 
-	// return clipped dimensions of actual image area
-	return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); 
-}
-
-S32 LLUIImage::getHeight() const
-{ 
-	// return clipped dimensions of actual image area
-	return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); 
-}
-
-S32 LLUIImage::getTextureWidth() const
-{
-	return mImage->getWidth(0);
-}
-
-S32 LLUIImage::getTextureHeight() const
-{
-	return mImage->getHeight(0);
-}
-
-boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb ) 
-{
-	if (!mImageLoaded) 
-	{
-		mImageLoaded = new image_loaded_signal_t();
-	}
-	return mImageLoaded->connect(cb);
-}
-
-
-void LLUIImage::onImageLoaded()
-{
-	if (mImageLoaded)
-	{
-		(*mImageLoaded)();
-	}
-}
-
-
-namespace LLInitParam
-{
-	void ParamValue<LLUIImage*>::updateValueFromBlock()
-	{
-		// The keyword "none" is specifically requesting a null image
-		// do not default to current value. Used to overwrite template images. 
-		if (name() == "none")
-		{
-			updateValue(NULL);
-			return;
-		}
-
-		LLUIImage* imagep =  LLUI::getUIImage(name());
-		if (imagep)
-		{
-			updateValue(imagep);
-		}
-	}
-	
-	void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)
-	{
-		if (getValue() == NULL)
-		{
-			name.set("none", make_block_authoritative);
-		}
-		else
-		{
-			name.set(getValue()->getName(), make_block_authoritative);
-		}
-	}
-
-	
-	bool ParamCompare<LLUIImage*, false>::equals(
-		LLUIImage* const &a,
-		LLUIImage* const &b)
-	{
-		// force all LLUIImages for XML UI export to be "non-default"
-		if (!a && !b)
-			return false;
-		else
-			return (a == b);
-	}
-}
-
diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h
deleted file mode 100644
index 7817ba1c7b..0000000000
--- a/indra/llui/lluiimage.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/** 
- * @file lluiimage.h
- * @brief wrapper for images used in the UI that handles smart scaling, etc.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLUIIMAGE_H
-#define LL_LLUIIMAGE_H
-
-#include "v4color.h"
-#include "llpointer.h"
-#include "llrefcount.h"
-#include "llrefcount.h"
-#include "llrect.h"
-#include <boost/function.hpp>
-#include <boost/signals2.hpp>
-#include "llinitparam.h"
-#include "lltexture.h"
-
-extern const LLColor4 UI_VERTEX_COLOR;
-
-class LLUIImage : public LLRefCount
-{
-public:
-	typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
-
-	LLUIImage(const std::string& name, LLPointer<LLTexture> image);
-	virtual ~LLUIImage();
-
-	void setClipRegion(const LLRectf& region);
-	void setScaleRegion(const LLRectf& region);
-
-	LLPointer<LLTexture> getImage() { return mImage; }
-	const LLPointer<LLTexture>& getImage() const { return mImage; }
-
-	void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
-	void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
-	void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
-	
-	void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
-	void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
-	void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
-
-	void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
-	void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
-	void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
-
-	void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
-
-	const std::string& getName() const { return mName; }
-
-	virtual S32 getWidth() const;
-	virtual S32 getHeight() const;
-
-	// returns dimensions of underlying textures, which might not be equal to ui image portion
-	S32 getTextureWidth() const;
-	S32 getTextureHeight() const;
-
-	boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
-
-	void onImageLoaded();
-
-protected:
-	image_loaded_signal_t* mImageLoaded;
-
-	std::string			mName;
-	LLRectf				mScaleRegion;
-	LLRectf				mClipRegion;
-	LLPointer<LLTexture> mImage;
-	BOOL				mUniformScaling;
-	BOOL				mNoClip;
-};
-
-namespace LLInitParam
-{
-	template<>
-	class ParamValue<LLUIImage*> 
-	:	public CustomParamValue<LLUIImage*>
-	{
-		typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type	T_const_ref;
-		typedef CustomParamValue<LLUIImage*> super_t;
-	public:
-		Optional<std::string> name;
-
-		ParamValue(LLUIImage* const& image = NULL)
-		:	super_t(image)
-		{
-			updateBlockFromValue(false);
-			addSynonym(name, "name");
-		}
-
-		void updateValueFromBlock();
-		void updateBlockFromValue(bool make_block_authoritative);
-	};
-
-	// Need custom comparison function for our test app, which only loads
-	// LLUIImage* as NULL.
-	template<>
-	struct ParamCompare<LLUIImage*, false>
-	{
-		static bool equals(LLUIImage* const &a, LLUIImage* const &b);
-	};
-}
-
-typedef LLPointer<LLUIImage> LLUIImagePtr;
-#endif
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0f77c68ec8..dac268ec92 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -803,7 +803,7 @@ bool LLAppViewer::init()
 		LLUIImageList::getInstance(),
 		ui_audio_callback,
 		deferred_ui_audio_callback,
-		&LLUI::sGLScaleFactor);
+		&LLUI::getScaleFactor());
 	LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
 
 	// NOW LLUI::getLanguage() should work. gDirUtilp must know the language
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 1208c9378e..60fa53f491 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -79,10 +79,10 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
 	S32 top =	llmax(y, mDragStartY);
 	S32 bottom =llmin(y, mDragStartY);
 
-	left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]);
-	right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]);
-	top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]);
-	bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]);
+	left = llround((F32) left * LLUI::getScaleFactor().mV[VX]);
+	right = llround((F32) right * LLUI::getScaleFactor().mV[VX]);
+	top = llround((F32) top * LLUI::getScaleFactor().mV[VY]);
+	bottom = llround((F32) bottom * LLUI::getScaleFactor().mV[VY]);
 
 	F32 old_far_plane = LLViewerCamera::getInstance()->getFar();
 	F32 old_near_plane = LLViewerCamera::getInstance()->getNear();
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 99b4707158..2075aeed63 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -119,8 +119,8 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
 
 	if(!getDecoupleTextureSize())
 	{
-		S32 screen_width = llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]);
-		S32 screen_height = llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]);
+		S32 screen_width = llround((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]);
+		S32 screen_height = llround((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]);
 			
 		setTextureSize(screen_width, screen_height);
 	}
@@ -469,8 +469,8 @@ void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
 {
 	if(!getDecoupleTextureSize())
 	{
-		S32 screen_width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]);
-		S32 screen_height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]);
+		S32 screen_width = llround((F32)width * LLUI::getScaleFactor().mV[VX]);
+		S32 screen_height = llround((F32)height * LLUI::getScaleFactor().mV[VY]);
 
 		// when floater is minimized, these sizes are negative
 		if ( screen_height > 0 && screen_width > 0 )
@@ -667,7 +667,7 @@ bool LLMediaCtrl::ensureMediaSourceExists()
 			mMediaSource->addObserver( this );
 			mMediaSource->setBackgroundColor( getBackgroundColor() );
 			mMediaSource->setTrustedBrowser(mTrusted);
-			mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] );
+			mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] );
 
 			if(mClearCache)
 			{
@@ -750,7 +750,7 @@ void LLMediaCtrl::draw()
 	{
 		gGL.pushUIMatrix();
 		{
-			mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] );
+			mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] );
 
 			// scale texture to fit the space using texture coords
 			gGL.getTexUnit(0)->bind(media_texture);
@@ -864,14 +864,14 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y)
 		coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL();
 	}
 	
-	x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]);
+	x = llround((F32)x * LLUI::getScaleFactor().mV[VX]);
 	if ( ! coords_opengl )
 	{
-		y = llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]);
+		y = llround((F32)(y) * LLUI::getScaleFactor().mV[VY]);
 	}
 	else
 	{
-		y = llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]);
+		y = llround((F32)(getRect().getHeight() - y) * LLUI::getScaleFactor().mV[VY]);
 	};
 }
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index ffeea2f4df..02f82aba63 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1425,7 +1425,7 @@ void render_ui_2d()
 		gGL.pushMatrix();
 		S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
 		S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
-		gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
+		gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f);
 		gGL.translatef((F32)half_width, (F32)half_height, 0.f);
 		F32 zoom = gAgentCamera.mHUDCurZoom;
 		gGL.scalef(zoom,zoom,1.f);
@@ -1463,10 +1463,10 @@ void render_ui_2d()
 				LLUI::sDirtyRect = last_rect;
 				last_rect = t_rect;
 			
-				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
-				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
-				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
-				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
+				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]);
+				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]);
+				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]);
+				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]);
 
 				LLRect clip_rect(last_rect);
 				
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 383eb3c9e4..db3476850b 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2157,7 +2157,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
 
 		calcDisplayScale();
 	
-		BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
+		BOOL display_scale_changed = mDisplayScale != LLUI::getScaleFactor();
 		LLUI::setScaleFactor(mDisplayScale);
 
 		// update our window rectangle
@@ -2363,7 +2363,7 @@ void LLViewerWindow::draw()
 		// scale view by UI global scale factor and aspect ratio correction factor
 		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
 
-		LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
+		LLVector2 old_scale_factor = LLUI::getScaleFactor();
 		// apply camera zoom transform (for high res screenshots)
 		F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
 		S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
@@ -2377,7 +2377,7 @@ void LLViewerWindow::draw()
 						(F32)getWindowHeightScaled() * -(F32)pos_y, 
 						0.f);
 			gGL.scalef(zoom_factor, zoom_factor, 1.f);
-			LLUI::sGLScaleFactor *= zoom_factor;
+			LLUI::getScaleFactor() *= zoom_factor;
 		}
 
 		// Draw tool specific overlay on world
@@ -2425,7 +2425,7 @@ void LLViewerWindow::draw()
 				LLFontGL::HCENTER, LLFontGL::TOP);
 		}
 
-		LLUI::sGLScaleFactor = old_scale_factor;
+		LLUI::setScaleFactor(old_scale_factor);
 	}
 	LLUI::popMatrix();
 	gGL.popMatrix();
@@ -3230,8 +3230,8 @@ void LLViewerWindow::updateLayout()
 
 void LLViewerWindow::updateMouseDelta()
 {
-	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
-	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
+	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]);
+	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]);
 
 	//RN: fix for asynchronous notification of mouse leaving window not working
 	LLCoordWindow mouse_pos;
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index ccc513b80d..ffb0964499 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -421,7 +421,7 @@ void LLWorldMapView::draw()
 			{
 				// Inform the fetch mechanism of the size we need
 				S32 draw_size = llround(sMapScale);
-				overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
+				overlayimage->setKnownDrawSize(llround(draw_size * LLUI::getScaleFactor().mV[VX]), llround(draw_size * LLUI::getScaleFactor().mV[VY]));
 				// Draw something whenever we have enough info
 				if (overlayimage->hasGLTexture())
 				{
@@ -1320,7 +1320,7 @@ void LLWorldMapView::drawTrackingCircle( const LLRect& rect, S32 x, S32 y, const
 
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.pushMatrix();
-	gGL.translatef((F32)x * LLUI::sGLScaleFactor.mV[VX], (F32)y * LLUI::sGLScaleFactor.mV[VY], 0.f);
+	gGL.translatef((F32)x * LLUI::getScaleFactor().mV[VX], (F32)y * LLUI::getScaleFactor().mV[VY], 0.f);
 	gl_washer_segment_2d(inner_radius, outer_radius, start_theta, end_theta, 40, color, color);
 	gGL.popMatrix();
 
-- 
cgit v1.2.3


From 0ebcdce82bffae18459ed541f05906f625ef47e2 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Tue, 12 Mar 2013 18:53:27 -0400
Subject: WIP: merge fixes

---
 indra/newview/lloutputmonitorctrl.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h
index a346909027..0682af1278 100644
--- a/indra/newview/lloutputmonitorctrl.h
+++ b/indra/newview/lloutputmonitorctrl.h
@@ -31,7 +31,7 @@
 #include "../llui/llview.h"
 #include "llmutelist.h"
 #include "llspeakingindicatormanager.h"
-#include "../llui/lluiimage.h"
+//#include "../llui/lluiimage.h"
 
 class LLTextBox;
 class LLUICtrlFactory;
-- 
cgit v1.2.3


From f945415210f0e18c2c6d941fda6b7d45cb0f06f1 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Wed, 13 Mar 2013 06:26:25 +0000
Subject: Large changes to the LLCurl::Responder API, as well as pulling in
 some changes to common libraries from the server codebase:

* Additional error checking in http handlers.
* Uniform log spam for http errors.
* Switch to using constants for http heads and status codes.
* Fixed bugs in incorrectly checking if parsing LLSD xml resulted in an error.
* Reduced spam regarding LLSD parsing errors in the default completedRaw http handler.  It should not longer be necessary to short-circuit completedRaw to avoid spam.
* Ported over a few bug fixes from the server code.
* Switch mode http status codes to use S32 instead of U32.
* Ported LLSD::asStringRef from server code; avoids copying strings all over the place.
* Ported server change to LLSD::asBinary; this always returns a reference now instead of copying the entire binary blob.
* Ported server pretty notation format (and pretty binary format) to llsd serialization.

* The new LLCurl::Responder API no longer has two error handlers to choose from.  Overriding the following methods have been deprecated:
** error - use httpFailure
** errorWithContent - use httpFailure
** result - use httpSuccess
** completed - use httpCompleted
** completedHeader - no longer necessary; call getResponseHeaders() from a completion method to obtain these headers.

* In order to 'catch' a completed http request, override one of these methods:
** httpSuccess - Called for any 2xx status code.
** httpFailure - Called for any non-2xx status code.
** httpComplete - Called for all status codes.  Default implementation is to call either httpSuccess or httpFailure.
* It is recommended to keep these methods protected/private in order to avoid triggering of these methods without using a 'push' method (see below).

* Uniform error handling should followed whenever possible by calling a variant of this during httpFailure:
** llwarns << dumpResponse() << llendl;
* Be sure to include LOG_CLASS(your_class_name) in your class in order for the log entry to give more context.

* In order to 'push' a result into the responder, you should no longer call error, errorWithContent, result, or completed.
* Nor should you directly call httpSuccess/Failure/Completed (unless passing a message up to a parent class).
* Instead, you can set the internal content of a responder and trigger a corresponding method using the following methods:
** successResult - Sets results and calls httpSuccess
** failureResult - Sets results and calls httpFailure
** completedResult - Sets results and calls httpCompleted

* To obtain information about a the response from a reponder method, use the following getters:
** getStatus - HTTP status code
** getReason - Reason string
** getContent - Content (Parsed body LLSD)
** getResponseHeaders - Response Headers (LLSD map)
** getHTTPMethod - HTTP method of the request
** getURL - URL of the request

* It is still possible to override completeRaw if you want to manipulate data directly out of LLPumpIO.

* See indra/llmessage/llcurl.h for more information.
---
 indra/llcommon/CMakeLists.txt                      |   1 -
 indra/llcommon/llhttpstatuscodes.h                 |  89 --------
 indra/llcommon/llsd.cpp                            |  11 +-
 indra/llcommon/llsd.h                              |   5 +-
 indra/llcommon/llsdserialize.cpp                   |  65 ++++--
 indra/llcommon/llsdserialize.h                     |  28 ++-
 indra/llcommon/llsdserialize_xml.cpp               |  15 +-
 indra/llcorehttp/_httplibcurl.cpp                  |   2 +-
 indra/llcorehttp/_httpoprequest.cpp                |   3 +-
 indra/llcrashlogger/llcrashlogger.cpp              |   9 +-
 indra/llmessage/CMakeLists.txt                     |  10 +-
 indra/llmessage/llavatarnamecache.cpp              |  53 ++---
 indra/llmessage/llavatarnamecache.h                |   2 +-
 indra/llmessage/llcurl.cpp                         | 225 ++++++++++++++++-----
 indra/llmessage/llcurl.h                           | 112 ++++++----
 indra/llmessage/llhttpassetstorage.cpp             |  21 +-
 indra/llmessage/llhttpclient.cpp                   | 137 +++++++------
 indra/llmessage/llhttpclientadapter.cpp            |  26 ++-
 indra/llmessage/llhttpclientadapter.h              |   8 +
 indra/llmessage/llhttpconstants.cpp                | 219 ++++++++++++++++++++
 indra/llmessage/llhttpconstants.h                  | 220 ++++++++++++++++++++
 indra/llmessage/llhttpnode.cpp                     |  22 +-
 indra/llmessage/llhttpnode.h                       |  11 +-
 indra/llmessage/lliohttpserver.cpp                 |  68 +++++--
 indra/llmessage/lliohttpserver.h                   |   5 -
 indra/llmessage/llmime.cpp                         |  39 ++--
 indra/llmessage/llregionpresenceverifier.cpp       | 153 --------------
 indra/llmessage/llregionpresenceverifier.h         |  98 ---------
 indra/llmessage/llsdmessage.cpp                    |  21 +-
 indra/llmessage/llsdmessage.h                      |   6 +-
 indra/llmessage/llsdrpcclient.h                    |   8 +-
 indra/llmessage/lltrustedmessageservice.cpp        |   2 +-
 indra/llmessage/llurlrequest.cpp                   |  43 ++--
 indra/llmessage/llurlrequest.h                     |  42 +---
 indra/llmessage/message.cpp                        |  12 +-
 indra/llmessage/tests/llcurl_stub.cpp              |  59 ++++--
 indra/llmessage/tests/llhttpclient_test.cpp        |  31 ++-
 indra/llmessage/tests/llhttpclientadapter_test.cpp |  81 ++++++--
 indra/llmessage/tests/llmime_test.cpp              |   1 +
 .../tests/llregionpresenceverifier_test.cpp        | 108 ----------
 indra/newview/CMakeLists.txt                       |  13 +-
 indra/newview/llaccountingcostmanager.cpp          |  14 +-
 indra/newview/llaccountingcostmanager.h            |   2 +-
 indra/newview/llagent.cpp                          |  46 +++--
 indra/newview/llappearancemgr.cpp                  |  83 +++++---
 indra/newview/llassetuploadqueue.cpp               |  83 ++++----
 indra/newview/llassetuploadresponders.cpp          |  81 ++++----
 indra/newview/llassetuploadresponders.h            |  28 ++-
 indra/newview/llclassifiedstatsresponder.cpp       |  13 +-
 indra/newview/llclassifiedstatsresponder.h         |   8 +-
 indra/newview/llestateinfomodel.cpp                |  10 +-
 indra/newview/lleventpoll.cpp                      |  45 +++--
 indra/newview/llfeaturemanager.cpp                 |  20 +-
 indra/newview/llfilepicker.cpp                     |  13 +-
 indra/newview/llfloaterabout.cpp                   |  40 ++--
 indra/newview/llfloateravatarpicker.cpp            |  11 +-
 indra/newview/llfloaterbuycurrencyhtml.cpp         |   3 +-
 indra/newview/llfloaterhelpbrowser.cpp             |   6 +-
 indra/newview/llfloatermodelpreview.cpp            |   4 +-
 indra/newview/llfloatermodelpreview.h              |   4 +-
 indra/newview/llfloatermodeluploadbase.cpp         |   2 +-
 indra/newview/llfloatermodeluploadbase.h           |   4 +-
 indra/newview/llfloaterobjectweights.cpp           |   2 +-
 indra/newview/llfloaterobjectweights.h             |   2 +-
 indra/newview/llfloaterregiondebugconsole.cpp      |  16 +-
 indra/newview/llfloaterregioninfo.cpp              |  25 +--
 indra/newview/llfloaterreporter.cpp                |  14 +-
 indra/newview/llfloaterscriptlimits.cpp            |  63 ++++--
 indra/newview/llfloaterscriptlimits.h              |  62 +++---
 indra/newview/llfloatersearch.cpp                  |   3 +-
 indra/newview/llfloatertos.cpp                     |  68 ++++---
 indra/newview/llfloaterurlentry.cpp                |  48 ++---
 indra/newview/llfloaterurlentry.h                  |   2 +-
 indra/newview/llfloaterwebcontent.cpp              |   7 +-
 indra/newview/llgroupmgr.cpp                       |  26 ++-
 indra/newview/llhomelocationresponder.cpp          |  35 ++--
 indra/newview/llhomelocationresponder.h            |   6 +-
 indra/newview/llimfloater.cpp                      |   7 +-
 indra/newview/llimpanel.cpp                        |   7 +-
 indra/newview/llimview.cpp                         |  30 ++-
 indra/newview/llinspectavatar.cpp                  |   8 +-
 indra/newview/llinventorymodel.cpp                 |  30 ++-
 indra/newview/llinventorymodel.h                   |   5 +-
 indra/newview/llinventorymodelbackgroundfetch.cpp  |  43 ++--
 indra/newview/llmarketplacefunctions.cpp           |  63 +++---
 indra/newview/llmediactrl.cpp                      |   5 +-
 indra/newview/llmediadataclient.cpp                |  52 +++--
 indra/newview/llmediadataclient.h                  |  29 ++-
 indra/newview/llmeshrepository.cpp                 | 140 ++++++-------
 indra/newview/llpanelclassified.cpp                |  10 +-
 indra/newview/llpanellandmarks.cpp                 |   2 +-
 indra/newview/llpanellandmarks.h                   |   2 +-
 indra/newview/llpanellogin.cpp                     |   4 +-
 indra/newview/llpanelpick.h                        |   2 +-
 indra/newview/llpanelplaceinfo.cpp                 |   6 +-
 indra/newview/llpanelplaceinfo.h                   |   2 +-
 indra/newview/llpanelplaces.cpp                    |   2 +-
 indra/newview/llpathfindingmanager.cpp             | 176 +++++++---------
 indra/newview/llpathfindingnavmesh.cpp             |   4 +-
 indra/newview/llpathfindingnavmesh.h               |   2 +-
 indra/newview/llproductinforequest.cpp             |  18 +-
 indra/newview/llremoteparcelrequest.cpp            |  17 +-
 indra/newview/llremoteparcelrequest.h              |   9 +-
 indra/newview/llspeakers.cpp                       |   8 +-
 indra/newview/lltexturefetch.cpp                   |  10 +-
 indra/newview/lltranslate.cpp                      |  18 +-
 indra/newview/lltranslate.h                        |   7 -
 indra/newview/lluploadfloaterobservers.cpp         |  20 +-
 indra/newview/lluploadfloaterobservers.h           |  19 +-
 indra/newview/llviewerdisplayname.cpp              |  14 +-
 indra/newview/llviewermedia.cpp                    | 122 ++++++-----
 indra/newview/llviewerobjectlist.cpp               |  24 +--
 indra/newview/llviewerparcelmedia.cpp              |   2 +-
 indra/newview/llviewerregion.cpp                   | 104 ++++++----
 indra/newview/llviewerstats.cpp                    |  19 +-
 indra/newview/llviewerwindow.cpp                   |   4 +-
 indra/newview/llvoavatarself.cpp                   |  45 ++---
 indra/newview/llvoicechannel.cpp                   |  21 +-
 indra/newview/llvoicevivox.cpp                     |  46 +++--
 indra/newview/llwebprofile.cpp                     |  53 ++---
 indra/newview/llwebsharing.cpp                     | 176 +++++++---------
 indra/newview/llwlhandlers.cpp                     |  27 ++-
 indra/newview/llwlhandlers.h                       |  14 +-
 indra/newview/llxmlrpctransaction.cpp              |   2 +-
 indra/newview/tests/llmediadataclient_test.cpp     |   8 +-
 indra/newview/tests/llremoteparcelrequest_test.cpp |  16 +-
 indra/newview/tests/lltranslate_test.cpp           |  12 +-
 indra/test/llassetuploadqueue_tut.cpp              |   4 +-
 indra/test/llblowfish_tut.cpp                      |   2 +-
 indra/test/llhttpnode_tut.cpp                      |   1 +
 indra/test/llsd_new_tut.cpp                        |  55 ++---
 indra/test/llsdtraits.h                            |   2 +-
 indra/test/message_tut.cpp                         |   3 +-
 indra/test/mock_http_client.h                      |  23 +--
 .../viewer_components/updater/llupdatechecker.cpp  |  18 +-
 indra/viewer_components/updater/llupdatechecker.h  |   7 +-
 136 files changed, 2537 insertions(+), 2027 deletions(-)
 delete mode 100644 indra/llcommon/llhttpstatuscodes.h
 create mode 100644 indra/llmessage/llhttpconstants.cpp
 create mode 100644 indra/llmessage/llhttpconstants.h
 delete mode 100644 indra/llmessage/llregionpresenceverifier.cpp
 delete mode 100644 indra/llmessage/llregionpresenceverifier.h
 delete mode 100644 indra/llmessage/tests/llregionpresenceverifier_test.cpp

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 5cce8ff2c4..31fac7caab 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -176,7 +176,6 @@ set(llcommon_HEADER_FILES
     llhandle.h
     llhash.h
     llheartbeat.h
-    llhttpstatuscodes.h
     llindexedqueue.h
     llinitparam.h
     llinstancetracker.h
diff --git a/indra/llcommon/llhttpstatuscodes.h b/indra/llcommon/llhttpstatuscodes.h
deleted file mode 100644
index 0173461dad..0000000000
--- a/indra/llcommon/llhttpstatuscodes.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/** 
- * @file llhttpstatuscodes.h
- * @brief Constants for HTTP status codes
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTP_STATUS_CODES_H
-#define LL_HTTP_STATUS_CODES_H
-
-#include "stdtypes.h"
-
-// Standard errors from HTTP spec:
-// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
-const S32 HTTP_CONTINUE = 100;
-const S32 HTTP_SWITCHING_PROTOCOLS = 101;
-
-// Success
-const S32 HTTP_OK = 200;
-const S32 HTTP_CREATED = 201;
-const S32 HTTP_ACCEPTED = 202;
-const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
-const S32 HTTP_NO_CONTENT = 204;
-const S32 HTTP_RESET_CONTENT = 205;
-const S32 HTTP_PARTIAL_CONTENT = 206;
-
-// Redirection
-const S32 HTTP_MULTIPLE_CHOICES = 300;
-const S32 HTTP_MOVED_PERMANENTLY = 301;
-const S32 HTTP_FOUND = 302;
-const S32 HTTP_SEE_OTHER = 303;
-const S32 HTTP_NOT_MODIFIED = 304;
-const S32 HTTP_USE_PROXY = 305;
-const S32 HTTP_TEMPORARY_REDIRECT = 307;
-
-// Client Error
-const S32 HTTP_BAD_REQUEST = 400;
-const S32 HTTP_UNAUTHORIZED = 401;
-const S32 HTTP_PAYMENT_REQUIRED = 402;
-const S32 HTTP_FORBIDDEN = 403;
-const S32 HTTP_NOT_FOUND = 404;
-const S32 HTTP_METHOD_NOT_ALLOWED = 405;
-const S32 HTTP_NOT_ACCEPTABLE = 406;
-const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
-const S32 HTTP_REQUEST_TIME_OUT = 408;
-const S32 HTTP_CONFLICT = 409;
-const S32 HTTP_GONE = 410;
-const S32 HTTP_LENGTH_REQUIRED = 411;
-const S32 HTTP_PRECONDITION_FAILED = 412;
-const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
-const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
-const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
-const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
-const S32 HTTP_EXPECTATION_FAILED = 417;
-
-// Server Error
-const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
-const S32 HTTP_NOT_IMPLEMENTED = 501;
-const S32 HTTP_BAD_GATEWAY = 502;
-const S32 HTTP_SERVICE_UNAVAILABLE = 503;
-const S32 HTTP_GATEWAY_TIME_OUT = 504;
-const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
-
-// We combine internal process errors with status codes
-// These status codes should not be sent over the wire
-//   and indicate something went wrong internally.
-// If you get these they are not normal.
-const S32 HTTP_INTERNAL_ERROR = 499;
-
-#endif
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 8276ec836a..9e4b92227e 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -126,7 +126,9 @@ public:
 	virtual UUID	asUUID() const				{ return LLUUID(); }
 	virtual Date	asDate() const				{ return LLDate(); }
 	virtual URI		asURI() const				{ return LLURI(); }
-	virtual Binary	asBinary() const			{ return std::vector<U8>(); }
+	virtual const Binary&	asBinary() const	{ static const std::vector<U8> empty; return empty; }
+
+	virtual const String& asStringRef() const { static const std::string empty; return empty; } 
 	
 	virtual bool has(const String&) const		{ return false; }
 	virtual LLSD get(const String&) const		{ return LLSD(); }
@@ -270,6 +272,7 @@ namespace
 		virtual LLSD::Date		asDate() const	{ return LLDate(mValue); }
 		virtual LLSD::URI		asURI() const	{ return LLURI(mValue); }
 		virtual int				size() const	{ return mValue.size(); }
+		virtual const LLSD::String&	asStringRef() const { return mValue; }
 	};
 	
 	LLSD::Integer	ImplString::asInteger() const
@@ -348,7 +351,7 @@ namespace
 	public:
 		ImplBinary(const LLSD::Binary& v) : Base(v) { }
 				
-		virtual LLSD::Binary	asBinary() const{ return mValue; }
+		virtual const LLSD::Binary&	asBinary() const{ return mValue; }
 	};
 
 
@@ -838,7 +841,9 @@ LLSD::String	LLSD::asString() const	{ return safe(impl).asString(); }
 LLSD::UUID		LLSD::asUUID() const	{ return safe(impl).asUUID(); }
 LLSD::Date		LLSD::asDate() const	{ return safe(impl).asDate(); }
 LLSD::URI		LLSD::asURI() const		{ return safe(impl).asURI(); }
-LLSD::Binary	LLSD::asBinary() const	{ return safe(impl).asBinary(); }
+const LLSD::Binary&	LLSD::asBinary() const	{ return safe(impl).asBinary(); }
+
+const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
 
 // const char * helpers
 LLSD::LLSD(const char* v) : impl(0)		{ ALLOC_LLSD_OBJECT;	assign(v); }
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 5eb69059ac..b9f490718c 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -249,7 +249,10 @@ public:
 		UUID	asUUID() const;
 		Date	asDate() const;
 		URI		asURI() const;
-		Binary	asBinary() const;
+		const Binary&	asBinary() const;
+
+		// asStringRef on any non-string type will return a ref to an empty string.
+		const String&	asStringRef() const;
 
 		operator Boolean() const	{ return asBoolean(); }
 		operator Integer() const	{ return asInteger(); }
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index ad4fce6f35..774d827762 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -873,7 +873,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 {
 /**
  * Undefined: '!'<br>
- * Boolean: 't' for true 'f' for false<br>
+ * Boolean: '1' for true '0' for false<br>
  * Integer: 'i' + 4 bytes network byte order<br>
  * Real: 'r' + 8 bytes IEEE double<br>
  * UUID: 'u' + 16 byte unsigned integer<br>
@@ -1260,13 +1260,38 @@ std::string LLSDNotationFormatter::escapeString(const std::string& in)
 
 // virtual
 S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
+{
+	S32 rv = format_impl(data, ostr, options, 0);
+	return rv;
+}
+
+S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const
 {
 	S32 format_count = 1;
+	std::string pre;
+	std::string post;
+
+	if (options & LLSDFormatter::OPTIONS_PRETTY)
+	{
+		for (U32 i = 0; i < level; i++)
+		{
+			pre += "    ";
+		}
+		post = "\n";
+	}
+
 	switch(data.type())
 	{
 	case LLSD::TypeMap:
 	{
+		if (0 != level) ostr << post << pre;
 		ostr << "{";
+		std::string inner_pre;
+		if (options & LLSDFormatter::OPTIONS_PRETTY)
+		{
+			inner_pre = pre + "    ";
+		}
+
 		bool need_comma = false;
 		LLSD::map_const_iterator iter = data.beginMap();
 		LLSD::map_const_iterator end = data.endMap();
@@ -1274,18 +1299,18 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 		{
 			if(need_comma) ostr << ",";
 			need_comma = true;
-			ostr << '\'';
+			ostr << post << inner_pre << '\'';
 			serialize_string((*iter).first, ostr);
 			ostr << "':";
-			format_count += format((*iter).second, ostr);
+			format_count += format_impl((*iter).second, ostr, options, level + 2);
 		}
-		ostr << "}";
+		ostr << post << pre << "}";
 		break;
 	}
 
 	case LLSD::TypeArray:
 	{
-		ostr << "[";
+		ostr << post << pre << "[";
 		bool need_comma = false;
 		LLSD::array_const_iterator iter = data.beginArray();
 		LLSD::array_const_iterator end = data.endArray();
@@ -1293,7 +1318,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 		{
 			if(need_comma) ostr << ",";
 			need_comma = true;
-			format_count += format(*iter, ostr);
+			format_count += format_impl(*iter, ostr, options, level + 1);
 		}
 		ostr << "]";
 		break;
@@ -1343,7 +1368,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 
 	case LLSD::TypeString:
 		ostr << '\'';
-		serialize_string(data.asString(), ostr);
+		serialize_string(data.asStringRef(), ostr);
 		ostr << '\'';
 		break;
 
@@ -1360,9 +1385,26 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
 	case LLSD::TypeBinary:
 	{
 		// *FIX: memory inefficient.
-		std::vector<U8> buffer = data.asBinary();
+		const std::vector<U8>& buffer = data.asBinary();
 		ostr << "b(" << buffer.size() << ")\"";
-		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
+		if(buffer.size())
+		{
+			if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY)
+			{
+				std::ios_base::fmtflags old_flags = ostr.flags();
+				ostr.setf( std::ios::hex, std::ios::basefield );
+				ostr << "0x";
+				for (int i = 0; i < buffer.size(); i++)
+				{
+					ostr << (int) buffer[i];
+				}
+				ostr.flags(old_flags);
+			}
+			else
+			{
+				ostr.write((const char*)&buffer[0], buffer.size());
+			}
+		}
 		ostr << "\"";
 		break;
 	}
@@ -1460,7 +1502,7 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
 
 	case LLSD::TypeString:
 		ostr.put('s');
-		formatString(data.asString(), ostr);
+		formatString(data.asStringRef(), ostr);
 		break;
 
 	case LLSD::TypeDate:
@@ -1478,9 +1520,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
 
 	case LLSD::TypeBinary:
 	{
-		// *FIX: memory inefficient.
 		ostr.put('b');
-		std::vector<U8> buffer = data.asBinary();
+		const std::vector<U8>& buffer = data.asBinary();
 		U32 size_nbo = htonl(buffer.size());
 		ostr.write((const char*)(&size_nbo), sizeof(U32));
 		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index e7a5507385..23a0c8cfb1 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -416,7 +416,8 @@ public:
 	typedef enum e_formatter_options_type
 	{
 		OPTIONS_NONE = 0,
-		OPTIONS_PRETTY = 1
+		OPTIONS_PRETTY = 1,
+		OPTIONS_PRETTY_BINARY = 2
 	} EFormatterOptions;
 
 	/** 
@@ -507,6 +508,17 @@ public:
 	 * @return Returns The number of LLSD objects fomatted out
 	 */
 	virtual S32 format(const LLSD& data, std::ostream& ostr, U32 options = LLSDFormatter::OPTIONS_NONE) const;
+
+protected:
+
+	/** 
+	 * @brief Implementation to format the data. This is called recursively.
+	 *
+	 * @param data The data to write.
+	 * @param ostr The destination stream for the data.
+	 * @return Returns The number of LLSD objects fomatted out
+	 */
+	S32 format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const;
 };
 
 
@@ -634,7 +646,7 @@ protected:
  *  </code>
  *
  * *NOTE - formerly this class inherited from its template parameter Formatter,
- * but all insnatiations passed in LLRefCount subclasses.  This conflicted with
+ * but all instantiations passed in LLRefCount subclasses.  This conflicted with
  * the auto allocation intended for this class template (demonstrated in the
  * example above).  -brad
  */
@@ -720,6 +732,18 @@ public:
 		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
 		return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
 	}
+	static S32 toPrettyNotation(const LLSD& sd, std::ostream& str)
+	{
+		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+		return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
+	}
+	static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str)
+	{
+		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+		return f->format(sd, str, 
+				LLSDFormatter::OPTIONS_PRETTY | 
+				LLSDFormatter::OPTIONS_PRETTY_BINARY);
+	}
 	static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes)
 	{
 		LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index cef743a7be..3ef7a7e4c1 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -168,8 +168,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
 		break;
 
 	case LLSD::TypeString:
-		if(data.asString().empty()) ostr << pre << "<string />" << post;
-		else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post;
+		if(data.asStringRef().empty()) ostr << pre << "<string />" << post;
+		else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post;
 		break;
 
 	case LLSD::TypeDate:
@@ -182,7 +182,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
 
 	case LLSD::TypeBinary:
 	{
-		LLSD::Binary buffer = data.asBinary();
+		const LLSD::Binary& buffer = data.asBinary();
 		if(buffer.empty())
 		{
 			ostr << pre << "<binary />" << post;
@@ -375,13 +375,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
 		{
 			break;
 		}
+		count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
+		if (!count)
 		{
-		
-			count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
-			if (!count)
-			{
-				break;
-			}
+			break;
 		}
 		status = XML_ParseBuffer(mParser, count, false);
 
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 6fe0bfc7d1..9ea831a771 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -31,7 +31,7 @@
 #include "_httpoprequest.h"
 #include "_httppolicy.h"
 
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 
 
 namespace LLCore
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 7db19b1841..5e703cd183 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -44,7 +44,7 @@
 #include "_httplibcurl.h"
 #include "_httpinternal.h"
 
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llproxy.h"
 
 namespace
@@ -479,6 +479,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 			curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
 			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
+			// *TODO: Should this be 'Keep-Alive' ?
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
 		}
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index fb2d43e3b0..b86e73c690 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -50,18 +50,21 @@ BOOL gSent = false;
 
 class LLCrashLoggerResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLCrashLoggerResponder);
 public:
 	LLCrashLoggerResponder() 
 	{
 	}
 
-	virtual void error(U32 status, const std::string& reason)
+protected:
+	virtual void httpFailure()
 	{
+		llwarns << dumpResponse() << llendl;
 		gBreak = true;
 	}
 
-	virtual void result(const LLSD& content)
-	{	
+	virtual void httpSuccess()
+	{
 		gBreak = true;
 		gSent = true;
 	}
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1a90c32fe4..181718f465 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -43,6 +43,7 @@ set(llmessage_SOURCE_FILES
     llhttpassetstorage.cpp
     llhttpclient.cpp
     llhttpclientadapter.cpp
+    llhttpconstants.cpp
     llhttpnode.cpp
     llhttpsender.cpp
     llinstantmessage.cpp
@@ -67,7 +68,6 @@ set(llmessage_SOURCE_FILES
     llpartdata.cpp
     llproxy.cpp
     llpumpio.cpp
-    llregionpresenceverifier.cpp
     llsdappservices.cpp
     llsdhttpserver.cpp
     llsdmessage.cpp
@@ -135,6 +135,7 @@ set(llmessage_HEADER_FILES
     llhttpclient.h
     llhttpclientinterface.h
     llhttpclientadapter.h
+    llhttpconstants.h
     llhttpnode.h
     llhttpnodeadapter.h
     llhttpsender.h
@@ -166,7 +167,6 @@ set(llmessage_HEADER_FILES
     llqueryflags.h
     llregionflags.h
     llregionhandle.h
-    llregionpresenceverifier.h
     llsdappservices.h
     llsdhttpserver.h
     llsdmessage.h
@@ -230,17 +230,15 @@ target_link_libraries(
 # tests
 if (LL_TESTS)
   SET(llmessage_TEST_SOURCE_FILES
-    # llhttpclientadapter.cpp
-    llmime.cpp
     llnamevalue.cpp
     lltrustedmessageservice.cpp
     lltemplatemessagedispatcher.cpp
-      llregionpresenceverifier.cpp
     )
   LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
 
   #    set(TEST_DEBUG on)
   set(test_libs
+    ${CURL_LIBRARIES}
     ${LLMESSAGE_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${LLVFS_LIBRARIES}
@@ -267,6 +265,8 @@ if (LL_TESTS)
 
   LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llmime "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
 endif (LL_TESTS)
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index f9e3ad26f7..87c4b5952c 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -126,7 +126,7 @@ namespace LLAvatarNameCache
 	// Erase expired names from cache
 	void eraseUnrefreshed();
 
-	bool expirationFromCacheControl(LLSD headers, F64 *expires);
+	bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
 }
 
 /* Sample response:
@@ -170,33 +170,31 @@ namespace LLAvatarNameCache
 
 class LLAvatarNameResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLAvatarNameResponder);
 private:
 	// need to store agent ids that are part of this request in case of
 	// an error, so we can flag them as unavailable
 	std::vector<LLUUID> mAgentIDs;
 
-	// Need the headers to look up Expires: and Retry-After:
-	LLSD mHeaders;
-	
 public:
 	LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
-	:	mAgentIDs(agent_ids),
-		mHeaders()
+	:	mAgentIDs(agent_ids)
 	{ }
 	
-	/*virtual*/ void completedHeader(U32 status, const std::string& reason, 
-		const LLSD& headers)
-	{
-		mHeaders = headers;
-	}
-
-	/*virtual*/ void result(const LLSD& content)
+protected:
+	/*virtual*/ void httpSuccess()
 	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		// Pull expiration out of headers if available
-		F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders);
+		F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders());
 		F64 now = LLFrameTimer::getTotalSeconds();
 
-		LLSD agents = content["agents"];
+		const LLSD& agents = content["agents"];
 		LLSD::array_const_iterator it = agents.beginArray();
 		for ( ; it != agents.endArray(); ++it)
 		{
@@ -226,7 +224,7 @@ public:
 		}
 
 		// Same logic as error response case
-		LLSD unresolved_agents = content["bad_ids"];
+		const LLSD& unresolved_agents = content["bad_ids"];
 		S32  num_unresolved = unresolved_agents.size();
 		if (num_unresolved > 0)
 		{
@@ -250,14 +248,13 @@ public:
                                  << LL_ENDL;
     }
 
-	/*virtual*/ void error(U32 status, const std::string& reason)
+	/*virtual*/ void httpFailure()
 	{
 		// If there's an error, it might be caused by PeopleApi,
 		// or when loading textures on startup and using a very slow 
 		// network, this query may time out.
 		// What we should do depends on whether or not we have a cached name
-		LL_WARNS("AvNameCache") << "LLAvatarNameResponder::error " << status << " " << reason
-								<< LL_ENDL;
+		LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL;
 
 		// Add dummy records for any agent IDs in this request that we do not have cached already
 		std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
@@ -748,7 +745,7 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
 	sCache[agent_id] = av_name;
 }
 
-F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
+F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
 {
 	F64 expires = 0.0;
 	if (expirationFromCacheControl(headers, &expires))
@@ -764,17 +761,25 @@ F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
 	}
 }
 
-bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires)
+bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *expires)
 {
 	bool fromCacheControl = false;
 	F64 now = LLFrameTimer::getTotalSeconds();
 
 	// Allow the header to override the default
-	LLSD cache_control_header = headers["cache-control"];
-	if (cache_control_header.isDefined())
+	std::string cache_control;
+	if (headers.has(HTTP_HEADER_CACHE_CONTROL))
+	{
+		cache_control = headers[HTTP_HEADER_CACHE_CONTROL].asString();
+	}
+	else if (headers.has(HTTP_HEADER_LOWER_CACHE_CONTROL))
+	{
+		cache_control = headers[HTTP_HEADER_LOWER_CACHE_CONTROL].asString();
+	}
+
+	if (!cache_control.empty())
 	{
 		S32 max_age = 0;
-		std::string cache_control = cache_control_header.asString();
 		if (max_age_from_cache_control(cache_control, &max_age))
 		{
 			*expires = now + (F64)max_age;
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 79f170f7c8..42c76fe058 100644
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -90,7 +90,7 @@ namespace LLAvatarNameCache
 
 	// Compute name expiration time from HTTP Cache-Control header,
 	// or return default value, in seconds from epoch.
-	F64 nameExpirationFromHeaders(LLSD headers);
+	F64 nameExpirationFromHeaders(const LLSD& headers);
 
 	void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
 }
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 47041a2880..1269b6bc5d 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -49,6 +49,7 @@
 #include "llproxy.h"
 #include "llsdserialize.h"
 #include "llstl.h"
+#include "llstring.h"
 #include "llthread.h"
 #include "lltimer.h"
 
@@ -98,7 +99,7 @@ void check_curl_code(CURLcode code)
 	{
 		// linux appears to throw a curl error once per session for a bad initialization
 		// at a pretty random time (when enabling cookies).
-		llinfos << "curl error detected: " << curl_easy_strerror(code) << llendl;
+		LL_WARNS("curl") << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL;
 	}
 }
 
@@ -108,7 +109,7 @@ void check_curl_multi_code(CURLMcode code)
 	{
 		// linux appears to throw a curl error once per session for a bad initialization
 		// at a pretty random time (when enabling cookies).
-		llinfos << "curl multi error detected: " << curl_multi_strerror(code) << llendl;
+		LL_WARNS("curl") << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL;
 	}
 }
 
@@ -133,6 +134,7 @@ std::string LLCurl::getVersionString()
 //////////////////////////////////////////////////////////////////////////////
 
 LLCurl::Responder::Responder()
+	: mHTTPMethod(HTTP_INVALID), mStatus(HTTP_INTERNAL_ERROR)
 {
 }
 
@@ -142,22 +144,30 @@ LLCurl::Responder::~Responder()
 }
 
 // virtual
-void LLCurl::Responder::errorWithContent(
-	U32 status,
-	const std::string& reason,
-	const LLSD&)
+void LLCurl::Responder::httpFailure()
 {
-	error(status, reason);
+	LL_WARNS("curl") << dumpResponse() << LL_ENDL;
 }
 
-// virtual
-void LLCurl::Responder::error(U32 status, const std::string& reason)
+std::string LLCurl::Responder::dumpResponse() const 
 {
-	llinfos << mURL << " [" << status << "]: " << reason << llendl;
+	std::ostringstream s;
+	s << "[" << httpMethodAsVerb(mHTTPMethod) << ":" << mURL << "] "
+	  << "[status:" << mStatus << "] "
+	  << "[reason:" << mReason << "] ";
+
+	if (mResponseHeaders.has(HTTP_HEADER_CONTENT_TYPE))
+	{
+		s << "[content-type:" << mResponseHeaders[HTTP_HEADER_CONTENT_TYPE] << "] ";
+	}
+
+	s << "[content:" << mContent << "]";
+
+	return s.str();
 }
 
 // virtual
-void LLCurl::Responder::result(const LLSD& content)
+void LLCurl::Responder::httpSuccess()
 {
 }
 
@@ -166,44 +176,124 @@ void LLCurl::Responder::setURL(const std::string& url)
 	mURL = url;
 }
 
+void LLCurl::Responder::successResult(const LLSD& content)
+{
+	setResult(HTTP_OK, "", content);
+	httpSuccess();
+}
+
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+	setResult(status, reason, content);
+	httpFailure();
+}
+
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+	setResult(status, reason, content);
+	httpCompleted();
+}
+
+void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+	mStatus = status;
+	mReason = reason;
+	mContent = content;
+}
+
+void LLCurl::Responder::setHTTPMethod(EHTTPMethod method)
+{
+	mHTTPMethod = method;
+}
+
+void LLCurl::Responder::setResponseHeader(const std::string& header, const std::string& value)
+{
+	mResponseHeaders[header] = value;
+}
+
+const std::string& LLCurl::Responder::getResponseHeader(const std::string& header, bool check_lower) const
+{
+	if (mResponseHeaders.has(header))
+	{
+		return mResponseHeaders[header].asStringRef();
+	}
+	if (check_lower)
+	{
+		std::string header_lower(header);
+		LLStringUtil::toLower(header_lower);
+		if (mResponseHeaders.has(header_lower))
+		{
+			return mResponseHeaders[header_lower].asStringRef();
+		}
+	}
+	static const std::string empty;
+	return empty;
+}
+
+bool LLCurl::Responder::hasResponseHeader(const std::string& header, bool check_lower) const
+{
+	if (mResponseHeaders.has(header)) return true;
+	if (check_lower)
+	{
+		std::string header_lower(header);
+		LLStringUtil::toLower(header_lower);
+		return mResponseHeaders.has(header_lower);
+	}
+	return false;
+}
+
 // virtual
 void LLCurl::Responder::completedRaw(
-	U32 status,
-	const std::string& reason,
 	const LLChannelDescriptors& channels,
 	const LLIOPipe::buffer_ptr_t& buffer)
 {
-	LLSD content;
 	LLBufferStream istr(channels, buffer.get());
-	const bool emit_errors = false;
-	if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(content, istr, emit_errors))
+	const bool emit_parse_errors = false;
+
+	std::string debug_body("(empty)");
+	bool parsed=true;
+	if (EOF == istr.peek())
+	{
+		parsed=false;
+	}
+	// Try to parse body as llsd, no matter what 'Content-Type' says.
+	else if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(mContent, istr, emit_parse_errors))
+	{
+		parsed=false;
+		char body[1025]; 
+		body[1024] = '\0';
+		istr.seekg(0, std::ios::beg);
+		istr.get(body,1024);
+		if (strlen(body) > 0)
+		{
+			mContent = body;
+			debug_body = body;
+		}
+	}
+
+	// Only emit an warning if we failed to parse when 'Content-Type' == 'application/llsd+xml'
+	if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_HEADER_CONTENT_TYPE)))
 	{
-		llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
-		content["reason"] = reason;
+		llwarns << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " 
+			<< "(" << mReason << ") body: " << debug_body << llendl;
 	}
 
-	completed(status, reason, content);
+	httpCompleted();
 }
 
 // virtual
-void LLCurl::Responder::completed(U32 status, const std::string& reason, const LLSD& content)
+void LLCurl::Responder::httpCompleted()
 {
-	if (isGoodStatus(status))
+	if (isGoodStatus())
 	{
-		result(content);
+		httpSuccess();
 	}
 	else
 	{
-		errorWithContent(status, reason, content);
+		httpFailure();
 	}
 }
 
-//virtual
-void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, const LLSD& content)
-{
-
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 std::set<CURL*> LLCurl::Easy::sFreeHandles;
@@ -287,7 +377,8 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
 	if (!easy->mCurlEasyHandle)
 	{
 		// this can happen if we have too many open files (fails in c-ares/ares_init.c)
-		llwarns << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
+		LL_WARNS("curl") << "allocEasyHandle() returned NULL! Easy handles: " 
+			<< gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
 		delete easy;
 		return NULL;
 	}
@@ -312,10 +403,14 @@ LLCurl::Easy::~Easy()
 	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
 	LL_CHECK_MEMORY
 	if (mResponder && LLCurl::sNotQuitting) //aborted
-	{	
-		std::string reason("Request timeout, aborted.") ;
-		mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort
-			reason, mChannels, mOutput);		
+	{
+		// HTTP_REQUEST_TIME_OUT, timeout, abort
+		// *TODO: This looks like improper use of the 408 status code.
+		// See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9
+		// This status code should be returned by the *server* when:
+		// "The client did not produce a request within the time that the server was prepared to wait."
+		mResponder->setResult(HTTP_REQUEST_TIME_OUT, "Request timeout, aborted.");
+		mResponder->completedRaw(mChannels, mOutput);
 		LL_CHECK_MEMORY
 	}
 	mResponder = NULL;
@@ -379,9 +474,9 @@ void LLCurl::Easy::getTransferInfo(LLCurl::TransferInfo* info)
 	check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload));
 }
 
-U32 LLCurl::Easy::report(CURLcode code)
+S32 LLCurl::Easy::report(CURLcode code)
 {
-	U32 responseCode = 0;	
+	S32 responseCode = 0;
 	std::string responseReason;
 	
 	if (code == CURLE_OK)
@@ -391,14 +486,15 @@ U32 LLCurl::Easy::report(CURLcode code)
 	}
 	else
 	{
-		responseCode = 499;
+		responseCode = HTTP_INTERNAL_ERROR;
 		responseReason = strerror(code) + " : " + mErrorBuffer;
 		setopt(CURLOPT_FRESH_CONNECT, TRUE);
 	}
 
 	if (mResponder)
 	{	
-		mResponder->completedRaw(responseCode, responseReason, mChannels, mOutput);
+		mResponder->setResult(responseCode, responseReason);
+		mResponder->completedRaw(mChannels, mOutput);
 		mResponder = NULL;
 	}
 	
@@ -435,9 +531,31 @@ void LLCurl::Easy::setoptString(CURLoption option, const std::string& value)
 	check_curl_code(result);
 }
 
+void LLCurl::Easy::slist_append(const std::string& header, const std::string& value)
+{
+	std::string pair(header);
+	if (value.empty())
+	{
+		pair += ":";
+	}
+	else
+	{
+		pair += ": ";
+		pair += value;
+	}
+	slist_append(pair.c_str());
+}
+
 void LLCurl::Easy::slist_append(const char* str)
 {
-	mHeaders = curl_slist_append(mHeaders, str);
+	if (str)
+	{
+		mHeaders = curl_slist_append(mHeaders, str);
+		if (!mHeaders)
+		{
+			llwarns << "curl_slist_append() call returned NULL appending " << str << llendl;
+		}
+	}
 }
 
 size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data)
@@ -524,8 +642,9 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 
 	if (!post)
 	{
-		slist_append("Connection: keep-alive");
-		slist_append("Keep-alive: 300");
+		// *TODO: Should this be set to 'Keep-Alive' ?
+		slist_append(HTTP_HEADER_CONNECTION, "keep-alive");
+		slist_append(HTTP_HEADER_KEEP_ALIVE, "300");
 		// Accept and other headers
 		for (std::vector<std::string>::const_iterator iter = headers.begin();
 			 iter != headers.end(); ++iter)
@@ -804,7 +923,7 @@ S32 LLCurl::Multi::process()
 		++processed;
 		if (msg->msg == CURLMSG_DONE)
 		{
-			U32 response = 0;
+			S32 response = 0;
 			Easy* easy = NULL ;
 
 			{
@@ -823,7 +942,7 @@ S32 LLCurl::Multi::process()
 			}
 			else
 			{
-				response = 499;
+				response = HTTP_INTERNAL_ERROR;
 				//*TODO: change to llwarns
 				llerrs << "cleaned up curl request completed!" << llendl;
 			}
@@ -1122,13 +1241,13 @@ bool LLCurlRequest::getByteRange(const std::string& url,
 	easy->setopt(CURLOPT_HTTPGET, 1);
 	if (length > 0)
 	{
-		std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1);
-		easy->slist_append(range.c_str());
+		std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
+		easy->slist_append(HTTP_HEADER_RANGE, range);
 	}
 	else if (offset > 0)
 	{
-		std::string range = llformat("Range: bytes=%d-", offset);
-		easy->slist_append(range.c_str());
+		std::string range = llformat("bytes=%d-", offset);
+		easy->slist_append(HTTP_HEADER_RANGE, range);
 	}
 	easy->setHeaders();
 	bool res = addEasy(easy);
@@ -1155,7 +1274,7 @@ bool LLCurlRequest::post(const std::string& url,
 	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
 	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
 
-	easy->slist_append("Content-Type: application/llsd+xml");
+	easy->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	easy->setHeaders();
 
 	lldebugs << "POSTING: " << bytes << " bytes." << llendl;
@@ -1183,7 +1302,7 @@ bool LLCurlRequest::post(const std::string& url,
 	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
 	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
 
-	easy->slist_append("Content-Type: application/octet-stream");
+	easy->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
 	easy->setHeaders();
 
 	lldebugs << "POSTING: " << bytes << " bytes." << llendl;
@@ -1555,6 +1674,14 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void*
 	}
 }
 
+void LLCurlEasyRequest::slist_append(const std::string& header, const std::string& value)
+{
+	if (isValid() && mEasy)
+	{
+		mEasy->slist_append(header, value);
+	}
+}
+
 void LLCurlEasyRequest::slist_append(const char* str)
 {
 	if (isValid() && mEasy)
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 7bcf61e233..c72e1e493a 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -39,6 +39,7 @@
 #include <curl/curl.h> // TODO: remove dependency
 
 #include "llbuffer.h"
+#include "llhttpconstants.h"
 #include "lliopipe.h"
 #include "llsd.h"
 #include "llthread.h"
@@ -77,59 +78,92 @@ public:
 		Responder();
 		virtual ~Responder();
 
-		/**
-		 * @brief return true if the status code indicates success.
-		 */
-		static bool isGoodStatus(U32 status)
+		virtual bool followRedir() 
 		{
-			return((200 <= status) && (status < 300));
+			return false;
 		}
-		
-		virtual void errorWithContent(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
-			//< called by completed() on bad status 
-
-		virtual void error(U32 status, const std::string& reason);
-			//< called by default error(status, reason, content)
-		
-		virtual void result(const LLSD& content);
-			//< called by completed for good status codes.
 
+		/**
+		 * @brief return true if the status code indicates success.
+		 */
+		bool isGoodStatus() const { return isHttpGoodStatus(mStatus); }
+
+		S32 getStatus() const { return mStatus; }
+		const std::string& getReason() const { return mReason; }
+		const LLSD& getContent() const { return mContent; }
+		bool hasResponseHeader(const std::string& header, bool check_lower=false) const;
+		const std::string& getResponseHeader(const std::string& header, bool check_lower=true) const;
+		const LLSD& getResponseHeaders() const { return mResponseHeaders; }
+		const std::string& getURL() const { return mURL; }
+		EHTTPMethod getHTTPMethod() const { return mHTTPMethod; }
+
+		// This formats response information for use in log spam.  Includes content spam.
+		std::string dumpResponse() const;
+
+		// Allows direct triggering of success/error with different results.
+		void completeResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+		void successResult(const LLSD& content);
+		void failureResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+
+		// The default implementation will try to parse body content as an LLSD, however
+		// it should not spam about parsing failures unless the server sent a
+		// Content-Type: application/llsd+xml header.
 		virtual void completedRaw(
-			U32 status,
-			const std::string& reason,
 			const LLChannelDescriptors& channels,
 			const LLIOPipe::buffer_ptr_t& buffer);
 			/**< Override point for clients that may want to use this
 			   class when the response is some other format besides LLSD
 			*/
+			
 
-		virtual void completed(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
-			/**< The default implemetnation calls
+		// The http* methods are not public since these should be triggered internally
+		// after status, reason, content, etc have been set.
+		// If you need to trigger a completion method, use the *Result methods, above.
+	protected:
+		// These methods are the preferred way to process final results.
+		// By default, when one of these is called the following information will be resolved:
+		// * HTTP status code - getStatus()
+		// * Reason string - getReason()
+		// * Content - getContent()
+		// * Response Headers - getResponseHeaders()
+
+		// By default, httpSuccess is triggered whenever httpCompleted is called with a 2xx status code.
+		virtual void httpSuccess();
+			//< called by completed for good status codes.
+
+		// By default, httpFailure is triggered whenever httpCompleted is called with a non-2xx status code.
+		virtual void httpFailure();
+			//< called by httpCompleted() on bad status 
+
+		// httpCompleted does not generally need to be overridden, unless
+		// you don't care about the status code (which determine httpFailure or httpSuccess)
+		// or if you want to re-interpret what a 'good' vs' bad' status code is.
+		virtual void httpCompleted();
+			/**< The default implementation calls
 				either:
-				* result(), or
-				* error() 
+				* httpSuccess(), or
+				* httpFailure() 
 			*/
-			
-			// Override to handle parsing of the header only.  Note: this is the only place where the contents
-			// of the header can be parsed.  In the ::completed call above only the body is contained in the LLSD.
-			virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
-
-			// Used internally to set the url for debugging later.
-			void setURL(const std::string& url);
 
-			virtual bool followRedir() 
-			{
-				return false;
-			}
+	public:
+		void setHTTPMethod(EHTTPMethod method);
+		void setURL(const std::string& url);
+		void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+		void setResponseHeader(const std::string& header, const std::string& value);
 
 	private:
+		// These can be accessed by the get* methods.  Treated as 'read-only' during completion handlers.
+		EHTTPMethod mHTTPMethod;
 		std::string mURL;
+		LLSD mResponseHeaders;
+
+	protected:
+		// These should also generally be treated as 'read-only' during completion handlers
+		// and should be accessed by the get* methods.  The exception to this rule would
+		// be when overriding the completedRaw method in preparation for calling httpCompleted().
+		S32 mStatus;
+		std::string mReason;
+		LLSD mContent;
 	};
 	typedef LLPointer<Responder>	ResponderPtr;
 
@@ -225,10 +259,11 @@ public:
 	// Copies the string so that it is guaranteed to stick around
 	void setoptString(CURLoption option, const std::string& value);
 
+	void slist_append(const std::string& header, const std::string& value);
 	void slist_append(const char* str);
 	void setHeaders();
 
-	U32 report(CURLcode);
+	S32 report(CURLcode);
 	void getTransferInfo(LLCurl::TransferInfo* info);
 
 	void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false);
@@ -484,6 +519,7 @@ public:
 	void setWriteCallback(curl_write_callback callback, void* userdata);
 	void setReadCallback(curl_read_callback callback, void* userdata);
 	void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
+	void slist_append(const std::string& header, const std::string& value);
 	void slist_append(const char* str);
 	void sendRequest(const std::string& url);
 	void requestComplete();
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index 7dcf160c9b..e841c8e3ed 100644
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -51,13 +51,6 @@ const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f;
 
 const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096;
 
-const S32 HTTP_OK = 200;
-const S32 HTTP_PUT_OK = 201;
-const S32 HTTP_NO_CONTENT = 204;
-const S32 HTTP_MISSING = 404;
-const S32 HTTP_SERVER_BAD_GATEWAY = 502;
-const S32 HTTP_SERVER_TEMP_UNAVAILABLE = 503;
-
 /////////////////////////////////////////////////////////////////////////////////
 // LLTempAssetData
 // An asset not stored on central asset store, but on a simulator node somewhere.
@@ -952,7 +945,7 @@ void LLHTTPAssetStorage::checkForTimeouts()
 			{
 				if (curl_msg->data.result == CURLE_OK && 
 					(   curl_result == HTTP_OK 
-					 || curl_result == HTTP_PUT_OK 
+					 || curl_result == HTTP_CREATED
 					 || curl_result == HTTP_NO_CONTENT))
 				{
 					llinfos << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << llendl;
@@ -963,8 +956,8 @@ void LLHTTPAssetStorage::checkForTimeouts()
 				}
 				else if (curl_msg->data.result == CURLE_COULDNT_CONNECT ||
 						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
-						curl_result == HTTP_SERVER_BAD_GATEWAY ||
-						curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)
+						curl_result == HTTP_BAD_GATEWAY ||
+						curl_result == HTTP_SERVICE_UNAVAILABLE)
 				{
 					llwarns << "Re-requesting upload for " << req->getUUID() << ".  Received upload error to " << req->mURLBuffer <<
 						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;
@@ -985,8 +978,8 @@ void LLHTTPAssetStorage::checkForTimeouts()
 
 				if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT ||
 						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
-						curl_result == HTTP_SERVER_BAD_GATEWAY ||
-						curl_result == HTTP_SERVER_TEMP_UNAVAILABLE))
+						curl_result == HTTP_BAD_GATEWAY ||
+						curl_result == HTTP_SERVICE_UNAVAILABLE))
 				{
 					// shared upload finished callback
 					// in the base class, this is called from processUploadComplete
@@ -1018,7 +1011,7 @@ void LLHTTPAssetStorage::checkForTimeouts()
 					llwarns << "Failure downloading " << req->mURLBuffer << 
 						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;
 
-					xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
+					xfer_result = (curl_result == HTTP_NOT_FOUND) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
 
 					if (req->mVFile)
 					{
@@ -1240,7 +1233,7 @@ S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asse
 		}
 		else
 		{
-			xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
+			xfer_result = curl_result == HTTP_NOT_FOUND ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
 			llinfos << "Failure downloading " << req.mURLBuffer << 
 				" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;
 		}
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 0c325a68aa..a4a1f02cd3 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -54,7 +54,7 @@ namespace
 	{
 	public:
 		LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder)
-			: LLURLRequestComplete(), mResponder(responder), mStatus(499),
+			: LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR),
 			  mReason("LLURLRequest complete w/no status")
 		{
 		}
@@ -63,7 +63,7 @@ namespace
 		{
 		}
 
-		virtual void httpStatus(U32 status, const std::string& reason)
+		virtual void httpStatus(S32 status, const std::string& reason)
 		{
 			LLURLRequestComplete::httpStatus(status,reason);
 
@@ -74,30 +74,33 @@ namespace
 		virtual void complete(const LLChannelDescriptors& channels,
 							  const buffer_ptr_t& buffer)
 		{
+			// *TODO: Re-interpret mRequestStatus codes?
+			//        Would like to detect curl errors, such as
+			//        connection errors, write erros, etc.
 			if (mResponder.get())
 			{
-				// Allow clients to parse headers before we attempt to parse
-				// the body and provide completed/result/error calls.
-				mResponder->completedHeader(mStatus, mReason, mHeaderOutput);
-				mResponder->completedRaw(mStatus, mReason, channels, buffer);
+				mResponder->setResult(mStatus, mReason);
+				mResponder->completedRaw(channels, buffer);
 			}
 		}
 		virtual void header(const std::string& header, const std::string& value)
 		{
-			mHeaderOutput[header] = value;
+			if (mResponder.get())
+			{
+				mResponder->setResponseHeader(header, value);
+			}
 		}
 
 	private:
 		LLCurl::ResponderPtr mResponder;
-		U32 mStatus;
+		S32 mStatus;
 		std::string mReason;
-		LLSD mHeaderOutput;
 	};
 	
 	class Injector : public LLIOPipe
 	{
 	public:
-		virtual const char* contentType() = 0;
+		virtual const std::string& contentType() = 0;
 	};
 
 	class LLSDInjector : public Injector
@@ -106,7 +109,7 @@ namespace
 		LLSDInjector(const LLSD& sd) : mSD(sd) {}
 		virtual ~LLSDInjector() {}
 
-		const char* contentType() { return "application/llsd+xml"; }
+		const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -126,7 +129,7 @@ namespace
 		RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {}
 		virtual ~RawInjector() {delete mData;}
 
-		const char* contentType() { return "application/octet-stream"; }
+		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -147,7 +150,7 @@ namespace
 		FileInjector(const std::string& filename) : mFilename(filename) {}
 		virtual ~FileInjector() {}
 
-		const char* contentType() { return "application/octet-stream"; }
+		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -180,7 +183,7 @@ namespace
 		VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {}
 		virtual ~VFileInjector() {}
 
-		const char* contentType() { return "application/octet-stream"; }
+		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
 
 		virtual EStatus process_impl(const LLChannelDescriptors& channels,
 			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -213,7 +216,7 @@ void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback cal
 
 static void request(
 	const std::string& url,
-	LLURLRequest::ERequestAction method,
+	EHTTPMethod method,
 	Injector* body_injector,
 	LLCurl::ResponderPtr responder,
 	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
@@ -222,7 +225,11 @@ static void request(
 {
 	if (!LLHTTPClient::hasPump())
 	{
-		responder->completed(U32_MAX, "No pump", LLSD());
+		if (responder)
+		{
+			responder->completeResult(HTTP_INTERNAL_ERROR, "No pump");
+		}
+		delete body_injector;
 		return;
 	}
 	LLPumpIO::chain_t chain;
@@ -230,20 +237,24 @@ static void request(
 	LLURLRequest* req = new LLURLRequest(method, url);
 	if(!req->isValid())//failed
 	{
-		delete req ;
-		return ;
+		if (responder)
+		{
+			responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure");
+		}
+		delete req;
+		delete body_injector;
+		return;
 	}
 
 	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
 
 	
-	lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "
-		<< headers << llendl;
+	LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;
 
 	// Insert custom headers if the caller sent any
 	if (headers.isMap())
 	{
-		if (headers.has("Cookie"))
+		if (headers.has(HTTP_HEADER_COOKIE))
 		{
 			req->allowCookies();
 		}
@@ -253,62 +264,56 @@ static void request(
 
         for (; iter != end; ++iter)
         {
-            std::ostringstream header;
             //if the header is "Pragma" with no value
             //the caller intends to force libcurl to drop
             //the Pragma header it so gratuitously inserts
             //Before inserting the header, force libcurl
             //to not use the proxy (read: llurlrequest.cpp)
-			static const std::string PRAGMA("Pragma");
-			if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
+			if ((iter->first == HTTP_HEADER_PRAGMA) && (iter->second.asString().empty()))
             {
                 req->useProxy(false);
             }
-            header << iter->first << ": " << iter->second.asString() ;
-            lldebugs << "header = " << header.str() << llendl;
-            req->addHeader(header.str().c_str());
+            LL_DEBUGS("LLHTTPClient") << "header = " << iter->first 
+                << ": " << iter->second.asString() << LL_ENDL;
+            req->addHeader(iter->first, iter->second.asString());
         }
     }
 
 	// Check to see if we have already set Accept or not. If no one
 	// set it, set it to application/llsd+xml since that's what we
 	// almost always want.
-	if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST )
+	if( method != HTTP_PUT && method != HTTP_POST )
 	{
-		static const std::string ACCEPT("Accept");
-		if(!headers.has(ACCEPT))
+		if(!headers.has(HTTP_HEADER_ACCEPT))
 		{
-			req->addHeader("Accept: application/llsd+xml");
+			req->addHeader(HTTP_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
 		}
 	}
 
 	if (responder)
 	{
 		responder->setURL(url);
+		responder->setHTTPMethod(method);
 	}
 
 	req->setCallback(new LLHTTPClientURLAdaptor(responder));
 
-	if (method == LLURLRequest::HTTP_POST  &&  gMessageSystem)
+	if (method == HTTP_POST  &&  gMessageSystem)
 	{
-		req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d",
-								gMessageSystem->mPort).c_str());
+		req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
+								gMessageSystem->mPort));
    	}
 
-	if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
+	if (method == HTTP_PUT || method == HTTP_POST)
 	{
-		static const std::string CONTENT_TYPE("Content-Type");
-		if(!headers.has(CONTENT_TYPE))
+		if(!headers.has(HTTP_HEADER_CONTENT_TYPE))
 		{
 			// If the Content-Type header was passed in, it has
 			// already been added as a header through req->addHeader
 			// in the loop above. We defer to the caller's wisdom, but
 			// if they did not specify a Content-Type, then ask the
 			// injector.
-			req->addHeader(
-				llformat(
-					"Content-Type: %s",
-					body_injector->contentType()).c_str());
+			req->addHeader(HTTP_HEADER_CONTENT_TYPE, body_injector->contentType());
 		}
    		chain.push_back(LLIOPipe::ptr_t(body_injector));
 	}
@@ -331,9 +336,9 @@ void LLHTTPClient::getByteRange(
 	if(offset > 0 || bytes > 0)
 	{
 		std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
-		headers["Range"] = range;
+		headers[HTTP_HEADER_RANGE] = range;
 	}
-    request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers);
+    request(url,HTTP_GET, NULL, responder, timeout, headers);
 }
 
 void LLHTTPClient::head(
@@ -342,16 +347,16 @@ void LLHTTPClient::head(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers);
+	request(url, HTTP_HEAD, NULL, responder, timeout, headers);
 }
 
 void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers);
+	request(url, HTTP_GET, NULL, responder, timeout, headers);
 }
 void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers);
+	request(url, HTTP_HEAD, NULL, responder, timeout, headers);
 }
 void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout)
 {
@@ -392,7 +397,7 @@ public:
 		return content;
 	}
 
-	std::string asString()
+	const std::string& asString()
 	{
 		return mBuffer;
 	}
@@ -421,7 +426,7 @@ private:
   */
 static LLSD blocking_request(
 	const std::string& url,
-	LLURLRequest::ERequestAction method,
+	EHTTPMethod method,
 	const LLSD& body,
 	const LLSD& headers = LLSD(),
 	const F32 timeout = 5
@@ -464,11 +469,11 @@ static LLSD blocking_request(
 	}
 	
 	// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
-	if (method == LLURLRequest::HTTP_GET)
+	if (method == HTTP_GET)
 	{
 		curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
 	}
-	else if (method == LLURLRequest::HTTP_POST)
+	else if (method == HTTP_POST)
 	{
 		curl_easy_setopt(curlp, CURLOPT_POST, 1);
 		//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
@@ -477,18 +482,20 @@ static LLSD blocking_request(
 		body_str = ostr.str();
 		curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
 		//copied from PHP libs, correct?
-		headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
+		headers_list = curl_slist_append(headers_list, 
+				llformat("%s: %s", HTTP_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
 
 		// copied from llurlrequest.cpp
 		// it appears that apache2.2.3 or django in etch is busted. If
 		// we do not clear the expect header, we get a 500. May be
 		// limited to django/mod_wsgi.
-		headers_list = curl_slist_append(headers_list, "Expect:");
+		headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_HEADER_EXPECT.c_str()).c_str());
 	}
 	
 	// * Do the action using curl, handle results
 	lldebugs << "HTTP body: " << body_str << llendl;
-	headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
+	headers_list = curl_slist_append(headers_list,
+				llformat("%s: %s", HTTP_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
 	CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
 	if ( curl_result != CURLE_OK )
 	{
@@ -497,11 +504,11 @@ static LLSD blocking_request(
 
 	LLSD response = LLSD::emptyMap();
 	S32 curl_success = curl_easy_perform(curlp);
-	S32 http_status = 499;
+	S32 http_status = HTTP_INTERNAL_ERROR;
 	curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
 	response["status"] = http_status;
 	// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
-	if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
+	if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) )
 	{
 		// We expect 404s, don't spam for them.
 		llwarns << "CURL REQ URL: " << url << llendl;
@@ -531,12 +538,12 @@ static LLSD blocking_request(
 
 LLSD LLHTTPClient::blockingGet(const std::string& url)
 {
-	return blocking_request(url, LLURLRequest::HTTP_GET, LLSD());
+	return blocking_request(url, HTTP_GET, LLSD());
 }
 
 LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
 {
-	return blocking_request(url, LLURLRequest::HTTP_POST, body);
+	return blocking_request(url, HTTP_POST, body);
 }
 
 void LLHTTPClient::put(
@@ -546,7 +553,7 @@ void LLHTTPClient::put(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+	request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
 }
 
 void LLHTTPClient::post(
@@ -556,7 +563,7 @@ void LLHTTPClient::post(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
+	request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
 }
 
 void LLHTTPClient::postRaw(
@@ -567,7 +574,7 @@ void LLHTTPClient::postRaw(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
+	request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
 }
 
 void LLHTTPClient::postFile(
@@ -577,7 +584,7 @@ void LLHTTPClient::postFile(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout, headers);
+	request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers);
 }
 
 void LLHTTPClient::postFile(
@@ -588,7 +595,7 @@ void LLHTTPClient::postFile(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
+	request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
 }
 
 // static
@@ -598,7 +605,7 @@ void LLHTTPClient::del(
 	const LLSD& headers,
 	const F32 timeout)
 {
-	request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout, headers);
+	request(url, HTTP_DELETE, NULL, responder, timeout, headers);
 }
 
 // static
@@ -610,8 +617,8 @@ void LLHTTPClient::move(
 	const F32 timeout)
 {
 	LLSD headers = hdrs;
-	headers["Destination"] = destination;
-	request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers);
+	headers[HTTP_HEADER_DESTINATION] = destination;
+	request(url, HTTP_MOVE, NULL, responder, timeout, headers);
 }
 
 
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index f5d7a9abb6..aaa31e36fc 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -35,16 +35,19 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo
 {
 	LLSD empty_pragma_header;
 	// Pragma is required to stop curl adding "no-cache"
-	// Space is required to stop llurlrequest from turnning off proxying
-	empty_pragma_header["Pragma"] = " "; 
+	// Space is required to stop llurlrequest from turning off proxying
+	empty_pragma_header[HTTP_HEADER_PRAGMA] = " "; 
 	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
 
 void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) 
 {
 	LLSD empty_pragma_header = headers;
-	// as above
-	empty_pragma_header["Pragma"] = " ";
+	if (!empty_pragma_header.has(HTTP_HEADER_PRAGMA))
+	{
+		// as above
+		empty_pragma_header[HTTP_HEADER_PRAGMA] = " ";
+	}
 	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
 
@@ -53,3 +56,18 @@ void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::
 	LLHTTPClient::put(url, body, responder);
 }
 
+void LLHTTPClientAdapter::put(
+		const std::string& url,
+		const LLSD& body,
+		LLCurl::ResponderPtr responder,
+		const LLSD& headers)
+{
+	LLHTTPClient::put(url, body, responder, headers);
+}
+
+void LLHTTPClientAdapter::del(
+	const std::string& url,
+	LLCurl::ResponderPtr responder)
+{
+	LLHTTPClient::del(url, responder);
+}
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index aae6426a59..270282c66f 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -37,6 +37,14 @@ public:
 	virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
 	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
 	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
+	virtual void put(
+		const std::string& url,
+		const LLSD& body,
+		LLCurl::ResponderPtr responder,
+		const LLSD& headers);
+	virtual void del(
+		const std::string& url,
+		LLCurl::ResponderPtr responder);
 };
 
 #endif
diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp
new file mode 100644
index 0000000000..2134024a14
--- /dev/null
+++ b/indra/llmessage/llhttpconstants.cpp
@@ -0,0 +1,219 @@
+/** 
+ * @file llhttpconstants.cpp
+ * @brief Implementation of the HTTP request / response constant lookups
+ *
+ * $LicenseInfo:firstyear=2013&license=viewergpl$
+ * 
+ * Copyright (c) 2013, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpconstants.h"
+#include "lltimer.h"
+
+// for curl_getdate() (apparently parsing RFC 1123 dates is hard)
+#include <curl/curl.h>
+
+const std::string HTTP_HEADER_ACCEPT("Accept");
+const std::string HTTP_HEADER_ACCEPT_CHARSET("Accept-Charset");
+const std::string HTTP_HEADER_ACCEPT_ENCODING("Accept-Encoding");
+const std::string HTTP_HEADER_ACCEPT_LANGUAGE("Accept-Language");
+const std::string HTTP_HEADER_ACCEPT_RANGES("Accept-Ranges");
+const std::string HTTP_HEADER_AGE("Age");
+const std::string HTTP_HEADER_ALLOW("Allow");
+const std::string HTTP_HEADER_AUTHORIZATION("Authorization");
+const std::string HTTP_HEADER_CACHE_CONTROL("Cache-Control");
+const std::string HTTP_HEADER_CONNECTION("Connection");
+const std::string HTTP_HEADER_CONTENT_DESCRIPTION("Content-Description");
+const std::string HTTP_HEADER_CONTENT_ENCODING("Content-Encoding");
+const std::string HTTP_HEADER_CONTENT_ID("Content-ID");
+const std::string HTTP_HEADER_CONTENT_LANGUAGE("Content-Language");
+const std::string HTTP_HEADER_CONTENT_LENGTH("Content-Length");
+const std::string HTTP_HEADER_CONTENT_LOCATION("Content-Location");
+const std::string HTTP_HEADER_CONTENT_MD5("Content-MD5");
+const std::string HTTP_HEADER_CONTENT_RANGE("Content-Range");
+const std::string HTTP_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
+const std::string HTTP_HEADER_CONTENT_TYPE("Content-Type");
+const std::string HTTP_HEADER_COOKIE("Cookie");
+const std::string HTTP_HEADER_DATE("Date");
+const std::string HTTP_HEADER_DESTINATION("Destination");
+const std::string HTTP_HEADER_ETAG("ETag");
+const std::string HTTP_HEADER_EXPECT("Expect");
+const std::string HTTP_HEADER_EXPIRES("Expires");
+const std::string HTTP_HEADER_FROM("From");
+const std::string HTTP_HEADER_HOST("Host");
+const std::string HTTP_HEADER_IF_MATCH("If-Match");
+const std::string HTTP_HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
+const std::string HTTP_HEADER_IF_NONE_MATCH("If-None-Match");
+const std::string HTTP_HEADER_IF_RANGE("If-Range");
+const std::string HTTP_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since");
+const std::string HTTP_HEADER_KEEP_ALIVE("Keep-Alive");
+const std::string HTTP_HEADER_LAST_MODIFIED("Last-Modified");
+const std::string HTTP_HEADER_LOCATION("Location");
+const std::string HTTP_HEADER_MAX_FORWARDS("Max-Forwards");
+const std::string HTTP_HEADER_MIME_VERSION("MIME-Version");
+const std::string HTTP_HEADER_PRAGMA("Pragma");
+const std::string HTTP_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate");
+const std::string HTTP_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization");
+const std::string HTTP_HEADER_RANGE("Range");
+const std::string HTTP_HEADER_REFERER("Referer");
+const std::string HTTP_HEADER_RETRY_AFTER("Retry-After");
+const std::string HTTP_HEADER_SERVER("Server");
+const std::string HTTP_HEADER_SET_COOKIE("Set-Cookie");
+const std::string HTTP_HEADER_TE("TE");
+const std::string HTTP_HEADER_TRAILER("Trailer");
+const std::string HTTP_HEADER_TRANSFER_ENCODING("Transfer-Encoding");
+const std::string HTTP_HEADER_UPGRADE("Upgrade");
+const std::string HTTP_HEADER_USER_AGENT("User-Agent");
+const std::string HTTP_HEADER_VARY("Vary");
+const std::string HTTP_HEADER_VIA("Via");
+const std::string HTTP_HEADER_WARNING("Warning");
+const std::string HTTP_HEADER_WWW_AUTHENTICATE("WWW-Authenticate");
+
+
+// Sadly, our proxied headers do not follow http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+// We need to deal with lowercase headers
+const std::string HTTP_HEADER_LOWER_ACCEPT_LANGUAGE("accept-language");
+const std::string HTTP_HEADER_LOWER_CACHE_CONTROL("cache-control");
+const std::string HTTP_HEADER_LOWER_CONTENT_LENGTH("content-length");
+const std::string HTTP_HEADER_LOWER_CONTENT_TYPE("content-type");
+const std::string HTTP_HEADER_LOWER_HOST("host");
+const std::string HTTP_HEADER_LOWER_USER_AGENT("user-agent");
+const std::string HTTP_HEADER_LOWER_X_FORWARDED_FOR("x-forwarded-for");
+
+const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml");
+const std::string HTTP_CONTENT_OCTET_STREAM("application/octet-stream");
+const std::string HTTP_CONTENT_XML("application/xml");
+const std::string HTTP_CONTENT_JSON("application/json");
+const std::string HTTP_CONTENT_TEXT_HTML("text/html");
+const std::string HTTP_CONTENT_TEXT_HTML_UTF8("text/html; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8("text/plain; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_LLSD("text/llsd");
+const std::string HTTP_CONTENT_TEXT_XML("text/xml");
+const std::string HTTP_CONTENT_TEXT_LSL("text/lsl");
+const std::string HTTP_CONTENT_TEXT_PLAIN("text/plain");
+const std::string HTTP_CONTENT_IMAGE_X_J2C("image/x-j2c");
+const std::string HTTP_CONTENT_IMAGE_J2C("image/j2c");
+const std::string HTTP_CONTENT_IMAGE_JPEG("image/jpeg");
+const std::string HTTP_CONTENT_IMAGE_PNG("image/png");
+const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp");
+
+const std::string HTTP_VERB_INVALID("(invalid)");
+const std::string HTTP_VERB_HEAD("HEAD");
+const std::string HTTP_VERB_GET("GET");
+const std::string HTTP_VERB_PUT("PUT");
+const std::string HTTP_VERB_POST("POST");
+const std::string HTTP_VERB_DELETE("DELETE");
+const std::string HTTP_VERB_MOVE("MOVE");
+const std::string HTTP_VERB_OPTIONS("OPTIONS");
+
+const std::string& httpMethodAsVerb(EHTTPMethod method)
+{
+	static const std::string VERBS[] =
+	{
+		HTTP_VERB_INVALID,
+		HTTP_VERB_HEAD,
+		HTTP_VERB_GET,
+		HTTP_VERB_PUT,
+		HTTP_VERB_POST,
+		HTTP_VERB_DELETE,
+		HTTP_VERB_MOVE,
+		HTTP_VERB_OPTIONS
+	};
+	if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT))
+	{
+		return VERBS[0];
+	}
+	return VERBS[method];
+}
+
+bool isHttpInformationalStatus(S32 status)
+{
+	// Check for status 1xx.
+	return((100 <= status) && (status < 200));
+}
+
+bool isHttpGoodStatus(S32 status)
+{
+	// Check for status 2xx.
+	return((200 <= status) && (status < 300));
+}
+
+bool isHttpRedirectStatus(S32 status)
+{
+	// Check for status 3xx.
+	return((300 <= status) && (status < 400));
+}
+
+bool isHttpClientErrorStatus(S32 status)
+{
+	// Status 499 is sometimes used for re-interpreted status 2xx errors
+	// based on body content.  Treat these as potentially retryable 'server' status errors,
+	// since we do not have enough context to know if this will always fail.
+	if (HTTP_INTERNAL_ERROR == status) return false;
+
+	// Check for status 5xx.
+	return((400 <= status) && (status < 500));
+}
+
+bool isHttpServerErrorStatus(S32 status)
+{
+	// Status 499 is sometimes used for re-interpreted status 2xx errors.
+	// Allow retry of these, since we don't have enough information in this
+	// context to know if this will always fail.
+	if (HTTP_INTERNAL_ERROR == status) return true;
+
+	// Check for status 5xx.
+	return((500 <= status) && (status < 600));
+}
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
+{
+	// *TODO:  This needs testing!   Not in use yet.
+	// Examples of Retry-After headers:
+	// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+	// Retry-After: 120
+
+	// Check for number of seconds version, first:
+	char* end = 0;
+	// Parse as double
+	double seconds = std::strtod(retry_after.c_str(), &end);
+	if ( end != 0 && *end == 0 )
+	{
+		// Successful parse
+		seconds_to_wait = (F32) seconds;
+		return true;
+	}
+
+	// Parse rfc1123 date.
+	time_t date = curl_getdate(retry_after.c_str(), NULL );
+	if (-1 == date) return false;
+
+	seconds_to_wait = (F32)date - (F32)LLTimer::getTotalSeconds();
+	return true;
+}
+
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h
new file mode 100644
index 0000000000..34263e17c8
--- /dev/null
+++ b/indra/llmessage/llhttpconstants.h
@@ -0,0 +1,220 @@
+/** 
+ * @file llhttpconstants.h
+ * @brief Constants for HTTP requests and responses
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2013, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_HTTP_CONSTANTS_H
+#define LL_HTTP_CONSTANTS_H
+
+#include "stdtypes.h"
+
+/////// HTTP STATUS CODES ///////
+
+// Standard errors from HTTP spec:
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
+const S32 HTTP_CONTINUE = 100;
+const S32 HTTP_SWITCHING_PROTOCOLS = 101;
+
+// Success
+const S32 HTTP_OK = 200;
+const S32 HTTP_CREATED = 201;
+const S32 HTTP_ACCEPTED = 202;
+const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
+const S32 HTTP_NO_CONTENT = 204;
+const S32 HTTP_RESET_CONTENT = 205;
+const S32 HTTP_PARTIAL_CONTENT = 206;
+
+// Redirection
+const S32 HTTP_MULTIPLE_CHOICES = 300;
+const S32 HTTP_MOVED_PERMANENTLY = 301;
+const S32 HTTP_FOUND = 302;
+const S32 HTTP_SEE_OTHER = 303;
+const S32 HTTP_NOT_MODIFIED = 304;
+const S32 HTTP_USE_PROXY = 305;
+const S32 HTTP_TEMPORARY_REDIRECT = 307;
+
+// Client Error
+const S32 HTTP_BAD_REQUEST = 400;
+const S32 HTTP_UNAUTHORIZED = 401;
+const S32 HTTP_PAYMENT_REQUIRED = 402;
+const S32 HTTP_FORBIDDEN = 403;
+const S32 HTTP_NOT_FOUND = 404;
+const S32 HTTP_METHOD_NOT_ALLOWED = 405;
+const S32 HTTP_NOT_ACCEPTABLE = 406;
+const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
+const S32 HTTP_REQUEST_TIME_OUT = 408;
+const S32 HTTP_CONFLICT = 409;
+const S32 HTTP_GONE = 410;
+const S32 HTTP_LENGTH_REQUIRED = 411;
+const S32 HTTP_PRECONDITION_FAILED = 412;
+const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
+const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
+const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
+const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
+const S32 HTTP_EXPECTATION_FAILED = 417;
+
+// Server Error
+const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
+const S32 HTTP_NOT_IMPLEMENTED = 501;
+const S32 HTTP_BAD_GATEWAY = 502;
+const S32 HTTP_SERVICE_UNAVAILABLE = 503;
+const S32 HTTP_GATEWAY_TIME_OUT = 504;
+const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
+
+// We combine internal process errors with status codes
+// These status codes should not be sent over the wire
+//   and indicate something went wrong internally.
+// If you get these they are not normal.
+const S32 HTTP_INTERNAL_CURL_ERROR = 498;
+const S32 HTTP_INTERNAL_ERROR = 499;
+
+
+////// HTTP Methods //////
+
+extern const std::string HTTP_VERB_INVALID;
+extern const std::string HTTP_VERB_HEAD;
+extern const std::string HTTP_VERB_GET;
+extern const std::string HTTP_VERB_PUT;
+extern const std::string HTTP_VERB_POST;
+extern const std::string HTTP_VERB_DELETE;
+extern const std::string HTTP_VERB_MOVE;
+extern const std::string HTTP_VERB_OPTIONS;
+
+enum EHTTPMethod
+{
+	HTTP_INVALID = 0,
+	HTTP_HEAD,
+	HTTP_GET,
+	HTTP_PUT,
+	HTTP_POST,
+	HTTP_DELETE,
+	HTTP_MOVE, // Caller will need to set 'Destination' header
+	HTTP_OPTIONS,
+	HTTP_METHOD_COUNT
+};
+
+const std::string& httpMethodAsVerb(EHTTPMethod method);
+bool isHttpInformationalStatus(S32 status);
+bool isHttpGoodStatus(S32 status);
+bool isHttpRedirectStatus(S32 status);
+bool isHttpClientErrorStatus(S32 status);
+bool isHttpServerErrorStatus(S32 status);
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
+
+//// HTTP Headers /////
+
+extern const std::string HTTP_HEADER_ACCEPT;
+extern const std::string HTTP_HEADER_ACCEPT_CHARSET;
+extern const std::string HTTP_HEADER_ACCEPT_ENCODING;
+extern const std::string HTTP_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_HEADER_ACCEPT_RANGES;
+extern const std::string HTTP_HEADER_AGE;
+extern const std::string HTTP_HEADER_ALLOW;
+extern const std::string HTTP_HEADER_AUTHORIZATION;
+extern const std::string HTTP_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_HEADER_CONNECTION;
+extern const std::string HTTP_HEADER_CONTENT_DESCRIPTION;
+extern const std::string HTTP_HEADER_CONTENT_ENCODING;
+extern const std::string HTTP_HEADER_CONTENT_ID;
+extern const std::string HTTP_HEADER_CONTENT_LANGUAGE;
+extern const std::string HTTP_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_HEADER_CONTENT_MD5;
+extern const std::string HTTP_HEADER_CONTENT_RANGE;
+extern const std::string HTTP_HEADER_CONTENT_TRANSFER_ENCODING;
+extern const std::string HTTP_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_HEADER_COOKIE;
+extern const std::string HTTP_HEADER_DATE;
+extern const std::string HTTP_HEADER_DESTINATION;
+extern const std::string HTTP_HEADER_ETAG;
+extern const std::string HTTP_HEADER_EXPECT;
+extern const std::string HTTP_HEADER_EXPIRES;
+extern const std::string HTTP_HEADER_FROM;
+extern const std::string HTTP_HEADER_HOST;
+extern const std::string HTTP_HEADER_IF_MATCH;
+extern const std::string HTTP_HEADER_IF_MODIFIED_SINCE;
+extern const std::string HTTP_HEADER_IF_NONE_MATCH;
+extern const std::string HTTP_HEADER_IF_RANGE;
+extern const std::string HTTP_HEADER_IF_UNMODIFIED_SINCE;
+extern const std::string HTTP_HEADER_KEEP_ALIVE;
+extern const std::string HTTP_HEADER_LAST_MODIFIED;
+extern const std::string HTTP_HEADER_LOCATION;
+extern const std::string HTTP_HEADER_MAX_FORWARDS;
+extern const std::string HTTP_HEADER_MIME_VERSION;
+extern const std::string HTTP_HEADER_PRAGMA;
+extern const std::string HTTP_HEADER_PROXY_AUTHENTICATE;
+extern const std::string HTTP_HEADER_PROXY_AUTHORIZATION;
+extern const std::string HTTP_HEADER_RANGE;
+extern const std::string HTTP_HEADER_REFERER;
+extern const std::string HTTP_HEADER_RETRY_AFTER;
+extern const std::string HTTP_HEADER_SERVER;
+extern const std::string HTTP_HEADER_SET_COOKIE;
+extern const std::string HTTP_HEADER_TE;
+extern const std::string HTTP_HEADER_TRAILER;
+extern const std::string HTTP_HEADER_TRANSFER_ENCODING;
+extern const std::string HTTP_HEADER_UPGRADE;
+extern const std::string HTTP_HEADER_USER_AGENT;
+extern const std::string HTTP_HEADER_VARY;
+extern const std::string HTTP_HEADER_VIA;
+extern const std::string HTTP_HEADER_WARNING;
+extern const std::string HTTP_HEADER_WWW_AUTHENTICATE;
+
+// Sadly, our proxied headers do not follow http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+// We need to deal with lowercase headers
+extern const std::string HTTP_HEADER_LOWER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_HEADER_LOWER_CACHE_CONTROL;
+extern const std::string HTTP_HEADER_LOWER_CONTENT_LENGTH;
+extern const std::string HTTP_HEADER_LOWER_CONTENT_TYPE;
+extern const std::string HTTP_HEADER_LOWER_HOST;
+extern const std::string HTTP_HEADER_LOWER_USER_AGENT;
+extern const std::string HTTP_HEADER_LOWER_X_FORWARDED_FOR;
+
+//// HTTP Content Types ////
+
+extern const std::string HTTP_CONTENT_LLSD_XML;
+extern const std::string HTTP_CONTENT_OCTET_STREAM;
+extern const std::string HTTP_CONTENT_XML;
+extern const std::string HTTP_CONTENT_JSON;
+extern const std::string HTTP_CONTENT_TEXT_HTML;
+extern const std::string HTTP_CONTENT_TEXT_HTML_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_LLSD;
+extern const std::string HTTP_CONTENT_TEXT_XML;
+extern const std::string HTTP_CONTENT_TEXT_LSL;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN;
+extern const std::string HTTP_CONTENT_IMAGE_X_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_JPEG;
+extern const std::string HTTP_CONTENT_IMAGE_PNG;
+extern const std::string HTTP_CONTENT_IMAGE_BMP;
+
+#endif
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index 5c2f73eccb..e3b42b1b16 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -30,6 +30,7 @@
 #include <boost/tokenizer.hpp>
 
 #include "llstl.h"
+#include "llhttpconstants.h"
 #include "lliohttpserver.h" // for string constants
 
 static const std::string CONTEXT_WILDCARD("wildcard");
@@ -173,13 +174,15 @@ LLSD LLHTTPNode::simpleDel(const LLSD&) const
 void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
 {
 	//llinfos << "options context: " << context << llendl;
+	LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL;
 
 	// default implementation constructs an url to the documentation.
+	// *TODO: Check for 'Host' header instead of 'host' header?
 	std::string host(
-		context[CONTEXT_REQUEST][CONTEXT_HEADERS]["host"].asString());
+		context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_HEADER_LOWER_HOST].asString());
 	if(host.empty())
 	{
-		response->status(400, "Bad Request -- need Host header");
+		response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header");
 		return;
 	}
 	std::ostringstream ostr;
@@ -187,7 +190,7 @@ void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
 	ostr << context[CONTEXT_REQUEST]["path"].asString();
 	static const std::string DOC_HEADER("X-Documentation-URL");
 	response->addHeader(DOC_HEADER, ostr.str());
-	response->status(200, "OK");
+	response->status(HTTP_OK, "OK");
 }
 
 
@@ -389,17 +392,17 @@ void LLHTTPNode::Response::statusUnknownError(S32 code)
 
 void LLHTTPNode::Response::notFound(const std::string& message)
 {
-	status(404, message);
+	status(HTTP_NOT_FOUND, message);
 }
 
 void LLHTTPNode::Response::notFound()
 {
-	status(404, "Not Found");
+	status(HTTP_NOT_FOUND, "Not Found");
 }
 
 void LLHTTPNode::Response::methodNotAllowed()
 {
-	status(405, "Method Not Allowed");
+	status(HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed");
 }
 
 void LLHTTPNode::Response::addHeader(
@@ -467,7 +470,7 @@ LLSimpleResponse::~LLSimpleResponse()
 
 void LLSimpleResponse::result(const LLSD& result)
 {
-	status(200, "OK");
+	status(HTTP_OK, "OK");
 }
 
 void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const LLSD& headers)
@@ -475,6 +478,11 @@ void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const L
 	status(code,body);
 }
 
+void LLSimpleResponse::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
+{
+	status(code,"(LLSD)");
+}
+
 void LLSimpleResponse::status(S32 code, const std::string& message)
 {
 	mCode = code;
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 148647ddde..2539eec6c3 100644
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -60,6 +60,8 @@ class LLChainIOFactory;
  */
 class LLHTTPNode
 {
+protected:
+    LOG_CLASS(LLHTTPNode);
 public:
 	LLHTTPNode();
 	virtual ~LLHTTPNode();
@@ -100,7 +102,12 @@ public:
 		/**
 		 * @brief return status code and message with headers.
 		 */
-		virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) = 0;
+		virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers = LLSD()) = 0;
+
+		/**
+		 * @brief return status code and LLSD result with headers.
+		 */
+		virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers = LLSD()) = 0;
 
 		/**
 		 * @brief return status code and reason string on http header,
@@ -287,7 +294,7 @@ public:
 	
 	void result(const LLSD& result);
 	void extendedResult(S32 code, const std::string& body, const LLSD& headers);
-	
+	void extendedResult(S32 code, const LLSD& result, const LLSD& headers);
 	void status(S32 code, const std::string& message);
 
 	void print(std::ostream& out) const;
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 1236fc8b71..509719786c 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -33,6 +33,7 @@
 #include "llapr.h"
 #include "llbuffer.h"
 #include "llbufferstream.h"
+#include "llhttpconstants.h"
 #include "llhttpnode.h"
 #include "lliopipe.h"
 #include "lliosocket.h"
@@ -53,11 +54,6 @@ const std::string CONTEXT_REQUEST("request");
 const std::string CONTEXT_RESPONSE("response");
 const std::string CONTEXT_VERB("verb");
 const std::string CONTEXT_HEADERS("headers");
-const std::string HTTP_VERB_GET("GET");
-const std::string HTTP_VERB_PUT("PUT");
-const std::string HTTP_VERB_POST("POST");
-const std::string HTTP_VERB_DELETE("DELETE");
-const std::string HTTP_VERB_OPTIONS("OPTIONS");
 
 static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL;
 static void* sTimingCallbackData = NULL;
@@ -102,7 +98,7 @@ private:
 		// from LLHTTPNode::Response
 		virtual void result(const LLSD&);
 		virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
-		
+		virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
 		virtual void status(S32 code, const std::string& message);
 
 		void nullPipe();
@@ -122,7 +118,8 @@ private:
 		STATE_LOCKED,
 		STATE_GOOD_RESULT,
 		STATE_STATUS_RESULT,
-		STATE_EXTENDED_RESULT
+		STATE_EXTENDED_RESULT,
+		STATE_EXTENDED_LLSD_RESULT
 	};
 	State mState;
 
@@ -132,7 +129,7 @@ private:
 	void lockChain(LLPumpIO*);
 	void unlockChain();
 
-	LLSD mGoodResult;
+	LLSD mResult;
 	S32 mStatusCode;
 	std::string mStatusMessage;	
 	LLSD mHeaders;
@@ -193,7 +190,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 			}
 			else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
 			{
-				std::stringstream strstrm;
+				std::ostringstream strstrm;
 				strstrm << istr.rdbuf();
 				input = strstrm.str();
 			}
@@ -209,7 +206,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 			}
 			else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
 			{
-				std::stringstream strstrm;
+				std::ostringstream strstrm;
 				strstrm << istr.rdbuf();
 				input = strstrm.str();
 			}
@@ -249,7 +246,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 			<< "s" << llendl;
 
 		// Log Internal Server Errors
-		//if(mStatusCode == 500)
+		//if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
 		//{
 		//	llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error" 
 		//			<< llendl;
@@ -271,10 +268,10 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_GOOD_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers["Content-Type"] = "application/llsd+xml";
+			headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			LLBufferStream ostr(channels, buffer.get());
-			LLSDSerialize::toXML(mGoodResult, ostr);
+			LLSDSerialize::toXML(mResult, ostr);
 
 			return STATUS_DONE;
 		}
@@ -282,7 +279,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_STATUS_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers["Content-Type"] = "text/plain";
+			headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
 			context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
@@ -300,6 +297,17 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 
 			return STATUS_DONE;
 		}
+		case STATE_EXTENDED_LLSD_RESULT:
+		{
+			LLSD headers = mHeaders;
+			headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+			context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+			LLBufferStream ostr(channels, buffer.get());
+			LLSDSerialize::toXML(mResult, ostr);
+
+			return STATUS_DONE;
+		}
 		default:
 			llwarns << "LLHTTPPipe::process_impl: unexpected state "
 				<< mState << llendl;
@@ -335,19 +343,35 @@ void LLHTTPPipe::Response::result(const LLSD& r)
 		return;
 	}
 
-	mPipe->mStatusCode = 200;
+	mPipe->mStatusCode = HTTP_OK;
 	mPipe->mStatusMessage = "OK";
-	mPipe->mGoodResult = r;
+	mPipe->mResult = r;
 	mPipe->mState = STATE_GOOD_RESULT;
 	mPipe->mHeaders = mHeaders;
-	mPipe->unlockChain();	
+	mPipe->unlockChain();
+}
+
+void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
+{
+	if(! mPipe)
+	{
+		llwarns << "LLHTTPPipe::Response::extendedResult: NULL pipe" << llendl;
+		return;
+	}
+
+	mPipe->mStatusCode = code;
+	mPipe->mStatusMessage = "(LLSD)";
+	mPipe->mResult = r;
+	mPipe->mHeaders = headers;
+	mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
+	mPipe->unlockChain();
 }
 
 void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
 {
 	if(! mPipe)
 	{
-		llwarns << "LLHTTPPipe::Response::status: NULL pipe" << llendl;
+		llwarns << "LLHTTPPipe::Response::extendedResult: NULL pipe" << llendl;
 		return;
 	}
 
@@ -454,9 +478,9 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 		std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
 		
 		int code = context[CONTEXT_RESPONSE]["statusCode"];
-		if (code < 200)
+		if (code < HTTP_OK)
 		{
-			code = 200;
+			code = HTTP_OK;
 			message = "OK";
 		}
 		
@@ -465,7 +489,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 		S32 content_length = buffer->countAfter(channels.in(), NULL);
 		if(0 < content_length)
 		{
-			ostr << "Content-Length: " << content_length << "\r\n";
+			ostr << HTTP_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
 		}
 		// *NOTE: This guard can go away once the LLSD static map
 		// iterator is available. Phoenix. 2008-05-09
@@ -771,7 +795,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 					std::string name(buf, pos_colon - buf);
 					std::string value(pos_colon + 2);
 					LLStringUtil::toLower(name);
-					if("content-length" == name)
+					if(HTTP_HEADER_LOWER_CONTENT_LENGTH == name)
 					{
 						lldebugs << "Content-Length: " << value << llendl;
 						mContentLength = atoi(value.c_str());
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index 5c1b0531ff..40537e05bc 100644
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -39,11 +39,6 @@ extern const std::string CONTEXT_REQUEST;
 extern const std::string CONTEXT_RESPONSE;
 extern const std::string CONTEXT_VERB;
 extern const std::string CONTEXT_HEADERS;
-extern const std::string HTTP_VERB_GET;
-extern const std::string HTTP_VERB_PUT;
-extern const std::string HTTP_VERB_POST;
-extern const std::string HTTP_VERB_DELETE;
-extern const std::string HTTP_VERB_OPTIONS;
 
 class LLIOHTTPServer
 {
diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp
index 9d9c4ebd68..90653098db 100644
--- a/indra/llmessage/llmime.cpp
+++ b/indra/llmessage/llmime.cpp
@@ -27,6 +27,7 @@
  */
 
 #include "linden_common.h"
+#include "llhttpconstants.h"
 #include "llmime.h"
 
 #include <vector>
@@ -36,20 +37,6 @@
 /**
  * Useful constants.
  */
-// Headers specified in rfc-2045 will be canonicalized below.
-static const std::string CONTENT_LENGTH("Content-Length");
-static const std::string CONTENT_TYPE("Content-Type");
-static const S32 KNOWN_HEADER_COUNT = 6;
-static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] =
-{
-	CONTENT_LENGTH,
-	CONTENT_TYPE,
-	std::string("MIME-Version"),
-	std::string("Content-Transfer-Encoding"),
-	std::string("Content-ID"),
-	std::string("Content-Description"),
-};
-
 // parser helpers
 static const std::string MULTIPART("multipart");
 static const std::string BOUNDARY("boundary");
@@ -115,7 +102,7 @@ S32 LLMimeIndex::contentLength() const
 {
 	// Find the content length in the headers.
 	S32 length = -1;
-	LLSD content_length = mImpl->mHeaders[CONTENT_LENGTH];
+	LLSD content_length = mImpl->mHeaders[HTTP_HEADER_CONTENT_LENGTH];
 	if(content_length.isDefined())
 	{
 		length = content_length.asInteger();
@@ -126,7 +113,7 @@ S32 LLMimeIndex::contentLength() const
 std::string LLMimeIndex::contentType() const
 {
 	std::string type;
-	LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
+	LLSD content_type = mImpl->mHeaders[HTTP_HEADER_CONTENT_TYPE];
 	if(content_type.isDefined())
 	{
 		type = content_type.asString();
@@ -137,7 +124,7 @@ std::string LLMimeIndex::contentType() const
 bool LLMimeIndex::isMultipart() const
 {
 	bool multipart = false;
-	LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
+	LLSD content_type = mImpl->mHeaders[HTTP_HEADER_CONTENT_TYPE];
 	if(content_type.isDefined())
 	{
 		std::string type = content_type.asString();
@@ -354,7 +341,7 @@ bool LLMimeParser::Impl::parseIndex(
 		if(index.isMultipart())
 		{
 			// Figure out the separator, scan past it, and recurse.
-			std::string ct = headers[CONTENT_TYPE].asString();
+			std::string ct = headers[HTTP_HEADER_CONTENT_TYPE].asString();
 			std::string sep = findSeparator(ct);
 			scanPastSeparator(istr, limit, sep);
 			while(continueParse() && parseIndex(istr, limit, sep, true, mime))
@@ -381,6 +368,18 @@ bool LLMimeParser::Impl::parseHeaders(
 	S32 limit,
 	LLSD& headers)
 {
+	// Headers specified in rfc-2045 will be canonicalized below.
+	static const S32 KNOWN_HEADER_COUNT = 6;
+	static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] =
+	{
+		HTTP_HEADER_CONTENT_LENGTH,
+		HTTP_HEADER_CONTENT_TYPE,
+		HTTP_HEADER_MIME_VERSION,
+		HTTP_HEADER_CONTENT_TRANSFER_ENCODING,
+		HTTP_HEADER_CONTENT_ID,
+		HTTP_HEADER_CONTENT_DESCRIPTION,
+	};
+
 	while(continueParse())
 	{
 		// Get the next line.
@@ -531,9 +530,9 @@ void LLMimeParser::Impl::scanPastContent(
 	LLSD headers,
 	const std::string separator)
 {
-	if(headers.has(CONTENT_LENGTH))
+	if(headers.has(HTTP_HEADER_CONTENT_LENGTH))
 	{
-		S32 content_length = headers[CONTENT_LENGTH].asInteger();
+		S32 content_length = headers[HTTP_HEADER_CONTENT_LENGTH].asInteger();
 		// Subtract 2 here for the \r\n after the content.
 		S32 max_skip = llmin(content_length, limit - mScanCount - 2);
 		istr.ignore(max_skip);
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
deleted file mode 100644
index 932cbf375e..0000000000
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/** 
- * @file llregionpresenceverifier.cpp
- * @brief 
- *
- * $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 "linden_common.h"
-
-#include "llregionpresenceverifier.h"
-#include "llhttpclientinterface.h"
-#include <sstream>
-#include "net.h"
-#include "message.h"
-
-namespace boost
-{
-	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
-	{
-		++p->mReferenceCount;
-	}
-	
-	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
-	{
-		if(p && 0 == --p->mReferenceCount)
-		{
-			delete p;
-		}
-	}
-};
-
-LLRegionPresenceVerifier::Response::~Response()
-{
-}
-
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
-														   uri,
-														   ResponsePtr data,
-														   S32 retry_count) :
-	mUri(uri),
-	mSharedData(data),
-	mRetryCount(retry_count)
-{
-}
-
-//virtual
-LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
-{
-}
-
-void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
-{
-	std::string host = content["private_host"].asString();
-	U32 port = content["private_port"].asInteger();
-	LLHost destination(host, port);
-	LLUUID id = content["region_id"];
-
-	lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl;
-
-	std::stringstream uri;
-	uri << "http://" << destination.getString() << "/state/basic/";
-	mSharedData->getHttpClient().get(
-		uri.str(),
-		new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
-}
-
-void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
-													 const std::string& reason)
-{
-	// TODO: babbage: distinguish between region presence service and
-	// region verification errors?
-	mSharedData->onRegionVerificationFailed();
-}
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
-	S32 retry_count):
-	mUri(uri),
-	mSharedData(data),
-	mContent(content),
-	mRetryCount(retry_count) 
-{
-}
-
-//virtual
-LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
-{
-}
-
-void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
-{
-	LLUUID actual_region_id = content["region_id"];
-	LLUUID expected_region_id = mContent["region_id"];
-
-	lldebugs << "Actual region: " << content << llendl;
-	lldebugs << "Expected region: " << mContent << llendl;
-
-	if (mSharedData->checkValidity(content) &&
-		(actual_region_id == expected_region_id))
-	{
-		mSharedData->onRegionVerified(mContent);
-	}
-	else if (mRetryCount > 0)
-	{
-		retry();
-	}
-	else
-	{
-		llwarns << "Simulator verification failed. Region: " << mUri << llendl;
-		mSharedData->onRegionVerificationFailed();
-	}
-}
-
-void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
-{
-	LLSD headers;
-	headers["Cache-Control"] = "no-cache, max-age=0";
-	llinfos << "Requesting region information, get uncached for region "
-			<< mUri << llendl;
-	--mRetryCount;
-	mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
-}
-
-void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
-{
-	if(mRetryCount > 0)
-	{
-		retry();
-	}
-	else
-	{
-		llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
-		mSharedData->onRegionVerificationFailed();
-	}
-}
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
deleted file mode 100644
index 5e8251e519..0000000000
--- a/indra/llmessage/llregionpresenceverifier.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/** 
- * @file llregionpresenceverifier.cpp
- * @brief 
- *
- * $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$
- */
-
-/* Macro Definitions */
-#ifndef LL_LLREGIONPRESENCEVERIFIER_H
-#define LL_LLREGIONPRESENCEVERIFIER_H
-
-#include "llhttpclient.h"
-#include <string>
-#include "llsd.h"
-#include <boost/intrusive_ptr.hpp>
-
-class LLHTTPClientInterface;
-
-class LLRegionPresenceVerifier
-{
-public:
-	class Response
-	{
-	public:
-		virtual ~Response() = 0;
-
-		virtual bool checkValidity(const LLSD& content) const = 0;
-		virtual void onRegionVerified(const LLSD& region_details) = 0;
-		virtual void onRegionVerificationFailed() = 0;
-
-		virtual LLHTTPClientInterface& getHttpClient() = 0;
-
-	public: /* but not really -- don't touch this */
-		U32 mReferenceCount;		
-	};
-
-	typedef boost::intrusive_ptr<Response> ResponsePtr;
-
-	class RegionResponder : public LLHTTPClient::Responder
-	{
-	public:
-		RegionResponder(const std::string& uri, ResponsePtr data,
-						S32 retry_count);
-		virtual ~RegionResponder(); 
-		virtual void result(const LLSD& content);
-		virtual void error(U32 status, const std::string& reason);
-
-	private:
-		ResponsePtr mSharedData;
-		std::string mUri;
-		S32 mRetryCount;
-	};
-
-	class VerifiedDestinationResponder : public LLHTTPClient::Responder
-	{
-	public:
-		VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
-									 const LLSD& content, S32 retry_count);
-		virtual ~VerifiedDestinationResponder();
-		virtual void result(const LLSD& content);
-		
-		virtual void error(U32 status, const std::string& reason);
-		
-	private:
-		void retry();
-		ResponsePtr mSharedData;
-		LLSD mContent;
-		std::string mUri;
-		S32 mRetryCount;
-	};
-};
-
-namespace boost
-{
-	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
-	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
-};
-
-#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
index 1c93c12d99..376f69ea36 100644
--- a/indra/llmessage/llsdmessage.cpp
+++ b/indra/llmessage/llsdmessage.cpp
@@ -92,14 +92,14 @@ bool LLSDMessage::httpListener(const LLSD& request)
     return false;
 }
 
-void LLSDMessage::EventResponder::result(const LLSD& data)
+void LLSDMessage::EventResponder::httpSuccess()
 {
     // If our caller passed an empty replyPump name, they're not
     // listening: this is a fire-and-forget message. Don't bother posting
     // to the pump whose name is "".
     if (! mReplyPump.empty())
     {
-        LLSD response(data);
+        LLSD response(getContent());
         mReqID.stamp(response);
         mPumps.obtain(mReplyPump).post(response);
     }
@@ -111,7 +111,7 @@ void LLSDMessage::EventResponder::result(const LLSD& data)
     }
 }
 
-void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLSDMessage::EventResponder::httpFailure()
 {
     // If our caller passed an empty errorPump name, they're not
     // listening: "default error handling is acceptable." Only post to an
@@ -121,19 +121,16 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string
         LLSD info(mReqID.makeResponse());
         info["target"]  = mTarget;
         info["message"] = mMessage;
-        info["status"]  = LLSD::Integer(status);
-        info["reason"]  = reason;
-        info["content"] = content;
+        info["status"]  = getStatus();
+        info["reason"]  = getReason();
+        info["content"] = getContent();
         mPumps.obtain(mErrorPump).post(info);
     }
     else                        // default error handling
     {
-        // convention seems to be to use llinfos, but that seems a bit casual?
         LL_WARNS("LLSDMessage::EventResponder")
             << "'" << mMessage << "' to '" << mTarget
-            << "' failed with code " << status << ": " << reason << '\n'
-            << ll_pretty_print_sd(content)
-            << LL_ENDL;
+            << "' failed " << dumpResponse() << LL_ENDL;
     }
 }
 
@@ -151,11 +148,11 @@ bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
 {
     if (success)
     {
-        mResponder->result(payload);
+        mResponder->successResult(payload);
     }
     else
     {
-        mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
+        mResponder->failureResult(payload["status"].asInteger(), payload["reason"], payload["content"]);
     }
 
     /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
index 0d34847ff2..e5d532d6a4 100644
--- a/indra/llmessage/llsdmessage.h
+++ b/indra/llmessage/llsdmessage.h
@@ -123,6 +123,7 @@ private:
     /// LLCapabilityListener. Others should use higher-level APIs.
     class EventResponder: public LLHTTPClient::Responder
     {
+        LOG_CLASS(EventResponder);
     public:
         /**
          * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
@@ -149,8 +150,9 @@ private:
             mErrorPump(errorPump)
         {}
     
-        virtual void result(const LLSD& data);
-        virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+    protected:
+        virtual void httpSuccess();
+        virtual void httpFailure();
     
     private:
         LLEventPumps& mPumps;
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index 0cecf4f688..02891d4f32 100644
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -240,7 +240,7 @@ public:
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
 		lldebugs << "LLSDRPCClientFactory::build" << llendl;
-		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		LLURLRequest* http(new LLURLRequest(HTTP_POST));
 		if(!http->isValid())
 		{
 			llwarns << "Creating LLURLRequest failed." << llendl ;
@@ -251,7 +251,7 @@ public:
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader("Content-Type: text/llsd");
+		http->addHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_LLSD);
 		if(mURL.empty())
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
@@ -291,7 +291,7 @@ public:
 	{
 		lldebugs << "LLXMLSDRPCClientFactory::build" << llendl;
 
-		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		LLURLRequest* http(new LLURLRequest(HTTP_POST));
 		if(!http->isValid())
 		{
 			llwarns << "Creating LLURLRequest failed." << llendl ;
@@ -301,7 +301,7 @@ public:
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader("Content-Type: text/xml");
+		http->addHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
 		if(mURL.empty())
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
index fea7fc72c4..8248b184e9 100644
--- a/indra/llmessage/lltrustedmessageservice.cpp
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -64,7 +64,7 @@ void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
 		LL_WARNS("Messaging") << "trusted message POST to /trusted-message/" 
 				<< name << " from unknown or untrusted sender "
 				<< sender << llendl;
-		response->status(403, "Unknown or untrusted sender");
+		response->status(HTTP_FORBIDDEN, "Unknown or untrusted sender");
 	}
 	else
 	{
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 627d591839..f354f5ab5d 100755
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -40,7 +40,6 @@
 #include "llstring.h"
 #include "apr_env.h"
 #include "llapr.h"
-static const U32 HTTP_STATUS_PIPE_ERROR = 499;
 
 /**
  * String constants
@@ -130,34 +129,15 @@ CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param)
  * class LLURLRequest
  */
 
-// static
-std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
-{
-	static const std::string VERBS[] =
-	{
-		"(invalid)",
-		"HEAD",
-		"GET",
-		"PUT",
-		"POST",
-		"DELETE",
-		"MOVE"
-	};
-	if(((S32)action <=0) || ((S32)action >= REQUEST_ACTION_COUNT))
-	{
-		return VERBS[0];
-	}
-	return VERBS[action];
-}
 
-LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
+LLURLRequest::LLURLRequest(EHTTPMethod action) :
 	mAction(action)
 {
 	initialize();
 }
 
 LLURLRequest::LLURLRequest(
-	LLURLRequest::ERequestAction action,
+	EHTTPMethod action,
 	const std::string& url) :
 	mAction(action)
 {
@@ -180,12 +160,17 @@ void LLURLRequest::setURL(const std::string& url)
 	}
 }
 
-std::string LLURLRequest::getURL() const
+const std::string& LLURLRequest::getURL() const
 {
 	return mDetail->mURL;
 }
 
-void LLURLRequest::addHeader(const char* header)
+void LLURLRequest::addHeader(const std::string& header, const std::string& value /* = "" */)
+{
+	mDetail->mCurlRequest->slist_append(header, value);
+}
+
+void LLURLRequest::addHeaderRaw(const char* header)
 {
 	mDetail->mCurlRequest->slist_append(header);
 }
@@ -272,7 +257,7 @@ LLIOPipe::EStatus LLURLRequest::handleError(
 		LLURLRequestComplete* complete = NULL;
 		complete = (LLURLRequestComplete*)mCompletionCallback.get();
 		complete->httpStatus(
-			HTTP_STATUS_PIPE_ERROR,
+			HTTP_INTERNAL_ERROR,
 			LLIOPipe::lookupStatusString(status));
 		complete->responseStatus(status);
 		pump->respond(complete);
@@ -494,7 +479,7 @@ bool LLURLRequest::configure()
 	case HTTP_PUT:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
-		addHeader("Expect:");
+		addHeader(HTTP_HEADER_EXPECT);
 
 		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
 		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
@@ -504,11 +489,11 @@ bool LLURLRequest::configure()
 	case HTTP_POST:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
-		addHeader("Expect:");
+		addHeader(HTTP_HEADER_EXPECT);
 
 		// Disable the content type http header.
 		// *FIX: what should it be?
-		addHeader("Content-Type:");
+		addHeader(HTTP_HEADER_CONTENT_TYPE);
 
 		// Set the handle for an http post
 		mDetail->mCurlRequest->setPost(NULL, bytes);
@@ -638,7 +623,7 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
 		S32 status_code = atoi(status.c_str());
 		if (status_code > 0)
 		{
-			complete->httpStatus((U32)status_code, reason);
+			complete->httpStatus(status_code, reason);
 			return header_len;
 		}
 	}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 44d358d906..f334c92cc3 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -68,42 +68,22 @@ class LLURLRequest : public LLIOPipe
 {
 	LOG_CLASS(LLURLRequest);
 public:
-
 	typedef int (* SSLCertVerifyCallback)(X509_STORE_CTX *ctx, void *param);
-	/** 
-	 * @brief This enumeration is for specifying the type of request.
-	 */
-	enum ERequestAction
-	{
-		INVALID,
-		HTTP_HEAD,
-		HTTP_GET,
-		HTTP_PUT,
-		HTTP_POST,
-		HTTP_DELETE,
-		HTTP_MOVE, // Caller will need to set 'Destination' header
-		REQUEST_ACTION_COUNT
-	};
-
-	/**
-	 * @brief Turn the requst action into an http verb.
-	 */
-	static std::string actionAsVerb(ERequestAction action);
 
 	/** 
 	 * @brief Constructor.
 	 *
-	 * @param action One of the ERequestAction enumerations.
+	 * @param action One of the EHTTPMethod enumerations.
 	 */
-	LLURLRequest(ERequestAction action);
+	LLURLRequest(EHTTPMethod action);
 
 	/** 
 	 * @brief Constructor.
 	 *
-	 * @param action One of the ERequestAction enumerations.
+	 * @param action One of the EHTTPMethod enumerations.
 	 * @param url The url of the request. It should already be encoded.
 	 */
-	LLURLRequest(ERequestAction action, const std::string& url);
+	LLURLRequest(EHTTPMethod action, const std::string& url);
 
 	/** 
 	 * @brief Destructor.
@@ -123,17 +103,17 @@ public:
 	 * 
 	 */
 	void setURL(const std::string& url);
-	std::string getURL() const;
+	const std::string& getURL() const;
 	/** 
 	 * @brief Add a header to the http post.
 	 *
-	 * The header must be correctly formatted for HTTP requests. This
-	 * provides a raw interface if you know what kind of request you
+	 * This provides a raw interface if you know what kind of request you
 	 * will be making during construction of this instance. All
 	 * required headers will be automatically constructed, so this is
 	 * usually useful for encoding parameters.
 	 */
-	void addHeader(const char* header);
+	void addHeader(const std::string& header, const std::string& value = "");
+	void addHeaderRaw(const char* header);
 
 	/**
 	 * @brief Check remote server certificate signed by a known root CA.
@@ -218,7 +198,7 @@ protected:
 		STATE_HAVE_RESPONSE,
 	};
 	EState mState;
-	ERequestAction mAction;
+	EHTTPMethod mAction;
 	LLURLRequestDetail* mDetail;
 	LLIOPipe::ptr_t mCompletionCallback;
 	 S32 mRequestTransferedBytes;
@@ -315,7 +295,7 @@ public:
 	// May be called more than once, particularly for redirects and proxy madness.
 	// Ex. a 200 for a connection to https through a proxy, followed by the "real" status
 	//     a 3xx for a redirect followed by a "real" status, or more redirects.
-	virtual void httpStatus(U32 status, const std::string& reason) { }
+	virtual void httpStatus(S32 status, const std::string& reason) { }
 
 	virtual void complete(
 		const LLChannelDescriptors& channels,
@@ -368,7 +348,7 @@ protected:
 	//@}
 
 	// value to note if we actually got the response. This value
-	// depends on correct useage from the LLURLRequest instance.
+	// depends on correct usage from the LLURLRequest instance.
 	EStatus mRequestStatus;
 };
 
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index ae95087377..78b259c3f1 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -113,20 +113,20 @@ namespace
 		{
 		}
 
-		virtual void error(U32 status, const std::string& reason)
+	protected:
+		virtual void httpFailure()
 		{
 			// don't spam when agent communication disconnected already
-			if (status != 410)
+			if (HTTP_GONE != getStatus())
 			{
-				LL_WARNS("Messaging") << "error status " << status
-						<< " for message " << mMessageName
-						<< " reason " << reason << llendl;
+				LL_WARNS("Messaging") << "error for message " << mMessageName
+					<< " " << dumpResponse() << LL_ENDL;
 			}
 			// TODO: Map status in to useful error code.
 			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT);
 		}
 		
-		virtual void result(const LLSD& content)
+		virtual void httpSuccess()
 		{
 			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
 		}
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 9b298d0c04..b7fdf4f437 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -24,55 +24,76 @@
  * $/LicenseInfo$
  */
 
+#ifndef LL_CURL_STUB_CPP
+#define LL_CURL_STUB_CPP
+
+
 #include "linden_common.h"
 #include "llcurl.h"
+#include "llhttpconstants.cpp"
 
 LLCurl::Responder::Responder()
 {
 }
 
-void LLCurl::Responder::completed(U32 status, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const &reason,
-								  LLSD const& mContent)
+void LLCurl::Responder::httpCompleted()
 {
-	if (isGoodStatus(status))
+	if (isGoodStatus())
 	{
-		result(mContent);
+		httpSuccess();
 	}
 	else
 	{
-		errorWithContent(status, reason, mContent);
+		httpFailure();
 	}
 }
 
-void LLCurl::Responder::completedHeader(unsigned,
-										std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
-										LLSD const&)
+void LLCurl::Responder::completedRaw(LLChannelDescriptors const&,
+									 boost::shared_ptr<LLBufferArray> const&)
 {
 }
 
-void LLCurl::Responder::completedRaw(unsigned,
-									 std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
-									 LLChannelDescriptors const&,
-									 boost::shared_ptr<LLBufferArray> const&)
+void LLCurl::Responder::httpFailure()
 {
 }
 
-void LLCurl::Responder::errorWithContent(unsigned,
-							  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
-							  LLSD const&)
+LLCurl::Responder::~Responder ()
 {
 }
 
-LLCurl::Responder::~Responder ()
+void LLCurl::Responder::httpSuccess()
+{
+}
+
+std::string LLCurl::Responder::dumpResponse() const
+{
+	return "dumpResponse()";
+}
+
+void LLCurl::Responder::successResult(const LLSD& content)
 {
+	setResult(HTTP_OK, "", content);
+	httpSuccess();
 }
 
-void LLCurl::Responder::error(unsigned,
-							  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content)
+{
+	setResult(status, reason, content);
+	httpFailure();
+}
+
+
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content)
 {
+	setResult(status, reason, content);
+	httpCompleted();
 }
 
-void LLCurl::Responder::result(LLSD const&)
+void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
 {
+	mStatus = status;
+	mReason = reason;
+	mContent = content;
 }
 
+#endif
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index 87cbafa404..bdc48ce53d 100644
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -101,7 +101,7 @@ namespace tut
 			if (mSawError)
 			{
 				std::string msg =
-					llformat("error() called when not expected, status %d",
+					llformat("httpFailure() called when not expected, status %d",
 						mStatus);
 				fail(msg);
 			}
@@ -111,7 +111,7 @@ namespace tut
 		{
 			if (!mSawError)
 			{
-				fail("error() wasn't called");
+				fail("httpFailure() wasn't called");
 			}
 		}
 
@@ -153,33 +153,26 @@ namespace tut
 				mClient.mResultDeleted = true;
 			}
 
-			virtual void error(U32 status, const std::string& reason)
+		protected:
+			virtual void httpFailure()
 			{
 				mClient.mSawError = true;
-				mClient.mStatus = status;
-				mClient.mReason = reason;
+				mClient.mStatus = getStatus();
+				mClient.mReason = getReason();
 			}
 
-			virtual void result(const LLSD& content)
+			virtual void httpSuccess()
 			{
-				mClient.mResult = content;
+				mClient.mResult = getContent();
 			}
 
-			virtual void completed(
-							U32 status, const std::string& reason,
-							const LLSD& content)
+			virtual void httpCompleted()
 			{
-				LLHTTPClient::Responder::completed(status, reason, content);
-
+				LLHTTPClient::Responder::httpCompleted();
+				
 				mClient.mSawCompleted = true;
-			}
-
-			virtual void completedHeader(
-				U32 status, const std::string& reason,
-				const LLSD& content)
-			{
-				mClient.mHeader = content;
 				mClient.mSawCompletedHeader = true;
+				mClient.mHeader = getResponseHeaders();
 			}
 
 		private:
diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp
index 13ce0a0edd..cc7feeab4f 100644
--- a/indra/llmessage/tests/llhttpclientadapter_test.cpp
+++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp
@@ -1,6 +1,6 @@
 /** 
- * @file 
- * @brief 
+ * @file llhttpclientadapter_test.cpp
+ * @brief Tests for LLHTTPClientAdapter
  *
  * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -33,8 +33,8 @@
 float const HTTP_REQUEST_EXPIRY_SECS = 1.0F;
 
 std::vector<std::string> get_urls;
-std::vector<boost::intrusive_ptr<LLCurl::Responder> > get_responders;
-void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
+std::vector< LLCurl::ResponderPtr > get_responders;
+void LLHTTPClient::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout)
 {
 	get_urls.push_back(url);
 	get_responders.push_back(responder);
@@ -42,16 +42,30 @@ void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Resp
 
 std::vector<std::string> put_urls;
 std::vector<LLSD> put_body;
-std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders;
+std::vector<LLSD> put_headers;
+std::vector<LLCurl::ResponderPtr> put_responders;
 
-void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
+void LLHTTPClient::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout)
 {
 	put_urls.push_back(url);
 	put_responders.push_back(responder);
 	put_body.push_back(body);
+	put_headers.push_back(headers);
 
 }
 
+std::vector<std::string> delete_urls;
+std::vector<LLCurl::ResponderPtr> delete_responders;
+
+void LLHTTPClient::del(
+	const std::string& url,
+	LLCurl::ResponderPtr responder,
+	const LLSD& headers,
+	const F32 timeout)
+{
+	delete_urls.push_back(url);
+	delete_responders.push_back(responder);
+}
 
 namespace tut
 {
@@ -64,6 +78,9 @@ namespace tut
 			put_urls.clear();
 			put_responders.clear();
 			put_body.clear();
+			put_headers.clear();
+			delete_urls.clear();
+			delete_responders.clear();
 		}
 	};
 
@@ -73,7 +90,7 @@ namespace tut
 
 namespace
 {
-	tut::factory tf("LLHTTPClientAdapterData test");
+	tut::factory tf("LLHTTPClientAdapterData");
 }
 
 namespace tut
@@ -91,7 +108,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		adapter.get("Made up URL", responder);
 		ensure_equals(get_urls.size(), 1);
@@ -103,7 +120,7 @@ namespace tut
 	void object::test<3>()
 	{
 		LLHTTPClientAdapter adapter;
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		adapter.get("Made up URL", responder);
 
@@ -117,7 +134,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		LLSD body;
 		body["TestBody"] = "Foobar";
@@ -133,7 +150,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		LLSD body;
 		body["TestBody"] = "Foobar";
@@ -150,7 +167,7 @@ namespace tut
 	{
 		LLHTTPClientAdapter adapter;
 
-		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
 
 		LLSD body;
 		body["TestBody"] = "Foobar";
@@ -160,5 +177,45 @@ namespace tut
 		ensure_equals(put_body.size(), 1);
 		ensure_equals(put_body[0]["TestBody"].asString(), "Foobar");
 	}
+
+	// Ensure that headers are passed through put properly
+	template<> template<>
+	void object::test<7>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
+
+		LLSD body = LLSD::emptyMap();
+		body["TestBody"] = "Foobar";
+
+		LLSD headers = LLSD::emptyMap();
+		headers["booger"] = "omg";
+
+		adapter.put("Made up URL", body, responder, headers);
+
+		ensure_equals("Header count", put_headers.size(), 1);
+		ensure_equals(
+			"First header",
+			put_headers[0]["booger"].asString(),
+			"omg");
+	}
+
+	// Ensure that del() passes appropriate arguments to the LLHTTPClient
+	template<> template<>
+	void object::test<8>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		LLCurl::ResponderPtr responder = new LLCurl::Responder();
+
+		adapter.del("Made up URL", responder);
+
+		ensure_equals("URL count", delete_urls.size(), 1);
+		ensure_equals("Received URL", delete_urls[0], "Made up URL");
+
+		ensure_equals("Responder count", delete_responders.size(), 1);
+		//ensure_equals("Responder", delete_responders[0], responder);
+	}
 }
 
diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp
index aed5c4589c..f8bf03bbcb 100644
--- a/indra/llmessage/tests/llmime_test.cpp
+++ b/indra/llmessage/tests/llmime_test.cpp
@@ -29,6 +29,7 @@
 #include "linden_common.h"
 
 #include "llsdserialize.h"
+#include "llhttpconstants.cpp"
 
 #include "../llmime.h"
 
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
deleted file mode 100644
index 5b89f2a8c6..0000000000
--- a/indra/llmessage/tests/llregionpresenceverifier_test.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/** 
- * @file 
- * @brief 
- *
- * $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 "linden_common.h"
-
-#include "../test/lltut.h"
-#include "llregionpresenceverifier.h"
-#include "llcurl_stub.cpp"
-#include "llhost.cpp"
-#include "net.cpp"
-#include "lltesthttpclientadapter.cpp"
-
-class LLTestResponse : public LLRegionPresenceVerifier::Response
-{
-public:
-
-	virtual bool checkValidity(const LLSD& content) const
-	{
-		return true;
-	}
-
-	virtual void onRegionVerified(const LLSD& region_details)
-	{
-	}
-
-	virtual void onRegionVerificationFailed()
-	{
-	}
-	
-	virtual LLHTTPClientInterface& getHttpClient()
-	{
-		return mHttpInterface;
-	}
-
-	LLTestHTTPClientAdapter mHttpInterface;
-};
-
-namespace tut
-{
-	struct LLRegionPresenceVerifierData
-	{
-		LLRegionPresenceVerifierData() :
-			mResponse(new LLTestResponse()),
-			mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
-					   LLSD(), 3)
-		{
-		}
-		
-		LLTestResponse* mResponse;
-		LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
-	};
-
-	typedef test_group<LLRegionPresenceVerifierData> factory;
-	typedef factory::object object;
-}
-
-namespace
-{
-	tut::factory tf("LLRegionPresenceVerifier");
-}
-
-namespace tut
-{
-	// Test that VerifiedDestinationResponder does retry
-    // on error when shouldRetry returns true.
-	template<> template<>
-	void object::test<1>()
-	{
-		mResponder.error(500, "Internal server error");
-		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
-	}
-
-	// Test that VerifiedDestinationResponder only retries
-	// on error until shouldRetry returns false.
-	template<> template<>
-	void object::test<2>()
-	{
-		mResponder.error(500, "Internal server error");
-		mResponder.error(500, "Internal server error");
-		mResponder.error(500, "Internal server error");
-		mResponder.error(500, "Internal server error");
-		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
-	}
-}
-
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index baedac1f2d..eb41c0aa3a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2068,10 +2068,21 @@ if (LL_TESTS)
     #llviewertexturelist.cpp
   )
 
+  set(test_libs
+    ${JSONCPP_LIBRARIES}
+    ${CURL_LIBRARIES}
+    )
+
   set_source_files_properties(
     lltranslate.cpp
     PROPERTIES
-    LL_TEST_ADDITIONAL_LIBRARIES "${JSONCPP_LIBRARIES}"
+    LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
+  )
+
+  set_source_files_properties(
+    llmediadataclient.cpp
+    PROPERTIES
+    LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}"
   )
 
   set_source_files_properties(
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index 7662a9689d..55d453cdcc 100644
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -36,6 +36,7 @@ LLAccountingCostManager::LLAccountingCostManager()
 //===============================================================================
 class LLAccountingCostResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLAccountingCostResponder);
 public:
 	LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle )
 	: mObjectIDs( objectIDs ),
@@ -56,24 +57,27 @@ public:
 		}
 	}
 	
-	void errorWithContent( U32 statusNum, const std::string& reason, const LLSD& content )
+protected:
+	void httpFailure()
 	{
-		llwarns << "Transport error [status:" << statusNum << "]: " << content <<llendl;
+		llwarns << dumpResponse() << llendl;
 		clearPendingRequests();
 
 		LLAccountingCostObserver* observer = mObserverHandle.get();
 		if (observer && observer->getTransactionID() == mTransactionID)
 		{
-			observer->setErrorStatus(statusNum, reason);
+			observer->setErrorStatus(getStatus(), getReason());
 		}
 	}
 	
-	void result( const LLSD& content )
+	void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		//Check for error
 		if ( !content.isMap() || content.has("error") )
 		{
-			llwarns	<< "Error on fetched data"<< llendl;
+			failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content);
+			return;
 		}
 		else if (content.has("selected"))
 		{
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index 0bca1f54ef..3ade34c81d 100644
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -38,7 +38,7 @@ public:
 	LLAccountingCostObserver() { mObserverHandle.bind(this); }
 	virtual ~LLAccountingCostObserver() {}
 	virtual void onWeightsUpdate(const SelectionCost& selection_cost) = 0;
-	virtual void setErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setErrorStatus(S32 status, const std::string& reason) = 0;
 	const LLHandle<LLAccountingCostObserver>& getObserverHandle() const { return mObserverHandle; }
 	const LLUUID& getTransactionID() { return mTransactionID; }
 
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 20954e4bae..4b0f451036 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -2546,17 +2546,19 @@ int LLAgent::convertTextToMaturity(char text)
 
 class LLMaturityPreferencesResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLMaturityPreferencesResponder);
 public:
 	LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity);
 	virtual ~LLMaturityPreferencesResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
+protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 protected:
 
 private:
-	U8 parseMaturityFromServerResponse(const LLSD &pContent);
+	U8 parseMaturityFromServerResponse(const LLSD &pContent) const;
 
 	LLAgent                                  *mAgent;
 	U8                                       mPreferredMaturity;
@@ -2575,29 +2577,33 @@ LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder()
 {
 }
 
-void LLMaturityPreferencesResponder::result(const LLSD &pContent)
+void LLMaturityPreferencesResponder::httpSuccess()
 {
-	U8 actualMaturity = parseMaturityFromServerResponse(pContent);
+	U8 actualMaturity = parseMaturityFromServerResponse(getContent());
 
 	if (actualMaturity != mPreferredMaturity)
 	{
-		llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity)
-			<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '"
-			<< LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast<U32>(actualMaturity) << ", llsd:"
-			<< pContent << "]" << llendl;
+		llwarns << "while attempting to change maturity preference from '"
+				<< LLViewerRegion::accessToString(mPreviousMaturity)
+				<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) 
+				<< "', the server responded with '"
+				<< LLViewerRegion::accessToString(actualMaturity) 
+				<< "' [value:" << static_cast<U32>(actualMaturity) 
+				<< "], " << dumpResponse() << llendl;
 	}
 	mAgent->handlePreferredMaturityResult(actualMaturity);
 }
 
-void LLMaturityPreferencesResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void LLMaturityPreferencesResponder::httpFailure()
 {
-	llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity)
-		<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error with [status:"
-		<< pStatus << "]: " << (pContent.isDefined() ? pContent : LLSD(pReason)) << llendl;
+	llwarns << "while attempting to change maturity preference from '" 
+			<< LLViewerRegion::accessToString(mPreviousMaturity)
+			<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) 
+			<< "', " << dumpResponse() << llendl;
 	mAgent->handlePreferredMaturityError();
 }
 
-U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent)
+U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) const
 {
 	// stinson 05/24/2012 Pathfinding regions have re-defined the response behavior.  In the old server code,
 	// if you attempted to change the preferred maturity to the same value, the response content would be an
@@ -2605,7 +2611,7 @@ U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &p
 	// defined.  Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged
 	// into server trunk and fully deployed.
 	U8 maturity = SIM_ACCESS_MIN;
-	if (pContent.isUndefined())
+	if (pContent.isUndefined() || !pContent.isMap())
 	{
 		maturity = mPreferredMaturity;
 	}
@@ -2783,7 +2789,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
 		// If we don't have a region, report it as an error
 		if (getRegion() == NULL)
 		{
-			responderPtr->errorWithContent(0U, "region is not defined", LLSD());
+			responderPtr->failureResult(0U, "region is not defined", LLSD());
 		}
 		else
 		{
@@ -2793,7 +2799,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
 			// If the capability is not defined, report it as an error
 			if (url.empty())
 			{
-				responderPtr->errorWithContent(0U, 
+				responderPtr->failureResult(0U, 
 							"capability 'UpdateAgentInformation' is not defined for region", LLSD());
 			}
 			else
@@ -3292,8 +3298,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
 			!input.has("body") )
 		{
 			//what to do with badly formed message?
-			response->statusUnknownError(400);
-			response->result(LLSD("Invalid message parameters"));
+			response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters"));
 		}
 
 		LLSD body = input["body"];
@@ -3362,8 +3367,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
 		else
 		{
 			//what to do with badly formed message?
-			response->statusUnknownError(400);
-			response->result(LLSD("Invalid message parameters"));
+			response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters"));
 		}
 	}
 };
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 2c76efc7fb..92a896a3c2 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2984,20 +2984,23 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount
 public:
 	LLHTTPRetryPolicy() {}
 	virtual ~LLHTTPRetryPolicy() {}
-	virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0;
+	virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0;
 };
 
 // Example of simplest possible policy, not necessarily recommended.
+// This would be a potentially dangerous policy to enable.  Removing for now:
+#if 0
 class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy
 {
 public:
 	LLAlwaysRetryImmediatelyPolicy() {}
-	bool shouldRetry(U32 status, F32& seconds_to_wait)
+	bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait)
 	{
 		seconds_to_wait = 0.0;
 		return true;
 	}
 };
+#endif
 
 // Very general policy with geometric back-off after failures,
 // up to a maximum delay, and maximum number of retries.
@@ -3014,10 +3017,25 @@ public:
 	{
 	}
 
-	bool shouldRetry(U32 status, F32& seconds_to_wait)
+	bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait)
 	{
-		seconds_to_wait = mDelay;
-		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+#if 0
+		// *TODO: Test using status codes to only retry server errors.
+		// Only server errors would potentially return a different result on retry.
+		if (!isHttpServerErrorStatus(status)) return false;
+#endif
+
+#if 0
+		// *TODO: Honor server Retry-After header.
+		// Status 503 may ask us to wait for a certain amount of time before retrying.
+		if (!headers.has(HTTP_HEADER_RETRY_AFTER)
+			|| !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait))
+#endif
+		{
+			seconds_to_wait = mDelay;
+			mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+		}
+
 		mRetryCount++;
 		return (mRetryCount<=mMaxRetries);
 	}
@@ -3033,6 +3051,7 @@ private:
 
 class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
 {
+	LOG_CLASS(RequestAgentUpdateAppearanceResponder);
 public:
 	RequestAgentUpdateAppearanceResponder()
 	{
@@ -3043,13 +3062,19 @@ public:
 	{
 	}
 
+protected:
 	// Successful completion.
-	/* virtual */ void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL;
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		if (content["success"].asBoolean())
 		{
-			LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
+			LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
 			if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 			{
 				dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
@@ -3057,33 +3082,35 @@ public:
 		}
 		else
 		{
-			onFailure(200);
+			failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
 		}
 	}
 
 	// Error
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	/*virtual*/ void httpFailure()
 	{
-		llwarns << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << llendl;
+		const LLSD& content = getContent();
+		LL_WARNS("Avatar") << "appearance update request failed "
+				<< dumpResponse() << LL_ENDL;
 		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
 			dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
 			debugCOF(content);
 		
 		}
-		onFailure(status);
-	}	
+		onFailure();
+	}
 
-	void onFailure(U32 status)
+	void onFailure()
 	{
 		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(status,seconds_to_wait))
+		if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait))
 		{
 			llinfos << "retrying" << llendl;
 			doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate,
 										LLAppearanceMgr::getInstance(),
-										LLCurl::ResponderPtr(this)),
-							seconds_to_wait);
+										LLHTTPClient::ResponderPtr(this)),
+										seconds_to_wait);
 		}
 		else
 		{
@@ -3286,6 +3313,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond
 
 class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLIncrementCofVersionResponder);
 public:
 	LLIncrementCofVersionResponder() : LLHTTPClient::Responder()
 	{
@@ -3296,10 +3324,17 @@ public:
 	{
 	}
 
-	virtual void result(const LLSD &pContent)
+protected:
+	virtual void httpSuccess()
 	{
 		llinfos << "Successfully incremented agent's COF." << llendl;
-		S32 new_version = pContent["category"]["version"].asInteger();
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		S32 new_version = content["category"]["version"].asInteger();
 
 		LLAppearanceMgr* app_mgr = LLAppearanceMgr::getInstance();
 
@@ -3308,12 +3343,13 @@ public:
 
 		app_mgr->mLastUpdateRequestCOFVersion = new_version;
 	}
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content)
+
+	virtual void httpFailure()
 	{
-		llwarns << "While attempting to increment the agent's cof we got an error with [status:"
-				<< pStatus << "]: " << content << llendl;
+		LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error "
+				<< dumpResponse() << LL_ENDL;
 		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait))
+		if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait))
 		{
 			llinfos << "retrying" << llendl;
 			doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion,
@@ -3327,6 +3363,7 @@ public:
 		}
 	}
 
+private:
 	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
 };
 
diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp
index 4bdb690225..cde9bc9dc0 100644
--- a/indra/newview/llassetuploadqueue.cpp
+++ b/indra/newview/llassetuploadqueue.cpp
@@ -36,6 +36,7 @@
 
 class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder
 {
+	LOG_CLASS(LLAssetUploadChainResponder);
 public:
 	
 	LLAssetUploadChainResponder(const LLSD& post_data,
@@ -51,52 +52,54 @@ public:
 		mDataSize(data_size),
 		mScriptName(script_name)
 	{
- 	}
+	}
 
 	virtual ~LLAssetUploadChainResponder() 
-   	{
-   		if(mSupplier)
-   		{
-   			LLAssetUploadQueue *queue = mSupplier->get();
-   			if (queue)
-   			{
-   				// Give ownership of supplier back to queue.
-   				queue->mSupplier = mSupplier;
-   				mSupplier = NULL;
-   			}
-   		}
-   		delete mSupplier;
+	{
+		if(mSupplier)
+		{
+			LLAssetUploadQueue *queue = mSupplier->get();
+			if (queue)
+			{
+				// Give ownership of supplier back to queue.
+				queue->mSupplier = mSupplier;
+				mSupplier = NULL;
+			}
+		}
+		delete mSupplier;
 		delete mData;
-   	}
+	}
 	
-	virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-   	{
-		llwarns << "LLAssetUploadChainResponder Error [status:" 
-				<< statusNum << "]: " << content << llendl;
-		LLUpdateTaskInventoryResponder::errorWithContent(statusNum, reason, content);
-   		LLAssetUploadQueue *queue = mSupplier->get();
-   		if (queue)
+protected:
+	virtual void httpFailure()
+	{
+		// Parent class will spam the failure.
+		//llwarns << dumpResponse() << llendl;
+		LLUpdateTaskInventoryResponder::httpFailure();
+		LLAssetUploadQueue *queue = mSupplier->get();
+		if (queue)
+		{
+			queue->request(&mSupplier);
+		}
+	}
+
+	virtual void httpSuccess()
+	{
+		LLUpdateTaskInventoryResponder::httpSuccess();
+		LLAssetUploadQueue *queue = mSupplier->get();
+		if (queue)
 		{
-   			queue->request(&mSupplier);
-   		}
-   	}
-
-	virtual void result(const LLSD& content)
-   	{
-		LLUpdateTaskInventoryResponder::result(content);
-   		LLAssetUploadQueue *queue = mSupplier->get();
-   		if (queue)
-   		{
-   			// Responder is reused across 2 phase upload,
-   			// so only start next upload after 2nd phase complete.
-   			std::string state = content["state"];
-   			if(state == "complete")
-   			{
-   				queue->request(&mSupplier);
-   			}
-   		}	
-   	}
+			// Responder is reused across 2 phase upload,
+			// so only start next upload after 2nd phase complete.
+			const std::string& state = getContent()["state"].asStringRef();
+			if(state == "complete")
+			{
+				queue->request(&mSupplier);
+			}
+		}
+	}
 	
+public:
 	virtual void uploadUpload(const LLSD& content)
 	{
 		std::string uploader = content["uploader"];
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 2564802387..ea511b18e2 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -225,37 +225,41 @@ LLAssetUploadResponder::~LLAssetUploadResponder()
 }
 
 // virtual
-void LLAssetUploadResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+void LLAssetUploadResponder::httpFailure()
 {
-	llinfos << "LLAssetUploadResponder::error [status:" 
-			<< statusNum << "]: " << content << llendl;
+	// *TODO: Add adaptive retry policy?
+	llwarns << dumpResponse() << llendl;
 	LLSD args;
-	switch(statusNum)
+	if (isHttpClientErrorStatus(getStatus()))
 	{
-		case 400:
-			args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
-			args["REASON"] = "Error in upload request.  Please visit "
-				"http://secondlife.com/support for help fixing this problem.";
-			LLNotificationsUtil::add("CannotUploadReason", args);
-			break;
-		case 500:
-		default:
-			args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
-			args["REASON"] = "The server is experiencing unexpected "
-				"difficulties.";
-			LLNotificationsUtil::add("CannotUploadReason", args);
-			break;
+		args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+		args["REASON"] = "Error in upload request.  Please visit "
+			"http://secondlife.com/support for help fixing this problem.";
+		LLNotificationsUtil::add("CannotUploadReason", args);
+	}
+	else
+	{
+		args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+		args["REASON"] = "The server is experiencing unexpected "
+			"difficulties.";
+		LLNotificationsUtil::add("CannotUploadReason", args);
 	}
 	LLUploadDialog::modalUploadFinished();
 	LLFilePicker::instance().reset();  // unlock file picker when bulk upload fails
 }
 
 //virtual 
-void LLAssetUploadResponder::result(const LLSD& content)
+void LLAssetUploadResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl;
 
-	std::string state = content["state"];
+	const std::string& state = content["state"].asStringRef();
 
 	if (state == "upload")
 	{
@@ -280,7 +284,7 @@ void LLAssetUploadResponder::result(const LLSD& content)
 
 void LLAssetUploadResponder::uploadUpload(const LLSD& content)
 {
-	std::string uploader = content["uploader"];
+	const std::string& uploader = content["uploader"].asStringRef();
 	if (mFileName.empty())
 	{
 		LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this);
@@ -293,6 +297,7 @@ void LLAssetUploadResponder::uploadUpload(const LLSD& content)
 
 void LLAssetUploadResponder::uploadFailure(const LLSD& content)
 {
+	llwarns << dumpResponse() << llendl;
 	// remove the "Uploading..." message
 	LLUploadDialog::modalUploadFinished();
 	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
@@ -301,7 +306,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content)
 		floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
 	}
 	
-	std::string reason = content["state"];
+	const std::string& reason = content["state"].asStringRef();
 	// deal with L$ errors
 	if (reason == "insufficient funds")
 	{
@@ -340,9 +345,9 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
 }
 
 // virtual
-void LLNewAgentInventoryResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+void LLNewAgentInventoryResponder::httpFailure()
 {
-	LLAssetUploadResponder::errorWithContent(statusNum, reason, content);
+	LLAssetUploadResponder::httpFailure();
 	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE);
 }
 
@@ -487,10 +492,9 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
 	}
 }
 
-void LLSendTexLayerResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+void LLSendTexLayerResponder::httpFailure()
 {
-	llinfos << "LLSendTexLayerResponder error [status:"
-			<< statusNum << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 	
 	// Invoke the original callback with an error result
 	LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
@@ -1009,19 +1013,14 @@ LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResp
 	delete mImpl;
 }
 
-void LLNewAgentInventoryVariablePriceResponder::errorWithContent(
-	U32 statusNum,
-	const std::string& reason,
-	const LLSD& content)
+void LLNewAgentInventoryVariablePriceResponder::httpFailure()
 {
-	lldebugs 
-		<< "LLNewAgentInventoryVariablePrice::error " << statusNum 
-		<< " reason: " << reason << llendl;
+	const LLSD& content = getContent();
+	LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
 
-	if ( content.has("error") )
+	static const std::string _ERROR = "error";
+	if ( content.has(_ERROR) )
 	{
-		static const std::string _ERROR = "error";
-
 		mImpl->onTransportError(content[_ERROR]);
 	}
 	else
@@ -1030,8 +1029,14 @@ void LLNewAgentInventoryVariablePriceResponder::errorWithContent(
 	}
 }
 
-void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
+void LLNewAgentInventoryVariablePriceResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	// Parse out application level errors and the appropriate
 	// responses for them
 	static const std::string _ERROR = "error";
@@ -1047,6 +1052,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
 	// Check for application level errors
 	if ( content.has(_ERROR) )
 	{
+		LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
 		onApplicationLevelError(content[_ERROR]);
 		return;
 	}
@@ -1090,6 +1096,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
 	}
 	else
 	{
+		LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
 		onApplicationLevelError("");
 	}
 }
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index a6d1016136..abfdc4ca77 100644
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -33,6 +33,8 @@
 // via capabilities
 class LLAssetUploadResponder : public LLHTTPClient::Responder
 {
+protected:
+	LOG_CLASS(LLAssetUploadResponder);
 public:
 	LLAssetUploadResponder(const LLSD& post_data,
 							const LLUUID& vfile_id,
@@ -42,8 +44,11 @@ public:
 							LLAssetType::EType asset_type);
 	~LLAssetUploadResponder();
 
-    virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content);
-	virtual void result(const LLSD& content);
+protected:
+	virtual void httpFailure();
+	virtual void httpSuccess();
+
+public:
 	virtual void uploadUpload(const LLSD& content);
 	virtual void uploadComplete(const LLSD& content);
 	virtual void uploadFailure(const LLSD& content);
@@ -58,6 +63,7 @@ protected:
 // TODO*: Remove this once deprecated
 class LLNewAgentInventoryResponder : public LLAssetUploadResponder
 {
+	LOG_CLASS(LLNewAgentInventoryResponder);
 public:
 	LLNewAgentInventoryResponder(
 		const LLSD& post_data,
@@ -67,9 +73,10 @@ public:
 		const LLSD& post_data,
 		const std::string& file_name,
 		LLAssetType::EType asset_type);
-    virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content);
 	virtual void uploadComplete(const LLSD& content);
 	virtual void uploadFailure(const LLSD& content);
+protected:
+	virtual void httpFailure();
 };
 
 // A base class which goes through and performs some default
@@ -79,6 +86,7 @@ public:
 class LLNewAgentInventoryVariablePriceResponder :
 	public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLNewAgentInventoryVariablePriceResponder);
 public:
 	LLNewAgentInventoryVariablePriceResponder(
 		const LLUUID& vfile_id,
@@ -91,12 +99,11 @@ public:
 		const LLSD& inventory_info);
 	virtual ~LLNewAgentInventoryVariablePriceResponder();
 
-	void errorWithContent(
-		U32 statusNum,
-		const std::string& reason,
-		const LLSD& content);
-	void result(const LLSD& content);
+private:
+	/* virtual */ void httpFailure();
+	/* virtual */ void httpSuccess();
 
+public:
 	virtual void onApplicationLevelError(
 		const LLSD& error);
 	virtual void showConfirmationDialog(
@@ -122,8 +129,11 @@ public:
 	~LLSendTexLayerResponder();
 
 	virtual void uploadComplete(const LLSD& content);
-	virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content);
 
+protected:
+	virtual void httpFailure();
+
+private:
 	LLBakedUploadData * mBakedUploadData;
 };
 
diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp
index e3cd83e174..923662e887 100644
--- a/indra/newview/llclassifiedstatsresponder.cpp
+++ b/indra/newview/llclassifiedstatsresponder.cpp
@@ -44,8 +44,14 @@ mClassifiedID(classified_id)
 }
 
 /*virtual*/
-void LLClassifiedStatsResponder::result(const LLSD& content)
+void LLClassifiedStatsResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	S32 teleport = content["teleport_clicks"].asInteger();
 	S32 map = content["map_clicks"].asInteger();
 	S32 profile = content["profile_clicks"].asInteger();
@@ -62,7 +68,8 @@ void LLClassifiedStatsResponder::result(const LLSD& content)
 }
 
 /*virtual*/
-void LLClassifiedStatsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLClassifiedStatsResponder::httpFailure()
 {
-	llinfos << "LLClassifiedStatsResponder::error [status:" << status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 }
+
diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h
index 06dcb62fd0..efa4d82411 100644
--- a/indra/newview/llclassifiedstatsresponder.h
+++ b/indra/newview/llclassifiedstatsresponder.h
@@ -33,13 +33,15 @@
 
 class LLClassifiedStatsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLClassifiedStatsResponder);
 public:
 	LLClassifiedStatsResponder(LLUUID classified_id);
+
+protected:
 	//If we get back a normal response, handle it here
-	virtual void result(const LLSD& content);
+	virtual void httpSuccess();
 	//If we get back an error (not found, etc...), handle it here
-	
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	virtual void httpFailure();
 
 protected:
 	LLUUID mClassifiedID;
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index 2669b0340f..db2c15a444 100644
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -112,19 +112,19 @@ void LLEstateInfoModel::notifyCommit()
 
 class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 {
-public:
-
+	LOG_CLASS(LLEstateChangeInfoResponder);
+protected:
 	// if we get a normal response, handle it here
-	virtual void result(const LLSD& content)
+	virtual void httpSuccesss()
 	{
 		llinfos << "Committed estate info" << llendl;
 		LLEstateInfoModel::instance().notifyCommit();
 	}
 
 	// if we get an error response
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	virtual void httpFailure()
 	{
-		llwarns << "Failed to commit estate info [status:" << status << "]: " << content << llendl;
+		llwarns << "Failed to commit estate info " << dumpResponse() << llendl;
 	}
 };
 
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index e0f7223a8c..c3b53d5e4a 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -31,7 +31,7 @@
 #include "llagent.h"
 
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llsdserialize.h"
 #include "lleventtimer.h"
 #include "llviewerregion.h"
@@ -49,6 +49,7 @@ namespace
 
 	class LLEventPollResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(LLEventPollResponder);
 	public:
 		
 		static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender);
@@ -56,19 +57,19 @@ namespace
 		
 		void makeRequest();
 
+		/* virtual */ void completedRaw(const LLChannelDescriptors& channels,
+								  const LLIOPipe::buffer_ptr_t& buffer);
+
 	private:
 		LLEventPollResponder(const std::string&	pollURL, const LLHost& sender);
 		~LLEventPollResponder();
 
 		
 		void handleMessage(const LLSD& content);
-		virtual	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-		virtual	void result(const LLSD&	content);
 
-		virtual void completedRaw(U32 status,
-									const std::string& reason,
-									const LLChannelDescriptors& channels,
-									const LLIOPipe::buffer_ptr_t& buffer);
+		/* virtual */ void httpFailure();
+		/* virtual */ void httpSuccess();
+
 	private:
 
 		bool	mDone;
@@ -149,20 +150,18 @@ namespace
 	}
 
 	// virtual 
-	void LLEventPollResponder::completedRaw(U32 status,
-									const std::string& reason,
-									const LLChannelDescriptors& channels,
-									const LLIOPipe::buffer_ptr_t& buffer)
+	void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels,
+											const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		if (status == HTTP_BAD_GATEWAY)
+		if (getStatus() == HTTP_BAD_GATEWAY)
 		{
 			// These errors are not parsable as LLSD, 
 			// which LLHTTPClient::Responder::completedRaw will try to do.
-			completed(status, reason, LLSD());
+			httpCompleted();
 		}
 		else
 		{
-			LLHTTPClient::Responder::completedRaw(status,reason,channels,buffer);
+			LLHTTPClient::Responder::completedRaw(channels,buffer);
 		}
 	}
 
@@ -187,13 +186,13 @@ namespace
 	}
 
 	//virtual
-	void LLEventPollResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	void LLEventPollResponder::httpFailure()
 	{
 		if (mDone) return;
 
 		// A HTTP_BAD_GATEWAY (502) error is our standard timeout response
 		// we get this when there are no events.
-		if ( status == HTTP_BAD_GATEWAY )	
+		if ( getStatus() == HTTP_BAD_GATEWAY )
 		{
 			mErrorCount = 0;
 			makeRequest();
@@ -207,12 +206,12 @@ namespace
 										+ mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC
 									, this);
 
-			llwarns << "LLEventPollResponder error [status:" << status << "]: " << content << llendl;
+			llwarns << dumpResponse() << llendl;
 		}
 		else
 		{
-			llwarns << "LLEventPollResponder error <" << mCount 
-					<< "> [status:" << status << "]: " << content
+			llwarns << dumpResponse()
+					<< " [count:" << mCount << "] "
 					<< (mDone ? " -- done" : "") << llendl;
 			stop();
 
@@ -234,7 +233,7 @@ namespace
 	}
 
 	//virtual
-	void LLEventPollResponder::result(const LLSD& content)
+	void LLEventPollResponder::httpSuccess()
 	{
 		lldebugs <<	"LLEventPollResponder::result <" << mCount	<< ">"
 				 <<	(mDone ? " -- done"	: "") << llendl;
@@ -243,10 +242,12 @@ namespace
 
 		mErrorCount = 0;
 
-		if (!content.get("events") ||
+		const LLSD& content = getContent();
+		if (!content.isMap() ||
+			!content.get("events") ||
 			!content.get("id"))
 		{
-			llwarns << "received event poll with no events or id key" << llendl;
+			llwarns << "received event poll with no events or id key: " << dumpResponse() << llendl;
 			makeRequest();
 			return;
 		}
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index a4cadcd5dc..c4ae718082 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -39,6 +39,7 @@
 #include "llsecondlifeurls.h"
 
 #include "llappviewer.h"
+#include "llbufferstream.h"
 #include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llviewercontrol.h"
@@ -509,6 +510,7 @@ void LLFeatureManager::parseGPUTable(std::string filename)
 // responder saves table into file
 class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLHTTPFeatureTableResponder);
 public:
 
 	LLHTTPFeatureTableResponder(std::string filename) :
@@ -517,11 +519,10 @@ public:
 	}
 
 	
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		if (isGoodStatus(status))
+		if (isGoodStatus())
 		{
 			// write to file
 
@@ -540,7 +541,18 @@ public:
 				out.close();
 			}
 		}
-		
+		else
+		{
+			char body[1025]; 
+			body[1024] = '\0';
+			LLBufferStream istr(channels, buffer.get());
+			istr.get(body,1024);
+			if (strlen(body) > 0)
+			{
+				mContent["body"] = body;
+			}
+			llwarns << dumpResponse() << llendl;
+		}
 	}
 	
 private:
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index d13f85baa2..89d74666f7 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -1240,9 +1240,9 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
 {
 	GtkFileFilter *gfilter = gtk_file_filter_new();
 	gtk_file_filter_add_pattern(gfilter, "*.tga");
-	gtk_file_filter_add_mime_type(gfilter, "image/jpeg");
-	gtk_file_filter_add_mime_type(gfilter, "image/png");
-	gtk_file_filter_add_mime_type(gfilter, "image/bmp");
+	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str());
+	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str());
+	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str());
 	std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
 	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
 	return filtername;
@@ -1250,13 +1250,13 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
  
 static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
 {
-	return add_simple_mime_filter_to_gtkchooser(picker,  "text/plain",
+	return add_simple_mime_filter_to_gtkchooser(picker,  HTTP_CONTENT_TEXT_PLAIN,
 							LLTrans::getString("script_files") + " (*.lsl)");
 }
 
 static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
 {
-	return add_simple_mime_filter_to_gtkchooser(picker,  "text/plain",
+	return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
 							LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
 }
 
@@ -1294,7 +1294,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
 			break;
 		case FFSAVE_BMP:
 			caption += add_simple_mime_filter_to_gtkchooser
-				(picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)");
+				(picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)");
 			suggest_ext = ".bmp";
 			break;
 		case FFSAVE_AVI:
@@ -1319,6 +1319,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
 			suggest_ext = ".raw";
 			break;
 		case FFSAVE_J2C:
+			// *TODO: Should this be 'image/j2c' ?
 			caption += add_simple_mime_filter_to_gtkchooser
 				(picker, "images/jp2",
 				 LLTrans::getString("compressed_image_files") + " (*.j2c)");
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 83fb887d81..63888ace11 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -77,14 +77,9 @@ class LLServerReleaseNotesURLFetcher : public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLServerReleaseNotesURLFetcher);
 public:
-
 	static void startFetch();
-	/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content);
-	/*virtual*/ void completedRaw(
-		U32 status,
-		const std::string& reason,
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer);
+private:
+	/* virtual */ void httpCompleted();
 };
 
 ///----------------------------------------------------------------------------
@@ -471,32 +466,27 @@ void LLServerReleaseNotesURLFetcher::startFetch()
 }
 
 // virtual
-void LLServerReleaseNotesURLFetcher::completedHeader(U32 status, const std::string& reason, const LLSD& content)
+void LLServerReleaseNotesURLFetcher::httpCompleted()
 {
-	lldebugs << "Status: " << status << llendl;
-	lldebugs << "Reason: " << reason << llendl;
-	lldebugs << "Headers: " << content << llendl;
+	LL_DEBUGS("ServerReleaseNotes") << dumpResponse() 
+		<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
 
 	LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about");
 	if (floater_about)
 	{
-		std::string location = content["location"].asString();
+		const bool check_lower = true;
+		const std::string& location = getResponseHeader(HTTP_HEADER_LOCATION, check_lower);
 		if (location.empty())
 		{
-			location = floater_about->getString("ErrorFetchingServerReleaseNotesURL");
+			LL_WARNS("ServerReleaseNotes") << "Missing Location header "
+				<< dumpResponse() << " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			floater_about->updateServerReleaseNotesURL(
+						floater_about->getString("ErrorFetchingServerReleaseNotesURL"));
+		}
+		else
+		{
+			floater_about->updateServerReleaseNotesURL(location);
 		}
-		floater_about->updateServerReleaseNotesURL(location);
 	}
 }
 
-// virtual
-void LLServerReleaseNotesURLFetcher::completedRaw(
-	U32 status,
-	const std::string& reason,
-	const LLChannelDescriptors& channels,
-	const LLIOPipe::buffer_ptr_t& buffer)
-{
-	// Do nothing.
-	// We're overriding just because the base implementation tries to
-	// deserialize LLSD which triggers warnings.
-}
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 752aba5e16..eaf4d062fe 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -380,12 +380,14 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
 
 class LLAvatarPickerResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLAvatarPickerResponder);
 public:
 	LLUUID mQueryID;
 
 	LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
 
-	/*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content)
+protected:
+	/*virtual*/ void httpCompleted()
 	{
 		//std::ostringstream ss;
 		//LLSDSerialize::toPrettyXML(content, ss);
@@ -393,19 +395,18 @@ public:
 
 		// in case of invalid characters, the avatar picker returns a 400
 		// just set it to process so it displays 'not found'
-		if (isGoodStatus(status) || status == 400)
+		if (isGoodStatus() || getStatus() == HTTP_BAD_REQUEST)
 		{
 			LLFloaterAvatarPicker* floater =
 				LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
 			if (floater)
 			{
-				floater->processResponse(mQueryID, content);
+				floater->processResponse(mQueryID, getContent());
 			}
 		}
 		else
 		{
-			llwarns << "avatar picker failed [status:" << status << "]: " << content << llendl;
-			
+			llwarns << "avatar picker failed " << dumpResponse() << llendl;
 		}
 	}
 };
diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp
index 013cf74c7b..6e641e7d40 100644
--- a/indra/newview/llfloaterbuycurrencyhtml.cpp
+++ b/indra/newview/llfloaterbuycurrencyhtml.cpp
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llfloaterbuycurrencyhtml.h"
+#include "llhttpconstants.h"
 #include "llstatusbar.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -85,7 +86,7 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL()
 	llinfos << "Buy currency HTML parsed URL is " << buy_currency_url << llendl;
 
 	// kick off the navigation
-	mBrowser->navigateTo( buy_currency_url, "text/html" );
+	mBrowser->navigateTo( buy_currency_url, HTTP_CONTENT_TEXT_HTML );
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index 4cb632bd6a..c0bb213540 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -29,6 +29,7 @@
 #include "llfloaterhelpbrowser.h"
 
 #include "llfloaterreg.h"
+#include "llhttpconstants.h"
 #include "llpluginclassmedia.h"
 #include "llmediactrl.h"
 #include "llviewerwindow.h"
@@ -37,7 +38,6 @@
 #include "llui.h"
 
 #include "llurlhistory.h"
-#include "llmediactrl.h"
 #include "llviewermedia.h"
 #include "llviewerhelp.h"
 
@@ -148,7 +148,7 @@ void LLFloaterHelpBrowser::openMedia(const std::string& media_url)
 {
 	// explicitly make the media mime type for this floater since it will
 	// only ever display one type of content (Web).
-	mBrowser->setHomePageUrl(media_url, "text/html");
-	mBrowser->navigateTo(media_url, "text/html");
+	mBrowser->setHomePageUrl(media_url, HTTP_CONTENT_TEXT_HTML);
+	mBrowser->navigateTo(media_url, HTTP_CONTENT_TEXT_HTML);
 	setCurrentURL(media_url);
 }
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index c9f5b42b20..c365666f00 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -5839,7 +5839,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
 	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
 }
 
-void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason)
+void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason)
 {
 	llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl;
 	doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true));
@@ -5915,7 +5915,7 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result)
 	getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm);
 }
 
-void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::string& reason)
+void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status, const std::string& reason)
 {
 	llwarns << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl;
 
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index e588418f7b..6c0c60b87f 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -200,11 +200,11 @@ public:
 	/*virtual*/ void onPermissionsReceived(const LLSD& result);
 
 	// called when error occurs during permissions request
-	/*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setPermissonsErrorStatus(S32 status, const std::string& reason);
 
 	/*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url);
 				void handleModelPhysicsFeeReceived();
-	/*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason);
 
 	/*virtual*/ void onModelUploadSuccess();
 
diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp
index 6d3800bfa4..9f1fc06e14 100644
--- a/indra/newview/llfloatermodeluploadbase.cpp
+++ b/indra/newview/llfloatermodeluploadbase.cpp
@@ -45,7 +45,7 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissions()
 	if (!url.empty())
 	{
 		llinfos<< typeid(*this).name() <<"::requestAgentUploadPermissions() requesting for upload model permissions from: "<< url <<llendl;
-		LLHTTPClient::get(url, new LLUploadModelPremissionsResponder(getPermObserverHandle()));
+		LLHTTPClient::get(url, new LLUploadModelPermissionsResponder(getPermObserverHandle()));
 	}
 	else
 	{
diff --git a/indra/newview/llfloatermodeluploadbase.h b/indra/newview/llfloatermodeluploadbase.h
index a52bc28687..d9a8879687 100644
--- a/indra/newview/llfloatermodeluploadbase.h
+++ b/indra/newview/llfloatermodeluploadbase.h
@@ -37,13 +37,13 @@ public:
 
 	virtual ~LLFloaterModelUploadBase(){};
 
-	virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0;
 
 	virtual void onPermissionsReceived(const LLSD& result) = 0;
 
 	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0;
 
-	virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0;
 
 	virtual void onModelUploadSuccess() {};
 
diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp
index 0862cd2897..c11a0568a6 100644
--- a/indra/newview/llfloaterobjectweights.cpp
+++ b/indra/newview/llfloaterobjectweights.cpp
@@ -123,7 +123,7 @@ void LLFloaterObjectWeights::onWeightsUpdate(const SelectionCost& selection_cost
 }
 
 //virtual
-void LLFloaterObjectWeights::setErrorStatus(U32 status, const std::string& reason)
+void LLFloaterObjectWeights::setErrorStatus(S32 status, const std::string& reason)
 {
 	const std::string text = getString("nothing_selected");
 
diff --git a/indra/newview/llfloaterobjectweights.h b/indra/newview/llfloaterobjectweights.h
index 9a244573be..1a2c317bad 100644
--- a/indra/newview/llfloaterobjectweights.h
+++ b/indra/newview/llfloaterobjectweights.h
@@ -63,7 +63,7 @@ public:
 	/*virtual*/ void onOpen(const LLSD& key);
 
 	/*virtual*/ void onWeightsUpdate(const SelectionCost& selection_cost);
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 
 	void updateLandImpacts(const LLParcel* parcel);
 	void refresh();
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
index 0cde878055..efc04ac358 100644
--- a/indra/newview/llfloaterregiondebugconsole.cpp
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -73,24 +73,29 @@ namespace
 	// called if this request times out.
 	class AsyncConsoleResponder : public LLHTTPClient::Responder
 	{
-	public:
+		LOG_CLASS(AsyncConsoleResponder);
+	protected:
 		/* virtual */
-		void errorWithContent(U32 status, const std::string& reason)
+		void httpFailure()
 		{
+			LL_WARNS("Console") << dumpResponse() << LL_ENDL;
 			sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
 		}
 	};
 
 	class ConsoleResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(ConsoleResponder);
 	public:
 		ConsoleResponder(LLTextEditor *output) : mOutput(output)
 		{
 		}
 
+	protected:
 		/*virtual*/
-		void error(U32 status, const std::string& reason)
+		void httpFailure()
 		{
+			LL_WARNS("Console") << dumpResponse() << LL_ENDL;
 			if (mOutput)
 			{
 				mOutput->appendText(
@@ -100,8 +105,10 @@ namespace
 		}
 
 		/*virtual*/
-		void result(const LLSD& content)
+		void httpSuccess()
 		{
+			const LLSD& content = getContent();
+			LL_DEBUGS("Console") << content << LL_ENDL;
 			if (mOutput)
 			{
 				mOutput->appendText(
@@ -109,6 +116,7 @@ namespace
 			}
 		}
 
+	public:
 		LLTextEditor * mOutput;
 	};
 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 4a9ea5acf0..6c0e91dd2c 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -754,12 +754,12 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
 
 class ConsoleRequestResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(ConsoleRequestResponder);
+protected:
 	/*virtual*/
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	void httpFailure()
 	{
-		llwarns << "ConsoleRequestResponder error requesting mesh_rez_enabled [status:"
-				<< status << "]: " << content << llendl;
+		llwarns << "error requesting mesh_rez_enabled " << dumpResponse() << llendl;
 	}
 };
 
@@ -767,12 +767,12 @@ public:
 // called if this request times out.
 class ConsoleUpdateResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(ConsoleUpdateResponder);
+protected:
 	/* virtual */
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	void httpFailure()
 	{
-		llwarns << "ConsoleRequestResponder error updating mesh enabled region setting [status:"
-				<< status << "]: " << content << llendl;
+		llwarns << "error updating mesh enabled region setting " << dumpResponse() << llendl;
 	}
 };
 
@@ -2191,14 +2191,16 @@ void LLPanelEstateInfo::getEstateOwner()
 
 class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLEstateChangeInfoResponder);
 public:
 	LLEstateChangeInfoResponder(LLPanelEstateInfo* panel)
 	{
 		mpPanel = panel->getHandle();
 	}
 	
+protected:
 	// if we get a normal response, handle it here
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
 		LL_INFOS("Windlight") << "Successfully committed estate info" << llendl;
 
@@ -2209,10 +2211,9 @@ public:
 	}
 	
 	// if we get an error response
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	virtual void httpFailure()
 	{
-		llinfos << "LLEstateChangeInfoResponder::error [status:"
-			<< status << "]: " << content << llendl;
+		LL_WARNS("Windlight") << dumpResponse() << LL_ENDL;
 	}
 private:
 	LLHandle<LLPanel> mpPanel;
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 685b566fa8..f7fca90ebd 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -692,16 +692,18 @@ public:
 
 class LLUserReportResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLUserReportResponder);
 public:
 	LLUserReportResponder(): LLHTTPClient::Responder()  {}
 
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
-	{
-		// *TODO do some user messaging here
-		LLUploadDialog::modalUploadFinished();
-	}
-	void result(const LLSD& content)
+private:
+	void httpCompleted()
 	{
+		if (!isGoodStatus())
+		{
+			// *TODO do some user messaging here
+			LL_WARNS("UserReport") << dumpResponse() << LL_ENDL;
+		}
 		// we don't care about what the server returns
 		LLUploadDialog::modalUploadFinished();
 	}
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 17c34f1da0..7e94784751 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -183,8 +183,14 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
 // Responders
 ///----------------------------------------------------------------------------
 
-void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
+void fetchScriptLimitsRegionInfoResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	//we don't need to test with a fake respose here (shouldn't anyway)
 
 #ifdef DUMP_REPLIES_TO_LLINFOS
@@ -221,13 +227,14 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
 	}
 }
 
-void fetchScriptLimitsRegionInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsRegionInfoResponder::httpFailure()
 {
-	llwarns << "fetchScriptLimitsRegionInfoResponder error [status:" << status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 }
 
-void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
+void fetchScriptLimitsRegionSummaryResponder::httpSuccess()
 {
+	const LLSD& content_ref = getContent();
 #ifdef USE_FAKE_RESPONSES
 
 	LLSD fake_content;
@@ -268,6 +275,12 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 
 #endif
 
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 
 #ifdef DUMP_REPLIES_TO_LLINFOS
 
@@ -291,7 +304,7 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 		if(tab)
 		{
-		LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
 			if(panel_memory)
 			{
 				panel_memory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
@@ -301,20 +314,21 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 				{
 					btn->setEnabled(true);
 				}
-				
-		panel_memory->setRegionSummary(content);
-	}
-}
+
+				panel_memory->setRegionSummary(content);
+			}
+		}
 	}
 }
 
-void fetchScriptLimitsRegionSummaryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsRegionSummaryResponder::httpFailure()
 {
-	llwarns << "fetchScriptLimitsRegionSummaryResponder error [status:" << status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 }
 
-void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref)
+void fetchScriptLimitsRegionDetailsResponder::httpSuccess()
 {
+	const LLSD& content_ref = getContent();
 #ifdef USE_FAKE_RESPONSES
 /*
 Updated detail service, ** denotes field added:
@@ -377,6 +391,12 @@ result (map)
 
 #endif
 
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 #ifdef DUMP_REPLIES_TO_LLINFOS
 
 	LLSDNotationStreamer notation_streamer(content);
@@ -417,13 +437,14 @@ result (map)
 	}
 }
 
-void fetchScriptLimitsRegionDetailsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsRegionDetailsResponder::httpFailure()
 {
-	llwarns << "fetchScriptLimitsRegionDetailsResponder error [status:" << status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 }
 
-void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
+void fetchScriptLimitsAttachmentInfoResponder::httpSuccess()
 {
+	const LLSD& content_ref = getContent();
 
 #ifdef USE_FAKE_RESPONSES
 
@@ -465,6 +486,12 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
 
 #endif
 
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 #ifdef DUMP_REPLIES_TO_LLINFOS
 
 	LLSDNotationStreamer notation_streamer(content);
@@ -513,9 +540,9 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
 	}
 }
 
-void fetchScriptLimitsAttachmentInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void fetchScriptLimitsAttachmentInfoResponder::httpFailure()
 {
-	llwarns << "fetchScriptLimitsAttachmentInfoResponder error [status:" << status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 }
 
 ///----------------------------------------------------------------------------
@@ -586,7 +613,7 @@ void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
 }
 
 // virtual
-void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason)
+void LLPanelScriptLimitsRegionMemory::setErrorStatus(S32 status, const std::string& reason)
 {
 	llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
 }
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index f8732ef94b..a5cb1b6184 100644
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -85,49 +85,49 @@ protected:
 
 class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
-
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
-		LLSD mInfo;
+	LOG_CLASS(fetchScriptLimitsRegionInfoResponder);
+public:
+	fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
+
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mInfo;
 };
 
 class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
-
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
-		LLSD mInfo;
+	LOG_CLASS(fetchScriptLimitsRegionSummaryResponder);
+public:
+	fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
+
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mInfo;
 };
 
 class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
-
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
-		LLSD mInfo;
+	LOG_CLASS(fetchScriptLimitsRegionDetailsResponder);
+public:
+	fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
+
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mInfo;
 };
 
 class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder
 {
-	public:
-		fetchScriptLimitsAttachmentInfoResponder() {};
+	LOG_CLASS(fetchScriptLimitsAttachmentInfoResponder);
+public:
+	fetchScriptLimitsAttachmentInfoResponder() {};
 
-		void result(const LLSD& content);
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	public:
-	protected:
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 };
 
 /////////////////////////////////////////////////////////////////////////////
@@ -190,7 +190,7 @@ protected:
 // LLRemoteParcelInfoObserver interface:
 /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 /*virtual*/ void setParcelID(const LLUUID& parcel_id);
-/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 	
 	static void onClickRefresh(void* userdata);
 	static void onClickHighlight(void* userdata);
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 2a946b1edf..a446b767ac 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -30,6 +30,7 @@
 #include "llcommandhandler.h"
 #include "llfloaterreg.h"
 #include "llfloatersearch.h"
+#include "llhttpconstants.h"
 #include "llmediactrl.h"
 #include "llnotificationsutil.h"
 #include "lllogininstance.h"
@@ -200,5 +201,5 @@ void LLFloaterSearch::search(const SearchQuery &p)
 	url = LLWeb::expandURLSubstitutions(url, subs);
 
 	// and load the URL in the web view
-	mWebBrowser->navigateTo(url, "text/html");
+	mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 }
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index a242b224cd..0613ffc94d 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -36,7 +36,7 @@
 #include "llbutton.h"
 #include "llevents.h"
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"	// for HTTP_FOUND
+#include "llhttpconstants.h"
 #include "llnotificationsutil.h"
 #include "llradiogroup.h"
 #include "lltextbox.h"
@@ -62,42 +62,46 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& data)
 // on parent class indicating if the web server is working or not
 class LLIamHere : public LLHTTPClient::Responder
 {
-	private:
-		LLIamHere( LLFloaterTOS* parent ) :
-		   mParent( parent )
-		{}
+	LOG_CLASS(LLIamHere);
+private:
+	LLIamHere( LLFloaterTOS* parent ) :
+	   mParent( parent )
+	{}
 
-		LLFloaterTOS* mParent;
+	LLFloaterTOS* mParent;
 
-	public:
-
-		static LLIamHere* build( LLFloaterTOS* parent )
-		{
-			return new LLIamHere( parent );
-		};
-		
-		virtual void  setParent( LLFloaterTOS* parentIn )
-		{
-			mParent = parentIn;
-		};
-		
-		virtual void result( const LLSD& content )
+public:
+	static LLIamHere* build( LLFloaterTOS* parent )
+	{
+		return new LLIamHere( parent );
+	}
+	
+	virtual void  setParent( LLFloaterTOS* parentIn )
+	{
+		mParent = parentIn;
+	}
+	
+protected:
+	virtual void httpSuccess()
+	{
+		if ( mParent )
 		{
-			if ( mParent )
-				mParent->setSiteIsAlive( true );
-		};
+			mParent->setSiteIsAlive( true );
+		}
+	}
 
-		virtual void error( U32 status, const std::string& reason )
+	virtual void httpFailure()
+	{
+		LL_DEBUGS("LLIamHere") << dumpResponse() << LL_ENDL;
+		if ( mParent )
 		{
-			if ( mParent )
-			{
-				// *HACK: For purposes of this alive check, 302 Found
-				// (aka Moved Temporarily) is considered alive.  The web site
-				// redirects this link to a "cache busting" temporary URL. JC
-				bool alive = (status == HTTP_FOUND);
-				mParent->setSiteIsAlive( alive );
-			}
-		};
+			// *HACK: For purposes of this alive check, 302 Found
+			// (aka Moved Temporarily) is considered alive.  The web site
+			// redirects this link to a "cache busting" temporary URL. JC
+			bool alive = (getStatus() == HTTP_FOUND);
+			mParent->setSiteIsAlive( alive );
+		}
+	}
 };
 
 // this is global and not a class member to keep crud out of the header file
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index e85d849c9a..0751c830d5 100644
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -48,31 +48,31 @@ static LLFloaterURLEntry* sInstance = NULL;
 // on the Panel Land Media and to discover the MIME type
 class LLMediaTypeResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLMediaTypeResponder);
 public:
 	LLMediaTypeResponder( const LLHandle<LLFloater> parent ) :
-	  mParent( parent )
-	  {}
-
-	  LLHandle<LLFloater> mParent;
-
-
-	  virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	  {
-		  std::string media_type = content["content-type"].asString();
-		  std::string::size_type idx1 = media_type.find_first_of(";");
-		  std::string mime_type = media_type.substr(0, idx1);
-		  completeAny(status, mime_type);
-	  }
-
-	  void completeAny(U32 status, const std::string& mime_type)
-	  {
-		  // Set empty type to none/none.  Empty string is reserved for legacy parcels
-		  // which have no mime type set.
-		  std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType();
-		  LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
-		  if ( floater_url_entry )
-			  floater_url_entry->headerFetchComplete( status, resolved_mime_type );
-	  }
+		mParent( parent )
+	{}
+
+	LLHandle<LLFloater> mParent;
+
+private:
+	/* virtual */ void httpCompleted()
+	{
+		const bool check_lower = true;
+		const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower);
+		std::string::size_type idx1 = media_type.find_first_of(";");
+		std::string mime_type = media_type.substr(0, idx1);
+
+		// Set empty type to none/none.  Empty string is reserved for legacy parcels
+		// which have no mime type set.
+		std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType();
+		LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
+		if ( floater_url_entry )
+		{
+			floater_url_entry->headerFetchComplete( getStatus(), resolved_mime_type );
+		}
+	}
 };
 
 //-----------------------------------------------------------------------------
@@ -136,7 +136,7 @@ void LLFloaterURLEntry::buildURLHistory()
 	}
 }
 
-void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type)
+void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_type)
 {
 	LLPanelLandMedia* panel_media = dynamic_cast<LLPanelLandMedia*>(mPanelLandMediaHandle.get());
 	if (panel_media)
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index dfb49fe5ac..bdd1ebe592 100644
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -40,7 +40,7 @@ public:
 	// that panel via the handle.
 	static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url);
 	/*virtual*/	BOOL	postBuild();
-	void headerFetchComplete(U32 status, const std::string& mime_type);
+	void headerFetchComplete(S32 status, const std::string& mime_type);
 
 	bool addURLToCombobox(const std::string& media_url);
 
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 3fe2518de6..21b171446f 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -29,6 +29,7 @@
 #include "llcombobox.h"
 #include "lliconctrl.h"
 #include "llfloaterreg.h"
+#include "llhttpconstants.h"
 #include "lllayoutstack.h"
 #include "llpluginclassmedia.h"
 #include "llprogressbar.h"
@@ -234,9 +235,9 @@ void LLFloaterWebContent::open_media(const Params& p)
 {
 	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
 	LLViewerMedia::proxyWindowOpened(p.target(), p.id());
-	mWebBrowser->setHomePageUrl(p.url, "text/html");
+	mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML);
 	mWebBrowser->setTarget(p.target);
-	mWebBrowser->navigateTo(p.url, "text/html");
+	mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML);
 	
 	set_current_url(p.url);
 
@@ -451,7 +452,7 @@ void LLFloaterWebContent::onEnterAddress()
 	std::string url = mAddressCombo->getValue().asString();
 	if ( url.length() > 0 )
 	{
-		mWebBrowser->navigateTo( url, "text/html");
+		mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 	};
 }
 
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index cbd844cdac..472e3862ea 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -1843,23 +1843,31 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
 // Responder class for capability group management
 class GroupMemberDataResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(GroupMemberDataResponder);
 public:
-		GroupMemberDataResponder() {}
-		virtual ~GroupMemberDataResponder() {}
-		virtual void result(const LLSD& pContent);
-		virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
+	GroupMemberDataResponder() {}
+	virtual ~GroupMemberDataResponder() {}
+
 private:
-		LLSD mMemberData;
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+	LLSD mMemberData;
 };
 
-void GroupMemberDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void GroupMemberDataResponder::httpFailure()
 {
-	LL_WARNS("GrpMgr") << "Error receiving group member data [status:" 
-		<< pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS("GrpMgr") << "Error receiving group member data "
+		<< dumpResponse() << LL_ENDL;
 }
 
-void GroupMemberDataResponder::result(const LLSD& content)
+void GroupMemberDataResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LLGroupMgr::processCapGroupMembersRequest(content);
 }
 
diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp
index 37428c4a44..b1286cccf2 100644
--- a/indra/newview/llhomelocationresponder.cpp
+++ b/indra/newview/llhomelocationresponder.cpp
@@ -33,71 +33,76 @@
 #include "llagent.h"
 #include "llviewerregion.h"
 
-void LLHomeLocationResponder::result( const LLSD& content )
+void LLHomeLocationResponder::httpSuccess()
 {
+  const LLSD& content = getContent();
   LLVector3 agent_pos;
   bool      error = true;
-		
+
   do {
-	
+
     // was the call to /agent/<agent-id>/home-location successful?
     // If not, we keep error set to true
     if( ! content.has("success") )
     {
       break;
     }
-		
+
     if( 0 != strncmp("true", content["success"].asString().c_str(), 4 ) )
     {
       break;
     }
-		
+
     // did the simulator return a "justified" home location?
     // If no, we keep error set to true
     if( ! content.has( "HomeLocation" ) )
     {
       break;
     }
-		
+
     if( ! content["HomeLocation"].has("LocationPos") )
     {
       break;
     }
-		
+
     if( ! content["HomeLocation"]["LocationPos"].has("X") )
     {
       break;
     }
 
     agent_pos.mV[VX] = content["HomeLocation"]["LocationPos"]["X"].asInteger();
-		
+
     if( ! content["HomeLocation"]["LocationPos"].has("Y") )
     {
       break;
     }
 
     agent_pos.mV[VY] = content["HomeLocation"]["LocationPos"]["Y"].asInteger();
-		
+
     if( ! content["HomeLocation"]["LocationPos"].has("Z") )
     {
       break;
     }
 
     agent_pos.mV[VZ] = content["HomeLocation"]["LocationPos"]["Z"].asInteger();
-		
+
     error = false;
   } while( 0 );
-	
-  if( ! error )
+
+  if( error )
+  {
+    failureResult(HTTP_INTERNAL_ERROR, "Invalid server response content", content);
+  }
+  else
   {
     llinfos << "setting home position" << llendl;
-		
+
     LLViewerRegion *viewer_region = gAgent.getRegion();
     gAgent.setHomePosRegion( viewer_region->getHandle(), agent_pos );
   }
 }
 
-void LLHomeLocationResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content )
+void LLHomeLocationResponder::httpFailure()
 {
-	llwarns << "LLHomeLocationResponder error [status:" << status << "]: " << content << llendl;
+  llwarns << dumpResponse() << llendl;
 }
diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h
index 9bf4b12c4e..adc6c8cb58 100644
--- a/indra/newview/llhomelocationresponder.h
+++ b/indra/newview/llhomelocationresponder.h
@@ -35,8 +35,10 @@
 /* Typedef, Enum, Class, Struct, etc. */
 class LLHomeLocationResponder : public LLHTTPClient::Responder
 {
-	virtual void result( const LLSD& content );
-	virtual void errorWithContent( U32 status, const std::string& reason, const LLSD& content );
+	LOG_CLASS(LLHomeLocationResponder);
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 };
 
 #endif
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index fff178f8fe..c933d5428d 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -979,16 +979,17 @@ BOOL LLIMFloater::isInviteAllowed() const
 
 class LLSessionInviteResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLSessionInviteResponder);
 public:
 	LLSessionInviteResponder(const LLUUID& session_id)
 	{
 		mSessionID = session_id;
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+protected:
+	void httpFailure()
 	{
-		llwarns << "Error inviting all agents to session [status:" 
-				<< statusNum << "]: " << content << llendl;
+		llwarns << "Error inviting all agents to session " << dumpResponse() << llendl;
 		//throw something back to the viewer here?
 	}
 
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 1dab0e67bf..95ede326e6 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -388,16 +388,17 @@ void LLFloaterIMPanel::draw()
 
 class LLSessionInviteResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLSessionInviteResponder);
 public:
 	LLSessionInviteResponder(const LLUUID& session_id)
 	{
 		mSessionID = session_id;
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+protected:
+	void httpFailure()
 	{
-		llwarns << "Error inviting all agents to session [status:" 
-				<< statusNum << "]: " << content << llendl;
+		llwarns << "Error inviting all agents to session " << dumpResponse() << llendl;
 		//throw something back to the viewer here?
 	}
 
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 20b33c5d08..a00de8eb26 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -1214,6 +1214,7 @@ void start_deprecated_conference_chat(
 
 class LLStartConferenceChatResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLStartConferenceChatResponder);
 public:
 	LLStartConferenceChatResponder(
 		const LLUUID& temp_session_id,
@@ -1227,10 +1228,12 @@ public:
 		mAgents = agents_to_invite;
 	}
 
-	virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+protected:
+	virtual void httpFailure()
 	{
 		//try an "old school" way.
-		if ( statusNum == 400 )
+		// *TODO: What about other error status codes?  4xx 5xx?
+		if ( getStatus() == HTTP_BAD_REQUEST )
 		{
 			start_deprecated_conference_chat(
 				mTempSessionID,
@@ -1239,8 +1242,7 @@ public:
 				mAgents);
 		}
 
-		llwarns << "LLStartConferenceChatResponder error [status:"
-				<< statusNum << "]: " << content << llendl;
+		llwarns << dumpResponse() << llendl;
 
 		//else throw an error back to the client?
 		//in theory we should have just have these error strings
@@ -1332,6 +1334,7 @@ bool LLIMModel::sendStartSession(
 class LLViewerChatterBoxInvitationAcceptResponder :
 	public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLViewerChatterBoxInvitationAcceptResponder);
 public:
 	LLViewerChatterBoxInvitationAcceptResponder(
 		const LLUUID& session_id,
@@ -1341,8 +1344,15 @@ public:
 		mInvitiationType = invitation_type;
 	}
 
-	void result(const LLSD& content)
+private:
+	void httpSuccess()
 	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		if ( gIMMgr)
 		{
 			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
@@ -1387,19 +1397,17 @@ public:
 		}
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+	void httpFailure()
 	{
-		llwarns << "LLViewerChatterBoxInvitationAcceptResponder error [status:"
-				<< statusNum << "]: " << content << llendl;
+		llwarns << dumpResponse() << llendl;
 		//throw something back to the viewer here?
 		if ( gIMMgr )
 		{
 			gIMMgr->clearPendingAgentListUpdates(mSessionID);
 			gIMMgr->clearPendingInvitation(mSessionID);
-			if ( 404 == statusNum )
+			if ( HTTP_NOT_FOUND == getStatus() )
 			{
-				std::string error_string;
-				error_string = "session_does_not_exist_error";
+				static const std::string error_string("session_does_not_exist_error");
 				gIMMgr->showSessionStartError(error_string, mSessionID);
 			}
 		}
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index aafc43b02d..1f719a22ef 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -495,21 +495,23 @@ void LLInspectAvatar::toggleSelectedVoice(bool enabled)
 
 		class MuteVoiceResponder : public LLHTTPClient::Responder
 		{
+			LOG_CLASS(MuteVoiceResponder);
 		public:
 			MuteVoiceResponder(const LLUUID& session_id)
 			{
 				mSessionID = session_id;
 			}
 
-			virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+		protected:
+			virtual void httpFailure()
 			{
-				llwarns << "MuteVoiceResponder error [status:" << status << "]: " << content << llendl;
+				llwarns << dumpResponse() << llendl;
 
 				if ( gIMMgr )
 				{
 					//403 == you're not a mod
 					//should be disabled if you're not a moderator
-					if ( 403 == status )
+					if ( HTTP_FORBIDDEN == getStatus() )
 					{
 						gIMMgr->showSessionEventError(
 							"mute",
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 99e72cdb22..0b2f80403d 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -414,6 +414,7 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe
 
 class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLCreateInventoryCategoryResponder);
 public:
 	LLCreateInventoryCategoryResponder(LLInventoryModel* model, 
 									   void (*callback)(const LLSD&, void*),
@@ -424,16 +425,21 @@ public:
 	{
 	}
 	
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+protected:
+	virtual void httpFailure()
 	{
-		LL_WARNS("InvAPI") << "CreateInventoryCategory failed [status:"
-				<< status << "]: " << content << LL_ENDL;
+		LL_WARNS("InvAPI") << dumpResponse() << LL_ENDL;
 	}
 	
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
 		//Server has created folder.
-		
+		const LLSD& content = getContent();
+		if (!content.isMap() || !content.has("folder_id"))
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLUUID category_id = content["folder_id"].asUUID();
 		
 		
@@ -1340,8 +1346,14 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
 }
 
 // If we get back a normal response, handle it here
-void  LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
-{	
+void LLInventoryModel::fetchInventoryResponder::httpSuccess()
+{
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	start_new_inventory_observer();
 
 	/*LLUUID agent_id;
@@ -1400,9 +1412,9 @@ void  LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
 }
 
 //If we get back an error (not found, etc...), handle it here
-void LLInventoryModel::fetchInventoryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLInventoryModel::fetchInventoryResponder::httpFailure()
 {
-	llwarns << "fetchInventory error [status:" << status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 	gInventory.notifyObservers();
 }
 
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index dfdd237c95..9c2ca8cae9 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -81,11 +81,12 @@ public:
 
 	class fetchInventoryResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(fetchInventoryResponder);
 	public:
 		fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
-		void result(const LLSD& content);			
-		void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
 	protected:
+		virtual void httpSuccess();
+		virtual void httpFailure();
 		LLSD mRequestSD;
 	};
 
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index f2b39e7186..e1537033f9 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -363,35 +363,39 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching)
 
 class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
 {
+	LOG_CLASS(LLInventoryModelFetchItemResponder);
 public:
 	LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
-	void result(const LLSD& content);			
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 };
 
-void LLInventoryModelFetchItemResponder::result( const LLSD& content )
+void LLInventoryModelFetchItemResponder::httpSuccess()
 {
-	LLInventoryModel::fetchInventoryResponder::result(content);
+	LLInventoryModel::fetchInventoryResponder::httpSuccess();
 	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
 }
 
-void LLInventoryModelFetchItemResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content )
+void LLInventoryModelFetchItemResponder::httpFailure()
 {
-	LLInventoryModel::fetchInventoryResponder::errorWithContent(status, reason, content);
+	LLInventoryModel::fetchInventoryResponder::httpFailure();
 	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
 }
 
 
 class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLInventoryModelFetchDescendentsResponder);
 public:
 	LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : 
 		mRequestSD(request_sd),
 		mRecursiveCatUUIDs(recursive_cats)
 	{};
 	//LLInventoryModelFetchDescendentsResponder() {};
-	void result(const LLSD& content);
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 protected:
 	BOOL getIsRecursive(const LLUUID& cat_id) const;
 private:
@@ -400,8 +404,14 @@ private:
 };
 
 // If we get back a normal response, handle it here.
-void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
+void LLInventoryModelFetchDescendentsResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
 	if (content.has("folders"))	
 	{
@@ -508,11 +518,12 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
 		for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
 			folder_it != content["bad_folders"].endArray();
 			++folder_it)
-		{	
+		{
+			// *TODO: Stop copying data
 			LLSD folder_sd = *folder_it;
 			
 			// These folders failed on the dataserver.  We probably don't want to retry them.
-			llinfos << "Folder " << folder_sd["folder_id"].asString() 
+			llwarns << "Folder " << folder_sd["folder_id"].asString() 
 					<< "Error: " << folder_sd["error"].asString() << llendl;
 		}
 	}
@@ -529,21 +540,19 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
 }
 
 // If we get back an error (not found, etc...), handle it here.
-void LLInventoryModelFetchDescendentsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLInventoryModelFetchDescendentsResponder::httpFailure()
 {
+	llwarns << dumpResponse() << llendl;
 	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
 
-	llinfos << "LLInventoryModelFetchDescendentsResponder::error [status:"
-			<< status << "]: " << content << llendl;
-						
 	fetcher->incrFetchCount(-1);
 
-	if (status==499) // timed out
+	if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure
 	{
 		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
 			folder_it != mRequestSD["folders"].endArray();
 			++folder_it)
-		{	
+		{
 			LLSD folder_sd = *folder_it;
 			LLUUID folder_id = folder_sd["folder_id"];
 			const BOOL recursive = getIsRecursive(folder_id);
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 0b009b68f7..bea1d62b93 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -99,7 +99,7 @@ namespace LLMarketplaceImport
 	bool hasSessionCookie();
 	bool inProgress();
 	bool resultPending();
-	U32 getResultStatus();
+	S32 getResultStatus();
 	const LLSD& getResults();
 
 	bool establishMarketplaceSessionCookie();
@@ -113,7 +113,7 @@ namespace LLMarketplaceImport
 	static bool sImportInProgress = false;
 	static bool sImportPostPending = false;
 	static bool sImportGetPending = false;
-	static U32 sImportResultStatus = 0;
+	static S32 sImportResultStatus = 0;
 	static LLSD sImportResults = LLSD::emptyMap();
 
 	static LLTimer slmGetTimer;
@@ -123,22 +123,22 @@ namespace LLMarketplaceImport
 	
 	class LLImportPostResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(LLImportPostResponder);
 	public:
 		LLImportPostResponder() : LLCurl::Responder() {}
-		
-		void completed(U32 status, const std::string& reason, const LLSD& content)
+
+	protected:
+		/* virtual */ void httpCompleted()
 		{
 			slmPostTimer.stop();
 
 			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 			{
-				llinfos << " SLM POST status: " << status << llendl;
-				llinfos << " SLM POST reason: " << reason << llendl;
-				llinfos << " SLM POST content: " << content.asString() << llendl;
-
-				llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl;
+				llinfos << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] "
+						<< dumpResponse() << llendl;
 			}
 
+			S32 status = getStatus();
 			if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
 				(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
 				(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
@@ -154,38 +154,36 @@ namespace LLMarketplaceImport
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
 			sImportPostPending = false;
 			sImportResultStatus = status;
-			sImportId = content;
+			sImportId = getContent();
 		}
 	};
 	
 	class LLImportGetResponder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(LLImportGetResponder);
 	public:
 		LLImportGetResponder() : LLCurl::Responder() {}
 		
-		void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	protected:
+		/* virtual */ void httpCompleted()
 		{
-			const std::string& set_cookie_string = content["set-cookie"].asString();
+			const bool check_lower = true;
+			const std::string& set_cookie_string = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower);
 			
 			if (!set_cookie_string.empty())
 			{
 				sMarketplaceCookie = set_cookie_string;
 			}
-		}
-		
-		void completed(U32 status, const std::string& reason, const LLSD& content)
-		{
+
 			slmGetTimer.stop();
 
 			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 			{
-				llinfos << " SLM GET status: " << status << llendl;
-				llinfos << " SLM GET reason: " << reason << llendl;
-				llinfos << " SLM GET content: " << content.asString() << llendl;
-
-				llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl;
+				llinfos << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] "
+						<< dumpResponse() << llendl;
 			}
 			
+			S32 status = getStatus();
 			if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
 				(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
 			{
@@ -200,7 +198,7 @@ namespace LLMarketplaceImport
 			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
 			sImportGetPending = false;
 			sImportResultStatus = status;
-			sImportResults = content;
+			sImportResults = getContent();
 		}
 	};
 
@@ -221,7 +219,7 @@ namespace LLMarketplaceImport
 		return (sImportPostPending || sImportGetPending);
 	}
 	
-	U32 getResultStatus()
+	S32 getResultStatus()
 	{
 		return sImportResultStatus;
 	}
@@ -280,10 +278,10 @@ namespace LLMarketplaceImport
 
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Cookie"] = sMarketplaceCookie;
-		headers["Content-Type"] = "application/llsd+xml";
-		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
+		headers[HTTP_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie;
+		headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+		headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
 		
 		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 		{
@@ -313,11 +311,12 @@ namespace LLMarketplaceImport
 		
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Connection"] = "Keep-Alive";
-		headers["Cookie"] = sMarketplaceCookie;
-		headers["Content-Type"] = "application/xml";
-		headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
+		headers[HTTP_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_HEADER_CONNECTION] = "Keep-Alive";
+		headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie;
+		// *TODO: Should this be 'application/llsd+xml'?
+		headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
+		headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
 		
 		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 		{
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 2075aeed63..cb5640b4da 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -52,6 +52,7 @@
 #include "llsdutil.h"
 #include "lllayoutstack.h"
 #include "lliconctrl.h"
+#include "llhttpconstants.h"
 #include "lltextbox.h"
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
@@ -576,7 +577,7 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str
 	{
 		mCurrentNavUrl = expanded_filename;
 		mMediaSource->setSize(mTextureWidth, mTextureHeight);
-		mMediaSource->navigateTo(expanded_filename, "text/html", false);
+		mMediaSource->navigateTo(expanded_filename, HTTP_CONTENT_TEXT_HTML, false);
 	}
 }
 
@@ -948,7 +949,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
 			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
 			if ( mErrorPageURL.length() > 0 )
 			{
-				navigateTo(mErrorPageURL, "text/html");
+				navigateTo(mErrorPageURL, HTTP_CONTENT_TEXT_HTML);
 			};
 		};
 		break;
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index e3b46d5d2f..bc1aa087e5 100644
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -35,7 +35,7 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llsdutil.h"
 #include "llmediaentry.h"
 #include "lltextureentry.h"
@@ -564,7 +564,7 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
 }
 
 /*virtual*/
-void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLMediaDataClient::Responder::httpFailure()
 {
 	mRequest->stopTracking();
 
@@ -574,9 +574,17 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin
 		return;
 	}
 	
-	if (status == HTTP_SERVICE_UNAVAILABLE)
+	if (getStatus() == HTTP_SERVICE_UNAVAILABLE)
 	{
-		F32 retry_timeout = mRequest->getRetryTimerDelay();
+		F32 retry_timeout;
+#if 0
+		// *TODO: Honor server Retry-After header.
+		if (!hasResponseHeader(HTTP_HEADER_RETRY_AFTER)
+			|| !getSecondsUntilRetryAfter(getResponseHeader(HTTP_HEADER_RETRY_AFTER), retry_timeout))
+#endif
+		{
+			retry_timeout = mRequest->getRetryTimerDelay();
+		}
 		
 		mRequest->incRetryCount();
 		
@@ -594,15 +602,16 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin
 				<< mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
 		}
 	}
+	// *TODO: Redirect on 3xx status codes.
 	else 
 	{
-		LL_WARNS("LLMediaDataClient") << *mRequest << " http error [status:" 
-				<< status << "]:" << content << ")" << LL_ENDL;
+		LL_WARNS("LLMediaDataClient") << *mRequest << " http failure "
+				<< dumpResponse() << LL_ENDL;
 	}
 }
 
 /*virtual*/
-void LLMediaDataClient::Responder::result(const LLSD& content)
+void LLMediaDataClient::Responder::httpSuccess()
 {
 	mRequest->stopTracking();
 
@@ -612,7 +621,7 @@ void LLMediaDataClient::Responder::result(const LLSD& content)
 		return;
 	}
 
-	LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
+	LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " " << dumpResponse() << LL_ENDL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -876,7 +885,7 @@ LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestUpdate::createResp
 
 
 /*virtual*/
-void LLObjectMediaDataClient::Responder::result(const LLSD& content)
+void LLObjectMediaDataClient::Responder::httpSuccess()
 {
 	getRequest()->stopTracking();
 
@@ -886,10 +895,16 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
 		return;
 	}
 
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+
 	// This responder is only used for GET requests, not UPDATE.
+	LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL;
 
-	LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
-	
 	// Look for an error
 	if (content.has("error"))
 	{
@@ -1003,7 +1018,7 @@ LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::crea
 }
 
 /*virtual*/
-void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLObjectMediaNavigateClient::Responder::httpFailure()
 {
 	getRequest()->stopTracking();
 
@@ -1015,14 +1030,14 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const
 
 	// Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base
 	// class
-	if (status == HTTP_SERVICE_UNAVAILABLE)
+	if (getStatus() == HTTP_SERVICE_UNAVAILABLE)
 	{
-		LLMediaDataClient::Responder::errorWithContent(status, reason, content);
+		LLMediaDataClient::Responder::httpFailure();
 	}
 	else
 	{
 		// bounce the face back
-		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL;
+		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: " << dumpResponse() << LL_ENDL;
 		const LLSD &payload = getRequest()->getPayload();
 		// bounce the face back
 		getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
@@ -1030,7 +1045,7 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const
 }
 
 /*virtual*/
-void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
+void LLObjectMediaNavigateClient::Responder::httpSuccess()
 {
 	getRequest()->stopTracking();
 
@@ -1040,8 +1055,9 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
 		return;
 	}
 
-	LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL;
+	LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << dumpResponse() << LL_ENDL;
 	
+	const LLSD& content = getContent();
 	if (content.has("error"))
 	{
 		const LLSD &error = content["error"];
@@ -1065,6 +1081,6 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
 	else 
 	{
 		// No action required.
-		LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " result : " << ll_print_sd(content) << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL;
 	}
 }
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 89e20a28d0..231b883c32 100644
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -74,8 +74,9 @@ public:
 // Abstracts the Cap URL, the request, and the responder
 class LLMediaDataClient : public LLRefCount
 {
-public:
+protected:
     LOG_CLASS(LLMediaDataClient);
+public:
     
     const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
 	const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
@@ -192,14 +193,16 @@ protected:
 	// Responder
 	class Responder : public LLHTTPClient::Responder
 	{
+		LOG_CLASS(Responder);
 	public:
 		Responder(const request_ptr_t &request);
+		request_ptr_t &getRequest() { return mRequest; }
+
+	protected:
 		//If we get back an error (not found, etc...), handle it here
-		virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+		virtual void httpFailure();
 		//If we get back a normal response, handle it here.	 Default just logs it.
-		virtual void result(const LLSD& content);
-
-		request_ptr_t &getRequest() { return mRequest; }
+		virtual void httpSuccess();
 
 	private:
 		request_ptr_t mRequest;
@@ -287,8 +290,9 @@ private:
 // MediaDataClient specific for the ObjectMedia cap
 class LLObjectMediaDataClient : public LLMediaDataClient
 {
-public:
+protected:
     LOG_CLASS(LLObjectMediaDataClient);
+public:
     LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
 							F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
 							U32 max_retries = MAX_RETRIES,
@@ -341,10 +345,12 @@ protected:
 		    
     class Responder : public LLMediaDataClient::Responder
     {
+        LOG_CLASS(Responder);
     public:
         Responder(const request_ptr_t &request)
             : LLMediaDataClient::Responder(request) {}
-        virtual void result(const LLSD &content);
+    protected:
+        virtual void httpSuccess();
     };
 private:
 	// The Get/Update data client needs a second queue to avoid object updates starving load-ins.
@@ -362,8 +368,9 @@ private:
 // MediaDataClient specific for the ObjectMediaNavigate cap
 class LLObjectMediaNavigateClient : public LLMediaDataClient
 {
-public:
+protected:
     LOG_CLASS(LLObjectMediaNavigateClient);
+public:
 	// NOTE: from llmediaservice.h
 	static const int ERROR_PERMISSION_DENIED_CODE = 8002;
 	
@@ -397,11 +404,13 @@ protected:
 
     class Responder : public LLMediaDataClient::Responder
     {
+        LOG_CLASS(Responder);
     public:
         Responder(const request_ptr_t &request)
             : LLMediaDataClient::Responder(request) {}
-		virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-        virtual void result(const LLSD &content);
+    protected:
+        virtual void httpFailure();
+        virtual void httpSuccess();
     private:
         void mediaNavigateBounceBack();
     };
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 17311dd75e..1469dbc346 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -28,7 +28,7 @@
 
 #include "apr_pools.h"
 #include "apr_dso.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llmeshrepository.h"
 
 #include "llagent.h"
@@ -202,6 +202,7 @@ U32	LLMeshRepoThread::sMaxConcurrentRequests = 1;
 
 class LLMeshHeaderResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLMeshHeaderResponder);
 public:
 	LLVolumeParams mMeshParams;
 	bool mProcessed;
@@ -230,14 +231,14 @@ public:
 		}
 	}
 
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer);
 
 };
 
 class LLMeshLODResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLMeshLODResponder);
 public:
 	LLVolumeParams mMeshParams;
 	S32 mLOD;
@@ -266,14 +267,14 @@ public:
 		}
 	}
 
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer);
 
 };
 
 class LLMeshSkinInfoResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLMeshSkinInfoResponder);
 public:
 	LLUUID mMeshID;
 	U32 mRequestedBytes;
@@ -291,14 +292,14 @@ public:
 		llassert(mProcessed);
 	}
 
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer);
 
 };
 
 class LLMeshDecompositionResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLMeshDecompositionResponder);
 public:
 	LLUUID mMeshID;
 	U32 mRequestedBytes;
@@ -316,14 +317,14 @@ public:
 		llassert(mProcessed);
 	}
 
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer);
 
 };
 
 class LLMeshPhysicsShapeResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLMeshPhysicsShapeResponder);
 public:
 	LLUUID mMeshID;
 	U32 mRequestedBytes;
@@ -341,8 +342,7 @@ public:
 		llassert(mProcessed);
 	}
 
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer);
 
 };
@@ -398,6 +398,7 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s
 
 class LLWholeModelFeeResponder: public LLCurl::Responder
 {
+	LOG_CLASS(LLWholeModelFeeResponder);
 	LLMeshUploadThread* mThread;
 	LLSD mModelData;
 	LLHandle<LLWholeModelFeeObserver> mObserverHandle;
@@ -421,21 +422,20 @@ public:
 		}
 	}
 
-	virtual void completed(U32 status,
-						   const std::string& reason,
-						   const LLSD& content)
+protected:
+	virtual void httpCompleted()
 	{
-		LLSD cc = content;
+		LLSD cc = getContent();
 		if (gSavedSettings.getS32("MeshUploadFakeErrors")&1)
 		{
 			cc = llsd_from_file("fake_upload_error.xml");
 		}
-			
+
 		dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
 
 		LLWholeModelFeeObserver* observer = mObserverHandle.get();
 
-		if (isGoodStatus(status) &&
+		if (isGoodStatus() &&
 			cc["state"].asString() == "upload")
 		{
 			mThread->mWholeModelUploadURL = cc["uploader"].asString();
@@ -448,13 +448,14 @@ public:
 		}
 		else
 		{
-			llwarns << "fee request failed" << llendl;
+			llwarns << "fee request failed " << dumpResponse() << llendl;
+			S32 status = getStatus();
 			log_upload_error(status,cc,"fee",mModelData["name"]);
 			mThread->mWholeModelUploadURL = "";
 
 			if (observer)
 			{
-				observer->setModelPhysicsFeeErrorStatus(status, reason);
+				observer->setModelPhysicsFeeErrorStatus(status, getReason());
 			}
 		}
 	}
@@ -463,6 +464,7 @@ public:
 
 class LLWholeModelUploadResponder: public LLCurl::Responder
 {
+	LOG_CLASS(LLWholeModelUploadResponder);
 	LLMeshUploadThread* mThread;
 	LLSD mModelData;
 	LLHandle<LLWholeModelUploadObserver> mObserverHandle;
@@ -487,11 +489,10 @@ public:
 		}
 	}
 
-	virtual void completed(U32 status,
-						   const std::string& reason,
-						   const LLSD& content)
+protected:
+	virtual void httpCompleted()
 	{
-		LLSD cc = content;
+		LLSD cc = getContent();
 		if (gSavedSettings.getS32("MeshUploadFakeErrors")&2)
 		{
 			cc = llsd_from_file("fake_upload_error.xml");
@@ -503,7 +504,7 @@ public:
 
 		// requested "mesh" asset type isn't actually the type
 		// of the resultant object, fix it up here.
-		if (isGoodStatus(status) &&
+		if (isGoodStatus() &&
 			cc["state"].asString() == "complete")
 		{
 			mModelData["asset_type"] = "object";
@@ -516,9 +517,9 @@ public:
 		}
 		else
 		{
-			llwarns << "upload failed" << llendl;
+			llwarns << "upload failed " << dumpResponse() << llendl;
 			std::string model_name = mModelData["name"].asString();
-			log_upload_error(status,cc,"upload",model_name);
+			log_upload_error(getStatus(),cc,"upload",model_name);
 
 			if (observer)
 			{
@@ -807,7 +808,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back("Accept: application/octet-stream");
+			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -889,7 +890,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back("Accept: application/octet-stream");
+			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -970,7 +971,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back("Accept: application/octet-stream");
+			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -1051,7 +1052,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c
 	//either cache entry doesn't exist or is corrupt, request header from simulator	
 	bool retval = true ;
 	std::vector<std::string> headers;
-	headers.push_back("Accept: application/octet-stream");
+	headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 	std::string http_url = constructUrl(mesh_params.getSculptID());
 	if (!http_url.empty())
@@ -1126,7 +1127,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back("Accept: application/octet-stream");
+			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -1898,10 +1899,10 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
 
 }
 
-void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
+void LLMeshLODResponder::completedRaw(const LLChannelDescriptors& channels,
+									  const LLIOPipe::buffer_ptr_t& buffer)
 {
+	S32 status = getStatus();
 	mProcessed = true;
 	
 	// thread could have already be destroyed during logout
@@ -1912,14 +1913,15 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
 	
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
+	// *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)?
 	if (status < 200 || status > 400)
 	{
-		llwarns << status << ": " << reason << llendl;
+		llwarns << dumpResponse() << llendl;
 	}
 
 	if (data_size < mRequestedBytes)
 	{
-		if (status == 499 || status == 503)
+		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)
 		{ //timeout or service unavailable, try again
 			llwarns << "Timeout or service unavailable, retrying." << llendl;
 			LLMeshRepository::sHTTPRetryCount++;
@@ -1927,8 +1929,8 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
 		}
 		else
 		{
-			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint
-			llwarns << "Unhandled status " << status << llendl;
+			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint
+			llwarns << "Unhandled status " << dumpResponse() << llendl;
 		}
 		return;
 	}
@@ -1962,10 +1964,10 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
 	delete [] data;
 }
 
-void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
+void LLMeshSkinInfoResponder::completedRaw(const LLChannelDescriptors& channels,
+										   const LLIOPipe::buffer_ptr_t& buffer)
 {
+	S32 status = getStatus();
 	mProcessed = true;
 
 	// thread could have already be destroyed during logout
@@ -1976,14 +1978,15 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason
 
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
+	// *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)?
 	if (status < 200 || status > 400)
 	{
-		llwarns << status << ": " << reason << llendl;
+		llwarns << dumpResponse() << llendl;
 	}
 
 	if (data_size < mRequestedBytes)
 	{
-		if (status == 499 || status == 503)
+		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)
 		{ //timeout or service unavailable, try again
 			llwarns << "Timeout or service unavailable, retrying." << llendl;
 			LLMeshRepository::sHTTPRetryCount++;
@@ -1991,8 +1994,8 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason
 		}
 		else
 		{
-			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint
-			llwarns << "Unhandled status " << status << llendl;
+			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint
+			llwarns << "Unhandled status " << dumpResponse() << llendl;
 		}
 		return;
 	}
@@ -2026,10 +2029,10 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason
 	delete [] data;
 }
 
-void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
+void LLMeshDecompositionResponder::completedRaw(const LLChannelDescriptors& channels,
+												const LLIOPipe::buffer_ptr_t& buffer)
 {
+	S32 status = getStatus();
 	mProcessed = true;
 	
 	if( !gMeshRepo.mThread )
@@ -2039,14 +2042,15 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r
 
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
+	// *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)?
 	if (status < 200 || status > 400)
 	{
-		llwarns << status << ": " << reason << llendl;
+		llwarns << dumpResponse() << llendl;
 	}
 
 	if (data_size < mRequestedBytes)
 	{
-		if (status == 499 || status == 503)
+		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)
 		{ //timeout or service unavailable, try again
 			llwarns << "Timeout or service unavailable, retrying." << llendl;
 			LLMeshRepository::sHTTPRetryCount++;
@@ -2054,8 +2058,8 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r
 		}
 		else
 		{
-			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint
-			llwarns << "Unhandled status " << status << llendl;
+			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint
+			llwarns << "Unhandled status " << dumpResponse() << llendl;
 		}
 		return;
 	}
@@ -2089,10 +2093,10 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r
 	delete [] data;
 }
 
-void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
+void LLMeshPhysicsShapeResponder::completedRaw(const LLChannelDescriptors& channels,
+											   const LLIOPipe::buffer_ptr_t& buffer)
 {
+	S32 status = getStatus();
 	mProcessed = true;
 
 	// thread could have already be destroyed during logout
@@ -2103,14 +2107,15 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re
 
 	S32 data_size = buffer->countAfter(channels.in(), NULL);
 
+	// *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)?
 	if (status < 200 || status > 400)
 	{
-		llwarns << status << ": " << reason << llendl;
+		llwarns << dumpResponse() << llendl;
 	}
 
 	if (data_size < mRequestedBytes)
 	{
-		if (status == 499 || status == 503)
+		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)
 		{ //timeout or service unavailable, try again
 			llwarns << "Timeout or service unavailable, retrying." << llendl;
 			LLMeshRepository::sHTTPRetryCount++;
@@ -2118,8 +2123,8 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re
 		}
 		else
 		{
-			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint
-			llwarns << "Unhandled status " << status << llendl;
+			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint
+			llwarns << "Unhandled status " << dumpResponse() << llendl;
 		}
 		return;
 	}
@@ -2153,10 +2158,10 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re
 	delete [] data;
 }
 
-void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
+void LLMeshHeaderResponder::completedRaw(const LLChannelDescriptors& channels,
+										 const LLIOPipe::buffer_ptr_t& buffer)
 {
+	S32 status = getStatus();
 	mProcessed = true;
 
 	// thread could have already be destroyed during logout
@@ -2165,6 +2170,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 		return;
 	}
 
+	// *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)?
 	if (status < 200 || status > 400)
 	{
 		//llwarns
@@ -2178,9 +2184,9 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 		// and (somewhat more optional than the others) retries
 		// again after some set period of time
 
-		llassert(status == 503 || status == 499);
+		llassert(status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_INTERNAL_ERROR);
 
-		if (status == 503 || status == 499)
+		if (status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_INTERNAL_ERROR)
 		{ //retry
 			llwarns << "Timeout or service unavailable, retrying." << llendl;
 			LLMeshRepository::sHTTPRetryCount++;
@@ -2192,7 +2198,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 		}
 		else
 		{
-			llwarns << "Unhandled status." << llendl;
+			llwarns << "Unhandled status " << dumpResponse() << llendl;
 		}
 	}
 
@@ -2214,9 +2220,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 
 	if (!success)
 	{
-		llwarns
-			<< "Unable to parse mesh header: "
-			<< status << ": " << reason << llendl;
+		llwarns << "Unable to parse mesh header: " << dumpResponse() << llendl;
 	}
 	else if (data && data_size > 0)
 	{
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 862e4be203..4f5e07c566 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -95,15 +95,11 @@ class LLClassifiedClickMessageResponder : public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLClassifiedClickMessageResponder);
 
-public:
+protected:
 	// If we get back an error (not found, etc...), handle it here
-	virtual void errorWithContent(
-		U32 status,
-		const std::string& reason,
-		const LLSD& content)
+	virtual void httpFailure()
 	{
-		llwarns << "Sending click message failed (" << status << "): [" << reason << "]" << llendl;
-		llwarns << "Content: [" << content << "]" << llendl;
+		llwarns << "Sending click message failed " << dumpResponse() << llendl;
 	}
 };
 
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index d6fccb9705..21b58dfbbf 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -529,7 +529,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
 }
 
 // virtual
-void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
+void LLLandmarksPanel::setErrorStatus(S32 status, const std::string& reason)
 {
 	llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
 }
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 4e787317ba..14709b267e 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -104,7 +104,7 @@ protected:
 	//LLRemoteParcelInfoObserver interface
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	/*virtual*/ void setParcelID(const LLUUID& parcel_id);
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 	
 private:
 	void initFavoritesInventoryPanel();
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index bcb90bcb56..c4ba097914 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -437,7 +437,7 @@ void LLPanelLogin::showLoginWidgets()
 		sInstance->reshapeBrowser();
 		// *TODO: Append all the usual login parameters, like first_login=Y etc.
 		std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
-		web_browser->navigateTo( splash_screen_url, "text/html" );
+		web_browser->navigateTo( splash_screen_url, HTTP_CONTENT_TEXT_HTML );
 		LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
 		username_combo->setFocus(TRUE);
 	}
@@ -791,7 +791,7 @@ void LLPanelLogin::loadLoginPage()
 	if (web_browser->getCurrentNavUrl() != login_uri.asString())
 	{
 		LL_DEBUGS("AppInit") << "loading:    " << login_uri << LL_ENDL;
-		web_browser->navigateTo( login_uri.asString(), "text/html" );
+		web_browser->navigateTo( login_uri.asString(), HTTP_CONTENT_TEXT_HTML );
 	}
 }
 
diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h
index 3c1f14759c..7a8bd66fcf 100644
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -86,7 +86,7 @@ public:
 	//This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	/*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; }
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason) {};
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {};
 
 protected:
 
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 4ae0c0eb12..4e7c5f6ed2 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -169,15 +169,15 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id,
 }
 
 // virtual
-void LLPanelPlaceInfo::setErrorStatus(U32 status, const std::string& reason)
+void LLPanelPlaceInfo::setErrorStatus(S32 status, const std::string& reason)
 {
 	// We only really handle 404 and 499 errors
 	std::string error_text;
-	if(status == 404)
+	if(status == HTTP_NOT_FOUND)
 	{
 		error_text = getString("server_error_text");
 	}
-	else if(status == 499)
+	else if(status == HTTP_INTERNAL_ERROR)
 	{
 		error_text = getString("server_forbidden_text");
 	}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 64f0b6b550..30327378ef 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -86,7 +86,7 @@ public:
 	void displayParcelInfo(const LLUUID& region_id,
 						   const LLVector3d& pos_global);
 
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
 
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 6c2a01fc82..730df2ea23 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -217,7 +217,7 @@ public:
 			LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
 		}
 	}
-	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason)
+	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason)
 	{
 		llerrs << "Can't complete remote parcel request. Http Status: "
 			   << status << ". Reason : " << reason << llendl;
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index c277359133..a9c755de35 100644
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -103,17 +103,16 @@ LLHTTPRegistration<LLAgentStateChangeNode> gHTTPRegistrationAgentStateChangeNode
 
 class NavMeshStatusResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(NavMeshStatusResponder);
 public:
-	NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly);
+	NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly);
 	virtual ~NavMeshStatusResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string    mCapabilityURL;
 	LLViewerRegion *mRegion;
 	LLUUID         mRegionUUID;
 	bool           mIsGetStatusOnly;
@@ -125,17 +124,16 @@ private:
 
 class NavMeshResponder : public LLHTTPClient::Responder
 {
+    LOG_CLASS(NavMeshResponder);
 public:
-	NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr);
+	NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr);
 	virtual ~NavMeshResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string             mCapabilityURL;
 	U32                     mNavMeshVersion;
 	LLPathfindingNavMeshPtr mNavMeshPtr;
 };
@@ -146,17 +144,14 @@ private:
 
 class AgentStateResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(AgentStateResponder);
 public:
-	AgentStateResponder(const std::string &pCapabilityURL);
+	AgentStateResponder();
 	virtual ~AgentStateResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
-
-private:
-	std::string mCapabilityURL;
+	virtual void httpSuccess();
+	virtual void httpFailure();
 };
 
 
@@ -165,17 +160,16 @@ private:
 //---------------------------------------------------------------------------
 class NavMeshRebakeResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(NavMeshRebakeResponder);
 public:
-	NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback);
+	NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback);
 	virtual ~NavMeshRebakeResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string                                     mCapabilityURL;
 	LLPathfindingManager::rebake_navmesh_callback_t mRebakeNavMeshCallback;
 };
 
@@ -190,11 +184,9 @@ public:
 	virtual ~LinksetsResponder();
 
 	void handleObjectLinksetsResult(const LLSD &pContent);
-	void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, 
-								   const LLSD& pContent, const std::string &pURL);
+	void handleObjectLinksetsError();
 	void handleTerrainLinksetsResult(const LLSD &pContent);
-	void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason,
-									const LLSD& pContent, const std::string &pURL);
+	void handleTerrainLinksetsError();
 
 protected:
 
@@ -227,17 +219,16 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr;
 
 class ObjectLinksetsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(ObjectLinksetsResponder);
 public:
-	ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr);
+	ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr);
 	virtual ~ObjectLinksetsResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string          mCapabilityURL;
 	LinksetsResponderPtr mLinksetsResponsderPtr;
 };
 
@@ -247,17 +238,16 @@ private:
 
 class TerrainLinksetsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(TerrainLinksetsResponder);
 public:
-	TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr);
+	TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr);
 	virtual ~TerrainLinksetsResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string          mCapabilityURL;
 	LinksetsResponderPtr mLinksetsResponsderPtr;
 };
 
@@ -267,17 +257,16 @@ private:
 
 class CharactersResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(TerrainLinksetsResponder);
 public:
-	CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback);
+	CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback);
 	virtual ~CharactersResponder();
 
-	virtual void result(const LLSD &pContent);
-	virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent);
-
 protected:
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
-	std::string                                     mCapabilityURL;
 	LLPathfindingManager::request_id_t              mRequestId;
 	LLPathfindingManager::object_request_callback_t mCharactersCallback;
 };
@@ -364,7 +353,7 @@ void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, b
 		std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion);
 		llassert(!navMeshStatusURL.empty());
 		navMeshPtr->handleNavMeshCheckVersion();
-		LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(navMeshStatusURL, pRegion, pIsGetStatusOnly);
+		LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(pRegion, pIsGetStatusOnly);
 		LLHTTPClient::get(navMeshStatusURL, navMeshStatusResponder);
 	}
 }
@@ -398,12 +387,12 @@ void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_re
 			bool doRequestTerrain = isAllowViewTerrainProperties();
 			LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain));
 
-			LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr);
+			LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr);
 			LLHTTPClient::get(objectLinksetsURL, objectLinksetsResponder);
 
 			if (doRequestTerrain)
 			{
-				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr);
+				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr);
 				LLHTTPClient::get(terrainLinksetsURL, terrainLinksetsResponder);
 			}
 		}
@@ -447,13 +436,13 @@ void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLP
 
 			if (!objectPostData.isUndefined())
 			{
-				LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr);
+				LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr);
 				LLHTTPClient::put(objectLinksetsURL, objectPostData, objectLinksetsResponder);
 			}
 
 			if (!terrainPostData.isUndefined())
 			{
-				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr);
+				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr);
 				LLHTTPClient::put(terrainLinksetsURL, terrainPostData, terrainLinksetsResponder);
 			}
 		}
@@ -486,7 +475,7 @@ void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_
 		{
 			pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr);
 
-			LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(charactersURL, pRequestId, pCharactersCallback);
+			LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(pRequestId, pCharactersCallback);
 			LLHTTPClient::get(charactersURL, charactersResponder);
 		}
 	}
@@ -519,7 +508,7 @@ void LLPathfindingManager::requestGetAgentState()
 		{
 			std::string agentStateURL = getAgentStateURLForRegion(currentRegion);
 			llassert(!agentStateURL.empty());
-			LLHTTPClient::ResponderPtr responder = new AgentStateResponder(agentStateURL);
+			LLHTTPClient::ResponderPtr responder = new AgentStateResponder();
 			LLHTTPClient::get(agentStateURL, responder);
 		}
 	}
@@ -543,7 +532,7 @@ void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebak
 		llassert(!navMeshStatusURL.empty());
 		LLSD postData;			
 		postData["command"] = "rebuild";
-		LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(navMeshStatusURL, pRebakeNavMeshCallback);
+		LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(pRebakeNavMeshCallback);
 		LLHTTPClient::post(navMeshStatusURL, postData, responder);
 	}
 }
@@ -565,7 +554,7 @@ void LLPathfindingManager::sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPt
 		else
 		{
 			navMeshPtr->handleNavMeshStart(pNavMeshStatus);
-			LLHTTPClient::ResponderPtr responder = new NavMeshResponder(navMeshURL, pNavMeshStatus.getVersion(), navMeshPtr);
+			LLHTTPClient::ResponderPtr responder = new NavMeshResponder(pNavMeshStatus.getVersion(), navMeshPtr);
 
 			LLSD postData;
 			LLHTTPClient::post(navMeshURL, postData, responder);
@@ -779,9 +768,8 @@ void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, c
 // NavMeshStatusResponder
 //---------------------------------------------------------------------------
 
-NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly)
+NavMeshStatusResponder::NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mRegion(pRegion),
 	mRegionUUID(),
 	mIsGetStatusOnly(pIsGetStatusOnly)
@@ -796,15 +784,15 @@ NavMeshStatusResponder::~NavMeshStatusResponder()
 {
 }
 
-void NavMeshStatusResponder::result(const LLSD &pContent)
+void NavMeshStatusResponder::httpSuccess()
 {
-	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, pContent);
+	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, getContent());
 	LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly);
 }
 
-void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void NavMeshStatusResponder::httpFailure()
 {
-	llwarns << "NavMeshStatusResponder error [status:" << pStatus << "]: " << pContent << llendl;
+	llwarns << dumpResponse() << llendl;
 	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID);
 	LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly);
 }
@@ -813,9 +801,8 @@ void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pR
 // NavMeshResponder
 //---------------------------------------------------------------------------
 
-NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr)
+NavMeshResponder::NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mNavMeshVersion(pNavMeshVersion),
 	mNavMeshPtr(pNavMeshPtr)
 {
@@ -825,23 +812,23 @@ NavMeshResponder::~NavMeshResponder()
 {
 }
 
-void NavMeshResponder::result(const LLSD &pContent)
+void NavMeshResponder::httpSuccess()
 {
-	mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion);
+	mNavMeshPtr->handleNavMeshResult(getContent(), mNavMeshVersion);
 }
 
-void NavMeshResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent)
+void NavMeshResponder::httpFailure()
 {
-	mNavMeshPtr->handleNavMeshError(pStatus, pReason, pContent, mCapabilityURL, mNavMeshVersion);
+	llwarns << dumpResponse() << llendl;
+	mNavMeshPtr->handleNavMeshError(mNavMeshVersion);
 }
 
 //---------------------------------------------------------------------------
 // AgentStateResponder
 //---------------------------------------------------------------------------
 
-AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL)
+AgentStateResponder::AgentStateResponder()
 : LLHTTPClient::Responder()
-, mCapabilityURL(pCapabilityURL)
 {
 }
 
@@ -849,17 +836,18 @@ AgentStateResponder::~AgentStateResponder()
 {
 }
 
-void AgentStateResponder::result(const LLSD &pContent)
+void AgentStateResponder::httpSuccess()
 {
+	const LLSD& pContent = getContent();
 	llassert(pContent.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD));
 	llassert(pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean());
 	BOOL canRebakeRegion = pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean();
 	LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion);
 }
 
-void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void AgentStateResponder::httpFailure()
 {
-	llwarns << "AgentStateResponder error [status:" << pStatus << "]: " << pContent << llendl;
+	llwarns << dumpResponse() << llendl;
 	LLPathfindingManager::getInstance()->handleAgentState(FALSE);
 }
 
@@ -867,9 +855,8 @@ void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReas
 //---------------------------------------------------------------------------
 // navmesh rebake responder
 //---------------------------------------------------------------------------
-NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback)
+NavMeshRebakeResponder::NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mRebakeNavMeshCallback(pRebakeNavMeshCallback)
 {
 }
@@ -878,14 +865,14 @@ NavMeshRebakeResponder::~NavMeshRebakeResponder()
 {
 }
 
-void NavMeshRebakeResponder::result(const LLSD &pContent)
+void NavMeshRebakeResponder::httpSuccess()
 {
 	mRebakeNavMeshCallback(true);
 }
 
-void NavMeshRebakeResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void NavMeshRebakeResponder::httpFailure()
 {
-	llwarns << "NavMeshRebakeResponder error [status:" << pStatus << "]: " << pContent << llendl;
+	llwarns << dumpResponse() << llendl;
 	mRebakeNavMeshCallback(false);
 }
 
@@ -918,11 +905,8 @@ void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent)
 	}
 }
 
-void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason,
-												 const LLSD& pContent, const std::string &pURL)
+void LinksetsResponder::handleObjectLinksetsError()
 {
-	llwarns << "LinksetsResponder object linksets error with request to URL '" << pURL << "' [status:"
-			<< pStatus << "]: " << pContent << llendl;
 	mObjectMessagingState = kReceivedError;
 	if (mTerrainMessagingState != kWaiting)
 	{
@@ -941,11 +925,8 @@ void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent)
 	}
 }
 
-void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason,
-												   const LLSD& pContent, const std::string &pURL)
+void LinksetsResponder::handleTerrainLinksetsError()
 {
-	llwarns << "LinksetsResponder terrain linksets error with request to URL '" << pURL << "' [status:"
-			<< pStatus << "]: " << pContent << llendl;
 	mTerrainMessagingState = kReceivedError;
 	if (mObjectMessagingState != kWaiting)
 	{
@@ -979,9 +960,8 @@ void LinksetsResponder::sendCallback()
 // ObjectLinksetsResponder
 //---------------------------------------------------------------------------
 
-ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr)
+ObjectLinksetsResponder::ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mLinksetsResponsderPtr(pLinksetsResponsderPtr)
 {
 }
@@ -990,23 +970,23 @@ ObjectLinksetsResponder::~ObjectLinksetsResponder()
 {
 }
 
-void ObjectLinksetsResponder::result(const LLSD &pContent)
+void ObjectLinksetsResponder::httpSuccess()
 {
-	mLinksetsResponsderPtr->handleObjectLinksetsResult(pContent);
+	mLinksetsResponsderPtr->handleObjectLinksetsResult(getContent());
 }
 
-void ObjectLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void ObjectLinksetsResponder::httpFailure()
 {
-	mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, pContent, mCapabilityURL);
+	llwarns << dumpResponse() << llendl;
+	mLinksetsResponsderPtr->handleObjectLinksetsError();
 }
 
 //---------------------------------------------------------------------------
 // TerrainLinksetsResponder
 //---------------------------------------------------------------------------
 
-TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr)
+TerrainLinksetsResponder::TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mLinksetsResponsderPtr(pLinksetsResponsderPtr)
 {
 }
@@ -1015,23 +995,23 @@ TerrainLinksetsResponder::~TerrainLinksetsResponder()
 {
 }
 
-void TerrainLinksetsResponder::result(const LLSD &pContent)
+void TerrainLinksetsResponder::httpSuccess()
 {
-	mLinksetsResponsderPtr->handleTerrainLinksetsResult(pContent);
+	mLinksetsResponsderPtr->handleTerrainLinksetsResult(getContent());
 }
 
-void TerrainLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void TerrainLinksetsResponder::httpFailure()
 {
-	mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, pContent, mCapabilityURL);
+	llwarns << dumpResponse() << llendl;
+	mLinksetsResponsderPtr->handleTerrainLinksetsError();
 }
 
 //---------------------------------------------------------------------------
 // CharactersResponder
 //---------------------------------------------------------------------------
 
-CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback)
+CharactersResponder::CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback)
 	: LLHTTPClient::Responder(),
-	mCapabilityURL(pCapabilityURL),
 	mRequestId(pRequestId),
 	mCharactersCallback(pCharactersCallback)
 {
@@ -1041,15 +1021,15 @@ CharactersResponder::~CharactersResponder()
 {
 }
 
-void CharactersResponder::result(const LLSD &pContent)
+void CharactersResponder::httpSuccess()
 {
-	LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(pContent));
+	LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(getContent()));
 	mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr);
 }
 
-void CharactersResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent)
+void CharactersResponder::httpFailure()
 {
-	llwarns << "CharactersResponder error [status:" << pStatus << "]: " << pContent << llendl;
+	llwarns << dumpResponse() << llendl;
 
 	LLPathfindingObjectListPtr characterListPtr =  LLPathfindingObjectListPtr(new LLPathfindingCharacterList());
 	mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr);
diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp
index 0c23e5ac92..555105cf40 100644
--- a/indra/newview/llpathfindingnavmesh.cpp
+++ b/indra/newview/llpathfindingnavmesh.cpp
@@ -184,10 +184,8 @@ void LLPathfindingNavMesh::handleNavMeshError()
 	setRequestStatus(kNavMeshRequestError);
 }
 
-void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion)
+void LLPathfindingNavMesh::handleNavMeshError(U32 pNavMeshVersion)
 {
-	llwarns << "LLPathfindingNavMesh error with request to URL '" << pURL << "' [status:"
-			<< pStatus << "]: " << pContent << llendl;
 	if (mNavMeshStatus.getVersion() == pNavMeshVersion)
 	{
 		handleNavMeshError();
diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h
index b872ccad7c..87f32b8d56 100644
--- a/indra/newview/llpathfindingnavmesh.h
+++ b/indra/newview/llpathfindingnavmesh.h
@@ -74,7 +74,7 @@ public:
 	void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion);
 	void handleNavMeshNotEnabled();
 	void handleNavMeshError();
-	void handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion);
+	void handleNavMeshError(U32 pNavMeshVersion);
 
 protected:
 
diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp
index 1390000fc5..94a6389f8a 100644
--- a/indra/newview/llproductinforequest.cpp
+++ b/indra/newview/llproductinforequest.cpp
@@ -35,18 +35,24 @@
 
 class LLProductInfoRequestResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(LLProductInfoRequestResponder);
+private:
 	//If we get back a normal response, handle it here
-	virtual void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		LLProductInfoRequestManager::instance().setSkuDescriptions(content);
+		const LLSD& content = getContent();
+		if (!content.isArray())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		LLProductInfoRequestManager::instance().setSkuDescriptions(getContent());
 	}
 
 	//If we get back an error (not found, etc...), handle it here
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpFailure()
 	{
-		llwarns << "LLProductInfoRequest error [status:"
-				<< status << ":] " << content << llendl;
+		llwarns << dumpResponse() << llendl;
 	}
 };
 
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index 500dec7ee5..7418bbf615 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -47,9 +47,15 @@ LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandle<LLRemote
 
 //If we get back a normal response, handle it here
 //virtual
-void LLRemoteParcelRequestResponder::result(const LLSD& content)
+void LLRemoteParcelRequestResponder::httpSuccess()
 {
-	LLUUID parcel_id = content["parcel_id"];
+	const LLSD& content = getContent();
+	if (!content.isMap() || !content.has("parcel_id"))
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+	LLUUID parcel_id = getContent()["parcel_id"];
 
 	// Panel inspecting the information may be closed and destroyed
 	// before this response is received.
@@ -62,17 +68,16 @@ void LLRemoteParcelRequestResponder::result(const LLSD& content)
 
 //If we get back an error (not found, etc...), handle it here
 //virtual
-void LLRemoteParcelRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLRemoteParcelRequestResponder::httpFailure()
 {
-	llwarns << "LLRemoteParcelRequest error [status:"
-			<< status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 
 	// Panel inspecting the information may be closed and destroyed
 	// before this response is received.
 	LLRemoteParcelInfoObserver* observer = mObserverHandle.get();
 	if (observer)
 	{
-		observer->setErrorStatus(status, reason);
+		observer->setErrorStatus(getStatus(), getReason());
 	}
 }
 
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index b87056573b..0f8ae41d76 100644
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -37,16 +37,17 @@ class LLRemoteParcelInfoObserver;
 
 class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLRemoteParcelRequestResponder);
 public:
 	LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle);
 
+private:
 	//If we get back a normal response, handle it here
-	/*virtual*/ void result(const LLSD& content);
+	/*virtual*/ void httpSuccess();
 
 	//If we get back an error (not found, etc...), handle it here
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	/*virtual*/ void httpFailure();
 
-protected:
 	LLHandle<LLRemoteParcelInfoObserver> mObserverHandle;
 };
 
@@ -78,7 +79,7 @@ public:
 	virtual ~LLRemoteParcelInfoObserver() {}
 	virtual void processParcelInfo(const LLParcelData& parcel_data) = 0;
 	virtual void setParcelID(const LLUUID& parcel_id) = 0;
-	virtual void setErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setErrorStatus(S32 status, const std::string& reason) = 0;
 	LLHandle<LLRemoteParcelInfoObserver>	getObserverHandle() const { return mObserverHandle; }
 
 protected:
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 890bc0f42d..1065b744b9 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -720,21 +720,23 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
 
 class ModerationResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(ModerationResponder);
 public:
 	ModerationResponder(const LLUUID& session_id)
 	{
 		mSessionID = session_id;
 	}
 
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+protected:
+	virtual void httpFailure()
 	{
-		llwarns << "ModerationResponder error [status:" << status << "]: " << content << llendl;
+		llwarns << dumpResponse() << llendl;
 
 		if ( gIMMgr )
 		{
 			//403 == you're not a mod
 			//should be disabled if you're not a moderator
-			if ( 403 == status )
+			if ( HTTP_FORBIDDEN == getStatus() )
 			{
 				gIMMgr->showSessionEventError(
 					"mute",
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 81bc70906d..d61a87c031 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -36,7 +36,7 @@
 
 #include "lldir.h"
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llimage.h"
 #include "llimagej2c.h"
 #include "llimageworker.h"
@@ -2350,9 +2350,10 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	mHttpRequest = new LLCore::HttpRequest;
 	mHttpOptions = new LLCore::HttpOptions;
 	mHttpHeaders = new LLCore::HttpHeaders;
-	mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c");
+	// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
+	mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
 	mHttpMetricsHeaders = new LLCore::HttpHeaders;
-	mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml");
+	mHttpMetricsHeaders->mHeaders.push_back(HTTP_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML);
 	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault();
 }
 
@@ -3950,7 +3951,8 @@ void LLTextureFetchDebugger::init()
 	if (! mHttpHeaders)
 	{
 		mHttpHeaders = new LLCore::HttpHeaders;
-		mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c");
+		// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
+		mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
 	}
 }
 
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index f3d8de1904..b9840fa3e4 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -84,7 +84,7 @@ bool LLGoogleTranslationHandler::parseResponse(
 		return false;
 	}
 
-	if (status != STATUS_OK)
+	if (status != HTTP_OK)
 	{
 		// Request failed. Extract error message from the response.
 		parseErrorResponse(root, status, err_msg);
@@ -186,7 +186,7 @@ bool LLBingTranslationHandler::parseResponse(
 	std::string& detected_lang,
 	std::string& err_msg) const
 {
-	if (status != STATUS_OK)
+	if (status != HTTP_OK)
 	{
 		static const std::string MSG_BEGIN_MARKER = "Message: ";
 		size_t begin = body.find(MSG_BEGIN_MARKER);
@@ -251,8 +251,6 @@ LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_la
 
 // virtual
 void LLTranslate::TranslationReceiver::completedRaw(
-	U32 http_status,
-	const std::string& reason,
 	const LLChannelDescriptors& channels,
 	const LLIOPipe::buffer_ptr_t& buffer)
 {
@@ -262,8 +260,8 @@ void LLTranslate::TranslationReceiver::completedRaw(
 
 	const std::string body = strstrm.str();
 	std::string translation, detected_lang, err_msg;
-	int status = http_status;
-	LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL;
+	int status = getStatus();
+	LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL;
 	LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL;
 	if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
 	{
@@ -301,12 +299,10 @@ LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const
 
 // virtual
 void LLTranslate::KeyVerificationReceiver::completedRaw(
-	U32 http_status,
-	const std::string& reason,
 	const LLChannelDescriptors& channels,
 	const LLIOPipe::buffer_ptr_t& buffer)
 {
-	bool ok = (http_status == 200);
+	bool ok = (getStatus() == HTTP_OK);
 	setVerificationStatus(ok);
 }
 
@@ -398,8 +394,8 @@ void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr
 			LLVersionInfo::getPatch(),
 			LLVersionInfo::getBuild());
 
-		sHeader.insert("Accept", "text/plain");
-		sHeader.insert("User-Agent", user_agent);
+		sHeader.insert(HTTP_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+		sHeader.insert(HTTP_HEADER_USER_AGENT, user_agent);
 	}
 
 	LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index db5ad9479c..972274714a 100755
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -95,9 +95,6 @@ public:
 	virtual bool isConfigured() const = 0;
 
 	virtual ~LLTranslationAPIHandler() {}
-
-protected:
-	static const int STATUS_OK = 200;
 };
 
 /// Google Translate v2 API handler.
@@ -201,8 +198,6 @@ public :
 		 * @see mHandler
 		 */
 		/*virtual*/ void completedRaw(
-			U32 http_status,
-			const std::string& reason,
 			const LLChannelDescriptors& channels,
 			const LLIOPipe::buffer_ptr_t& buffer);
 
@@ -250,8 +245,6 @@ public :
 		 * @see setVerificationStatus()
 		 */
 		/*virtual*/ void completedRaw(
-			U32 http_status,
-			const std::string& reason,
 			const LLChannelDescriptors& channels,
 			const LLIOPipe::buffer_ptr_t& buffer);
 
diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp
index 1d777b3f7f..88c48ba0a3 100644
--- a/indra/newview/lluploadfloaterobservers.cpp
+++ b/indra/newview/lluploadfloaterobservers.cpp
@@ -1,6 +1,6 @@
 /**
  * @file lluploadfloaterobservers.cpp
- * @brief LLUploadModelPremissionsResponder definition
+ * @brief LLUploadModelPermissionsResponder definition
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -28,26 +28,31 @@
 
 #include "lluploadfloaterobservers.h"
 
-LLUploadModelPremissionsResponder::LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer)
+LLUploadModelPermissionsResponder::LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer)
 :mObserverHandle(observer)
 {
 }
 
-void LLUploadModelPremissionsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLUploadModelPermissionsResponder::httpFailure()
 {
-	llwarns << "LLUploadModelPremissionsResponder error [status:"
-			<< status << "]: " << content << llendl;
+	llwarns << dumpResponse() << llendl;
 
 	LLUploadPermissionsObserver* observer = mObserverHandle.get();
 
 	if (observer)
 	{
-		observer->setPermissonsErrorStatus(status, reason);
+		observer->setPermissonsErrorStatus(getStatus(), getReason());
 	}
 }
 
-void LLUploadModelPremissionsResponder::result(const LLSD& content)
+void LLUploadModelPermissionsResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	LLUploadPermissionsObserver* observer = mObserverHandle.get();
 
 	if (observer)
@@ -55,3 +60,4 @@ void LLUploadModelPremissionsResponder::result(const LLSD& content)
 		observer->onPermissionsReceived(content);
 	}
 }
+
diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h
index b43ddb44d9..4ff4a827a5 100644
--- a/indra/newview/lluploadfloaterobservers.h
+++ b/indra/newview/lluploadfloaterobservers.h
@@ -1,6 +1,6 @@
 /**
  * @file lluploadfloaterobservers.h
- * @brief LLUploadModelPremissionsResponder declaration
+ * @brief LLUploadModelPermissionsResponder declaration
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -39,7 +39,7 @@ public:
 	virtual ~LLUploadPermissionsObserver() {}
 
 	virtual void onPermissionsReceived(const LLSD& result) = 0;
-	virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0;
 
 	LLHandle<LLUploadPermissionsObserver> getPermObserverHandle() const {return mUploadPermObserverHandle;}
 
@@ -54,7 +54,7 @@ public:
 	virtual ~LLWholeModelFeeObserver() {}
 
 	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0;
-	virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0;
+	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0;
 
 	LLHandle<LLWholeModelFeeObserver> getWholeModelFeeObserverHandle() const { return mWholeModelFeeObserverHandle; }
 
@@ -80,17 +80,16 @@ protected:
 };
 
 
-class LLUploadModelPremissionsResponder : public LLHTTPClient::Responder
+class LLUploadModelPermissionsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLUploadModelPermissionsResponder);
 public:
-
-	LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer);
-
-	void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-
-	void result(const LLSD& content);
+	LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer);
 
 private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
+
 	LLHandle<LLUploadPermissionsObserver> mObserverHandle;
 };
 
diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp
index 1ac6a90894..07fceefde0 100644
--- a/indra/newview/llviewerdisplayname.cpp
+++ b/indra/newview/llviewerdisplayname.cpp
@@ -57,12 +57,12 @@ namespace LLViewerDisplayName
 
 class LLSetDisplayNameResponder : public LLHTTPClient::Responder
 {
-public:
+	LOG_CLASS(LLSetDisplayNameResponder);
+private:
 	// only care about errors
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	/*virtual*/ void httpFailure()
 	{
-		llwarns << "LLSetDisplayNameResponder error [status:"
-				<< status << "]: " << content << llendl;
+		llwarns << dumpResponse() << llendl;
 		LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
 		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
 	}
@@ -85,7 +85,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl
 	// People API can return localized error messages.  Indicate our
 	// language preference via header.
 	LLSD headers;
-	headers["Accept-Language"] = LLUI::getLanguage();
+	headers[HTTP_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage();
 
 	// People API requires both the old and new value to change a variable.
 	// Our display name will be in cache before the viewer's UI is available
@@ -127,7 +127,7 @@ public:
 		LLSD body = input["body"];
 
 		S32 status = body["status"].asInteger();
-		bool success = (status == 200);
+		bool success = (status == HTTP_OK);
 		std::string reason = body["reason"].asString();
 		LLSD content = body["content"];
 
@@ -136,7 +136,7 @@ public:
 		// If viewer's concept of display name is out-of-date, the set request
 		// will fail with 409 Conflict.  If that happens, fetch up-to-date
 		// name information.
-		if (status == 409)
+		if (status == HTTP_CONFLICT)
 		{
 			LLUUID agent_id = gAgent.getID();
 			// Flush stale data
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 2df028de69..8c29a03176 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -158,7 +158,7 @@ LLViewerMediaObserver::~LLViewerMediaObserver()
 // on the Panel Land Media and to discover the MIME type
 class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
 {
-LOG_CLASS(LLMimeDiscoveryResponder);
+	LOG_CLASS(LLMimeDiscoveryResponder);
 public:
 	LLMimeDiscoveryResponder( viewer_media_t media_impl)
 		: mMediaImpl(media_impl),
@@ -177,13 +177,20 @@ public:
 		disconnectOwner();
 	}
 
-	virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpCompleted()
 	{
-		std::string media_type = content["content-type"].asString();
+		if (!isGoodStatus())
+		{
+			llwarns << dumpResponse()
+					<< " [headers:" << getResponseHeaders() << "]" << llendl;
+		}
+		const bool check_lower = true;
+		const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower);
 		std::string::size_type idx1 = media_type.find_first_of(";");
 		std::string mime_type = media_type.substr(0, idx1);
 
-		lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl;
+		lldebugs << "status is " << getStatus() << ", media type \"" << media_type << "\"" << llendl;
 		
 		// 2xx status codes indicate success.
 		// Most 4xx status codes are successful enough for our purposes.
@@ -200,32 +207,27 @@ public:
 //			)
 		// We now no longer check the error code returned from the probe.
 		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
-		if(1)
+		//if(1)
 		{
 			// The probe was successful.
 			if(mime_type.empty())
 			{
 				// Some sites don't return any content-type header at all.
 				// Treat an empty mime type as text/html.
-				mime_type = "text/html";
+				mime_type = HTTP_CONTENT_TEXT_HTML;
 			}
-			
-			completeAny(status, mime_type);
 		}
-		else
-		{
-			llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
-		
-			if(mMediaImpl)
-			{
-				mMediaImpl->mMediaSourceFailed = true;
-			}
-		}
-
-	}
+		//else
+		//{
+		//	llwarns << "responder failed with status " << dumpResponse() << llendl;
+		//
+		//	if(mMediaImpl)
+		//	{
+		//		mMediaImpl->mMediaSourceFailed = true;
+		//	}
+		//	return;
+		//}
 
-	void completeAny(U32 status, const std::string& mime_type)
-	{
 		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
 		// Make a local copy so we can call loadURI() afterwards.
 		LLViewerMediaImpl *impl = mMediaImpl;
@@ -241,6 +243,7 @@ public:
 		}
 	}
 	
+public:
 	void cancelRequest()
 	{
 		disconnectOwner();
@@ -269,7 +272,7 @@ public:
 
 class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
 {
-LOG_CLASS(LLViewerMediaOpenIDResponder);
+	LOG_CLASS(LLViewerMediaOpenIDResponder);
 public:
 	LLViewerMediaOpenIDResponder( )
 	{
@@ -279,23 +282,18 @@ public:
 	{
 	}
 
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
-		LL_DEBUGS("MediaAuth") << content << LL_ENDL;
-		std::string cookie = content["set-cookie"].asString();
-		
-		LLViewerMedia::openIDCookieResponse(cookie);
-	}
-
 	/* virtual */ void completedRaw(
-		U32 status,
-		const std::string& reason,
 		const LLChannelDescriptors& channels,
 		const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		// This is just here to disable the default behavior (attempting to parse the response as llsd).
-		// We don't care about the content of the response, only the set-cookie header.
+		// We don't care about the content of the response, only the Set-Cookie header.
+		LL_DEBUGS("MediaAuth") << dumpResponse() 
+				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
+		const bool check_lower = true;
+		const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower);
+		
+		// *TODO: What about bad status codes?  Does this destroy previous cookies?
+		LLViewerMedia::openIDCookieResponse(cookie);
 	}
 
 };
@@ -313,17 +311,25 @@ public:
 	{
 	}
 
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	 void completedRaw(
+		const LLChannelDescriptors& channels,
+		const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
+		// We don't care about the content of the response, only the set-cookie header.
+		LL_WARNS("MediaAuth") << dumpResponse() 
+				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
 
-		LLSD stripped_content = content;
+		LLSD stripped_content = getResponseHeaders();
+		// *TODO: Check that this works.
+		stripped_content.erase(HTTP_HEADER_SET_COOKIE);
 		stripped_content.erase("set-cookie");
 		LL_WARNS("MediaAuth") << stripped_content << LL_ENDL;
 
-		std::string cookie = content["set-cookie"].asString();
+		const bool check_lower = true;
+		const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower);
 		LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
 
+		// *TODO: What about bad status codes?  Does this destroy previous cookies?
 		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
 
 		// Set cookie for snapshot publishing.
@@ -331,16 +337,6 @@ public:
 		LLWebProfile::setAuthCookie(auth_cookie);
 	}
 
-	 void completedRaw(
-		U32 status,
-		const std::string& reason,
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// This is just here to disable the default behavior (attempting to parse the response as llsd).
-		// We don't care about the content of the response, only the set-cookie header.
-	}
-
 	std::string mHost;
 };
 
@@ -1387,10 +1383,12 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 LLSD LLViewerMedia::getHeaders()
 {
 	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "*/*";
-	headers["Content-Type"] = "application/xml";
-	headers["Cookie"] = sOpenIDCookie;
-	headers["User-Agent"] = getCurrentUserAgent();
+	headers[HTTP_HEADER_ACCEPT] = "*/*";
+	// *TODO: Should this be 'application/llsd+xml' ?
+	// *TODO: Should this even be set at all?   This header is only not overridden in 'GET' methods.
+	headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
+	headers[HTTP_HEADER_COOKIE] = sOpenIDCookie;
+	headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent();
 
 	return headers;
 }
@@ -1431,9 +1429,9 @@ void LLViewerMedia::setOpenIDCookie()
 
 		// Do a web profile get so we can store the cookie 
 		LLSD headers = LLSD::emptyMap();
-		headers["Accept"] = "*/*";
-		headers["Cookie"] = sOpenIDCookie;
-		headers["User-Agent"] = getCurrentUserAgent();
+		headers[HTTP_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_HEADER_COOKIE] = sOpenIDCookie;
+		headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent();
 
 		std::string profile_url = getProfileURL("");
 		LLURL raw_profile_url( profile_url.c_str() );
@@ -1463,9 +1461,9 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string
 
 	LLSD headers = LLSD::emptyMap();
 	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
-	headers["Accept"] = "*/*";
+	headers[HTTP_HEADER_ACCEPT] = "*/*";
 	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
-	headers["Content-Type"] = "application/x-www-form-urlencoded";
+	headers[HTTP_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded";
 
 	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
 	size_t size = openid_token.size();
@@ -1537,7 +1535,7 @@ void LLViewerMedia::createSpareBrowserMediaSource()
 		// The null owner will keep the browser plugin from fully initializing 
 		// (specifically, it keeps LLPluginClassMedia from negotiating a size change, 
 		// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
-		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
+		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0);
 	}
 }
 
@@ -2633,16 +2631,16 @@ void LLViewerMediaImpl::navigateInternal()
 			//    Accept: application/llsd+xml
 			// which is really not what we want.
 			LLSD headers = LLSD::emptyMap();
-			headers["Accept"] = "*/*";
+			headers[HTTP_HEADER_ACCEPT] = "*/*";
 			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
-			headers["Cookie"] = "";
+			headers[HTTP_HEADER_COOKIE] = "";
 			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
 		}
 		else if("data" == scheme || "file" == scheme || "about" == scheme)
 		{
 			// FIXME: figure out how to really discover the type for these schemes
 			// We use "data" internally for a text/html url for loading the login screen
-			if(initializeMedia("text/html"))
+			if(initializeMedia(HTTP_CONTENT_TEXT_HTML))
 			{
 				loadURI();
 			}
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 0561e731e7..576b801d5b 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -671,6 +671,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 
 class LLObjectCostResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLObjectCostResponder);
 public:
 	LLObjectCostResponder(const LLSD& object_ids)
 		: mObjectIDs(object_ids)
@@ -691,20 +692,19 @@ public:
 		}
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpFailure()
 	{
-		llwarns
-			<< "Transport error requesting object cost "
-			<< "[status: " << statusNum << "]: "
-			<< content << llendl;
+		llwarns << dumpResponse() << llendl;
 
 		// TODO*: Error message to user
 		// For now just clear the request from the pending list
 		clear_object_list_pending_requests();
 	}
 
-	void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		if ( !content.isMap() || content.has("error") )
 		{
 			// Improper response or the request had an error,
@@ -760,6 +760,7 @@ private:
 
 class LLPhysicsFlagsResponder : public LLCurl::Responder
 {
+	LOG_CLASS(LLPhysicsFlagsResponder);
 public:
 	LLPhysicsFlagsResponder(const LLSD& object_ids)
 		: mObjectIDs(object_ids)
@@ -780,20 +781,19 @@ public:
 		}
 	}
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpFailure()
 	{
-		llwarns
-			<< "Transport error requesting object physics flags "
-			<< "[status: " << statusNum << "]: "
-			<< content << llendl;
+		llwarns << dumpResponse() << llendl;
 
 		// TODO*: Error message to user
 		// For now just clear the request from the pending list
 		clear_object_list_pending_requests();
 	}
 
-	void result(const LLSD& content)
+	/* virtual void */ void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		if ( !content.isMap() || content.has("error") )
 		{
 			// Improper response or the request had an error,
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index 386b2fd400..d7e14ac6f5 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -99,7 +99,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
 			std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL());
 
 			// if we have a current (link sharing) url, use it instead
-			if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html")
+			if (mediaCurrentUrl != "" && parcel->getMediaType() == HTTP_CONTENT_TEXT_HTML)
 			{
 				mediaUrl = mediaCurrentUrl;
 			}
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b8b53aa6e4..2286bb09e1 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -204,24 +204,30 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder
 {
 	LOG_CLASS(BaseCapabilitiesComplete);
 public:
-    BaseCapabilitiesComplete(U64 region_handle, S32 id)
+	BaseCapabilitiesComplete(U64 region_handle, S32 id)
 		: mRegionHandle(region_handle), mID(id)
-    { }
+	{ }
 	virtual ~BaseCapabilitiesComplete()
 	{ }
 
-    void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-    {
-		LL_WARNS2("AppInit", "Capabilities") << "[status:" << statusNum << ":] " << content << LL_ENDL;
+	static BaseCapabilitiesComplete* build( U64 region_handle, S32 id )
+	{
+		return new BaseCapabilitiesComplete(region_handle, id);
+	}
+
+private:
+	/* virtual */void httpFailure()
+	{
+		LL_WARNS2("AppInit", "Capabilities") << dumpResponse() << LL_ENDL;
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if (regionp)
 		{
 			regionp->failedSeedCapability();
 		}
-    }
+	}
 
-   void result(const LLSD& content)
-    {
+	/* virtual */ void httpSuccess()
+	{
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if(!regionp) //region was removed
 		{
@@ -234,11 +240,17 @@ public:
 			return ;
 		}
 
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
 			regionp->setCapability(iter->first, iter->second);
-			
+
 			LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " 
 				<< iter->first << LL_ENDL;
 
@@ -257,11 +269,6 @@ public:
 		}
 	}
 
-    static BaseCapabilitiesComplete* build( U64 region_handle, S32 id )
-    {
-		return new BaseCapabilitiesComplete(region_handle, id);
-    }
-
 private:
 	U64 mRegionHandle;
 	S32 mID;
@@ -278,19 +285,32 @@ public:
 	virtual ~BaseCapabilitiesCompleteTracker()
 	{ }
 
-	void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
+	static BaseCapabilitiesCompleteTracker* build( U64 region_handle )
+	{
+		return new BaseCapabilitiesCompleteTracker( region_handle );
+	}
+
+private:
+	/* virtual */ void httpFailure()
 	{
-		llwarns << "BaseCapabilitiesCompleteTracker error [status:"
-				<< statusNum << "]: " << content << llendl;
+		llwarns << dumpResponse() << llendl;
 	}
 
-	void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if( !regionp ) 
 		{
+			LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
 			return ;
-		}		
+		}
+
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
@@ -300,7 +320,8 @@ public:
 		
 		if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )
 		{
-			llinfos<<"BaseCapabilitiesCompleteTracker "<<"Sim sent duplicate seed caps that differs in size - most likely content."<<llendl;			
+			LL_WARNS2("AppInit", "Capabilities") 
+				<< "Sim sent duplicate seed caps that differs in size - most likely content." << LL_ENDL;
 			//todo#add cap debug versus original check?
 			/*CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin();
 			while (iter!=regionp->getRegionImpl()->mCapabilities.end() )
@@ -311,16 +332,11 @@ public:
 			*/
 			regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
 		}
-
 	}
 
-	static BaseCapabilitiesCompleteTracker* build( U64 region_handle )
-	{
-		return new BaseCapabilitiesCompleteTracker( region_handle );
-	}
 
 private:
-	U64 mRegionHandle;	
+	U64 mRegionHandle;
 };
 
 
@@ -1728,31 +1744,37 @@ class SimulatorFeaturesReceived : public LLHTTPClient::Responder
 {
 	LOG_CLASS(SimulatorFeaturesReceived);
 public:
-    SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
+	SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
 			S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
-	: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
-    { }
-	
-	
-    void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-    {
-		LL_WARNS2("AppInit", "SimulatorFeatures") << "[status:" << statusNum << "]: " << content << LL_ENDL;
+		: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
+	{ }
+
+private:
+	/* virtual */ void httpFailure()
+	{
+		LL_WARNS2("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL;
 		retry();
-    }
+	}
 
-    void result(const LLSD& content)
-    {
+	/* virtual */ void httpSuccess()
+	{
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if(!regionp) //region is removed or responder is not created.
 		{
-			LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL;
+			LL_WARNS2("AppInit", "SimulatorFeatures") 
+				<< "Received results for region that no longer exists!" << LL_ENDL;
 			return ;
 		}
-		
+
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		regionp->setSimulatorFeatures(content);
 	}
 
-private:
 	void retry()
 	{
 		if (mAttempt < mMaxAttempts)
@@ -1762,7 +1784,7 @@ private:
 			LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT);
 		}
 	}
-	
+
 	std::string mRetryURL;
 	U64 mRegionHandle;
 	S32 mAttempt;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 4ed01f36ab..a9256ed5ea 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -527,18 +527,19 @@ void update_statistics()
 
 class ViewerStatsResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(ViewerStatsResponder);
 public:
-    ViewerStatsResponder() { }
+	ViewerStatsResponder() { }
 
-    void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content)
-    {
-		llwarns << "ViewerStatsResponder error [status:" << statusNum << "]: "
-				<< content << llendl;
-    }
+private:
+	/* virtual */ void httpFailure()
+	{
+		llwarns << dumpResponse() << llendl;
+	}
 
-    void result(const LLSD& content)
-    {
-		llinfos << "ViewerStatsResponder::result" << llendl;
+	/* virtual */ void httpSuccess()
+	{
+		llinfos << "OK" << llendl;
 	}
 };
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a98e9ce511..7e95263f4b 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1914,7 +1914,7 @@ void LLViewerWindow::initWorldUI()
 		destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
 		std::string url = gSavedSettings.getString("DestinationGuideURL");
 		url = LLWeb::expandURLSubstitutions(url, LLSD());
-		destinations->navigateTo(url, "text/html");
+		destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 	}
 	LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents");
 	if (avatar_picker)
@@ -1922,7 +1922,7 @@ void LLViewerWindow::initWorldUI()
 		avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
 		std::string url = gSavedSettings.getString("AvatarPickerURL");
 		url = LLWeb::expandURLSubstitutions(url, LLSD());
-		avatar_picker->navigateTo(url, "text/html");
+		avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
 	}
 }
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 9be1de4f0e..81454f5da4 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2241,6 +2241,7 @@ LLSD LLVOAvatarSelf::metricsData()
 
 class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
 {
+	LOG_CLASS(ViewerAppearanceChangeMetricsResponder);
 public:
 	ViewerAppearanceChangeMetricsResponder( S32 expected_sequence,
 											volatile const S32 & live_sequence,
@@ -2251,32 +2252,25 @@ public:
 	{
 	}
 
-	virtual void completed(U32 status,
-						   const std::string& reason,
-						   const LLSD& content)
+private:
+	/* virtual */ void httpSuccess()
 	{
-		gPendingMetricsUploads--; // if we add retry, this should be moved to the isGoodStatus case.
-		if (isGoodStatus(status))
-		{
-			LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
-			result(content);
-		}
-		else
-		{
-			LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL;
-			errorWithContent(status,reason,content);
-		}
-	}
+		LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
 
-	// virtual
-	void result(const LLSD & content)
-	{
+		gPendingMetricsUploads--;
 		if (mLiveSequence == mExpectedSequence)
 		{
 			mReportingStarted = true;
 		}
 	}
 
+	/* virtual */ void httpFailure()
+	{
+		// if we add retry, this should be removed from the httpFailure case
+		LL_WARNS("Avatar") << dumpResponse() << LL_ENDL;
+		gPendingMetricsUploads--;
+	}
+
 private:
 	S32 mExpectedSequence;
 	volatile const S32 & mLiveSequence;
@@ -2425,6 +2419,7 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 
 class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder
 {
+	LOG_CLASS(CheckAgentAppearanceServiceResponder);
 public:
 	CheckAgentAppearanceServiceResponder()
 	{
@@ -2434,22 +2429,24 @@ public:
 	{
 	}
 
-	/* virtual */ void result(const LLSD& content)
+private:
+	/* virtual */ void httpSuccess()
 	{
-		LL_DEBUGS("Avatar") << "status OK" << llendl;
+		LL_DEBUGS("Avatar") << "OK" << llendl;
 	}
 
 	// Error
-	/*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	/*virtual*/ void httpFailure()
 	{
 		if (isAgentAvatarValid())
 		{
-			LL_DEBUGS("Avatar") << "failed, will rebake [status:"
-					<< status << "]: " << content << llendl;
+			LL_DEBUGS("Avatar") << "failed, will rebake "
+					<< dumpResponse() << LL_ENDL;
 			forceAppearanceUpdate();
 		}
-	}	
+	}
 
+public:
 	static void forceAppearanceUpdate()
 	{
 		// Trying to rebake immediately after crossing region boundary
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 181735ee30..be836d7752 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -53,26 +53,27 @@ const U32 DEFAULT_RETRIES_COUNT = 3;
 
 class LLVoiceCallCapResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLVoiceCallCapResponder);
 public:
 	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
 
+protected:
 	// called with bad status codes
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	virtual void result(const LLSD& content);
+	virtual void httpFailure();
+	virtual void httpSuccess();
 
 private:
 	LLUUID mSessionID;
 };
 
 
-void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLVoiceCallCapResponder::httpFailure()
 {
-	LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:"
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("Voice") << dumpResponse() << LL_ENDL;
 	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
 	if ( channelp )
 	{
-		if ( 403 == status )
+		if ( HTTP_FORBIDDEN == getStatus() )
 		{
 			//403 == no ability
 			LLNotificationsUtil::add(
@@ -89,12 +90,18 @@ void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& re
 	}
 }
 
-void LLVoiceCallCapResponder::result(const LLSD& content)
+void LLVoiceCallCapResponder::httpSuccess()
 {
 	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
 	if (channelp)
 	{
 		//*TODO: DEBUG SPAM
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index e112c589e9..360f8f15a3 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -120,17 +120,19 @@ static int scale_speaker_volume(float volume)
 class LLVivoxVoiceAccountProvisionResponder :
 	public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLVivoxVoiceAccountProvisionResponder);
 public:
 	LLVivoxVoiceAccountProvisionResponder(int retries)
 	{
 		mRetries = retries;
 	}
 
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+private:
+	/* virtual */ void httpFailure()
 	{
 		LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, "
 			<<  ( (mRetries > 0) ? "retrying" : "too many retries (giving up)" )
-			<< status << "]: " << content << LL_ENDL;
+			<< " " << dumpResponse() << LL_ENDL;
 
 		if ( mRetries > 0 )
 		{
@@ -142,14 +144,19 @@ public:
 		}
 	}
 
-	virtual void result(const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-
 		std::string voice_sip_uri_hostname;
 		std::string voice_account_server_uri;
 		
-		LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+		LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << dumpResponse() << LL_ENDL;
 		
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		if(content.has("voice_sip_uri_hostname"))
 			voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
 		
@@ -162,7 +169,6 @@ public:
 			content["password"].asString(),
 			voice_sip_uri_hostname,
 			voice_account_server_uri);
-
 	}
 
 private:
@@ -193,33 +199,34 @@ static LLVivoxVoiceClientFriendsObserver *friendslist_listener = NULL;
 
 class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder
 {
+	LOG_CLASS(LLVivoxVoiceClientCapResponder);
 public:
 	LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {};
 
+private:
 	// called with bad status codes
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
-	virtual void result(const LLSD& content);
+	/* virtual */ void httpFailure();
+	/* virtual */ void httpSuccess();
 
-private:
 	LLVivoxVoiceClient::state mRequestingState;  // state 
 };
 
-void LLVivoxVoiceClientCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLVivoxVoiceClientCapResponder::httpFailure()
 {
-	LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder error [status:"
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("Voice") << dumpResponse() << LL_ENDL;
 	LLVivoxVoiceClient::getInstance()->sessionTerminate();
 }
 
-void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
+void LLVivoxVoiceClientCapResponder::httpSuccess()
 {
 	LLSD::map_const_iterator iter;
 	
-	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << dumpResponse() << LL_ENDL;
 
 	std::string uri;
 	std::string credentials;
 	
+	const LLSD& content = getContent();
 	if ( content.has("voice_credentials") )
 	{
 		LLSD voice_credentials = content["voice_credentials"];
@@ -2982,7 +2989,7 @@ void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString
 	
 	// Status code of 20200 means "bad password".  We may want to special-case that at some point.
 	
-	if ( statusCode == 401 )
+	if ( statusCode == HTTP_UNAUTHORIZED )
 	{
 		// Login failure which is probably caused by the delay after a user's password being updated.
 		LL_INFOS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL;
@@ -3484,7 +3491,7 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent(
 		switch(statusCode)
 		{
 			case 0:
-			case 200:
+			case HTTP_OK:
 				// generic success
 				// Don't change the saved error code (it may have been set elsewhere)
 			break;
@@ -3835,7 +3842,7 @@ void LLVivoxVoiceClient::messageEvent(
 	LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL;
 //	LL_DEBUGS("Voice") << "    header " << messageHeader << ", body: \n" << messageBody << LL_ENDL;
 	
-	if(messageHeader.find("text/html") != std::string::npos)
+	if(messageHeader.find(HTTP_CONTENT_TEXT_HTML) != std::string::npos)
 	{
 		std::string message;
 
@@ -6119,9 +6126,10 @@ void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESta
 		{
 			switch(mAudioSession->mErrorStatusCode)
 			{
-				case 404:	// NOT_FOUND
+				case HTTP_NOT_FOUND:	// NOT_FOUND
+				// *TODO: Should this be 503?
 				case 480:	// TEMPORARILY_UNAVAILABLE
-				case 408:	// REQUEST_TIMEOUT
+				case HTTP_REQUEST_TIME_OUT:	// REQUEST_TIMEOUT
 					// call failed because other user was not available
 					// treat this as an error case
 					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index 641f338f2c..ee78ba20cb 100644
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -67,9 +67,8 @@ public:
 	{
 	}
 
+	// *TODO: Check for 'application/json' content type, and parse json at the base class.
 	/*virtual*/ void completedRaw(
-		U32 status,
-		const std::string& reason,
 		const LLChannelDescriptors& channels,
 		const LLIOPipe::buffer_ptr_t& buffer)
 	{
@@ -78,9 +77,9 @@ public:
 		strstrm << istr.rdbuf();
 		const std::string body = strstrm.str();
 
-		if (status != 200)
+		if (getStatus() != HTTP_OK)
 		{
-			llwarns << "Failed to get upload config (" << status << ")" << llendl;
+			llwarns << "Failed to get upload config " << dumpResponse() << llendl;
 			LLWebProfile::reportImageUploadStatus(false);
 			return;
 		}
@@ -128,14 +127,12 @@ class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient::
 
 public:
 	/*virtual*/ void completedRaw(
-		U32 status,
-		const std::string& reason,
 		const LLChannelDescriptors& channels,
 		const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		if (status != 200)
+		if (getStatus() != HTTP_OK)
 		{
-			llwarns << "Failed to upload image: " << status << " " << reason << llendl;
+			llwarns << "Failed to upload image " << dumpResponse() << llendl;
 			LLWebProfile::reportImageUploadStatus(false);
 			return;
 		}
@@ -161,33 +158,37 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde
 	LOG_CLASS(LLWebProfileResponders::PostImageResponder);
 
 public:
-	/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	/*virtual*/ void completedRaw(const LLChannelDescriptors& channels,
+								  const LLIOPipe::buffer_ptr_t& buffer)
 	{
 		// Viewer seems to fail to follow a 303 redirect on POST request
 		// (URLRequest Error: 65, Send failed since rewinding of the data stream failed).
 		// Handle it manually.
-		if (status == 303)
+		if (getStatus() == HTTP_SEE_OTHER)
 		{
 			LLSD headers = LLViewerMedia::getHeaders();
-			headers["Cookie"] = LLWebProfile::getAuthCookie();
-			const std::string& redir_url = content["location"];
-			LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
-			LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
+			headers[HTTP_HEADER_COOKIE] = LLWebProfile::getAuthCookie();
+			const bool check_lower=true;
+			const std::string& redir_url = getResponseHeader(HTTP_HEADER_LOCATION, check_lower);
+			if (redir_url.empty())
+			{
+				llwarns << "Received empty redirection URL " << dumpResponse() << llendl;
+				LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+				LLWebProfile::reportImageUploadStatus(false);
+			}
+			else
+			{
+				LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
+				LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
+			}
 		}
 		else
 		{
-			llwarns << "Unexpected POST status: " << status << " " << reason << llendl;
-			LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl;
+			llwarns << "Unexpected POST response " << dumpResponse() << llendl;
+			LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
 			LLWebProfile::reportImageUploadStatus(false);
 		}
 	}
-
-	// Override just to suppress warnings.
-	/*virtual*/ void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
-	{
-	}
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -206,7 +207,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
 
 	LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl;
 	LLSD headers = LLViewerMedia::getHeaders();
-	headers["Cookie"] = getAuthCookie();
+	headers[HTTP_HEADER_COOKIE] = getAuthCookie();
 	LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers);
 }
 
@@ -230,8 +231,8 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
 	const std::string boundary = "----------------------------0123abcdefab";
 
 	LLSD headers = LLViewerMedia::getHeaders();
-	headers["Cookie"] = getAuthCookie();
-	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
+	headers[HTTP_HEADER_COOKIE] = getAuthCookie();
+	headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary;
 
 	std::ostringstream body;
 
diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp
index 3a80051b9b..ba536ac582 100644
--- a/indra/newview/llwebsharing.cpp
+++ b/indra/newview/llwebsharing.cpp
@@ -32,7 +32,7 @@
 #include "llagentui.h"
 #include "llbufferstream.h"
 #include "llhttpclient.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 #include "llsdserialize.h"
 #include "llsdutil.h"
 #include "llurl.h"
@@ -45,36 +45,57 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLWebSharingConfigResponder : public LLHTTPClient::Responder
+
+class LLWebSharingJSONResponder : public LLHTTPClient::Responder
 {
-	LOG_CLASS(LLWebSharingConfigResponder);
+	LOG_CLASS(LLWebSharingJSONResponder);
 public:
 	/// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response.
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
+	virtual void completedRaw(const LLChannelDescriptors& channels,
 							  const LLIOPipe::buffer_ptr_t& buffer)
 	{
-		LLSD content;
 		LLBufferStream istr(channels, buffer.get());
 		LLPointer<LLSDParser> parser = new LLSDNotationParser();
 
-		if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
-		{
-			LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL;
-		}
-		else
+		if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
 		{
-			completed(status, reason, content);
+			if (HTTP_CONTENT_JSON == getResponseHeader(HTTP_HEADER_CONTENT_TYPE))
+			{
+				mStatus = HTTP_INTERNAL_ERROR;
+				mReason = "Failed to deserialize LLSD from JSON response.";
+				char body[1025]; 
+				body[1024] = '\0';
+				istr.seekg(0, std::ios::beg);
+				istr.get(body,1024);
+				if (strlen(body) > 0)
+				{
+					mContent["body"] = body;
+				}
+			}
 		}
+
+		httpCompleted();
 	}
+};
+
+class LLWebSharingConfigResponder : public LLWebSharingJSONResponder
+{
+	LOG_CLASS(LLWebSharingConfigResponder);
+private:
 
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+	virtual void httpFailure()
 	{
-		LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL;
+		LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL;
 	}
 
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
 		LLWebSharing::instance().receiveConfig(content);
 	}
 };
@@ -87,39 +108,35 @@ class LLWebSharingOpenIDAuthResponder : public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLWebSharingOpenIDAuthResponder);
 public:
-	/* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		completed(status, reason, content);
-	}
-
-	/* virtual */ void completedRaw(U32 status, const std::string& reason,
-									const LLChannelDescriptors& channels,
+	/* virtual */ void completedRaw(const LLChannelDescriptors& channels,
 									const LLIOPipe::buffer_ptr_t& buffer)
 	{
 		/// Left empty to override the default LLSD parsing behaviour.
+		httpCompleted();
 	}
 
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+private:
+	virtual void httpFailure()
 	{
-		if (HTTP_UNAUTHORIZED == status)
+		if (HTTP_UNAUTHORIZED == getStatus())
 		{
 			LL_WARNS("WebSharing") << "AU account not authenticated." << LL_ENDL;
 			// *TODO: No account found on AU, so start the account creation process here.
 		}
 		else
 		{
-			LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL;
+			LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL;
 			LLWebSharing::instance().retryOpenIDAuth();
 		}
-
 	}
 
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
-		if (content.has("set-cookie"))
+		const bool check_lower=true;
+		if (hasResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower))
 		{
 			// OpenID request succeeded and returned a session cookie.
-			LLWebSharing::instance().receiveSessionCookie(content["set-cookie"].asString());
+			LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower));
 		}
 	}
 };
@@ -128,38 +145,19 @@ public:
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLWebSharingSecurityTokenResponder : public LLHTTPClient::Responder
+class LLWebSharingSecurityTokenResponder : public LLWebSharingJSONResponder
 {
 	LOG_CLASS(LLWebSharingSecurityTokenResponder);
-public:
-	/// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response.
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
+private:
+	virtual void httpFailure()
 	{
-		LLSD content;
-		LLBufferStream istr(channels, buffer.get());
-		LLPointer<LLSDParser> parser = new LLSDNotationParser();
-
-		if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
-		{
-			LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL;
-			LLWebSharing::instance().retryOpenIDAuth();
-		}
-		else
-		{
-			completed(status, reason, content);
-		}
-	}
-
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
-	{
-		LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL;
+		LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL;
 		LLWebSharing::instance().retryOpenIDAuth();
 	}
 
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		if (content[0].has("st") && content[0].has("expires"))
 		{
 			const std::string& token   = content[0]["st"].asString();
@@ -172,7 +170,8 @@ public:
 		}
 		else
 		{
-			LL_WARNS("WebSharing") << "No security token received." << LL_ENDL;
+			failureResult(HTTP_INTERNAL_ERROR, "No security token received.", content);
+			return;
 		}
 
 		LLWebSharing::instance().retryOpenIDAuth();
@@ -183,51 +182,18 @@ public:
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLWebSharingUploadResponder : public LLHTTPClient::Responder
+class LLWebSharingUploadResponder : public LLWebSharingJSONResponder
 {
 	LOG_CLASS(LLWebSharingUploadResponder);
-public:
-	/// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response.
-	virtual void completedRaw(U32 status, const std::string& reason,
-							  const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
-	{
-/*
-		 // Dump the body, for debugging.
-
-		 LLBufferStream istr1(channels, buffer.get());
-		 std::ostringstream ostr;
-		 std::string body;
-
-		 while (istr1.good())
-		 {
-			char buf[1024];
-			istr1.read(buf, sizeof(buf));
-			body.append(buf, istr1.gcount());
-		 }
-		 LL_DEBUGS("WebSharing") << body << LL_ENDL;
-*/
-		LLSD content;
-		LLBufferStream istr(channels, buffer.get());
-		LLPointer<LLSDParser> parser = new LLSDNotationParser();
-
-		if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
-		{
-			LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL;
-		}
-		else
-		{
-			completed(status, reason, content);
-		}
-	}
-
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+private:
+	virtual void httpFailure()
 	{
-		LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL;
+		LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL;
 	}
 
-	virtual void result(const LLSD& content)
+	virtual void httpSuccess()
 	{
+		const LLSD& content = getContent();
 		if (content[0].has("result") && content[0].has("id") &&
 			content[0]["id"].asString() == "newMediaItem")
 		{
@@ -235,8 +201,8 @@ public:
 		}
 		else
 		{
-			LL_WARNS("WebSharing") << "Error [" << content[0]["code"].asString()
-								   << "]: " << content[0]["message"].asString() << LL_ENDL;
+			failureResult(HTTP_INTERNAL_ERROR, "Invalid response content", content);
+			return;
 		}
 	}
 };
@@ -333,7 +299,7 @@ void LLWebSharing::sendConfigRequest()
 	LL_DEBUGS("WebSharing") << "Requesting Snapshot Sharing config data from: " << config_url << LL_ENDL;
 
 	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
+	headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
 
 	LLHTTPClient::get(config_url, new LLWebSharingConfigResponder(), headers);
 }
@@ -344,8 +310,8 @@ void LLWebSharing::sendOpenIDAuthRequest()
 	LL_DEBUGS("WebSharing") << "Starting OpenID Auth: " << auth_url << LL_ENDL;
 
 	LLSD headers = LLSD::emptyMap();
-	headers["Cookie"] = mOpenIDCookie;
-	headers["Accept"] = "*/*";
+	headers[HTTP_HEADER_COOKIE] = mOpenIDCookie;
+	headers[HTTP_HEADER_ACCEPT] = "*/*";
 
 	// Send request, successful login will trigger fetching a security token.
 	LLHTTPClient::get(auth_url, new LLWebSharingOpenIDAuthResponder(), headers);
@@ -371,10 +337,10 @@ void LLWebSharing::sendSecurityTokenRequest()
 	LL_DEBUGS("WebSharing") << "Fetching security token from: " << token_url << LL_ENDL;
 
 	LLSD headers = LLSD::emptyMap();
-	headers["Cookie"] = mSessionCookie;
+	headers[HTTP_HEADER_COOKIE] = mSessionCookie;
 
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
+	headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
+	headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON;
 
 	std::ostringstream body;
 	body << "{ \"gadgets\": [{ \"url\":\""
@@ -400,10 +366,10 @@ void LLWebSharing::sendUploadRequest()
 	static const std::string BOUNDARY("------------abcdef012345xyZ");
 
 	LLSD headers = LLSD::emptyMap();
-	headers["Cookie"] = mSessionCookie;
+	headers[HTTP_HEADER_COOKIE] = mSessionCookie;
 
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "multipart/form-data; boundary=" + BOUNDARY;
+	headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
+	headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY;
 
 	std::ostringstream body;
 	body << "--" << BOUNDARY << "\r\n"
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index 93eba5b604..3bedfbe502 100644
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -95,8 +95,9 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
 {
 	mID = ++sCount;
 }
-/*virtual*/ void LLEnvironmentRequestResponder::result(const LLSD& unvalidated_content)
+/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess()
 {
+	const LLSD& unvalidated_content = getContent();
 	LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
 
 	if (mID != sCount)
@@ -122,10 +123,10 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
 	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content);
 }
 /*virtual*/
-void LLEnvironmentRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLEnvironmentRequestResponder::httpFailure()
 {
-	LL_INFOS("WindlightCaps") << "Got an error, not using region windlight... [status:" 
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... "
+			<< dumpResponse() << LL_ENDL;
 	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
 }
 
@@ -169,8 +170,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 /****
  * LLEnvironmentApplyResponder
  ****/
-/*virtual*/ void LLEnvironmentApplyResponder::result(const LLSD& content)
+/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess()
 {
+	const LLSD& content = getContent();
+	if (!content.isMap() || !content.has("regionID"))
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
 	if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
 	{
 		LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
@@ -185,7 +192,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 	}
 	else
 	{
-		LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  Reason from sim: " << content["fail_reason"].asString() << LL_ENDL;
+		LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  " << dumpResponse() << LL_ENDL;
 		LLSD args(LLSD::emptyMap());
 		args["FAIL_REASON"] = content["fail_reason"].asString();
 		LLNotificationsUtil::add("WLRegionApplyFail", args);
@@ -193,14 +200,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 	}
 }
 /*virtual*/
-void LLEnvironmentApplyResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+void LLEnvironmentApplyResponder::httpFailure()
 {
-	LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region!  [status:"
-		<< status << "]: " << content << LL_ENDL;
+	LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! "
+		<< dumpResponse() << LL_ENDL;
 
 	LLSD args(LLSD::emptyMap());
 	std::stringstream msg;
-	msg << reason << " (Code " << status << ")";
+	msg << getReason() << " (Code " << getStatus() << ")";
 	args["FAIL_REASON"] = msg.str();
 	LLNotificationsUtil::add("WLRegionApplyFail", args);
 }
diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h
index 598ce6d52a..089c799da7 100644
--- a/indra/newview/llwlhandlers.h
+++ b/indra/newview/llwlhandlers.h
@@ -45,9 +45,9 @@ private:
 class LLEnvironmentRequestResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLEnvironmentRequestResponder);
-public:
-	virtual void result(const LLSD& content);
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+private:
+	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 
 private:
 	friend class LLEnvironmentRequest;
@@ -72,7 +72,7 @@ private:
 class LLEnvironmentApplyResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLEnvironmentApplyResponder);
-public:
+private:
 	/*
 	 * Expecting reply from sim in form of:
 	 * {
@@ -87,10 +87,10 @@ public:
 	 *   fail_reason : string
 	 * }
 	 */
-	virtual void result(const LLSD& content);
+	/* virtual */ void httpSuccess();
 
-	// non-200 errors only
-	virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+	// non-2xx errors only
+	/* virtual */ void httpFailure();
 
 private:
 	friend class LLEnvironmentApply;
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 0da70d398b..604e08161e 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -331,7 +331,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	   This might help with bug #503 */
 	mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
 
-    mCurlRequest->slist_append("Content-Type: text/xml");
+    mCurlRequest->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
 
 	if (useGzip)
 	{
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
index 41cb344808..01195d1269 100644
--- a/indra/newview/tests/llmediadataclient_test.cpp
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -33,7 +33,7 @@
 #include "llsdserialize.h"
 #include "llsdutil.h"
 #include "llerrorcontrol.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
 
 #include "../llmediadataclient.h"
 #include "../llvovolume.h"
@@ -128,7 +128,7 @@ void LLHTTPClient::post(
 	{
 		LLSD content;
 		content["reason"] = "fake reason";
-		responder->errorWithContent(HTTP_SERVICE_UNAVAILABLE, "fake reason", content);
+		responder->failureResult(HTTP_SERVICE_UNAVAILABLE, "fake reason", content);
 		return;
 	}
 	else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) 
@@ -136,8 +136,8 @@ void LLHTTPClient::post(
 		LLSD error;
 		error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
 		result["error"] = error;
-	}	
-	responder->result(result);
+	}
+	responder->successResult(result);
 }
 
 const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index ed66066b0a..c49b0350e9 100644
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -40,12 +40,14 @@ namespace {
 
 LLCurl::Responder::Responder() { }
 LLCurl::Responder::~Responder() { }
-void LLCurl::Responder::error(U32,std::string const &) { }
-void LLCurl::Responder::result(LLSD const &) { }
-void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { }
-void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
-void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { }
-void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { }
+void LLCurl::Responder::httpFailure() { }
+void LLCurl::Responder::httpSuccess() { }
+void LLCurl::Responder::httpCompleted() { }
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content) { }
+void LLCurl::Responder::successResult(const LLSD& content) { }
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content) { }
+std::string LLCurl::Responder::dumpResponse() const { return "(failure)"; }
+void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
 void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { }
 void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { }
 void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { }
@@ -85,7 +87,7 @@ namespace tut
 
 		virtual void setParcelID(const LLUUID& parcel_id) { }
 
-		virtual void setErrorStatus(U32 status, const std::string& reason) { }
+		virtual void setErrorStatus(S32 status, const std::string& reason) { }
 
 		bool mProcessed;
 	};
diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp
index fd9527d631..b28eb5db43 100644
--- a/indra/newview/tests/lltranslate_test.cpp
+++ b/indra/newview/tests/lltranslate_test.cpp
@@ -34,6 +34,8 @@
 #include "lltrans.h"
 #include "llui.h"
 
+#include "../../llmessage/llhttpconstants.cpp"
+
 static const std::string GOOGLE_VALID_RESPONSE1 =
 "{\
  \"data\": {\
@@ -300,12 +302,10 @@ std::string LLControlGroup::getString(const std::string& name) { return "dummy";
 LLControlGroup::~LLControlGroup() {}
 
 LLCurl::Responder::Responder() {}
-void LLCurl::Responder::completedHeader(U32, std::string const&, LLSD const&) {}
-void LLCurl::Responder::completedRaw(U32, const std::string&, const LLChannelDescriptors&, const LLIOPipe::buffer_ptr_t& buffer) {}
-void LLCurl::Responder::completed(U32, std::string const&, LLSD const&) {}
-void LLCurl::Responder::error(U32, std::string const&) {}
-void LLCurl::Responder::errorWithContent(U32, std::string const&, LLSD const&) {}
-void LLCurl::Responder::result(LLSD const&) {}
+void LLCurl::Responder::httpFailure() { }
+void LLCurl::Responder::httpSuccess() { }
+void LLCurl::Responder::httpCompleted() { }
+void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
 LLCurl::Responder::~Responder() {}
 
 void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32) {}
diff --git a/indra/test/llassetuploadqueue_tut.cpp b/indra/test/llassetuploadqueue_tut.cpp
index ec952e0058..25efe63d3f 100644
--- a/indra/test/llassetuploadqueue_tut.cpp
+++ b/indra/test/llassetuploadqueue_tut.cpp
@@ -45,11 +45,11 @@ LLAssetUploadResponder::~LLAssetUploadResponder()
 {
 }
 
-void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)
+void LLAssetUploadResponder::httpFailure()
 {
 }
 
-void LLAssetUploadResponder::result(const LLSD& content)
+void LLAssetUploadResponder::httpSuccess()
 {
 }
 
diff --git a/indra/test/llblowfish_tut.cpp b/indra/test/llblowfish_tut.cpp
index 2573cab81f..20e7960829 100644
--- a/indra/test/llblowfish_tut.cpp
+++ b/indra/test/llblowfish_tut.cpp
@@ -65,7 +65,7 @@ namespace tut
 			}
 			if (!fp)
 			{
-				llwarns << "unabled to open " << filename << llendl;
+				llwarns << "unable to open " << filename << llendl;
 				return false;
 			}
 
diff --git a/indra/test/llhttpnode_tut.cpp b/indra/test/llhttpnode_tut.cpp
index 216c59d766..d580263103 100644
--- a/indra/test/llhttpnode_tut.cpp
+++ b/indra/test/llhttpnode_tut.cpp
@@ -81,6 +81,7 @@ namespace tut
 			void result(const LLSD& result) { mResult = result; }
 			void status(S32 code, const std::string& message) { }
 			void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
+			void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
 			
 		private:
 			Response() {;} // Must be accessed through LLPointer.
diff --git a/indra/test/llsd_new_tut.cpp b/indra/test/llsd_new_tut.cpp
index f928a1bad0..03df1d339b 100644
--- a/indra/test/llsd_new_tut.cpp
+++ b/indra/test/llsd_new_tut.cpp
@@ -93,6 +93,18 @@ namespace tut
 			ensure(			s + " type",	traits.checkType(actual));
 			ensure_equals(	s + " value",	traits.get(actual), expectedValue);
 		}
+
+		template<class T>
+		static void ensureTypeAndRefValue(const char* msg, const LLSD& actual,
+			const T& expectedValue)
+		{
+			LLSDTraits<const T&> traits;
+			
+			std::string s(msg);
+			
+			ensure(			s + " type",	traits.checkType(actual));
+			ensure_equals(	s + " value",	traits.get(actual), expectedValue);
+		}
 	};
 	
 	typedef test_group<SDTestData>	SDTestGroup;
@@ -162,7 +174,7 @@ namespace tut
 		std::vector<U8> data;
 		copy(&source[0], &source[sizeof(source)], back_inserter(data));
 		
-		v = data;		ensureTypeAndValue("set to data", v, data);
+		v = data;		ensureTypeAndRefValue("set to data", v, data);
 		
 		v.clear();
 		ensure("reset to undefined", v.type() == LLSD::TypeUndefined);
@@ -213,8 +225,8 @@ namespace tut
 		const char source[] = "once in a blue moon";
 		std::vector<U8> data;
 		copy(&source[0], &source[sizeof(source)], back_inserter(data));
-		LLSD x1(data);	ensureTypeAndValue("construct vector<U8>", x1, data);
-		LLSD x2 = data;	ensureTypeAndValue("initialize vector<U8>", x2, data);
+		LLSD x1(data);	ensureTypeAndRefValue("construct vector<U8>", x1, data);
+		LLSD x2 = data;	ensureTypeAndRefValue("initialize vector<U8>", x2, data);
 	}
 	
 	void checkConversions(const char* msg, const LLSD& v,
@@ -754,42 +766,6 @@ namespace tut
 			w = "nice day";
 		}
 
-		{
-			SDAllocationCheck check("shared values test for threaded work", 9);
-
-			//U32 start_llsd_count = llsd::outstandingCount();
-
-			LLSD m = LLSD::emptyMap();
-
-			m["one"] = 1;
-			m["two"] = 2;
-			m["one_copy"] = m["one"];			// 3 (m, "one" and "two")
-
-			m["undef_one"] = LLSD();
-			m["undef_two"] = LLSD();
-			m["undef_one_copy"] = m["undef_one"];
-
-			{	// Ensure first_array gets freed to avoid counting it
-				LLSD first_array = LLSD::emptyArray();
-				first_array.append(1.0f);
-				first_array.append(2.0f);			
-				first_array.append(3.0f);			// 7
-
-				m["array"] = first_array;
-				m["array_clone"] = first_array;
-				m["array_copy"] = m["array"];		// 7
-			}
-
-			m["string_one"] = "string one value";
-			m["string_two"] = "string two value";
-			m["string_one_copy"] = m["string_one"];		// 9
-
-			//U32 llsd_object_count = llsd::outstandingCount();
-			//std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl;
-
-			//m.dumpStats();
-		}
-
 		{
 			SDAllocationCheck check("shared values test for threaded work", 9);
 
@@ -852,3 +828,4 @@ namespace tut
 		test serializations
 	*/
 }
+
diff --git a/indra/test/llsdtraits.h b/indra/test/llsdtraits.h
index 8144aaee94..07f6193ce2 100644
--- a/indra/test/llsdtraits.h
+++ b/indra/test/llsdtraits.h
@@ -93,7 +93,7 @@ LLSDTraits<LLSD::URI>::LLSDTraits()
 { }
 
 template<> inline
-LLSDTraits<LLSD::Binary>::LLSDTraits()
+LLSDTraits<const LLSD::Binary&>::LLSDTraits()
 	: type(LLSD::TypeBinary), getter(&LLSD::asBinary)
 { }
 
diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp
index d971b33475..0dae5178be 100644
--- a/indra/test/message_tut.cpp
+++ b/indra/test/message_tut.cpp
@@ -46,6 +46,7 @@ namespace
 			mStatus = code;
 		}
 		virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
+		virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
 		S32 mStatus;
 	};
 }
@@ -142,7 +143,7 @@ namespace tut
 		const LLSD message;
 		const LLPointer<Response> response = new Response();
 		gMessageSystem->dispatch(name, message, response);
-		ensure_equals(response->mStatus, 404);
+		ensure_equals(response->mStatus, HTTP_NOT_FOUND);
 	}
 }
 
diff --git a/indra/test/mock_http_client.h b/indra/test/mock_http_client.h
index 7668a43fdf..a2b9b435fb 100644
--- a/indra/test/mock_http_client.h
+++ b/indra/test/mock_http_client.h
@@ -98,7 +98,7 @@ namespace tut
 			if (mSawError)
 			{
 				std::string msg =
-					llformat("error() called when not expected, status %d",
+					llformat("httpFailure() called when not expected, status %d",
 						mStatus); 
 				fail(msg);
 			}
@@ -108,7 +108,7 @@ namespace tut
 		{
 			if (!mSawError)
 			{
-				fail("error() wasn't called");
+				fail("httpFailure() wasn't called");
 			}
 		}
 		
@@ -119,7 +119,7 @@ namespace tut
 	
 	protected:
 		bool mSawError;
-		U32 mStatus;
+		S32 mStatus;
 		std::string mReason;
 		bool mSawCompleted;
 		LLSD mResult;
@@ -144,23 +144,22 @@ namespace tut
 				mClient.mResultDeleted = true;
 			}
 			
-			virtual void error(U32 status, const std::string& reason)
+		protected:
+			virtual void httpFailure()
 			{
 				mClient.mSawError = true;
-				mClient.mStatus = status;
-				mClient.mReason = reason;
+				mClient.mStatus = getStatus();
+				mClient.mReason = getReason();
 			}
 
-			virtual void result(const LLSD& content)
+			virtual void httpSuccess()
 			{
-				mClient.mResult = content;
+				mClient.mResult = getContent();
 			}
 
-			virtual void completed(
-							U32 status, const std::string& reason,
-							const LLSD& content)
+			virtual void httpCompleted()
 			{
-				LLHTTPClient::Responder::completed(status, reason, content);
+				LLHTTPClient::Responder::httpCompleted();
 				
 				mClient.mSawCompleted = true;
 			}
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index 5edbbf9914..49b404a7ad 100644
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -106,15 +106,14 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolV
 	mHttpClient.get(checkUrl, this);
 }
 
-void LLUpdateChecker::Implementation::completed(U32 status,
-							  const std::string & reason,
-							  const LLSD & content)
+void LLUpdateChecker::Implementation::httpCompleted()
 {
-	mInProgress = false;	
-	
-	if(status != 200) {
-		LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
-		mClient.error(reason);
+	mInProgress = false;
+
+	const LLSD& content = getContent();
+	if(getStatus() != HTTP_OK) {
+		LL_WARNS("UpdateCheck") << "html error " << dumpResponse() << LL_ENDL;
+		mClient.error(getReason());
 	} else if(!content.asBoolean()) {
 		LL_INFOS("UpdateCheck") << "up to date" << llendl;
 		mClient.upToDate();
@@ -130,8 +129,9 @@ void LLUpdateChecker::Implementation::completed(U32 status,
 }
 
 
-void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
+void LLUpdateChecker::Implementation::httpFailure()
 {
+	const std::string& reason = getReason();
 	mInProgress = false;
 	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
 	mClient.error(reason);
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
index 23f62a7c5e..3ecd6230be 100644
--- a/indra/viewer_components/updater/llupdatechecker.h
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -47,11 +47,10 @@ public:
 		void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, 
 				   std::string const & servicePath, std::string channel, std::string version);
 	
+    protected:
 		// Responder:
-		virtual void completed(U32 status,
-							   const std::string & reason,
-							   const LLSD& content);
-		virtual void error(U32 status, const std::string & reason);
+		virtual void httpCompleted();
+		virtual void httpFailure();
 	
 	private:	
 		static const char * sProtocolVersion;
-- 
cgit v1.2.3


From bc0b3efc5dd8c60f4054ffd8d8589e5dccdcda8c Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Wed, 13 Mar 2013 19:10:32 +0000
Subject: Fixing gcc 4.6 compiler issue on Linux in llwindowsdl.cpp

---
 indra/llwindow/llwindowsdl.cpp | 49 ++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 5cc4fbb2a5..b5420e77fd 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -1636,38 +1636,53 @@ void check_vm_bloat()
 {
 #if LL_LINUX
 	// watch our own VM and RSS sizes, warn if we bloated rapidly
-	FILE *fp = fopen("/proc/self/stat", "r");
+	static const std::string STATS_FILE = "/proc/self/stat";
+	FILE *fp = fopen(STATS_FILE.c_str(), "r");
 	if (fp)
 	{
 		static long long last_vm_size = 0;
 		static long long last_rss_size = 0;
 		const long long significant_vm_difference = 250 * 1024*1024;
 		const long long significant_rss_difference = 50 * 1024*1024;
+		long long this_vm_size = 0;
+		long long this_rss_size = 0;
 
-		//size_t res;
+		size_t res;
 		size_t dummy;
-		char *ptr;
+		char *ptr = NULL;
 		for (int i=0; i<22; ++i) // parse past the values we don't want
 		{
-			ptr = NULL;
-			//res = getdelim(&ptr, &dummy, ' ', fp);
-			getdelim(&ptr, &dummy, ' ', fp);
+			res = getdelim(&ptr, &dummy, ' ', fp);
+			if (-1 == res)
+			{
+				llwarns << "Unable to parse " << STATS_FILE << llendl;
+				goto finally;
+			}
 			free(ptr);
+			ptr = NULL;
 		}
 		// 23rd space-delimited entry is vsize
-		ptr = NULL;
-		//res = getdelim(&ptr, &dummy, ' ', fp);
-		getdelim(&ptr, &dummy, ' ', fp);
+		res = getdelim(&ptr, &dummy, ' ', fp);
 		llassert(ptr);
-		long long this_vm_size = atoll(ptr);
+		if (-1 == res)
+		{
+			llwarns << "Unable to parse " << STATS_FILE << llendl;
+			goto finally;
+		}
+		this_vm_size = atoll(ptr);
 		free(ptr);
-		// 24th space-delimited entry is RSS
 		ptr = NULL;
-		//res = getdelim(&ptr, &dummy, ' ', fp);
-		getdelim(&ptr, &dummy, ' ', fp);
+		// 24th space-delimited entry is RSS
+		res = getdelim(&ptr, &dummy, ' ', fp);
 		llassert(ptr);
-		long long this_rss_size = getpagesize() * atoll(ptr);
+		if (-1 == res)
+		{
+			llwarns << "Unable to parse " << STATS_FILE << llendl;
+			goto finally;
+		}
+		this_rss_size = getpagesize() * atoll(ptr);
 		free(ptr);
+		ptr = NULL;
 
 		llinfos << "VM SIZE IS NOW " << (this_vm_size/(1024*1024)) << " MB, RSS SIZE IS NOW " << (this_rss_size/(1024*1024)) << " MB" << llendl;
 
@@ -1700,6 +1715,12 @@ void check_vm_bloat()
 		last_rss_size = this_rss_size;
 		last_vm_size = this_vm_size;
 
+finally:
+		if (NULL != ptr)
+		{
+			free(ptr);
+			ptr = NULL;
+		}
 		fclose(fp);
 	}
 #endif // LL_LINUX
-- 
cgit v1.2.3


From 5d8a60dd8b09c3846d2fddd1da09294b8cae6691 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Wed, 13 Mar 2013 19:28:16 +0000
Subject: Small fix to llwindowsdl.cpp change to match sunshine-stable

---
 indra/llwindow/llwindowsdl.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index b5420e77fd..205466e936 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -1647,7 +1647,7 @@ void check_vm_bloat()
 		long long this_vm_size = 0;
 		long long this_rss_size = 0;
 
-		size_t res;
+		ssize_t res;
 		size_t dummy;
 		char *ptr = NULL;
 		for (int i=0; i<22; ++i) // parse past the values we don't want
-- 
cgit v1.2.3


From 626cb6319945f6ff8feee2aec862924581a66056 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Tue, 19 Mar 2013 20:19:40 +0000
Subject: Fixing booking issues in inventory background fetching (especially
 when caps are not resolved)

---
 indra/newview/llinventorymodelbackgroundfetch.cpp | 64 ++++++++---------------
 1 file changed, 22 insertions(+), 42 deletions(-)

diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index e1537033f9..01b0e647a9 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -1,6 +1,6 @@
 /** 
- * @file llinventorymodel.cpp
- * @brief Implementation of the inventory model used to track agent inventory.
+ * @file llinventorymodelbackgroundfetch.cpp
+ * @brief Implementation of background fetching of inventory.
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -365,25 +365,19 @@ class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInvento
 {
 	LOG_CLASS(LLInventoryModelFetchItemResponder);
 public:
-	LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
+	LLInventoryModelFetchItemResponder(const LLSD& request_sd) :
+		LLInventoryModel::fetchInventoryResponder(request_sd)
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(1);
+	}
 private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
+	/* virtual */ void httpCompleted()
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+		LLInventoryModel::fetchInventoryResponder::httpCompleted();
+	}
 };
 
-void LLInventoryModelFetchItemResponder::httpSuccess()
-{
-	LLInventoryModel::fetchInventoryResponder::httpSuccess();
-	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
-}
-
-void LLInventoryModelFetchItemResponder::httpFailure()
-{
-	LLInventoryModel::fetchInventoryResponder::httpFailure();
-	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
-}
-
-
 class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(LLInventoryModelFetchDescendentsResponder);
@@ -391,9 +385,16 @@ public:
 	LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : 
 		mRequestSD(request_sd),
 		mRecursiveCatUUIDs(recursive_cats)
-	{};
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(1);
+	}
 	//LLInventoryModelFetchDescendentsResponder() {};
 private:
+	/* virtual */ void httpCompleted()
+	{
+		LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+		LLHTTPClient::Responder::httpCompleted();
+	}
 	/* virtual */ void httpSuccess();
 	/* virtual */ void httpFailure();
 protected:
@@ -527,8 +528,6 @@ void LLInventoryModelFetchDescendentsResponder::httpSuccess()
 					<< "Error: " << folder_sd["error"].asString() << llendl;
 		}
 	}
-
-	fetcher->incrFetchCount(-1);
 	
 	if (fetcher->isBulkFetchProcessingComplete())
 	{
@@ -545,8 +544,6 @@ void LLInventoryModelFetchDescendentsResponder::httpFailure()
 	llwarns << dumpResponse() << llendl;
 	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
 
-	fetcher->incrFetchCount(-1);
-
 	if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure
 	{
 		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
@@ -595,7 +592,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 		(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
 	{
 		return; // just bail if we are disconnected
-	}	
+	}
 
 	U32 item_count=0;
 	U32 folder_count=0;
@@ -698,7 +695,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 			std::string url = region->getCapability("FetchInventoryDescendents2");   			
 			if ( !url.empty() )
 			{
-				mFetchCount++;
 				if (folder_request_body["folders"].size())
 				{
 					LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
@@ -711,7 +707,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 					LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
 					LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
 				}
-			}					
+			}
 		}
 		if (item_count)
 		{
@@ -719,39 +715,23 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 
 			if (item_request_body.size())
 			{
-				mFetchCount++;
 				url = region->getCapability("FetchInventory2");
 				if (!url.empty())
 				{
 					LLSD body;
-					body["agent_id"]	= gAgent.getID();
 					body["items"] = item_request_body;
 
 					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
 				}
-				//else
-				//{
-				//	LLMessageSystem* msg = gMessageSystem;
-				//	msg->newMessage("FetchInventory");
-				//	msg->nextBlock("AgentData");
-				//	msg->addUUID("AgentID", gAgent.getID());
-				//	msg->addUUID("SessionID", gAgent.getSessionID());
-				//	msg->nextBlock("InventoryData");
-				//	msg->addUUID("OwnerID", mPermissions.getOwner());
-				//	msg->addUUID("ItemID", mUUID);
-				//	gAgent.sendReliableMessage();
-				//}
 			}
 
 			if (item_request_body_lib.size())
 			{
-				mFetchCount++;
 
 				url = region->getCapability("FetchLib2");
 				if (!url.empty())
 				{
 					LLSD body;
-					body["agent_id"]	= gAgent.getID();
 					body["items"] = item_request_body_lib;
 
 					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
-- 
cgit v1.2.3


From cfd35b8b22e8043ab14c57f6ee6108cea471a1ab Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Thu, 28 Mar 2013 18:07:54 -0400
Subject: Made a bug that was masking the warning about mismatched caps coming
 from a region. They could never match because certain capabilities are
 explicitly not stored when we receive them. * Made mSecondCapabilitiesTracker
 set capabilities in a way that more closely matches mCapabilities so that
 they will match up when we get a second cap grant from a region if the caps
 that were sent are actually the same. * Added more logging around setting a
 region's seed capability. * Also added a static function in llviewerregion to
 dump out a CapabilityMap based on the logActiveCapabilities method. Defined
 the old method in terms of the new static free function.

---
 indra/newview/app_settings/logcontrol.xml |  4 +-
 indra/newview/llstartup.cpp               |  2 +
 indra/newview/llviewermessage.cpp         |  5 ++
 indra/newview/llviewerregion.cpp          | 81 +++++++++++++++++++++++--------
 indra/newview/llworld.cpp                 |  2 +
 5 files changed, 70 insertions(+), 24 deletions(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index c5561166fc..04b3c81602 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -43,9 +43,7 @@
 					<key>tags</key>
 						<array>
 						     <string>Avatar</string>
-						<!-- sample entry for debugging specific items	
-						     <string>Voice</string>		
-						-->
+						     <string>CrossingCaps</string>		
 						</array>
 				</map>
       </array>
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 8b71f1067f..e4627b132f 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1279,6 +1279,8 @@ bool idle_startup()
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
 		LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL;
 		
+		LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == "
+		<< gFirstSimSeedCap << LL_ENDL;
 		regionp->setSeedCapability(gFirstSimSeedCap);
 		LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL;
 		display_startup();
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index f167bd14d8..0178982d45 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3922,6 +3922,8 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
 	gAgent.setTeleportState( LLAgent::TELEPORT_MOVING );
 	gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]);
 
+	LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_teleport_finish(). Seed cap == "
+			<< seedCap << LL_ENDL;
 	regionp->setSeedCapability(seedCap);
 
 	// Don't send camera updates to the new region until we're
@@ -4176,6 +4178,9 @@ void process_crossed_region(LLMessageSystem* msg, void**)
 	send_complete_agent_movement(sim_host);
 
 	LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host);
+
+	LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_crossed_region(). Seed cap == "
+			<< seedCap << LL_ENDL;
 	regionp->setSeedCapability(seedCap);
 }
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 2286bb09e1..223f754c2e 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -87,6 +87,8 @@ const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
 
 typedef std::map<std::string, std::string> CapabilityMap;
 
+static void logCapabilities(const CapabilityMap &capmap);
+
 class LLViewerRegionImpl {
 public:
 	LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
@@ -321,17 +323,36 @@ private:
 		if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )
 		{
 			LL_WARNS2("AppInit", "Capabilities") 
-				<< "Sim sent duplicate seed caps that differs in size - most likely content." << LL_ENDL;
-			//todo#add cap debug versus original check?
-			/*CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin();
-			while (iter!=regionp->getRegionImpl()->mCapabilities.end() )
-			{
-				llinfos<<"BaseCapabilitiesCompleteTracker Original "<<iter->first<<" "<< iter->second<<llendl;
-				++iter;
-			}
-			*/
+				<< "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. "
+				<< "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size()
+				<< " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
+				<< LL_ENDL;
+
+			//LL_WARNS2("AppInit", "Capabilities")
+			//	<< "Initial Base capabilities: " << LL_ENDL;
+
+			//logCapabilities(regionp->getRegionImpl()->mCapabilities);
+
+			//LL_WARNS2("AppInit", "Capabilities")
+			//				<< "Latest base capabilities: " << LL_ENDL;
+
+			//logCapabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
+
+			// *TODO 
+			//add cap debug versus original check?
+			//CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin();
+			//while (iter!=regionp->getRegionImpl()->mCapabilities.end() )
+			//{
+			//	llinfos<<"BaseCapabilitiesCompleteTracker Original "<<iter->first<<" "<< iter->second<<llendl;
+			//	++iter;
+			//}
+
 			regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
 		}
+		else
+		{
+			LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;
+		}
 	}
 
 
@@ -1671,7 +1692,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 {
 	if (getCapability("Seed") == url)
     {	
-		//llwarns << "Ignoring duplicate seed capability" << llendl;
+		setCapabilityDebug("Seed", url);
+		LL_DEBUGS("CrossingCaps") <<  "Received duplicate seed capability, posting to seed " <<
+				url	<< llendl;
 		//Instead of just returning we build up a second set of seed caps and compare them 
 		//to the "original" seed cap received and determine why there is problem!
 		LLSD capabilityNames = LLSD::emptyArray();
@@ -1821,7 +1844,16 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
 
 void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::string& url)
 {
-	mImpl->mSecondCapabilitiesTracker[name] = url;
+	// Continue to not add certain caps, as we do in setCapability. This is so they match up when we check them later.
+	if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) )
+	{
+		mImpl->mSecondCapabilitiesTracker[name] = url;
+		if(name == "GetTexture")
+		{
+			mHttpUrl = url ;
+		}
+	}
+
 }
 
 bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
@@ -1872,16 +1904,7 @@ boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(cons
 
 void LLViewerRegion::logActiveCapabilities() const
 {
-	int count = 0;
-	CapabilityMap::const_iterator iter;
-	for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count)
-	{
-		if (!iter->second.empty())
-		{
-			llinfos << iter->first << " URL is " << iter->second << llendl;
-		}
-	}
-	llinfos << "Dumped " << count << " entries." << llendl;
+	logCapabilities(mImpl->mCapabilities);
 }
 
 LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
@@ -1965,3 +1988,19 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const
 			 mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean());
 }
 
+/* Static Functions */
+
+void logCapabilities(const CapabilityMap &capmap)
+{
+	S32 count = 0;
+	CapabilityMap::const_iterator iter;
+	for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count)
+	{
+		if (!iter->second.empty())
+		{
+			llinfos << "logCapabilities: " << iter->first << " URL is " << iter->second << llendl;
+		}
+	}
+	llinfos << "logCapabilities: Dumped " << count << " entries." << llendl;
+}
+
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 793becf0c8..d9da639af9 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1065,6 +1065,8 @@ public:
 					<< sim << llendl;
 			return;
 		}
+		LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == "
+				<< input["body"]["seed-capability"] << LL_ENDL;
 		regionp->setSeedCapability(input["body"]["seed-capability"]);
 	}
 };
-- 
cgit v1.2.3


From 298660a5f15e08ef00c240330553f3228db5437f Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Mon, 1 Apr 2013 11:59:27 -0400
Subject: Backed out accidentally committed change to logcontrol.xml.

---
 indra/newview/app_settings/logcontrol.xml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 04b3c81602..c5561166fc 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -43,7 +43,9 @@
 					<key>tags</key>
 						<array>
 						     <string>Avatar</string>
-						     <string>CrossingCaps</string>		
+						<!-- sample entry for debugging specific items	
+						     <string>Voice</string>		
+						-->
 						</array>
 				</map>
       </array>
-- 
cgit v1.2.3


From 9927963ac9d7ef19db96e8d5ffa04c04d0e3b803 Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Mon, 1 Apr 2013 20:10:39 -0400
Subject: If we get more caps from a subsequent grant for a region, go ahead
 and use them. This is a hack that should be safe to remove after SH-3895 is
 fixed everywhere on the sim side.

---
 indra/newview/llviewerregion.cpp | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 223f754c2e..f4b6ff318b 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -347,12 +347,23 @@ private:
 			//	++iter;
 			//}
 
-			regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
+			if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() )
+			{
+				// *HACK Since we were granted more base capabilities in this grant request than the initial, replace
+				// the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a
+				// sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the
+				// inventory api capability grants.
+
+				// Need to clear a std::map before copying into it because old keys take precedence.
+				regionp->getRegionImplNC()->mCapabilities.clear();
+				regionp->getRegionImplNC()->mCapabilities = regionp->getRegionImpl()->mSecondCapabilitiesTracker;
+			}
 		}
 		else
 		{
 			LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;
 		}
+		regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
 	}
 
 
-- 
cgit v1.2.3


From 557adcabb925acbcc79f39f76f7cb74b6202a8da Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Tue, 2 Apr 2013 19:51:45 +0000
Subject: Renamed logCapabilites static function to log_capabilities in
 llviewerregion.cpp to better match coding standard.

---
 indra/newview/llviewerregion.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index f4b6ff318b..f0d81c599c 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -87,7 +87,7 @@ const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
 
 typedef std::map<std::string, std::string> CapabilityMap;
 
-static void logCapabilities(const CapabilityMap &capmap);
+static void log_capabilities(const CapabilityMap &capmap);
 
 class LLViewerRegionImpl {
 public:
@@ -331,12 +331,12 @@ private:
 			//LL_WARNS2("AppInit", "Capabilities")
 			//	<< "Initial Base capabilities: " << LL_ENDL;
 
-			//logCapabilities(regionp->getRegionImpl()->mCapabilities);
+			//log_capabilities(regionp->getRegionImpl()->mCapabilities);
 
 			//LL_WARNS2("AppInit", "Capabilities")
 			//				<< "Latest base capabilities: " << LL_ENDL;
 
-			//logCapabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
+			//log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
 
 			// *TODO 
 			//add cap debug versus original check?
@@ -1915,7 +1915,7 @@ boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(cons
 
 void LLViewerRegion::logActiveCapabilities() const
 {
-	logCapabilities(mImpl->mCapabilities);
+	log_capabilities(mImpl->mCapabilities);
 }
 
 LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
@@ -2001,7 +2001,7 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const
 
 /* Static Functions */
 
-void logCapabilities(const CapabilityMap &capmap)
+void log_capabilities(const CapabilityMap &capmap)
 {
 	S32 count = 0;
 	CapabilityMap::const_iterator iter;
@@ -2009,9 +2009,9 @@ void logCapabilities(const CapabilityMap &capmap)
 	{
 		if (!iter->second.empty())
 		{
-			llinfos << "logCapabilities: " << iter->first << " URL is " << iter->second << llendl;
+			llinfos << "log_capabilities: " << iter->first << " URL is " << iter->second << llendl;
 		}
 	}
-	llinfos << "logCapabilities: Dumped " << count << " entries." << llendl;
+	llinfos << "log_capabilities: Dumped " << count << " entries." << llendl;
 }
 
-- 
cgit v1.2.3


From beeefb45269f45ea717f58b30a0985951ae23c20 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Thu, 4 Apr 2013 21:50:45 +0000
Subject: Renaming HTTP_HEADER_* into HTTP_IN_HEADER_* and HTTP_OUT_HEADER_* to
 make it more clear which header strings should be used for incoming vs
 outgoing situations. Using constants for commonly used llhttpnode context
 strings.

---
 indra/llmessage/CMakeLists.txt                     |   3 -
 indra/llmessage/llavatarnamecache.cpp              |   8 +-
 indra/llmessage/llcurl.cpp                         |  41 +-
 indra/llmessage/llcurl.h                           |   4 +-
 indra/llmessage/llhttpclient.cpp                   |  66 +--
 indra/llmessage/llhttpclientadapter.cpp            |   6 +-
 indra/llmessage/llhttpconstants.cpp                | 139 ++---
 indra/llmessage/llhttpconstants.h                  | 139 ++---
 indra/llmessage/llhttpnode.cpp                     |  14 +-
 indra/llmessage/llhttpnode.h                       |  19 +-
 indra/llmessage/lliohttpserver.cpp                 |  28 +-
 indra/llmessage/lliohttpserver.h                   |   7 -
 indra/llmessage/lliosocket.cpp                     |   7 +-
 indra/llmessage/lliosocket.h                       |   3 +
 indra/llmessage/llmime.cpp                         | 628 ---------------------
 indra/llmessage/llmime.h                           | 292 ----------
 indra/llmessage/llsdappservices.cpp                |  10 +-
 indra/llmessage/llsdhttpserver.cpp                 |   2 +-
 indra/llmessage/llsdrpcclient.h                    |   4 +-
 indra/llmessage/lltrustedmessageservice.cpp        |   6 +-
 indra/llmessage/lltrustedmessageservice.h          |   4 +
 indra/llmessage/llurlrequest.cpp                   |  11 +-
 indra/llmessage/llurlrequest.h                     |  12 +-
 indra/llmessage/message.cpp                        |   2 +-
 indra/llmessage/tests/llhttpclient_test.cpp        |   2 -
 indra/llmessage/tests/llhttpnode_stub.cpp          | 112 ++++
 indra/llmessage/tests/llmime_test.cpp              | 446 ---------------
 .../tests/lltrustedmessageservice_test.cpp         |   1 +
 indra/newview/llappearancemgr.cpp                  |   4 +-
 indra/newview/llfloaterabout.cpp                   |   3 +-
 indra/newview/llfloaterurlentry.cpp                |   3 +-
 indra/newview/llmarketplacefunctions.cpp           |  23 +-
 indra/newview/llmediadataclient.cpp                |   4 +-
 indra/newview/llmeshrepository.cpp                 |  10 +-
 indra/newview/lltexturefetch.cpp                   |   6 +-
 indra/newview/lltranslate.cpp                      |   4 +-
 indra/newview/llviewerdisplayname.cpp              |   2 +-
 indra/newview/llviewermedia.cpp                    |  34 +-
 indra/newview/llwebprofile.cpp                     |  11 +-
 indra/newview/llwebsharing.cpp                     |  69 ++-
 indra/newview/llxmlrpctransaction.cpp              |   2 +-
 indra/test/llhttpnode_tut.cpp                      |   2 +-
 indra/test/mock_http_client.cpp                    |   3 +-
 43 files changed, 478 insertions(+), 1718 deletions(-)
 delete mode 100644 indra/llmessage/llmime.cpp
 delete mode 100644 indra/llmessage/llmime.h
 create mode 100644 indra/llmessage/tests/llhttpnode_stub.cpp
 delete mode 100644 indra/llmessage/tests/llmime_test.cpp

diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 181718f465..6fa2669be6 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -59,7 +59,6 @@ set(llmessage_SOURCE_FILES
     llmessagetemplate.cpp
     llmessagetemplateparser.cpp
     llmessagethrottle.cpp
-    llmime.cpp
     llnamevalue.cpp
     llnullcipher.cpp
     llpacketack.cpp
@@ -154,7 +153,6 @@ set(llmessage_HEADER_FILES
     llmessagetemplate.h
     llmessagetemplateparser.h
     llmessagethrottle.h
-    llmime.h
     llmsgvariabletype.h
     llnamevalue.h
     llnullcipher.h
@@ -266,7 +264,6 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llmime "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
 endif (LL_TESTS)
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 1d01b69969..e0b71acbd5 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -711,13 +711,9 @@ bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *exp
 
 	// Allow the header to override the default
 	std::string cache_control;
-	if (headers.has(HTTP_HEADER_CACHE_CONTROL))
+	if (headers.has(HTTP_IN_HEADER_CACHE_CONTROL))
 	{
-		cache_control = headers[HTTP_HEADER_CACHE_CONTROL].asString();
-	}
-	else if (headers.has(HTTP_HEADER_LOWER_CACHE_CONTROL))
-	{
-		cache_control = headers[HTTP_HEADER_LOWER_CACHE_CONTROL].asString();
+		cache_control = headers[HTTP_IN_HEADER_CACHE_CONTROL].asString();
 	}
 
 	if (!cache_control.empty())
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 1269b6bc5d..68282626ae 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -156,9 +156,9 @@ std::string LLCurl::Responder::dumpResponse() const
 	  << "[status:" << mStatus << "] "
 	  << "[reason:" << mReason << "] ";
 
-	if (mResponseHeaders.has(HTTP_HEADER_CONTENT_TYPE))
+	if (mResponseHeaders.has(HTTP_IN_HEADER_CONTENT_TYPE))
 	{
-		s << "[content-type:" << mResponseHeaders[HTTP_HEADER_CONTENT_TYPE] << "] ";
+		s << "[content-type:" << mResponseHeaders[HTTP_IN_HEADER_CONTENT_TYPE] << "] ";
 	}
 
 	s << "[content:" << mContent << "]";
@@ -211,34 +211,19 @@ void LLCurl::Responder::setResponseHeader(const std::string& header, const std::
 	mResponseHeaders[header] = value;
 }
 
-const std::string& LLCurl::Responder::getResponseHeader(const std::string& header, bool check_lower) const
+const std::string& LLCurl::Responder::getResponseHeader(const std::string& header) const
 {
 	if (mResponseHeaders.has(header))
 	{
 		return mResponseHeaders[header].asStringRef();
 	}
-	if (check_lower)
-	{
-		std::string header_lower(header);
-		LLStringUtil::toLower(header_lower);
-		if (mResponseHeaders.has(header_lower))
-		{
-			return mResponseHeaders[header_lower].asStringRef();
-		}
-	}
 	static const std::string empty;
 	return empty;
 }
 
-bool LLCurl::Responder::hasResponseHeader(const std::string& header, bool check_lower) const
+bool LLCurl::Responder::hasResponseHeader(const std::string& header) const
 {
 	if (mResponseHeaders.has(header)) return true;
-	if (check_lower)
-	{
-		std::string header_lower(header);
-		LLStringUtil::toLower(header_lower);
-		return mResponseHeaders.has(header_lower);
-	}
 	return false;
 }
 
@@ -256,7 +241,7 @@ void LLCurl::Responder::completedRaw(
 	{
 		parsed=false;
 	}
-	// Try to parse body as llsd, no matter what 'Content-Type' says.
+	// Try to parse body as llsd, no matter what 'content-type' says.
 	else if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(mContent, istr, emit_parse_errors))
 	{
 		parsed=false;
@@ -271,8 +256,8 @@ void LLCurl::Responder::completedRaw(
 		}
 	}
 
-	// Only emit an warning if we failed to parse when 'Content-Type' == 'application/llsd+xml'
-	if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_HEADER_CONTENT_TYPE)))
+	// Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+	if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
 	{
 		llwarns << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " 
 			<< "(" << mReason << ") body: " << debug_body << llendl;
@@ -643,8 +628,8 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 	if (!post)
 	{
 		// *TODO: Should this be set to 'Keep-Alive' ?
-		slist_append(HTTP_HEADER_CONNECTION, "keep-alive");
-		slist_append(HTTP_HEADER_KEEP_ALIVE, "300");
+		slist_append(HTTP_OUT_HEADER_CONNECTION, "keep-alive");
+		slist_append(HTTP_OUT_HEADER_KEEP_ALIVE, "300");
 		// Accept and other headers
 		for (std::vector<std::string>::const_iterator iter = headers.begin();
 			 iter != headers.end(); ++iter)
@@ -1242,12 +1227,12 @@ bool LLCurlRequest::getByteRange(const std::string& url,
 	if (length > 0)
 	{
 		std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
-		easy->slist_append(HTTP_HEADER_RANGE, range);
+		easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
 	}
 	else if (offset > 0)
 	{
 		std::string range = llformat("bytes=%d-", offset);
-		easy->slist_append(HTTP_HEADER_RANGE, range);
+		easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
 	}
 	easy->setHeaders();
 	bool res = addEasy(easy);
@@ -1274,7 +1259,7 @@ bool LLCurlRequest::post(const std::string& url,
 	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
 	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
 
-	easy->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+	easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	easy->setHeaders();
 
 	lldebugs << "POSTING: " << bytes << " bytes." << llendl;
@@ -1302,7 +1287,7 @@ bool LLCurlRequest::post(const std::string& url,
 	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
 	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
 
-	easy->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
+	easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
 	easy->setHeaders();
 
 	lldebugs << "POSTING: " << bytes << " bytes." << llendl;
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index c72e1e493a..8a65c783be 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -91,8 +91,8 @@ public:
 		S32 getStatus() const { return mStatus; }
 		const std::string& getReason() const { return mReason; }
 		const LLSD& getContent() const { return mContent; }
-		bool hasResponseHeader(const std::string& header, bool check_lower=false) const;
-		const std::string& getResponseHeader(const std::string& header, bool check_lower=true) const;
+		bool hasResponseHeader(const std::string& header) const;
+		const std::string& getResponseHeader(const std::string& header) const;
 		const LLSD& getResponseHeaders() const { return mResponseHeaders; }
 		const std::string& getURL() const { return mURL; }
 		EHTTPMethod getHTTPMethod() const { return mHTTPMethod; }
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index a4a1f02cd3..5830a5eca0 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -248,45 +248,45 @@ static void request(
 
 	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
 
-	
+
 	LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;
 
 	// Insert custom headers if the caller sent any
 	if (headers.isMap())
 	{
-		if (headers.has(HTTP_HEADER_COOKIE))
+		if (headers.has(HTTP_OUT_HEADER_COOKIE))
 		{
 			req->allowCookies();
 		}
 
-        LLSD::map_const_iterator iter = headers.beginMap();
-        LLSD::map_const_iterator end  = headers.endMap();
-
-        for (; iter != end; ++iter)
-        {
-            //if the header is "Pragma" with no value
-            //the caller intends to force libcurl to drop
-            //the Pragma header it so gratuitously inserts
-            //Before inserting the header, force libcurl
-            //to not use the proxy (read: llurlrequest.cpp)
-			if ((iter->first == HTTP_HEADER_PRAGMA) && (iter->second.asString().empty()))
-            {
-                req->useProxy(false);
-            }
-            LL_DEBUGS("LLHTTPClient") << "header = " << iter->first 
-                << ": " << iter->second.asString() << LL_ENDL;
-            req->addHeader(iter->first, iter->second.asString());
-        }
-    }
+		LLSD::map_const_iterator iter = headers.beginMap();
+		LLSD::map_const_iterator end  = headers.endMap();
+
+		for (; iter != end; ++iter)
+		{
+			//if the header is "Pragma" with no value
+			//the caller intends to force libcurl to drop
+			//the Pragma header it so gratuitously inserts
+			//Before inserting the header, force libcurl
+			//to not use the proxy (read: llurlrequest.cpp)
+			if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty()))
+			{
+				req->useProxy(false);
+			}
+			LL_DEBUGS("LLHTTPClient") << "header = " << iter->first 
+				<< ": " << iter->second.asString() << LL_ENDL;
+			req->addHeader(iter->first, iter->second.asString());
+		}
+	}
 
 	// Check to see if we have already set Accept or not. If no one
 	// set it, set it to application/llsd+xml since that's what we
 	// almost always want.
 	if( method != HTTP_PUT && method != HTTP_POST )
 	{
-		if(!headers.has(HTTP_HEADER_ACCEPT))
+		if(!headers.has(HTTP_OUT_HEADER_ACCEPT))
 		{
-			req->addHeader(HTTP_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
+			req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
 		}
 	}
 
@@ -301,21 +301,21 @@ static void request(
 	if (method == HTTP_POST  &&  gMessageSystem)
 	{
 		req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
-								gMessageSystem->mPort));
-   	}
+					gMessageSystem->mPort));
+	}
 
 	if (method == HTTP_PUT || method == HTTP_POST)
 	{
-		if(!headers.has(HTTP_HEADER_CONTENT_TYPE))
+		if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
 		{
 			// If the Content-Type header was passed in, it has
 			// already been added as a header through req->addHeader
 			// in the loop above. We defer to the caller's wisdom, but
 			// if they did not specify a Content-Type, then ask the
 			// injector.
-			req->addHeader(HTTP_HEADER_CONTENT_TYPE, body_injector->contentType());
+			req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType());
 		}
-   		chain.push_back(LLIOPipe::ptr_t(body_injector));
+		chain.push_back(LLIOPipe::ptr_t(body_injector));
 	}
 
 	chain.push_back(LLIOPipe::ptr_t(req));
@@ -336,7 +336,7 @@ void LLHTTPClient::getByteRange(
 	if(offset > 0 || bytes > 0)
 	{
 		std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
-		headers[HTTP_HEADER_RANGE] = range;
+		headers[HTTP_OUT_HEADER_RANGE] = range;
 	}
     request(url,HTTP_GET, NULL, responder, timeout, headers);
 }
@@ -483,19 +483,19 @@ static LLSD blocking_request(
 		curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
 		//copied from PHP libs, correct?
 		headers_list = curl_slist_append(headers_list, 
-				llformat("%s: %s", HTTP_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
+				llformat("%s: %s", HTTP_OUT_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
 
 		// copied from llurlrequest.cpp
 		// it appears that apache2.2.3 or django in etch is busted. If
 		// we do not clear the expect header, we get a 500. May be
 		// limited to django/mod_wsgi.
-		headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_HEADER_EXPECT.c_str()).c_str());
+		headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_OUT_HEADER_EXPECT.c_str()).c_str());
 	}
 	
 	// * Do the action using curl, handle results
 	lldebugs << "HTTP body: " << body_str << llendl;
 	headers_list = curl_slist_append(headers_list,
-				llformat("%s: %s", HTTP_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
+				llformat("%s: %s", HTTP_OUT_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
 	CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
 	if ( curl_result != CURLE_OK )
 	{
@@ -617,7 +617,7 @@ void LLHTTPClient::move(
 	const F32 timeout)
 {
 	LLSD headers = hdrs;
-	headers[HTTP_HEADER_DESTINATION] = destination;
+	headers[HTTP_OUT_HEADER_DESTINATION] = destination;
 	request(url, HTTP_MOVE, NULL, responder, timeout, headers);
 }
 
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index aaa31e36fc..b56a804f94 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -36,17 +36,17 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo
 	LLSD empty_pragma_header;
 	// Pragma is required to stop curl adding "no-cache"
 	// Space is required to stop llurlrequest from turning off proxying
-	empty_pragma_header[HTTP_HEADER_PRAGMA] = " "; 
+	empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " "; 
 	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
 
 void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) 
 {
 	LLSD empty_pragma_header = headers;
-	if (!empty_pragma_header.has(HTTP_HEADER_PRAGMA))
+	if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
 	{
 		// as above
-		empty_pragma_header[HTTP_HEADER_PRAGMA] = " ";
+		empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
 	}
 	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp
index 2134024a14..1995fad1e5 100644
--- a/indra/llmessage/llhttpconstants.cpp
+++ b/indra/llmessage/llhttpconstants.cpp
@@ -37,72 +37,76 @@
 // for curl_getdate() (apparently parsing RFC 1123 dates is hard)
 #include <curl/curl.h>
 
-const std::string HTTP_HEADER_ACCEPT("Accept");
-const std::string HTTP_HEADER_ACCEPT_CHARSET("Accept-Charset");
-const std::string HTTP_HEADER_ACCEPT_ENCODING("Accept-Encoding");
-const std::string HTTP_HEADER_ACCEPT_LANGUAGE("Accept-Language");
-const std::string HTTP_HEADER_ACCEPT_RANGES("Accept-Ranges");
-const std::string HTTP_HEADER_AGE("Age");
-const std::string HTTP_HEADER_ALLOW("Allow");
-const std::string HTTP_HEADER_AUTHORIZATION("Authorization");
-const std::string HTTP_HEADER_CACHE_CONTROL("Cache-Control");
-const std::string HTTP_HEADER_CONNECTION("Connection");
-const std::string HTTP_HEADER_CONTENT_DESCRIPTION("Content-Description");
-const std::string HTTP_HEADER_CONTENT_ENCODING("Content-Encoding");
-const std::string HTTP_HEADER_CONTENT_ID("Content-ID");
-const std::string HTTP_HEADER_CONTENT_LANGUAGE("Content-Language");
-const std::string HTTP_HEADER_CONTENT_LENGTH("Content-Length");
-const std::string HTTP_HEADER_CONTENT_LOCATION("Content-Location");
-const std::string HTTP_HEADER_CONTENT_MD5("Content-MD5");
-const std::string HTTP_HEADER_CONTENT_RANGE("Content-Range");
-const std::string HTTP_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
-const std::string HTTP_HEADER_CONTENT_TYPE("Content-Type");
-const std::string HTTP_HEADER_COOKIE("Cookie");
-const std::string HTTP_HEADER_DATE("Date");
-const std::string HTTP_HEADER_DESTINATION("Destination");
-const std::string HTTP_HEADER_ETAG("ETag");
-const std::string HTTP_HEADER_EXPECT("Expect");
-const std::string HTTP_HEADER_EXPIRES("Expires");
-const std::string HTTP_HEADER_FROM("From");
-const std::string HTTP_HEADER_HOST("Host");
-const std::string HTTP_HEADER_IF_MATCH("If-Match");
-const std::string HTTP_HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
-const std::string HTTP_HEADER_IF_NONE_MATCH("If-None-Match");
-const std::string HTTP_HEADER_IF_RANGE("If-Range");
-const std::string HTTP_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since");
-const std::string HTTP_HEADER_KEEP_ALIVE("Keep-Alive");
-const std::string HTTP_HEADER_LAST_MODIFIED("Last-Modified");
-const std::string HTTP_HEADER_LOCATION("Location");
-const std::string HTTP_HEADER_MAX_FORWARDS("Max-Forwards");
-const std::string HTTP_HEADER_MIME_VERSION("MIME-Version");
-const std::string HTTP_HEADER_PRAGMA("Pragma");
-const std::string HTTP_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate");
-const std::string HTTP_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization");
-const std::string HTTP_HEADER_RANGE("Range");
-const std::string HTTP_HEADER_REFERER("Referer");
-const std::string HTTP_HEADER_RETRY_AFTER("Retry-After");
-const std::string HTTP_HEADER_SERVER("Server");
-const std::string HTTP_HEADER_SET_COOKIE("Set-Cookie");
-const std::string HTTP_HEADER_TE("TE");
-const std::string HTTP_HEADER_TRAILER("Trailer");
-const std::string HTTP_HEADER_TRANSFER_ENCODING("Transfer-Encoding");
-const std::string HTTP_HEADER_UPGRADE("Upgrade");
-const std::string HTTP_HEADER_USER_AGENT("User-Agent");
-const std::string HTTP_HEADER_VARY("Vary");
-const std::string HTTP_HEADER_VIA("Via");
-const std::string HTTP_HEADER_WARNING("Warning");
-const std::string HTTP_HEADER_WWW_AUTHENTICATE("WWW-Authenticate");
-
-
-// Sadly, our proxied headers do not follow http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
-// We need to deal with lowercase headers
-const std::string HTTP_HEADER_LOWER_ACCEPT_LANGUAGE("accept-language");
-const std::string HTTP_HEADER_LOWER_CACHE_CONTROL("cache-control");
-const std::string HTTP_HEADER_LOWER_CONTENT_LENGTH("content-length");
-const std::string HTTP_HEADER_LOWER_CONTENT_TYPE("content-type");
-const std::string HTTP_HEADER_LOWER_HOST("host");
-const std::string HTTP_HEADER_LOWER_USER_AGENT("user-agent");
-const std::string HTTP_HEADER_LOWER_X_FORWARDED_FOR("x-forwarded-for");
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+const std::string HTTP_OUT_HEADER_ACCEPT("Accept");
+const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET("Accept-Charset");
+const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING("Accept-Encoding");
+const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE("Accept-Language");
+const std::string HTTP_OUT_HEADER_ACCEPT_RANGES("Accept-Ranges");
+const std::string HTTP_OUT_HEADER_AGE("Age");
+const std::string HTTP_OUT_HEADER_ALLOW("Allow");
+const std::string HTTP_OUT_HEADER_AUTHORIZATION("Authorization");
+const std::string HTTP_OUT_HEADER_CACHE_CONTROL("Cache-Control");
+const std::string HTTP_OUT_HEADER_CONNECTION("Connection");
+const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION("Content-Description");
+const std::string HTTP_OUT_HEADER_CONTENT_ENCODING("Content-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_ID("Content-ID");
+const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE("Content-Language");
+const std::string HTTP_OUT_HEADER_CONTENT_LENGTH("Content-Length");
+const std::string HTTP_OUT_HEADER_CONTENT_LOCATION("Content-Location");
+const std::string HTTP_OUT_HEADER_CONTENT_MD5("Content-MD5");
+const std::string HTTP_OUT_HEADER_CONTENT_RANGE("Content-Range");
+const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_TYPE("Content-Type");
+const std::string HTTP_OUT_HEADER_COOKIE("Cookie");
+const std::string HTTP_OUT_HEADER_DATE("Date");
+const std::string HTTP_OUT_HEADER_DESTINATION("Destination");
+const std::string HTTP_OUT_HEADER_ETAG("ETag");
+const std::string HTTP_OUT_HEADER_EXPECT("Expect");
+const std::string HTTP_OUT_HEADER_EXPIRES("Expires");
+const std::string HTTP_OUT_HEADER_FROM("From");
+const std::string HTTP_OUT_HEADER_HOST("Host");
+const std::string HTTP_OUT_HEADER_IF_MATCH("If-Match");
+const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
+const std::string HTTP_OUT_HEADER_IF_NONE_MATCH("If-None-Match");
+const std::string HTTP_OUT_HEADER_IF_RANGE("If-Range");
+const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since");
+const std::string HTTP_OUT_HEADER_KEEP_ALIVE("Keep-Alive");
+const std::string HTTP_OUT_HEADER_LAST_MODIFIED("Last-Modified");
+const std::string HTTP_OUT_HEADER_LOCATION("Location");
+const std::string HTTP_OUT_HEADER_MAX_FORWARDS("Max-Forwards");
+const std::string HTTP_OUT_HEADER_MIME_VERSION("MIME-Version");
+const std::string HTTP_OUT_HEADER_PRAGMA("Pragma");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization");
+const std::string HTTP_OUT_HEADER_RANGE("Range");
+const std::string HTTP_OUT_HEADER_REFERER("Referer");
+const std::string HTTP_OUT_HEADER_RETRY_AFTER("Retry-After");
+const std::string HTTP_OUT_HEADER_SERVER("Server");
+const std::string HTTP_OUT_HEADER_SET_COOKIE("Set-Cookie");
+const std::string HTTP_OUT_HEADER_TE("TE");
+const std::string HTTP_OUT_HEADER_TRAILER("Trailer");
+const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING("Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_UPGRADE("Upgrade");
+const std::string HTTP_OUT_HEADER_USER_AGENT("User-Agent");
+const std::string HTTP_OUT_HEADER_VARY("Vary");
+const std::string HTTP_OUT_HEADER_VIA("Via");
+const std::string HTTP_OUT_HEADER_WARNING("Warning");
+const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE("WWW-Authenticate");
+
+// Incoming headers are normalized to lower-case.
+const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE("accept-language");
+const std::string HTTP_IN_HEADER_CACHE_CONTROL("cache-control");
+const std::string HTTP_IN_HEADER_CONTENT_LENGTH("content-length");
+const std::string HTTP_IN_HEADER_CONTENT_LOCATION("content-location");
+const std::string HTTP_IN_HEADER_CONTENT_TYPE("content-type");
+const std::string HTTP_IN_HEADER_HOST("host");
+const std::string HTTP_IN_HEADER_LOCATION("location");
+const std::string HTTP_IN_HEADER_RETRY_AFTER("retry-after");
+const std::string HTTP_IN_HEADER_SET_COOKIE("set-cookie");
+const std::string HTTP_IN_HEADER_USER_AGENT("user-agent");
+const std::string HTTP_IN_HEADER_X_FORWARDED_FOR("x-forwarded-for");
 
 const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml");
 const std::string HTTP_CONTENT_OCTET_STREAM("application/octet-stream");
@@ -121,6 +125,9 @@ const std::string HTTP_CONTENT_IMAGE_JPEG("image/jpeg");
 const std::string HTTP_CONTENT_IMAGE_PNG("image/png");
 const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp");
 
+const std::string HTTP_NO_CACHE("no-cache");
+const std::string HTTP_NO_CACHE_CONTROL("no-cache, max-age=0");
+
 const std::string HTTP_VERB_INVALID("(invalid)");
 const std::string HTTP_VERB_HEAD("HEAD");
 const std::string HTTP_VERB_GET("GET");
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h
index 34263e17c8..8cc3459654 100644
--- a/indra/llmessage/llhttpconstants.h
+++ b/indra/llmessage/llhttpconstants.h
@@ -132,71 +132,76 @@ bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_w
 
 //// HTTP Headers /////
 
-extern const std::string HTTP_HEADER_ACCEPT;
-extern const std::string HTTP_HEADER_ACCEPT_CHARSET;
-extern const std::string HTTP_HEADER_ACCEPT_ENCODING;
-extern const std::string HTTP_HEADER_ACCEPT_LANGUAGE;
-extern const std::string HTTP_HEADER_ACCEPT_RANGES;
-extern const std::string HTTP_HEADER_AGE;
-extern const std::string HTTP_HEADER_ALLOW;
-extern const std::string HTTP_HEADER_AUTHORIZATION;
-extern const std::string HTTP_HEADER_CACHE_CONTROL;
-extern const std::string HTTP_HEADER_CONNECTION;
-extern const std::string HTTP_HEADER_CONTENT_DESCRIPTION;
-extern const std::string HTTP_HEADER_CONTENT_ENCODING;
-extern const std::string HTTP_HEADER_CONTENT_ID;
-extern const std::string HTTP_HEADER_CONTENT_LANGUAGE;
-extern const std::string HTTP_HEADER_CONTENT_LENGTH;
-extern const std::string HTTP_HEADER_CONTENT_LOCATION;
-extern const std::string HTTP_HEADER_CONTENT_MD5;
-extern const std::string HTTP_HEADER_CONTENT_RANGE;
-extern const std::string HTTP_HEADER_CONTENT_TRANSFER_ENCODING;
-extern const std::string HTTP_HEADER_CONTENT_TYPE;
-extern const std::string HTTP_HEADER_COOKIE;
-extern const std::string HTTP_HEADER_DATE;
-extern const std::string HTTP_HEADER_DESTINATION;
-extern const std::string HTTP_HEADER_ETAG;
-extern const std::string HTTP_HEADER_EXPECT;
-extern const std::string HTTP_HEADER_EXPIRES;
-extern const std::string HTTP_HEADER_FROM;
-extern const std::string HTTP_HEADER_HOST;
-extern const std::string HTTP_HEADER_IF_MATCH;
-extern const std::string HTTP_HEADER_IF_MODIFIED_SINCE;
-extern const std::string HTTP_HEADER_IF_NONE_MATCH;
-extern const std::string HTTP_HEADER_IF_RANGE;
-extern const std::string HTTP_HEADER_IF_UNMODIFIED_SINCE;
-extern const std::string HTTP_HEADER_KEEP_ALIVE;
-extern const std::string HTTP_HEADER_LAST_MODIFIED;
-extern const std::string HTTP_HEADER_LOCATION;
-extern const std::string HTTP_HEADER_MAX_FORWARDS;
-extern const std::string HTTP_HEADER_MIME_VERSION;
-extern const std::string HTTP_HEADER_PRAGMA;
-extern const std::string HTTP_HEADER_PROXY_AUTHENTICATE;
-extern const std::string HTTP_HEADER_PROXY_AUTHORIZATION;
-extern const std::string HTTP_HEADER_RANGE;
-extern const std::string HTTP_HEADER_REFERER;
-extern const std::string HTTP_HEADER_RETRY_AFTER;
-extern const std::string HTTP_HEADER_SERVER;
-extern const std::string HTTP_HEADER_SET_COOKIE;
-extern const std::string HTTP_HEADER_TE;
-extern const std::string HTTP_HEADER_TRAILER;
-extern const std::string HTTP_HEADER_TRANSFER_ENCODING;
-extern const std::string HTTP_HEADER_UPGRADE;
-extern const std::string HTTP_HEADER_USER_AGENT;
-extern const std::string HTTP_HEADER_VARY;
-extern const std::string HTTP_HEADER_VIA;
-extern const std::string HTTP_HEADER_WARNING;
-extern const std::string HTTP_HEADER_WWW_AUTHENTICATE;
-
-// Sadly, our proxied headers do not follow http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
-// We need to deal with lowercase headers
-extern const std::string HTTP_HEADER_LOWER_ACCEPT_LANGUAGE;
-extern const std::string HTTP_HEADER_LOWER_CACHE_CONTROL;
-extern const std::string HTTP_HEADER_LOWER_CONTENT_LENGTH;
-extern const std::string HTTP_HEADER_LOWER_CONTENT_TYPE;
-extern const std::string HTTP_HEADER_LOWER_HOST;
-extern const std::string HTTP_HEADER_LOWER_USER_AGENT;
-extern const std::string HTTP_HEADER_LOWER_X_FORWARDED_FOR;
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+extern const std::string HTTP_OUT_HEADER_ACCEPT;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_RANGES;
+extern const std::string HTTP_OUT_HEADER_AGE;
+extern const std::string HTTP_OUT_HEADER_ALLOW;
+extern const std::string HTTP_OUT_HEADER_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_OUT_HEADER_CONNECTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ID;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_MD5;
+extern const std::string HTTP_OUT_HEADER_CONTENT_RANGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_OUT_HEADER_COOKIE;
+extern const std::string HTTP_OUT_HEADER_DATE;
+extern const std::string HTTP_OUT_HEADER_DESTINATION;
+extern const std::string HTTP_OUT_HEADER_ETAG;
+extern const std::string HTTP_OUT_HEADER_EXPECT;
+extern const std::string HTTP_OUT_HEADER_EXPIRES;
+extern const std::string HTTP_OUT_HEADER_FROM;
+extern const std::string HTTP_OUT_HEADER_HOST;
+extern const std::string HTTP_OUT_HEADER_IF_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_IF_NONE_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_RANGE;
+extern const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_KEEP_ALIVE;
+extern const std::string HTTP_OUT_HEADER_LAST_MODIFIED;
+extern const std::string HTTP_OUT_HEADER_LOCATION;
+extern const std::string HTTP_OUT_HEADER_MAX_FORWARDS;
+extern const std::string HTTP_OUT_HEADER_MIME_VERSION;
+extern const std::string HTTP_OUT_HEADER_PRAGMA;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_RANGE;
+extern const std::string HTTP_OUT_HEADER_REFERER;
+extern const std::string HTTP_OUT_HEADER_RETRY_AFTER;
+extern const std::string HTTP_OUT_HEADER_SERVER;
+extern const std::string HTTP_OUT_HEADER_SET_COOKIE;
+extern const std::string HTTP_OUT_HEADER_TE;
+extern const std::string HTTP_OUT_HEADER_TRAILER;
+extern const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_UPGRADE;
+extern const std::string HTTP_OUT_HEADER_USER_AGENT;
+extern const std::string HTTP_OUT_HEADER_VARY;
+extern const std::string HTTP_OUT_HEADER_VIA;
+extern const std::string HTTP_OUT_HEADER_WARNING;
+extern const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE;
+
+// Incoming headers are normalized to lower-case.
+extern const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_IN_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_IN_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_IN_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_IN_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_IN_HEADER_HOST;
+extern const std::string HTTP_IN_HEADER_LOCATION;
+extern const std::string HTTP_IN_HEADER_RETRY_AFTER;
+extern const std::string HTTP_IN_HEADER_SET_COOKIE;
+extern const std::string HTTP_IN_HEADER_USER_AGENT;
+extern const std::string HTTP_IN_HEADER_X_FORWARDED_FOR;
 
 //// HTTP Content Types ////
 
@@ -217,4 +222,8 @@ extern const std::string HTTP_CONTENT_IMAGE_JPEG;
 extern const std::string HTTP_CONTENT_IMAGE_PNG;
 extern const std::string HTTP_CONTENT_IMAGE_BMP;
 
+//// HTTP Cache Settings ////
+extern const std::string HTTP_NO_CACHE;
+extern const std::string HTTP_NO_CACHE_CONTROL;
+
 #endif
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index e3b42b1b16..c0c3d0bcbe 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -31,9 +31,14 @@
 
 #include "llstl.h"
 #include "llhttpconstants.h"
-#include "lliohttpserver.h" // for string constants
 
-static const std::string CONTEXT_WILDCARD("wildcard");
+const std::string CONTEXT_HEADERS("headers");
+const std::string CONTEXT_PATH("path");
+const std::string CONTEXT_QUERY_STRING("query-string");
+const std::string CONTEXT_REQUEST("request");
+const std::string CONTEXT_RESPONSE("response");
+const std::string CONTEXT_VERB("verb");
+const std::string CONTEXT_WILDCARD("wildcard");
 
 /**
  * LLHTTPNode
@@ -177,9 +182,8 @@ void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
 	LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL;
 
 	// default implementation constructs an url to the documentation.
-	// *TODO: Check for 'Host' header instead of 'host' header?
 	std::string host(
-		context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_HEADER_LOWER_HOST].asString());
+		context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_IN_HEADER_HOST].asString());
 	if(host.empty())
 	{
 		response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header");
@@ -187,7 +191,7 @@ void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
 	}
 	std::ostringstream ostr;
 	ostr << "http://" << host << "/web/server/api";
-	ostr << context[CONTEXT_REQUEST]["path"].asString();
+	ostr << context[CONTEXT_REQUEST][CONTEXT_PATH].asString();
 	static const std::string DOC_HEADER("X-Documentation-URL");
 	response->addHeader(DOC_HEADER, ostr.str());
 	response->status(HTTP_OK, "OK");
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 2539eec6c3..1144d88be1 100644
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -31,6 +31,17 @@
 #include "llrefcount.h"
 #include "llsd.h"
 
+// common strings use for populating the context. basically 'request',
+// 'wildcard', and 'headers'.
+extern const std::string CONTEXT_HEADERS;
+extern const std::string CONTEXT_PATH;
+extern const std::string CONTEXT_QUERY_STRING;
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_VERB;
+extern const std::string CONTEXT_WILDCARD;
+
+
 class LLChainIOFactory;
 
 /**
@@ -125,7 +136,7 @@ public:
 		virtual void methodNotAllowed();
 
 		/**
-		* @breif Add a name: value http header.
+		* @brief Add a name: value http header.
 		*
 		* No effort is made to ensure the response is a valid http
 		* header.
@@ -194,15 +205,15 @@ public:
 			 name, and return true if the name will construct to a valid url.
 			 For convenience, the <code>getChild()</code> method above will
 			 automatically insert the name in
-			 context["request"]["wildcard"][key] if this method returns true.
+			 context[CONTEXT_REQUEST][CONTEXT_WILDCARD][key] if this method returns true.
 			 For example, the node "agent/<agent_id>/detail" will set
-			 context["request"]["wildcard"]["agent_id"] eqaul to the value 
+			 context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["agent_id"] eqaul to the value 
 			 found during traversal.
 		*/
 		
 	const LLHTTPNode* traverse(const std::string& path, LLSD& context) const;
 		/**< find a node, if any, that can service this path
-			 set up context["request"] information 
+			 set up context[CONTEXT_REQUEST] information 
  		*/
  	//@}
  
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 509719786c..293e74d0da 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -50,10 +50,6 @@
 #include <boost/tokenizer.hpp>
 
 static const char HTTP_VERSION_STR[] = "HTTP/1.0";
-const std::string CONTEXT_REQUEST("request");
-const std::string CONTEXT_RESPONSE("response");
-const std::string CONTEXT_VERB("verb");
-const std::string CONTEXT_HEADERS("headers");
 
 static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL;
 static void* sTimingCallbackData = NULL;
@@ -241,7 +237,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		// Log all HTTP transactions.
 		// TODO: Add a way to log these to their own file instead of indra.log
 		// It is just too spammy to be in indra.log.
-		lldebugs << verb << " " << context[CONTEXT_REQUEST]["path"].asString()
+		lldebugs << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
 			<< " " << mStatusCode << " " <<  mStatusMessage << " " << delta
 			<< "s" << llendl;
 
@@ -268,7 +264,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_GOOD_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+			headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			LLBufferStream ostr(channels, buffer.get());
 			LLSDSerialize::toXML(mResult, ostr);
@@ -279,7 +275,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_STATUS_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
+			headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
 			context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
@@ -300,7 +296,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		case STATE_EXTENDED_LLSD_RESULT:
 		{
 			LLSD headers = mHeaders;
-			headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+			headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
 			context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
 			context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
 			LLBufferStream ostr(channels, buffer.get());
@@ -489,7 +485,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 		S32 content_length = buffer->countAfter(channels.in(), NULL);
 		if(0 < content_length)
 		{
-			ostr << HTTP_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
+			ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
 		}
 		// *NOTE: This guard can go away once the LLSD static map
 		// iterator is available. Phoenix. 2008-05-09
@@ -795,7 +791,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 					std::string name(buf, pos_colon - buf);
 					std::string value(pos_colon + 2);
 					LLStringUtil::toLower(name);
-					if(HTTP_HEADER_LOWER_CONTENT_LENGTH == name)
+					if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
 					{
 						lldebugs << "Content-Length: " << value << llendl;
 						mContentLength = atoi(value.c_str());
@@ -870,12 +866,12 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 			// HTTP headers.
 			LLPumpIO::chain_t chain;
 			chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
-			context[CONTEXT_REQUEST]["path"] = mPath;
-			context[CONTEXT_REQUEST]["query-string"] = mQuery;
-			context[CONTEXT_REQUEST]["remote-host"]
-				= mBuildContext["remote-host"];
-			context[CONTEXT_REQUEST]["remote-port"]
-				= mBuildContext["remote-port"];
+			context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
+			context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
+			context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
+				= mBuildContext[CONTEXT_REMOTE_HOST];
+			context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
+				= mBuildContext[CONTEXT_REMOTE_PORT];
 			context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
 
 			const LLChainIOFactory* protocolHandler
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index 40537e05bc..a23eafe58a 100644
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -33,13 +33,6 @@
 
 class LLPumpIO;
 
-// common strings use for populating the context. bascally 'request',
-// 'wildcard', and 'headers'.
-extern const std::string CONTEXT_REQUEST;
-extern const std::string CONTEXT_RESPONSE;
-extern const std::string CONTEXT_VERB;
-extern const std::string CONTEXT_HEADERS;
-
 class LLIOHTTPServer
 {
 public:
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 2043bae5e7..a60b840067 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -39,6 +39,9 @@
 // constants
 //
 
+const std::string CONTEXT_REMOTE_HOST("remote-host");
+const std::string CONTEXT_REMOTE_PORT("remote-port");
+
 static const S32 LL_DEFAULT_LISTEN_BACKLOG = 10;
 static const S32 LL_SEND_BUFFER_SIZE = 40000;
 static const S32 LL_RECV_BUFFER_SIZE = 40000;
@@ -619,8 +622,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
 		apr_sockaddr_ip_get(&remote_host_string, remote_addr);
 
 		LLSD context;
-		context["remote-host"] = remote_host_string;
-		context["remote-port"] = remote_addr->port;
+		context[CONTEXT_REMOTE_HOST] = remote_host_string;
+		context[CONTEXT_REMOTE_PORT] = remote_addr->port;
 
 		LLPumpIO::chain_t chain;
 		chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index be0f7dfcc6..08c21a1b97 100644
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -42,6 +42,9 @@
 #include "apr_network_io.h"
 #include "llchainio.h"
 
+extern const std::string CONTEXT_REMOTE_HOST;
+extern const std::string CONTEXT_REMOTE_PORT;
+
 class LLHost;
 
 /** 
diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp
deleted file mode 100644
index 90653098db..0000000000
--- a/indra/llmessage/llmime.cpp
+++ /dev/null
@@ -1,628 +0,0 @@
-/** 
- * @file llmime.cpp
- * @author Phoenix
- * @date 2006-12-20
- * @brief Implementation of mime tools.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llhttpconstants.h"
-#include "llmime.h"
-
-#include <vector>
-
-#include "llmemorystream.h"
-
-/**
- * Useful constants.
- */
-// parser helpers
-static const std::string MULTIPART("multipart");
-static const std::string BOUNDARY("boundary");
-static const std::string END_OF_CONTENT_PARAMETER("\r\n ;\t");
-static const std::string SEPARATOR_PREFIX("--");
-//static const std::string SEPARATOR_SUFFIX("\r\n");
-
-/*
-Content-Type: multipart/mixed; boundary="segment"
-Content-Length: 24832
-
---segment
-Content-Type: image/j2c
-Content-Length: 23715
-
-<data>
-
---segment
-Content-Type: text/xml; charset=UTF-8
-
-<meta data>
-EOF
-
-*/
-
-/**
- * LLMimeIndex
- */
-
-/** 
- * @class LLMimeIndex::Impl
- * @brief Implementation details of the mime index class.
- * @see LLMimeIndex
- */
-class LLMimeIndex::Impl
-{
-public:
-	Impl() : mOffset(-1), mUseCount(1)
-	{}
-	Impl(LLSD headers, S32 offset) :
-		mHeaders(headers), mOffset(offset), mUseCount(1)
-	{}
-public:
-	LLSD mHeaders;
-	S32 mOffset;
-	S32 mUseCount;
-
-	typedef std::vector<LLMimeIndex> sub_part_t;
-	sub_part_t mAttachments;
-};
-
-LLSD LLMimeIndex::headers() const
-{
-	return mImpl->mHeaders;
-}
-
-S32 LLMimeIndex::offset() const
-{
-	return mImpl->mOffset;
-}
-
-S32 LLMimeIndex::contentLength() const
-{
-	// Find the content length in the headers.
-	S32 length = -1;
-	LLSD content_length = mImpl->mHeaders[HTTP_HEADER_CONTENT_LENGTH];
-	if(content_length.isDefined())
-	{
-		length = content_length.asInteger();
-	}
-	return length;
-}
-
-std::string LLMimeIndex::contentType() const
-{
-	std::string type;
-	LLSD content_type = mImpl->mHeaders[HTTP_HEADER_CONTENT_TYPE];
-	if(content_type.isDefined())
-	{
-		type = content_type.asString();
-	}
-	return type;
-}
-
-bool LLMimeIndex::isMultipart() const
-{
-	bool multipart = false;
-	LLSD content_type = mImpl->mHeaders[HTTP_HEADER_CONTENT_TYPE];
-	if(content_type.isDefined())
-	{
-		std::string type = content_type.asString();
-		int comp = type.compare(0, MULTIPART.size(), MULTIPART);
-		if(0 == comp)
-		{
-			multipart = true;
-		}
-	}
-	return multipart;
-}
-
-S32 LLMimeIndex::subPartCount() const
-{
-	return mImpl->mAttachments.size();
-}
-
-LLMimeIndex LLMimeIndex::subPart(S32 index) const
-{
-	LLMimeIndex part;
-	if((index >= 0) && (index < (S32)mImpl->mAttachments.size()))
-	{
-		part = mImpl->mAttachments[index];
-	}
-	return part;
-}
-
-LLMimeIndex::LLMimeIndex() : mImpl(new LLMimeIndex::Impl)
-{
-}
-
-LLMimeIndex::LLMimeIndex(LLSD headers, S32 content_offset) :
-	mImpl(new LLMimeIndex::Impl(headers, content_offset))
-{
-}
-
-LLMimeIndex::LLMimeIndex(const LLMimeIndex& mime) :
-	mImpl(mime.mImpl)
-{
-	++mImpl->mUseCount;
-}
-
-LLMimeIndex::~LLMimeIndex()
-{
-	if(0 == --mImpl->mUseCount)
-	{
-		delete mImpl;
-	}
-}
-
-LLMimeIndex& LLMimeIndex::operator=(const LLMimeIndex& mime)
-{
-	// Increment use count first so that we handle self assignment
-	// automatically.
-	++mime.mImpl->mUseCount;
-	if(0 == --mImpl->mUseCount)
-	{
-		delete mImpl;
-	}
-	mImpl = mime.mImpl;
-	return *this;
-}
-
-bool LLMimeIndex::attachSubPart(LLMimeIndex sub_part)
-{
-	// *FIX: Should we check for multi-part?
-	if(mImpl->mAttachments.size() < S32_MAX)
-	{
-		mImpl->mAttachments.push_back(sub_part);
-		return true;
-	}
-	return false;
-}
-
-/**
- * LLMimeParser
- */
-/** 
- * @class LLMimeParser::Impl
- * @brief Implementation details of the mime parser class.
- * @see LLMimeParser
- */
-class LLMimeParser::Impl
-{
-public:
-	// @brief Constructor.
-	Impl();
-
-	// @brief Reset this for a new parse.
-	void reset();
-
-	/** 
-	 * @brief Parse a mime entity to find the index information.
-	 *
-	 * This method will scan the istr until a single complete mime
-	 * entity is read, an EOF, or limit bytes have been scanned. The
-	 * istr will be modified by this parsing, so pass in a temporary
-	 * stream or rewind/reset the stream after this call.
-	 * @param istr An istream which contains a mime entity.
-	 * @param limit The maximum number of bytes to scan.
-	 * @param separator The multipart separator if it is known.
-	 * @param is_subpart Set true if parsing a multipart sub part.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(
-		std::istream& istr,
-		S32 limit,
-		const std::string& separator,
-		bool is_subpart,
-		LLMimeIndex& index);
-
-protected:
-	/**
-	 * @brief parse the headers.
-	 *
-	 * At the end of a successful parse, mScanCount will be at the
-	 * start of the content.
-	 * @param istr The input stream.
-	 * @param limit maximum number of bytes to process
-	 * @param headers[out] A map of the headers found.
-	 * @return Returns true if the parse was successful.
-	 */
-	bool parseHeaders(std::istream& istr, S32 limit, LLSD& headers);
-
-	/**
-	 * @brief Figure out the separator string from a content type header.
-	 * 
-	 * @param multipart_content_type The content type value from the headers.
-	 * @return Returns the separator string.
-	 */
-	std::string findSeparator(std::string multipart_content_type);
-
-	/**
-	 * @brief Scan through istr past the separator.
-	 *
-	 * @param istr The input stream.
-	 * @param limit Maximum number of bytes to scan.
-	 * @param separator The multipart separator.
-	 */
-	void scanPastSeparator(
-		std::istream& istr,
-		S32 limit,
-		const std::string& separator);
-
-	/**
-	 * @brief Scan through istr past the content of the current mime part.
-	 *
-	 * @param istr The input stream.
-	 * @param limit Maximum number of bytes to scan.
-	 * @param headers The headers for this mime part.
-	 * @param separator The multipart separator if known.
-	 */
-	void scanPastContent(
-		std::istream& istr,
-		S32 limit,
-		LLSD headers,
-		const std::string separator);
-
-	/**
-	 * @brief Eat CRLF.
-	 *
-	 * This method has no concept of the limit, so ensure you have at
-	 * least 2 characters left to eat before hitting the limit. This
-	 * method will increment mScanCount as it goes.
-	 * @param istr The input stream.
-	 * @return Returns true if CRLF was found and consumed off of istr.
-	 */
-	bool eatCRLF(std::istream& istr);
-
-	// @brief Returns true if parsing should continue.
-	bool continueParse() const { return (!mError && mContinue); }
-
-	// @brief anonymous enumeration for parse buffer size.
-	enum
-	{
-		LINE_BUFFER_LENGTH = 1024
-	};
-
-protected:
-	S32 mScanCount;
-	bool mContinue;
-	bool mError;
-	char mBuffer[LINE_BUFFER_LENGTH];
-};
-
-LLMimeParser::Impl::Impl()
-{
-	reset();
-}
-
-void LLMimeParser::Impl::reset()
-{
-	mScanCount = 0;
-	mContinue = true;
-	mError = false;
-	mBuffer[0] = '\0';
-}
-
-bool LLMimeParser::Impl::parseIndex(
-	std::istream& istr,
-	S32 limit,
-	const std::string& separator,
-	bool is_subpart,
-	LLMimeIndex& index)
-{
-	LLSD headers;
-	bool parsed_something = false;
-	if(parseHeaders(istr, limit, headers))
-	{
-		parsed_something = true;
-		LLMimeIndex mime(headers, mScanCount);
-		index = mime;
-		if(index.isMultipart())
-		{
-			// Figure out the separator, scan past it, and recurse.
-			std::string ct = headers[HTTP_HEADER_CONTENT_TYPE].asString();
-			std::string sep = findSeparator(ct);
-			scanPastSeparator(istr, limit, sep);
-			while(continueParse() && parseIndex(istr, limit, sep, true, mime))
-			{
-				index.attachSubPart(mime);
-			}
-		}
-		else
-		{
-			// Scan to the end of content.
-			scanPastContent(istr, limit, headers, separator);
-			if(is_subpart)
-			{
-				scanPastSeparator(istr, limit, separator);
-			}
-		}
-	}
-	if(mError) return false;
-	return parsed_something;
-}
-
-bool LLMimeParser::Impl::parseHeaders(
-	std::istream& istr,
-	S32 limit,
-	LLSD& headers)
-{
-	// Headers specified in rfc-2045 will be canonicalized below.
-	static const S32 KNOWN_HEADER_COUNT = 6;
-	static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] =
-	{
-		HTTP_HEADER_CONTENT_LENGTH,
-		HTTP_HEADER_CONTENT_TYPE,
-		HTTP_HEADER_MIME_VERSION,
-		HTTP_HEADER_CONTENT_TRANSFER_ENCODING,
-		HTTP_HEADER_CONTENT_ID,
-		HTTP_HEADER_CONTENT_DESCRIPTION,
-	};
-
-	while(continueParse())
-	{
-		// Get the next line.
-		// We subtract 1 from the limit so that we make sure
-		// not to read past limit when we get() the newline.
-		S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
-		istr.getline(mBuffer, max_get, '\r');
-		mScanCount += (S32)istr.gcount();
-		int c = istr.get();
-		if(EOF == c)
-		{
-			mContinue = false;
-			return false;
-		}
-		++mScanCount;
-		if(c != '\n')
-		{
-			mError = true;
-			return false;
-		}
-		if(mScanCount >= limit)
-		{
-			mContinue = false;
-		}
-
-		// Check if that's the end of headers.
-		if('\0' == mBuffer[0])
-		{
-			break;
-		}
-
-		// Split out the name and value.
-		// *NOTE: The use of strchr() here is safe since mBuffer is
-		// guaranteed to be NULL terminated from the call to getline()
-		// above.
-		char* colon = strchr(mBuffer, ':');
-		if(!colon)
-		{
-			mError = true;
-			return false;
-		}
-
-		// Cononicalize the name part, and store the name: value in
-		// the headers structure. We do this by iterating through
-		// 'known' headers and replacing the value found with the
-		// correct one.
-		// *NOTE: Not so efficient, but iterating through a small
-		// subset should not be too much of an issue.
-		std::string name(mBuffer, colon++ - mBuffer);
-		while(isspace(*colon)) ++colon;
-		std::string value(colon);
-		for(S32 ii = 0; ii < KNOWN_HEADER_COUNT; ++ii)
-		{
-			if(0 == LLStringUtil::compareInsensitive(name, KNOWN_HEADER[ii]))
-			{
-				name = KNOWN_HEADER[ii];
-				break;
-			}
-		}
-		headers[name] = value;
-	}
-	if(headers.isUndefined()) return false;
-	return true;
-}
-
-std::string LLMimeParser::Impl::findSeparator(std::string header)
-{
-	//                               01234567890
-	//Content-Type: multipart/mixed; boundary="segment"
-	std::string separator;
-	std::string::size_type pos = header.find(BOUNDARY);
-	if(std::string::npos == pos) return separator;
-	pos += BOUNDARY.size() + 1;
-	std::string::size_type end;
-	if(header[pos] == '"')
-	{
-		// the boundary is quoted, find the end from pos, and take the
-		// substring.
-		end = header.find('"', ++pos);
-		if(std::string::npos == end)
-		{
-			// poorly formed boundary.
-			mError = true;
-		}
-	}
-	else
-	{
-		// otherwise, it's every character until a whitespace, end of
-		// line, or another parameter begins.
-		end = header.find_first_of(END_OF_CONTENT_PARAMETER, pos);
-		if(std::string::npos == end)
-		{
-			// it goes to the end of the string.
-			end = header.size();
-		}
-	}
-	if(!mError) separator = header.substr(pos, end - pos);
-	return separator;
-}
-
-void LLMimeParser::Impl::scanPastSeparator(
-	std::istream& istr,
-	S32 limit,
-	const std::string& sep)
-{
-	std::ostringstream ostr;
-	ostr << SEPARATOR_PREFIX << sep;
-	std::string separator = ostr.str();
-	bool found_separator = false;
-	while(!found_separator && continueParse())
-	{
-		// Subtract 1 from the limit so that we make sure not to read
-		// past limit when we get() the newline.
-		S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
-		istr.getline(mBuffer, max_get, '\r');
-		mScanCount += (S32)istr.gcount();
-		if(istr.gcount() >= LINE_BUFFER_LENGTH - 1)
-		{
-			// that's way too long to be a separator, so ignore it.
-			continue;
-		}
-		int c = istr.get();
-		if(EOF == c)
-		{
-			mContinue = false;
-			return;
-		}
-		++mScanCount;
-		if(c != '\n')
-		{
-			mError = true;
-			return;
-		}
-		if(mScanCount >= limit)
-		{
-			mContinue = false;
-		}
-		if(0 == LLStringUtil::compareStrings(std::string(mBuffer), separator))
-		{
-			found_separator = true;
-		}
-	}
-}
-
-void LLMimeParser::Impl::scanPastContent(
-	std::istream& istr,
-	S32 limit,
-	LLSD headers,
-	const std::string separator)
-{
-	if(headers.has(HTTP_HEADER_CONTENT_LENGTH))
-	{
-		S32 content_length = headers[HTTP_HEADER_CONTENT_LENGTH].asInteger();
-		// Subtract 2 here for the \r\n after the content.
-		S32 max_skip = llmin(content_length, limit - mScanCount - 2);
-		istr.ignore(max_skip);
-		mScanCount += max_skip;
-
-		// *NOTE: Check for hitting the limit and eof here before
-		// checking for the trailing EOF, because our mime parser has
-		// to gracefully handle incomplete mime entites.
-		if((mScanCount >= limit) || istr.eof())
-		{
-			mContinue = false;
-		}
-		else if(!eatCRLF(istr))
-		{
-			mError = true;
-			return;
-		}
-	}
-}
-
-bool LLMimeParser::Impl::eatCRLF(std::istream& istr)
-{
-	int c = istr.get();
-	++mScanCount;
-	if(c != '\r')
-	{
-		return false;
-	}
-	c = istr.get();
-	++mScanCount;
-	if(c != '\n')
-	{
-		return false;
-	}
-	return true;
-}
-	
-
-LLMimeParser::LLMimeParser() : mImpl(* new LLMimeParser::Impl)
-{
-}
-
-LLMimeParser::~LLMimeParser()
-{
-	delete & mImpl;
-}
-
-void LLMimeParser::reset()
-{
-	mImpl.reset();
-}
-
-bool LLMimeParser::parseIndex(std::istream& istr, LLMimeIndex& index)
-{
-	std::string separator;
-	return mImpl.parseIndex(istr, S32_MAX, separator, false, index);
-}
-
-bool LLMimeParser::parseIndex(
-	const std::vector<U8>& buffer,
-	LLMimeIndex& index)
-{
-	LLMemoryStream mstr(&buffer[0], buffer.size());
-	return parseIndex(mstr, buffer.size() + 1, index);
-}
-
-bool LLMimeParser::parseIndex(
-	std::istream& istr,
-	S32 limit,
-	LLMimeIndex& index)
-{
-	std::string separator;
-	return mImpl.parseIndex(istr, limit, separator, false, index);
-}
-
-bool LLMimeParser::parseIndex(const U8* buffer, S32 length, LLMimeIndex& index)
-{
-	LLMemoryStream mstr(buffer, length);
-	return parseIndex(mstr, length + 1, index);
-}
-
-/*
-bool LLMimeParser::verify(std::istream& isr, LLMimeIndex& index) const
-{
-	return false;
-}
-
-bool LLMimeParser::verify(U8* buffer, S32 length, LLMimeIndex& index) const
-{
-	LLMemoryStream mstr(buffer, length);
-	return verify(mstr, index);
-}
-*/
diff --git a/indra/llmessage/llmime.h b/indra/llmessage/llmime.h
deleted file mode 100644
index e6617fb503..0000000000
--- a/indra/llmessage/llmime.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/** 
- * @file llmime.h
- * @author Phoenix
- * @date 2006-12-20
- * @brief Declaration of mime tools.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMIME_H
-#define LL_LLMIME_H
-
-#include <string>
-#include "llsd.h"
-
-/**
- * This file declares various tools for parsing and creating MIME
- * objects as described in RFCs 2045, 2046, 2047, 2048, and 2049.
- */
-
-/** 
- * @class LLMimeIndex
- * @brief Skeletal information useful for handling mime packages.
- * @see LLMimeParser
- *
- * An instance of this class is the parsed output from a LLMimeParser
- * which then allows for easy access into a data stream to find and
- * get what you want out of it.
- *
- * This class meant as a tool to quickly find what you seek in a
- * parsed mime entity. As such, it does not have useful support for
- * modification of a mime entity and specializes the interface toward
- * querying data from a fixed mime entity. Modifying an instance of
- * LLMimeIndx does not alter a mime entity and changes to a mime
- * entity itself are not propogated into an instance of a LLMimeIndex.
- *
- * Usage:<br>
- *  LLMimeIndex mime_index;<br>
- *  std::ifstream fstr("package.mime", ios::binary);<br>
- *  LLMimeParser parser;<br>
- *  if(parser.parseIndex(fstr, mime_index))<br>
- *  {<br>
- *    std::vector<U8> content;<br>
- *    content.resize(mime_index.contentLength());<br>
- *    fstr.seekg(mime_index.offset(), ios::beg);<br>
- *    // ...do work on fstr and content<br>
- *  }<br>
- */
-class LLMimeIndex
-{
-public:
-	/* @name Client interface.
-	 */
-	//@{
-	/** 
-	 * @brief Get the full parsed headers for this.
-	 *
-	 * If there are any headers, it will be a map of header name to
-	 * the value found on the line. The name is everything before the
-	 * colon, and the value is the string found after the colon to the
-	 * end of the line after trimming leading whitespace. So, for
-	 * example:
-	 * Content-Type:  text/plain
-	 * would become an entry in the headers of:
-	 * headers["Content-Type"] == "text/plain"
-	 *
-	 * If this instance of an index was generated by the
-	 * LLMimeParser::parseIndex() call, all header names in rfc2045
-	 * will be capitalized as in rfc, eg Content-Length and
-	 * MIME-Version, not content-length and mime-version.
-	 * @return Returns an LLSD map of header name to value. Returns
-	 * undef if there are no headers.
-	 */
-	LLSD headers() const;
-
-	/** 
-	 * @brief Get the content offset.
-	 *
-	 * @return Returns the number of bytes to the start of the data
-	 * segment from the start of serialized mime entity. Returns -1 if
-	 * offset is not known.
-	 */
-	S32 offset() const;
-
-	/** 
-	 * @brief Get the length of the data segment for this mime part.
-	 *
-	 * @return Returns the content length in bytes. Returns -1 if
-	 * length is not known.
-	 */
-	S32 contentLength() const;
-
-	/** 
-	 * @brief Get the mime type associated with this node.
-	 *
-	 * @return Returns the mimetype.
-	 */
-	std::string contentType() const;
-
-	/** 
-	 * @brief Helper method which simplifies parsing the return from type()
-	 *
-	 * @return Returns true if this is a multipart mime, and therefore
-	 * getting subparts will succeed.
-	 */
-	bool isMultipart() const;
-
-	/** 
-	 * @brief Get the number of atachments.
-	 *
-	 * @return Returns the number of sub-parts for this.
-	 */
-	S32 subPartCount() const;
-
-	/** 
-	 * @brief Get the indicated attachment.
-	 *
-	 * @param index Value from 0 to (subPartCount() - 1).
-	 * @return Returns the indicated sub-part, or an invalid mime
-	 * index on failure.
-	 */
-	LLMimeIndex subPart(S32 index) const;
-	//@}
-
-	/* @name Interface for building, testing, and helpers for typical use.
-	 */
-	//@{
-	/**
-	 * @brief Default constructor - creates a useless LLMimeIndex.
-	 */
-	LLMimeIndex();
-
-	/**
-	 * @brief Full constructor.
-	 *
-	 * @param headers The complete headers.
-	 * @param content_offset The number of bytes to the start of the
-	 * data segment of this mime entity from the start of the stream
-	 * or buffer.
-	 */
-	LLMimeIndex(LLSD headers, S32 content_offset);
-
-	/**
-	 * @brief Copy constructor.
-	 *
-	 * @param mime The other mime object.
-	 */
-	LLMimeIndex(const LLMimeIndex& mime);
-
-	// @brief Destructor.
-	~LLMimeIndex();
-
-	/*
-	 * @breif Assignment operator.
-	 *
-	 * @param mime The other mime object.
-	 * @return Returns this after assignment.
-	 */
-	LLMimeIndex& operator=(const LLMimeIndex& mime);
-
-	/** 
-	 * @brief Add attachment information as a sub-part to a multipart mime.
-	 *
-	 * @param sub_part the part to attach.
-	 * @return Returns true on success, false on failure.
-	 */
-	bool attachSubPart(LLMimeIndex sub_part);
-	//@}
-
-protected:
-	// Implementation.
-	class Impl;
-	Impl* mImpl;
-};
-
-
-/** 
- * @class LLMimeParser
- * @brief This class implements a MIME parser and verifier.
- *
- * THOROUGH_DESCRIPTION
- */
-class LLMimeParser
-{
-public:
-	// @brief Make a new mime parser.
-	LLMimeParser();
-	
-	// @brief Mime parser Destructor.
-	~LLMimeParser();
-
-	// @brief Reset internal state of this parser.
-	void reset();
-
-	
-	/* @name Index generation interface.
-	 */
-	//@{
-	/** 
-	 * @brief Parse a stream to find the mime index information.
-	 *
-	 * This method will scan the istr until a single complete mime
-	 * entity is read or EOF. The istr will be modified by this
-	 * parsing, so pass in a temporary stream or rewind/reset the
-	 * stream after this call.
-	 * @param istr An istream which contains a mime entity.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(std::istream& istr, LLMimeIndex& index);
-
-	/** 
-	 * @brief Parse a vector to find the mime index information.
-	 *
-	 * @param buffer A vector with data to parse.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(const std::vector<U8>& buffer, LLMimeIndex& index);
-
-	/** 
-	 * @brief Parse a stream to find the mime index information.
-	 *
-	 * This method will scan the istr until a single complete mime
-	 * entity is read, an EOF, or limit bytes have been scanned. The
-	 * istr will be modified by this parsing, so pass in a temporary
-	 * stream or rewind/reset the stream after this call.
-	 * @param istr An istream which contains a mime entity.
-	 * @param limit The maximum number of bytes to scan.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(std::istream& istr, S32 limit, LLMimeIndex& index);
-
-	/** 
-	 * @brief Parse a memory bufffer to find the mime index information.
-	 *
-	 * @param buffer The start of the buffer to parse.
-	 * @param buffer_length The length of the buffer.
-	 * @param index[out] The parsed output.
-	 * @return Returns true if an index was parsed and no errors occurred.
-	 */
-	bool parseIndex(const U8* buffer, S32 buffer_length, LLMimeIndex& index);
-	//@}
-
-	/** 
-	 * @brief 
-	 *
-	 * @return
-	 */
-	//bool verify(std::istream& istr, LLMimeIndex& index) const;
-
-	/** 
-	 * @brief 
-	 *
-	 * @return
-	 */
-	//bool verify(U8* buffer, S32 buffer_length, LLMimeIndex& index) const;
-
-protected:
-	// Implementation.
-	class Impl;
-	Impl& mImpl;
-
-private:
-	// @brief Not implemneted to prevent copy consturction.
-	LLMimeParser(const LLMimeParser& parser);
-
-	// @brief Not implemneted to prevent assignment.
-	LLMimeParser& operator=(const LLMimeParser& mime);
-};
-
-#endif // LL_LLMIME_H
diff --git a/indra/llmessage/llsdappservices.cpp b/indra/llmessage/llsdappservices.cpp
index 8bab91b0c0..c593027802 100644
--- a/indra/llmessage/llsdappservices.cpp
+++ b/indra/llmessage/llsdappservices.cpp
@@ -121,7 +121,7 @@ public:
 	{
 		//llinfos << "validate: " << name << ", "
 		//	<< LLSDOStreamer<LLSDNotationFormatter>(context) << llendl;
-		if((std::string("PUT") == context["request"]["verb"].asString()) && !name.empty())
+		if((std::string("PUT") == context[CONTEXT_REQUEST][CONTEXT_VERB].asString()) && !name.empty())
 		{
 			return true;
 		}
@@ -139,7 +139,7 @@ public:
 		LLHTTPNode::ResponsePtr response,
 		const LLSD& context) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		LLSD options = LLApp::instance()->getOptionData(
 			LLApp::PRIORITY_RUNTIME_OVERRIDE);
 		response->result(options[name]);
@@ -150,7 +150,7 @@ public:
 		const LLSD& context,
 		const LLSD& input) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		LLSD options = LLApp::instance()->getOptionData(
 			LLApp::PRIORITY_RUNTIME_OVERRIDE);
 		options[name] = input;
@@ -164,7 +164,7 @@ public:
 		LLHTTPNode::ResponsePtr response,
 		const LLSD& context) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		LLSD options = LLApp::instance()->getOptionData(
 			LLApp::PRIORITY_RUNTIME_OVERRIDE);
 		options.erase(name);
@@ -268,7 +268,7 @@ public:
 		LLHTTPNode::ResponsePtr response,
 		const LLSD& context) const
 	{
-		std::string name = context["request"]["wildcard"]["option-name"];
+		std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
 		response->result(LLApp::instance()->getOption(name));
 	}
 };
diff --git a/indra/llmessage/llsdhttpserver.cpp b/indra/llmessage/llsdhttpserver.cpp
index 5c8fc7b2bb..8ac6b3cb12 100644
--- a/indra/llmessage/llsdhttpserver.cpp
+++ b/indra/llmessage/llsdhttpserver.cpp
@@ -109,7 +109,7 @@ public:
 
     virtual void get(ResponsePtr response, const LLSD& context) const
 	{
-		const LLSD& remainder = context["request"]["remainder"];
+		const LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
 		
 		if (remainder.size() > 0)
 		{
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index 02891d4f32..dfd3b7e1d0 100644
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -251,7 +251,7 @@ public:
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_LLSD);
+		http->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_LLSD);
 		if(mURL.empty())
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
@@ -301,7 +301,7 @@ public:
 		LLIOPipe::ptr_t service(new Client);
 		chain.push_back(service);		
 		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+		http->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
 		if(mURL.empty())
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
index 8248b184e9..a67ba35879 100644
--- a/indra/llmessage/lltrustedmessageservice.cpp
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -42,9 +42,9 @@ void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
 								   const LLSD& context,
 								   const LLSD& input) const
 {
-	std::string name = context["request"]["wildcard"]["message-name"];
-	std::string senderIP = context["request"]["remote-host"];
-	std::string senderPort = context["request"]["headers"]
+	std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
+	std::string senderIP = context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST];
+	std::string senderPort = context[CONTEXT_REQUEST][CONTEXT_HEADERS]
 		["x-secondlife-udp-listen-port"];
 
 	LLSD message_data;
diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h
index 688937ac2c..12a37bb535 100644
--- a/indra/llmessage/lltrustedmessageservice.h
+++ b/indra/llmessage/lltrustedmessageservice.h
@@ -30,6 +30,10 @@
 #include "linden_common.h"
 #include "llhttpnode.h"
 
+// These are defined in lliosocket.h/lliosocket.cpp  
+extern const std::string CONTEXT_REMOTE_HOST;
+extern const std::string CONTEXT_REMOTE_PORT;
+
 class LLSD;
 
 class LLTrustedMessageService
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index f354f5ab5d..49cfef2771 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -47,11 +47,12 @@
 const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
 const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
 
+// These are defined in llhttpnode.h/llhttpnode.cpp
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_RESPONSE;
 
 static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
 
-
-
 /**
  * class LLURLRequestDetail
  */
@@ -479,7 +480,7 @@ bool LLURLRequest::configure()
 	case HTTP_PUT:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
-		addHeader(HTTP_HEADER_EXPECT);
+		addHeader(HTTP_OUT_HEADER_EXPECT);
 
 		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
 		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
@@ -489,11 +490,11 @@ bool LLURLRequest::configure()
 	case HTTP_POST:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
-		addHeader(HTTP_HEADER_EXPECT);
+		addHeader(HTTP_OUT_HEADER_EXPECT);
 
 		// Disable the content type http header.
 		// *FIX: what should it be?
-		addHeader(HTTP_HEADER_CONTENT_TYPE);
+		addHeader(HTTP_OUT_HEADER_CONTENT_TYPE);
 
 		// Set the handle for an http post
 		mDetail->mCurlRequest->setPost(NULL, bytes);
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index f334c92cc3..f3d32f5419 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -42,9 +42,10 @@
 #include "llcurl.h"
 
 
-extern const std::string CONTEXT_REQUEST;
+/**
+ * External constants
+ */
 extern const std::string CONTEXT_DEST_URI_SD_LABEL;
-extern const std::string CONTEXT_RESPONSE;
 extern const std::string CONTEXT_TRANSFERED_BYTES;
 
 class LLURLRequestDetail;
@@ -352,11 +353,4 @@ protected:
 	EStatus mRequestStatus;
 };
 
-
-
-/**
- * External constants
- */
-extern const std::string CONTEXT_DEST_URI_SD_LABEL;
-
 #endif // LL_LLURLREQUEST_H
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 78b259c3f1..5a63da628d 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -152,7 +152,7 @@ class LLMessageHandlerBridge : public LLHTTPNode
 void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response, 
 							const LLSD& context, const LLSD& input) const
 {
-	std::string name = context["request"]["wildcard"]["message-name"];
+	std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
 	char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
 	
 	lldebugs << "Setting mLastSender " << input["sender"].asString() << llendl;
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index bdc48ce53d..43fac83c57 100644
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -40,8 +40,6 @@
 #include "llproxy.h"
 #include "llpumpio.h"
 
-#include "llsdhttpserver.h"
-#include "lliohttpserver.h"
 #include "lliosocket.h"
 #include "stringize.h"
 
diff --git a/indra/llmessage/tests/llhttpnode_stub.cpp b/indra/llmessage/tests/llhttpnode_stub.cpp
new file mode 100644
index 0000000000..cc2108fed5
--- /dev/null
+++ b/indra/llmessage/tests/llhttpnode_stub.cpp
@@ -0,0 +1,112 @@
+/** 
+ * @file llhttpnode_stub.cpp
+ * @brief STUB Implementation of classes for generic HTTP/LSL/REST handling.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ * 
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpnode.h"
+
+const std::string CONTEXT_VERB("verb");
+const std::string CONTEXT_REQUEST("request");
+const std::string CONTEXT_WILDCARD("wildcard");
+const std::string CONTEXT_PATH("path");
+const std::string CONTEXT_QUERY_STRING("query-string");
+const std::string CONTEXT_REMOTE_HOST("remote-host");
+const std::string CONTEXT_REMOTE_PORT("remote-port");
+const std::string CONTEXT_HEADERS("headers");
+const std::string CONTEXT_RESPONSE("response");
+
+/**
+ * LLHTTPNode
+ */
+class LLHTTPNode::Impl
+{
+    // dummy
+};
+
+LLHTTPNode::LLHTTPNode(): impl(*new Impl) {}
+LLHTTPNode::~LLHTTPNode() {}
+LLSD LLHTTPNode::simpleGet() const { return LLSD(); }
+LLSD LLHTTPNode::simplePut(const LLSD& input) const { return LLSD(); }
+LLSD LLHTTPNode::simplePost(const LLSD& input) const { return LLSD(); }
+LLSD LLHTTPNode::simpleDel(const LLSD&) const { return LLSD(); }
+void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) const {}
+void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const {}
+void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const {}
+void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) const {}
+void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const {}
+LLHTTPNode* LLHTTPNode::getChild(const std::string& name, LLSD& context) const { return NULL; }
+bool LLHTTPNode::handles(const LLSD& remainder, LLSD& context) const { return false; }
+bool LLHTTPNode::validate(const std::string& name, LLSD& context) const { return false; }
+const LLHTTPNode* LLHTTPNode::traverse(const std::string& path, LLSD& context) const { return NULL; }
+void LLHTTPNode::addNode(const std::string& path, LLHTTPNode* nodeToAdd) { }
+LLSD LLHTTPNode::allNodePaths() const { return LLSD(); }
+const LLHTTPNode* LLHTTPNode::rootNode() const { return NULL; }
+const LLHTTPNode* LLHTTPNode::findNode(const std::string& name) const { return NULL; }
+
+LLHTTPNode::Response::~Response(){}
+void LLHTTPNode::Response::notFound(const std::string& message)
+{
+	status(404, message);
+}
+void LLHTTPNode::Response::notFound()
+{
+	status(404, "Not Found");
+}
+void LLHTTPNode::Response::methodNotAllowed()
+{
+	status(405, "Method Not Allowed");
+}
+void LLHTTPNode::Response::statusUnknownError(S32 code)
+{
+	status(code, "Unknown Error");
+}
+
+void LLHTTPNode::Response::status(S32 code, const std::string& message)
+{
+}
+
+void LLHTTPNode::Response::addHeader(const std::string& name,const std::string& value) 
+{
+	mHeaders[name] = value;
+}
+void LLHTTPNode::describe(Description& desc) const { }
+
+
+const LLChainIOFactory* LLHTTPNode::getProtocolHandler() const { return NULL; }
+
+
+LLHTTPRegistrar::NodeFactory::~NodeFactory() { }
+
+void LLHTTPRegistrar::registerFactory(
+    const std::string& path, NodeFactory& factory) {}
+void LLHTTPRegistrar::buildAllServices(LLHTTPNode& root) {}
+
+
diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp
deleted file mode 100644
index f8bf03bbcb..0000000000
--- a/indra/llmessage/tests/llmime_test.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/** 
- * @file llmime_test.cpp
- * @author Phoenix
- * @date 2006-12-24
- * @brief BRIEF_DESC of llmime_test.cpp
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llsdserialize.h"
-#include "llhttpconstants.cpp"
-
-#include "../llmime.h"
-
-#include "../test/lltut.h"
-
-namespace tut
-{
-	struct mime_index
-	{
-	};
-	typedef test_group<mime_index> mime_index_t;
-	typedef mime_index_t::object mime_index_object_t;
-	tut::mime_index_t tut_mime_index("LLMime");
-
-	template<> template<>
-	void mime_index_object_t::test<1>()
-	{
-		LLMimeIndex mime;
-		ensure("no headers", mime.headers().isUndefined());
-		ensure_equals("invalid offset", mime.offset(), -1);
-		ensure_equals("invalid content length", mime.contentLength(), -1);
-		ensure("no content type", mime.contentType().empty());
-		ensure("not multipart", !mime.isMultipart());
-		ensure_equals("no attachments", mime.subPartCount(), 0);
-	}
-
-	template<> template<>
-	void mime_index_object_t::test<2>()
-	{
-		const S32 CONTENT_LENGTH = 6000;
-		const S32 CONTENT_OFFSET = 100;
-		const std::string CONTENT_TYPE = std::string("image/j2c");
-		LLSD headers;
-		headers["Content-Length"] = CONTENT_LENGTH;
-		headers["Content-Type"] = CONTENT_TYPE;
-		LLMimeIndex mime(headers, CONTENT_OFFSET);
-		ensure("headers are map", mime.headers().isMap());
-		ensure_equals("offset", mime.offset(), CONTENT_OFFSET);
-		ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH);
-		ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE);
-		ensure("not multipart", !mime.isMultipart());
-		ensure_equals("no attachments", mime.subPartCount(), 0);
-	}
-
-	template<> template<>
-	void mime_index_object_t::test<3>()
-	{
-		const S32 MULTI_CONTENT_LENGTH = 8000;
-		const S32 MULTI_CONTENT_OFFSET = 100;
-		const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
-		LLSD headers;
-		headers["Content-Length"] = MULTI_CONTENT_LENGTH;
-		headers["Content-Type"] = MULTI_CONTENT_TYPE;
-		LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
-		llinfos << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
-			<< llendl;
-
-
-		const S32 META_CONTENT_LENGTH = 700;
-		const S32 META_CONTENT_OFFSET = 69;
-		const std::string META_CONTENT_TYPE = std::string(
-			"text/llsd+xml");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = META_CONTENT_LENGTH;
-		headers["Content-Type"] = META_CONTENT_TYPE;
-		LLMimeIndex meta(headers, META_CONTENT_OFFSET);
-		mime.attachSubPart(meta);
-
-		const S32 IMAGE_CONTENT_LENGTH = 6000;
-		const S32 IMAGE_CONTENT_OFFSET = 200;
-		const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
-		headers["Content-Type"] = IMAGE_CONTENT_TYPE;
-		LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
-		mime.attachSubPart(image);
-
-		// make sure we have a valid multi-part
-		ensure("is multipart", mime.isMultipart());
-		ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
-		ensure_equals(
-			"multi content length",
-			mime.contentLength(),
-			MULTI_CONTENT_LENGTH);
-		ensure_equals("two attachments", mime.subPartCount(), 2);
-
-		// make sure ranged gets do the right thing with out of bounds
-		// sub-parts.
-		LLMimeIndex invalid_child(mime.subPart(-1));
-		ensure("no headers", invalid_child.headers().isUndefined());
-		ensure_equals("invalid offset", invalid_child.offset(), -1);
-		ensure_equals(
-			"invalid content length", invalid_child.contentLength(), -1);
-		ensure("no content type", invalid_child.contentType().empty());
-		ensure("not multipart", !invalid_child.isMultipart());
-		ensure_equals("no attachments", invalid_child.subPartCount(), 0);
-
-		invalid_child = mime.subPart(2);
-		ensure("no headers", invalid_child.headers().isUndefined());
-		ensure_equals("invalid offset", invalid_child.offset(), -1);
-		ensure_equals(
-			"invalid content length", invalid_child.contentLength(), -1);
-		ensure("no content type", invalid_child.contentType().empty());
-		ensure("not multipart", !invalid_child.isMultipart());
-		ensure_equals("no attachments", invalid_child.subPartCount(), 0);
-	}
-
-	template<> template<>
-	void mime_index_object_t::test<4>()
-	{
-		const S32 MULTI_CONTENT_LENGTH = 8000;
-		const S32 MULTI_CONTENT_OFFSET = 100;
-		const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
-		LLSD headers;
-		headers["Content-Length"] = MULTI_CONTENT_LENGTH;
-		headers["Content-Type"] = MULTI_CONTENT_TYPE;
-		LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
-
-		const S32 META_CONTENT_LENGTH = 700;
-		const S32 META_CONTENT_OFFSET = 69;
-		const std::string META_CONTENT_TYPE = std::string(
-			"application/llsd+xml");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = META_CONTENT_LENGTH;
-		headers["Content-Type"] = META_CONTENT_TYPE;
-		LLMimeIndex meta(headers, META_CONTENT_OFFSET);
-		mime.attachSubPart(meta);
-
-		const S32 IMAGE_CONTENT_LENGTH = 6000;
-		const S32 IMAGE_CONTENT_OFFSET = 200;
-		const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
-		headers = LLSD::emptyMap();
-		headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
-		headers["Content-Type"] = IMAGE_CONTENT_TYPE;
-		LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
-		mime.attachSubPart(image);
-
-		// check what we have
-		ensure("is multipart", mime.isMultipart());
-		ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
-		ensure_equals(
-			"multi content length",
-			mime.contentLength(),
-			MULTI_CONTENT_LENGTH);
-		ensure_equals("two attachments", mime.subPartCount(), 2);
-
-		LLMimeIndex actual_meta = mime.subPart(0);
-		ensure_equals(
-			"meta type", actual_meta.contentType(), META_CONTENT_TYPE);
-		ensure_equals(
-			"meta offset", actual_meta.offset(), META_CONTENT_OFFSET);
-		ensure_equals(
-			"meta content length",
-			actual_meta.contentLength(),
-			META_CONTENT_LENGTH);
-
-		LLMimeIndex actual_image = mime.subPart(1);
-		ensure_equals(
-			"image type", actual_image.contentType(), IMAGE_CONTENT_TYPE);
-		ensure_equals(
-			"image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET);
-		ensure_equals(
-			"image content length",
-			actual_image.contentLength(),
-			IMAGE_CONTENT_LENGTH);
-	}
-
-/*
-	template<> template<>
-	void mime_index_object_t::test<5>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<6>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<7>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<8>()
-	{
-	}
-	template<> template<>
-	void mime_index_object_t::test<>()
-	{
-	}
-*/
-}
-
-
-namespace tut
-{
-	struct mime_parse
-	{
-	};
-	typedef test_group<mime_parse> mime_parse_t;
-	typedef mime_parse_t::object mime_parse_object_t;
-	tut::mime_parse_t tut_mime_parse("LLMimeParse");
-
-	template<> template<>
-	void mime_parse_object_t::test<1>()
-	{
-		// parse one mime object
-		const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure_equals("content type", mime.contentType(), "text/plain");
-		ensure_equals("content length", mime.contentLength(), 200);
-		ensure_equals("offset", mime.offset(), 49);
- 	}
-
-	template<> template<>
-	void mime_parse_object_t::test<2>()
-	{
-		// make sure we only parse one.
-		const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("not multipart.", !mime.isMultipart());
-		ensure_equals("content type", mime.contentType(), "text/plain");
-		ensure_equals("content length", mime.contentLength(), 200);
-		ensure_equals("offset", mime.offset(), 49);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<3>()
-	{
-		// test multi-part and lack of content length for some of it.
-		/*
-Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
-		 */
-		const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 150);
-		ensure_equals("data offset for multipart", mime.offset(), 74);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length not known.",
-			mime_plain.contentLength(),
-			-1);
-		ensure_equals("first part offset", mime_plain.offset(), 113);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-		ensure_equals("second part offset", mime_xml.offset(), 198);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<4>()
-	{
-		// test multi-part, unquoted separator, and premature eof conditions
-		/*
-Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn		 */
-		const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 220);
-		ensure_equals("data offset for multipart", mime.offset(), 72);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length",
-			mime_plain.contentLength(),
-			55);
-		ensure_equals("first part offset", mime_plain.offset(), 131);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-		ensure_equals("second part offset", mime_xml.offset(), 262);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<5>()
-	{
-		// test multi-part with multiple params
-		const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 220);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length",
-			mime_plain.contentLength(),
-			55);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-	}
-
-	template<> template<>
-	void mime_parse_object_t::test<6>()
-	{
-		// test multi-part with no specified boundary and eof
-/*
-Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
-*/
-		const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
-		std::stringstream istr;
-		istr.str(SERIALIZED_MIME);
-		LLMimeIndex mime;
-		LLMimeParser parser;
-		bool ok = parser.parseIndex(istr, mime);
-		ensure("Parse successful.", ok);
-		ensure("is multipart.", mime.isMultipart());
-		ensure_equals("sub-part count", mime.subPartCount(), 2);
-		ensure_equals("content length", mime.contentLength(), 500);
-		ensure_equals("data offset for multipart", mime.offset(), 56);
-
-		LLMimeIndex mime_plain(mime.subPart(0));
-		ensure_equals(
-			"first part type",
-			mime_plain.contentType(),
-			"text/plain");
-		ensure_equals(
-			"first part content length",
-			mime_plain.contentLength(),
-			55);
-		ensure_equals("first part offset", mime_plain.offset(), 108);
-
-		LLMimeIndex mime_xml(mime.subPart(1));
-		ensure_equals(
-			"second part type",
-			mime_xml.contentType(),
-			"text/xml; charset=UTF-8");
-		ensure_equals(
-			"second part content length",
-			mime_xml.contentLength(),
-			22);
-		ensure_equals("second part offset", mime_xml.offset(), 232);
-	}
-
-/*
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-	template<> template<>
-	void mime_parse_object_t::test<>()
-	{
-	}
-*/
-}
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
index b287a29841..55748ad27e 100644
--- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -32,6 +32,7 @@
 
 #include "message.h"
 #include "llmessageconfig.h"
+#include "llhttpnode_stub.cpp"
 
 LLMessageSystem* gMessageSystem = NULL;
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 43439bac5d..0b85f438bd 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3008,8 +3008,8 @@ public:
 #if 0
 		// *TODO: Honor server Retry-After header.
 		// Status 503 may ask us to wait for a certain amount of time before retrying.
-		if (!headers.has(HTTP_HEADER_RETRY_AFTER)
-			|| !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait))
+		if (!headers.has(HTTP_IN_HEADER_RETRY_AFTER)
+			|| !getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait))
 #endif
 		{
 			seconds_to_wait = mDelay;
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 63888ace11..801a24f472 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -474,8 +474,7 @@ void LLServerReleaseNotesURLFetcher::httpCompleted()
 	LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about");
 	if (floater_about)
 	{
-		const bool check_lower = true;
-		const std::string& location = getResponseHeader(HTTP_HEADER_LOCATION, check_lower);
+		const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
 		if (location.empty())
 		{
 			LL_WARNS("ServerReleaseNotes") << "Missing Location header "
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index 0751c830d5..e26f1e9ea5 100644
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -59,8 +59,7 @@ public:
 private:
 	/* virtual */ void httpCompleted()
 	{
-		const bool check_lower = true;
-		const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower);
+		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
 		std::string::size_type idx1 = media_type.find_first_of(";");
 		std::string mime_type = media_type.substr(0, idx1);
 
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index bea1d62b93..28e1df725a 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -167,8 +167,7 @@ namespace LLMarketplaceImport
 	protected:
 		/* virtual */ void httpCompleted()
 		{
-			const bool check_lower = true;
-			const std::string& set_cookie_string = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower);
+			const std::string& set_cookie_string = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
 			
 			if (!set_cookie_string.empty())
 			{
@@ -278,10 +277,11 @@ namespace LLMarketplaceImport
 
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie;
-		headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
-		headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
+		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
+		// *TODO: Why are we setting Content-Type for a GET request?
+		headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+		headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
 		
 		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 		{
@@ -311,12 +311,11 @@ namespace LLMarketplaceImport
 		
 		// Make the headers for the post
 		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_HEADER_CONNECTION] = "Keep-Alive";
-		headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie;
-		// *TODO: Should this be 'application/llsd+xml'?
-		headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
-		headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
+		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_OUT_HEADER_CONNECTION] = "Keep-Alive";
+		headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
+		headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
+		headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
 		
 		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
 		{
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index bc1aa087e5..691be13610 100644
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -579,8 +579,8 @@ void LLMediaDataClient::Responder::httpFailure()
 		F32 retry_timeout;
 #if 0
 		// *TODO: Honor server Retry-After header.
-		if (!hasResponseHeader(HTTP_HEADER_RETRY_AFTER)
-			|| !getSecondsUntilRetryAfter(getResponseHeader(HTTP_HEADER_RETRY_AFTER), retry_timeout))
+		if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER)
+			|| !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout))
 #endif
 		{
 			retry_timeout = mRequest->getRetryTimerDelay();
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 1469dbc346..524467a37e 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -808,7 +808,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
+			headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -890,7 +890,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
+			headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -971,7 +971,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
+			headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
@@ -1052,7 +1052,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c
 	//either cache entry doesn't exist or is corrupt, request header from simulator	
 	bool retval = true ;
 	std::vector<std::string> headers;
-	headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
+	headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 	std::string http_url = constructUrl(mesh_params.getSculptID());
 	if (!http_url.empty())
@@ -1127,7 +1127,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 
 			//reading from VFS failed for whatever reason, fetch from sim
 			std::vector<std::string> headers;
-			headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
+			headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM);
 
 			std::string http_url = constructUrl(mesh_id);
 			if (!http_url.empty())
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 9e9efa7ebd..cc6dc64626 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2408,9 +2408,9 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	mHttpOptions = new LLCore::HttpOptions;
 	mHttpHeaders = new LLCore::HttpHeaders;
 	// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
-	mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
+	mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
 	mHttpMetricsHeaders = new LLCore::HttpHeaders;
-	mHttpMetricsHeaders->mHeaders.push_back(HTTP_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML);
+	mHttpMetricsHeaders->mHeaders.push_back(HTTP_OUT_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML);
 	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault();
 }
 
@@ -4043,7 +4043,7 @@ void LLTextureFetchDebugger::init()
 	{
 		mHttpHeaders = new LLCore::HttpHeaders;
 		// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
-		mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
+		mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
 	}
 }
 
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index b9840fa3e4..ae934d9f5a 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -394,8 +394,8 @@ void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr
 			LLVersionInfo::getPatch(),
 			LLVersionInfo::getBuild());
 
-		sHeader.insert(HTTP_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
-		sHeader.insert(HTTP_HEADER_USER_AGENT, user_agent);
+		sHeader.insert(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+		sHeader.insert(HTTP_OUT_HEADER_USER_AGENT, user_agent);
 	}
 
 	LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp
index 5d94756da3..3f836efdd3 100644
--- a/indra/newview/llviewerdisplayname.cpp
+++ b/indra/newview/llviewerdisplayname.cpp
@@ -86,7 +86,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl
 	// People API can return localized error messages.  Indicate our
 	// language preference via header.
 	LLSD headers;
-	headers[HTTP_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage();
+	headers[HTTP_OUT_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage();
 
 	// People API requires both the old and new value to change a variable.
 	// Our display name will be in cache before the viewer's UI is available
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 8c29a03176..2cec808f19 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -185,8 +185,7 @@ private:
 			llwarns << dumpResponse()
 					<< " [headers:" << getResponseHeaders() << "]" << llendl;
 		}
-		const bool check_lower = true;
-		const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower);
+		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
 		std::string::size_type idx1 = media_type.find_first_of(";");
 		std::string mime_type = media_type.substr(0, idx1);
 
@@ -289,8 +288,7 @@ public:
 		// We don't care about the content of the response, only the Set-Cookie header.
 		LL_DEBUGS("MediaAuth") << dumpResponse() 
 				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-		const bool check_lower = true;
-		const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower);
+		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
 		
 		// *TODO: What about bad status codes?  Does this destroy previous cookies?
 		LLViewerMedia::openIDCookieResponse(cookie);
@@ -321,12 +319,10 @@ public:
 
 		LLSD stripped_content = getResponseHeaders();
 		// *TODO: Check that this works.
-		stripped_content.erase(HTTP_HEADER_SET_COOKIE);
-		stripped_content.erase("set-cookie");
+		stripped_content.erase(HTTP_IN_HEADER_SET_COOKIE);
 		LL_WARNS("MediaAuth") << stripped_content << LL_ENDL;
 
-		const bool check_lower = true;
-		const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower);
+		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
 		LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
 
 		// *TODO: What about bad status codes?  Does this destroy previous cookies?
@@ -1383,12 +1379,12 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
 LLSD LLViewerMedia::getHeaders()
 {
 	LLSD headers = LLSD::emptyMap();
-	headers[HTTP_HEADER_ACCEPT] = "*/*";
+	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
 	// *TODO: Should this be 'application/llsd+xml' ?
 	// *TODO: Should this even be set at all?   This header is only not overridden in 'GET' methods.
-	headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
-	headers[HTTP_HEADER_COOKIE] = sOpenIDCookie;
-	headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent();
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
+	headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie;
+	headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent();
 
 	return headers;
 }
@@ -1429,9 +1425,9 @@ void LLViewerMedia::setOpenIDCookie()
 
 		// Do a web profile get so we can store the cookie 
 		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_HEADER_COOKIE] = sOpenIDCookie;
-		headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent();
+		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
+		headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie;
+		headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent();
 
 		std::string profile_url = getProfileURL("");
 		LLURL raw_profile_url( profile_url.c_str() );
@@ -1461,9 +1457,9 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string
 
 	LLSD headers = LLSD::emptyMap();
 	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
-	headers[HTTP_HEADER_ACCEPT] = "*/*";
+	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
 	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
-	headers[HTTP_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded";
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded";
 
 	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
 	size_t size = openid_token.size();
@@ -2631,9 +2627,9 @@ void LLViewerMediaImpl::navigateInternal()
 			//    Accept: application/llsd+xml
 			// which is really not what we want.
 			LLSD headers = LLSD::emptyMap();
-			headers[HTTP_HEADER_ACCEPT] = "*/*";
+			headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
 			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
-			headers[HTTP_HEADER_COOKIE] = "";
+			headers[HTTP_OUT_HEADER_COOKIE] = "";
 			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
 		}
 		else if("data" == scheme || "file" == scheme || "about" == scheme)
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index ee78ba20cb..567138e160 100644
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -167,9 +167,8 @@ public:
 		if (getStatus() == HTTP_SEE_OTHER)
 		{
 			LLSD headers = LLViewerMedia::getHeaders();
-			headers[HTTP_HEADER_COOKIE] = LLWebProfile::getAuthCookie();
-			const bool check_lower=true;
-			const std::string& redir_url = getResponseHeader(HTTP_HEADER_LOCATION, check_lower);
+			headers[HTTP_OUT_HEADER_COOKIE] = LLWebProfile::getAuthCookie();
+			const std::string& redir_url = getResponseHeader(HTTP_IN_HEADER_LOCATION);
 			if (redir_url.empty())
 			{
 				llwarns << "Received empty redirection URL " << dumpResponse() << llendl;
@@ -207,7 +206,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
 
 	LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl;
 	LLSD headers = LLViewerMedia::getHeaders();
-	headers[HTTP_HEADER_COOKIE] = getAuthCookie();
+	headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie();
 	LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers);
 }
 
@@ -231,8 +230,8 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
 	const std::string boundary = "----------------------------0123abcdefab";
 
 	LLSD headers = LLViewerMedia::getHeaders();
-	headers[HTTP_HEADER_COOKIE] = getAuthCookie();
-	headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary;
+	headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie();
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary;
 
 	std::ostringstream body;
 
diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp
index ba536ac582..7036162014 100644
--- a/indra/newview/llwebsharing.cpp
+++ b/indra/newview/llwebsharing.cpp
@@ -55,25 +55,47 @@ public:
 							  const LLIOPipe::buffer_ptr_t& buffer)
 	{
 		LLBufferStream istr(channels, buffer.get());
+		// *TODO: LLSD notation is not actually JSON.
 		LLPointer<LLSDParser> parser = new LLSDNotationParser();
 
-		if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
+		std::string debug_body("(empty)");
+		bool parsed=true;
+		if (EOF == istr.peek())
 		{
-			if (HTTP_CONTENT_JSON == getResponseHeader(HTTP_HEADER_CONTENT_TYPE))
+			parsed=false;
+		}
+		// Try to parse body as llsd, no matter what 'content-type' says.
+		else if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
+		{
+			parsed=false;
+			char body[1025]; 
+			body[1024] = '\0';
+			istr.seekg(0, std::ios::beg);
+			istr.get(body,1024);
+			if (strlen(body) > 0)
 			{
-				mStatus = HTTP_INTERNAL_ERROR;
-				mReason = "Failed to deserialize LLSD from JSON response.";
-				char body[1025]; 
-				body[1024] = '\0';
-				istr.seekg(0, std::ios::beg);
-				istr.get(body,1024);
-				if (strlen(body) > 0)
-				{
-					mContent["body"] = body;
-				}
+				mContent = body;
+				debug_body = body;
 			}
 		}
 
+		// Only emit a warning if we failed to parse when 'content-type' == 'application/json'
+		if (!parsed && (HTTP_CONTENT_JSON == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
+		{
+			llwarns << "Failed to deserialize LLSD from JSON response. " << getURL()
+				<< " [status:" << mStatus << "] " 
+				<< "(" << mReason << ") body: " << debug_body << llendl;
+		}
+
+		if (!parsed)
+		{
+			// *TODO: This isn't necessarily the server's fault.  Using a 5xx code
+			// isn't really appropriate here.
+			// Also, this hides the actual status returned by the server....
+			mStatus = HTTP_INTERNAL_ERROR;
+			mReason = "Failed to deserialize LLSD from JSON response.";
+		}
+
 		httpCompleted();
 	}
 };
@@ -132,11 +154,10 @@ private:
 
 	virtual void httpSuccess()
 	{
-		const bool check_lower=true;
-		if (hasResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower))
+		if (hasResponseHeader(HTTP_IN_HEADER_SET_COOKIE))
 		{
 			// OpenID request succeeded and returned a session cookie.
-			LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower));
+			LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_IN_HEADER_SET_COOKIE));
 		}
 	}
 };
@@ -299,7 +320,7 @@ void LLWebSharing::sendConfigRequest()
 	LL_DEBUGS("WebSharing") << "Requesting Snapshot Sharing config data from: " << config_url << LL_ENDL;
 
 	LLSD headers = LLSD::emptyMap();
-	headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
+	headers[HTTP_OUT_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
 
 	LLHTTPClient::get(config_url, new LLWebSharingConfigResponder(), headers);
 }
@@ -310,8 +331,8 @@ void LLWebSharing::sendOpenIDAuthRequest()
 	LL_DEBUGS("WebSharing") << "Starting OpenID Auth: " << auth_url << LL_ENDL;
 
 	LLSD headers = LLSD::emptyMap();
-	headers[HTTP_HEADER_COOKIE] = mOpenIDCookie;
-	headers[HTTP_HEADER_ACCEPT] = "*/*";
+	headers[HTTP_OUT_HEADER_COOKIE] = mOpenIDCookie;
+	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
 
 	// Send request, successful login will trigger fetching a security token.
 	LLHTTPClient::get(auth_url, new LLWebSharingOpenIDAuthResponder(), headers);
@@ -337,10 +358,10 @@ void LLWebSharing::sendSecurityTokenRequest()
 	LL_DEBUGS("WebSharing") << "Fetching security token from: " << token_url << LL_ENDL;
 
 	LLSD headers = LLSD::emptyMap();
-	headers[HTTP_HEADER_COOKIE] = mSessionCookie;
+	headers[HTTP_OUT_HEADER_COOKIE] = mSessionCookie;
 
-	headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
-	headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON;
+	headers[HTTP_OUT_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON;
 
 	std::ostringstream body;
 	body << "{ \"gadgets\": [{ \"url\":\""
@@ -366,10 +387,10 @@ void LLWebSharing::sendUploadRequest()
 	static const std::string BOUNDARY("------------abcdef012345xyZ");
 
 	LLSD headers = LLSD::emptyMap();
-	headers[HTTP_HEADER_COOKIE] = mSessionCookie;
+	headers[HTTP_OUT_HEADER_COOKIE] = mSessionCookie;
 
-	headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
-	headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY;
+	headers[HTTP_OUT_HEADER_ACCEPT] = HTTP_CONTENT_JSON;
+	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY;
 
 	std::ostringstream body;
 	body << "--" << BOUNDARY << "\r\n"
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 604e08161e..7c5f8be1b5 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -331,7 +331,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	   This might help with bug #503 */
 	mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
 
-    mCurlRequest->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+    mCurlRequest->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
 
 	if (useGzip)
 	{
diff --git a/indra/test/llhttpnode_tut.cpp b/indra/test/llhttpnode_tut.cpp
index d580263103..c528a34129 100644
--- a/indra/test/llhttpnode_tut.cpp
+++ b/indra/test/llhttpnode_tut.cpp
@@ -44,7 +44,7 @@ namespace tut
 			std::ostringstream pathOutput;
 			bool addSlash = false;
 			
-			LLSD& remainder = mContext["request"]["remainder"];
+			LLSD& remainder = mContext[CONTEXT_REQUEST]["remainder"];
 			for (LLSD::array_const_iterator i = remainder.beginArray();
 				i != remainder.endArray();
 				++i)
diff --git a/indra/test/mock_http_client.cpp b/indra/test/mock_http_client.cpp
index d7ef407d52..e72902bfc2 100644
--- a/indra/test/mock_http_client.cpp
+++ b/indra/test/mock_http_client.cpp
@@ -25,8 +25,7 @@
  */
 
 #include "linden_common.h"
-#include "llsdhttpserver.h"
-#include "lliohttpserver.h"
+#include "llhttpnode.h"
 
 namespace tut
 {
-- 
cgit v1.2.3


From 0a6a5f63b45bf3d97c7926b8d415b0b3885f64a1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 5 Apr 2013 13:44:33 -0400
Subject: SH-4061 WIP - spelling fix, allow un-set of missing asset flag for
 textures

---
 indra/newview/llviewertexture.cpp | 44 ++++++++++++++++++++++++---------------
 indra/newview/llviewertexture.h   |  2 +-
 indra/newview/llvoavatar.cpp      |  6 +++---
 indra/newview/llvoavatar.h        |  2 +-
 indra/newview/llvoavatarself.cpp  |  2 +-
 5 files changed, 33 insertions(+), 23 deletions(-)
 mode change 100644 => 100755 indra/newview/llviewertexture.cpp
 mode change 100644 => 100755 indra/newview/llviewertexture.h

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
old mode 100644
new mode 100755
index eb6c453e76..500a6c8869
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2005,29 +2005,39 @@ void LLViewerFetchedTexture::forceToDeleteRequest()
 	mDesiredDiscardLevel = getMaxDiscardLevel() + 1;
 }
 
-void LLViewerFetchedTexture::setIsMissingAsset()
+void LLViewerFetchedTexture::setIsMissingAsset(bool is_missing)
 {
-	if (mUrl.empty())
+	if (is_missing)
 	{
-		llwarns << mID << ": Marking image as missing" << llendl;
+		if (mUrl.empty())
+		{
+			llwarns << mID << ": Marking image as missing" << llendl;
+		}
+		else
+		{
+			// This may or may not be an error - it is normal to have no
+			// map tile on an empty region, but bad if we're failing on a
+			// server bake texture.
+			if (getFTType() != FTT_MAP_TILE)
+			{
+				llwarns << mUrl << ": Marking image as missing" << llendl;
+			}
+		}
+		if (mHasFetcher)
+		{
+			LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+			mHasFetcher = FALSE;
+			mIsFetching = FALSE;
+			mLastPacketTimer.reset();
+			mFetchState = 0;
+			mFetchPriority = 0;
+		}
 	}
 	else
 	{
-		// This may or may not be an error - it is normal to have no
-		// map tile on an empty region, but bad if we're failing on a
-		// server bake texture.
-		llwarns << mUrl << ": Marking image as missing" << llendl;
-	}
-	if (mHasFetcher)
-	{
-		LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
-		mHasFetcher = FALSE;
-		mIsFetching = FALSE;
-		mLastPacketTimer.reset();
-		mFetchState = 0;
-		mFetchPriority = 0;
+		llinfos << mID << ": un-flagging missing asset" << llendl;
 	}
-	mIsMissingAsset = TRUE;
+	mIsMissingAsset = is_missing;
 }
 
 void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
old mode 100644
new mode 100755
index f2e1a90713..1f2079104f
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -338,7 +338,7 @@ public:
 	// more data.
 	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
-	void setIsMissingAsset();
+	void setIsMissingAsset(bool is_missing = true);
 	/*virtual*/ BOOL isMissingAsset()	const		{ return mIsMissingAsset; }
 
 	// returns dimensions of original image for local files (before power of two scaling)
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 5695fc04b9..a71bb93ba2 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -4408,7 +4408,7 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture
 }
 
 const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames.	
-const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = S32_MAX ; //frames
+const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = S32_MAX ; //frames
 void LLVOAvatar::checkTextureLoading()
 {
 	static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds
@@ -4471,11 +4471,11 @@ const F32  ADDITIONAL_PRI = 0.5f;
 void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
 {
 	//Note:
-	//if this function is not called for the last MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL frames, 
+	//if this function is not called for the last MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL frames, 
 	//the texture pipeline will stop fetching this texture.
 
 	imagep->resetTextureStats();
-	imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL);
+	imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
 	imagep->resetMaxVirtualSizeResetCounter() ;
 
 	mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 85f6f25009..98e8491cb1 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -991,7 +991,7 @@ protected: // Shared with LLVOAvatarSelf
 
 }; // LLVOAvatar
 extern const F32 SELF_ADDITIONAL_PRI;
-extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL;
+extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
 
 std::string get_sequential_numbered_file_name(const std::string& prefix,
 											  const std::string& suffix);
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 0404884245..5f9b4a59e7 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2587,7 +2587,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
 				imagep->setBoostLevel(getAvatarBoostLevel());
 				imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
 				imagep->resetTextureStats();
-				imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL);
+				imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
 				imagep->addTextureStats( desired_pixels / texel_area_ratio );
 				imagep->forceUpdateBindStats() ;
 				if (imagep->getDiscardLevel() < 0)
-- 
cgit v1.2.3


From e16435c37cb7410f3ea4596e30fd232ac558bc71 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 8 Apr 2013 13:26:05 -0400
Subject: SH-4061 WIP - added ability to un-set missing asset, do this in the
 case of FTT_SERVER_BAKE images. This is needed because 'missing' is not
 necessarily permanent for such images.

---
 indra/newview/llpaneloutfitsinventory.cpp | 3 ++-
 indra/newview/llviewertexture.cpp         | 6 +++++-
 indra/newview/llviewertexture.h           | 8 ++++----
 indra/newview/llvoavatar.cpp              | 4 ++++
 4 files changed, 15 insertions(+), 6 deletions(-)
 mode change 100644 => 100755 indra/newview/llpaneloutfitsinventory.cpp

diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
old mode 100644
new mode 100755
index f90236f6f2..d6c927ab58
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -76,7 +76,8 @@ BOOL LLPanelOutfitsInventory::postBuild()
 	// Fetch your outfits folder so that the links are in memory.
 	// ( This is only necessary if we want to show a warning if a user deletes an item that has a
 	// a link in an outfit, see "ConfirmItemDeleteHasLinks". )
-	const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTFIT, false);
+
+	const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
 	if (outfits_cat.notNull())
 	{
 		LLInventoryModelBackgroundFetch::instance().start(outfits_cat);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 500a6c8869..9cca8a244e 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2005,8 +2005,12 @@ void LLViewerFetchedTexture::forceToDeleteRequest()
 	mDesiredDiscardLevel = getMaxDiscardLevel() + 1;
 }
 
-void LLViewerFetchedTexture::setIsMissingAsset(bool is_missing)
+void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 {
+	if (is_missing == mIsMissingAsset)
+	{
+		return;
+	}
 	if (is_missing)
 	{
 		if (mUrl.empty())
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 1f2079104f..9465fe180b 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -120,7 +120,7 @@ public:
 	LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
 
 	virtual S8 getType() const;
-	virtual BOOL isMissingAsset()const ;
+	virtual BOOL isMissingAsset() const ;
 	virtual void dump();	// debug info to llinfos
 	
 	/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
@@ -338,8 +338,8 @@ public:
 	// more data.
 	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
-	void setIsMissingAsset(bool is_missing = true);
-	/*virtual*/ BOOL isMissingAsset()	const		{ return mIsMissingAsset; }
+	void setIsMissingAsset(BOOL is_missing = true);
+	/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
 
 	// returns dimensions of original image for local files (before power of two scaling)
 	// and returns 0 for all asset system images
@@ -449,7 +449,7 @@ protected:
 	bool mCanUseHTTP ;              //This texture can be fetched through http if true.
 
 	FTType mFTType; // What category of image is this - map tile, server bake, etc?
-	mutable S8 mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
+	mutable BOOL mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
 
 	typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
 	S8              mLoadedCallbackDesiredDiscardLevel;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index a71bb93ba2..58da77efbb 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1884,6 +1884,10 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 			LL_DEBUGS("Avatar") << avString() << "from URL " << url << llendl;
 			result = LLViewerTextureManager::getFetchedTextureFromUrl(
 				url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
+			if (result->isMissingAsset())
+			{
+				result->setIsMissingAsset(false);
+			}
 		}
 		else
 		{
-- 
cgit v1.2.3


From 985b7277e824c39275d9a06c6262b6f394b02133 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Mon, 8 Apr 2013 17:10:46 -0400
Subject: WIP SH-4035: confirmation when closing appearance window when changes
 present

---
 indra/newview/llfloatersidepanelcontainer.cpp      | 16 ++--
 indra/newview/llfloatersidepanelcontainer.h        |  2 +
 indra/newview/llinspectavatar.cpp                  |  5 +-
 indra/newview/llsidepanelappearance.cpp            | 88 +++++++++++++++++++++-
 indra/newview/llsidepanelappearance.h              | 16 +++-
 indra/newview/llspeakers.cpp                       |  5 +-
 .../newview/skins/default/xui/en/notifications.xml | 13 ++++
 7 files changed, 126 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index 5f9556a870..b1f9a18d6f 100644
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -67,15 +67,17 @@ void LLFloaterSidePanelContainer::onClickCloseBtn()
 		if (parent == this )
 		{
 			LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
-			if ( panel_appearance )
-			{
-				panel_appearance->getWearable()->onClose();
-				panel_appearance->showOutfitsInventoryPanel();
-			}
+			panel_appearance->onClose(this);			
 		}
 	}
-	
-	LLFloater::onClickCloseBtn();
+	else
+	{
+		LLFloater::onClickCloseBtn();
+	}
+}
+void LLFloaterSidePanelContainer::close()
+{
+		LLFloater::onClickCloseBtn();
 }
 
 LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params)
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index 491723471f..940673b643 100644
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -55,6 +55,8 @@ public:
 
 	LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params);
 
+	void close();
+
 	static void showPanel(const std::string& floater_name, const LLSD& key);
 
 	static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key);
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 0b3268eb54..6ff16742dd 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -292,10 +292,7 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
 	delete mPropertiesRequest;
 	mPropertiesRequest = NULL;
 }
-/*
-prep#
-	virtual void httpFailure()
-	*/
+
 
 void LLInspectAvatar::updateVolumeSlider()
 {
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 74fa5a87bb..53b5593ac9 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -48,6 +48,8 @@
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
 #include "llviewerwearable.h"
+#include "llnotificationsutil.h"
+#include "llfloatersidepanelcontainer.h"
 
 static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance");
 
@@ -70,13 +72,84 @@ private:
 	LLSidepanelAppearance *mPanel;
 };
 
+bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if ( option == 0 ) 
+	{		
+		gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE);		
+		LLAppearanceMgr::instance().setOutfitDirty( true );		
+		showOutfitsInventoryPanel();
+		LLAppearanceMgr::getInstance()->wearBaseOutfit();		
+		return true;
+	}
+	gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE);
+	return false;
+}
+
+bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if ( option == 0 ) 
+	{		
+		gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE);
+		mEditWearable->revertChanges();
+		LLAppearanceMgr::getInstance()->wearBaseOutfit();
+		mLLFloaterSidePanelContainer->close();
+		return true;
+	}
+	gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE);	
+	return false;
+}
+
+void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose()
+{
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	{
+		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
+		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
+	}
+	else
+	{
+		showOutfitsInventoryPanel();
+	}
+}
+
+void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
+{
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	{
+		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
+		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) );
+	}
+	else
+	{
+		showOutfitsInventoryPanel();
+	}
+}
+
+void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
+{
+	mLLFloaterSidePanelContainer = obj;
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	{
+		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
+		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
+	}
+	else
+	{
+		mLLFloaterSidePanelContainer->close();
+	}
+}
+
 LLSidepanelAppearance::LLSidepanelAppearance() :
 	LLPanel(),
 	mFilterSubString(LLStringUtil::null),
 	mFilterEditor(NULL),
 	mOutfitEdit(NULL),
 	mCurrOutfitPanel(NULL),
-	mOpened(false)
+	mOpened(false),
+	mSidePanelJustOpened(true)
 {
 	LLOutfitObserver& outfit_observer =  LLOutfitObserver::instance();
 	outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
@@ -85,6 +158,8 @@ LLSidepanelAppearance::LLSidepanelAppearance() :
 
 	gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true));
 	gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false));
+
+
 }
 
 LLSidepanelAppearance::~LLSidepanelAppearance()
@@ -119,8 +194,8 @@ BOOL LLSidepanelAppearance::postBuild()
 	{
 		LLButton* back_btn = mOutfitEdit->getChild<LLButton>("back_btn");
 		if (back_btn)
-		{
-			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this));
+		{			
+			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack, this));
 		}
 
 	}
@@ -144,6 +219,7 @@ BOOL LLSidepanelAppearance::postBuild()
 
 	setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2));
 
+
 	return TRUE;
 }
 
@@ -183,6 +259,12 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 
 void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 {
+	//handle leaving and subsequent user verification of discarding any unsaved data
+	if ( mSidePanelJustOpened )
+	{
+		mSidePanelJustOpened = false;
+	}
+
 	LLSD visibility;
 	visibility["visible"] = new_visibility.asBoolean();
 	visibility["reset_accordion"] = false;
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 762f557a80..85e7734567 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -38,9 +38,11 @@ class LLCurrentlyWornFetchObserver;
 class LLPanelEditWearable;
 class LLViewerWearable;
 class LLPanelOutfitsInventory;
+class LLFloaterSidePanelContainer;
 
 class LLSidepanelAppearance : public LLPanel
-{
+{	
+
 	LOG_CLASS(LLSidepanelAppearance);
 public:
 	LLSidepanelAppearance();
@@ -48,6 +50,8 @@ public:
 
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onOpen(const LLSD& key);	
+				void onClose(LLFloaterSidePanelContainer* obj);
+	void onClickCloseBtn();
 
 	void refreshCurrentOutfitName(const std::string& name = "");
 
@@ -65,6 +69,11 @@ public:
 	void updateScrollingPanelList();
 	void updateToVisibility( const LLSD& new_visibility );
 	LLPanelEditWearable* getWearable(){ return mEditWearable; }
+	bool callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response);
+	void onClickConfirmExitWithoutSaveViaBack();
+	bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response);
+	void onClickConfirmExitWithoutSaveViaClose();
+
 
 private:
 	void onFilterEdit(const std::string& search_string);
@@ -85,6 +94,7 @@ private:
 	LLButton*					mOpenOutfitBtn;
 	LLButton*					mEditAppearanceBtn;
 	LLButton*					mNewOutfitBtn;
+	
 	LLPanel*					mCurrOutfitPanel;
 
 	LLTextBox*					mCurrentLookName;
@@ -99,6 +109,10 @@ private:
 
 	// Gets set to true when we're opened for the first time.
 	bool mOpened;
+	// Set to true if sidepanel has just been opened
+	bool mSidePanelJustOpened;
+	LLFloaterSidePanelContainer* mLLFloaterSidePanelContainer;
+
 };
 
 #endif //LL_LLSIDEPANELAPPEARANCE_H
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 3c3c699d17..bf209df863 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -855,10 +855,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
 		}
 	}
 }
-/*prep#
-	virtual void httpFailure()
-		llwarns << dumpResponse() << llendl;
-		*/
+
 void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
 {
 	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 105bef7321..2170283af2 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10030,5 +10030,18 @@ Cannot create large prims that intersect other players.  Please re-try when othe
      name="okignore"
      yestext="OK"/>
   </notification>
+
+
+  <notification
+   icon="alertmodal.tga"
+   name="ConfirmExitWithoutSave"
+   type="alertmodal">
+    Closing this window will discard any changes you have made.
+    <tag>confirm</tag>
+    <usetemplate
+     name="okcancelbuttons"
+     notext="Cancel"
+     yestext="OK"/>
+  </notification>
   
 </notifications>
-- 
cgit v1.2.3


From 4bbcd26941c3be6b83214d0dc45c70f99e474dda Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 8 Apr 2013 18:16:58 -0400
Subject: SH-4061 FIX - texture fetch failures added retry logic and fault
 injection for testing

---
 indra/newview/app_settings/settings.xml | 11 +++++++++++
 indra/newview/lltexturefetch.cpp        | 28 ++++++++++++++++++++--------
 indra/newview/lltexturefetch.h          |  2 +-
 indra/newview/llviewertexture.cpp       | 29 ++++++++++++++++++++++-------
 indra/newview/llviewertexture.h         |  1 +
 5 files changed, 55 insertions(+), 16 deletions(-)
 mode change 100644 => 100755 indra/newview/lltexturefetch.h

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index f66d8fca5b..0b7f99ebc1 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11130,6 +11130,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>TextureFetchFakeFailures</key>
+  <map>
+    <key>Comment</key>
+    <string>Simulate HTTP fetch failures for some server bake textures.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
     <key>TextureFetchSource</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index cc6dc64626..2e6fb160d5 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -388,10 +388,12 @@ public:
 	// Threads:  Ttf
 	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
 	
+	void setFakeFailure(bool fake_failure) { mFakeFailure = fake_failure; }
+
 protected:
 	LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type,
 						 const std::string& url, const LLUUID& id, const LLHost& host,
-						 F32 priority, S32 discard, S32 size);
+						 F32 priority, S32 discard, S32 size, bool fake_failure);
 
 private:
 
@@ -547,6 +549,7 @@ private:
 	S32 mActiveCount;
 	LLCore::HttpStatus mGetStatus;
 	std::string mGetReason;
+	bool mFakeFailure;
 	
 	// Work Data
 	LLMutex mWorkMutex;
@@ -836,7 +839,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 										   const LLHost& host,	// Simulator host
 										   F32 priority,		// Priority
 										   S32 discard,			// Desired discard
-										   S32 size)			// Desired size
+										   S32 size,			// Desired size
+										   bool fake_failure)   // For testing, simulate http failure if true.
 	: LLWorkerClass(fetcher, "TextureFetch"),
 	  LLCore::HttpHandler(),
 	  mState(INIT),
@@ -889,7 +893,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mHttpHasResource(false),
 	  mCacheReadCount(0U),
 	  mCacheWriteCount(0U),
-	  mResourceWaitCount(0U)
+	  mResourceWaitCount(0U),
+	  mFakeFailure(fake_failure)
 {
 	mCanUseNET = mUrl.empty() ;
 	
@@ -1519,15 +1524,16 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			{
 				if (http_not_found == mGetStatus)
 				{
+					llwarns << "Texture missing from server (404): " << mUrl << llendl;
+
 					if(mWriteToCacheState == NOT_WRITE) //map tiles
 					{
 						setState(DONE);
 						releaseHttpSemaphore();
-						LL_DEBUGS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl;
+						LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl;
 						return true; // failed, means no map tile on the empty region.
 					}
 
-					llwarns << "Texture missing from server (404): " << mUrl << llendl;
 
 					// roll back to try UDP
 					if (mCanUseNET)
@@ -1891,6 +1897,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
 	}
 
+	if (mFakeFailure)
+	{
+		llwarns << "For debugging, setting fake failure status for texture " << mID << llendl;
+		response->setStatus(LLCore::HttpStatus(404));
+	}
 	bool success = true;
 	bool partial = false;
 	LLCore::HttpStatus status(response->getStatus());
@@ -2455,7 +2466,7 @@ LLTextureFetch::~LLTextureFetch()
 }
 
 bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
-								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)
+								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http, bool fake_failure)
 {
 	if(mFetcherLocked)
 	{
@@ -2523,7 +2534,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		worker->mNeedsAux = needs_aux;
 		worker->setImagePriority(priority);
 		worker->setDesiredDiscard(desired_discard, desired_size);
-		worker->setCanUseHTTP(can_use_http) ;
+		worker->setCanUseHTTP(can_use_http);
+		worker->setFakeFailure(fake_failure);
 		if (!worker->haveWork())
 		{
 			worker->setState(LLTextureFetchWorker::INIT);
@@ -2538,7 +2550,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 	}
 	else
 	{
-		worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size);
+		worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size, fake_failure);
 		lockQueue();													// +Mfq
 		mRequestMap[id] = worker;
 		unlockQueue();													// -Mfq
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
old mode 100644
new mode 100755
index 902a3d7a25..b99480d18e
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -78,7 +78,7 @@ public:
 
 	// Threads:  T* (but Tmain mostly)
 	bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
-					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);
+					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http, bool fake_failure);
 
 	// Requests that a fetch operation be deleted from the queue.
 	// If @cancel is true, also stops any I/O operations pending.
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 9cca8a244e..a157600cc9 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -962,6 +962,8 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	// does not contain this image.
 	mIsMissingAsset = FALSE;
 
+	mFetchFailureCount = 0;
+
 	mLoadedCallbackDesiredDiscardLevel = S8_MAX;
 	mPauseLoadedCallBacks = FALSE ;
 
@@ -1823,12 +1825,18 @@ bool LLViewerFetchedTexture::updateFetch()
 				// We finished but received no data
 				if (current_discard < 0)
 				{
-					llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority
-							<< " mRawDiscardLevel " << mRawDiscardLevel
-							<< " current_discard " << current_discard
-							<< llendl;
-					setIsMissingAsset();
-					desired_discard = -1;
+					const S32 MAX_FETCH_FAILURE = 1;
+					mFetchFailureCount++;
+					llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount << llendl;
+					if (getFTType() != FTT_SERVER_BAKE || mFetchFailureCount >= MAX_FETCH_FAILURE)
+					{
+						llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority
+								<< " mRawDiscardLevel " << mRawDiscardLevel
+								<< " current_discard " << current_discard
+								<< llendl;
+						setIsMissingAsset();
+						desired_discard = -1;
+					}
 				}
 				else
 				{
@@ -1942,8 +1950,14 @@ bool LLViewerFetchedTexture::updateFetch()
 		
 		// bypass texturefetch directly by pulling from LLTextureCache
 		bool fetch_request_created = false;
+		bool fake_failure = false;
+		const bool debug_setting_fake_failures = gSavedSettings.getBOOL("TextureFetchFakeFailures");
+		if (getFTType() == FTT_SERVER_BAKE && mFetchFailureCount == 0 && debug_setting_fake_failures)
+		{
+			fake_failure = true;
+		}
 		fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
-																			  w, h, c, desired_discard, needsAux(), mCanUseHTTP);
+																			  w, h, c, desired_discard, needsAux(), mCanUseHTTP, fake_failure);
 		
 		if (fetch_request_created)
 		{
@@ -2040,6 +2054,7 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 	else
 	{
 		llinfos << mID << ": un-flagging missing asset" << llendl;
+		mFetchFailureCount = 0;
 	}
 	mIsMissingAsset = is_missing;
 }
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 9465fe180b..320e6f8630 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -450,6 +450,7 @@ protected:
 
 	FTType mFTType; // What category of image is this - map tile, server bake, etc?
 	mutable BOOL mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
+	S32 mFetchFailureCount; // How many times has a fetch failed in a way that suggests the asset is missing?
 
 	typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
 	S8              mLoadedCallbackDesiredDiscardLevel;
-- 
cgit v1.2.3


From 67790d0dd8fec2750906ae3d3fed1e735be6b078 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Tue, 9 Apr 2013 15:14:51 -0500
Subject: SH-4035: Bug fix to handle closing the panel when editing a specific
 wearable

---
 indra/newview/llsidepanelappearance.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 53b5593ac9..3899450804 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -131,7 +131,9 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
 void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
 {
 	mLLFloaterSidePanelContainer = obj;
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	if (  LLAppearanceMgr::getInstance()->isOutfitDirty() && 
+		 !LLAppearanceMgr::getInstance()->isOutfitLocked() ||
+		 ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) )
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
 		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
-- 
cgit v1.2.3


From 24fa7736dd123429425d91b2b72c3b3b7110b764 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Tue, 9 Apr 2013 15:30:51 -0500
Subject: SH-4035: Removed unneeded functional call

---
 indra/newview/llsidepanelappearance.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 3899450804..ae6ceabdaa 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -93,7 +93,6 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 	if ( option == 0 ) 
 	{		
 		gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE);
-		mEditWearable->revertChanges();
 		LLAppearanceMgr::getInstance()->wearBaseOutfit();
 		mLLFloaterSidePanelContainer->close();
 		return true;
-- 
cgit v1.2.3


From f78da987913de659367b24e3aa0add2c570f8e1f Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 10 Apr 2013 11:43:48 -0400
Subject: SH-4061 WIP - capture http status codes from requests, restrict SB
 fetch retries to 5xx errors

---
 indra/newview/lltexturefetch.cpp  | 15 ++++++++++-----
 indra/newview/lltexturefetch.h    |  3 ++-
 indra/newview/llviewertexture.cpp | 20 ++++++++++++++++----
 indra/newview/llviewertexture.h   |  4 +++-
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 2e6fb160d5..5a6338d9d8 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -382,6 +382,8 @@ public:
 	void setCanUseHTTP(bool can_use_http) { mCanUseHTTP = can_use_http; }
 	bool getCanUseHTTP() const { return mCanUseHTTP; }
 
+	void setUrl(const std::string& url) { mUrl = url; }
+
 	LLTextureFetch & getFetcher() { return *mFetcher; }
 
 	// Inherited from LLCore::HttpHandler
@@ -1291,7 +1293,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				std::string http_url = region->getHttpUrl() ;
 				if (!http_url.empty())
 				{
-					mUrl = http_url + "/?texture_id=" + mID.asString().c_str();
+					setUrl(http_url + "/?texture_id=" + mID.asString().c_str());
 					mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.
 				}
 				else
@@ -1900,7 +1902,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 	if (mFakeFailure)
 	{
 		llwarns << "For debugging, setting fake failure status for texture " << mID << llendl;
-		response->setStatus(LLCore::HttpStatus(404));
+		response->setStatus(LLCore::HttpStatus(500));
 	}
 	bool success = true;
 	bool partial = false;
@@ -1918,11 +1920,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 // 			<< " offset: " << offset << " length: " << length
 // 			<< llendl;
 
+	std::string reason(status.toString());
+	setGetStatus(status, reason);
 	if (! status)
 	{
 		success = false;
-		std::string reason(status.toString());
-		setGetStatus(status, reason);
 		llwarns << "CURL GET FAILED, status: " << status.toHex()
 				<< " reason: " << reason << llendl;
 	}
@@ -2535,6 +2537,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		worker->setImagePriority(priority);
 		worker->setDesiredDiscard(desired_discard, desired_size);
 		worker->setCanUseHTTP(can_use_http);
+		worker->setUrl(url);
 		worker->setFakeFailure(fake_failure);
 		if (!worker->haveWork())
 		{
@@ -2741,7 +2744,8 @@ LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
 
 // Threads:  T*
 bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
-										LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux)
+										LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,
+										LLCore::HttpStatus& last_http_get_status)
 {
 	bool res = false;
 	LLTextureFetchWorker* worker = getWorker(id);
@@ -2763,6 +2767,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
 		else if (worker->checkWork())
 		{
 			worker->lockWorkMutex();									// +Mw
+			last_http_get_status = worker->mGetStatus;
 			discard_level = worker->mDecodedDiscard;
 			raw = worker->mRawImage;
 			aux = worker->mAuxImage;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index b99480d18e..9f77d58727 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -95,7 +95,8 @@ public:
 
 	// Threads:  T*
 	bool getRequestFinished(const LLUUID& id, S32& discard_level,
-							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux);
+							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,
+							LLCore::HttpStatus& last_http_get_status);
 
 	// Threads:  T*
 	bool updateRequestPriority(const LLUUID& id, F32 priority);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index a157600cc9..7a1afb1238 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1760,7 +1760,8 @@ bool LLViewerFetchedTexture::updateFetch()
 		
 		if (mRawImage.notNull()) sRawCount--;
 		if (mAuxRawImage.notNull()) sAuxCount--;
-		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
+		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage,
+																		   mLastHttpGetStatus);
 		if (mRawImage.notNull()) sRawCount++;
 		if (mAuxRawImage.notNull()) sAuxCount++;
 		if (finished)
@@ -1825,14 +1826,25 @@ bool LLViewerFetchedTexture::updateFetch()
 				// We finished but received no data
 				if (current_discard < 0)
 				{
-					const S32 MAX_FETCH_FAILURE = 1;
+					const S32 MAX_FETCH_FAILURE = 3;
 					mFetchFailureCount++;
-					llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount << llendl;
-					if (getFTType() != FTT_SERVER_BAKE || mFetchFailureCount >= MAX_FETCH_FAILURE)
+					llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount
+							<< " status " << mLastHttpGetStatus.toHex() << llendl;
+					// Will retry server-bake textures under a limited set of circumstances.
+					if (getFTType() == FTT_SERVER_BAKE && 
+						mLastHttpGetStatus.isHttpStatus() && 
+						mLastHttpGetStatus.mType >= 500 && 
+						mLastHttpGetStatus.mType <= 599 && // Only retry 5xx failures.
+						mFetchFailureCount < MAX_FETCH_FAILURE)
+					{
+						llwarns << "Will retry fetch" << llendl;
+					}
+					else // Otherwise, assume the image is missing.
 					{
 						llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority
 								<< " mRawDiscardLevel " << mRawDiscardLevel
 								<< " current_discard " << current_discard
+								<< " stats " << mLastHttpGetStatus.toHex()
 								<< llendl;
 						setIsMissingAsset();
 						desired_discard = -1;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 320e6f8630..91e903ffd6 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -34,6 +34,7 @@
 #include "llgltypes.h"
 #include "llrender.h"
 #include "llmetricperformancetester.h"
+#include "httpcommon.h"
 
 #include <map>
 #include <list>
@@ -446,7 +447,8 @@ protected:
 	S8  mIsRawImageValid;
 	S8  mHasFetcher;				// We've made a fecth request
 	S8  mIsFetching;				// Fetch request is active
-	bool mCanUseHTTP ;              //This texture can be fetched through http if true.
+	bool mCanUseHTTP;              //This texture can be fetched through http if true.
+	LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture.
 
 	FTType mFTType; // What category of image is this - map tile, server bake, etc?
 	mutable BOOL mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
-- 
cgit v1.2.3


From 34e2478388341a1add33bf88cac43031e351340e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 10 Apr 2013 11:57:22 -0400
Subject: SH-4061 WIP - less log spamming for (expected and normal) map tile
 failures.

---
 indra/newview/lltexturefetch.cpp  | 21 +++++++++++++++------
 indra/newview/llviewertexture.cpp | 20 +++++++++++++-------
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 5a6338d9d8..58cfc80839 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1526,14 +1526,20 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			{
 				if (http_not_found == mGetStatus)
 				{
-					llwarns << "Texture missing from server (404): " << mUrl << llendl;
+					if (mFTType != FTT_MAP_TILE)
+					{
+						llwarns << "Texture missing from server (404): " << mUrl << llendl;
+					}
 
-					if(mWriteToCacheState == NOT_WRITE) //map tiles
+					if(mWriteToCacheState == NOT_WRITE) //map tiles or server bakes
 					{
 						setState(DONE);
 						releaseHttpSemaphore();
-						LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl;
-						return true; // failed, means no map tile on the empty region.
+						if (mFTType != FTT_MAP_TILE)
+						{
+							LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl;
+						}
+						return true; 
 					}
 
 
@@ -1925,8 +1931,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 	if (! status)
 	{
 		success = false;
-		llwarns << "CURL GET FAILED, status: " << status.toHex()
-				<< " reason: " << reason << llendl;
+		if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them.
+		{
+			llwarns << "CURL GET FAILED, status: " << status.toHex()
+					<< " reason: " << reason << llendl;
+		}
 	}
 	else
 	{
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 7a1afb1238..5f4c66a04c 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1828,8 +1828,11 @@ bool LLViewerFetchedTexture::updateFetch()
 				{
 					const S32 MAX_FETCH_FAILURE = 3;
 					mFetchFailureCount++;
-					llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount
-							<< " status " << mLastHttpGetStatus.toHex() << llendl;
+					if (getFTType() != FTT_MAP_TILE)
+					{
+						llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount
+								<< " status " << mLastHttpGetStatus.toHex() << llendl;
+					}
 					// Will retry server-bake textures under a limited set of circumstances.
 					if (getFTType() == FTT_SERVER_BAKE && 
 						mLastHttpGetStatus.isHttpStatus() && 
@@ -1841,11 +1844,14 @@ bool LLViewerFetchedTexture::updateFetch()
 					}
 					else // Otherwise, assume the image is missing.
 					{
-						llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority
-								<< " mRawDiscardLevel " << mRawDiscardLevel
-								<< " current_discard " << current_discard
-								<< " stats " << mLastHttpGetStatus.toHex()
-								<< llendl;
+						if (getFTType() != FTT_MAP_TILE)
+						{
+							llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority
+									<< " mRawDiscardLevel " << mRawDiscardLevel
+									<< " current_discard " << current_discard
+									<< " stats " << mLastHttpGetStatus.toHex()
+									<< llendl;
+						}
 						setIsMissingAsset();
 						desired_discard = -1;
 					}
-- 
cgit v1.2.3


From 2798c355c441f8d92a02537eca6e253c8fbf2bc4 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Wed, 10 Apr 2013 16:53:46 -0500
Subject: SH-4035:Added ignore message to notification

---
 indra/newview/llsidepanelappearance.cpp              | 6 +-----
 indra/newview/skins/default/xui/en/notifications.xml | 7 ++++---
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index ae6ceabdaa..6d2b643434 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -77,13 +77,11 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notificat
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( option == 0 ) 
 	{		
-		gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE);		
 		LLAppearanceMgr::instance().setOutfitDirty( true );		
 		showOutfitsInventoryPanel();
 		LLAppearanceMgr::getInstance()->wearBaseOutfit();		
 		return true;
 	}
-	gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE);
 	return false;
 }
 
@@ -91,13 +89,11 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 {
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( option == 0 ) 
-	{		
-		gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE);
+	{	
 		LLAppearanceMgr::getInstance()->wearBaseOutfit();
 		mLLFloaterSidePanelContainer->close();
 		return true;
 	}
-	gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE);	
 	return false;
 }
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 2170283af2..1ff63c6def 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10039,9 +10039,10 @@ Cannot create large prims that intersect other players.  Please re-try when othe
     Closing this window will discard any changes you have made.
     <tag>confirm</tag>
     <usetemplate
-     name="okcancelbuttons"
+     name="okcancelignore"
      notext="Cancel"
-     yestext="OK"/>
+     yestext="OK"
+     ignoretext="Don't show me this again."/>
   </notification>
-  
+
 </notifications>
-- 
cgit v1.2.3


From 14ca6a1247e68805aae22cf573a39819383fe3d4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Apr 2013 11:18:16 -0400
Subject: SH-4061 WIP - moved retry policy to llmessage, added integration test

---
 indra/llmessage/CMakeLists.txt                   |   2 +
 indra/llmessage/llhttpretrypolicy.cpp            |  71 ++++++++
 indra/llmessage/llhttpretrypolicy.h              |  76 ++++++++
 indra/llmessage/tests/llhttpretrypolicy_test.cpp | 220 +++++++++++++++++++++++
 indra/newview/llappearancemgr.cpp                |  79 +-------
 5 files changed, 374 insertions(+), 74 deletions(-)
 mode change 100644 => 100755 indra/llmessage/CMakeLists.txt
 create mode 100755 indra/llmessage/llhttpretrypolicy.cpp
 create mode 100755 indra/llmessage/llhttpretrypolicy.h
 create mode 100755 indra/llmessage/tests/llhttpretrypolicy_test.cpp

diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
old mode 100644
new mode 100755
index 6fa2669be6..6df724f960
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -67,6 +67,7 @@ set(llmessage_SOURCE_FILES
     llpartdata.cpp
     llproxy.cpp
     llpumpio.cpp
+    llhttpretrypolicy.cpp
     llsdappservices.cpp
     llsdhttpserver.cpp
     llsdmessage.cpp
@@ -266,5 +267,6 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "" "${test_libs}")
 endif (LL_TESTS)
 
diff --git a/indra/llmessage/llhttpretrypolicy.cpp b/indra/llmessage/llhttpretrypolicy.cpp
new file mode 100755
index 0000000000..23d9e64c13
--- /dev/null
+++ b/indra/llmessage/llhttpretrypolicy.cpp
@@ -0,0 +1,71 @@
+/** 
+ * @file llhttpretrypolicy.h
+ * @brief Header for a retry policy class intended for use with http responders.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpretrypolicy.h"
+
+void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
+{
+	if (mRetryCount > 0)
+	{
+		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+	}
+	// Honor server Retry-After header.
+	// Status 503 may ask us to wait for a certain amount of time before retrying.
+	F32 wait_time = mDelay;
+	F32 retry_header_time;
+	if (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
+		&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time))
+	{
+		wait_time = retry_header_time;
+	}
+
+	if (mRetryCount>=mMaxRetries)
+	{
+		llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl;
+		mShouldRetry = false;
+	}
+	if (!isHttpServerErrorStatus(status))
+	{
+		llinfos << "Non-server error " << status << ", will not retry" << llendl;
+		mShouldRetry = false;
+	}
+	if (mShouldRetry)
+	{
+		llinfos << "Retry count " << mRetryCount << " should retry after " << wait_time << llendl;
+		mRetryTimer.reset();
+		mRetryTimer.setTimerExpirySec(wait_time);
+	}
+	mRetryCount++;
+}
+	
+
+bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
+{
+	llassert(mRetryCount>0); // have to call onFailure() before shouldRetry()
+	seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX;
+	return mShouldRetry;
+}
diff --git a/indra/llmessage/llhttpretrypolicy.h b/indra/llmessage/llhttpretrypolicy.h
new file mode 100755
index 0000000000..f2eba0965b
--- /dev/null
+++ b/indra/llmessage/llhttpretrypolicy.h
@@ -0,0 +1,76 @@
+/** 
+ * @file file llhttpretrypolicy.h
+ * @brief declarations for http retry policy class.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+										
+#ifndef LL_RETRYPOLICY_H
+#define LL_RETRYPOLICY_H
+
+#include "lltimer.h"
+#include "llthread.h"
+#include "llhttpconstants.h"
+
+// This is intended for use with HTTP Clients/Responders, but is not
+// specifically coupled with those classes.
+class LLHTTPRetryPolicy: public LLThreadSafeRefCount
+{
+public:
+	LLHTTPRetryPolicy() {}
+	virtual ~LLHTTPRetryPolicy() {}
+	// Call once after an HTTP failure to update state.
+	virtual void onFailure(S32 status, const LLSD& headers) = 0;
+	virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
+};
+
+// Very general policy with geometric back-off after failures,
+// up to a maximum delay, and maximum number of retries.
+class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
+{
+public:
+	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
+		mMinDelay(min_delay),
+		mMaxDelay(max_delay),
+		mBackoffFactor(backoff_factor),
+		mMaxRetries(max_retries),
+		mDelay(min_delay),
+		mRetryCount(0),
+		mShouldRetry(true)
+	{
+	}
+
+	void onFailure(S32 status, const LLSD& headers);
+	bool shouldRetry(F32& seconds_to_wait) const;
+
+private:
+	F32 mMinDelay; // delay never less than this value
+	F32 mMaxDelay; // delay never exceeds this value
+	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
+	U32 mMaxRetries; // maximum number of times shouldRetry will return true.
+	F32 mDelay; // current default delay.
+	U32 mRetryCount; // number of times shouldRetry has been called.
+	LLTimer mRetryTimer; // time until next retry.
+	bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc.
+};
+
+#endif
diff --git a/indra/llmessage/tests/llhttpretrypolicy_test.cpp b/indra/llmessage/tests/llhttpretrypolicy_test.cpp
new file mode 100755
index 0000000000..ebf626d9a8
--- /dev/null
+++ b/indra/llmessage/tests/llhttpretrypolicy_test.cpp
@@ -0,0 +1,220 @@
+/** 
+ * @file llhttpretrypolicy_test.cpp
+ * @brief Header tests to exercise the LLHTTPRetryPolicy classes.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpretrypolicy.h"
+#include "lltut.h"
+
+namespace tut
+{
+struct TestData
+{
+};
+
+typedef test_group<TestData>	RetryPolicyTestGroup;
+typedef RetryPolicyTestGroup::object		RetryPolicyTestObject;
+RetryPolicyTestGroup retryPolicyTestGroup("retry_policy");
+
+template<> template<>
+void RetryPolicyTestObject::test<1>()
+{
+	LLAdaptiveRetryPolicy never_retry(1.0,1.0,1.0,0);
+	LLSD headers;
+	F32 wait_seconds;
+	
+	never_retry.onFailure(500,headers);
+	ensure("never retry", !never_retry.shouldRetry(wait_seconds)); 
+}
+
+template<> template<>
+void RetryPolicyTestObject::test<2>()
+{
+	LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10);
+	LLSD headers;
+	F32 wait_seconds;
+	
+	retry404.onFailure(404,headers);
+	ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); 
+}
+
+template<> template<>
+void RetryPolicyTestObject::test<3>()
+{
+	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
+	LLAdaptiveRetryPolicy basic_retry(1.0,3.0,2.0,4);
+	LLSD headers;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	// Starting wait 1.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 1", should_retry);
+	ensure_approximately_equals("basic_retry 1", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 2", should_retry);
+	ensure_approximately_equals("basic_retry 2", wait_seconds, 2.0F, frac_bits);
+
+	// Hit max wait of 3.0 (4.0 clamped to max 3)
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 3", should_retry);
+	ensure_approximately_equals("basic_retry 3", wait_seconds, 3.0F, frac_bits);
+
+	// At max wait, should stay at 3.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 4", should_retry);
+	ensure_approximately_equals("basic_retry 4", wait_seconds, 3.0F, frac_bits);
+
+	// Max retries, should fail now.
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 5", !should_retry);
+}
+
+// Retries should stop as soon as a non-5xx error is received.
+template<> template<>
+void RetryPolicyTestObject::test<4>()
+{
+	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
+	LLAdaptiveRetryPolicy killer404(1.0,3.0,2.0,4);
+	LLSD headers;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	// Starting wait 1.0
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 1", should_retry);
+	ensure_approximately_equals("killer404 1", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 2", should_retry);
+	ensure_approximately_equals("killer404 2", wait_seconds, 2.0F, frac_bits);
+
+	// Should fail on non-5xx
+	killer404.onFailure(404,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 3", !should_retry);
+
+	// After a non-5xx, should keep failing.
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 4", !should_retry);
+}
+
+// Test handling of "retry-after" header. If present, this header
+// value overrides the computed delay, but does not affect the
+// progression of delay values.  For example, if the normal
+// progression of delays would be 1,2,4,8..., but the 2nd and 3rd calls
+// get a retry header of 33, the pattern would become 1,33,33,8...
+template<> template<>
+void RetryPolicyTestObject::test<5>()
+{
+	LLAdaptiveRetryPolicy policy(1.0,25.0,2.0,6);
+	LLSD headers_with_retry;
+	headers_with_retry[HTTP_IN_HEADER_RETRY_AFTER] = "666";
+	LLSD headers_without_retry;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 1", should_retry);
+	ensure_approximately_equals("retry header 1", wait_seconds, 1.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 2", should_retry);
+	ensure_approximately_equals("retry header 2", wait_seconds, 2.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 3", should_retry);
+	// 4.0 overrides by header -> 666.0
+	ensure_approximately_equals("retry header 3", wait_seconds, 666.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 4", should_retry);
+	// 8.0 overrides by header -> 666.0
+	ensure_approximately_equals("retry header 4", wait_seconds, 666.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 5", should_retry);
+	ensure_approximately_equals("retry header 5", wait_seconds, 16.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 6", should_retry);
+	ensure_approximately_equals("retry header 6", wait_seconds, 25.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 7", !should_retry);
+}
+
+// Test getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait),
+// used by header parsing of the retry policy.
+template<> template<>
+void RetryPolicyTestObject::test<6>()
+{
+	F32 seconds_to_wait;
+	bool success;
+
+	std::string str1("0");
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str1, seconds_to_wait);
+	ensure("parse 1", success);
+	ensure_equals("parse 1", seconds_to_wait, 0.0);
+
+	std::string str2("999.9");
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str2, seconds_to_wait);
+	ensure("parse 2", success);
+	ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8);
+
+	time_t nowseconds;
+	time(&nowseconds);
+	std::string str3 = LLDate((F64)nowseconds).asRFC1123();
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
+	ensure("parse 3", success);
+	ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6);
+}
+
+}
+
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index c2be472cbc..85f6f92278 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -52,6 +52,7 @@
 #include "llwearablelist.h"
 #include "llsdutil.h"
 #include "llsdserialize.h"
+#include "llhttpretrypolicy.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -2957,78 +2958,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 	if (inventory_changed) gInventory.notifyObservers();
 }
 
-// This is intended for use with HTTP Clients/Responders, but is not
-// specifically coupled with those classes.
-class LLHTTPRetryPolicy: public LLThreadSafeRefCount
-{
-public:
-	LLHTTPRetryPolicy() {}
-	virtual ~LLHTTPRetryPolicy() {}
-	virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0;
-};
-
-// Example of simplest possible policy, not necessarily recommended.
-// This would be a potentially dangerous policy to enable.  Removing for now:
-#if 0
-class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy
-{
-public:
-	LLAlwaysRetryImmediatelyPolicy() {}
-	bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait)
-	{
-		seconds_to_wait = 0.0;
-		return true;
-	}
-};
-#endif
-
-// Very general policy with geometric back-off after failures,
-// up to a maximum delay, and maximum number of retries.
-class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
-{
-public:
-	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
-		mMinDelay(min_delay),
-		mMaxDelay(max_delay),
-		mBackoffFactor(backoff_factor),
-		mMaxRetries(max_retries),
-		mDelay(min_delay),
-		mRetryCount(0)
-	{
-	}
-
-	bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait)
-	{
-#if 0
-		// *TODO: Test using status codes to only retry server errors.
-		// Only server errors would potentially return a different result on retry.
-		if (!isHttpServerErrorStatus(status)) return false;
-#endif
-
-#if 0
-		// *TODO: Honor server Retry-After header.
-		// Status 503 may ask us to wait for a certain amount of time before retrying.
-		if (!headers.has(HTTP_IN_HEADER_RETRY_AFTER)
-			|| !getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait))
-#endif
-		{
-			seconds_to_wait = mDelay;
-			mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
-		}
-
-		mRetryCount++;
-		return (mRetryCount<=mMaxRetries);
-	}
-
-private:
-	F32 mMinDelay; // delay never less than this value
-	F32 mMaxDelay; // delay never exceeds this value
-	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
-	U32 mMaxRetries; // maximum number of times shouldRetry will return true.
-	F32 mDelay; // current delay.
-	U32 mRetryCount; // number of times shouldRetry has been called.
-};
-
 class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(RequestAgentUpdateAppearanceResponder);
@@ -3084,7 +3013,8 @@ protected:
 	void onFailure()
 	{
 		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait))
+		mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
+		if (mRetryPolicy->shouldRetry(seconds_to_wait))
 		{
 			llinfos << "retrying" << llendl;
 			doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate,
@@ -3327,7 +3257,8 @@ protected:
 		LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error "
 				<< dumpResponse() << LL_ENDL;
 		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait))
+		mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
+		if (mRetryPolicy->shouldRetry(seconds_to_wait))
 		{
 			llinfos << "retrying" << llendl;
 			doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion,
-- 
cgit v1.2.3


From e17920defbf1d39ecd9e88500ba268c59bb84008 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Apr 2013 16:17:23 -0400
Subject: SH-4061 WIP - started adding retry to texture fetch, making retry
 policy compatible with old and new http libraries

---
 indra/llmessage/llhttpretrypolicy.cpp | 17 ++++++++++++++---
 indra/llmessage/llhttpretrypolicy.h   | 17 +++++++++++++++++
 indra/newview/lltexturefetch.cpp      |  1 +
 indra/newview/lltexturefetch.h        |  3 +++
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/indra/llmessage/llhttpretrypolicy.cpp b/indra/llmessage/llhttpretrypolicy.cpp
index 23d9e64c13..7e4dfc7250 100755
--- a/indra/llmessage/llhttpretrypolicy.cpp
+++ b/indra/llmessage/llhttpretrypolicy.cpp
@@ -27,7 +27,20 @@
 #include "linden_common.h"
 #include "llhttpretrypolicy.h"
 
+bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, retry_header_time)
+{
+	return (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
+			&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time));
+}
+
 void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
+{
+	F32 retry_header_time;
+	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
+	onFailureCommon(status, has_retry_header_time, retry_header_time);
+}
+
+void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
 {
 	if (mRetryCount > 0)
 	{
@@ -36,9 +49,7 @@ void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
 	// Honor server Retry-After header.
 	// Status 503 may ask us to wait for a certain amount of time before retrying.
 	F32 wait_time = mDelay;
-	F32 retry_header_time;
-	if (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
-		&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time))
+	if (has_retry_header_time)
 	{
 		wait_time = retry_header_time;
 	}
diff --git a/indra/llmessage/llhttpretrypolicy.h b/indra/llmessage/llhttpretrypolicy.h
index f2eba0965b..cf27bb3048 100755
--- a/indra/llmessage/llhttpretrypolicy.h
+++ b/indra/llmessage/llhttpretrypolicy.h
@@ -29,8 +29,13 @@
 
 #include "lltimer.h"
 #include "llthread.h"
+
 #include "llhttpconstants.h"
 
+// For compatibility with new core http lib.
+#include "httpresponse.h"
+#include "httpheaders.h"
+
 // This is intended for use with HTTP Clients/Responders, but is not
 // specifically coupled with those classes.
 class LLHTTPRetryPolicy: public LLThreadSafeRefCount
@@ -40,6 +45,9 @@ public:
 	virtual ~LLHTTPRetryPolicy() {}
 	// Call once after an HTTP failure to update state.
 	virtual void onFailure(S32 status, const LLSD& headers) = 0;
+
+	virtual void onFailure(const HttpResponse *response, const HttpHeaders *headers) = 0;
+
 	virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
 };
 
@@ -59,10 +67,19 @@ public:
 	{
 	}
 
+	// virtual
 	void onFailure(S32 status, const LLSD& headers);
+	// virtual
+	void onFailure(const HttpResponse *response, const HttpHeaders *headers);
+	// virtual
 	bool shouldRetry(F32& seconds_to_wait) const;
 
+protected:
+	bool getRetryAfter(const LLSD& headers, retry_header_time)
+	void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
+
 private:
+
 	F32 mMinDelay; // delay never less than this value
 	F32 mMaxDelay; // delay never exceeds this value
 	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 58cfc80839..026f36e205 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1918,6 +1918,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 						 << " status: " << status.toHex()
 						 << " '" << status.toString() << "'"
 						 << llendl;
+
 //	unsigned int offset(0), length(0), full_length(0);
 //	response->getRange(&offset, &length, &full_length);
 // 	llwarns << "HTTP COMPLETE: " << mID << " handle: " << handle
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 9f77d58727..c6bd342a7b 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -396,6 +396,9 @@ private:
 	e_tex_source mFetchSource;
 	e_tex_source mOriginFetchSource;
 
+	// Retry logic
+	LLAdaptiveRetryPolicy mFetchRetryPolicy;
+	
 public:
 	//debug use
 	LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;}
-- 
cgit v1.2.3


From a8cdcfc9a893b7debf7c006022b57c389b50bf0d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 12 Apr 2013 09:16:25 -0400
Subject: SH-4061 WIP - moved retry policy to newview so it can work with
 either llmessage or CoreHttp libraries. Updated tests.

---
 indra/llmessage/CMakeLists.txt                   |   2 -
 indra/llmessage/llhttpretrypolicy.cpp            |  82 -------
 indra/llmessage/llhttpretrypolicy.h              |  93 --------
 indra/llmessage/tests/llhttpretrypolicy_test.cpp | 220 ------------------
 indra/newview/CMakeLists.txt                     |   5 +
 indra/newview/llhttpretrypolicy.cpp              | 117 ++++++++++
 indra/newview/llhttpretrypolicy.h                |  94 ++++++++
 indra/newview/lltexturefetch.h                   |   2 +-
 indra/newview/tests/llhttpretrypolicy_test.cpp   | 275 +++++++++++++++++++++++
 9 files changed, 492 insertions(+), 398 deletions(-)
 delete mode 100755 indra/llmessage/llhttpretrypolicy.cpp
 delete mode 100755 indra/llmessage/llhttpretrypolicy.h
 delete mode 100755 indra/llmessage/tests/llhttpretrypolicy_test.cpp
 mode change 100644 => 100755 indra/newview/CMakeLists.txt
 create mode 100755 indra/newview/llhttpretrypolicy.cpp
 create mode 100755 indra/newview/llhttpretrypolicy.h
 create mode 100755 indra/newview/tests/llhttpretrypolicy_test.cpp

diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 6df724f960..6fa2669be6 100755
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -67,7 +67,6 @@ set(llmessage_SOURCE_FILES
     llpartdata.cpp
     llproxy.cpp
     llpumpio.cpp
-    llhttpretrypolicy.cpp
     llsdappservices.cpp
     llsdhttpserver.cpp
     llsdmessage.cpp
@@ -267,6 +266,5 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "" "${test_libs}")
 endif (LL_TESTS)
 
diff --git a/indra/llmessage/llhttpretrypolicy.cpp b/indra/llmessage/llhttpretrypolicy.cpp
deleted file mode 100755
index 7e4dfc7250..0000000000
--- a/indra/llmessage/llhttpretrypolicy.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/** 
- * @file llhttpretrypolicy.h
- * @brief Header for a retry policy class intended for use with http responders.
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llhttpretrypolicy.h"
-
-bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, retry_header_time)
-{
-	return (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
-			&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time));
-}
-
-void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
-{
-	F32 retry_header_time;
-	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
-	onFailureCommon(status, has_retry_header_time, retry_header_time);
-}
-
-void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
-{
-	if (mRetryCount > 0)
-	{
-		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
-	}
-	// Honor server Retry-After header.
-	// Status 503 may ask us to wait for a certain amount of time before retrying.
-	F32 wait_time = mDelay;
-	if (has_retry_header_time)
-	{
-		wait_time = retry_header_time;
-	}
-
-	if (mRetryCount>=mMaxRetries)
-	{
-		llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl;
-		mShouldRetry = false;
-	}
-	if (!isHttpServerErrorStatus(status))
-	{
-		llinfos << "Non-server error " << status << ", will not retry" << llendl;
-		mShouldRetry = false;
-	}
-	if (mShouldRetry)
-	{
-		llinfos << "Retry count " << mRetryCount << " should retry after " << wait_time << llendl;
-		mRetryTimer.reset();
-		mRetryTimer.setTimerExpirySec(wait_time);
-	}
-	mRetryCount++;
-}
-	
-
-bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
-{
-	llassert(mRetryCount>0); // have to call onFailure() before shouldRetry()
-	seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX;
-	return mShouldRetry;
-}
diff --git a/indra/llmessage/llhttpretrypolicy.h b/indra/llmessage/llhttpretrypolicy.h
deleted file mode 100755
index cf27bb3048..0000000000
--- a/indra/llmessage/llhttpretrypolicy.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/** 
- * @file file llhttpretrypolicy.h
- * @brief declarations for http retry policy class.
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-										
-#ifndef LL_RETRYPOLICY_H
-#define LL_RETRYPOLICY_H
-
-#include "lltimer.h"
-#include "llthread.h"
-
-#include "llhttpconstants.h"
-
-// For compatibility with new core http lib.
-#include "httpresponse.h"
-#include "httpheaders.h"
-
-// This is intended for use with HTTP Clients/Responders, but is not
-// specifically coupled with those classes.
-class LLHTTPRetryPolicy: public LLThreadSafeRefCount
-{
-public:
-	LLHTTPRetryPolicy() {}
-	virtual ~LLHTTPRetryPolicy() {}
-	// Call once after an HTTP failure to update state.
-	virtual void onFailure(S32 status, const LLSD& headers) = 0;
-
-	virtual void onFailure(const HttpResponse *response, const HttpHeaders *headers) = 0;
-
-	virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
-};
-
-// Very general policy with geometric back-off after failures,
-// up to a maximum delay, and maximum number of retries.
-class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
-{
-public:
-	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
-		mMinDelay(min_delay),
-		mMaxDelay(max_delay),
-		mBackoffFactor(backoff_factor),
-		mMaxRetries(max_retries),
-		mDelay(min_delay),
-		mRetryCount(0),
-		mShouldRetry(true)
-	{
-	}
-
-	// virtual
-	void onFailure(S32 status, const LLSD& headers);
-	// virtual
-	void onFailure(const HttpResponse *response, const HttpHeaders *headers);
-	// virtual
-	bool shouldRetry(F32& seconds_to_wait) const;
-
-protected:
-	bool getRetryAfter(const LLSD& headers, retry_header_time)
-	void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
-
-private:
-
-	F32 mMinDelay; // delay never less than this value
-	F32 mMaxDelay; // delay never exceeds this value
-	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
-	U32 mMaxRetries; // maximum number of times shouldRetry will return true.
-	F32 mDelay; // current default delay.
-	U32 mRetryCount; // number of times shouldRetry has been called.
-	LLTimer mRetryTimer; // time until next retry.
-	bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc.
-};
-
-#endif
diff --git a/indra/llmessage/tests/llhttpretrypolicy_test.cpp b/indra/llmessage/tests/llhttpretrypolicy_test.cpp
deleted file mode 100755
index ebf626d9a8..0000000000
--- a/indra/llmessage/tests/llhttpretrypolicy_test.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/** 
- * @file llhttpretrypolicy_test.cpp
- * @brief Header tests to exercise the LLHTTPRetryPolicy classes.
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llhttpretrypolicy.h"
-#include "lltut.h"
-
-namespace tut
-{
-struct TestData
-{
-};
-
-typedef test_group<TestData>	RetryPolicyTestGroup;
-typedef RetryPolicyTestGroup::object		RetryPolicyTestObject;
-RetryPolicyTestGroup retryPolicyTestGroup("retry_policy");
-
-template<> template<>
-void RetryPolicyTestObject::test<1>()
-{
-	LLAdaptiveRetryPolicy never_retry(1.0,1.0,1.0,0);
-	LLSD headers;
-	F32 wait_seconds;
-	
-	never_retry.onFailure(500,headers);
-	ensure("never retry", !never_retry.shouldRetry(wait_seconds)); 
-}
-
-template<> template<>
-void RetryPolicyTestObject::test<2>()
-{
-	LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10);
-	LLSD headers;
-	F32 wait_seconds;
-	
-	retry404.onFailure(404,headers);
-	ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); 
-}
-
-template<> template<>
-void RetryPolicyTestObject::test<3>()
-{
-	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
-	LLAdaptiveRetryPolicy basic_retry(1.0,3.0,2.0,4);
-	LLSD headers;
-	F32 wait_seconds;
-	bool should_retry;
-	U32 frac_bits = 6;
-
-	// Starting wait 1.0
-	basic_retry.onFailure(500,headers);
-	should_retry = basic_retry.shouldRetry(wait_seconds);
-	ensure("basic_retry 1", should_retry);
-	ensure_approximately_equals("basic_retry 1", wait_seconds, 1.0F, frac_bits);
-
-	// Double wait to 2.0
-	basic_retry.onFailure(500,headers);
-	should_retry = basic_retry.shouldRetry(wait_seconds);
-	ensure("basic_retry 2", should_retry);
-	ensure_approximately_equals("basic_retry 2", wait_seconds, 2.0F, frac_bits);
-
-	// Hit max wait of 3.0 (4.0 clamped to max 3)
-	basic_retry.onFailure(500,headers);
-	should_retry = basic_retry.shouldRetry(wait_seconds);
-	ensure("basic_retry 3", should_retry);
-	ensure_approximately_equals("basic_retry 3", wait_seconds, 3.0F, frac_bits);
-
-	// At max wait, should stay at 3.0
-	basic_retry.onFailure(500,headers);
-	should_retry = basic_retry.shouldRetry(wait_seconds);
-	ensure("basic_retry 4", should_retry);
-	ensure_approximately_equals("basic_retry 4", wait_seconds, 3.0F, frac_bits);
-
-	// Max retries, should fail now.
-	basic_retry.onFailure(500,headers);
-	should_retry = basic_retry.shouldRetry(wait_seconds);
-	ensure("basic_retry 5", !should_retry);
-}
-
-// Retries should stop as soon as a non-5xx error is received.
-template<> template<>
-void RetryPolicyTestObject::test<4>()
-{
-	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
-	LLAdaptiveRetryPolicy killer404(1.0,3.0,2.0,4);
-	LLSD headers;
-	F32 wait_seconds;
-	bool should_retry;
-	U32 frac_bits = 6;
-
-	// Starting wait 1.0
-	killer404.onFailure(500,headers);
-	should_retry = killer404.shouldRetry(wait_seconds);
-	ensure("killer404 1", should_retry);
-	ensure_approximately_equals("killer404 1", wait_seconds, 1.0F, frac_bits);
-
-	// Double wait to 2.0
-	killer404.onFailure(500,headers);
-	should_retry = killer404.shouldRetry(wait_seconds);
-	ensure("killer404 2", should_retry);
-	ensure_approximately_equals("killer404 2", wait_seconds, 2.0F, frac_bits);
-
-	// Should fail on non-5xx
-	killer404.onFailure(404,headers);
-	should_retry = killer404.shouldRetry(wait_seconds);
-	ensure("killer404 3", !should_retry);
-
-	// After a non-5xx, should keep failing.
-	killer404.onFailure(500,headers);
-	should_retry = killer404.shouldRetry(wait_seconds);
-	ensure("killer404 4", !should_retry);
-}
-
-// Test handling of "retry-after" header. If present, this header
-// value overrides the computed delay, but does not affect the
-// progression of delay values.  For example, if the normal
-// progression of delays would be 1,2,4,8..., but the 2nd and 3rd calls
-// get a retry header of 33, the pattern would become 1,33,33,8...
-template<> template<>
-void RetryPolicyTestObject::test<5>()
-{
-	LLAdaptiveRetryPolicy policy(1.0,25.0,2.0,6);
-	LLSD headers_with_retry;
-	headers_with_retry[HTTP_IN_HEADER_RETRY_AFTER] = "666";
-	LLSD headers_without_retry;
-	F32 wait_seconds;
-	bool should_retry;
-	U32 frac_bits = 6;
-
-	policy.onFailure(500,headers_without_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 1", should_retry);
-	ensure_approximately_equals("retry header 1", wait_seconds, 1.0F, frac_bits);
-
-	policy.onFailure(500,headers_without_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 2", should_retry);
-	ensure_approximately_equals("retry header 2", wait_seconds, 2.0F, frac_bits);
-
-	policy.onFailure(500,headers_with_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 3", should_retry);
-	// 4.0 overrides by header -> 666.0
-	ensure_approximately_equals("retry header 3", wait_seconds, 666.0F, frac_bits);
-
-	policy.onFailure(500,headers_with_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 4", should_retry);
-	// 8.0 overrides by header -> 666.0
-	ensure_approximately_equals("retry header 4", wait_seconds, 666.0F, frac_bits);
-
-	policy.onFailure(500,headers_without_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 5", should_retry);
-	ensure_approximately_equals("retry header 5", wait_seconds, 16.0F, frac_bits);
-
-	policy.onFailure(500,headers_without_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 6", should_retry);
-	ensure_approximately_equals("retry header 6", wait_seconds, 25.0F, frac_bits);
-
-	policy.onFailure(500,headers_with_retry);
-	should_retry = policy.shouldRetry(wait_seconds);
-	ensure("retry header 7", !should_retry);
-}
-
-// Test getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait),
-// used by header parsing of the retry policy.
-template<> template<>
-void RetryPolicyTestObject::test<6>()
-{
-	F32 seconds_to_wait;
-	bool success;
-
-	std::string str1("0");
-	seconds_to_wait = F32_MAX;
-	success = getSecondsUntilRetryAfter(str1, seconds_to_wait);
-	ensure("parse 1", success);
-	ensure_equals("parse 1", seconds_to_wait, 0.0);
-
-	std::string str2("999.9");
-	seconds_to_wait = F32_MAX;
-	success = getSecondsUntilRetryAfter(str2, seconds_to_wait);
-	ensure("parse 2", success);
-	ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8);
-
-	time_t nowseconds;
-	time(&nowseconds);
-	std::string str3 = LLDate((F64)nowseconds).asRFC1123();
-	seconds_to_wait = F32_MAX;
-	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
-	ensure("parse 3", success);
-	ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6);
-}
-
-}
-
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
old mode 100644
new mode 100755
index 05736f6360..27dbe15005
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -299,6 +299,7 @@ set(viewer_SOURCE_FILES
     llgroupmgr.cpp
     llhints.cpp
     llhomelocationresponder.cpp
+    llhttpretrypolicy.cpp
     llhudeffect.cpp
     llhudeffectbeam.cpp
     llhudeffectlookat.cpp
@@ -877,6 +878,7 @@ set(viewer_HEADER_FILES
     llgrouplist.h
     llgroupmgr.h
     llhints.h
+    llhttpretrypolicy.h
     llhomelocationresponder.h
     llhudeffect.h
     llhudeffectbeam.h
@@ -2152,6 +2154,7 @@ if (LL_TESTS)
 
   set(test_libs
     ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLMATH_LIBRARIES}
@@ -2197,6 +2200,8 @@ if (LL_TESTS)
     "${test_libs}"
     )
 
+  LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "llhttpretrypolicy.cpp" "${test_libs}")
+
   #ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
   #ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
   #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
new file mode 100755
index 0000000000..5c6dabbe99
--- /dev/null
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -0,0 +1,117 @@
+/** 
+ * @file llhttpretrypolicy.h
+ * @brief Header for a retry policy class intended for use with http responders.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "llviewerprecompiledheaders.h"
+
+#include "llhttpretrypolicy.h"
+
+bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time)
+{
+	return (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
+			&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time));
+}
+
+bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time)
+{
+	// Look for matching header. Hopefully it's correct enough to let
+	// us extract the field we are looking for. Does not purport to be
+	// in any way a viable general HTTP header parser.
+	if (headers)
+	{
+		for (std::vector<std::string>::const_iterator it = headers->mHeaders.begin();
+			 it != headers->mHeaders.end();
+			 ++it)
+		{
+			const std::string& str = *it;
+			const std::string match = HTTP_IN_HEADER_RETRY_AFTER + ":";
+			size_t pos = str.find(match);
+			if ((pos != std::string::npos) &&
+				(pos+match.length() <= str.length()))
+			{
+				retry_header_time = strtod(str.substr(pos+match.length()).c_str(), NULL);
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
+{
+	F32 retry_header_time;
+	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
+	onFailureCommon(status, has_retry_header_time, retry_header_time);
+}
+  
+// TODO: replace this parsing junk once CoreHttp has its own header parsing capabilities.
+void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
+{
+	F32 retry_header_time;
+	const LLCore::HttpHeaders *headers = response->getHeaders();
+	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
+	onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time);
+}
+
+void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
+{
+	if (mRetryCount > 0)
+	{
+		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
+	}
+	// Honor server Retry-After header.
+	// Status 503 may ask us to wait for a certain amount of time before retrying.
+	F32 wait_time = mDelay;
+	if (has_retry_header_time)
+	{
+		wait_time = retry_header_time;
+	}
+
+	if (mRetryCount>=mMaxRetries)
+	{
+		llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl;
+		mShouldRetry = false;
+	}
+	if (!isHttpServerErrorStatus(status))
+	{
+		llinfos << "Non-server error " << status << ", will not retry" << llendl;
+		mShouldRetry = false;
+	}
+	if (mShouldRetry)
+	{
+		llinfos << "Retry count " << mRetryCount << " should retry after " << wait_time << llendl;
+		mRetryTimer.reset();
+		mRetryTimer.setTimerExpirySec(wait_time);
+	}
+	mRetryCount++;
+}
+	
+
+bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
+{
+	llassert(mRetryCount>0); // have to call onFailure() before shouldRetry()
+	seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX;
+	return mShouldRetry;
+}
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
new file mode 100755
index 0000000000..ca37e5f73c
--- /dev/null
+++ b/indra/newview/llhttpretrypolicy.h
@@ -0,0 +1,94 @@
+/** 
+ * @file file llhttpretrypolicy.h
+ * @brief declarations for http retry policy class.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+										
+#ifndef LL_RETRYPOLICY_H
+#define LL_RETRYPOLICY_H
+
+#include "lltimer.h"
+#include "llthread.h"
+
+#include "llhttpconstants.h"
+
+// For compatibility with new core http lib.
+#include "httpresponse.h"
+#include "httpheaders.h"
+
+// This is intended for use with HTTP Clients/Responders, but is not
+// specifically coupled with those classes.
+class LLHTTPRetryPolicy: public LLThreadSafeRefCount
+{
+public:
+	LLHTTPRetryPolicy() {}
+	virtual ~LLHTTPRetryPolicy() {}
+	// Call once after an HTTP failure to update state.
+	virtual void onFailure(S32 status, const LLSD& headers) = 0;
+
+	virtual void onFailure(const LLCore::HttpResponse *response) = 0;
+
+	virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
+};
+
+// Very general policy with geometric back-off after failures,
+// up to a maximum delay, and maximum number of retries.
+class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
+{
+public:
+	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
+		mMinDelay(min_delay),
+		mMaxDelay(max_delay),
+		mBackoffFactor(backoff_factor),
+		mMaxRetries(max_retries),
+		mDelay(min_delay),
+		mRetryCount(0),
+		mShouldRetry(true)
+	{
+	}
+
+	// virtual
+	void onFailure(S32 status, const LLSD& headers);
+	// virtual
+	void onFailure(const LLCore::HttpResponse *response);
+	// virtual
+	bool shouldRetry(F32& seconds_to_wait) const;
+
+protected:
+	bool getRetryAfter(const LLSD& headers, F32& retry_header_time);
+	bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time);
+	void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
+
+private:
+
+	F32 mMinDelay; // delay never less than this value
+	F32 mMaxDelay; // delay never exceeds this value
+	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
+	U32 mMaxRetries; // maximum number of times shouldRetry will return true.
+	F32 mDelay; // current default delay.
+	U32 mRetryCount; // number of times shouldRetry has been called.
+	LLTimer mRetryTimer; // time until next retry.
+	bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc.
+};
+
+#endif
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index c6bd342a7b..12226d51c8 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -397,7 +397,7 @@ private:
 	e_tex_source mOriginFetchSource;
 
 	// Retry logic
-	LLAdaptiveRetryPolicy mFetchRetryPolicy;
+	//LLAdaptiveRetryPolicy mFetchRetryPolicy;
 	
 public:
 	//debug use
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
new file mode 100755
index 0000000000..39bd15d62f
--- /dev/null
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -0,0 +1,275 @@
+/** 
+ * @file llhttpretrypolicy_test.cpp
+ * @brief Header tests to exercise the LLHTTPRetryPolicy classes.
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "../llviewerprecompiledheaders.h"
+#include "../llhttpretrypolicy.h"
+#include "lltut.h"
+
+namespace tut
+{
+struct TestData
+{
+};
+
+typedef test_group<TestData>	RetryPolicyTestGroup;
+typedef RetryPolicyTestGroup::object		RetryPolicyTestObject;
+RetryPolicyTestGroup retryPolicyTestGroup("retry_policy");
+
+template<> template<>
+void RetryPolicyTestObject::test<1>()
+{
+	LLAdaptiveRetryPolicy never_retry(1.0,1.0,1.0,0);
+	LLSD headers;
+	F32 wait_seconds;
+	
+	never_retry.onFailure(500,headers);
+	ensure("never retry", !never_retry.shouldRetry(wait_seconds)); 
+}
+
+template<> template<>
+void RetryPolicyTestObject::test<2>()
+{
+	LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10);
+	LLSD headers;
+	F32 wait_seconds;
+	
+	retry404.onFailure(404,headers);
+	ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); 
+}
+
+template<> template<>
+void RetryPolicyTestObject::test<3>()
+{
+	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
+	LLAdaptiveRetryPolicy basic_retry(1.0,3.0,2.0,4);
+	LLSD headers;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	// Starting wait 1.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 1", should_retry);
+	ensure_approximately_equals("basic_retry 1", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 2", should_retry);
+	ensure_approximately_equals("basic_retry 2", wait_seconds, 2.0F, frac_bits);
+
+	// Hit max wait of 3.0 (4.0 clamped to max 3)
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 3", should_retry);
+	ensure_approximately_equals("basic_retry 3", wait_seconds, 3.0F, frac_bits);
+
+	// At max wait, should stay at 3.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 4", should_retry);
+	ensure_approximately_equals("basic_retry 4", wait_seconds, 3.0F, frac_bits);
+
+	// Max retries, should fail now.
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 5", !should_retry);
+}
+
+// Retries should stop as soon as a non-5xx error is received.
+template<> template<>
+void RetryPolicyTestObject::test<4>()
+{
+	// Should retry after 1.0, 2.0, 3.0, 3.0 seconds.
+	LLAdaptiveRetryPolicy killer404(1.0,3.0,2.0,4);
+	LLSD headers;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	// Starting wait 1.0
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 1", should_retry);
+	ensure_approximately_equals("killer404 1", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 2", should_retry);
+	ensure_approximately_equals("killer404 2", wait_seconds, 2.0F, frac_bits);
+
+	// Should fail on non-5xx
+	killer404.onFailure(404,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 3", !should_retry);
+
+	// After a non-5xx, should keep failing.
+	killer404.onFailure(500,headers);
+	should_retry = killer404.shouldRetry(wait_seconds);
+	ensure("killer404 4", !should_retry);
+}
+
+// Test handling of "retry-after" header. If present, this header
+// value overrides the computed delay, but does not affect the
+// progression of delay values.  For example, if the normal
+// progression of delays would be 1,2,4,8..., but the 2nd and 3rd calls
+// get a retry header of 33, the pattern would become 1,33,33,8...
+template<> template<>
+void RetryPolicyTestObject::test<5>()
+{
+	LLAdaptiveRetryPolicy policy(1.0,25.0,2.0,6);
+	LLSD headers_with_retry;
+	headers_with_retry[HTTP_IN_HEADER_RETRY_AFTER] = "666";
+	LLSD headers_without_retry;
+	F32 wait_seconds;
+	bool should_retry;
+	U32 frac_bits = 6;
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 1", should_retry);
+	ensure_approximately_equals("retry header 1", wait_seconds, 1.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 2", should_retry);
+	ensure_approximately_equals("retry header 2", wait_seconds, 2.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 3", should_retry);
+	// 4.0 overrides by header -> 666.0
+	ensure_approximately_equals("retry header 3", wait_seconds, 666.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 4", should_retry);
+	// 8.0 overrides by header -> 666.0
+	ensure_approximately_equals("retry header 4", wait_seconds, 666.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 5", should_retry);
+	ensure_approximately_equals("retry header 5", wait_seconds, 16.0F, frac_bits);
+
+	policy.onFailure(500,headers_without_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 6", should_retry);
+	ensure_approximately_equals("retry header 6", wait_seconds, 25.0F, frac_bits);
+
+	policy.onFailure(500,headers_with_retry);
+	should_retry = policy.shouldRetry(wait_seconds);
+	ensure("retry header 7", !should_retry);
+}
+
+// Test getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait),
+// used by header parsing of the retry policy.
+template<> template<>
+void RetryPolicyTestObject::test<6>()
+{
+	F32 seconds_to_wait;
+	bool success;
+
+	std::string str1("0");
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str1, seconds_to_wait);
+	ensure("parse 1", success);
+	ensure_equals("parse 1", seconds_to_wait, 0.0);
+
+	std::string str2("999.9");
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str2, seconds_to_wait);
+	ensure("parse 2", success);
+	ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8);
+
+	time_t nowseconds;
+	time(&nowseconds);
+	std::string str3 = LLDate((F64)nowseconds).asRFC1123();
+	seconds_to_wait = F32_MAX;
+	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
+	ensure("parse 3", success);
+	ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6);
+}
+
+// Test retry-after field in both llmessage and CoreHttp headers.
+template<> template<>
+void RetryPolicyTestObject::test<7>()
+{
+	LLSD sd_headers;
+	time_t nowseconds;
+	time(&nowseconds);
+	sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123();
+	LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,10);
+	F32 seconds_to_wait;
+	bool should_retry;
+
+	// no retry header, use default.
+	policy.onFailure(500,LLSD());
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 1", should_retry);
+	ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6);
+
+	// retry header should override, give delay of 0
+	policy.onFailure(503,sd_headers);
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 2", should_retry);
+	ensure_approximately_equals("header 2", seconds_to_wait, 0.0F, 6);
+
+	// retry header in LLCore::HttpHeaders
+	{
+		LLCore::HttpResponse *response = new LLCore::HttpResponse();
+		LLCore::HttpHeaders *headers = new LLCore::HttpHeaders();
+		response->setStatus(503);
+		response->setHeaders(headers);
+		headers->mHeaders.push_back("retry-after: 600");
+		policy.onFailure(response);
+		should_retry = policy.shouldRetry(seconds_to_wait);
+		ensure("header 3",should_retry);
+		ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6);
+		response->release();
+	}
+
+	// retry header in LLCore::HttpHeaders
+	{
+		LLCore::HttpResponse *response = new LLCore::HttpResponse();
+		LLCore::HttpHeaders *headers = new LLCore::HttpHeaders();
+		response->setStatus(503);
+		response->setHeaders(headers);
+		LLSD sd_headers;
+		time(&nowseconds);
+		headers->mHeaders.push_back("retry-after: " + LLDate((F64)nowseconds).asRFC1123());
+		policy.onFailure(response);
+		should_retry = policy.shouldRetry(seconds_to_wait);
+		ensure("header 3",should_retry);
+		ensure_approximately_equals("header 3", seconds_to_wait, 0.0F, 6);
+		response->release();
+	}
+}
+
+}
+
-- 
cgit v1.2.3


From 766daa73a29d34cb3410c033fc99bfc156844c92 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 12 Apr 2013 10:09:44 -0500
Subject: Sh-4035: Fix for skin changes not being reverted after cancel

---
 indra/newview/llsidepanelappearance.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 6d2b643434..7b89e0617b 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -90,6 +90,7 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( option == 0 ) 
 	{	
+		mEditWearable->revertChanges();
 		LLAppearanceMgr::getInstance()->wearBaseOutfit();
 		mLLFloaterSidePanelContainer->close();
 		return true;
-- 
cgit v1.2.3


From bb237ce15f0a7bc4a3fbffc45b1e4548fd1d2f81 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 12 Apr 2013 17:04:48 -0400
Subject: SH_4061 WIP - retry policy org and tests

---
 indra/newview/llhttpretrypolicy.cpp            | 23 +++++++++++++++++-
 indra/newview/llhttpretrypolicy.h              | 11 +--------
 indra/newview/tests/llhttpretrypolicy_test.cpp | 33 +++++++++++++++++++++-----
 3 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 5c6dabbe99..82f6eab00e 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -28,6 +28,17 @@
 
 #include "llhttpretrypolicy.h"
 
+LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
+	mMinDelay(min_delay),
+	mMaxDelay(max_delay),
+	mBackoffFactor(backoff_factor),
+	mMaxRetries(max_retries),
+	mDelay(min_delay),
+	mRetryCount(0),
+	mShouldRetry(true)
+{
+}
+
 bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time)
 {
 	return (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
@@ -77,6 +88,11 @@ void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
 
 void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
 {
+	if (!mShouldRetry)
+	{
+		llinfos << "keep on failing" << llendl;
+		return;
+	}
 	if (mRetryCount > 0)
 	{
 		mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
@@ -111,7 +127,12 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti
 
 bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
 {
-	llassert(mRetryCount>0); // have to call onFailure() before shouldRetry()
+	if (mRetryCount == 0)
+	{
+		// Called shouldRetry before any failure.
+		seconds_to_wait = F32_MAX;
+		return false;
+	}
 	seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX;
 	return mShouldRetry;
 }
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
index ca37e5f73c..6f63f047de 100755
--- a/indra/newview/llhttpretrypolicy.h
+++ b/indra/newview/llhttpretrypolicy.h
@@ -56,16 +56,7 @@ public:
 class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
 {
 public:
-	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
-		mMinDelay(min_delay),
-		mMaxDelay(max_delay),
-		mBackoffFactor(backoff_factor),
-		mMaxRetries(max_retries),
-		mDelay(min_delay),
-		mRetryCount(0),
-		mShouldRetry(true)
-	{
-	}
+	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries);
 
 	// virtual
 	void onFailure(S32 status, const LLSD& headers);
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index 39bd15d62f..43fc1178cc 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -45,8 +45,12 @@ void RetryPolicyTestObject::test<1>()
 	LLSD headers;
 	F32 wait_seconds;
 	
+	// No retry until we've finished a try.
+	ensure("never retry 0", !never_retry.shouldRetry(wait_seconds));
+
+	// 0 retries max.
 	never_retry.onFailure(500,headers);
-	ensure("never retry", !never_retry.shouldRetry(wait_seconds)); 
+	ensure("never retry 1", !never_retry.shouldRetry(wait_seconds)); 
 }
 
 template<> template<>
@@ -70,6 +74,9 @@ void RetryPolicyTestObject::test<3>()
 	bool should_retry;
 	U32 frac_bits = 6;
 
+	// No retry until we've finished a try.
+	ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds));
+
 	// Starting wait 1.0
 	basic_retry.onFailure(500,headers);
 	should_retry = basic_retry.shouldRetry(wait_seconds);
@@ -224,10 +231,13 @@ void RetryPolicyTestObject::test<7>()
 	time_t nowseconds;
 	time(&nowseconds);
 	sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123();
-	LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,10);
+	LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5);
 	F32 seconds_to_wait;
 	bool should_retry;
 
+	// No retry until we've finished a try.
+	ensure("header 0", !policy.shouldRetry(seconds_to_wait));
+	
 	// no retry header, use default.
 	policy.onFailure(500,LLSD());
 	should_retry = policy.shouldRetry(seconds_to_wait);
@@ -246,7 +256,7 @@ void RetryPolicyTestObject::test<7>()
 		LLCore::HttpHeaders *headers = new LLCore::HttpHeaders();
 		response->setStatus(503);
 		response->setHeaders(headers);
-		headers->mHeaders.push_back("retry-after: 600");
+		headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": 600");
 		policy.onFailure(response);
 		should_retry = policy.shouldRetry(seconds_to_wait);
 		ensure("header 3",should_retry);
@@ -262,13 +272,24 @@ void RetryPolicyTestObject::test<7>()
 		response->setHeaders(headers);
 		LLSD sd_headers;
 		time(&nowseconds);
-		headers->mHeaders.push_back("retry-after: " + LLDate((F64)nowseconds).asRFC1123());
+		headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": " + LLDate((F64)nowseconds).asRFC1123());
 		policy.onFailure(response);
 		should_retry = policy.shouldRetry(seconds_to_wait);
-		ensure("header 3",should_retry);
-		ensure_approximately_equals("header 3", seconds_to_wait, 0.0F, 6);
+		ensure("header 4",should_retry);
+		ensure_approximately_equals("header 4", seconds_to_wait, 0.0F, 6);
 		response->release();
 	}
+
+	// Timeout should be clamped at max.
+	policy.onFailure(500,LLSD());
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 5", should_retry);
+	ensure_approximately_equals("header 5", seconds_to_wait, 644.0F, 6);
+
+	// No more retries.
+	policy.onFailure(500,LLSD());
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 6", !should_retry);
 }
 
 }
-- 
cgit v1.2.3


From 8868964b549822f260694c2bf26b903dbce8ed0a Mon Sep 17 00:00:00 2001
From: Monty Brandenberg <monty@lindenlab.com>
Date: Mon, 15 Apr 2013 16:55:35 +0000
Subject: SH-4106 Significantly upgrade the HttpHeaders interface for SSB.
 Header container moves from a vector of raw lines to a vector of string pairs
 representing name/value pairs in headers.  For incoming headers, we normalize
 the name to lowercase and trim it.  Values are only left-trimmed.  Outgoing
 headers are left as-is.  Simple find() method for the common case, forward
 and reverse iterators for those few who need to do it themselves. The HTTP
 status line (e.g. 'HTTP/1.1 200 Ok') is no longer treated as a header to be
 returned to caller.  Unit tests, as usual, were a bear but they absolutely
 ensured outgoing HTTP header conformance after the change.  Grunt work paid
 off.

LLTextureFetch was also given a second options structure
for texture fetches.  Same as the original but with header return
to caller requested.  Baked textures should use this, the other
20,000 texture fetch requests should continue to use the original.
---
 indra/llcorehttp/_httplibcurl.cpp               |  17 +-
 indra/llcorehttp/_httpoprequest.cpp             |  14 +-
 indra/llcorehttp/examples/http_texture_load.cpp |   4 +-
 indra/llcorehttp/httpheaders.cpp                | 141 +++++-
 indra/llcorehttp/httpheaders.h                  | 112 ++++-
 indra/llcorehttp/tests/test_httpheaders.hpp     | 345 ++++++++++++++-
 indra/llcorehttp/tests/test_httprequest.hpp     | 563 +++++++++++++++++++-----
 indra/newview/lltexturefetch.cpp                |  17 +-
 indra/newview/lltexturefetch.h                  |   3 +-
 9 files changed, 1056 insertions(+), 160 deletions(-)

diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 9ea831a771..d49f615ac4 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -359,12 +359,17 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const
 
 struct curl_slist * append_headers_to_slist(const HttpHeaders * headers, struct curl_slist * slist)
 {
-	for (HttpHeaders::container_t::const_iterator it(headers->mHeaders.begin());
-
-		headers->mHeaders.end() != it;
-		 ++it)
+	const HttpHeaders::const_iterator end(headers->end());
+	for (HttpHeaders::const_iterator it(headers->begin()); end != it; ++it)
 	{
-		slist = curl_slist_append(slist, (*it).c_str());
+		static const char sep[] = ": ";
+		std::string header;
+		header.reserve((*it).first.size() + (*it).second.size() + sizeof(sep));
+		header.append((*it).first);
+		header.append(sep);
+		header.append((*it).second);
+		
+		slist = curl_slist_append(slist, header.c_str());
 	}
 	return slist;
 }
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 74fc5c393a..95e0f72c0b 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -610,7 +610,8 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 
 	const size_t hdr_size(size * nmemb);
 	const char * hdr_data(static_cast<const char *>(data));		// Not null terminated
-
+	bool is_header(true);
+	
 	if (hdr_size >= status_line_len && ! strncmp(status_line, hdr_data, status_line_len))
 	{
 		// One of possibly several status lines.  Reset what we know and start over
@@ -621,8 +622,9 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 		op->mStatus = HttpStatus();
 		if (op->mReplyHeaders)
 		{
-			op->mReplyHeaders->mHeaders.clear();
+			op->mReplyHeaders->clear();
 		}
+		is_header = false;
 	}
 
 	// Nothing in here wants a final CR/LF combination.  Remove
@@ -637,18 +639,18 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 	}
 	
 	// Save header if caller wants them in the response
-	if (op->mProcFlags & PF_SAVE_HEADERS)
+	if (is_header && op->mProcFlags & PF_SAVE_HEADERS)
 	{
 		// Save headers in response
 		if (! op->mReplyHeaders)
 		{
 			op->mReplyHeaders = new HttpHeaders;
 		}
-		op->mReplyHeaders->mHeaders.push_back(std::string(hdr_data, wanted_hdr_size));
+		op->mReplyHeaders->appendNormal(hdr_data, wanted_hdr_size);
 	}
 
 	// Detect and parse 'Content-Range' headers
-	if (op->mProcFlags & PF_SCAN_RANGE_HEADER)
+	if (is_header && op->mProcFlags & PF_SCAN_RANGE_HEADER)
 	{
 		char hdr_buffer[128];			// Enough for a reasonable header
 		size_t frag_size((std::min)(wanted_hdr_size, sizeof(hdr_buffer) - 1));
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index 40ad4f047d..909dc5b0cb 100644
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -328,7 +328,7 @@ WorkingSet::WorkingSet()
 	mTextures.reserve(30000);
 
 	mHeaders = new LLCore::HttpHeaders;
-	mHeaders->mHeaders.push_back("Accept: image/x-j2c");
+	mHeaders->append("Accept", "image/x-j2c");
 }
 
 
diff --git a/indra/llcorehttp/httpheaders.cpp b/indra/llcorehttp/httpheaders.cpp
index 2832696271..23ebea361c 100644
--- a/indra/llcorehttp/httpheaders.cpp
+++ b/indra/llcorehttp/httpheaders.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -26,6 +26,8 @@
 
 #include "httpheaders.h"
 
+#include "llstring.h"
+
 
 namespace LLCore
 {
@@ -40,5 +42,142 @@ HttpHeaders::~HttpHeaders()
 {}
 
 
+void
+HttpHeaders::clear()
+{
+	mHeaders.clear();
+}
+
+
+void HttpHeaders::append(const std::string & name, const std::string & value)
+{
+	mHeaders.push_back(value_type(name, value));
+}
+
+
+void HttpHeaders::append(const char * name, const char * value)
+{
+	mHeaders.push_back(value_type(name, value));
+}
+
+
+void HttpHeaders::appendNormal(const char * header, size_t size)
+{
+	std::string name;
+	std::string value;
+
+	int col_pos(0);
+	for (; col_pos < size; ++col_pos)
+	{
+		if (':' == header[col_pos])
+			break;
+	}
+	
+	if (col_pos < size)
+	{
+		// Looks like a header, split it and normalize.
+		// Name is everything before the colon, may be zero-length.
+		name.assign(header, col_pos);
+
+		// Value is everything after the colon, may also be zero-length.
+		const size_t val_len(size - col_pos - 1);
+		if (val_len)
+		{
+			value.assign(header + col_pos + 1, val_len);
+		}
+
+		// Clean the strings
+		LLStringUtil::toLower(name);
+		LLStringUtil::trim(name);
+		LLStringUtil::trimHead(value);
+	}
+	else
+	{
+		// Uncertain what this is, we'll pack it as
+		// a name without a value.  Won't clean as we don't
+		// know what it is...
+		name.assign(header, size);
+	}
+
+	mHeaders.push_back(value_type(name, value));
+}
+
+
+// Find from end to simulate a tradition of using single-valued
+// std::map for this in the past.
+const std::string * HttpHeaders::find(const char * name) const
+{
+	const_reverse_iterator iend(rend());
+	for (const_reverse_iterator iter(rbegin()); iend != iter; ++iter)
+	{
+		if ((*iter).first == name)
+		{
+			return &(*iter).second;
+		}
+	}
+	return NULL;
+}
+
+
+// Standard Iterators
+HttpHeaders::iterator HttpHeaders::begin()
+{
+	return mHeaders.begin();
+}
+
+
+HttpHeaders::const_iterator HttpHeaders::begin() const
+{
+	return mHeaders.begin();
+}
+
+
+HttpHeaders::iterator HttpHeaders::end()
+{
+	return mHeaders.end();
+}
+
+
+HttpHeaders::const_iterator HttpHeaders::end() const
+{
+	return mHeaders.end();
+}
+
+
+// Standard Reverse Iterators
+HttpHeaders::reverse_iterator HttpHeaders::rbegin()
+{
+	return mHeaders.rbegin();
+}
+
+
+HttpHeaders::const_reverse_iterator HttpHeaders::rbegin() const
+{
+	return mHeaders.rbegin();
+}
+
+
+HttpHeaders::reverse_iterator HttpHeaders::rend()
+{
+	return mHeaders.rend();
+}
+
+
+HttpHeaders::const_reverse_iterator HttpHeaders::rend() const
+{
+	return mHeaders.rend();
+}
+
+
+// Return the raw container to the caller.
+//
+// To be used FOR UNIT TESTS ONLY.
+//
+HttpHeaders::container_t & HttpHeaders::getContainerTESTONLY()
+{
+	return mHeaders;
+}
+
+
 }   // end namespace LLCore
 
diff --git a/indra/llcorehttp/httpheaders.h b/indra/llcorehttp/httpheaders.h
index 3449daa3a1..f70cd898f3 100644
--- a/indra/llcorehttp/httpheaders.h
+++ b/indra/llcorehttp/httpheaders.h
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -43,13 +43,26 @@ namespace LLCore
 /// caller has asked that headers be returned (not the default
 /// option).
 ///
-/// @note
-/// This is a minimally-functional placeholder at the moment
-/// to fill out the class hierarchy.  The final class will be
-/// something else, probably more pair-oriented.  It's also
-/// an area where shared values are desirable so refcounting is
-/// already specced and a copy-on-write scheme imagined.
-/// Expect changes here.
+/// Class is mostly a thin wrapper around a vector of pairs
+/// of strings.  Methods provided are few and intended to
+/// reflect actual use patterns.  These include:
+/// - Clearing the list
+/// - Appending a name/value pair to the vector
+/// - Processing a raw byte string into a normalized name/value
+///   pair and appending the result.
+/// - Simple case-sensitive find-last-by-name search
+/// - Forward and reverse iterators over all pairs
+///
+/// Container is ordered and multi-valued.  Headers are
+/// written in the order in which they are appended and
+/// are stored in the order in which they're received from
+/// the wire.  The same header may appear two or more times
+/// in any container.  Searches using the simple find()
+/// interface will find only the last occurrence (somewhat
+/// simulates the use of std::map).  Fuller searches require
+/// the use of an iterator.  Headers received from the wire
+/// are only returned from the last request when redirections
+/// are involved.
 ///
 /// Threading:  Not intrinsically thread-safe.  It *is* expected
 /// that callers will build these objects and then share them
@@ -63,6 +76,16 @@ namespace LLCore
 
 class HttpHeaders : public LLCoreInt::RefCounted
 {
+public:
+	typedef std::pair<std::string, std::string> header_t;
+	typedef std::vector<header_t> container_t;
+	typedef container_t::iterator iterator;
+	typedef container_t::const_iterator const_iterator;
+	typedef container_t::reverse_iterator reverse_iterator;
+	typedef container_t::const_reverse_iterator const_reverse_iterator;
+	typedef container_t::value_type value_type;
+	typedef container_t::size_type size_type;
+
 public:
 	/// @post In addition to the instance, caller has a refcount
 	/// to the instance.  A call to @see release() will destroy
@@ -76,7 +99,78 @@ protected:
 	void operator=(const HttpHeaders &);		// Not defined
 
 public:
-	typedef std::vector<std::string> container_t;
+	// Empty the list of headers.
+	void clear();
+
+	// Append a name/value pair supplied as either std::strings
+	// or NUL-terminated char * to the header list.  No normalization
+	// is performed on the strings.  No conformance test is
+	// performed (names may contain spaces, colons, etc.).
+	//
+	void append(const std::string & name, const std::string & value);
+	void append(const char * name, const char * value);
+
+	// Extract a name/value pair from a raw byte array using
+	// the first colon character as a separator.  Input string
+	// does not need to be NUL-terminated.  Resulting name/value
+	// pair is appended to the header list.
+	//
+	// Normalization is performed on the name/value pair as
+	// follows:
+	// - name is lower-cased according to mostly ASCII rules
+	// - name is left- and right-trimmed of spaces and tabs
+	// - value is left-trimmed of spaces and tabs
+	// - either or both of name and value may be zero-length
+	//
+	// By convention, headers read from the wire will be normalized
+	// in this fashion prior to delivery to any HttpHandler code.
+	// Headers to be written to the wire are left as appended to
+	// the list.
+	void appendNormal(const char * header, size_t size);
+
+	// Perform a simple, case-sensitive search of the header list
+	// returning a pointer to the value of the last matching header
+	// in the header list.  If none is found, a NULL pointer is returned.
+	//
+	// Any pointer returned references objects in the container itself
+	// and will have the same lifetime as this class.  If you want
+	// the value beyond the lifetime of this instance, make a copy.
+	//
+	// @arg		name	C-style string giving the name of a header
+	//					to search.  The comparison is case-sensitive
+	//					though list entries may have been normalized
+	//					to lower-case.
+	//
+	// @return			NULL if the header wasn't found otherwise
+	//					a pointer to a std::string in the container.
+	//					Pointer is valid only for the lifetime of
+	//					the container or until container is modifed.
+	//
+	const std::string * find(const char * name) const;
+
+	// Count of headers currently in the list.
+	size_type size() const
+		{
+			return mHeaders.size();
+		}
+
+	// Standard std::vector-based forward iterators.
+	iterator begin();
+	const_iterator begin() const;
+	iterator end();
+	const_iterator end() const;
+
+	// Standard std::vector-based reverse iterators.
+	reverse_iterator rbegin();
+	const_reverse_iterator rbegin() const;
+	reverse_iterator rend();
+	const_reverse_iterator rend() const;
+
+public:
+	// For unit tests only - not a public API
+	container_t &		getContainerTESTONLY();
+	
+protected:
 	container_t			mHeaders;
 	
 }; // end class HttpHeaders
diff --git a/indra/llcorehttp/tests/test_httpheaders.hpp b/indra/llcorehttp/tests/test_httpheaders.hpp
index ce0d19b058..668c36dc66 100644
--- a/indra/llcorehttp/tests/test_httpheaders.hpp
+++ b/indra/llcorehttp/tests/test_httpheaders.hpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -36,7 +36,6 @@
 using namespace LLCoreInt;
 
 
-
 namespace tut
 {
 
@@ -63,7 +62,7 @@ void HttpHeadersTestObjectType::test<1>()
 	HttpHeaders * headers = new HttpHeaders();
 	ensure("One ref on construction of HttpHeaders", headers->getRefCount() == 1);
 	ensure("Memory being used", mMemTotal < GetMemTotal());
-	ensure("Nothing in headers", 0 == headers->mHeaders.size());
+	ensure("Nothing in headers", 0 == headers->size());
 
 	// release the implicit reference, causing the object to be released
 	headers->release();
@@ -85,14 +84,340 @@ void HttpHeadersTestObjectType::test<2>()
 	
 	{
 		// Append a few strings
-		std::string str1("Pragma:");
-		headers->mHeaders.push_back(str1);
-		std::string str2("Accept: application/json");
-		headers->mHeaders.push_back(str2);
+		std::string str1n("Pragma");
+		std::string str1v("");
+		headers->append(str1n, str1v);
+		std::string str2n("Accept");
+		std::string str2v("application/json");
+		headers->append(str2n, str2v);
+	
+		ensure("Headers retained", 2 == headers->size());
+		HttpHeaders::container_t & c(headers->getContainerTESTONLY());
+		
+		ensure("First name is first name", c[0].first == str1n);
+		ensure("First value is first value", c[0].second == str1v);
+		ensure("Second name is second name", c[1].first == str2n);
+		ensure("Second value is second value", c[1].second == str2v);
+	}
+	
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+template <> template <>
+void HttpHeadersTestObjectType::test<3>()
+{
+	set_test_name("HttpHeaders basic find");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+	
+	{
+		// Append a few strings
+		std::string str1n("Uno");
+		std::string str1v("1");
+		headers->append(str1n, str1v);
+		std::string str2n("doS");
+		std::string str2v("2-2-2-2");
+		headers->append(str2n, str2v);
+		std::string str3n("TRES");
+		std::string str3v("trois gymnopedie");
+		headers->append(str3n, str3v);
+	
+		ensure("Headers retained", 3 == headers->size());
+
+		const std::string * result(NULL);
+
+		// Find a header
+		result = headers->find("TRES");
+		ensure("Found the last item", result != NULL);
+		ensure("Last item is a nice", result != NULL && str3v == *result);
+
+		// appends above are raw and find is case sensitive
+		result = headers->find("TReS");
+		ensure("Last item not found due to case", result == NULL);
+
+		result = headers->find("TRE");
+		ensure("Last item not found due to prefixing (1)", result == NULL);
+
+		result = headers->find("TRESS");
+		ensure("Last item not found due to prefixing (2)", result == NULL);
+	}
+	
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+template <> template <>
+void HttpHeadersTestObjectType::test<4>()
+{
+	set_test_name("HttpHeaders normalized header entry");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+	
+	{
+		static char line1[] = " AcCePT : image/yourfacehere";
+		static char line1v[] = "image/yourfacehere";
+		headers->appendNormal(line1, sizeof(line1) - 1);
+		
+		ensure("First append worked in some fashion", 1 == headers->size());
+
+		const std::string * result(NULL);
+
+		// Find a header
+		result = headers->find("accept");
+		ensure("Found 'accept'", result != NULL);
+		ensure("accept value has face", result != NULL && *result == line1v);
+
+		// Left-clean on value
+		static char line2[] = " next : \t\tlinejunk \t";
+		headers->appendNormal(line2, sizeof(line2) - 1);
+		ensure("Second append worked", 2 == headers->size());
+		result = headers->find("next");
+		ensure("Found 'next'", result != NULL);
+		ensure("next value is left-clean", result != NULL &&
+			   *result == "linejunk \t");
+
+		// First value unmolested
+		result = headers->find("accept");
+		ensure("Found 'accept' again", result != NULL);
+		ensure("accept value has face", result != NULL && *result == line1v);
+
+		// Colons in value are okay
+		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
+		static char line3v[] = ":plop:-neuf-=vleem=";
+		headers->appendNormal(line3, sizeof(line3) - 1);
+		ensure("Third append worked", 3 == headers->size());
+		result = headers->find("fancy-pants");
+		ensure("Found 'fancy-pants'", result != NULL);
+		ensure("fancy-pants value has colons", result != NULL && *result == line3v);
+
+		// Zero-length value
+		static char line4[] = "all-talk-no-walk:";
+		headers->appendNormal(line4, sizeof(line4) - 1);
+		ensure("Fourth append worked", 4 == headers->size());
+		result = headers->find("all-talk-no-walk");
+		ensure("Found 'all-talk'", result != NULL);
+		ensure("al-talk value is zero-length", result != NULL && result->size() == 0);
+
+		// Zero-length name
+		static char line5[] = ":all-talk-no-walk";
+		static char line5v[] = "all-talk-no-walk";
+		headers->appendNormal(line5, sizeof(line5) - 1);
+		ensure("Fifth append worked", 5 == headers->size());
+		result = headers->find("");
+		ensure("Found no-name", result != NULL);
+		ensure("no-name value is something", result != NULL && *result == line5v);
+
+		// Lone colon is still something
+		headers->clear();
+		static char line6[] = "  :";
+		headers->appendNormal(line6, sizeof(line6) - 1);
+		ensure("Sixth append worked", 1 == headers->size());
+		result = headers->find("");
+		ensure("Found 2nd no-name", result != NULL);
+		ensure("2nd no-name value is nothing", result != NULL && result->size() == 0);
+
+		// Line without colons is taken as-is and unstripped in name
+		static char line7[] = " \toskdgioasdghaosdghoowg28342908tg8902hg0hwedfhqew890v7qh0wdebv78q0wdevbhq>?M>BNM<ZV>?NZ? \t";
+		headers->appendNormal(line7, sizeof(line7) - 1);
+		ensure("Seventh append worked", 2 == headers->size());
+		result = headers->find(line7);
+		ensure("Found whatsit line", result != NULL);
+		ensure("Whatsit line has no value", result != NULL && result->size() == 0);
+
+		// Normaling interface heeds the byte count, doesn't look for NUL-terminator
+		static char line8[] = "binary:ignorestuffontheendofthis";
+		headers->appendNormal(line8, 13);
+		ensure("Eighth append worked", 3 == headers->size());
+		result = headers->find("binary");
+		ensure("Found 'binary'", result != NULL);
+		ensure("binary value was limited to 'ignore'", result != NULL &&
+			   *result == "ignore");
+
+	}
 	
-		ensure("Headers retained", 2 == headers->mHeaders.size());
-		ensure("First is first", headers->mHeaders[0] == str1);
-		ensure("Second is second", headers->mHeaders[1] == str2);
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+// Verify forward iterator finds everything as expected
+template <> template <>
+void HttpHeadersTestObjectType::test<5>()
+{
+	set_test_name("HttpHeaders iterator tests");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+
+	HttpHeaders::iterator end(headers->end()), begin(headers->begin());
+	ensure("Empty container has equal begin/end const iterators", end == begin);
+	HttpHeaders::const_iterator cend(headers->end()), cbegin(headers->begin());
+	ensure("Empty container has equal rbegin/rend const iterators", cend == cbegin);
+
+	ensure("Empty container has equal begin/end iterators", headers->end() == headers->begin());
+	
+	{
+		static char line1[] = " AcCePT : image/yourfacehere";
+		static char line1v[] = "image/yourfacehere";
+		headers->appendNormal(line1, sizeof(line1) - 1);
+
+		static char line2[] = " next : \t\tlinejunk \t";
+		static char line2v[] = "linejunk \t";
+		headers->appendNormal(line2, sizeof(line2) - 1);
+
+		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
+		static char line3v[] = ":plop:-neuf-=vleem=";
+		headers->appendNormal(line3, sizeof(line3) - 1);
+
+		static char line4[] = "all-talk-no-walk:";
+		static char line4v[] = "";
+		headers->appendNormal(line4, sizeof(line4) - 1);
+
+		static char line5[] = ":all-talk-no-walk";
+		static char line5v[] = "all-talk-no-walk";
+		headers->appendNormal(line5, sizeof(line5) - 1);
+
+		static char line6[] = "  :";
+		static char line6v[] = "";
+		headers->appendNormal(line6, sizeof(line6) - 1);
+
+		ensure("All entries accounted for", 6 == headers->size());
+
+		static char * values[] = {
+			line1v,
+			line2v,
+			line3v,
+			line4v,
+			line5v,
+			line6v
+		};
+			
+		int i(0);
+		HttpHeaders::const_iterator cend(headers->end());
+		for (HttpHeaders::const_iterator it(headers->begin());
+			 cend != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Const Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
+
+		// Rewind, do non-consts
+		i = 0;
+		HttpHeaders::iterator end(headers->end());
+		for (HttpHeaders::iterator it(headers->begin());
+			 end != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Const Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
+	}
+	
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+// Reverse iterators find everything as expected
+template <> template <>
+void HttpHeadersTestObjectType::test<6>()
+{
+	set_test_name("HttpHeaders reverse iterator tests");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+
+	HttpHeaders::reverse_iterator rend(headers->rend()), rbegin(headers->rbegin());
+	ensure("Empty container has equal rbegin/rend const iterators", rend == rbegin);
+	HttpHeaders::const_reverse_iterator crend(headers->rend()), crbegin(headers->rbegin());
+	ensure("Empty container has equal rbegin/rend const iterators", crend == crbegin);
+	
+	{
+		static char line1[] = " AcCePT : image/yourfacehere";
+		static char line1v[] = "image/yourfacehere";
+		headers->appendNormal(line1, sizeof(line1) - 1);
+
+		static char line2[] = " next : \t\tlinejunk \t";
+		static char line2v[] = "linejunk \t";
+		headers->appendNormal(line2, sizeof(line2) - 1);
+
+		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
+		static char line3v[] = ":plop:-neuf-=vleem=";
+		headers->appendNormal(line3, sizeof(line3) - 1);
+
+		static char line4[] = "all-talk-no-walk:";
+		static char line4v[] = "";
+		headers->appendNormal(line4, sizeof(line4) - 1);
+
+		static char line5[] = ":all-talk-no-walk";
+		static char line5v[] = "all-talk-no-walk";
+		headers->appendNormal(line5, sizeof(line5) - 1);
+
+		static char line6[] = "  :";
+		static char line6v[] = "";
+		headers->appendNormal(line6, sizeof(line6) - 1);
+
+		ensure("All entries accounted for", 6 == headers->size());
+
+		static char * values[] = {
+			line6v,
+			line5v,
+			line4v,
+			line3v,
+			line2v,
+			line1v
+		};
+			
+		int i(0);
+		HttpHeaders::const_reverse_iterator cend(headers->rend());
+		for (HttpHeaders::const_reverse_iterator it(headers->rbegin());
+			 cend != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Const Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
+
+		// Rewind, do non-consts
+		i = 0;
+		HttpHeaders::reverse_iterator end(headers->rend());
+		for (HttpHeaders::reverse_iterator it(headers->rbegin());
+			 end != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
 	}
 	
 	// release the implicit reference, causing the object to be released
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index e5488cf941..27d65f171e 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -60,6 +60,8 @@ void usleep(unsigned long usec);
 namespace tut
 {
 
+typedef std::vector<std::pair<boost::regex, boost::regex> > regex_container_t;
+
 struct HttpRequestTestData
 {
 	// the test objects inherit from this so the member functions and variables
@@ -109,11 +111,17 @@ public:
 					for (int i(0); i < mHeadersRequired.size(); ++i)
 					{
 						bool found = false;
-						for (HttpHeaders::container_t::const_iterator iter(header->mHeaders.begin());
-							 header->mHeaders.end() != iter;
+						for (HttpHeaders::const_iterator iter(header->begin());
+							 header->end() != iter;
 							 ++iter)
 						{
-							if (boost::regex_match(*iter, mHeadersRequired[i]))
+							// std::cerr << "Header: " << (*iter).first
+							//		  << ": " << (*iter).second << std::endl;
+							
+							if (boost::regex_match((*iter).first,
+												   mHeadersRequired[i].first) &&
+								boost::regex_match((*iter).second,
+												   mHeadersRequired[i].second))
 							{
 								found = true;
 								break;
@@ -129,11 +137,14 @@ public:
 				{
 					for (int i(0); i < mHeadersDisallowed.size(); ++i)
 					{
-						for (HttpHeaders::container_t::const_iterator iter(header->mHeaders.begin());
-							 header->mHeaders.end() != iter;
+						for (HttpHeaders::const_iterator iter(header->begin());
+							 header->end() != iter;
 							 ++iter)
 						{
-							if (boost::regex_match(*iter, mHeadersDisallowed[i]))
+							if (boost::regex_match((*iter).first,
+												   mHeadersDisallowed[i].first) &&
+								boost::regex_match((*iter).second,
+												   mHeadersDisallowed[i].second))
 							{
 								std::ostringstream str;
 								str << "Disallowed header # " << i << " not found in response";
@@ -159,8 +170,8 @@ public:
 	std::string mName;
 	HttpHandle mExpectHandle;
 	std::string mCheckContentType;
-	std::vector<boost::regex> mHeadersRequired;
-	std::vector<boost::regex> mHeadersDisallowed;
+	regex_container_t mHeadersRequired;
+	regex_container_t mHeadersDisallowed;
 };
 
 typedef test_group<HttpRequestTestData> HttpRequestTestGroupType;
@@ -1335,7 +1346,9 @@ void HttpRequestTestObjectType::test<13>()
 		
 		// Issue a GET that succeeds
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("\\W*X-LL-Special:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase),
+										  boost::regex(".*", boost::regex::icase)));
 		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
 													 0U,
 													 url_base,
@@ -1702,18 +1715,54 @@ void HttpRequestTestObjectType::test<16>()
 		
 		// Issue a GET that *can* connect
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
 		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
@@ -1735,23 +1784,60 @@ void HttpRequestTestObjectType::test<16>()
 
 		// Do a texture-style fetch
 		headers = new HttpHeaders;
-		headers->mHeaders.push_back("Accept: image/x-j2c");
+		headers->append("Accept", "image/x-j2c");
 		
 		mStatus = HttpStatus(200);
 		handler.mHeadersRequired.clear();
 		handler.mHeadersDisallowed.clear();
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*image/x-j2c", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("\\W*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("image/x-j2c", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("\\W*X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
 		handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
 										  0U,
 										  url_base + "reflect/",
@@ -1892,20 +1978,63 @@ void HttpRequestTestObjectType::test<17>()
 			
 		// Issue a default POST
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/x-www-form-urlencoded", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/x-www-form-urlencoded", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer_encoding", boost::regex::icase),
+				boost::regex(".*chunked.*", boost::regex::icase)));
 		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
 											 0U,
 											 url_base + "reflect/",
@@ -2052,20 +2181,64 @@ void HttpRequestTestObjectType::test<18>()
 			
 		// Issue a default PUT
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*chunked.*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
 		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
@@ -2206,27 +2379,73 @@ void HttpRequestTestObjectType::test<19>()
 
 		// headers
 		headers = new HttpHeaders;
-		headers->mHeaders.push_back("Keep-Alive: 120");
-		headers->mHeaders.push_back("Accept-encoding: deflate");
-		headers->mHeaders.push_back("Accept: text/plain");
+		headers->append("Keep-Alive", "120");
+		headers->append("Accept-encoding", "deflate");
+		headers->append("Accept", "text/plain");
 
 		// Issue a GET with modified headers
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*text/plain", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*deflate", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*120", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-keep-alive:\\s*300", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("text/plain", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("deflate", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("120", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("300", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
 		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
@@ -2359,10 +2578,10 @@ void HttpRequestTestObjectType::test<20>()
 
 		// headers
 		headers = new HttpHeaders();
-		headers->mHeaders.push_back("keep-Alive: 120");
-		headers->mHeaders.push_back("Accept:  text/html");
-		headers->mHeaders.push_back("content-type:  application/llsd+xml");
-		headers->mHeaders.push_back("cache-control: no-store");
+		headers->append("keep-Alive", "120");
+		headers->append("Accept", "text/html");
+		headers->append("content-type", "application/llsd+xml");
+		headers->append("cache-control", "no-store");
 		
 		// And a buffer array
 		const char * msg("<xml><llsd><string>It was the best of times, it was the worst of times.</string></llsd></xml>");
@@ -2371,23 +2590,76 @@ void HttpRequestTestObjectType::test<20>()
 			
 		// Issue a default POST
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*text/html", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*120", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/llsd\\+xml", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("\\s*X-Reflect-cache-control:\\s*no-store", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*application/x-www-form-urlencoded", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-keep-alive:\\s*300", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("text/html", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("120", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/llsd\\+xml", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex("no-store", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/x-www-form-urlencoded", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("300", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
 		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
 											 0U,
 											 url_base + "reflect/",
@@ -2529,9 +2801,9 @@ void HttpRequestTestObjectType::test<21>()
 
 		// headers
 		headers = new HttpHeaders;
-		headers->mHeaders.push_back("content-type:  text/plain");
-		headers->mHeaders.push_back("content-type:  text/html");
-		headers->mHeaders.push_back("content-type:  application/llsd+xml");
+		headers->append("content-type", "text/plain");
+		headers->append("content-type", "text/html");
+		headers->append("content-type", "application/llsd+xml");
 		
 		// And a buffer array
 		const char * msg("<xml><llsd><string>It was the best of times, it was the worst of times.</string></llsd></xml>");
@@ -2540,22 +2812,71 @@ void HttpRequestTestObjectType::test<21>()
 			
 		// Issue a default PUT
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/llsd\\+xml", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*text/plain", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*text/html", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/llsd\\+xml", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("text/plain", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("text/html", boost::regex::icase)));
 		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index cc6dc64626..5e12c341d5 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -2376,6 +2376,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	  mQAMode(qa_mode),
 	  mHttpRequest(NULL),
 	  mHttpOptions(NULL),
+	  mHttpOptionsWithHeaders(NULL),
 	  mHttpHeaders(NULL),
 	  mHttpMetricsHeaders(NULL),
 	  mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
@@ -2406,11 +2407,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	
 	mHttpRequest = new LLCore::HttpRequest;
 	mHttpOptions = new LLCore::HttpOptions;
+	mHttpOptionsWithHeaders = new LLCore::HttpOptions;
+	mHttpOptionsWithHeaders->setWantHeaders(true);
 	mHttpHeaders = new LLCore::HttpHeaders;
 	// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
-	mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
+	mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
 	mHttpMetricsHeaders = new LLCore::HttpHeaders;
-	mHttpMetricsHeaders->mHeaders.push_back(HTTP_OUT_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML);
+	mHttpMetricsHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault();
 }
 
@@ -2431,6 +2434,12 @@ LLTextureFetch::~LLTextureFetch()
 		mHttpOptions = NULL;
 	}
 
+	if (mHttpOptionsWithHeaders)
+	{
+		mHttpOptionsWithHeaders->release();
+		mHttpOptionsWithHeaders = NULL;
+	}
+
 	if (mHttpHeaders)
 	{
 		mHttpHeaders->release();
@@ -4043,7 +4052,7 @@ void LLTextureFetchDebugger::init()
 	{
 		mHttpHeaders = new LLCore::HttpHeaders;
 		// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
-		mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
+		mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
 	}
 }
 
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 902a3d7a25..3c79a5a24d 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -351,6 +351,7 @@ private:
 	// LLCurl interfaces used in the past.
 	LLCore::HttpRequest *				mHttpRequest;					// Ttf
 	LLCore::HttpOptions *				mHttpOptions;					// Ttf
+	LLCore::HttpOptions *				mHttpOptionsWithHeaders;		// Ttf
 	LLCore::HttpHeaders *				mHttpHeaders;					// Ttf
 	LLCore::HttpHeaders *				mHttpMetricsHeaders;			// Ttf
 	LLCore::HttpRequest::policy_t		mHttpPolicyClass;				// T*
-- 
cgit v1.2.3


From ac8f6011ca6fdd0fd8451d8485f4ecc92be072a6 Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Mon, 15 Apr 2013 14:36:07 -0400
Subject: Committing trivial change to test automated build change.

---
 indra/edit-me-to-trigger-new-build.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index 0f6a8b8a1d..48e8b566a6 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1 +1 @@
-Wed Nov  7 00:25:19 UTC 2012
+Mon Apr 15 14:35:39 EDT 2013
-- 
cgit v1.2.3


From 5976dc144e774ae363cbf774337ccf663015cc6d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 15 Apr 2013 15:12:22 -0400
Subject: SH-4061 WIP - simulated failures/image fetch retries

---
 indra/newview/lltexturefetch.cpp  | 113 ++++++++++++++++++++++++++++++--------
 indra/newview/llviewertexture.cpp |   2 +-
 indra/newview/llvoavatar.cpp      |   2 +-
 3 files changed, 92 insertions(+), 25 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 026f36e205..8e78638c0a 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -63,6 +63,8 @@
 #include "bufferarray.h"
 #include "bufferstream.h"
 
+#include "llhttpretrypolicy.h"
+
 bool LLTextureFetchDebugger::sDebuggerEnabled = false ;
 LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128);
 LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128);
@@ -244,6 +246,25 @@ static const S32 HTTP_REQUESTS_IN_QUEUE_LOW_WATER = 20;			// Active level at whi
 
 //////////////////////////////////////////////////////////////////////////////
 
+static const char* e_state_name[] =
+{
+	"INVALID",
+	"INIT",
+	"LOAD_FROM_TEXTURE_CACHE",
+	"CACHE_POST",
+	"LOAD_FROM_NETWORK",
+	"LOAD_FROM_SIMULATOR",
+	"WAIT_HTTP_RESOURCE",
+	"WAIT_HTTP_RESOURCE2",
+	"SEND_HTTP_REQ",
+	"WAIT_HTTP_REQ",
+	"DECODE_IMAGE",
+	"DECODE_IMAGE_UPDATE",
+	"WRITE_TO_CACHE",
+	"WAIT_ON_WRITE",
+	"DONE"
+};
+
 class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 
 {
@@ -552,6 +573,8 @@ private:
 	LLCore::HttpStatus mGetStatus;
 	std::string mGetReason;
 	bool mFakeFailure;
+	LLAdaptiveRetryPolicy mFetchRetryPolicy;
+
 	
 	// Work Data
 	LLMutex mWorkMutex;
@@ -896,7 +919,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mCacheReadCount(0U),
 	  mCacheWriteCount(0U),
 	  mResourceWaitCount(0U),
-	  mFakeFailure(fake_failure)
+	  mFakeFailure(fake_failure),
+	  mFetchRetryPolicy(15.0,15.0,1.0,10)
 {
 	mCanUseNET = mUrl.empty() ;
 	
@@ -1277,6 +1301,20 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 	if (mState == LOAD_FROM_NETWORK)
 	{
+		// Check for retries to previous server failures.
+		F32 wait_seconds;
+		if (mFetchRetryPolicy.shouldRetry(wait_seconds))
+		{
+			if (wait_seconds <= 0.0)
+			{
+				llinfos << mID << " retrying now" << llendl;
+			}
+			else
+			{
+				//llinfos << mID << " waiting to retry for " << wait_seconds << " seconds" << llendl;
+				return false;
+			}
+		}
 		static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP");
 
 // 		if (mHost != LLHost::invalid) get_url = false;
@@ -1557,6 +1595,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				else if (http_service_unavail == mGetStatus)
 				{
 					LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
+					llinfos << "503: HTTP GET failed for: " << mUrl
+							<< " Status: " << mGetStatus.toHex()
+							<< " Reason: '" << mGetReason << "'"
+							<< llendl;
 				}
 				else if (http_not_sat == mGetStatus)
 				{
@@ -1565,11 +1607,29 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				}
 				else
 				{
-					llinfos << "HTTP GET failed for: " << mUrl
+					llinfos << "other: HTTP GET failed for: " << mUrl
 							<< " Status: " << mGetStatus.toHex()
 							<< " Reason: '" << mGetReason << "'"
 							<< llendl;
 				}
+#if 0
+				if (isHttpServerErrorStatus(mGetStatus.mType))
+				{
+					// Check for retry
+					F32 wait_seconds;
+					if (mFetchRetryPolicy.shouldRetry(wait_seconds))
+					{
+						llinfos << mID  << " status " << (S32) mGetStatus.mType << " will retry after " << wait_seconds << llendl;
+						setState(INIT);
+						releaseHttpSemaphore();
+						return false;
+					}
+					else
+					{
+						llinfos << mID << " will not retry on status " << (S32) mGetStatus.mType << llendl;
+					}
+				}
+#endif
 
 				mUrl.clear();
 				if (cur_size > 0)
@@ -1907,12 +1967,33 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 
 	if (mFakeFailure)
 	{
-		llwarns << "For debugging, setting fake failure status for texture " << mID << llendl;
+		llwarns << mID << " for debugging, setting fake failure status for texture " << mID << llendl;
 		response->setStatus(LLCore::HttpStatus(500));
+		setFakeFailure(false);
 	}
 	bool success = true;
 	bool partial = false;
 	LLCore::HttpStatus status(response->getStatus());
+	if (!status && (mFTType == FTT_SERVER_BAKE))
+	{
+		llinfos << mID << " state " << e_state_name[mState] << llendl;
+		mFetchRetryPolicy.onFailure(response);
+		F32 retry_after;
+		if (mFetchRetryPolicy.shouldRetry(retry_after))
+		{
+			llinfos << mID << " should retry after " << retry_after << ", resetting state to INIT" << llendl;
+			mFetcher->removeFromHTTPQueue(mID, 0);
+			std::string reason(status.toString());
+			setGetStatus(status, reason);
+			releaseHttpSemaphore();
+			setState(INIT);
+			return;
+		}
+		else
+		{
+			llinfos << mID << " should not retry" << llendl;
+		}
+	}
 	
 	LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID
 						 << " status: " << status.toHex()
@@ -1934,7 +2015,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		success = false;
 		if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them.
 		{
-			llwarns << "CURL GET FAILED, status: " << status.toHex()
+			llwarns << mID << " CURL GET FAILED, status: " << status.toHex()
 					<< " reason: " << reason << llendl;
 		}
 	}
@@ -2488,7 +2569,11 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 	{
 		return false;
 	}
-	
+
+	if (f_type == FTT_SERVER_BAKE)
+	{
+		llinfos << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl;
+	}
 	LLTextureFetchWorker* worker = getWorker(id) ;
 	if (worker)
 	{
@@ -3248,24 +3333,6 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
 
 void LLTextureFetchWorker::setState(e_state new_state)
 {
-	static const char* e_state_name[] =
-	{
-		"INVALID",
-		"INIT",
-		"LOAD_FROM_TEXTURE_CACHE",
-		"CACHE_POST",
-		"LOAD_FROM_NETWORK",
-		"LOAD_FROM_SIMULATOR",
-		"WAIT_HTTP_RESOURCE",
-		"WAIT_HTTP_RESOURCE2",
-		"SEND_HTTP_REQ",
-		"WAIT_HTTP_REQ",
-		"DECODE_IMAGE",
-		"DECODE_IMAGE_UPDATE",
-		"WRITE_TO_CACHE",
-		"WAIT_ON_WRITE",
-		"DONE"
-	};
 	LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
 	mState = new_state;
 }
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5f4c66a04c..8f7c8e40b7 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1826,7 +1826,7 @@ bool LLViewerFetchedTexture::updateFetch()
 				// We finished but received no data
 				if (current_discard < 0)
 				{
-					const S32 MAX_FETCH_FAILURE = 3;
+					const S32 MAX_FETCH_FAILURE = 1;
 					mFetchFailureCount++;
 					if (getFTType() != FTT_MAP_TILE)
 					{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index cf4cc64ac3..a2ba8f36aa 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7302,7 +7302,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
 		LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
 		if (id == image_baked->getID())
 		{
-			LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL;
+			//LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL;
 			mBakedTextureDatas[i].mIsLoaded = true;
 			mBakedTextureDatas[i].mLastTextureID = id;
 			mBakedTextureDatas[i].mIsUsed = true;
-- 
cgit v1.2.3


From 7182203ebf4ba914c3a49f9593b1ed831fa6c1e9 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 15 Apr 2013 17:46:28 -0400
Subject: SH-4061 WIP - moved all retry logic into lltexturefetch, some
 cleanup. Debug setting now defines a fake failure rate.

---
 indra/newview/app_settings/logcontrol.xml |  0
 indra/newview/app_settings/settings.xml   |  6 ++---
 indra/newview/lltexturefetch.cpp          | 37 +++++++++++++------------
 indra/newview/lltexturefetch.h            |  2 +-
 indra/newview/llviewertexture.cpp         | 45 +++++++------------------------
 indra/newview/llviewertexture.h           |  1 -
 6 files changed, 33 insertions(+), 58 deletions(-)
 mode change 100644 => 100755 indra/newview/app_settings/logcontrol.xml

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
old mode 100644
new mode 100755
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0b7f99ebc1..18a33b3542 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11130,16 +11130,16 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-  <key>TextureFetchFakeFailures</key>
+  <key>TextureFetchFakeFailureRate</key>
   <map>
     <key>Comment</key>
     <string>Simulate HTTP fetch failures for some server bake textures.</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
-    <string>Boolean</string>
+    <string>F32</string>
     <key>Value</key>
-    <integer>0</integer>
+    <integer>0.0</integer>
   </map>
     <key>TextureFetchSource</key>
     <map>
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 8e78638c0a..2cebd4b6eb 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -410,13 +410,11 @@ public:
 	// Inherited from LLCore::HttpHandler
 	// Threads:  Ttf
 	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
-	
-	void setFakeFailure(bool fake_failure) { mFakeFailure = fake_failure; }
 
 protected:
 	LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type,
 						 const std::string& url, const LLUUID& id, const LLHost& host,
-						 F32 priority, S32 discard, S32 size, bool fake_failure);
+						 F32 priority, S32 discard, S32 size);
 
 private:
 
@@ -572,7 +570,6 @@ private:
 	S32 mActiveCount;
 	LLCore::HttpStatus mGetStatus;
 	std::string mGetReason;
-	bool mFakeFailure;
 	LLAdaptiveRetryPolicy mFetchRetryPolicy;
 
 	
@@ -864,8 +861,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 										   const LLHost& host,	// Simulator host
 										   F32 priority,		// Priority
 										   S32 discard,			// Desired discard
-										   S32 size,			// Desired size
-										   bool fake_failure)   // For testing, simulate http failure if true.
+										   S32 size)			// Desired size
 	: LLWorkerClass(fetcher, "TextureFetch"),
 	  LLCore::HttpHandler(),
 	  mState(INIT),
@@ -919,7 +915,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mCacheReadCount(0U),
 	  mCacheWriteCount(0U),
 	  mResourceWaitCount(0U),
-	  mFakeFailure(fake_failure),
 	  mFetchRetryPolicy(15.0,15.0,1.0,10)
 {
 	mCanUseNET = mUrl.empty() ;
@@ -1179,6 +1174,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE
 		LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority)
 							 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
+
 		// fall through
 	}
 
@@ -1315,6 +1311,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				return false;
 			}
 		}
+
 		static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP");
 
 // 		if (mHost != LLHost::invalid) get_url = false;
@@ -1965,11 +1962,14 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
 	}
 
-	if (mFakeFailure)
+	static LLCachedControl<F32> fake_failure_rate(gSavedSettings, "TextureFetchFakeFailureRate");
+	F32 rand_val = ll_frand();
+	F32 rate = fake_failure_rate;
+	if (mFTType == FTT_SERVER_BAKE && (fake_failure_rate > 0.0) && (rand_val < fake_failure_rate))
 	{
-		llwarns << mID << " for debugging, setting fake failure status for texture " << mID << llendl;
-		response->setStatus(LLCore::HttpStatus(500));
-		setFakeFailure(false);
+		llwarns << mID << " for debugging, setting fake failure status for texture " << mID
+				<< " (rand was " << rand_val << "/" << rate << ")" << llendl;
+		response->setStatus(LLCore::HttpStatus(503));
 	}
 	bool success = true;
 	bool partial = false;
@@ -1981,12 +1981,12 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		F32 retry_after;
 		if (mFetchRetryPolicy.shouldRetry(retry_after))
 		{
-			llinfos << mID << " should retry after " << retry_after << ", resetting state to INIT" << llendl;
+			llinfos << mID << " should retry after " << retry_after << ", resetting state to LOAD_FROM_NETWORK" << llendl;
 			mFetcher->removeFromHTTPQueue(mID, 0);
 			std::string reason(status.toString());
 			setGetStatus(status, reason);
 			releaseHttpSemaphore();
-			setState(INIT);
+			setState(LOAD_FROM_NETWORK);
 			return;
 		}
 		else
@@ -2559,7 +2559,7 @@ LLTextureFetch::~LLTextureFetch()
 }
 
 bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
-								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http, bool fake_failure)
+								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)
 {
 	if(mFetcherLocked)
 	{
@@ -2633,7 +2633,6 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		worker->setDesiredDiscard(desired_discard, desired_size);
 		worker->setCanUseHTTP(can_use_http);
 		worker->setUrl(url);
-		worker->setFakeFailure(fake_failure);
 		if (!worker->haveWork())
 		{
 			worker->setState(LLTextureFetchWorker::INIT);
@@ -2648,7 +2647,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 	}
 	else
 	{
-		worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size, fake_failure);
+		worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size);
 		lockQueue();													// +Mfq
 		mRequestMap[id] = worker;
 		unlockQueue();													// -Mfq
@@ -3333,7 +3332,11 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
 
 void LLTextureFetchWorker::setState(e_state new_state)
 {
-	LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
+	if (mFTType == FTT_SERVER_BAKE)
+	{
+//		LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
+	}
+//	LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
 	mState = new_state;
 }
 
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 12226d51c8..5e2b55dbbb 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -78,7 +78,7 @@ public:
 
 	// Threads:  T* (but Tmain mostly)
 	bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
-					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http, bool fake_failure);
+					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);
 
 	// Requests that a fetch operation be deleted from the queue.
 	// If @cancel is true, also stops any I/O operations pending.
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 8f7c8e40b7..45b402f0f6 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -962,8 +962,6 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	// does not contain this image.
 	mIsMissingAsset = FALSE;
 
-	mFetchFailureCount = 0;
-
 	mLoadedCallbackDesiredDiscardLevel = S8_MAX;
 	mPauseLoadedCallBacks = FALSE ;
 
@@ -1826,35 +1824,17 @@ bool LLViewerFetchedTexture::updateFetch()
 				// We finished but received no data
 				if (current_discard < 0)
 				{
-					const S32 MAX_FETCH_FAILURE = 1;
-					mFetchFailureCount++;
 					if (getFTType() != FTT_MAP_TILE)
 					{
-						llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount
-								<< " status " << mLastHttpGetStatus.toHex() << llendl;
-					}
-					// Will retry server-bake textures under a limited set of circumstances.
-					if (getFTType() == FTT_SERVER_BAKE && 
-						mLastHttpGetStatus.isHttpStatus() && 
-						mLastHttpGetStatus.mType >= 500 && 
-						mLastHttpGetStatus.mType <= 599 && // Only retry 5xx failures.
-						mFetchFailureCount < MAX_FETCH_FAILURE)
-					{
-						llwarns << "Will retry fetch" << llendl;
-					}
-					else // Otherwise, assume the image is missing.
-					{
-						if (getFTType() != FTT_MAP_TILE)
-						{
-							llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority
-									<< " mRawDiscardLevel " << mRawDiscardLevel
-									<< " current_discard " << current_discard
-									<< " stats " << mLastHttpGetStatus.toHex()
-									<< llendl;
-						}
-						setIsMissingAsset();
-						desired_discard = -1;
+						llwarns << mID
+								<< " Fetch failure, setting as missing, decode_priority " << decode_priority
+								<< " mRawDiscardLevel " << mRawDiscardLevel
+								<< " current_discard " << current_discard
+								<< " stats " << mLastHttpGetStatus.toHex()
+								<< llendl;
 					}
+					setIsMissingAsset();
+					desired_discard = -1;
 				}
 				else
 				{
@@ -1968,14 +1948,8 @@ bool LLViewerFetchedTexture::updateFetch()
 		
 		// bypass texturefetch directly by pulling from LLTextureCache
 		bool fetch_request_created = false;
-		bool fake_failure = false;
-		const bool debug_setting_fake_failures = gSavedSettings.getBOOL("TextureFetchFakeFailures");
-		if (getFTType() == FTT_SERVER_BAKE && mFetchFailureCount == 0 && debug_setting_fake_failures)
-		{
-			fake_failure = true;
-		}
 		fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
-																			  w, h, c, desired_discard, needsAux(), mCanUseHTTP, fake_failure);
+																			  w, h, c, desired_discard, needsAux(), mCanUseHTTP);
 		
 		if (fetch_request_created)
 		{
@@ -2072,7 +2046,6 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 	else
 	{
 		llinfos << mID << ": un-flagging missing asset" << llendl;
-		mFetchFailureCount = 0;
 	}
 	mIsMissingAsset = is_missing;
 }
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 91e903ffd6..bf6aadd218 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -452,7 +452,6 @@ protected:
 
 	FTType mFTType; // What category of image is this - map tile, server bake, etc?
 	mutable BOOL mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
-	S32 mFetchFailureCount; // How many times has a fetch failed in a way that suggests the asset is missing?
 
 	typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
 	S8              mLoadedCallbackDesiredDiscardLevel;
-- 
cgit v1.2.3


From 68cdbf387cf876da8833157b76048991120dc3f6 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 15 Apr 2013 18:03:31 -0400
Subject: SH-4061 WIP - comments, timing of retries

---
 indra/newview/lltexturefetch.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 2cebd4b6eb..7b719190a4 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -915,7 +915,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mCacheReadCount(0U),
 	  mCacheWriteCount(0U),
 	  mResourceWaitCount(0U),
-	  mFetchRetryPolicy(15.0,15.0,1.0,10)
+	  mFetchRetryPolicy(10.0,3600.0,2.0,10)
 {
 	mCanUseNET = mUrl.empty() ;
 	
@@ -1981,7 +1981,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		F32 retry_after;
 		if (mFetchRetryPolicy.shouldRetry(retry_after))
 		{
-			llinfos << mID << " should retry after " << retry_after << ", resetting state to LOAD_FROM_NETWORK" << llendl;
+			llinfos << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << llendl;
 			mFetcher->removeFromHTTPQueue(mID, 0);
 			std::string reason(status.toString());
 			setGetStatus(status, reason);
@@ -1991,7 +1991,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		}
 		else
 		{
-			llinfos << mID << " should not retry" << llendl;
+			llinfos << mID << " will not retry" << llendl;
 		}
 	}
 	
@@ -3334,9 +3334,12 @@ void LLTextureFetchWorker::setState(e_state new_state)
 {
 	if (mFTType == FTT_SERVER_BAKE)
 	{
+	// NOTE: turning on these log statements is a reliable way to get
+	// blurry images fairly frequently. Presumably this is an
+	// indication of some subtle timing or locking issue.
+
 //		LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
 	}
-//	LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
 	mState = new_state;
 }
 
-- 
cgit v1.2.3


From 24b9657597be6d0b7af472d5deda4b4828ead606 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 15 Apr 2013 20:35:26 -0400
Subject: SH-4061 WIP - improved retry policy test, turned up and fixed a bug
 in getSecondsUntilRetryAfter

---
 indra/llmessage/llhttpconstants.cpp            | 36 +++++++------
 indra/newview/tests/llhttpretrypolicy_test.cpp | 70 +++++++++++++-------------
 2 files changed, 53 insertions(+), 53 deletions(-)
 mode change 100644 => 100755 indra/llmessage/llhttpconstants.cpp

diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp
old mode 100644
new mode 100755
index 1995fad1e5..016f1f1970
--- a/indra/llmessage/llhttpconstants.cpp
+++ b/indra/llmessage/llhttpconstants.cpp
@@ -2,31 +2,28 @@
  * @file llhttpconstants.cpp
  * @brief Implementation of the HTTP request / response constant lookups
  *
- * $LicenseInfo:firstyear=2013&license=viewergpl$
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
  * 
  * Copyright (c) 2013, Linden Research, Inc.
  * 
  * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2013, Linden Research, Inc.
  * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
  * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
  * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
  */
 
@@ -220,7 +217,8 @@ bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_w
 	time_t date = curl_getdate(retry_after.c_str(), NULL );
 	if (-1 == date) return false;
 
-	seconds_to_wait = (F32)date - (F32)LLTimer::getTotalSeconds();
+	seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
+
 	return true;
 }
 
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index 42bb9abe90..6fa3a57364 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -216,21 +216,23 @@ void RetryPolicyTestObject::test<6>()
 
 	time_t nowseconds;
 	time(&nowseconds);
-	std::string str3 = LLDate((F64)nowseconds).asRFC1123();
+	std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123();
 	seconds_to_wait = F32_MAX;
 	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
+	std::cerr << " str3 [" << str3 << "]" << std::endl;
 	ensure("parse 3", success);
-	ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6);
+	ensure_approximately_equals("parse 3", seconds_to_wait, 44.0F, 2);
 }
 
 // Test retry-after field in both llmessage and CoreHttp headers.
 template<> template<>
 void RetryPolicyTestObject::test<7>()
 {
+	std::cerr << "7 starts" << std::endl;
+	
 	LLSD sd_headers;
 	time_t nowseconds;
 	time(&nowseconds);
-	sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123();
 	LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5);
 	F32 seconds_to_wait;
 	bool should_retry;
@@ -245,40 +247,40 @@ void RetryPolicyTestObject::test<7>()
 	ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6);
 
 	// retry header should override, give delay of 0
+	std::string date_string = LLDate((F64)(nowseconds+7)).asRFC1123();
+	sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = date_string;
 	policy.onFailure(503,sd_headers);
 	should_retry = policy.shouldRetry(seconds_to_wait);
 	ensure("header 2", should_retry);
-	ensure_approximately_equals("header 2", seconds_to_wait, 0.0F, 6);
-
-	// retry header in LLCore::HttpHeaders
-	{
-		LLCore::HttpResponse *response = new LLCore::HttpResponse();
-		LLCore::HttpHeaders *headers = new LLCore::HttpHeaders();
-		response->setStatus(503);
-		response->setHeaders(headers);
-		headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600"));
-		policy.onFailure(response);
-		should_retry = policy.shouldRetry(seconds_to_wait);
-		ensure("header 3",should_retry);
-		ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6);
-		response->release();
-	}
-
-	// retry header in LLCore::HttpHeaders
-	{
-		LLCore::HttpResponse *response = new LLCore::HttpResponse();
-		LLCore::HttpHeaders *headers = new LLCore::HttpHeaders();
-		response->setStatus(503);
-		response->setHeaders(headers);
-		LLSD sd_headers;
-		time(&nowseconds);
-		headers->append(HTTP_IN_HEADER_RETRY_AFTER,LLDate((F64)nowseconds).asRFC1123());
-		policy.onFailure(response);
-		should_retry = policy.shouldRetry(seconds_to_wait);
-		ensure("header 4",should_retry);
-		ensure_approximately_equals("header 4", seconds_to_wait, 0.0F, 6);
-		response->release();
-	}
+	ensure_approximately_equals("header 2", seconds_to_wait, 7.0F, 2);
+
+	LLCore::HttpResponse *response;
+	LLCore::HttpHeaders *headers;
+
+	response = new LLCore::HttpResponse();
+	headers = new LLCore::HttpHeaders();
+	response->setStatus(503);
+	response->setHeaders(headers);
+	headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600"));
+	policy.onFailure(response);
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 3",should_retry);
+	ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6);
+	response->release();
+
+	response = new LLCore::HttpResponse();
+	headers = new LLCore::HttpHeaders();
+	response->setStatus(503);
+	response->setHeaders(headers);
+	time(&nowseconds);
+	date_string = LLDate((F64)(nowseconds+77)).asRFC1123();
+	std::cerr << "date_string [" << date_string << "]" << std::endl;
+	headers->append(HTTP_IN_HEADER_RETRY_AFTER,date_string);
+	policy.onFailure(response);
+	should_retry = policy.shouldRetry(seconds_to_wait);
+	ensure("header 4",should_retry);
+	ensure_approximately_equals("header 4", seconds_to_wait, 77.0F, 2);
+	response->release();
 
 	// Timeout should be clamped at max.
 	policy.onFailure(500,LLSD());
-- 
cgit v1.2.3


From 9cbbb45a0ca8a56707125cdb3f6ea95de7f9deef Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 16 Apr 2013 09:19:35 -0400
Subject: SH-4061 WIP - cleanup

---
 indra/newview/lltexturefetch.cpp | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index ce7bd61ce4..1a6a308230 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1609,24 +1609,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 							<< " Reason: '" << mGetReason << "'"
 							<< llendl;
 				}
-#if 0
-				if (isHttpServerErrorStatus(mGetStatus.mType))
-				{
-					// Check for retry
-					F32 wait_seconds;
-					if (mFetchRetryPolicy.shouldRetry(wait_seconds))
-					{
-						llinfos << mID  << " status " << (S32) mGetStatus.mType << " will retry after " << wait_seconds << llendl;
-						setState(INIT);
-						releaseHttpSemaphore();
-						return false;
-					}
-					else
-					{
-						llinfos << mID << " will not retry on status " << (S32) mGetStatus.mType << llendl;
-					}
-				}
-#endif
 
 				mUrl.clear();
 				if (cur_size > 0)
-- 
cgit v1.2.3


From 0a413e1dc82bbe18c5c9fe510b10e33f8fb0a93c Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Tue, 16 Apr 2013 11:54:16 -0500
Subject: Fix for SH-4108 - observer does not see the outfit change when
 closing appearance panel.

---
 indra/newview/llsidepanelappearance.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 7b89e0617b..3c21219dc1 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -136,6 +136,7 @@ void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
 	}
 	else
 	{
+		LLVOAvatarSelf::onCustomizeEnd(FALSE);		
 		mLLFloaterSidePanelContainer->close();
 	}
 }
-- 
cgit v1.2.3


From e3bad9fb86c3f44ad67488402ce2e46743a2422e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 16 Apr 2013 20:27:49 -0400
Subject: SH-4061 WIP - fix for build issues on mac, reset the retry policy on
 success.

---
 indra/newview/llhttpretrypolicy.cpp            | 18 ++++++++++---
 indra/newview/llhttpretrypolicy.h              | 16 +++++++++---
 indra/newview/lltexturefetch.cpp               |  4 +++
 indra/newview/tests/llhttpretrypolicy_test.cpp | 35 +++++++++++++++++++++-----
 indra/test/lltut.h                             | 10 ++++++++
 5 files changed, 69 insertions(+), 14 deletions(-)
 mode change 100644 => 100755 indra/test/lltut.h

diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 10b923be5a..80d97e4362 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -32,11 +32,16 @@ LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 b
 	mMinDelay(min_delay),
 	mMaxDelay(max_delay),
 	mBackoffFactor(backoff_factor),
-	mMaxRetries(max_retries),
-	mDelay(min_delay),
-	mRetryCount(0),
-	mShouldRetry(true)
+	mMaxRetries(max_retries)
 {
+	init();
+}
+
+void LLAdaptiveRetryPolicy::init()
+{
+	mDelay = mMinDelay;
+	mRetryCount = 0;
+	mShouldRetry = true;
 }
 
 bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time)
@@ -59,6 +64,11 @@ bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F3
 	return false;
 }
 
+void LLAdaptiveRetryPolicy::onSuccess()
+{
+	init();
+}
+
 void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
 {
 	F32 retry_header_time;
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
index 6f63f047de..1fb0cac03f 100755
--- a/indra/newview/llhttpretrypolicy.h
+++ b/indra/newview/llhttpretrypolicy.h
@@ -42,7 +42,11 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount
 {
 public:
 	LLHTTPRetryPolicy() {}
+
 	virtual ~LLHTTPRetryPolicy() {}
+	// Call after a sucess to reset retry state.
+
+	virtual void onSuccess() = 0;
 	// Call once after an HTTP failure to update state.
 	virtual void onFailure(S32 status, const LLSD& headers) = 0;
 
@@ -58,6 +62,9 @@ class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
 public:
 	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries);
 
+	// virtual
+	void onSuccess();
+	
 	// virtual
 	void onFailure(S32 status, const LLSD& headers);
 	// virtual
@@ -66,16 +73,17 @@ public:
 	bool shouldRetry(F32& seconds_to_wait) const;
 
 protected:
+	void init();
 	bool getRetryAfter(const LLSD& headers, F32& retry_header_time);
 	bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time);
 	void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
 
 private:
 
-	F32 mMinDelay; // delay never less than this value
-	F32 mMaxDelay; // delay never exceeds this value
-	F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
-	U32 mMaxRetries; // maximum number of times shouldRetry will return true.
+	const F32 mMinDelay; // delay never less than this value
+	const F32 mMaxDelay; // delay never exceeds this value
+	const F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
+	const U32 mMaxRetries; // maximum number of times shouldRetry will return true.
 	F32 mDelay; // current default delay.
 	U32 mRetryCount; // number of times shouldRetry has been called.
 	LLTimer mRetryTimer; // time until next retry.
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 1a6a308230..774c925fa1 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1976,6 +1976,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 			llinfos << mID << " will not retry" << llendl;
 		}
 	}
+	else
+	{
+		mFetchRetryPolicy.onSuccess();
+	}
 	
 	LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID
 						 << " status: " << status.toHex()
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index 6fa3a57364..ed7f3ba326 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -45,7 +45,7 @@ void RetryPolicyTestObject::test<1>()
 	LLSD headers;
 	F32 wait_seconds;
 	
-	// No retry until we've finished a try.
+	// No retry until we've failed a try.
 	ensure("never retry 0", !never_retry.shouldRetry(wait_seconds));
 
 	// 0 retries max.
@@ -74,7 +74,7 @@ void RetryPolicyTestObject::test<3>()
 	bool should_retry;
 	U32 frac_bits = 6;
 
-	// No retry until we've finished a try.
+	// No retry until we've failed a try.
 	ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds));
 
 	// Starting wait 1.0
@@ -105,6 +105,29 @@ void RetryPolicyTestObject::test<3>()
 	basic_retry.onFailure(500,headers);
 	should_retry = basic_retry.shouldRetry(wait_seconds);
 	ensure("basic_retry 5", !should_retry);
+
+	// Max retries, should fail now.
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 5", !should_retry);
+
+	// After a success, should reset to the starting state.
+	basic_retry.onSuccess();
+
+	// No retry until we've failed a try.
+	ensure("basic_retry 6", !basic_retry.shouldRetry(wait_seconds));
+
+	// Starting wait 1.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 7", should_retry);
+	ensure_approximately_equals("basic_retry 7", wait_seconds, 1.0F, frac_bits);
+
+	// Double wait to 2.0
+	basic_retry.onFailure(500,headers);
+	should_retry = basic_retry.shouldRetry(wait_seconds);
+	ensure("basic_retry 8", should_retry);
+	ensure_approximately_equals("basic_retry 8", wait_seconds, 2.0F, frac_bits);
 }
 
 // Retries should stop as soon as a non-5xx error is received.
@@ -221,7 +244,7 @@ void RetryPolicyTestObject::test<6>()
 	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
 	std::cerr << " str3 [" << str3 << "]" << std::endl;
 	ensure("parse 3", success);
-	ensure_approximately_equals("parse 3", seconds_to_wait, 44.0F, 2);
+	ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F);
 }
 
 // Test retry-after field in both llmessage and CoreHttp headers.
@@ -237,7 +260,7 @@ void RetryPolicyTestObject::test<7>()
 	F32 seconds_to_wait;
 	bool should_retry;
 
-	// No retry until we've finished a try.
+	// No retry until we've failed a try.
 	ensure("header 0", !policy.shouldRetry(seconds_to_wait));
 	
 	// no retry header, use default.
@@ -252,7 +275,7 @@ void RetryPolicyTestObject::test<7>()
 	policy.onFailure(503,sd_headers);
 	should_retry = policy.shouldRetry(seconds_to_wait);
 	ensure("header 2", should_retry);
-	ensure_approximately_equals("header 2", seconds_to_wait, 7.0F, 2);
+	ensure_approximately_equals_range("header 2", seconds_to_wait, 7.0F, 2.0F);
 
 	LLCore::HttpResponse *response;
 	LLCore::HttpHeaders *headers;
@@ -279,7 +302,7 @@ void RetryPolicyTestObject::test<7>()
 	policy.onFailure(response);
 	should_retry = policy.shouldRetry(seconds_to_wait);
 	ensure("header 4",should_retry);
-	ensure_approximately_equals("header 4", seconds_to_wait, 77.0F, 2);
+	ensure_approximately_equals_range("header 4", seconds_to_wait, 77.0F, 2.0F);
 	response->release();
 
 	// Timeout should be clamped at max.
diff --git a/indra/test/lltut.h b/indra/test/lltut.h
old mode 100644
new mode 100755
index 55d84bcaca..243e869be7
--- a/indra/test/lltut.h
+++ b/indra/test/lltut.h
@@ -65,6 +65,16 @@ namespace tut
 		ensure_approximately_equals(NULL, actual, expected, frac_bits);
 	}
 
+	inline void ensure_approximately_equals_range(const char *msg, F32 actual, F32 expected, F32 delta)
+	{
+		if (fabs(actual-expected)>delta)
+		{
+			std::stringstream ss;
+			ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected << " tolerance: " << delta;
+			throw tut::failure(ss.str().c_str());
+		}
+	}
+
 	inline void ensure_memory_matches(const char* msg,const void* actual, U32 actual_len, const void* expected,U32 expected_len)
 	{
 		if((expected_len != actual_len) || 
-- 
cgit v1.2.3


From 8cf67fe50cfa070e5aa786acdb9bce58c350d840 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 17 Apr 2013 10:33:33 -0400
Subject: Fix for SH-4104: Inventory window does not close

---
 indra/newview/llfloatersidepanelcontainer.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index b1f9a18d6f..4dd558c9c0 100644
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -69,6 +69,10 @@ void LLFloaterSidePanelContainer::onClickCloseBtn()
 			LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
 			panel_appearance->onClose(this);			
 		}
+		else
+		{
+			LLFloater::onClickCloseBtn();
+		}
 	}
 	else
 	{
-- 
cgit v1.2.3


From 392f561b6c28aede2b61bc9cc2cc75de587926b6 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 17 Apr 2013 11:08:40 -0400
Subject: Fix for SH-4123: outfit update corrected for edit/save/abandon
 sequence

---
 indra/newview/llsidepanelappearance.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 3c21219dc1..75da23b558 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -90,8 +90,9 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( option == 0 ) 
 	{	
+		//revert curernt edits
 		mEditWearable->revertChanges();
-		LLAppearanceMgr::getInstance()->wearBaseOutfit();
+		LLVOAvatarSelf::onCustomizeEnd(FALSE);	
 		mLLFloaterSidePanelContainer->close();
 		return true;
 	}
-- 
cgit v1.2.3


From b224b8978adfd42c89e1c66bc5495ead8fa1e85d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 17 Apr 2013 11:32:23 -0400
Subject: SH-4061 WIP - request headers for server-bake images

---
 indra/newview/lltexturefetch.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 774c925fa1..346374ef4e 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1524,12 +1524,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
 								 << LL_ENDL;
 
 			// Will call callbackHttpGet when curl request completes
+			// Only server bake images use the returned headers currently, for getting retry-after field.
+			HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
 			mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass,
 																	  mWorkPriority,
 																	  mUrl,
 																	  mRequestedOffset,
 																	  mRequestedSize,
-																	  mFetcher->mHttpOptions,
+																	  options,
 																	  mFetcher->mHttpHeaders,
 																	  this);
 		}
-- 
cgit v1.2.3


From b29e6f656eb28d557ef4488a022b6757a58d29e1 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 17 Apr 2013 11:32:49 -0400
Subject: Fix for SH-4124: Closing appearance panel also closes the edit
 wearable panel if it was active

---
 indra/newview/llsidepanelappearance.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 75da23b558..77e9604460 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -92,6 +92,7 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 	{	
 		//revert curernt edits
 		mEditWearable->revertChanges();
+		toggleWearableEditPanel(FALSE);
 		LLVOAvatarSelf::onCustomizeEnd(FALSE);	
 		mLLFloaterSidePanelContainer->close();
 		return true;
@@ -138,6 +139,7 @@ void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
 	else
 	{
 		LLVOAvatarSelf::onCustomizeEnd(FALSE);		
+		toggleWearableEditPanel(FALSE);
 		mLLFloaterSidePanelContainer->close();
 	}
 }
-- 
cgit v1.2.3


From 17af76fae18e305d0a42192a326648f00c84d1f3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 18 Apr 2013 13:56:16 -0400
Subject: SH-4128 WIP - use the AISv3 inventory cap when available for cof link
 deletion, hook in to callback mechanism so all link operations should be done
 before outfit is worn.

---
 indra/newview/llappearancemgr.cpp   |  20 ++-----
 indra/newview/llappearancemgr.h     |   2 +-
 indra/newview/lltexturefetch.cpp    |   4 +-
 indra/newview/llviewerinventory.cpp | 101 ++++++++++++++++++++++++++++++++++++
 indra/newview/llviewerinventory.h   |   4 ++
 indra/newview/llviewerregion.cpp    |   1 +
 6 files changed, 113 insertions(+), 19 deletions(-)
 mode change 100644 => 100755 indra/newview/llviewerinventory.cpp
 mode change 100644 => 100755 indra/newview/llviewerinventory.h

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 85f6f92278..f1a2141b99 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1661,7 +1661,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
 	}
 }
 
-void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items)
+void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer<LLInventoryCallback> cb)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLInventoryModel::item_array_t items;
@@ -1674,19 +1674,8 @@ void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_lin
 			continue;
 		if (item->getIsLinkType())
 		{
-#if 0
-			if (keep_items && keep_items->find(item) != LLInventoryModel::item_array_t::FAIL)
-			{
-				llinfos << "preserved item" << llendl;
-			}
-			else
-			{
-				gInventory.purgeObject(item->getUUID());
-			}
-#else
-			gInventory.purgeObject(item->getUUID());
+			remove_inventory_item(item->getUUID(), cb);
 		}
-#endif
 	}
 }
 
@@ -1819,7 +1808,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// carried over (e.g. keeping old shape if the new outfit does not
 	// contain one)
 	bool keep_outfit_links = append;
-	purgeCategory(cof, keep_outfit_links, &all_items);
+	purgeCategory(cof, keep_outfit_links, link_waiter);
 	gInventory.notifyObservers();
 
 	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
@@ -2824,7 +2813,7 @@ bool LLAppearanceMgr::updateBaseOutfit()
 	updateClothingOrderingInfo();
 
 	// in a Base Outfit we do not remove items, only links
-	purgeCategory(base_outfit_id, false);
+	purgeCategory(base_outfit_id, false, NULL);
 
 	LLPointer<LLInventoryCallback> dirty_state_updater =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
@@ -3211,7 +3200,6 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond
 	}
 	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl;
 	
-	//LLCurl::ResponderPtr responder_ptr;
 	if (!responder_ptr.get())
 	{
 		responder_ptr = new RequestAgentUpdateAppearanceResponder;
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 46252afbde..b933b4fc50 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -222,7 +222,7 @@ private:
 								   LLInventoryModel::item_array_t& gest_items,
 								   bool follow_folder_links);
 
-	void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items = NULL);
+	void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer<LLInventoryCallback> cb);
 	static void onOutfitRename(const LLSD& notification, const LLSD& response);
 
 	void setOutfitLocked(bool locked);
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 346374ef4e..f7fbb19bdc 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1525,7 +1525,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 			// Will call callbackHttpGet when curl request completes
 			// Only server bake images use the returned headers currently, for getting retry-after field.
-			HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
+			LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
 			mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass,
 																	  mWorkPriority,
 																	  mUrl,
@@ -2569,7 +2569,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 
 	if (f_type == FTT_SERVER_BAKE)
 	{
-		llinfos << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl;
+		LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl;
 	}
 	LLTextureFetchWorker* worker = getWorker(id) ;
 	if (worker)
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
old mode 100644
new mode 100755
index fff9821e86..316fca7769
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1179,6 +1179,107 @@ void move_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
+void handle_item_deletion(const LLUUID& item_id)
+{
+	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+	if(obj)
+	{
+		// From item removeFromServer()
+		LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
+		gInventory.accountForUpdate(up);
+
+		// From purgeObject()
+		LLPreview::hide(item_id);
+		gInventory.deleteObject(item_id);
+	}
+}
+
+class RemoveItemResponder: public LLHTTPClient::Responder
+{
+public:
+	RemoveItemResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback):
+		mItemUUID(item_id),
+		mCallback(callback)
+	{
+	}
+	/* virtual */ void httpSuccess()
+	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl;
+
+		handle_item_deletion(mItemUUID);
+
+		if (mCallback)
+		{
+			mCallback->fire(mItemUUID);
+		}
+	}
+	/*virtual*/ void httpFailure()
+	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl;
+	}
+private:
+	LLPointer<LLInventoryCallback> mCallback;
+	const LLUUID mItemUUID;
+};
+
+void remove_inventory_item(
+	const LLUUID& item_id,
+	LLPointer<LLInventoryCallback> cb)
+{
+	llinfos << "item_id: [" << item_id << "] " << llendl;
+	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+	if(obj)
+	{
+		std::string cap;
+		if (gAgent.getRegion())
+		{
+			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+		}
+		if (!cap.empty())
+		{
+			std::string url = cap + std::string("/item/") + item_id.asString();
+			llinfos << "url: " << url << llendl;
+			LLCurl::ResponderPtr responder_ptr = new RemoveItemResponder(item_id,cb);
+			LLHTTPClient::del(url,responder_ptr);
+		}
+		else // no cap
+		{
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_RemoveInventoryItem);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addUUIDFast(_PREHASH_ItemID, item_id);
+			gAgent.sendReliableMessage();
+
+			// Update inventory and call callback immediately since
+			// message-based system has no callback mechanism (!)
+			handle_item_deletion(item_id);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
+		}
+	}
+	else
+	{
+		llwarns << "remove_inventory_item called for nonexistent item " << item_id << llendl;
+	}
+}
+
 const LLUUID get_folder_by_itemtype(const LLInventoryItem *src)
 {
 	LLUUID retval = LLUUID::null;
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
old mode 100644
new mode 100755
index 61b1b8d846..7cb62efb47
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -365,6 +365,10 @@ void move_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
+void remove_inventory_item(
+	const LLUUID& item_id,
+	LLPointer<LLInventoryCallback> cb);
+	
 const LLUUID get_folder_by_itemtype(const LLInventoryItem *src);
 
 void copy_inventory_from_notecard(const LLUUID& destination_id,
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index f0d81c599c..e77b29aca4 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1641,6 +1641,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 		capabilityNames.append("FetchInventory2");
 		capabilityNames.append("FetchInventoryDescendents2");
 		capabilityNames.append("IncrementCOFVersion");
+		capabilityNames.append("InventoryAPIv3");
 	}
 
 	capabilityNames.append("GetDisplayNames");
-- 
cgit v1.2.3


From e3ceb10c48b7ce339fab8c3c7a726bd4bf2e30e8 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 18 Apr 2013 17:31:35 -0400
Subject: SH-4128 WIP - avoid needless called to updateLinkedObjectsFromPurge()

---
 indra/newview/llinventorymodel.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
 mode change 100644 => 100755 indra/newview/llinventorymodel.cpp

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
old mode 100644
new mode 100755
index 8d7478233a..3d2fcdc494
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1171,8 +1171,14 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 		mParentChildCategoryTree.erase(id);
 	}
 	addChangedMask(LLInventoryObserver::REMOVE, id);
+	bool is_link_type = obj->getIsLinkType();
 	obj = NULL; // delete obj
-	updateLinkedObjectsFromPurge(id);
+	// Can't have links to links, so there's no need for this update
+	// if the item removed is a link.
+	if (!is_link_type)
+	{
+		updateLinkedObjectsFromPurge(id);
+	}
 	gInventory.notifyObservers();
 }
 
-- 
cgit v1.2.3


From 7b52a41e34e1fefd751d69be708b23df59774c6a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 18 Apr 2013 17:49:10 -0400
Subject: SH-4116 WIP - removed follow_folder_links behavior, which was used
 nowhere and isn't really desirable currently

---
 indra/newview/llappearancemgr.cpp  | 49 ++++++++++++++++----------------------
 indra/newview/llappearancemgr.h    |  6 ++---
 indra/newview/llinventorymodel.cpp | 33 +------------------------
 indra/newview/llinventorymodel.h   |  3 +--
 4 files changed, 24 insertions(+), 67 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index f1a2141b99..fffec223d7 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1204,8 +1204,7 @@ const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink()
 									cat_array,
 									item_array,
 									false,
-									is_category,
-									false);
+									is_category);
 	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
 		 iter != item_array.end();
 		 iter++)
@@ -1738,7 +1737,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	if (!append)
 	{
 		LLInventoryModel::item_array_t gest_items;
-		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
+		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE);
 		for(S32 i = 0; i  < gest_items.count(); ++i)
 		{
 			LLViewerInventoryItem *gest_item = gest_items.get(i);
@@ -1755,8 +1754,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// required parts are missing.
 	// Preserve body parts from COF if appending.
 	LLInventoryModel::item_array_t body_items;
-	getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false);
-	getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false);
+	getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART);
+	getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART);
 	if (append)
 		reverse(body_items.begin(), body_items.end());
 	// Reduce body items to max of one per type.
@@ -1766,8 +1765,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// - Wearables: include COF contents only if appending.
 	LLInventoryModel::item_array_t wear_items;
 	if (append)
-		getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false);
-	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false);
+		getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING);
+	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING);
 	// Reduce wearables to max of one per type.
 	removeDuplicateItems(wear_items);
 	filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
@@ -1775,15 +1774,15 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// - Attachments: include COF contents only if appending.
 	LLInventoryModel::item_array_t obj_items;
 	if (append)
-		getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false);
-	getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false);
+		getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT);
+	getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT);
 	removeDuplicateItems(obj_items);
 
 	// - Gestures: include COF contents only if appending.
 	LLInventoryModel::item_array_t gest_items;
 	if (append)
-		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
-	getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false);
+		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE);
+	getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE);
 	removeDuplicateItems(gest_items);
 	
 	// Create links to new COF contents.
@@ -1927,7 +1926,7 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 	S32 to_kill_count = 0;
 
 	LLInventoryModel::item_array_t items;
-	getDescendentsOfAssetType(cat_id, items, type, false);
+	getDescendentsOfAssetType(cat_id, items, type);
 	LLInventoryModel::item_array_t curr_items = items;
 	removeDuplicateItems(items);
 	if (max_items > 0)
@@ -2009,7 +2008,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 	
 	//dumpCat(getCOF(),"COF, start");
 
-	bool follow_folder_links = false;
 	LLUUID current_outfit_id = getCOF();
 
 	// Find all the wearables that are in the COF's subtree.
@@ -2017,7 +2015,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 	LLInventoryModel::item_array_t wear_items;
 	LLInventoryModel::item_array_t obj_items;
 	LLInventoryModel::item_array_t gest_items;
-	getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
+	getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items);
 	// Get rid of non-links in case somehow the COF was corrupted.
 	remove_non_link_items(wear_items);
 	remove_non_link_items(obj_items);
@@ -2113,8 +2111,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 
 void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
 													LLInventoryModel::item_array_t& items,
-													LLAssetType::EType type,
-													bool follow_folder_links)
+													LLAssetType::EType type)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLIsType is_of_type(type);
@@ -2122,15 +2119,13 @@ void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
 									cats,
 									items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_of_type,
-									follow_folder_links);
+									is_of_type);
 }
 
 void LLAppearanceMgr::getUserDescendents(const LLUUID& category, 
 											 LLInventoryModel::item_array_t& wear_items,
 											 LLInventoryModel::item_array_t& obj_items,
-											 LLInventoryModel::item_array_t& gest_items,
-											 bool follow_folder_links)
+											 LLInventoryModel::item_array_t& gest_items)
 {
 	LLInventoryModel::cat_array_t wear_cats;
 	LLFindWearables is_wearable;
@@ -2138,8 +2133,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
 									wear_cats,
 									wear_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_wearable,
-									follow_folder_links);
+									is_wearable);
 
 	LLInventoryModel::cat_array_t obj_cats;
 	LLIsType is_object( LLAssetType::AT_OBJECT );
@@ -2147,8 +2141,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
 									obj_cats,
 									obj_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_object,
-									follow_folder_links);
+									is_object);
 
 	// Find all gestures in this folder
 	LLInventoryModel::cat_array_t gest_cats;
@@ -2157,8 +2150,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
 									gest_cats,
 									gest_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_gesture,
-									follow_folder_links);
+									is_gesture);
 }
 
 void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
@@ -2514,8 +2506,7 @@ void LLAppearanceMgr::removeAllClothesFromAvatar()
 									dummy,
 									clothing_items,
 									LLInventoryModel::EXCLUDE_TRASH,
-									is_clothing,
-									false);
+									is_clothing);
 	uuid_vec_t item_ids;
 	for (LLInventoryModel::item_array_t::iterator it = clothing_items.begin();
 		it != clothing_items.end(); ++it)
@@ -2910,7 +2901,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 
 	// COF is processed if cat_id is not specified
 	LLInventoryModel::item_array_t wear_items;
-	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING, false);
+	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
 
 	wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);
 	divvyWearablesByType(wear_items, items_by_type);
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index b933b4fc50..6c014b1a4b 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -213,14 +213,12 @@ private:
 	
 	void getDescendentsOfAssetType(const LLUUID& category, 
 										  LLInventoryModel::item_array_t& items,
-										  LLAssetType::EType type,
-										  bool follow_folder_links);
+										  LLAssetType::EType type);
 
 	void getUserDescendents(const LLUUID& category, 
 								   LLInventoryModel::item_array_t& wear_items,
 								   LLInventoryModel::item_array_t& obj_items,
-								   LLInventoryModel::item_array_t& gest_items,
-								   bool follow_folder_links);
+								   LLInventoryModel::item_array_t& gest_items);
 
 	void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer<LLInventoryCallback> cb);
 	static void onOutfitRename(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 3d2fcdc494..bbf284147a 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -624,8 +624,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
 											cat_array_t& cats,
 											item_array_t& items,
 											BOOL include_trash,
-											LLInventoryCollectFunctor& add,
-											BOOL follow_folder_links)
+											LLInventoryCollectFunctor& add)
 {
 	// Start with categories
 	if(!include_trash)
@@ -652,36 +651,6 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
 	LLViewerInventoryItem* item = NULL;
 	item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
 
-	// Follow folder links recursively.  Currently never goes more
-	// than one level deep (for current outfit support)
-	// Note: if making it fully recursive, need more checking against infinite loops.
-	if (follow_folder_links && item_array)
-	{
-		S32 count = item_array->count();
-		for(S32 i = 0; i < count; ++i)
-		{
-			item = item_array->get(i);
-			if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER)
-			{
-				LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
-				if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT)
-					// BAP - was 
-					// LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType()))
-					// Change back once ensemble typing is in place.
-				{
-					if(add(linked_cat,NULL))
-					{
-						// BAP should this be added here?  May not
-						// matter if it's only being used in current
-						// outfit traversal.
-						cats.put(LLPointer<LLViewerInventoryCategory>(linked_cat));
-					}
-					collectDescendentsIf(linked_cat->getUUID(), cats, items, include_trash, add, FALSE);
-				}
-			}
-		}
-	}
-	
 	// Move onto items
 	if(item_array)
 	{
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 3aa29bd91d..0b017b7514 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -213,8 +213,7 @@ public:
 							  cat_array_t& categories,
 							  item_array_t& items,
 							  BOOL include_trash,
-							  LLInventoryCollectFunctor& add,
-							  BOOL follow_folder_links = FALSE);
+							  LLInventoryCollectFunctor& add);
 
 	// Collect all items in inventory that are linked to item_id.
 	// Assumes item_id is itself not a linked item.
-- 
cgit v1.2.3


From d807a9162662aa3b921020af2df2c30cc71b1b32 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 22 Apr 2013 16:48:02 -0400
Subject: SH-4128 WIP - more stages of outfit change now go through the
 callback mechanism for link removals

---
 indra/newview/llappearancemgr.cpp | 89 +++++++++++++++++++++++----------------
 indra/newview/llappearancemgr.h   | 17 ++++++--
 2 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index fffec223d7..21af5adf09 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -501,9 +501,11 @@ public:
 	}
 };
 
-LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering):
+LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
+														 bool enforce_item_restrictions):
 	mFireCount(0),
-	mUpdateBaseOrder(update_base_outfit_ordering)
+	mUpdateBaseOrder(update_base_outfit_ordering),
+	mEnforceItemRestrictions(enforce_item_restrictions)
 {
 	selfStartPhase("update_appearance_on_destroy");
 }
@@ -517,7 +519,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 
 		selfStopPhase("update_appearance_on_destroy");
 
-		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder);
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions);
 	}
 }
 
@@ -1660,7 +1662,8 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
 	}
 }
 
-void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer<LLInventoryCallback> cb)
+void LLAppearanceMgr::removeCategoryContents(const LLUUID& category, bool keep_outfit_links,
+											 LLPointer<LLInventoryCallback> cb)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLInventoryModel::item_array_t items;
@@ -1726,6 +1729,18 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
 	}
 }
 
+void LLAppearanceMgr::removeAll(LLInventoryModel::item_array_t& items_to_kill,
+							   LLPointer<LLInventoryCallback> cb)
+{
+	for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin();
+		 it != items_to_kill.end();
+		 ++it)
+	{
+		LLViewerInventoryItem *item = *it;
+		remove_inventory_item(item->getUUID(), cb);
+	}
+}
+
 void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 {
 	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
@@ -1807,8 +1822,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// carried over (e.g. keeping old shape if the new outfit does not
 	// contain one)
 	bool keep_outfit_links = append;
-	purgeCategory(cof, keep_outfit_links, link_waiter);
-	gInventory.notifyObservers();
+	removeCategoryContents(cof, keep_outfit_links, link_waiter);
 
 	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
 }
@@ -1945,34 +1959,20 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 	return to_kill_count;
 }
 	
-												 
-void LLAppearanceMgr::enforceItemRestrictions()
-{
-	S32 purge_count = 0;
-	LLInventoryModel::item_array_t items_to_kill;
-
-	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART,
-											  1, items_to_kill);
-	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING,
-											  LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
-	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT,
-											  -1, items_to_kill);
 
-	if (items_to_kill.size()>0)
-	{
-		for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin();
-			 it != items_to_kill.end();
-			 ++it)
-		{
-			LLViewerInventoryItem *item = *it;
-			LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL;
-			gInventory.purgeObject(item->getUUID());
-		}
-		gInventory.notifyObservers();
-	}
+void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
+													LLInventoryModel::item_array_t& items_to_kill)
+{
+	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART,
+							   1, items_to_kill);
+	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_CLOTHING,
+							   LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
+	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_OBJECT,
+							   -1, items_to_kill);
 }
 
-void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
+void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
+											  bool enforce_item_restrictions)
 {
 	if (mIsInUpdateAppearanceFromCOF)
 	{
@@ -1985,14 +1985,31 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 
 	LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL;
 
+	if (enforce_item_restrictions)
+	{
+		LLInventoryModel::item_array_t items_to_kill;
+		findAllExcessOrDuplicateItems(getCOF(), items_to_kill);
+		if (items_to_kill.size()>0)
+		{
+			// The point here is just to call
+			// updateAppearanceFromCOF() again after excess items
+			// have been removed. That time we will set
+			// enforce_item_restrictions to false so we don't get
+			// caught in a perpetual loop.
+			LLPointer<LLInventoryCallback> cb(
+				new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false));
+
+			// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
+			// this should catch anything that gets through.
+			removeAll(items_to_kill, cb);
+			return;
+		}
+	}
+
 	//checking integrity of the COF in terms of ordering of wearables, 
 	//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
 	updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering);
 
-	// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
-	// this should catch anything that gets through.
-	enforceItemRestrictions();
-	
 	// update dirty flag to see if the state of the COF matches
 	// the saved outfit stored as a folder link
 	updateIsDirty();
@@ -2804,7 +2821,7 @@ bool LLAppearanceMgr::updateBaseOutfit()
 	updateClothingOrderingInfo();
 
 	// in a Base Outfit we do not remove items, only links
-	purgeCategory(base_outfit_id, false, NULL);
+	removeCategoryContents(base_outfit_id, false, NULL);
 
 	LLPointer<LLInventoryCallback> dirty_state_updater =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 6c014b1a4b..0cc06ab210 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -49,7 +49,8 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 public:
 	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
 
-	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false);
+	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false,
+								 bool enforce_item_restrictions = true);
 	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
@@ -65,7 +66,8 @@ public:
 								   LLAssetType::EType type,
 								   S32 max_items,
 								   LLInventoryModel::item_array_t& items_to_kill);
-	void enforceItemRestrictions();
+	void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
+									  LLInventoryModel::item_array_t& items_to_kill);
 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
@@ -129,6 +131,10 @@ public:
 				 LLInventoryModel::item_array_t& items,
 				 LLPointer<LLInventoryCallback> cb);
 
+	// And bulk removal.
+	void removeAll(LLInventoryModel::item_array_t& items,
+				   LLPointer<LLInventoryCallback> cb);
+
 	// Add COF link to individual item.
 	void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
 	void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
@@ -220,7 +226,8 @@ private:
 								   LLInventoryModel::item_array_t& obj_items,
 								   LLInventoryModel::item_array_t& gest_items);
 
-	void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer<LLInventoryCallback> cb);
+	void removeCategoryContents(const LLUUID& category, bool keep_outfit_links,
+								LLPointer<LLInventoryCallback> cb);
 	static void onOutfitRename(const LLSD& notification, const LLSD& response);
 
 	void setOutfitLocked(bool locked);
@@ -254,13 +261,15 @@ public:
 class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 {
 public:
-	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false);
+	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false,
+								bool enforce_item_restrictions = true);
 	virtual ~LLUpdateAppearanceOnDestroy();
 	/* virtual */ void fire(const LLUUID& inv_item);
 
 private:
 	U32 mFireCount;
 	bool mUpdateBaseOrder;
+	bool mEnforceItemRestrictions;
 };
 
 
-- 
cgit v1.2.3


From 1bf66885617564c8df9baac3b45ed5e9d96ef153 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 23 Apr 2013 15:52:12 -0400
Subject: SH-4128 WIP - rewiring various link-deleting operations to support
 callbacks

---
 indra/newview/llagentwearables.cpp  |   9 +-
 indra/newview/llappearancemgr.cpp   | 203 ++++++++++++------------------------
 indra/newview/llappearancemgr.h     |  27 +++--
 indra/newview/llfloatergesture.cpp  |   2 +-
 indra/newview/llpaneloutfitedit.cpp |   4 +-
 indra/newview/llviewerinventory.h   |   2 +-
 6 files changed, 95 insertions(+), 152 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index c88694ef76..b4c3e33e0e 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -69,7 +69,7 @@ void wear_and_edit_cb(const LLUUID& inv_item)
 	gAgentWearables.requestEditingWearable(inv_item);
 	
 	// Wear it.
-	LLAppearanceMgr::instance().wearItemOnAvatar(inv_item);
+	LLAppearanceMgr::instance().wearItemOnAvatar(inv_item,true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -239,7 +239,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i
 	}
 	if (mTodo & CALL_RECOVERDONE)
 	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item,false);
+		LLAppearanceMgr::instance().addCOFItemLink(inv_item);
 		gAgentWearables.recoverMissingWearableDone();
 	}
 	/*
@@ -247,7 +247,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i
 	 */
 	if (mTodo & CALL_CREATESTANDARDDONE)
 	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item,false);
+		LLAppearanceMgr::instance().addCOFItemLink(inv_item);
 		gAgentWearables.createStandardWearablesDone(mType, mIndex);
 	}
 	if (mTodo & CALL_MAKENEWOUTFITDONE)
@@ -256,7 +256,8 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i
 	}
 	if (mTodo & CALL_WEARITEM)
 	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription);
+		LLAppearanceMgr::instance().addCOFItemLink(inv_item, 
+			new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription);
 	}
 }
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 21af5adf09..634f5d1389 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -421,86 +421,6 @@ public:
 	}
 };
 
-class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr
-{
-public:
-	LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items,
-								const LLUUID& dst_cat_id,
-								const std::string& phase_name,
-								nullary_func_t on_completion_func,
-								nullary_func_t on_failure_func = no_op,
-								 F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL,
-								 S32 max_retries = DEFAULT_MAX_RETRIES
-		):
-		LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries)
-	{
-		addItems(src_items);
-	}
-	
-	virtual bool requestOperation(const LLUUID& item_id)
-	{
-		bool request_sent = false;
-		LLViewerInventoryItem *item = gInventory.getItem(item_id);
-		if (item)
-		{
-			if (item->getParentUUID() == mDstCatID)
-			{
-				LL_DEBUGS("Avatar") << "item " << item_id << " name " << item->getName() << " is already a child of " << mDstCatID << llendl;
-				return false;
-			}
-			LL_DEBUGS("Avatar") << "linking item " << item_id << " name " << item->getName() << " to " << mDstCatID << llendl;
-			// create an inventory item link.
-			if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate"))
-			{
-				LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl;
-				return true;
-			}
-			link_inventory_item(gAgent.getID(),
-								item->getLinkedUUID(),
-								mDstCatID,
-								item->getName(),
-								item->getActualDescription(),
-								LLAssetType::AT_LINK,
-								new LLBoostFuncInventoryCallback(
-									boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer())));
-			return true;
-		}
-		else
-		{
-			// create a base outfit link if appropriate.
-			LLViewerInventoryCategory *catp = gInventory.getCategory(item_id);
-			if (!catp)
-			{
-				llwarns << "link request failed, id not found as inventory item or category " << item_id << llendl;
-				return false;
-			}
-			const LLUUID cof = LLAppearanceMgr::instance().getCOF();
-			std::string new_outfit_name = "";
-
-			LLAppearanceMgr::instance().purgeBaseOutfitLink(cof);
-
-			if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
-			{
-				if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate"))
-				{
-					LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl;
-					return true;
-				}
-				LL_DEBUGS("Avatar") << "linking folder " << item_id << " name " << catp->getName() << " to cof " << cof << llendl;
-				link_inventory_item(gAgent.getID(), item_id, cof, catp->getName(), "",
-									LLAssetType::AT_LINK_FOLDER, 
-									new LLBoostFuncInventoryCallback(
-										boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer())));
-				new_outfit_name = catp->getName();
-				request_sent = true;
-			}
-	
-			LLAppearanceMgr::instance().updatePanelOutfitName(new_outfit_name);
-		}
-		return request_sent;
-	}
-};
-
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
 														 bool enforce_item_restrictions):
 	mFireCount(0),
@@ -533,6 +453,32 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
 	mFireCount++;
 }
 
+LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id):
+	mItemID(item_id)
+{
+}
+
+LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy()
+{
+	LLAppearanceMgr::instance().updateAppearanceFromCOF();
+	
+	// Start editing the item if previously requested.
+	gAgentWearables.editWearableIfRequested(mItemID);
+	
+	// TODO: camera mode may not be changed if a debug setting is tweaked
+	if( gAgentCamera.cameraCustomizeAvatar() )
+	{
+		// If we're in appearance editing mode, the current tab may need to be refreshed
+		LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(
+			LLFloaterSidePanelContainer::getPanel("appearance"));
+		if (panel)
+		{
+			panel->showDefaultSubpart();
+		}
+	}
+}
+
+
 struct LLFoundData
 {
 	LLFoundData() :
@@ -1272,8 +1218,12 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false)
 	}
 }
 
-bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer<LLInventoryCallback> cb)
+bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
+									   bool do_update,
+									   bool replace,
+									   LLPointer<LLInventoryCallback> cb)
 {
+
 	if (item_id_to_wear.isNull()) return false;
 
 	// *TODO: issue with multi-wearable should be fixed:
@@ -1320,7 +1270,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 			{
 				removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1));
 			}
-			addCOFItemLink(item_to_wear, do_update, cb);
+			if (!cb && do_update)
+			{
+				cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+			}
+			addCOFItemLink(item_to_wear, cb);
 		} 
 		break;
 	case LLAssetType::AT_BODYPART:
@@ -1329,8 +1283,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 		// Remove the existing wearables of the same type.
 		// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
 		removeCOFLinksOfType(item_to_wear->getWearableType());
-
-		addCOFItemLink(item_to_wear, do_update, cb);
+		if (!cb && do_update)
+		{
+			cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+		}
+		addCOFItemLink(item_to_wear, cb);
 		break;
 	case LLAssetType::AT_OBJECT:
 		rez_attachment(item_to_wear, NULL, replace);
@@ -1640,7 +1597,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
 	return items.size() > 0;
 }
 
-void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
+void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLInventoryModel::item_array_t items;
@@ -1656,7 +1613,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
 			LLViewerInventoryCategory* catp = item->getLinkedCategory();
 			if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
 			{
-				gInventory.purgeObject(item->getUUID());
+				remove_inventory_item(item->getUUID(), cb);
 			}
 		}
 	}
@@ -1843,7 +1800,7 @@ void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointer<LLI
 	LLViewerInventoryCategory* catp = gInventory.getCategory(category);
 	std::string new_outfit_name = "";
 
-	purgeBaseOutfitLink(cof);
+	purgeBaseOutfitLink(cof, link_waiter);
 
 	if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
 	{
@@ -2339,9 +2296,8 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor
 class LLDeferredCOFLinkObserver: public LLInventoryObserver
 {
 public:
-	LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer<LLInventoryCallback> cb = NULL, std::string description = ""):
+	LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL, std::string description = ""):
 		mItemID(item_id),
-		mDoUpdate(do_update),
 		mCallback(cb),
 		mDescription(description)
 	{
@@ -2357,14 +2313,13 @@ public:
 		if (item)
 		{
 			gInventory.removeObserver(this);
-			LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate,mCallback);
+			LLAppearanceMgr::instance().addCOFItemLink(item, mCallback);
 			delete this;
 		}
 	}
 
 private:
 	const LLUUID mItemID;
-	bool mDoUpdate;
 	std::string mDescription;
 	LLPointer<LLInventoryCallback> mCallback;
 };
@@ -2372,42 +2327,26 @@ private:
 
 // BAP - note that this runs asynchronously if the item is not already loaded from inventory.
 // Dangerous if caller assumes link will exist after calling the function.
-void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer<LLInventoryCallback> cb, const std::string description)
+void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id,
+									 LLPointer<LLInventoryCallback> cb,
+									 const std::string description)
 {
 	const LLInventoryItem *item = gInventory.getItem(item_id);
 	if (!item)
 	{
-		LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb, description);
+		LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, cb, description);
 		gInventory.addObserver(observer);
 	}
 	else
 	{
-		addCOFItemLink(item, do_update, cb, description);
+		addCOFItemLink(item, cb, description);
 	}
 }
 
-void modified_cof_cb(const LLUUID& inv_item)
-{
-	LLAppearanceMgr::instance().updateAppearanceFromCOF();
-
-	// Start editing the item if previously requested.
-	gAgentWearables.editWearableIfRequested(inv_item);
-
-	// TODO: camera mode may not be changed if a debug setting is tweaked
-	if( gAgentCamera.cameraCustomizeAvatar() )
-	{
-		// If we're in appearance editing mode, the current tab may need to be refreshed
-		LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance"));
-		if (panel)
-		{
-			panel->showDefaultSubpart();
-		}
-	}
-}
-
-void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer<LLInventoryCallback> cb, const std::string description)
+void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
+									 LLPointer<LLInventoryCallback> cb,
+									 const std::string description)
 {		
-	std::string link_description = description;
 	const LLViewerInventoryItem *vitem = dynamic_cast<const LLViewerInventoryItem*>(item);
 	if (!vitem)
 	{
@@ -2447,30 +2386,19 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
 			++count;
 			if (is_body_part && inv_item->getIsLinkType()  && (vitem->getWearableType() == wearable_type))
 			{
-				gInventory.purgeObject(inv_item->getUUID());
+				remove_inventory_item(inv_item->getUUID(), cb);
 			}
 			else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
 			{
 				// MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
-				gInventory.purgeObject(inv_item->getUUID());
+				remove_inventory_item(inv_item->getUUID(), cb);
 			}
 		}
 	}
 
-	if (linked_already)
+	if (!linked_already)
 	{
-		if (do_update)
-		{	
-			LLAppearanceMgr::updateAppearanceFromCOF();
-		}
-		return;
-	}
-	else
-	{
-		if(do_update && cb.isNull())
-		{
-			cb = new LLBoostFuncInventoryCallback(modified_cof_cb);
-		}
+		std::string link_description = description;
 		if (vitem->getIsLinkType())
 		{
 			link_description = vitem->getActualDescription();
@@ -2483,7 +2411,6 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
 							 LLAssetType::AT_LINK,
 							 cb);
 	}
-	return;
 }
 
 LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id)
@@ -2567,7 +2494,7 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar()
 	removeItemsFromAvatar(ids_to_remove);
 }
 
-void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id)
+void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb)
 {
 	gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
 
@@ -2582,12 +2509,12 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id)
 		const LLInventoryItem* item = item_array.get(i).get();
 		if (item->getIsLinkType() && item->getLinkedUUID() == item_id)
 		{
-			gInventory.purgeObject(item->getUUID());
+			remove_inventory_item(item->getUUID(), cb);
 		}
 	}
 }
 
-void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type)
+void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, LLPointer<LLInventoryCallback> cb)
 {
 	LLFindWearablesOfType filter_wearables_of_type(type);
 	LLInventoryModel::cat_array_t cats;
@@ -2600,7 +2527,7 @@ void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type)
 		const LLViewerInventoryItem* item = *it;
 		if (item->getIsLinkType()) // we must operate on links only
 		{
-			gInventory.purgeObject(item->getUUID());
+			remove_inventory_item(item->getUUID(), cb);
 		}
 	}
 }
@@ -3550,7 +3477,7 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
 		   // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF.
 		   // it will trigger gAgentWariables.notifyLoadingFinished()
 		   // But it is not acceptable solution. See EXT-7777
-		   LLAppearanceMgr::addCOFItemLink(item_id, false);  // Add COF link for item.
+		   LLAppearanceMgr::addCOFItemLink(item_id);  // Add COF link for item.
 	   }
 	   else
 	   {
@@ -3586,8 +3513,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id)
 	 gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
 									 cats,
 									 items,
-	 LLInventoryModel::EXCLUDE_TRASH,
-	 find_links);
+									 LLInventoryModel::EXCLUDE_TRASH,
+									 find_links);
 
 	 return !items.empty();
 }
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 0cc06ab210..2cc76c4b4c 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -107,12 +107,13 @@ public:
 	const LLUUID getBaseOutfitUUID();
 
 	// Wear/attach an item (from a user's inventory) on the agent
-	bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update = true, bool replace = false, LLPointer<LLInventoryCallback> cb = NULL);
+	bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
+						  LLPointer<LLInventoryCallback> cb = NULL);
 
 	// Update the displayed outfit name in UI.
 	void updatePanelOutfitName(const std::string& name);
 
-	void purgeBaseOutfitLink(const LLUUID& category);
+	void purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb = NULL);
 	void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter);
 
 	void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
@@ -136,15 +137,15 @@ public:
 				   LLPointer<LLInventoryCallback> cb);
 
 	// Add COF link to individual item.
-	void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
-	void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
+	void addCOFItemLink(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
+	void addCOFItemLink(const LLInventoryItem *item, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
 
 	// Find COF entries referencing the given item.
 	LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id);
 
 	// Remove COF entries
-	void removeCOFItemLinks(const LLUUID& item_id);
-	void removeCOFLinksOfType(LLWearableType::EType type);
+	void removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL);
+	void removeCOFLinksOfType(LLWearableType::EType type, LLPointer<LLInventoryCallback> cb = NULL);
 	void removeAllClothesFromAvatar();
 	void removeAllAttachmentsFromAvatar();
 
@@ -272,6 +273,20 @@ private:
 	bool mEnforceItemRestrictions;
 };
 
+class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback
+{
+public:
+	LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id);
+
+	/* virtual */ void fire(const LLUUID& item_id) {}
+
+	~LLUpdateAppearanceAndEditWearableOnDestroy();
+	
+private:
+	LLUUID mItemID;
+};
+
+class 
 
 #define SUPPORT_ENSEMBLES 0
 
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index 56051ff684..def4d40f9f 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -619,7 +619,7 @@ void LLFloaterGesture::addToCurrentOutFit()
 	LLAppearanceMgr* am = LLAppearanceMgr::getInstance();
 	for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
 	{
-		am->addCOFItemLink(*it);
+		am->addCOFItemLink(*it, new LLUpdateAppearanceAndEditWearableOnDestroy(*it));
 	}
 }
 
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index c09d4393c8..0e3057dcad 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -1184,12 +1184,12 @@ BOOL LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 			 * second argument is used to delay the appearance update until all dragged items
 			 * are added to optimize user experience.
 			 */
-			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), false);
+			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID());
 		}
 		else
 		{
 			// if asset id is not available for the item we must wear it immediately (attachments only)
-			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), true);
+			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), new LLUpdateAppearanceAndEditWearableOnDestroy(item->getUUID()));
 		}
 	}
 
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 7cb62efb47..6b0e8ed4ef 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -274,7 +274,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback
 {
 public:
 
-	LLBoostFuncInventoryCallback(inventory_func_type fire_func,
+	LLBoostFuncInventoryCallback(inventory_func_type fire_func = no_op_inventory_func,
 								 nullary_func_type destroy_func = no_op):
 		mFireFunc(fire_func),
 		mDestroyFunc(destroy_func)
-- 
cgit v1.2.3


From 4967998a5c10abcc64e097a4e95505f9adbe4de7 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 24 Apr 2013 13:27:04 -0400
Subject: CHUI-849 WIP, SH-4116 WIP - added simpler match check in inventory
 for when we don't need the list of matches to be returned.

---
 indra/newview/llappearancemgr.cpp  | 61 +++++++++-----------------------------
 indra/newview/llinventorymodel.cpp | 59 ++++++++++++++++++++++++++++++------
 indra/newview/llinventorymodel.h   |  3 ++
 3 files changed, 67 insertions(+), 56 deletions(-)
 mode change 100644 => 100755 indra/newview/llinventorymodel.h

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 634f5d1389..5a9901f12d 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1541,15 +1541,8 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id)
 // static
 bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id)
 {
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
 	LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false);
-	gInventory.collectDescendentsIf(outfit_cat_id,
-		cats,
-		items,
-		LLInventoryModel::EXCLUDE_TRASH,
-		is_worn);
-	return items.size() > 0;
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn);
 }
 
 // static
@@ -1560,15 +1553,8 @@ bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id)
 		return false;
 	}
 
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
 	LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
-	gInventory.collectDescendentsIf(outfit_cat_id,
-		cats,
-		items,
-		LLInventoryModel::EXCLUDE_TRASH,
-		not_worn);
-	return items.size() > 0;
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn);
 }
 
 bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
@@ -1586,15 +1572,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
 	}
 
 	// Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
 	LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
-	gInventory.collectDescendentsIf(outfit_cat_id,
-		cats,
-		items,
-		LLInventoryModel::EXCLUDE_TRASH,
-		is_worn);
-	return items.size() > 0;
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn);
 }
 
 void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb)
@@ -2243,6 +2222,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
 	LLAppearanceMgr::changeOutfit(TRUE, category->getUUID(), append);
 }
 
+// FIXME do we really want to search entire inventory for matching name?
 void LLAppearanceMgr::wearOutfitByName(const std::string& name)
 {
 	LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL;
@@ -3501,22 +3481,21 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
 
 BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
 {
-	return gInventory.isObjectDescendentOf(obj_id, getCOF());
+	const LLUUID& cof = getCOF();
+	if (obj_id == cof)
+		return TRUE;
+	const LLInventoryObject* obj = gInventory.getObject(obj_id);
+	if (obj && obj->getParentUUID() == cof)
+		return TRUE;
+	return FALSE;
 }
 
 // static
 bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id)
 {
-	 LLInventoryModel::cat_array_t cats;
-	 LLInventoryModel::item_array_t items;
-	 LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id));
-	 gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
-									 cats,
-									 items,
-									 LLInventoryModel::EXCLUDE_TRASH,
-									 find_links);
-
-	 return !items.empty();
+	const LLUUID& target_id = gInventory.getLinkedItemID(obj_id);
+	LLLinkedItemIDMatches find_links(target_id);
+	return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links);
 }
 
 BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
@@ -3533,18 +3512,6 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
 	// For now, don't allow direct deletion from the COF.  Instead, force users
 	// to choose "Detach" or "Take Off".
 	return TRUE;
-	/*
-	const LLInventoryObject *obj = gInventory.getObject(obj_id);
-	if (!obj) return FALSE;
-
-	// Can't delete bodyparts, since this would be equivalent to removing the item.
-	if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE;
-
-	// Can't delete the folder link, since this is saved for bookkeeping.
-	if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE;
-
-	return FALSE;
-	*/
 }
 
 class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index bbf284147a..11223d96b6 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -593,6 +593,40 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 	return id;
 }
 
+// This is optimized for the case that we just want to know whether a
+// category has any immediate children meeting a condition, without
+// needing to recurse or build up any lists.
+bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id,
+												   LLInventoryCollectFunctor& filter)
+{
+	LLInventoryModel::cat_array_t *cats;
+	LLInventoryModel::item_array_t *items;
+	getDirectDescendentsOf(cat_id, cats, items);
+	if (cats)
+	{
+		for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin();
+			 it != cats->end(); ++it)
+		{
+			if (filter(*it,NULL))
+			{
+				return true;
+			}
+		}
+	}
+	if (items)
+	{
+		for (LLInventoryModel::item_array_t::const_iterator it = items->begin();
+			 it != items->end(); ++it)
+		{
+			if (filter(NULL,*it))
+			{
+				return true;
+			}
+		}
+	}
+	return false;
+}
+												  
 // Starting with the object specified, add it's descendents to the
 // array provided, but do not add the inventory object specified by
 // id. There is no guaranteed order. Neither array will be erased
@@ -723,6 +757,10 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID
 																	const LLUUID& start_folder_id)
 {
 	item_array_t items;
+	const LLInventoryObject *obj = getObject(id);
+	if (!obj || obj->getIsLinkType())
+		return items;
+	
 	LLInventoryModel::cat_array_t cat_array;
 	LLLinkedItemIDMatches is_linked_item_match(id);
 	collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id),
@@ -1170,17 +1208,20 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
 
 	// REBUILD is expensive, so clear the current change list first else
 	// everything else on the changelist will also get rebuilt.
-	gInventory.notifyObservers();
-	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
-		 iter != item_array.end();
-		 iter++)
+	if (item_array.size())
 	{
-		const LLViewerInventoryItem *linked_item = (*iter);
-		const LLUUID &item_id = linked_item->getUUID();
-		if (item_id == baseobj_id) continue;
-		addChangedMask(LLInventoryObserver::REBUILD, item_id);
+		gInventory.notifyObservers();
+		for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+			iter != item_array.end();
+			iter++)
+		{
+			const LLViewerInventoryItem *linked_item = (*iter);
+			const LLUUID &item_id = linked_item->getUUID();
+			if (item_id == baseobj_id) continue;
+			addChangedMask(LLInventoryObserver::REBUILD, item_id);
+		}
+		gInventory.notifyObservers();
 	}
-	gInventory.notifyObservers();
 }
 
 // This is a method which collects the descendents of the id
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
old mode 100644
new mode 100755
index 0b017b7514..50b57ea08d
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -205,6 +205,9 @@ public:
 		EXCLUDE_TRASH = FALSE, 
 		INCLUDE_TRASH = TRUE 
 	};
+	// Simpler existence test if matches don't actually need to be collected.
+	bool hasMatchingDirectDescendent(const LLUUID& cat_id,
+									 LLInventoryCollectFunctor& filter);
 	void collectDescendents(const LLUUID& id,
 							cat_array_t& categories,
 							item_array_t& items,
-- 
cgit v1.2.3


From a9fa707a7da9977914db8527f15b59bb6a4bc6b7 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 24 Apr 2013 16:09:33 -0400
Subject: SH-4128 - more cleanup of COF-link manipulating functions

---
 indra/newview/llappearancemgr.cpp  | 60 +++++++++++++++++++-------------------
 indra/newview/llfloatergesture.cpp |  3 +-
 2 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 5a9901f12d..792220c385 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -430,6 +430,16 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit
 	selfStartPhase("update_appearance_on_destroy");
 }
 
+void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
+{
+	LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
+	const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL;
+#endif
+	mFireCount++;
+}
+
 LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 {
 	if (!LLApp::isExiting())
@@ -443,16 +453,6 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 	}
 }
 
-void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
-{
-	LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
-	const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-	LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL;
-#endif
-	mFireCount++;
-}
-
 LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id):
 	mItemID(item_id)
 {
@@ -460,20 +460,23 @@ LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnD
 
 LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy()
 {
-	LLAppearanceMgr::instance().updateAppearanceFromCOF();
-	
-	// Start editing the item if previously requested.
-	gAgentWearables.editWearableIfRequested(mItemID);
-	
-	// TODO: camera mode may not be changed if a debug setting is tweaked
-	if( gAgentCamera.cameraCustomizeAvatar() )
+	if (!LLApp::isExiting())
 	{
-		// If we're in appearance editing mode, the current tab may need to be refreshed
-		LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(
-			LLFloaterSidePanelContainer::getPanel("appearance"));
-		if (panel)
+		LLAppearanceMgr::instance().updateAppearanceFromCOF();
+		
+		// Start editing the item if previously requested.
+		gAgentWearables.editWearableIfRequested(mItemID);
+		
+		// TODO: camera mode may not be changed if a debug setting is tweaked
+		if( gAgentCamera.cameraCustomizeAvatar() )
 		{
-			panel->showDefaultSubpart();
+			// If we're in appearance editing mode, the current tab may need to be refreshed
+			LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(
+				LLFloaterSidePanelContainer::getPanel("appearance"));
+			if (panel)
+			{
+				panel->showDefaultSubpart();
+			}
 		}
 	}
 }
@@ -1587,13 +1590,10 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLIn
 		LLViewerInventoryItem *item = items.get(i);
 		if (item->getActualType() != LLAssetType::AT_LINK_FOLDER)
 			continue;
-		if (item->getIsLinkType())
+		LLViewerInventoryCategory* catp = item->getLinkedCategory();
+		if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
 		{
-			LLViewerInventoryCategory* catp = item->getLinkedCategory();
-			if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
-			{
-				remove_inventory_item(item->getUUID(), cb);
-			}
+			remove_inventory_item(item->getUUID(), cb);
 		}
 	}
 }
@@ -2276,7 +2276,7 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor
 class LLDeferredCOFLinkObserver: public LLInventoryObserver
 {
 public:
-	LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL, std::string description = ""):
+	LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb, const std::string& description):
 		mItemID(item_id),
 		mCallback(cb),
 		mDescription(description)
@@ -2293,7 +2293,7 @@ public:
 		if (item)
 		{
 			gInventory.removeObserver(this);
-			LLAppearanceMgr::instance().addCOFItemLink(item, mCallback);
+			LLAppearanceMgr::instance().addCOFItemLink(item, mCallback, mDescription);
 			delete this;
 		}
 	}
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index def4d40f9f..af5c11e12c 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -617,9 +617,10 @@ void LLFloaterGesture::addToCurrentOutFit()
 	uuid_vec_t ids;
 	getSelectedIds(ids);
 	LLAppearanceMgr* am = LLAppearanceMgr::getInstance();
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
 	for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
 	{
-		am->addCOFItemLink(*it, new LLUpdateAppearanceAndEditWearableOnDestroy(*it));
+		am->addCOFItemLink(*it, cb);
 	}
 }
 
-- 
cgit v1.2.3


From cafb5b0d4738aa8e161461e89ac4c5831706065d Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Wed, 24 Apr 2013 21:55:03 +0000
Subject: updating appearance utility source package

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 80a44ec75d..95fb5a9629 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>5bc44db15eb3cca021382e40e04a9a38</string>
+              <string>419c3634dd982e8855785ce36f22892e</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/271972/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130315.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/274704/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130424.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From eb88e4d37850a48132193d332fa8945d3932369b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 24 Apr 2013 18:08:20 -0400
Subject: SH-4128 WIP - cleanup around item link removal and callbacks

---
 indra/newview/llappearancemgr.cpp     | 24 ++++++++++++++----------
 indra/newview/llgesturemgr.cpp        | 13 ++++++++++---
 indra/newview/llinventorymodel.cpp    |  5 +++--
 indra/newview/llpaneleditwearable.cpp | 23 ++++++++++++++++++-----
 4 files changed, 45 insertions(+), 20 deletions(-)
 mode change 100644 => 100755 indra/newview/llgesturemgr.cpp
 mode change 100644 => 100755 indra/newview/llpaneleditwearable.cpp

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 792220c385..399cea676c 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1265,18 +1265,21 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
 	switch (item_to_wear->getType())
 	{
 	case LLAssetType::AT_CLOTHING:
-		if (gAgentWearables.areWearablesLoaded())
+	if (gAgentWearables.areWearablesLoaded())
 		{
+			if (!cb && do_update)
+			{
+				cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+			}
 			S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
 			if ((replace && wearable_count != 0) ||
 				(wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
 			{
-				removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1));
-			}
-			if (!cb && do_update)
-			{
-				cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+				LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(),
+																   wearable_count-1);
+				removeCOFItemLinks(item_id, cb);
 			}
+
 			addCOFItemLink(item_to_wear, cb);
 		} 
 		break;
@@ -3284,21 +3287,22 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
 	if (ids_to_remove.empty())
 	{
 		llwarns << "called with empty list, nothing to do" << llendl;
+		return;
 	}
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
 	for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it)
 	{
 		const LLUUID& id_to_remove = *it;
 		const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove);
-		removeCOFItemLinks(linked_item_id);
+		removeCOFItemLinks(linked_item_id, cb);
 	}
-	updateAppearanceFromCOF();
 }
 
 void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
 {
 	LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove);
-	removeCOFItemLinks(linked_item_id);
-	updateAppearanceFromCOF();
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
+	removeCOFItemLinks(linked_item_id, cb);
 }
 
 bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body)
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
old mode 100644
new mode 100755
index 9aa86297fc..5eaa83d872
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -299,6 +299,12 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id,
 }
 
 
+void notify_update_label(const LLUUID& base_item_id)
+{
+	gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
+	LLGestureMgr::instance().notifyObservers();
+}
+
 void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
 {
 	const LLUUID& base_item_id = get_linked_uuid(item_id);
@@ -322,7 +328,6 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
 	}
 
 	mActive.erase(it);
-	gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
 
 	// Inform the database of this change
 	LLMessageSystem* msg = gMessageSystem;
@@ -338,9 +343,11 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
 
 	gAgent.sendReliableMessage();
 
-	LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id);
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func,
+										 boost::bind(notify_update_label,base_item_id));
 
-	notifyObservers();
+	LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, cb);
 }
 
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 11223d96b6..bc327b8359 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1178,10 +1178,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 		mParentChildCategoryTree.erase(id);
 	}
 	addChangedMask(LLInventoryObserver::REMOVE, id);
-	bool is_link_type = obj->getIsLinkType();
 	obj = NULL; // delete obj
+
 	// Can't have links to links, so there's no need for this update
 	// if the item removed is a link.
+	bool is_link_type = obj->getIsLinkType();
 	if (!is_link_type)
 	{
 		updateLinkedObjectsFromPurge(id);
@@ -1208,7 +1209,7 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
 
 	// REBUILD is expensive, so clear the current change list first else
 	// everything else on the changelist will also get rebuilt.
-	if (item_array.size())
+	if (item_array.size() > 0)
 	{
 		gInventory.notifyObservers();
 		for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
old mode 100644
new mode 100755
index e71dba5cae..06c923273b
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1079,10 +1079,15 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 
         if (force_save_as)
         {
-                // the name of the wearable has changed, re-save wearable with new name
-                LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID());
+			// FIXME race condition if removeCOFItemLinks does not
+			// complete immediately.  Looks like we're counting on the
+			// fact that updateAppearanceFromCOF will get called after
+			// we exit customize mode.
+
+			// the name of the wearable has changed, re-save wearable with new name
+			LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID());
 			gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE);
-                mNameEditor->setText(mWearableItem->getName());
+			mNameEditor->setText(mWearableItem->getName());
         }
         else
         {
@@ -1091,6 +1096,14 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 			// version so texture baking service knows appearance has changed.
 			if (link_item)
 			{
+				// FIXME - two link-modifying calls here plus one
+				// inventory change request, none of which use a
+				// callback. When does a new appearance request go out
+				// and how is it synced with these changes?  As above,
+				// we seem to be implicitly depending on
+				// updateAppearanceFromCOF() to be called when we
+				// exit customize mode.
+
 				// Create new link
 				link_inventory_item( gAgent.getID(),
 									 link_item->getLinkedUUID(),
@@ -1100,9 +1113,9 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 									 LLAssetType::AT_LINK,
 									 NULL);
 				// Remove old link
-				gInventory.purgeObject(link_item->getUUID());
+				remove_inventory_item(link_item->getUUID());
 			}
-                gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
+			gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
         }
 
 	
-- 
cgit v1.2.3


From d73588eaddb1ada6ac896850c3aa9d25307e076a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 24 Apr 2013 18:38:40 -0400
Subject: SH-4128 WIP - misc cleanup

---
 indra/newview/llinventorymodel.cpp    | 4 ++--
 indra/newview/llpaneleditwearable.cpp | 2 +-
 indra/newview/llviewerinventory.cpp   | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index bc327b8359..a0b9e7b0ec 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1178,11 +1178,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 		mParentChildCategoryTree.erase(id);
 	}
 	addChangedMask(LLInventoryObserver::REMOVE, id);
-	obj = NULL; // delete obj
-
+	
 	// Can't have links to links, so there's no need for this update
 	// if the item removed is a link.
 	bool is_link_type = obj->getIsLinkType();
+	obj = NULL; // delete obj
 	if (!is_link_type)
 	{
 		updateLinkedObjectsFromPurge(id);
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 06c923273b..580e31591c 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1113,7 +1113,7 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 									 LLAssetType::AT_LINK,
 									 NULL);
 				// Remove old link
-				remove_inventory_item(link_item->getUUID());
+				remove_inventory_item(link_item->getUUID(), NULL);
 			}
 			gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
         }
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 316fca7769..06efeb86d9 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1276,7 +1276,7 @@ void remove_inventory_item(
 	}
 	else
 	{
-		llwarns << "remove_inventory_item called for nonexistent item " << item_id << llendl;
+		llwarns << "remove_inventory_item called for invalid or nonexistent item " << item_id << llendl;
 	}
 }
 
-- 
cgit v1.2.3


From d58b9ee54e84b709e063cdbbc349de25feafa59b Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Thu, 25 Apr 2013 14:09:42 -0400
Subject: SH-4050 FIX camera goes underground if hover set low enough

Changing viewer limit for avatar height to match server limit, camera does not go underground.
Also clarified where we do not need avatar offset in the code, through comments
---
 indra/llappearance/llavatarappearance.cpp | 8 +++++---
 indra/newview/llvoavatar.cpp              | 4 +++-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 3bb759d458..0196558a5a 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -491,11 +491,13 @@ void LLAvatarAppearance::computeBodySize()
 	// Certain configurations of avatars can force the overall height (with offset) to go negative.
 	// Enforce a constraint to make sure we don't go below 0.1 meters.
 	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
-	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f) 
+	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 1.1f) 
 	{
-		mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail.
+		F32 old_offset = mAvatarOffset.mV[VZ];
+		F32 old_effective_height = new_body_size.mV[VZ] + mAvatarOffset.mV[VZ];
+		mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 1.11f); // avoid floating point rounding making the above check continue to fail.
 
-		llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f);
+		llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 1.1f);
 
 		if (mWearableData && isSelf()) 
 		{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 0475e9fc89..bf6e28b93d 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2144,7 +2144,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 		{
 			LLVector3 tagPos = mRoot->getWorldPosition();
 			tagPos[VZ] -= mPelvisToFoot;
-			tagPos[VZ] += ( mBodySize[VZ] + 0.125f );
+			tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); // does not need mAvatarOffset -Nyx
 			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );
 		}
 	}//if ( voiceEnabled )
@@ -2885,6 +2885,8 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
 	local_camera_up.normalize();
 	local_camera_up = local_camera_up * inv_root_rot;
 
+
+	// position is based on head position, does not require mAvatarOffset here. - Nyx
 	LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f,
 								mBodySize.mV[VY] * 0.4f,
 								mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT);
-- 
cgit v1.2.3


From f35a229281c1b9dbec1f6f939e97344ed86d5429 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Thu, 25 Apr 2013 16:17:01 -0400
Subject: BUILDFIX: removing unused variables

---
 indra/llappearance/llavatarappearance.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 0196558a5a..0a15f06bfd 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -493,8 +493,6 @@ void LLAvatarAppearance::computeBodySize()
 	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
 	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 1.1f) 
 	{
-		F32 old_offset = mAvatarOffset.mV[VZ];
-		F32 old_effective_height = new_body_size.mV[VZ] + mAvatarOffset.mV[VZ];
 		mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 1.11f); // avoid floating point rounding making the above check continue to fail.
 
 		llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 1.1f);
-- 
cgit v1.2.3


From d843a0d8bef5d36d3a4ef838b1b0335b4532147b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 25 Apr 2013 17:09:05 -0400
Subject: SH-4137 WIP - added callback-based support for purge descendents,
 remove category

---
 indra/llinventory/llinventory.cpp   |   7 -
 indra/llinventory/llinventory.h     |   1 -
 indra/newview/llinventorybridge.cpp |   9 +-
 indra/newview/llinventorymodel.cpp  | 207 ++++++++++----------------
 indra/newview/llinventorymodel.h    |  19 +--
 indra/newview/llpreview.cpp         |   7 -
 indra/newview/llviewerinventory.cpp | 286 ++++++++++++++++++++++++++++--------
 indra/newview/llviewerinventory.h   |  14 +-
 8 files changed, 321 insertions(+), 229 deletions(-)

diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 41d58c6deb..a4cd8333cf 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -249,13 +249,6 @@ BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) co
 	return TRUE;
 }
 
-
-void LLInventoryObject::removeFromServer()
-{
-	// don't do nothin'
-	llwarns << "LLInventoryObject::removeFromServer() called.  Doesn't do anything." << llendl;
-}
-
 void LLInventoryObject::updateParentOnServer(BOOL) const
 {
 	// don't do nothin'
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 99716ed7be..8b865f044d 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -101,7 +101,6 @@ public:
 	virtual BOOL importLegacyStream(std::istream& input_stream);
 	virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
 
-	virtual void removeFromServer();
 	virtual void updateParentOnServer(BOOL) const;
 	virtual void updateServer(BOOL) const;
 
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index a5043a30ac..27f35c5946 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1159,17 +1159,10 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 
 void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
 {
-	LLInventoryCategory* cat = model->getCategory(uuid);
-	if (cat)
-	{
-		model->purgeDescendentsOf(uuid);
-		model->notifyObservers();
-	}
 	LLInventoryObject* obj = model->getObject(uuid);
 	if (obj)
 	{
-		model->purgeObject(uuid);
-		model->notifyObservers();
+		remove_inventory_object(uuid, NULL);
 	}
 }
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index a0b9e7b0ec..ae8efeecda 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1136,6 +1136,79 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
 	notifyObservers();
 }
 
+// Update model after descendents have been purged.
+void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id)
+{
+	LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
+	if (cat.notNull())
+	{
+		// do the cache accounting
+		S32 descendents = cat->getDescendentCount();
+		if(descendents > 0)
+		{
+			LLInventoryModel::LLCategoryUpdate up(object_id, -descendents);
+			accountForUpdate(up);
+		}
+
+		// we know that descendent count is 0, however since the
+		// accounting may actually not do an update, we should force
+		// it here.
+		cat->setDescendentCount(0);
+
+		// unceremoniously remove anything we have locally stored.
+		LLInventoryModel::cat_array_t categories;
+		LLInventoryModel::item_array_t items;
+		collectDescendents(object_id,
+						   categories,
+						   items,
+						   LLInventoryModel::INCLUDE_TRASH);
+		S32 count = items.count();
+
+		LLUUID uu_id;
+		for(S32 i = 0; i < count; ++i)
+		{
+			uu_id = items.get(i)->getUUID();
+
+			// This check prevents the deletion of a previously deleted item.
+			// This is necessary because deletion is not done in a hierarchical
+			// order. The current item may have been already deleted as a child
+			// of its deleted parent.
+			if (getItem(uu_id))
+			{
+				deleteObject(uu_id);
+			}
+		}
+
+		count = categories.count();
+		for(S32 i = 0; i < count; ++i)
+		{
+			uu_id = categories.get(i)->getUUID();
+			if (getCategory(uu_id))
+			{
+				deleteObject(uu_id);
+			}
+		}
+	}
+}
+
+// Update model after an item is confirmed as removed from
+// server. Works for categories or items.
+void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id)
+{
+	LLPointer<LLInventoryObject> obj = getObject(object_id);
+	if(obj)
+	{
+		// From item/cat removeFromServer()
+		LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
+		accountForUpdate(up);
+
+		// From purgeObject()
+		LLPreview::hide(object_id);
+		deleteObject(object_id);
+	}
+}
+
+
 // Delete a particular inventory object by ID.
 void LLInventoryModel::deleteObject(const LLUUID& id)
 {
@@ -1187,20 +1260,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 	{
 		updateLinkedObjectsFromPurge(id);
 	}
-	gInventory.notifyObservers();
-}
-
-// Delete a particular inventory item by ID, and remove it from the server.
-void LLInventoryModel::purgeObject(const LLUUID &id)
-{
-	lldebugs << "LLInventoryModel::purgeObject() [ id: " << id << " ] " << llendl;
-	LLPointer<LLInventoryObject> obj = getObject(id);
-	if(obj)
-	{
-		obj->removeFromServer();
-		LLPreview::hide(id);
-		deleteObject(id);
-	}
+	notifyObservers();
 }
 
 void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
@@ -1225,119 +1285,6 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
 	}
 }
 
-// This is a method which collects the descendents of the id
-// provided. If the category is not found, no action is
-// taken. This method goes through the long winded process of
-// cancelling any calling cards, removing server representation of
-// folders, items, etc in a fairly efficient manner.
-void LLInventoryModel::purgeDescendentsOf(const LLUUID& id)
-{
-	EHasChildren children = categoryHasChildren(id);
-	if(children == CHILDREN_NO)
-	{
-		llinfos << "Not purging descendents of " << id << llendl;
-		return;
-	}
-	LLPointer<LLViewerInventoryCategory> cat = getCategory(id);
-	if (cat.notNull())
-	{
-		if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode())
-		{
-			// Something on the clipboard is in "cut mode" and needs to be preserved
-			llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
-			<< " iterate and purge non hidden items" << llendl;
-			cat_array_t* categories;
-			item_array_t* items;
-			// Get the list of direct descendants in tha categoy passed as argument
-			getDirectDescendentsOf(id, categories, items);
-			std::vector<LLUUID> list_uuids;
-			// Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently)
-			// Note: we need to do that shallow copy as purging things will invalidate the categories or items lists
-			for (cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it)
-			{
-				list_uuids.push_back((*it)->getUUID());
-			}
-			for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it)
-			{
-				list_uuids.push_back((*it)->getUUID());
-			}
-			// Iterate through the list and only purge the UUIDs that are not on the clipboard
-			for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
-			{
-				if (!LLClipboard::instance().isOnClipboard(*it))
-				{
-					purgeObject(*it);
-				}
-			}
-		}
-		else
-		{
-			// Fast purge
-			// do the cache accounting
-			llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
-				<< llendl;
-			S32 descendents = cat->getDescendentCount();
-			if(descendents > 0)
-			{
-				LLCategoryUpdate up(id, -descendents);
-				accountForUpdate(up);
-			}
-
-			// we know that descendent count is 0, however since the
-			// accounting may actually not do an update, we should force
-			// it here.
-			cat->setDescendentCount(0);
-
-			// send it upstream
-			LLMessageSystem* msg = gMessageSystem;
-			msg->newMessage("PurgeInventoryDescendents");
-			msg->nextBlock("AgentData");
-			msg->addUUID("AgentID", gAgent.getID());
-			msg->addUUID("SessionID", gAgent.getSessionID());
-			msg->nextBlock("InventoryData");
-			msg->addUUID("FolderID", id);
-			gAgent.sendReliableMessage();
-
-			// unceremoniously remove anything we have locally stored.
-			cat_array_t categories;
-			item_array_t items;
-			collectDescendents(id,
-							   categories,
-							   items,
-							   INCLUDE_TRASH);
-			S32 count = items.count();
-
-			item_map_t::iterator item_map_end = mItemMap.end();
-			cat_map_t::iterator cat_map_end = mCategoryMap.end();
-			LLUUID uu_id;
-
-			for(S32 i = 0; i < count; ++i)
-			{
-				uu_id = items.get(i)->getUUID();
-
-				// This check prevents the deletion of a previously deleted item.
-				// This is necessary because deletion is not done in a hierarchical
-				// order. The current item may have been already deleted as a child
-				// of its deleted parent.
-				if (mItemMap.find(uu_id) != item_map_end)
-				{
-					deleteObject(uu_id);
-				}
-			}
-
-			count = categories.count();
-			for(S32 i = 0; i < count; ++i)
-			{
-				uu_id = categories.get(i)->getUUID();
-				if (mCategoryMap.find(uu_id) != cat_map_end)
-				{
-					deleteObject(uu_id);
-				}
-			}
-		}
-	}
-}
-
 // Add/remove an observer. If the observer is destroyed, be sure to
 // remove it.
 void LLInventoryModel::addObserver(LLInventoryObserver* observer)
@@ -3114,8 +3061,7 @@ bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const L
 	if (option == 0) // YES
 	{
 		const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
-		purgeDescendentsOf(folder_id);
-		notifyObservers();
+		purge_descendents_of(folder_id, NULL);
 	}
 	return false;
 }
@@ -3130,8 +3076,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT
 	else
 	{
 		const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
-		purgeDescendentsOf(folder_id);
-		notifyObservers();
+		purge_descendents_of(folder_id, NULL);
 	}
 }
 
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 50b57ea08d..b7e1888f20 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -325,6 +325,14 @@ public:
 	// Delete
 	//--------------------------------------------------------------------
 public:
+	
+	// Update model after an item is confirmed as removed from
+	// server. Works for categories or items.
+	void onObjectDeletedFromServer(const LLUUID& item_id);
+
+	// Update model after all descendents removed from server.
+	void onDescendentsPurgedFromServer(const LLUUID& object_id);
+
 	// Delete a particular inventory object by ID. Will purge one
 	// object from the internal data structures, maintaining a
 	// consistent internal state. No cache accounting, observer
@@ -337,17 +345,6 @@ public:
 	/// removeItem() or removeCategory(), whichever is appropriate
 	void removeObject(const LLUUID& object_id);
 
-	// Delete a particular inventory object by ID, and delete it from
-	// the server. Also updates linked items.
-	void purgeObject(const LLUUID& id);
-
-	// Collects and purges the descendants of the id
-	// provided. If the category is not found, no action is
-	// taken. This method goes through the long winded process of
-	// removing server representation of folders and items while doing
-	// cache accounting in a fairly efficient manner. This method does
-	// not notify observers (though maybe it should...)
-	void purgeDescendentsOf(const LLUUID& id);
 protected:
 	void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id);
 	
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 04934b13f1..452efad291 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -401,13 +401,6 @@ void LLPreview::onDiscardBtn(void* data)
 	self->mForceClose = TRUE;
 	self->closeFloater();
 
-	// Delete the item entirely
-	/*
-	item->removeFromServer();
-	gInventory.deleteObject(item->getUUID());
-	gInventory.notifyObservers();
-	*/
-
 	// Move the item to the trash
 	const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
 	if (item->getParentUUID() != trash_id)
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 06efeb86d9..fbd6b292bd 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -65,6 +65,7 @@
 #include "llavataractions.h"
 #include "lllogininstance.h"
 #include "llfavoritesbar.h"
+#include "llclipboard.h"
 
 // Two do-nothing ops for use in callbacks.
 void no_op_inventory_func(const LLUUID&) {} 
@@ -345,24 +346,6 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& ne
 	}
 }
 
-void LLViewerInventoryItem::removeFromServer()
-{
-	lldebugs << "Removing inventory item " << mUUID << " from server."
-			 << llendl;
-
-	LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
-	gInventory.accountForUpdate(up);
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_RemoveInventoryItem);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 
-	msg->nextBlockFast(_PREHASH_InventoryData);
-	msg->addUUIDFast(_PREHASH_ItemID, mUUID);
-	gAgent.sendReliableMessage();
-}
-
 void LLViewerInventoryItem::updateServer(BOOL is_new) const
 {
 	if(!mIsComplete)
@@ -637,30 +620,6 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
 	gAgent.sendReliableMessage();
 }
 
-void LLViewerInventoryCategory::removeFromServer( void )
-{
-	llinfos << "Removing inventory category " << mUUID << " from server."
-			<< llendl;
-	// communicate that change with the server.
-	if(LLFolderType::lookupIsProtectedType(mPreferredType))
-	{
-		LLNotificationsUtil::add("CannotRemoveProtectedCategories");
-		return;
-	}
-
-	LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
-	gInventory.accountForUpdate(up);
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_RemoveInventoryFolder);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->nextBlockFast(_PREHASH_FolderData);
-	msg->addUUIDFast(_PREHASH_FolderID, mUUID);
-	gAgent.sendReliableMessage();
-}
-
 S32 LLViewerInventoryCategory::getVersion() const
 {
 	return mVersion;
@@ -1179,25 +1138,10 @@ void move_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
-void handle_item_deletion(const LLUUID& item_id)
-{
-	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
-	if(obj)
-	{
-		// From item removeFromServer()
-		LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
-		gInventory.accountForUpdate(up);
-
-		// From purgeObject()
-		LLPreview::hide(item_id);
-		gInventory.deleteObject(item_id);
-	}
-}
-
-class RemoveItemResponder: public LLHTTPClient::Responder
+class RemoveObjectResponder: public LLHTTPClient::Responder
 {
 public:
-	RemoveItemResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback):
+	RemoveObjectResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback):
 		mItemUUID(item_id),
 		mCallback(callback)
 	{
@@ -1212,7 +1156,7 @@ public:
 		}
 		llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl;
 
-		handle_item_deletion(mItemUUID);
+		gInventory.onObjectDeletedFromServer(mItemUUID);
 
 		if (mCallback)
 		{
@@ -1251,7 +1195,7 @@ void remove_inventory_item(
 		{
 			std::string url = cap + std::string("/item/") + item_id.asString();
 			llinfos << "url: " << url << llendl;
-			LLCurl::ResponderPtr responder_ptr = new RemoveItemResponder(item_id,cb);
+			LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(item_id,cb);
 			LLHTTPClient::del(url,responder_ptr);
 		}
 		else // no cap
@@ -1267,7 +1211,7 @@ void remove_inventory_item(
 
 			// Update inventory and call callback immediately since
 			// message-based system has no callback mechanism (!)
-			handle_item_deletion(item_id);
+			gInventory.onObjectDeletedFromServer(item_id);
 			if (cb)
 			{
 				cb->fire(item_id);
@@ -1280,6 +1224,224 @@ void remove_inventory_item(
 	}
 }
 
+class LLRemoveObjectOnDestroy: public LLInventoryCallback
+{
+public:
+	LLRemoveObjectOnDestroy(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb):
+		mID(item_id),
+		mCB(cb)
+	{
+	}
+	/* virtual */ void fire(const LLUUID& item_id) {}
+	~LLRemoveObjectOnDestroy()
+	{
+		remove_inventory_object(mID, mCB);
+	}
+private:
+	LLUUID mID;
+	LLPointer<LLInventoryCallback> mCB;
+};
+
+void remove_inventory_category(
+	const LLUUID& cat_id,
+	LLPointer<LLInventoryCallback> cb)
+{
+	llinfos << "cat_id: [" << cat_id << "] " << llendl;
+	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
+	if(obj)
+	{
+		if(LLFolderType::lookupIsProtectedType(obj->getPreferredType()))
+		{
+			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
+			return;
+		}
+		LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id);
+		if(children != LLInventoryModel::CHILDREN_NO)
+		{
+			llinfos << "Will purge descendents first before deleting category " << cat_id << llendl;
+			LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveObjectOnDestroy(cat_id,cb); 
+			purge_descendents_of(cat_id, wrap_cb);
+			return;
+		}
+
+		std::string cap;
+		if (gAgent.getRegion())
+		{
+			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+		}
+		if (!cap.empty())
+		{
+			std::string url = cap + std::string("/category/") + cat_id.asString();
+			llinfos << "url: " << url << llendl;
+			LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(cat_id,cb);
+			LLHTTPClient::del(url,responder_ptr);
+		}
+		else // no cap
+		{
+
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_RemoveInventoryFolder);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->nextBlockFast(_PREHASH_FolderData);
+			msg->addUUIDFast(_PREHASH_FolderID, cat_id);
+			gAgent.sendReliableMessage();
+
+			// Update inventory and call callback immediately since
+			// message-based system has no callback mechanism (!)
+			gInventory.onObjectDeletedFromServer(cat_id);
+			if (cb)
+			{
+				cb->fire(cat_id);
+			}
+		}
+	}
+	else
+	{
+		llwarns << "remove_inventory_category called for invalid or nonexistent item " << cat_id << llendl;
+	}
+}
+
+void remove_inventory_object(
+	const LLUUID& object_id,
+	LLPointer<LLInventoryCallback> cb)
+{
+	if (gInventory.getCategory(object_id))
+	{
+		remove_inventory_category(object_id, cb);
+	}
+	else
+	{
+		remove_inventory_item(object_id, cb);
+	}
+}
+
+class PurgeDescendentsResponder: public LLHTTPClient::Responder
+{
+public:
+	PurgeDescendentsResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback):
+		mItemUUID(item_id),
+		mCallback(callback)
+	{
+	}
+	/* virtual */ void httpSuccess()
+	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl;
+
+		gInventory.onDescendentsPurgedFromServer(mItemUUID);
+
+		if (mCallback)
+		{
+			mCallback->fire(mItemUUID);
+		}
+	}
+	/*virtual*/ void httpFailure()
+	{
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl;
+	}
+private:
+	LLPointer<LLInventoryCallback> mCallback;
+	const LLUUID mItemUUID;
+};
+
+// This is a method which collects the descendents of the id
+// provided. If the category is not found, no action is
+// taken. This method goes through the long winded process of
+// cancelling any calling cards, removing server representation of
+// folders, items, etc in a fairly efficient manner.
+void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id);
+	if(children == LLInventoryModel::CHILDREN_NO)
+	{
+		llinfos << "No descendents to purge for " << id << llendl;
+		return;
+	}
+	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id);
+	if (cat.notNull())
+	{
+		if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode())
+		{
+			// Something on the clipboard is in "cut mode" and needs to be preserved
+			llinfos << "purge_descendents_of clipboard case " << cat->getName()
+			<< " iterate and purge non hidden items" << llendl;
+			LLInventoryModel::cat_array_t* categories;
+			LLInventoryModel::item_array_t* items;
+			// Get the list of direct descendants in tha categoy passed as argument
+			gInventory.getDirectDescendentsOf(id, categories, items);
+			std::vector<LLUUID> list_uuids;
+			// Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently)
+			// Note: we need to do that shallow copy as purging things will invalidate the categories or items lists
+			for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it)
+			{
+				list_uuids.push_back((*it)->getUUID());
+			}
+			for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); it != items->end(); ++it)
+			{
+				list_uuids.push_back((*it)->getUUID());
+			}
+			// Iterate through the list and only purge the UUIDs that are not on the clipboard
+			for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
+			{
+				if (!LLClipboard::instance().isOnClipboard(*it))
+				{
+					remove_inventory_object(*it, NULL);
+				}
+			}
+		}
+		else
+		{
+			std::string cap;
+			if (gAgent.getRegion())
+			{
+				cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+			}
+			if (!cap.empty())
+			{
+				std::string url = cap + std::string("/category/") + id.asString() + "/children";
+				llinfos << "url: " << url << llendl;
+				LLCurl::ResponderPtr responder_ptr = new PurgeDescendentsResponder(id,cb);
+				LLHTTPClient::del(url,responder_ptr);
+			}
+			else // no cap
+			{
+				// Fast purge
+				llinfos << "purge_descendents_of fast case " << cat->getName() << llendl;
+
+				// send it upstream
+				LLMessageSystem* msg = gMessageSystem;
+				msg->newMessage("PurgeInventoryDescendents");
+				msg->nextBlock("AgentData");
+				msg->addUUID("AgentID", gAgent.getID());
+				msg->addUUID("SessionID", gAgent.getSessionID());
+				msg->nextBlock("InventoryData");
+				msg->addUUID("FolderID", id);
+				gAgent.sendReliableMessage();
+
+				// Update model immediately because there is no callback mechanism.
+				gInventory.onDescendentsPurgedFromServer(id);
+				if (cb)
+				{
+					cb->fire(id);
+				}
+			}
+		}
+	}
+}
+
 const LLUUID get_folder_by_itemtype(const LLInventoryItem *src)
 {
 	LLUUID retval = LLUUID::null;
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 6b0e8ed4ef..4e24dc87d1 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -118,7 +118,6 @@ public:
 	void cloneViewerItem(LLPointer<LLViewerInventoryItem>& newitem) const;
 
 	// virtual methods
-	virtual void removeFromServer( void );
 	virtual void updateParentOnServer(BOOL restamp) const;
 	virtual void updateServer(BOOL is_new) const;
 	void fetchFromServer(void) const;
@@ -198,7 +197,6 @@ public:
 	LLViewerInventoryCategory(const LLViewerInventoryCategory* other);
 	void copyViewerCategory(const LLViewerInventoryCategory* other);
 
-	virtual void removeFromServer();
 	virtual void updateParentOnServer(BOOL restamp_children) const;
 	virtual void updateServer(BOOL is_new) const;
 
@@ -369,6 +367,18 @@ void remove_inventory_item(
 	const LLUUID& item_id,
 	LLPointer<LLInventoryCallback> cb);
 	
+void remove_inventory_category(
+	const LLUUID& cat_id,
+	LLPointer<LLInventoryCallback> cb);
+	
+void remove_inventory_object(
+	const LLUUID& object_id,
+	LLPointer<LLInventoryCallback> cb);
+
+void purge_descendents_of(
+	const LLUUID& cat_id,
+	LLPointer<LLInventoryCallback> cb);
+
 const LLUUID get_folder_by_itemtype(const LLInventoryItem *src);
 
 void copy_inventory_from_notecard(const LLUUID& destination_id,
-- 
cgit v1.2.3


From 638514ca0cbc666a324e757c8de4cceaaaeeadd4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 26 Apr 2013 10:01:09 -0400
Subject: SH-4142 FIX - avoid stack overflow in an AISv3 responder failure
 case.

---
 indra/newview/llviewerinventory.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index fbd6b292bd..c44552d7d2 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1168,7 +1168,7 @@ public:
 		const LLSD& content = getContent();
 		if (!content.isMap())
 		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			llwarns << "Malformed response contents" << content << llendl;
 			return;
 		}
 		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl;
@@ -1347,7 +1347,7 @@ public:
 		const LLSD& content = getContent();
 		if (!content.isMap())
 		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			llwarns << "Malformed response contents" << content << llendl;
 			return;
 		}
 		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl;
-- 
cgit v1.2.3


From fb51bab6cd2e3f037142ce7c5f547113d76f0504 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 26 Apr 2013 10:17:41 -0400
Subject: SH-4142 FIX - made error messages a bit more informative

---
 indra/newview/llviewerinventory.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index c44552d7d2..3eab85b8b3 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1166,12 +1166,14 @@ public:
 	/*virtual*/ void httpFailure()
 	{
 		const LLSD& content = getContent();
+		S32 status = getStatus();
+		const std::string& reason = getReason();
 		if (!content.isMap())
 		{
-			llwarns << "Malformed response contents" << content << llendl;
+			llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl;
 			return;
 		}
-		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl;
+		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl;
 	}
 private:
 	LLPointer<LLInventoryCallback> mCallback;
@@ -1345,12 +1347,14 @@ public:
 	/*virtual*/ void httpFailure()
 	{
 		const LLSD& content = getContent();
+		S32 status = getStatus();
+		const std::string& reason = getReason();
 		if (!content.isMap())
 		{
-			llwarns << "Malformed response contents" << content << llendl;
+			llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl;
 			return;
 		}
-		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl;
+		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl;
 	}
 private:
 	LLPointer<LLInventoryCallback> mCallback;
-- 
cgit v1.2.3


From 2c617e0beb145f3c8451ffdc8445e97358a17427 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 26 Apr 2013 14:33:49 -0500
Subject: llappearance package update

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 95fb5a9629..713cfd5337 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>419c3634dd982e8855785ce36f22892e</string>
+              <string>090967db76abcb1f342a8319bb31ffdc</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/274704/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130424.tar.bz2</string>
+	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/274927/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130426.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From c198d9db81073d4208de9cefacd0c6ba1ee9ff1f Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 26 Apr 2013 15:55:39 -0500
Subject: LLAppearance package update

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 713cfd5337..04ac4b4c9c 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>090967db76abcb1f342a8319bb31ffdc</string>
+              <string>5dd6d3070ece946abad8bfd2d95656cb</string>
               <key>url</key>
-	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/274927/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130426.tar.bz2</string>
+	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/274933/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130426.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From fcb4f8265dd7ca80ebf858e31b86ac523465e74d Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Mon, 29 Apr 2013 11:49:49 -0400
Subject: SH-4146 FIX petite avatars can't touch the ground

adjusted avatar hover limits to make sure that they are not forced to
go above the default
---
 indra/llappearance/llavatarappearance.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 0a15f06bfd..0abe9ccb87 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -491,12 +491,21 @@ void LLAvatarAppearance::computeBodySize()
 	// Certain configurations of avatars can force the overall height (with offset) to go negative.
 	// Enforce a constraint to make sure we don't go below 0.1 meters.
 	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
-	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 1.1f) 
+	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 1.1f && mAvatarOffset.mV[VZ] < 0.0f) 
 	{
 		mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 1.11f); // avoid floating point rounding making the above check continue to fail.
 
 		llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 1.1f);
 
+	
+		// some mesh avatars force the default height to be less than 1.1 meters. Do not force hover to be positive.
+		// This will allow them to appear to be on the ground, even if the server forces their physics shape to be 
+		// taller than their visual representation.
+		if (mAvatarOffset.mV[VZ] > 0.0f) 
+		{
+			mAvatarOffset.mV[VZ] = 0.0f;
+		}
+
 		if (mWearableData && isSelf()) 
 		{
 			LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0);
-- 
cgit v1.2.3


From e4c96827d237a489873ce8453640d3a13f83d01a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 29 Apr 2013 14:24:05 -0400
Subject: SH-4144 FIX - Debug setting now disables use of AISv3 by default.
 This is just a workaround for the problem of aditi advertising the cap when
 it isn't really present. Once we have aditi in a consistent state we should
 remove the setting, or at least default it to true.

---
 indra/newview/app_settings/logcontrol.xml |  2 +-
 indra/newview/app_settings/settings.xml   | 11 +++++++++++
 indra/newview/llviewerinventory.cpp       | 10 +++++++---
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 92a241857e..c5561166fc 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,8 +42,8 @@
 						</array>
 					<key>tags</key>
 						<array>
-						<!-- sample entry for debugging specific items	
 						     <string>Avatar</string>
+						<!-- sample entry for debugging specific items	
 						     <string>Voice</string>		
 						-->
 						</array>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 18a33b3542..1262089b3d 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14033,6 +14033,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>UseAISv3Inventory</key>
+    <map>
+      <key>Comment</key>
+      <string>Allow use of AISv3 inventory - this setting should only be needed during development.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>ClickToWalk</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 3eab85b8b3..d45512df9c 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -627,6 +627,10 @@ S32 LLViewerInventoryCategory::getVersion() const
 
 void LLViewerInventoryCategory::setVersion(S32 version)
 {
+	if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT)
+	{
+		llinfos << "cof version change " << mVersion << " => " << version << llendl;
+	}
 	mVersion = version;
 }
 
@@ -1189,7 +1193,7 @@ void remove_inventory_item(
 	if(obj)
 	{
 		std::string cap;
-		if (gAgent.getRegion())
+		if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory"))
 		{
 			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
 		}
@@ -1267,7 +1271,7 @@ void remove_inventory_category(
 		}
 
 		std::string cap;
-		if (gAgent.getRegion())
+		if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory"))
 		{
 			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
 		}
@@ -1409,7 +1413,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		else
 		{
 			std::string cap;
-			if (gAgent.getRegion())
+			if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory"))
 			{
 				cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
 			}
-- 
cgit v1.2.3


From 72aa727a3f371cf592d33e6cccefbf74be053b70 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 29 Apr 2013 14:29:04 -0400
Subject: removed overly enthusiastic log setting

---
 indra/newview/app_settings/logcontrol.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index c5561166fc..92a241857e 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,8 +42,8 @@
 						</array>
 					<key>tags</key>
 						<array>
-						     <string>Avatar</string>
 						<!-- sample entry for debugging specific items	
+						     <string>Avatar</string>
 						     <string>Voice</string>		
 						-->
 						</array>
-- 
cgit v1.2.3


From 9caeb5ad5045352c4bb77195c5c0bc71575bc3fd Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 29 Apr 2013 14:31:15 -0400
Subject: removed debugging code that got pushed incorrectly.

---
 indra/newview/app_settings/logcontrol.xml | 2 +-
 indra/newview/llviewerinventory.cpp       | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 92a241857e..c5561166fc 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,8 +42,8 @@
 						</array>
 					<key>tags</key>
 						<array>
-						<!-- sample entry for debugging specific items	
 						     <string>Avatar</string>
+						<!-- sample entry for debugging specific items	
 						     <string>Voice</string>		
 						-->
 						</array>
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d45512df9c..b39dbd51a1 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -627,10 +627,12 @@ S32 LLViewerInventoryCategory::getVersion() const
 
 void LLViewerInventoryCategory::setVersion(S32 version)
 {
+#if 0
 	if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT)
 	{
 		llinfos << "cof version change " << mVersion << " => " << version << llendl;
 	}
+#endif
 	mVersion = version;
 }
 
-- 
cgit v1.2.3


From 48d684c7befae1ca7f7b43f682d7bea03fc4e0c0 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 29 Apr 2013 14:32:03 -0400
Subject: logcontrol.xml fix this time for sure.

---
 indra/newview/app_settings/logcontrol.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index c5561166fc..92a241857e 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,8 +42,8 @@
 						</array>
 					<key>tags</key>
 						<array>
-						     <string>Avatar</string>
 						<!-- sample entry for debugging specific items	
+						     <string>Avatar</string>
 						     <string>Voice</string>		
 						-->
 						</array>
-- 
cgit v1.2.3


From ae53d22141288ab1b5ba4a5927d11cf84c59d445 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 29 Apr 2013 16:59:10 -0400
Subject: SH-4140 FIX, SH-3860 FIX - appearance on first-time login should now
 be reliable without depending on retries of appearance update requests. May
 still see COF mismatch errors in the log - these will only be fixed, if at
 all, with AISv3 integration.

---
 indra/newview/llappearancemgr.cpp   | 13 ++++++++++---
 indra/newview/llviewerinventory.cpp |  2 --
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 399cea676c..40ec88f1be 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2890,7 +2890,7 @@ protected:
 		}
 		if (content["success"].asBoolean())
 		{
-			LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
+			//LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
 			if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 			{
 				dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
@@ -2907,7 +2907,8 @@ protected:
 	{
 		const LLSD& content = getContent();
 		LL_WARNS("Avatar") << "appearance update request failed "
-				<< dumpResponse() << LL_ENDL;
+						   << dumpResponse() << LL_ENDL;
+
 		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
 			dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
@@ -3247,6 +3248,13 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
 	LLAppearanceMgr::getInstance()->updateIsDirty();
 	gAgentWearables.notifyLoadingFinished(); // New outfit is saved.
 	LLAppearanceMgr::getInstance()->updatePanelOutfitName("");
+
+	// For SSB, need to update appearance after we add a base outfit
+	// link, since, the COF version has changed. There is a race
+	// condition in initial outfit setup which can lead to rez
+	// failures - SH-3860.
+	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
+	LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb);
 }
 
 LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
@@ -3267,7 +3275,6 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, b
 	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func,
 																		 boost::bind(show_created_outfit,folder_id,show_panel));
 	shallowCopyCategoryContents(getCOF(),folder_id, cb);
-	createBaseOutfitLink(folder_id, cb);
 
 	dumpCat(folder_id,"COF, new outfit");
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index b39dbd51a1..d45512df9c 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -627,12 +627,10 @@ S32 LLViewerInventoryCategory::getVersion() const
 
 void LLViewerInventoryCategory::setVersion(S32 version)
 {
-#if 0
 	if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT)
 	{
 		llinfos << "cof version change " << mVersion << " => " << version << llendl;
 	}
-#endif
 	mVersion = version;
 }
 
-- 
cgit v1.2.3


From b322c1dbaceaa9359243e030a125e312c54448f3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 30 Apr 2013 16:54:52 -0400
Subject: SH-4140 FIX - removed a gratuitous log message

---
 indra/newview/llviewerinventory.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d45512df9c..f9afdee4f9 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -627,10 +627,6 @@ S32 LLViewerInventoryCategory::getVersion() const
 
 void LLViewerInventoryCategory::setVersion(S32 version)
 {
-	if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT)
-	{
-		llinfos << "cof version change " << mVersion << " => " << version << llendl;
-	}
 	mVersion = version;
 }
 
-- 
cgit v1.2.3


From 7e599539f0855fd949e59340aa6891ebc91ee27a Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 1 May 2013 16:58:02 -0400
Subject: LLAppearance package update

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 04ac4b4c9c..fdd2cb2d67 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>5dd6d3070ece946abad8bfd2d95656cb</string>
+              <string>e452ebec5a7fce6b3345a6682c250c6e</string>
               <key>url</key>
-	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/274933/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130426.tar.bz2</string>
+	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275124/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130501.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From 89cef0cad260e7c8369070c32478621f1cd22f62 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 1 May 2013 17:55:49 -0400
Subject: SH-4154 WIP - gInventory.validate() has inventory model internal
 consistency checks

---
 indra/newview/llinventorymodel.cpp                | 197 +++++++++++++++++++++-
 indra/newview/llinventorymodel.h                  |   4 +
 indra/newview/llinventorymodelbackgroundfetch.cpp |   2 +
 3 files changed, 202 insertions(+), 1 deletion(-)
 mode change 100644 => 100755 indra/newview/llinventorymodelbackgroundfetch.cpp

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index ae8efeecda..f60fd63eee 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -252,6 +252,23 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL
 	return NULL;
 }
 
+bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
+{
+	LLInventoryObject *object = getObject(object_id);
+	while (object && object->getParentUUID().notNull())
+	{
+		LLInventoryObject *parent_object = getObject(object->getParentUUID());
+		if (!parent_object)
+		{
+			llwarns << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << llendl;
+			return false;
+		}
+		object = parent_object;
+	}
+	result = object->getUUID();
+	return true;
+}
+
 // Get the object by id. Returns NULL if not found.
 LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const
 {
@@ -2083,7 +2100,7 @@ void LLInventoryModel::buildParentChildMap()
 			// implement it, we would need a set or map of uuid pairs
 			// which would be (folder_id, new_parent_id) to be sent up
 			// to the server.
-			llinfos << "Lost categroy: " << cat->getUUID() << " - "
+			llinfos << "Lost category: " << cat->getUUID() << " - "
 					<< cat->getName() << llendl;
 			++lost;
 			// plop it into the lost & found.
@@ -2102,6 +2119,8 @@ void LLInventoryModel::buildParentChildMap()
 				// it's a protected folder.
 				cat->setParent(gInventory.getRootFolderID());
 			}
+			// FIXME note that updateServer() fails with protected
+			// types, so this will not work as intended in that case.
 			cat->updateServer(TRUE);
 			catsp = getUnlockedCatArray(cat->getParentUUID());
 			if(catsp)
@@ -2247,6 +2266,11 @@ void LLInventoryModel::buildParentChildMap()
 			notifyObservers();
 		}
 	}
+
+	//if (!gInventory.validate())
+	//{
+	//	llwarns << "model failed validity check!" << llendl;
+	//}
 }
 
 struct LLUUIDAndName
@@ -2917,6 +2941,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 		InventoryCallbackInfo cbinfo = (*inv_it);
 		gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);
 	}
+
+	//gInventory.validate();
+
 	// Don't show the inventory.  We used to call showAgentInventory here.
 	//LLFloaterInventory* view = LLFloaterInventory::getActiveInventory();
 	//if(view)
@@ -3363,6 +3390,174 @@ void LLInventoryModel::dumpInventory() const
 	llinfos << "\n**********************\nEnd Inventory Dump" << llendl;
 }
 
+// Do various integrity checks on model, logging issues found and
+// returning an overall good/bad flag.
+bool LLInventoryModel::validate() const
+{
+	bool valid = true;
+
+	if (getRootFolderID().isNull())
+	{
+		llwarns << "no root folder id" << llendl;
+		valid = false;
+	}
+	if (getLibraryRootFolderID().isNull())
+	{
+		llwarns << "no root folder id" << llendl;
+		valid = false;
+	}
+
+	if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
+	{
+		// ParentChild should be one larger because of the special entry for null uuid.
+		llinfos << "unexpected sizes: cat map size " << mCategoryMap.size()
+				<< " parent/child " << mParentChildCategoryTree.size() << llendl;
+		valid = false;
+	}
+	S32 cat_lock = 0;
+	S32 item_lock = 0;
+	S32 desc_unknown_count = 0;
+	S32 version_unknown_count = 0;
+	for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+	{
+		const LLUUID& cat_id = cit->first;
+		const LLViewerInventoryCategory *cat = cit->second;
+		if (!cat)
+		{
+			llwarns << "invalid cat" << llendl;
+			valid = false;
+			continue;
+		}
+		if (cat_id != cat->getUUID())
+		{
+			llwarns << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << llendl;
+			valid = false;
+		}
+
+		if (cat->getParentUUID().isNull())
+		{
+			if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())
+			{
+				llwarns << "cat " << cat_id << " has no parent, but is not root ("
+						<< getRootFolderID() << ") or library root ("
+						<< getLibraryRootFolderID() << ")" << llendl;
+			}
+		}
+		cat_array_t* cats;
+		item_array_t* items;
+		getDirectDescendentsOf(cat_id,cats,items);
+		if (!cats || !items)
+		{
+			llwarns << "invalid direct descendents for " << cat_id << llendl;
+			valid = false;
+			continue;
+		}
+		if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
+		{
+			desc_unknown_count++;
+		}
+		else if (cats->size() + items->size() != cat->getDescendentCount())
+		{
+			llwarns << "invalid desc count for " << cat_id << " name " << cat->getName()
+					<< " cached " << cat->getDescendentCount()
+					<< " expected " << cats->size() << "+" << items->size()
+					<< "=" << cats->size() +items->size() << llendl;
+			valid = false;
+		}
+		if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
+		{
+			version_unknown_count++;
+		}
+		if (mCategoryLock.count(cat_id))
+		{
+			cat_lock++;
+		}
+		if (mItemLock.count(cat_id))
+		{
+			item_lock++;
+		}
+		for (S32 i = 0; i<items->size(); i++)
+		{
+			LLViewerInventoryItem *item = items->get(i);
+
+			if (!item)
+			{
+				llwarns << "null item at index " << i << " for cat " << cat_id << llendl;
+				valid = false;
+				continue;
+			}
+
+			const LLUUID& item_id = item->getUUID();
+			
+			if (item->getParentUUID() != cat_id)
+			{
+				llwarns << "wrong parent for " << item_id << " found "
+						<< item->getParentUUID() << " expected " << cat_id
+						<< llendl;
+				valid = false;
+			}
+
+
+			// Entries in items and mItemMap should correspond.
+			item_map_t::const_iterator it = mItemMap.find(item_id);
+			if (it == mItemMap.end())
+			{
+				llwarns << "item " << item_id << " found as child of "
+						<< cat_id << " but not in top level mItemMap" << llendl;
+				valid = false;
+			}
+			else
+			{
+				LLViewerInventoryItem *top_item = it->second;
+				if (top_item != item)
+				{
+					llwarns << "item mismatch, item_id " << item_id
+							<< " top level entry is different, uuid " << top_item->getUUID() << llendl;
+				}
+			}
+
+			// Topmost ancestor should be root or library.
+			LLUUID topmost_ancestor_id;
+			bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
+			if (!found)
+			{
+				llwarns << "unable to find topmost ancestor for " << item_id << llendl;
+				valid = false;
+			}
+			else
+			{
+				if (topmost_ancestor_id != getRootFolderID() &&
+					topmost_ancestor_id != getLibraryRootFolderID())
+				{
+					llwarns << "unrecognized top level ancestor for " << item_id
+							<< " got " << topmost_ancestor_id
+							<< " expected " << getRootFolderID()
+							<< " or " << getLibraryRootFolderID() << llendl;
+					valid = false;
+				}
+			}
+		}
+
+	}
+	if (cat_lock > 0 || item_lock > 0)
+	{
+		llwarns << "Found locks on some categories: sub-cat arrays "
+				<< cat_lock << ", item arrays " << item_lock << llendl;
+	}
+	if (desc_unknown_count != 0)
+	{
+		llinfos << "Found " << desc_unknown_count << " cats with unknown descendent count" << llendl; 
+	}
+	if (version_unknown_count != 0)
+	{
+		llinfos << "Found " << version_unknown_count << " cats with unknown version" << llendl;
+	}
+
+	llinfos << "Validate done, valid = " << (U32) valid << llendl;
+
+	return valid;
+}
+
 ///----------------------------------------------------------------------------
 /// Local function definitions
 ///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index b7e1888f20..2459f10a37 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -227,6 +227,9 @@ public:
 	// Check if one object has a parent chain up to the category specified by UUID.
 	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
 
+	// Follow parent chain to the top.
+	bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
+	
 	//--------------------------------------------------------------------
 	// Find
 	//--------------------------------------------------------------------
@@ -551,6 +554,7 @@ private:
 	//--------------------------------------------------------------------
 public:
 	void dumpInventory() const;
+	bool validate() const;
 
 /**                    Miscellaneous
  **                                                                            **
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
old mode 100644
new mode 100755
index 01b0e647a9..4eeb528c66
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -172,6 +172,8 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
 		mRecursiveLibraryFetchStarted)
 	{
 		mAllFoldersFetched = TRUE;
+		//llinfos << "All folders fetched, validating" << llendl;
+		//gInventory.validate();
 	}
 	mFolderFetchActive = false;
 }
-- 
cgit v1.2.3


From af1431731802320e241037486b8bff0003a4d827 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Thu, 2 May 2013 13:56:10 -0400
Subject: SH-4060 FIX avatar hover being set to minimum at seemingly random
 times

avatar hover was being temporarily set to -2.0 for the preview render, which
was triggering the minimum enforcement, even when the user's requested value
is no where near the minimum. Added a flag to disable the minimum enforcement
if we are temporarily changing the value.
---
 indra/llappearance/llavatarappearance.cpp | 28 ----------------------------
 indra/llappearance/llavatarappearance.h   |  2 +-
 indra/newview/lltoolmorph.cpp             | 12 ++++++++++++
 indra/newview/llviewerwearable.h          |  4 ++++
 indra/newview/llvoavatar.cpp              | 30 ++++++++++++++++++++++++++++++
 indra/newview/llvoavatar.h                |  3 +++
 6 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 0abe9ccb87..e3497c107d 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -488,34 +488,6 @@ void LLAvatarAppearance::computeBodySize()
 	mAvatarOffset.mV[VX] = 0.0f;
 	mAvatarOffset.mV[VY] = 0.0f;
 
-	// Certain configurations of avatars can force the overall height (with offset) to go negative.
-	// Enforce a constraint to make sure we don't go below 0.1 meters.
-	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
-	if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 1.1f && mAvatarOffset.mV[VZ] < 0.0f) 
-	{
-		mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 1.11f); // avoid floating point rounding making the above check continue to fail.
-
-		llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 1.1f);
-
-	
-		// some mesh avatars force the default height to be less than 1.1 meters. Do not force hover to be positive.
-		// This will allow them to appear to be on the ground, even if the server forces their physics shape to be 
-		// taller than their visual representation.
-		if (mAvatarOffset.mV[VZ] > 0.0f) 
-		{
-			mAvatarOffset.mV[VZ] = 0.0f;
-		}
-
-		if (mWearableData && isSelf()) 
-		{
-			LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0);
-			if (shape) 
-			{
-				shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false);
-			}
-		}
-	}
-
 	if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
 	{
 		mBodySize = new_body_size;
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index bce2540258..0a6a236d34 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -137,7 +137,7 @@ public:
 	typedef std::map<std::string, LLJoint*> joint_map_t;
 	joint_map_t			mJointMap;
 	
-	void				computeBodySize();
+	virtual void		computeBodySize();
 
 
 protected:
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 148e5a015b..f39b98dd31 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -54,6 +54,7 @@
 #include "llviewercamera.h"
 #include "llviewertexturelist.h"
 #include "llviewerobject.h"
+#include "llviewerwearable.h"
 #include "llviewerwindow.h"
 #include "llvoavatarself.h"
 #include "pipeline.h"
@@ -147,6 +148,11 @@ BOOL LLVisualParamHint::needsRender()
 
 void LLVisualParamHint::preRender(BOOL clear_depth)
 {
+	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
+	if (wearable)
+	{
+		wearable->setVolitile(TRUE);
+	}
 	mLastParamWeight = mVisualParam->getWeight();
 	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
 	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
@@ -239,6 +245,12 @@ BOOL LLVisualParamHint::render()
 	}
 	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
 	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight, FALSE);
+	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
+	if (wearable)
+	{
+		wearable->setVolitile(FALSE);
+	}
+
 	gAgentAvatarp->updateVisualParams();
 	gGL.color4f(1,1,1,1);
 	mGLTexturep->setGLTextureCreated(true);
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
index 65566f23a5..047b2ce143 100644
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -68,6 +68,8 @@ public:
 	
 	void				setParamsToDefaults();
 	void				setTexturesToDefaults();
+	void				setVolitile(BOOL volitle) { mVolitle = volitle; } // TRUE when doing preview renders, some updates will be suppressed.
+	BOOL				getVolitile() { return mVolitle; }
 
 	/*virtual*/ LLUUID	getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const;
 
@@ -96,6 +98,8 @@ protected:
 	LLAssetID			mAssetID;
 	LLTransactionID		mTransactionID;
 
+	BOOL 				mVolitle; // True when rendering preview images. Can suppress some updates.
+
 	LLUUID				mItemID;  // ID of the inventory item in the agent's inventory	
 };
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index a56e09cde0..919627c47c 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5214,6 +5214,36 @@ void LLVOAvatar::updateVisualParams()
 	updateHeadOffset();
 }
 
+/*virtual*/ 
+void LLVOAvatar::computeBodySize()
+{
+	LLAvatarAppearance::computeBodySize();
+
+	// Certain configurations of avatars can force the overall height (with offset) to go negative.
+	// Enforce a constraint to make sure we don't go below 0.1 meters.
+	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
+	if (isSelf() && getWearableData())
+	{
+		LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0);
+		if (shape && shape->getVolitile()) 
+		{
+			F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER);
+			if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f))
+			{
+				hover_value = -(mBodySize.mV[VZ] - 1.1f); // avoid floating point rounding making the above check continue to fail.
+				llassert(mBodySize.mV[VZ] + hover_value >= 1.1f);
+
+				hover_value =  llmin(hover_value, 0.0f); // don't force the hover value to be greater than 0.
+
+				mAvatarOffset.mV[VZ] = hover_value;
+				shape->setVisualParamWeight(AVATAR_HOVER,hover_value, FALSE);
+
+			}
+		}
+	}
+}
+
+
 //-----------------------------------------------------------------------------
 // isActive()
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 98e8491cb1..19ad49d3a1 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -212,6 +212,9 @@ public:
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
 	virtual void			updateVisualParams();
 
+	/*virtual*/ void		computeBodySize();
+
+
 
 /**                    Inherited
  **                                                                            **
-- 
cgit v1.2.3


From f3cc77377a689fdb8a8ddbbf47e65f5af957a72b Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Fri, 3 May 2013 12:17:43 -0400
Subject: Updated appearance util.

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index fdd2cb2d67..56f4385fa5 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>e452ebec5a7fce6b3345a6682c250c6e</string>
+              <string>b1f23031c5814c142b1d35bd5d8ffd67</string>
               <key>url</key>
-	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275124/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130501.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275241/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130503.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From be008638aaa7e77ea5916167296467d9e7c8cafd Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 3 May 2013 14:37:06 -0500
Subject: Updated appearance package

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 56f4385fa5..e26a944db4 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b1f23031c5814c142b1d35bd5d8ffd67</string>
+              <string>c56041be22b709bd6d96ec55cea76943</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275241/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130503.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275254/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130503.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From 668a822ace1a7f1dffd090bbdd68712c31d0ac5c Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 3 May 2013 17:30:36 -0400
Subject: SH-4147 FIX Macro avatars with hover==0 look incorrect on relog

Inverted logic meant that we would enforce minimums only while
in preview renders, not for actual user adjustments. This seems to fix it.
---
 indra/newview/llvoavatar.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 3189507b53..e2ed6f54cc 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5225,7 +5225,7 @@ void LLVOAvatar::computeBodySize()
 	if (isSelf() && getWearableData())
 	{
 		LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0);
-		if (shape && shape->getVolitile()) 
+		if (shape && !shape->getVolitile()) 
 		{
 			F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER);
 			if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f))
-- 
cgit v1.2.3


From 0ef6ca8879738b23eb7b6d99413ae7b6ca32b546 Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Fri, 3 May 2013 19:57:40 -0400
Subject: Updated llappearanceutility-source package.

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index e26a944db4..c1254a47f7 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>c56041be22b709bd6d96ec55cea76943</string>
+              <string>9106d605d19c5f48ab6d89b015bf816c</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275254/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130503.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275275/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130503.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From c9aae997a00c994c6e9fee08d09de64d5745cb16 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Mon, 6 May 2013 10:43:18 -0400
Subject: LLAppearance package update

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index c1254a47f7..061f2bbc43 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>9106d605d19c5f48ab6d89b015bf816c</string>
+              <string>3d748c32332c6d0dac95168bd4ecdaa6</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275275/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130503.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275316/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130506.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From e6bc0c5d695796c56bdc2a53f5db594e93e58aff Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Mon, 6 May 2013 18:31:17 -0400
Subject: SH-4147 FIX macro avatars with low hover look wrong after relog

Preventing hover limit from being applied during startup or shutdown
when the rigged mesh may not be fully loaded.
---
 indra/newview/llvoavatar.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index e2ed6f54cc..8e7bed39c4 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5222,7 +5222,7 @@ void LLVOAvatar::computeBodySize()
 	// Certain configurations of avatars can force the overall height (with offset) to go negative.
 	// Enforce a constraint to make sure we don't go below 0.1 meters.
 	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
-	if (isSelf() && getWearableData())
+	if (isSelf() && getWearableData() && isFullyLoaded() && !LLApp::isQuitting())
 	{
 		LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0);
 		if (shape && !shape->getVolitile()) 
-- 
cgit v1.2.3


From 9881b65845b7320a2fc23b8ebc2a68996840ca16 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 7 May 2013 16:12:18 -0400
Subject: SH-4154 FIX - added a few more validity checks. Disabled by default
 so users won't have logs spammed.

---
 indra/newview/llinventorymodel.cpp                | 92 +++++++++++++++++++++--
 indra/newview/llinventorymodelbackgroundfetch.cpp |  1 +
 2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index f60fd63eee..bb5da2e9db 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2267,10 +2267,10 @@ void LLInventoryModel::buildParentChildMap()
 		}
 	}
 
-	//if (!gInventory.validate())
-	//{
-	//	llwarns << "model failed validity check!" << llendl;
-	//}
+	// if (!gInventory.validate())
+	// {
+	// 	llwarns << "model failed validity check!" << llendl;
+	// }
 }
 
 struct LLUUIDAndName
@@ -3002,7 +3002,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
 		// If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
 		if (gInventory.getItem(titem->getUUID()))
 		{
-			lldebugs << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
+			llinfos << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
 			continue;
 		}
 		gInventory.updateItem(titem);
@@ -3458,7 +3458,8 @@ bool LLInventoryModel::validate() const
 		}
 		else if (cats->size() + items->size() != cat->getDescendentCount())
 		{
-			llwarns << "invalid desc count for " << cat_id << " name " << cat->getName()
+			llwarns << "invalid desc count for " << cat_id << " name [" << cat->getName()
+					<< "] parent " << cat->getParentUUID()
 					<< " cached " << cat->getDescendentCount()
 					<< " expected " << cats->size() << "+" << items->size()
 					<< "=" << cats->size() +items->size() << llendl;
@@ -3538,7 +3539,86 @@ bool LLInventoryModel::validate() const
 			}
 		}
 
+		// Does this category appear as a child of its supposed parent?
+		const LLUUID& parent_id = cat->getParentUUID();
+		if (!parent_id.isNull())
+		{
+			cat_array_t* cats;
+			item_array_t* items;
+			getDirectDescendentsOf(parent_id,cats,items);
+			if (!cats)
+			{
+				llwarns << "cat " << cat_id << " name [" << cat->getName()
+						<< "] orphaned - no child cat array for alleged parent " << parent_id << llendl;
+				valid = false;
+			}
+			else
+			{
+				bool found = false;
+				for (S32 i = 0; i<cats->size(); i++)
+				{
+					LLViewerInventoryCategory *kid_cat = cats->get(i);
+					if (kid_cat == cat)
+					{
+						found = true;
+						break;
+					}
+				}
+				if (!found)
+				{
+					llwarns << "cat " << cat_id << " name [" << cat->getName()
+							<< "] orphaned - not found in child cat array of alleged parent " << parent_id << llendl;
+				}
+			}
+		}
+	}
+
+	for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+	{
+		const LLUUID& item_id = iit->first;
+		LLViewerInventoryItem *item = iit->second;
+		if (item->getUUID() != item_id)
+		{
+			llwarns << "item_id " << item_id << " does not match " << item->getUUID() << llendl;
+			valid = false;
+		}
+
+		const LLUUID& parent_id = item->getParentUUID();
+		if (parent_id.isNull())
+		{
+			llwarns << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << llendl;
+		}
+		else
+		{
+			cat_array_t* cats;
+			item_array_t* items;
+			getDirectDescendentsOf(parent_id,cats,items);
+			if (!items)
+			{
+				llwarns << "item " << item_id << " name [" << item->getName()
+						<< "] orphaned - alleged parent has no child items list " << parent_id << llendl;
+			}
+			else
+			{
+				bool found = false;
+				for (S32 i=0; i<items->size(); ++i)
+				{
+					if (items->get(i) == item) 
+					{
+						found = true;
+						break;
+					}
+				}
+				if (!found)
+				{
+					llwarns << "item " << item_id << " name [" << item->getName()
+							<< "] orphaned - not found as child of alleged parent " << parent_id << llendl;
+				}
+			}
+				
+		}
 	}
+	
 	if (cat_lock > 0 || item_lock > 0)
 	{
 		llwarns << "Found locks on some categories: sub-cat arrays "
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 4eeb528c66..864f38cbde 100755
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -176,6 +176,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
 		//gInventory.validate();
 	}
 	mFolderFetchActive = false;
+	mBackgroundFetchActive = false;
 }
 
 void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
-- 
cgit v1.2.3


From 23c6016481ebc6de5433b9e9b9d07ebc4d5ae3cd Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Wed, 8 May 2013 16:34:12 -0400
Subject: SH-4048 SH-4171 SH-4046 FIX avatar sinks into ground, updates sent to
 observers

Avatar preview code was triggering avatar size updates, which were causing the
avatar's height above the ground to change when the previews were rendered.

Also added code to suppress appearance updates being sent out while in
appearance editing mode.
---
 indra/newview/llagent.cpp     | 2 +-
 indra/newview/lltoolmorph.cpp | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 939d9398b2..883200c0f5 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4296,7 +4296,7 @@ void LLAgent::sendAgentSetAppearance()
 		return;
 	}
 
-	if (!isAgentAvatarValid() || (getRegion() && getRegion()->getCentralBakeVersion())) return;
+	if (!isAgentAvatarValid() || gAgentAvatarp->isEditingAppearance() || (getRegion() && getRegion()->getCentralBakeVersion())) return;
 
 	// At this point we have a complete appearance to send and are in a non-baking region.
 	// DRANO FIXME
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index f39b98dd31..fa94b52362 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -159,7 +159,9 @@ void LLVisualParamHint::preRender(BOOL clear_depth)
 	gAgentAvatarp->setVisualParamWeight("Blink_Left", 0.f);
 	gAgentAvatarp->setVisualParamWeight("Blink_Right", 0.f);
 	gAgentAvatarp->updateComposites();
-	gAgentAvatarp->updateVisualParams();
+	// Calling LLCharacter version, as we don't want position/height changes to cause the avatar to jump
+	// up and down when we're doing preview renders. -Nyx
+	gAgentAvatarp->LLCharacter::updateVisualParams();
 	gAgentAvatarp->updateGeometry(gAgentAvatarp->mDrawable);
 	gAgentAvatarp->updateLOD();
 
-- 
cgit v1.2.3


From 228178ac15f60f9b66b72a9d3f13e706d7d6de36 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 9 May 2013 11:01:29 -0400
Subject: SH-4168 WIP - fixed some bugs in inventory deletion and
 lost-and-found handling.

---
 indra/newview/llinventorymodel.cpp | 121 +++++++++++++++++++++++++------------
 1 file changed, 84 insertions(+), 37 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index bb5da2e9db..b49e617f62 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1197,14 +1197,39 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id)
 		}
 
 		count = categories.count();
-		for(S32 i = 0; i < count; ++i)
+		// Slightly kludgy way to make sure categories are removed
+		// only after their child categories have gone away.
+
+		// FIXME: Would probably make more sense to have this whole
+		// descendent-clearing thing be a post-order recursive
+		// function to get the leaf-up behavior automatically.
+		S32 deleted_count;
+		S32 total_deleted_count = 0;
+		do
 		{
-			uu_id = categories.get(i)->getUUID();
-			if (getCategory(uu_id))
+			deleted_count = 0;
+			for(S32 i = 0; i < count; ++i)
 			{
-				deleteObject(uu_id);
+				uu_id = categories.get(i)->getUUID();
+				if (getCategory(uu_id))
+				{
+					cat_array_t* cat_list = getUnlockedCatArray(uu_id);
+					if (!cat_list || (cat_list->size() == 0))
+					{
+						deleteObject(uu_id);
+						deleted_count++;
+					}
+				}
 			}
+			total_deleted_count += deleted_count;
+		}
+		while (deleted_count > 0);
+		if (total_deleted_count != count)
+		{
+			llwarns << "Unexpected count of categories deleted, got "
+					<< total_deleted_count << " expected " << count << llendl;
 		}
+		gInventory.validate();
 	}
 }
 
@@ -1258,12 +1283,20 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 	item_list = getUnlockedItemArray(id);
 	if(item_list)
 	{
+		if (item_list->size())
+		{
+			llwarns << "Deleting cat " << id << " while it still has child items" << llendl;
+		}
 		delete item_list;
 		mParentChildItemTree.erase(id);
 	}
 	cat_list = getUnlockedCatArray(id);
 	if(cat_list)
 	{
+		if (cat_list->size())
+		{
+			llwarns << "Deleting cat " << id << " while it still has child cats" << llendl;
+		}
 		delete cat_list;
 		mParentChildCategoryTree.erase(id);
 	}
@@ -2084,11 +2117,16 @@ void LLInventoryModel::buildParentChildMap()
 	S32 count = cats.count();
 	S32 i;
 	S32 lost = 0;
+	cat_array_t lost_cats;
 	for(i = 0; i < count; ++i)
 	{
 		LLViewerInventoryCategory* cat = cats.get(i);
 		catsp = getUnlockedCatArray(cat->getParentUUID());
-		if(catsp)
+		if(catsp &&
+		   // Only the two root folders should be children of null.
+		   // Others should go to lost & found.
+		   (cat->getParentUUID().notNull() || 
+			cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY ))
 		{
 			catsp->put(cat);
 		}
@@ -2103,34 +2141,7 @@ void LLInventoryModel::buildParentChildMap()
 			llinfos << "Lost category: " << cat->getUUID() << " - "
 					<< cat->getName() << llendl;
 			++lost;
-			// plop it into the lost & found.
-			LLFolderType::EType pref = cat->getPreferredType();
-			if(LLFolderType::FT_NONE == pref)
-			{
-				cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
-			}
-			else if(LLFolderType::FT_ROOT_INVENTORY == pref)
-			{
-				// it's the root
-				cat->setParent(LLUUID::null);
-			}
-			else
-			{
-				// it's a protected folder.
-				cat->setParent(gInventory.getRootFolderID());
-			}
-			// FIXME note that updateServer() fails with protected
-			// types, so this will not work as intended in that case.
-			cat->updateServer(TRUE);
-			catsp = getUnlockedCatArray(cat->getParentUUID());
-			if(catsp)
-			{
-				catsp->put(cat);
-			}
-			else
-			{		
-				llwarns << "Lost and found Not there!!" << llendl;
-			}
+			lost_cats.put(cat);
 		}
 	}
 	if(lost)
@@ -2138,6 +2149,42 @@ void LLInventoryModel::buildParentChildMap()
 		llwarns << "Found  " << lost << " lost categories." << llendl;
 	}
 
+	// Do moves in a separate pass to make sure we've properly filed
+	// the FT_LOST_AND_FOUND category before we try to find its UUID.
+	for(i = 0; i<lost_cats.count(); ++i)
+	{
+		LLViewerInventoryCategory *cat = lost_cats.get(i);
+
+		// plop it into the lost & found.
+		LLFolderType::EType pref = cat->getPreferredType();
+		if(LLFolderType::FT_NONE == pref)
+		{
+			cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
+		}
+		else if(LLFolderType::FT_ROOT_INVENTORY == pref)
+		{
+			// it's the root
+			cat->setParent(LLUUID::null);
+		}
+		else
+		{
+			// it's a protected folder.
+			cat->setParent(gInventory.getRootFolderID());
+		}
+		// FIXME note that updateServer() fails with protected
+		// types, so this will not work as intended in that case.
+		cat->updateServer(TRUE);
+		catsp = getUnlockedCatArray(cat->getParentUUID());
+		if(catsp)
+		{
+			catsp->put(cat);
+		}
+		else
+		{		
+			llwarns << "Lost and found Not there!!" << llendl;
+		}
+	}
+
 	const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null);
 	sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
 
@@ -2267,10 +2314,10 @@ void LLInventoryModel::buildParentChildMap()
 		}
 	}
 
-	// if (!gInventory.validate())
-	// {
-	// 	llwarns << "model failed validity check!" << llendl;
-	// }
+	if (!gInventory.validate())
+	{
+	 	llwarns << "model failed validity check!" << llendl;
+	}
 }
 
 struct LLUUIDAndName
-- 
cgit v1.2.3


From d4e537b3ef1319af451eeebc31bbe080242ed7d5 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 9 May 2013 16:41:55 -0400
Subject: SH-4176 WIP - made debugCOF() slightly harder to get to.

---
 indra/newview/llappearancemgr.cpp | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 40ec88f1be..543eb04c0b 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2947,7 +2947,7 @@ protected:
 
 	void debugCOF(const LLSD& content)
 	{
-		LL_DEBUGS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl;
+		LL_INFOS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl;
 		std::set<LLUUID> ais_items, local_items;
 		const LLSD& cof_raw = content["cof_raw"];
 		for (LLSD::array_const_iterator it = cof_raw.beginArray();
@@ -2959,14 +2959,14 @@ protected:
 				ais_items.insert(item["item_id"].asUUID());
 				if (item["type"].asInteger() == 24) // link
 				{
-					LL_DEBUGS("Avatar") << "Link: item_id: " << item["item_id"].asUUID()
+					LL_INFOS("Avatar") << "Link: item_id: " << item["item_id"].asUUID()
 										<< " linked_item_id: " << item["asset_id"].asUUID()
 										<< " name: " << item["name"].asString()
 										<< llendl; 
 				}
 				else if (item["type"].asInteger() == 25) // folder link
 				{
-					LL_DEBUGS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID()
+					LL_INFOS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID()
 										<< " linked_item_id: " << item["asset_id"].asUUID()
 										<< " name: " << item["name"].asString()
 										<< llendl; 
@@ -2974,15 +2974,15 @@ protected:
 				}
 				else
 				{
-					LL_DEBUGS("Avatar") << "Other: item_id: " << item["item_id"].asUUID()
+					LL_INFOS("Avatar") << "Other: item_id: " << item["item_id"].asUUID()
 										<< " linked_item_id: " << item["asset_id"].asUUID()
 										<< " name: " << item["name"].asString()
 										<< llendl; 
 				}
 			}
 		}
-		LL_DEBUGS("Avatar") << llendl;
-		LL_DEBUGS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl;
+		LL_INFOS("Avatar") << llendl;
+		LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl;
 		LLInventoryModel::cat_array_t cat_array;
 		LLInventoryModel::item_array_t item_array;
 		gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
@@ -2991,24 +2991,24 @@ protected:
 		{
 			const LLViewerInventoryItem* inv_item = item_array.get(i).get();
 			local_items.insert(inv_item->getUUID());
-			LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID()
+			LL_INFOS("Avatar") << "item_id: " << inv_item->getUUID()
 								<< " linked_item_id: " << inv_item->getLinkedUUID()
 								<< " name: " << inv_item->getName()
 								<< llendl;
 		}
-		LL_DEBUGS("Avatar") << llendl;
+		LL_INFOS("Avatar") << llendl;
 		for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
 		{
 			if (ais_items.find(*it) == ais_items.end())
 			{
-				LL_DEBUGS("Avatar") << "LOCAL ONLY: " << *it << llendl;
+				LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl;
 			}
 		}
 		for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
 		{
 			if (local_items.find(*it) == local_items.end())
 			{
-				LL_DEBUGS("Avatar") << "AIS ONLY: " << *it << llendl;
+				LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl;
 			}
 		}
 	}
-- 
cgit v1.2.3


From 55e686b0e305fa14ae5e40f7917f0ce3f3e3c6a1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 10 May 2013 07:52:22 -0400
Subject: SH-4176 WIP - tweaks to debugCOF(), which shows differences between
 viewer and server side views of the COF when a mismatch occurs

---
 indra/newview/llappearancemgr.cpp | 49 ++++++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 543eb04c0b..e8bdb0d7ec 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2947,7 +2947,8 @@ protected:
 
 	void debugCOF(const LLSD& content)
 	{
-		LL_INFOS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl;
+		LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
+						   << " ================================= " << llendl;
 		std::set<LLUUID> ais_items, local_items;
 		const LLSD& cof_raw = content["cof_raw"];
 		for (LLSD::array_const_iterator it = cof_raw.beginArray();
@@ -2959,30 +2960,32 @@ protected:
 				ais_items.insert(item["item_id"].asUUID());
 				if (item["type"].asInteger() == 24) // link
 				{
-					LL_INFOS("Avatar") << "Link: item_id: " << item["item_id"].asUUID()
-										<< " linked_item_id: " << item["asset_id"].asUUID()
-										<< " name: " << item["name"].asString()
-										<< llendl; 
+					LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
+									   << " linked_item_id: " << item["asset_id"].asUUID()
+									   << " name: " << item["name"].asString()
+									   << llendl; 
 				}
 				else if (item["type"].asInteger() == 25) // folder link
 				{
-					LL_INFOS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID()
-										<< " linked_item_id: " << item["asset_id"].asUUID()
-										<< " name: " << item["name"].asString()
-										<< llendl; 
+					LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
+									   << " linked_item_id: " << item["asset_id"].asUUID()
+									   << " name: " << item["name"].asString()
+									   << llendl; 
 					
 				}
 				else
 				{
-					LL_INFOS("Avatar") << "Other: item_id: " << item["item_id"].asUUID()
-										<< " linked_item_id: " << item["asset_id"].asUUID()
-										<< " name: " << item["name"].asString()
-										<< llendl; 
+					LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID()
+									   << " linked_item_id: " << item["asset_id"].asUUID()
+									   << " name: " << item["name"].asString()
+									   << " type: " << item["type"].asInteger()
+									   << llendl; 
 				}
 			}
 		}
 		LL_INFOS("Avatar") << llendl;
-		LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl;
+		LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() 
+						   << " ================================= " << llendl;
 		LLInventoryModel::cat_array_t cat_array;
 		LLInventoryModel::item_array_t item_array;
 		gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
@@ -2991,12 +2994,13 @@ protected:
 		{
 			const LLViewerInventoryItem* inv_item = item_array.get(i).get();
 			local_items.insert(inv_item->getUUID());
-			LL_INFOS("Avatar") << "item_id: " << inv_item->getUUID()
-								<< " linked_item_id: " << inv_item->getLinkedUUID()
-								<< " name: " << inv_item->getName()
-								<< llendl;
+			LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
+							   << " linked_item_id: " << inv_item->getLinkedUUID()
+							   << " name: " << inv_item->getName()
+							   << " parent: " << inv_item->getParentUUID()
+							   << llendl;
 		}
-		LL_INFOS("Avatar") << llendl;
+		LL_INFOS("Avatar") << " ================================= " << llendl;
 		for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
 		{
 			if (ais_items.find(*it) == ais_items.end())
@@ -3011,6 +3015,13 @@ protected:
 				LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl;
 			}
 		}
+		if (local_items.size()==0 && ais_items.size()==0)
+		{
+			LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
+							   << content["observed"].asInteger()
+							   << " rcv " << content["expected"].asInteger()
+							   << ")" << llendl;
+		}
 	}
 
 	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-- 
cgit v1.2.3


From 43224062a64cc658d429e434a7b673fac0b7c012 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 10 May 2013 09:19:34 -0400
Subject: SH-4176 WIP - avoid raw dump of whole error contents in log file

---
 indra/newview/llappearancemgr.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index e8bdb0d7ec..3c141aa37a 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2905,15 +2905,14 @@ protected:
 	// Error
 	/*virtual*/ void httpFailure()
 	{
-		const LLSD& content = getContent();
-		LL_WARNS("Avatar") << "appearance update request failed "
-						   << dumpResponse() << LL_ENDL;
+		LL_WARNS("Avatar") << "appearance update request failed, status "
+						   << getStatus() << " reason " << getReason() << LL_ENDL;
 
 		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
+			const LLSD& content = getContent();
 			dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
 			debugCOF(content);
-		
 		}
 		onFailure();
 	}
-- 
cgit v1.2.3


From 96a2173c643e145a6f5d4964282c4d43f0fc0c3e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 10 May 2013 09:32:30 -0400
Subject: SH-4176 WIP - allow retries on 4xx errors if enabled by flag. So
 enable in the case of appearance requests.

---
 indra/newview/llappearancemgr.cpp              |  3 ++-
 indra/newview/llhttpretrypolicy.cpp            |  7 ++++---
 indra/newview/llhttpretrypolicy.h              |  3 ++-
 indra/newview/tests/llhttpretrypolicy_test.cpp | 15 +++++++++++----
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 3c141aa37a..84a494186f 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2871,7 +2871,8 @@ class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
 public:
 	RequestAgentUpdateAppearanceResponder()
 	{
-		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
+		bool retry_on_4xx = true;
+		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx);
 	}
 
 	virtual ~RequestAgentUpdateAppearanceResponder()
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 80d97e4362..1512b46103 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -28,11 +28,12 @@
 
 #include "llhttpretrypolicy.h"
 
-LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries):
+LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx):
 	mMinDelay(min_delay),
 	mMaxDelay(max_delay),
 	mBackoffFactor(backoff_factor),
-	mMaxRetries(max_retries)
+	mMaxRetries(max_retries),
+	mRetryOn4xx(retry_on_4xx)
 {
 	init();
 }
@@ -108,7 +109,7 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti
 		llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl;
 		mShouldRetry = false;
 	}
-	if (!isHttpServerErrorStatus(status))
+	if (!mRetryOn4xx && !isHttpServerErrorStatus(status))
 	{
 		llinfos << "Non-server error " << status << ", will not retry" << llendl;
 		mShouldRetry = false;
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
index 1fb0cac03f..5b1a1d79e0 100755
--- a/indra/newview/llhttpretrypolicy.h
+++ b/indra/newview/llhttpretrypolicy.h
@@ -60,7 +60,7 @@ public:
 class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
 {
 public:
-	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries);
+	LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx = false);
 
 	// virtual
 	void onSuccess();
@@ -88,6 +88,7 @@ private:
 	U32 mRetryCount; // number of times shouldRetry has been called.
 	LLTimer mRetryTimer; // time until next retry.
 	bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc.
+	bool mRetryOn4xx; // Normally only retry on 5xx server errors.
 };
 
 #endif
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index ed7f3ba326..25e6de46d9 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -56,12 +56,19 @@ void RetryPolicyTestObject::test<1>()
 template<> template<>
 void RetryPolicyTestObject::test<2>()
 {
-	LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10);
 	LLSD headers;
 	F32 wait_seconds;
-	
-	retry404.onFailure(404,headers);
-	ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); 
+
+	// Normally only retry on server error (5xx)
+	LLAdaptiveRetryPolicy noRetry404(1.0,2.0,3.0,10);
+	noRetry404.onFailure(404,headers);
+	ensure("no retry on 404", !noRetry404.shouldRetry(wait_seconds)); 
+
+	// Can retry on 4xx errors if enabled by flag.
+	bool do_retry_4xx = true;
+	LLAdaptiveRetryPolicy doRetry404(1.0,2.0,3.0,10,do_retry_4xx);
+	doRetry404.onFailure(404,headers);
+	ensure("do retry on 404", doRetry404.shouldRetry(wait_seconds)); 
 }
 
 template<> template<>
-- 
cgit v1.2.3


From 5c219f694a97d010332618eff9de7bdbeb5b6ed6 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 10 May 2013 12:58:41 -0400
Subject: DEBUG adding additional logging for avatar height usually disabled,
 enable avatar in logcontrol.xml to get output.

---
 indra/newview/llagent.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 883200c0f5..d7ab68ccd1 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4337,7 +4337,9 @@ void LLAgent::sendAgentSetAppearance()
 	// to compensate for the COLLISION_TOLERANCE ugliness we will have 
 	// to tweak this number again
 	const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset;
-	msg->addVector3Fast(_PREHASH_Size, body_size);	
+	msg->addVector3Fast(_PREHASH_Size, body_size);
+	
+	LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mv[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL;	
 
 	// To guard against out of order packets
 	// Note: always start by sending 1.  This resets the server's count. 0 on the server means "uninitialized"
-- 
cgit v1.2.3


From cd9acddf09ba80a3a2249194256217882c71bf7c Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 10 May 2013 13:04:18 -0400
Subject: BUILDFIX capitalization error

---
 indra/newview/llagent.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index d7ab68ccd1..21625815b9 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4339,7 +4339,7 @@ void LLAgent::sendAgentSetAppearance()
 	const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset;
 	msg->addVector3Fast(_PREHASH_Size, body_size);
 	
-	LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mv[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL;	
+	LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mV[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL;	
 
 	// To guard against out of order packets
 	// Note: always start by sending 1.  This resets the server's count. 0 on the server means "uninitialized"
-- 
cgit v1.2.3


From 3f1d360a04c4e4d8f07b7e93cd926961ae379430 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 10 May 2013 13:57:02 -0500
Subject: SH-4035: Removed prompt to save if av just has outfit changes. Hooked
 up logic to handle ctrl+w and ctrl+shift+w confirmation prompts

---
 indra/llui/llfloater.cpp                      | 31 +++++++++++++++++++++----
 indra/llui/llfloater.h                        |  3 ++-
 indra/llui/llpanel.cpp                        | 22 ++++++++++++++++--
 indra/llui/llpanel.h                          | 10 +++++++-
 indra/newview/llfloatersidepanelcontainer.cpp | 33 +++++++++++++++++++++++++++
 indra/newview/llfloatersidepanelcontainer.h   |  3 ++-
 indra/newview/llsidepanelappearance.cpp       | 22 ++++++++++--------
 7 files changed, 104 insertions(+), 20 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 09e27a264a..28dfda8faf 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -704,9 +704,15 @@ void LLFloater::openFloater(const LLSD& key)
 	dirtyRect();
 }
 
+void LLFloater::verifyClose()
+{
+	LLPanel::handleCloseConfirmation();
+}
+
 void LLFloater::closeFloater(bool app_quitting)
 {
 	llinfos << "Closing floater " << getName() << llendl;
+	
 	if (app_quitting)
 	{
 		LLFloater::sQuitting = true;
@@ -781,7 +787,7 @@ void LLFloater::closeFloater(bool app_quitting)
 		dirtyRect();
 
 		// Close callbacks
-		onClose(app_quitting);
+		onClose(app_quitting);	
 		mCloseSignal(this, LLSD(app_quitting));
 		
 		// Hide or Destroy
@@ -1788,11 +1794,19 @@ void LLFloater::initRectControl()
 void LLFloater::closeFrontmostFloater()
 {
 	LLFloater* floater_to_close = gFloaterView->getFrontmostClosableFloater();
-	if(floater_to_close)
+	if( floater_to_close )
 	{
-		floater_to_close->closeFloater();
+		if ( floater_to_close->mVerifyUponClose )
+		{			
+			floater_to_close->verifyClose();
+			//Closing of the window handle in the subclass - so bug out here.
+			return;
+		}
+		else
+		{
+			floater_to_close->closeFloater();
+		}
 	}
-
 	// if nothing took focus after closing focused floater
 	// give it to next floater (to allow closing multiple windows via keyboard in rapid succession)
 	if (gFocusMgr.getKeyboardFocus() == NULL)
@@ -2631,7 +2645,14 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
 		if (floaterp->canClose() && !floaterp->isDead() &&
 			(app_quitting || floaterp->getVisible()))
 		{
-			floaterp->closeFloater(app_quitting);
+			if ( floaterp->mVerifyUponClose )
+			{			
+				floaterp->verifyClose();
+			}
+			else
+			{
+				floaterp->closeFloater(app_quitting);
+			}
 		}
 	}
 }
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 4dba1e645f..bf71b527b3 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -225,6 +225,7 @@ public:
 
 	// If allowed, close the floater cleanly, releasing focus.
 	virtual void	closeFloater(bool app_quitting = false);
+	virtual void	verifyClose();
 
 	// Close the floater or its host. Use when hidding or toggling a floater instance.
 	virtual void	closeHostedFloater();
@@ -303,7 +304,7 @@ public:
 
 	/*virtual*/ void setVisible(BOOL visible); // do not override
 	/*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
-	
+				void handleCloseConfirmation( );
 	void			setFrontmost(BOOL take_focus = TRUE);
     virtual void	setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());    
 	
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 67472ad166..01165a5718 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -114,7 +114,9 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 	mCommitCallbackRegistrar(false),
 	mEnableCallbackRegistrar(false),
 	mXMLFilename(p.filename),
-	mVisibleSignal(NULL)
+	mVisibleSignal(NULL),
+	mCloseConfirmationSignal(NULL),
+	mVerifyUponClose(false)
 	// *NOTE: Be sure to also change LLPanel::initFromParams().  We have too
 	// many classes derived from LLPanel to retrofit them all to pass in params.
 {
@@ -127,6 +129,7 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 LLPanel::~LLPanel()
 {
 	delete mVisibleSignal;
+	delete mCloseConfirmationSignal;
 }
 
 // virtual
@@ -349,6 +352,14 @@ void LLPanel::handleVisibilityChange ( BOOL new_visibility )
 		(*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass BOOL as LLSD
 }
 
+
+void LLPanel::handleCloseConfirmation( )
+{	
+	if (mCloseConfirmationSignal)
+	{
+		(*mCloseConfirmationSignal)(this, LLSD() ); 
+	}
+}
 void LLPanel::setFocus(BOOL b)
 {
 	if( b && !hasFocus())
@@ -959,10 +970,17 @@ boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::
 	{
 		mVisibleSignal = new commit_signal_t();
 	}
-
 	return mVisibleSignal->connect(cb);
 }
 
+boost::signals2::connection LLPanel::setCloseConfirmationCallback( const commit_signal_t::slot_type& cb )
+{
+	if (!mCloseConfirmationSignal)
+	{
+		mCloseConfirmationSignal = new commit_signal_t();
+	}	
+	return mCloseConfirmationSignal->connect(cb);
+}
 static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index e63b41f97c..1b0beaa5c8 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -116,6 +116,8 @@ public:
 	/*virtual*/ void	draw();	
 	/*virtual*/ BOOL	handleKeyHere( KEY key, MASK mask );
 	/*virtual*/ void 	handleVisibilityChange ( BOOL new_visibility );
+				void	handleCloseConfirmation( );
+
 
 	// From LLFocusableElement
 	/*virtual*/ void	setFocus( BOOL b );
@@ -251,6 +253,10 @@ public:
 	std::string getXMLFilename() { return mXMLFilename; };
 	
 	boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
+	boost::signals2::connection setCloseConfirmationCallback( const commit_signal_t::slot_type& cb );
+
+public:
+	const BOOL confirmClose() const { return mVerifyUponClose; }
 
 protected:
 	// Override to set not found list
@@ -260,6 +266,7 @@ protected:
 	EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
 
 	commit_signal_t* mVisibleSignal;		// Called when visibility changes, passes new visibility as LLSD()
+	commit_signal_t* mCloseConfirmationSignal; 
 
 	std::string		mHelpTopic;         // the name of this panel's help topic to display in the Help Viewer
 	typedef std::deque<const LLCallbackMap::map_t*> factory_stack_t;
@@ -267,7 +274,8 @@ protected:
 
 	// for setting the xml filename when building panel in context dependent cases
 	std::string		mXMLFilename;
-	
+	//Specific close-down logic in subclass
+	BOOL			mVerifyUponClose;
 private:
 	BOOL			mBgVisible;				// any background at all?
 	BOOL			mBgOpaque;				// use opaque color or image
diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index 4dd558c9c0..43ee54ecd2 100644
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -45,6 +45,39 @@ LLFloaterSidePanelContainer::LLFloaterSidePanelContainer(const LLSD& key, const
 	// Prevent transient floaters (e.g. IM windows) from hiding
 	// when this floater is clicked.
 	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this);
+	//We want this container to handle the shutdown logic of the sidepanelappearance.
+	mVerifyUponClose = TRUE;
+}
+
+BOOL LLFloaterSidePanelContainer::postBuild()
+{
+	setCloseConfirmationCallback( boost::bind(&LLFloaterSidePanelContainer::onConfirmationClose,this,_2));
+	return TRUE;
+}
+
+void  LLFloaterSidePanelContainer::onConfirmationClose( const LLSD &confirm )
+{
+	/*
+	LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
+	if (panel_outfit_edit)
+	{
+		LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
+		if (parent == this )
+		{
+			LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
+			panel_appearance->onClose(this);			
+		}
+		else
+		{
+			LLFloater::onClickCloseBtn();
+		}
+	}
+	else
+	{
+		LLFloater::onClickCloseBtn();
+	}
+	*/
+	onClickCloseBtn();
 }
 
 LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer()
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index 940673b643..26fc092200 100644
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -50,8 +50,9 @@ public:
 	~LLFloaterSidePanelContainer();
 
 	/*virtual*/ void onOpen(const LLSD& key);
-
 	/*virtual*/ void onClickCloseBtn();
+	/*virtual*/ BOOL postBuild();
+				void  onConfirmationClose( const LLSD &confirm );
 
 	LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params);
 
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 77e9604460..f77275fd1c 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -90,11 +90,12 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( option == 0 ) 
 	{	
-		//revert curernt edits
-		mEditWearable->revertChanges();
-		toggleWearableEditPanel(FALSE);
-		LLVOAvatarSelf::onCustomizeEnd(FALSE);	
-		mLLFloaterSidePanelContainer->close();
+		//revert current edits
+		mEditWearable->revertChanges();					
+		//LLAppearanceMgr::getInstance()->wearBaseOutfit();				
+		toggleWearableEditPanel(FALSE);		
+		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
+		mLLFloaterSidePanelContainer->close();			
 		return true;
 	}
 	return false;
@@ -115,7 +116,7 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose()
 
 void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
 {
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened /*&& !LLAppearanceMgr::getInstance()->isOutfitLocked()*/ )
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
 		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) );
@@ -128,9 +129,9 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
 
 void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
 {
-	mLLFloaterSidePanelContainer = obj;
-	if (  LLAppearanceMgr::getInstance()->isOutfitDirty() && 
-		 !LLAppearanceMgr::getInstance()->isOutfitLocked() ||
+	mLLFloaterSidePanelContainer = obj;	
+	if (  /*LLAppearanceMgr::getInstance()->isOutfitDirty() && */
+		 /*!LLAppearanceMgr::getInstance()->isOutfitLocked() ||*/
 		 ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) )
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
@@ -275,8 +276,9 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 
 void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
 {
-	if (new_visibility["visible"].asBoolean())
+	if (new_visibility["visible"].asBoolean() )
 	{
+
 		const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
 		const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
 
-- 
cgit v1.2.3


From 5bb540ddbf8a403f2ed52b2caea78d52950f534b Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Sat, 11 May 2013 04:12:31 +0000
Subject: Updating appearance utility

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 061f2bbc43..b4d7e582cf 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>3d748c32332c6d0dac95168bd4ecdaa6</string>
+              <string>8510897fc575409393cd97fa8f42f8c3</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275316/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130506.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275700/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130511.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From 7ff4d160415ef33157d12e6330e9fdd5c66434d5 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Sat, 11 May 2013 08:28:40 +0000
Subject: Updating appearance utility

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index b4d7e582cf..8de06784f1 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>8510897fc575409393cd97fa8f42f8c3</string>
+              <string>df8857aeb5f44dfd95f9f9f57814423a</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275700/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130511.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275707/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130511.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From 69df2f1b0430dc00519b08bd2f0abd6712d3d2bc Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Mon, 13 May 2013 11:54:37 -0500
Subject: SH-4035: Hooked up logic to handle 'me->appearance'. Refactored out
 some commonly used code in llfloatersidepanelcontainer

---
 indra/newview/llfloatersidepanelcontainer.cpp | 83 +++++++++++++++------------
 indra/newview/llfloatersidepanelcontainer.h   |  5 ++
 indra/newview/llsidepanelappearance.cpp       | 34 +++++++++++
 indra/newview/llsidepanelappearance.h         |  4 +-
 4 files changed, 87 insertions(+), 39 deletions(-)

diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index 43ee54ecd2..3ea39cf196 100644
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -56,30 +56,11 @@ BOOL LLFloaterSidePanelContainer::postBuild()
 }
 
 void  LLFloaterSidePanelContainer::onConfirmationClose( const LLSD &confirm )
-{
-	/*
-	LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
-	if (panel_outfit_edit)
-	{
-		LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
-		if (parent == this )
-		{
-			LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
-			panel_appearance->onClose(this);			
-		}
-		else
-		{
-			LLFloater::onClickCloseBtn();
-		}
-	}
-	else
-	{
-		LLFloater::onClickCloseBtn();
-	}
-	*/
+{	
 	onClickCloseBtn();
 }
 
+
 LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer()
 {
 	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::GLOBAL, this);
@@ -92,20 +73,10 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key)
 
 void LLFloaterSidePanelContainer::onClickCloseBtn()
 {
-	LLPanelOutfitEdit* panel_outfit_edit =
-		dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
-	if (panel_outfit_edit)
+	LLSidepanelAppearance* panel = getSidePanelAppearance();
+	if ( panel )
 	{
-		LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
-		if (parent == this )
-		{
-			LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
-			panel_appearance->onClose(this);			
-		}
-		else
-		{
-			LLFloater::onClickCloseBtn();
-		}
+		panel->onClose( this );			
 	}
 	else
 	{
@@ -114,7 +85,7 @@ void LLFloaterSidePanelContainer::onClickCloseBtn()
 }
 void LLFloaterSidePanelContainer::close()
 {
-		LLFloater::onClickCloseBtn();
+	LLFloater::onClickCloseBtn();
 }
 
 LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params)
@@ -124,7 +95,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na
 
 	if (!getVisible())
 	{
-	openFloater();
+		openFloater();
 	}
 
 	LLPanel* panel = NULL;
@@ -145,10 +116,30 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na
 
 void LLFloaterSidePanelContainer::showPanel(const std::string& floater_name, const LLSD& key)
 {
-	LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>(floater_name);
+	//If we're already open then check whether anything is dirty	 
+	LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>(floater_name);	
 	if (floaterp)
 	{
-		floaterp->openChildPanel(sMainPanelName, key);
+		if ( floaterp->getVisible() )
+		{
+			LLSidepanelAppearance* panel = floaterp->getSidePanelAppearance();
+			if ( panel )
+			{
+				if ( panel->checkForDirtyEdits() )
+				{
+					panel->onClickConfirmExitWithoutSaveIntoAppearance();
+				}
+				else
+				{
+					//or a call into some new f() that just shows inv panel?
+					floaterp->openChildPanel(sMainPanelName, key);
+				}
+			}
+		}
+		else
+		{
+			floaterp->openChildPanel(sMainPanelName, key);
+		}
 	}
 }
 
@@ -172,3 +163,19 @@ LLPanel* LLFloaterSidePanelContainer::getPanel(const std::string& floater_name,
 
 	return NULL;
 }
+
+LLSidepanelAppearance* LLFloaterSidePanelContainer::getSidePanelAppearance()
+{
+	LLSidepanelAppearance* panel_appearance = NULL;
+	LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
+	if (panel_outfit_edit)
+	{
+		LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
+		if (parent == this )
+		{
+			panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
+		}
+	}
+	return panel_appearance;			
+
+}
\ No newline at end of file
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index 26fc092200..974934b48f 100644
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -30,6 +30,8 @@
 
 #include "llfloater.h"
 
+class LLSidepanelAppearance;
+
 /**
  * Class LLFloaterSidePanelContainer
  *
@@ -81,6 +83,9 @@ public:
 		}
 		return panel;
 	}
+
+private:
+	LLSidepanelAppearance* getSidePanelAppearance();
 };
 
 #endif // LL_LLFLOATERSIDEPANELCONTAINER_H
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index f77275fd1c..cf759dd8f7 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -114,6 +114,35 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose()
 	}
 }
 
+
+bool LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if ( option == 0 ) 
+	{	
+		//revert current edits
+		mEditWearable->revertChanges();
+		toggleWearableEditPanel(FALSE);		
+		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
+		//mLLFloaterSidePanelContainer->close();			
+		showOutfitsInventoryPanel();
+		return true;
+	}
+	return false;
+}
+
+void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance()
+{
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	{
+		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
+		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance,pSelf,_1,_2) );
+	}
+	else
+	{
+		showOutfitsInventoryPanel();
+	}
+}
 void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
 {
 	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened /*&& !LLAppearanceMgr::getInstance()->isOutfitLocked()*/ )
@@ -629,3 +658,8 @@ void LLSidepanelAppearance::updateScrollingPanelList()
 		mEditWearable->updateScrollingPanelList();
 	}
 }
+
+bool LLSidepanelAppearance::checkForDirtyEdits()
+{
+	return ( mEditWearable->isDirty() ) ? true : false;
+}
\ No newline at end of file
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 85e7734567..caf5be62e9 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -73,7 +73,9 @@ public:
 	void onClickConfirmExitWithoutSaveViaBack();
 	bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response);
 	void onClickConfirmExitWithoutSaveViaClose();
-
+	bool checkForDirtyEdits();	
+	bool callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response);
+	void onClickConfirmExitWithoutSaveIntoAppearance();
 
 private:
 	void onFilterEdit(const std::string& search_string);
-- 
cgit v1.2.3


From b7161fcd58853fb60900e51a4ac221b02941905e Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Mon, 13 May 2013 16:03:22 -0500
Subject: SH-4035: Removed prompt to save if av just has outfit changes and you
 click on the back button

---
 indra/newview/llsidepanelappearance.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index cf759dd8f7..1b56aff3b6 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -145,12 +145,14 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance()
 }
 void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
 {
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened /*&& !LLAppearanceMgr::getInstance()->isOutfitLocked()*/ )
+	/*
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
 		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) );
 	}
 	else
+		*/
 	{
 		showOutfitsInventoryPanel();
 	}
-- 
cgit v1.2.3


From b1998cabc487c434555276a389ed19847b98f998 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 13 May 2013 17:08:37 -0400
Subject: SH-4168 WIP, SH-4155 WIP - update inventory model based on ais
 returns, try to maintain loading... string more consistently in folder bridge

---
 indra/newview/llinventorybridge.cpp | 18 ++++----
 indra/newview/llinventorymodel.cpp  | 85 +++++++++++++++++++++++++++++++++----
 indra/newview/llinventorymodel.h    | 11 +++--
 indra/newview/llviewerinventory.cpp |  8 ++--
 4 files changed, 96 insertions(+), 26 deletions(-)
 mode change 100644 => 100755 indra/newview/llinventorybridge.cpp

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
old mode 100644
new mode 100755
index 27f35c5946..abebd0aa5e
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1566,18 +1566,18 @@ void LLItemBridge::buildDisplayName() const
 	else
 	{
 		mDisplayName.assign(LLStringUtil::null);
-}
-
+	}
+	
 	mSearchableName.assign(mDisplayName);
 	mSearchableName.append(getLabelSuffix());
 	LLStringUtil::toUpper(mSearchableName);
-
+	
     //Name set, so trigger a sort
     if(mParent)
-{
-        mParent->requestSort();
-	}
+	{
+		mParent->requestSort();
 	}
+}
 
 LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
 {
@@ -1901,8 +1901,7 @@ void LLFolderBridge::update()
 		possibly_has_children = true;
 	}
 
-	bool loading = (possibly_has_children
-		&& !up_to_date );
+	bool loading = (possibly_has_children && !up_to_date );
 
 	if (loading != mIsLoading)
 	{
@@ -1929,12 +1928,13 @@ void LLFolderBridge::update()
 			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive()
 				&&	root_is_loading))
 		{
+			buildDisplayName();
 			mDisplayName = LLInvFVBridge::getDisplayName() + " ( " +   LLTrans::getString("LoadingData") + " ) ";
 			mIsLoading = true;
 		}
 		else
 		{
-			mDisplayName = LLInvFVBridge::getDisplayName();
+			buildDisplayName();
 			mIsLoading = false;
 		}
 	}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b49e617f62..fd57845c0e 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -48,6 +48,7 @@
 #include "llcallbacklist.h"
 #include "llvoavatarself.h"
 #include "llgesturemgr.h"
+#include "llsdutil.h"
 #include <typeinfo>
 
 //#define DIFF_INVENTORY_FILES
@@ -1153,8 +1154,69 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
 	notifyObservers();
 }
 
+void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_vec_t& ids)
+{
+	ids.clear();
+	if (content.has(name))
+	{
+		for(LLSD::array_const_iterator it = content[name].beginArray(),
+				end = content[name].endArray();
+				it != end; ++it)
+		{
+			ids.push_back((*it).asUUID());
+		}
+	}
+}
+
+void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
+{
+	llinfos << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl;
+
+	uuid_vec_t cat_ids;
+	parse_llsd_uuid_array(update,"_categories_removed",cat_ids);
+	for (uuid_vec_t::const_iterator it = cat_ids.begin();
+		 it != cat_ids.end(); ++it)
+	{
+		llinfos << "remove category: " << *it << llendl;
+		onObjectDeletedFromServer(*it, false);
+	}
+
+	uuid_vec_t item_ids;
+	parse_llsd_uuid_array(update,"_category_items_removed",item_ids);
+	for (uuid_vec_t::const_iterator it = item_ids.begin();
+		 it != item_ids.end(); ++it)
+	{
+		llinfos << "remove item: " << *it << llendl;
+		onObjectDeletedFromServer(*it, false);
+	}
+
+	uuid_vec_t broken_link_ids;
+	parse_llsd_uuid_array(update,"_broken_links_removed",broken_link_ids);
+	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
+		 it != broken_link_ids.end(); ++it)
+	{
+		llinfos << "remove broken link: " << *it << llendl;
+		onObjectDeletedFromServer(*it, false);
+	}
+
+	const std::string& ucv = "_updated_category_versions";
+	if (update.has(ucv))
+	{
+		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
+				end = update[ucv].endMap();
+				it != end; ++it)
+		{
+			const LLUUID id((*it).first);
+			S32 version = (*it).second.asInteger();
+			llinfos << "update category: " << id << " to version " << version << llendl;
+		}
+	}
+
+	
+}
+
 // Update model after descendents have been purged.
-void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id)
+void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links)
 {
 	LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
 	if (cat.notNull())
@@ -1192,7 +1254,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id)
 			// of its deleted parent.
 			if (getItem(uu_id))
 			{
-				deleteObject(uu_id);
+				deleteObject(uu_id, fix_broken_links);
 			}
 		}
 
@@ -1216,7 +1278,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id)
 					cat_array_t* cat_list = getUnlockedCatArray(uu_id);
 					if (!cat_list || (cat_list->size() == 0))
 					{
-						deleteObject(uu_id);
+						deleteObject(uu_id, fix_broken_links);
 						deleted_count++;
 					}
 				}
@@ -1235,24 +1297,30 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id)
 
 // Update model after an item is confirmed as removed from
 // server. Works for categories or items.
-void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id)
+void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links)
 {
 	LLPointer<LLInventoryObject> obj = getObject(object_id);
 	if(obj)
 	{
+		if (getCategory(object_id))
+		{
+			// For category, need to delete/update all children first.
+			onDescendentsPurgedFromServer(object_id, fix_broken_links);
+		}
+
 		// From item/cat removeFromServer()
 		LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
 		accountForUpdate(up);
 
 		// From purgeObject()
 		LLPreview::hide(object_id);
-		deleteObject(object_id);
+		deleteObject(object_id, fix_broken_links);
 	}
 }
 
 
 // Delete a particular inventory object by ID.
-void LLInventoryModel::deleteObject(const LLUUID& id)
+void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links)
 {
 	lldebugs << "LLInventoryModel::deleteObject()" << llendl;
 	LLPointer<LLInventoryObject> obj = getObject(id);
@@ -1303,10 +1371,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
 	addChangedMask(LLInventoryObserver::REMOVE, id);
 	
 	// Can't have links to links, so there's no need for this update
-	// if the item removed is a link.
+	// if the item removed is a link. Can also skip if source of the
+	// update is getting broken link info separately.
 	bool is_link_type = obj->getIsLinkType();
 	obj = NULL; // delete obj
-	if (!is_link_type)
+	if (fix_broken_links && !is_link_type)
 	{
 		updateLinkedObjectsFromPurge(id);
 	}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 2459f10a37..696d0a9163 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -328,19 +328,22 @@ public:
 	// Delete
 	//--------------------------------------------------------------------
 public:
-	
+
+	// Update model after an AISv3 update received for any operation.
+	void onAISUpdateReceived(const std::string& context, const LLSD& update);
+		
 	// Update model after an item is confirmed as removed from
 	// server. Works for categories or items.
-	void onObjectDeletedFromServer(const LLUUID& item_id);
+	void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true);
 
 	// Update model after all descendents removed from server.
-	void onDescendentsPurgedFromServer(const LLUUID& object_id);
+	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
 
 	// Delete a particular inventory object by ID. Will purge one
 	// object from the internal data structures, maintaining a
 	// consistent internal state. No cache accounting, observer
 	// notification, or server update is performed.
-	void deleteObject(const LLUUID& id);
+	void deleteObject(const LLUUID& id, bool fix_broken_links = true);
 	/// move Item item_id to Trash
 	void removeItem(const LLUUID& item_id);
 	/// move Category category_id to Trash
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index f9afdee4f9..5ffd560942 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1154,8 +1154,8 @@ public:
 			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
 			return;
 		}
-		llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl;
-
+		gInventory.onAISUpdateReceived("removeObjectResponder " + mItemUUID.asString(), content);
+		// FIXME - not needed after AIS starts returning deleted item in its response.
 		gInventory.onObjectDeletedFromServer(mItemUUID);
 
 		if (mCallback)
@@ -1335,9 +1335,7 @@ public:
 			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
 			return;
 		}
-		llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl;
-
-		gInventory.onDescendentsPurgedFromServer(mItemUUID);
+		gInventory.onAISUpdateReceived("purgeDescendentsResponder " + mItemUUID.asString(), content);
 
 		if (mCallback)
 		{
-- 
cgit v1.2.3


From 931410211e1d644028f5b09cbf77b179e0e75aab Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 15 May 2013 09:45:10 -0400
Subject: SH-4144 FIX - removed UseAISv3Inventory debug settings - cap is now
 managed sim-side

---
 indra/newview/app_settings/settings.xml | 11 -----------
 indra/newview/llviewerinventory.cpp     |  6 +++---
 2 files changed, 3 insertions(+), 14 deletions(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 1262089b3d..18a33b3542 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14033,17 +14033,6 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>UseAISv3Inventory</key>
-    <map>
-      <key>Comment</key>
-      <string>Allow use of AISv3 inventory - this setting should only be needed during development.</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
     <key>ClickToWalk</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 5ffd560942..e819479923 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1189,7 +1189,7 @@ void remove_inventory_item(
 	if(obj)
 	{
 		std::string cap;
-		if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory"))
+		if (gAgent.getRegion())
 		{
 			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
 		}
@@ -1267,7 +1267,7 @@ void remove_inventory_category(
 		}
 
 		std::string cap;
-		if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory"))
+		if (gAgent.getRegion())
 		{
 			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
 		}
@@ -1407,7 +1407,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		else
 		{
 			std::string cap;
-			if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory"))
+			if (gAgent.getRegion())
 			{
 				cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
 			}
-- 
cgit v1.2.3


From 2ed3746aee81901435f3f28f71a497d234d680d2 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 15 May 2013 13:27:16 -0400
Subject: SH-4197 FIX - also simplified the category remove flow for AIS, don't
 need to purge descendents first.

---
 indra/newview/llviewerinventory.cpp | 39 ++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index e819479923..202ed43caa 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1155,8 +1155,6 @@ public:
 			return;
 		}
 		gInventory.onAISUpdateReceived("removeObjectResponder " + mItemUUID.asString(), content);
-		// FIXME - not needed after AIS starts returning deleted item in its response.
-		gInventory.onObjectDeletedFromServer(mItemUUID);
 
 		if (mCallback)
 		{
@@ -1226,18 +1224,26 @@ void remove_inventory_item(
 	}
 }
 
-class LLRemoveObjectOnDestroy: public LLInventoryCallback
+class LLRemoveCategoryOnDestroy: public LLInventoryCallback
 {
 public:
-	LLRemoveObjectOnDestroy(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb):
-		mID(item_id),
+	LLRemoveCategoryOnDestroy(const LLUUID& cat_id, LLPointer<LLInventoryCallback> cb):
+		mID(cat_id),
 		mCB(cb)
 	{
 	}
 	/* virtual */ void fire(const LLUUID& item_id) {}
-	~LLRemoveObjectOnDestroy()
+	~LLRemoveCategoryOnDestroy()
 	{
-		remove_inventory_object(mID, mCB);
+		LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID);
+		if(children != LLInventoryModel::CHILDREN_NO)
+		{
+			llwarns << "remove descendents failed, cannot remove category " << llendl;
+		}
+		else
+		{
+			remove_inventory_category(mID, mCB);
+		}
 	}
 private:
 	LLUUID mID;
@@ -1257,15 +1263,6 @@ void remove_inventory_category(
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
 			return;
 		}
-		LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id);
-		if(children != LLInventoryModel::CHILDREN_NO)
-		{
-			llinfos << "Will purge descendents first before deleting category " << cat_id << llendl;
-			LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveObjectOnDestroy(cat_id,cb); 
-			purge_descendents_of(cat_id, wrap_cb);
-			return;
-		}
-
 		std::string cap;
 		if (gAgent.getRegion())
 		{
@@ -1280,6 +1277,16 @@ void remove_inventory_category(
 		}
 		else // no cap
 		{
+			// RemoveInventoryFolder does not remove children, so must
+			// clear descendents first.
+			LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id);
+			if(children != LLInventoryModel::CHILDREN_NO)
+			{
+				llinfos << "Will purge descendents first before deleting category " << cat_id << llendl;
+				LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); 
+				purge_descendents_of(cat_id, wrap_cb);
+				return;
+			}
 
 			LLMessageSystem* msg = gMessageSystem;
 			msg->newMessageFast(_PREHASH_RemoveInventoryFolder);
-- 
cgit v1.2.3


From 8a4add76b44bab32633c5432f8852e5351770c91 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 15 May 2013 18:08:12 -0400
Subject: SH-4175 WIP - Avoid add to outfit or remove from outfit when an
 outfit change is already in progress

---
 indra/newview/llappearancemgr.cpp   | 14 +++++++++++---
 indra/newview/llinventorybridge.cpp |  4 ++++
 indra/newview/llviewerinventory.cpp |  2 +-
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 84a494186f..f48755ecce 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1547,6 +1547,11 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id)
 // static
 bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id)
 {
+	if (gAgentWearables.isCOFChangeInProgress())
+	{
+		return false;
+	}
+
 	LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false);
 	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn);
 }
@@ -1578,8 +1583,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
 	}
 
 	// Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
-	LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
-	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn);
+	LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
+	return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn);
 }
 
 void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb)
@@ -3001,11 +3006,13 @@ protected:
 							   << llendl;
 		}
 		LL_INFOS("Avatar") << " ================================= " << llendl;
+		S32 local_only = 0, ais_only = 0;
 		for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
 		{
 			if (ais_items.find(*it) == ais_items.end())
 			{
 				LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl;
+				local_only++;
 			}
 		}
 		for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
@@ -3013,9 +3020,10 @@ protected:
 			if (local_items.find(*it) == local_items.end())
 			{
 				LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl;
+				ais_only++;
 			}
 		}
-		if (local_items.size()==0 && ais_items.size()==0)
+		if (local_only==0 && ais_only==0)
 		{
 			LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
 							   << content["observed"].asInteger()
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index abebd0aa5e..b857f8bbec 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3579,6 +3579,10 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&
 		{
 			disabled_items.push_back(std::string("Replace Outfit"));
 		}
+		if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID))
+		{
+			disabled_items.push_back(std::string("Add To Outfit"));
+		}
 		items.push_back(std::string("Outfit Separator"));
 	}
 }
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 202ed43caa..18ea812471 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1182,8 +1182,8 @@ void remove_inventory_item(
 	const LLUUID& item_id,
 	LLPointer<LLInventoryCallback> cb)
 {
-	llinfos << "item_id: [" << item_id << "] " << llendl;
 	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+	llinfos << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
 	if(obj)
 	{
 		std::string cap;
-- 
cgit v1.2.3


From 14a3c5187b644b084f0b0a024a8ac953e89f37de Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 16 May 2013 14:40:04 -0400
Subject: SH-4175 WIP - removed a case where we request to delete the base
 outfit link twice when changing outfits

---
 indra/newview/llappearancemgr.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index f48755ecce..cfe9055aab 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1765,7 +1765,10 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// the link_waiter so links can be followed for any items that get
 	// carried over (e.g. keeping old shape if the new outfit does not
 	// contain one)
-	bool keep_outfit_links = append;
+
+	// even in the non-append case, createBaseOutfitLink() already
+	// deletes the existing link, don't need to do it again here.
+	bool keep_outfit_links = true;
 	removeCategoryContents(cof, keep_outfit_links, link_waiter);
 
 	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
-- 
cgit v1.2.3


From 14f7ad902330051e1bb3ff17abbbfa05a0ebf7e8 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 16 May 2013 19:17:52 -0700
Subject: SH-4168 FIX Inventory: Loading... Loading... shown on folders cleaned
 up logic for displaying "loading..." message so that it only applies to
 folders that are opened whose contents aren't yet loaded

---
 indra/newview/llinventorybridge.cpp | 48 ++++++++++---------------------------
 indra/newview/llinventorybridge.h   |  4 +++-
 2 files changed, 16 insertions(+), 36 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b857f8bbec..c32abe507e 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -200,6 +200,7 @@ const std::string& LLInvFVBridge::getDisplayName() const
 	{
 		buildDisplayName();
 	}
+
 	return mDisplayName;
 }
 
@@ -1894,49 +1895,19 @@ void LLFolderBridge::buildDisplayName() const
 
 void LLFolderBridge::update()
 {
-	bool possibly_has_children = false;
-	bool up_to_date = isUpToDate();
-	if(!up_to_date && hasChildren()) // we know we have children but  haven't  fetched them (doesn't obey filter)
-	{
-		possibly_has_children = true;
-	}
-
-	bool loading = (possibly_has_children && !up_to_date );
+	// we know we have children but  haven't  fetched them (doesn't obey filter)
+	bool loading = !isUpToDate() && hasChildren() && mFolderViewItem->isOpen();
 
 	if (loading != mIsLoading)
 	{
-		if ( loading && !mIsLoading )
+		if ( loading )
 		{
 			// Measure how long we've been in the loading state
 			mTimeSinceRequestStart.reset();
 		}
+		mIsLoading = loading;
 
-		const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID());
-		const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID());
-
-		bool root_is_loading = false;
-		if (in_inventory)
-		{
-			root_is_loading =   LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress();
-		}
-		if (in_library)
-		{
-			root_is_loading =   LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress();
-		}
-		if ((mIsLoading
-				&&	mTimeSinceRequestStart.getElapsedTimeF32() >=   gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
-			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive()
-				&&	root_is_loading))
-		{
-			buildDisplayName();
-			mDisplayName = LLInvFVBridge::getDisplayName() + " ( " +   LLTrans::getString("LoadingData") + " ) ";
-			mIsLoading = true;
-		}
-		else
-		{
-			buildDisplayName();
-			mIsLoading = false;
-		}
+		mFolderViewItem->refresh();
 	}
 }
 
@@ -3056,6 +3027,13 @@ LLUIImagePtr LLFolderBridge::getIconOverlay() const
 	return NULL;
 }
 
+std::string LLFolderBridge::getLabelSuffix() const
+{
+	static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime");
+	return mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay() 
+		? llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str())
+		: LLStringUtil::null;
+}
 
 BOOL LLFolderBridge::renameItem(const std::string& new_name)
 {
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 517153e171..2a937b574d 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -248,7 +248,7 @@ public:
 	LLFolderBridge(LLInventoryPanel* inventory, 
 				   LLFolderView* root,
 				   const LLUUID& uuid) 
-        :       LLInvFVBridge(inventory, root, uuid),
+	:	LLInvFVBridge(inventory, root, uuid),
 		mCallingCards(FALSE),
 		mWearables(FALSE),
 		mIsLoading(false)
@@ -272,6 +272,8 @@ public:
 	virtual LLUIImagePtr getIconOverlay() const;
 
 	static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
+	
+	virtual std::string getLabelSuffix() const;
 
 	virtual BOOL renameItem(const std::string& new_name);
 
-- 
cgit v1.2.3


From d09db5949050ac23547e1cd06712ebbf9a980b2a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 17 May 2013 18:01:52 -0400
Subject: SH-4200 WIP - added AISCommand classes with retry capabilities.

---
 indra/newview/llviewerinventory.cpp | 205 +++++++++++++++++++++++-------------
 1 file changed, 131 insertions(+), 74 deletions(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 18ea812471..31ff3bb5d6 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -66,6 +66,7 @@
 #include "lllogininstance.h"
 #include "llfavoritesbar.h"
 #include "llclipboard.h"
+#include "llhttpretrypolicy.h"
 
 // Two do-nothing ops for use in callbacks.
 void no_op_inventory_func(const LLUUID&) {} 
@@ -1138,44 +1139,156 @@ void move_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
-class RemoveObjectResponder: public LLHTTPClient::Responder
+class AISCommand: public LLHTTPClient::Responder
 {
 public:
-	RemoveObjectResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback):
-		mItemUUID(item_id),
+	typedef boost::function<void()> command_func_type;
+
+	AISCommand(LLPointer<LLInventoryCallback> callback):
 		mCallback(callback)
 	{
+		llinfos << "constructor" << llendl;
+		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
+	}
+
+	virtual ~AISCommand()
+	{
+		llinfos << "destructor" << llendl;
+	}
+
+	void run_command()
+	{
+		mCommandFunc();
+	}
+
+	void setCommandFunc(command_func_type command_func)
+	{
+		mCommandFunc = command_func;
+	}
+	
+	// Need to do command-specific parsing to get an id here.  May or
+	// may not need to bother, since most LLInventoryCallbacks do
+	// their work in the destructor.
+	virtual bool getResponseUUID(const LLSD& content, LLUUID& id)
+	{
+		return false;
 	}
+	
 	/* virtual */ void httpSuccess()
 	{
+		// Command func holds a reference to self, need to release it
+		// after a success or final failure.
+		setCommandFunc(no_op);
+		
 		const LLSD& content = getContent();
 		if (!content.isMap())
 		{
 			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
 			return;
 		}
-		gInventory.onAISUpdateReceived("removeObjectResponder " + mItemUUID.asString(), content);
+		mRetryPolicy->onSuccess();
+		
+		gInventory.onAISUpdateReceived("AISCommand", content);
 
 		if (mCallback)
 		{
-			mCallback->fire(mItemUUID);
+			LLUUID item_id; // will default to null if parse fails.
+			getResponseUUID(content,item_id);
+			mCallback->fire(item_id);
 		}
 	}
+
 	/*virtual*/ void httpFailure()
 	{
 		const LLSD& content = getContent();
 		S32 status = getStatus();
 		const std::string& reason = getReason();
+		const LLSD& headers = getResponseHeaders();
 		if (!content.isMap())
 		{
-			llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl;
-			return;
+			llwarns << "Malformed response contents " << content
+					<< " status " << status << " reason " << reason << llendl;
+		}
+		else
+		{
+			llwarns << "failed with content: " << ll_pretty_print_sd(content)
+					<< " status " << status << " reason " << reason << llendl;
+		}
+		mRetryPolicy->onFailure(status, headers);
+		F32 seconds_to_wait;
+		if (mRetryPolicy->shouldRetry(seconds_to_wait))
+		{
+			doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
+		}
+		else
+		{
+			// Command func holds a reference to self, need to release it
+			// after a success or final failure.
+			setCommandFunc(no_op);
 		}
-		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl;
 	}
+
+	static bool getCap(std::string& cap)
+	{
+		if (gAgent.getRegion())
+		{
+			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+		}
+		if (!cap.empty())
+		{
+			return true;
+		}
+		return false;
+	}
+
 private:
+	command_func_type mCommandFunc;
+	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
 	LLPointer<LLInventoryCallback> mCallback;
-	const LLUUID mItemUUID;
+};
+
+class RemoveObjectCommand: public AISCommand
+{
+public:
+	RemoveObjectCommand(const LLUUID& item_id,
+						LLPointer<LLInventoryCallback> callback):
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			return;
+		}
+		const std::string url = cap + std::string("/item/") + item_id.asString();
+		llinfos << "url: " << url << llendl;
+		LLHTTPClient::ResponderPtr responder = this;
+		LLSD headers;
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+};
+
+class PurgeDescendentsCommand: public AISCommand
+{
+public:
+	PurgeDescendentsCommand(const LLUUID& item_id,
+							LLPointer<LLInventoryCallback> callback):
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			return;
+		}
+		std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
+		llinfos << "url: " << url << llendl;
+		LLCurl::ResponderPtr responder = this;
+		LLSD headers;
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
 };
 
 void remove_inventory_item(
@@ -1187,16 +1300,10 @@ void remove_inventory_item(
 	if(obj)
 	{
 		std::string cap;
-		if (gAgent.getRegion())
-		{
-			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
-		}
-		if (!cap.empty())
+		if (AISCommand::getCap(cap))
 		{
-			std::string url = cap + std::string("/item/") + item_id.asString();
-			llinfos << "url: " << url << llendl;
-			LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(item_id,cb);
-			LLHTTPClient::del(url,responder_ptr);
+			LLPointer<AISCommand> cmd_ptr = new RemoveObjectCommand(item_id, cb);
+			cmd_ptr->run_command();
 		}
 		else // no cap
 		{
@@ -1264,16 +1371,12 @@ void remove_inventory_category(
 			return;
 		}
 		std::string cap;
-		if (gAgent.getRegion())
-		{
-			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
-		}
-		if (!cap.empty())
+		if (AISCommand::getCap(cap))
 		{
 			std::string url = cap + std::string("/category/") + cat_id.asString();
 			llinfos << "url: " << url << llendl;
-			LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(cat_id,cb);
-			LLHTTPClient::del(url,responder_ptr);
+			LLPointer<AISCommand> cmd_ptr = new RemoveObjectCommand(cat_id, cb);
+			cmd_ptr->run_command();
 		}
 		else // no cap
 		{
@@ -1326,46 +1429,6 @@ void remove_inventory_object(
 	}
 }
 
-class PurgeDescendentsResponder: public LLHTTPClient::Responder
-{
-public:
-	PurgeDescendentsResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback):
-		mItemUUID(item_id),
-		mCallback(callback)
-	{
-	}
-	/* virtual */ void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		gInventory.onAISUpdateReceived("purgeDescendentsResponder " + mItemUUID.asString(), content);
-
-		if (mCallback)
-		{
-			mCallback->fire(mItemUUID);
-		}
-	}
-	/*virtual*/ void httpFailure()
-	{
-		const LLSD& content = getContent();
-		S32 status = getStatus();
-		const std::string& reason = getReason();
-		if (!content.isMap())
-		{
-			llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl;
-			return;
-		}
-		llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl;
-	}
-private:
-	LLPointer<LLInventoryCallback> mCallback;
-	const LLUUID mItemUUID;
-};
-
 // This is a method which collects the descendents of the id
 // provided. If the category is not found, no action is
 // taken. This method goes through the long winded process of
@@ -1414,16 +1477,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		else
 		{
 			std::string cap;
-			if (gAgent.getRegion())
-			{
-				cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
-			}
-			if (!cap.empty())
+			if (AISCommand::getCap(cap))
 			{
-				std::string url = cap + std::string("/category/") + id.asString() + "/children";
-				llinfos << "url: " << url << llendl;
-				LLCurl::ResponderPtr responder_ptr = new PurgeDescendentsResponder(id,cb);
-				LLHTTPClient::del(url,responder_ptr);
+				LLPointer<AISCommand> cmd_ptr = new PurgeDescendentsCommand(id, cb);
+				cmd_ptr->run_command();
 			}
 			else // no cap
 			{
-- 
cgit v1.2.3


From 0f6a4a3389cdce6d5bb92cd6f4861a46def284cc Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 20 May 2013 18:06:26 -0400
Subject: SH-4200 FIX - retry ais ops on 5xx errors, dialed back some verbose
 logging.

---
 indra/newview/app_settings/logcontrol.xml |  1 +
 indra/newview/llinventorymodel.cpp        | 28 +++++++------
 indra/newview/llviewerinventory.cpp       | 67 ++++++++++++++++++++-----------
 3 files changed, 60 insertions(+), 36 deletions(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 92a241857e..6594fdb249 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -43,6 +43,7 @@
 					<key>tags</key>
 						<array>
 						<!-- sample entry for debugging specific items	
+						     <string>Inventory</string>
 						     <string>Avatar</string>
 						     <string>Voice</string>		
 						-->
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index fd57845c0e..73ef3e60da 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1170,14 +1170,13 @@ void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_ve
 
 void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
 {
-	llinfos << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl;
+	LL_DEBUGS("Inventory") << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl;
 
 	uuid_vec_t cat_ids;
 	parse_llsd_uuid_array(update,"_categories_removed",cat_ids);
 	for (uuid_vec_t::const_iterator it = cat_ids.begin();
 		 it != cat_ids.end(); ++it)
 	{
-		llinfos << "remove category: " << *it << llendl;
 		onObjectDeletedFromServer(*it, false);
 	}
 
@@ -1186,7 +1185,6 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	for (uuid_vec_t::const_iterator it = item_ids.begin();
 		 it != item_ids.end(); ++it)
 	{
-		llinfos << "remove item: " << *it << llendl;
 		onObjectDeletedFromServer(*it, false);
 	}
 
@@ -1195,10 +1193,13 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
 		 it != broken_link_ids.end(); ++it)
 	{
-		llinfos << "remove broken link: " << *it << llendl;
 		onObjectDeletedFromServer(*it, false);
 	}
 
+	// TODO - how can we use this version info? Need to be sure all
+	// changes are going through AIS first, or at least through
+	// something with a reliable responder.
+#if 0
 	const std::string& ucv = "_updated_category_versions";
 	if (update.has(ucv))
 	{
@@ -1208,9 +1209,9 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 		{
 			const LLUUID id((*it).first);
 			S32 version = (*it).second.asInteger();
-			llinfos << "update category: " << id << " to version " << version << llendl;
 		}
 	}
+#endif
 
 	
 }
@@ -1291,7 +1292,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 			llwarns << "Unexpected count of categories deleted, got "
 					<< total_deleted_count << " expected " << count << llendl;
 		}
-		gInventory.validate();
+		//gInventory.validate();
 	}
 }
 
@@ -2925,7 +2926,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	LLUUID tid;
 	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid);
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-	llinfos << "Bulk inventory: " << tid << llendl;
+	LL_DEBUGS("Inventory") << "Bulk inventory: " << tid << llendl;
 #endif
 
 	update_map_t update;
@@ -2937,9 +2938,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	{
 		LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
 		tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
-		llinfos << "unpacked folder '" << tfolder->getName() << "' ("
-				<< tfolder->getUUID() << ") in " << tfolder->getParentUUID()
-				<< llendl;
+		LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' ("
+							   << tfolder->getUUID() << ") in " << tfolder->getParentUUID()
+							   << llendl;
 		if(tfolder->getUUID().notNull())
 		{
 			folders.push_back(tfolder);
@@ -2979,8 +2980,8 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	{
 		LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
 		titem->unpackMessage(msg, _PREHASH_ItemData, i);
-		llinfos << "unpacked item '" << titem->getName() << "' in "
-				<< titem->getParentUUID() << llendl;
+		LL_DEBUGS("Inventory") << "unpacked item '" << titem->getName() << "' in "
+							   << titem->getParentUUID() << llendl;
 		U32 callback_id;
 		msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
 		if(titem->getUUID().notNull() ) // && callback_id.notNull() )
@@ -3118,7 +3119,8 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
 		// If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
 		if (gInventory.getItem(titem->getUUID()))
 		{
-			llinfos << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
+			LL_DEBUGS("Inventory") << "Skipping prefetched item [ Name: " << titem->getName()
+								   << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
 			continue;
 		}
 		gInventory.updateItem(titem);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 31ff3bb5d6..50d67463c7 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1147,13 +1147,11 @@ public:
 	AISCommand(LLPointer<LLInventoryCallback> callback):
 		mCallback(callback)
 	{
-		llinfos << "constructor" << llendl;
 		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
 	}
 
 	virtual ~AISCommand()
 	{
-		llinfos << "destructor" << llendl;
 	}
 
 	void run_command()
@@ -1206,13 +1204,13 @@ public:
 		const LLSD& headers = getResponseHeaders();
 		if (!content.isMap())
 		{
-			llwarns << "Malformed response contents " << content
-					<< " status " << status << " reason " << reason << llendl;
+			LL_DEBUGS("Inventory") << "Malformed response contents " << content
+								   << " status " << status << " reason " << reason << llendl;
 		}
 		else
 		{
-			llwarns << "failed with content: " << ll_pretty_print_sd(content)
-					<< " status " << status << " reason " << reason << llendl;
+			LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
+								   << " status " << status << " reason " << reason << llendl;
 		}
 		mRetryPolicy->onFailure(status, headers);
 		F32 seconds_to_wait;
@@ -1247,20 +1245,44 @@ private:
 	LLPointer<LLInventoryCallback> mCallback;
 };
 
-class RemoveObjectCommand: public AISCommand
+class RemoveItemCommand: public AISCommand
 {
 public:
-	RemoveObjectCommand(const LLUUID& item_id,
-						LLPointer<LLInventoryCallback> callback):
+	RemoveItemCommand(const LLUUID& item_id,
+					  LLPointer<LLInventoryCallback> callback):
 		AISCommand(callback)
 	{
 		std::string cap;
 		if (!getCap(cap))
 		{
+			llwarns << "No cap found" << llendl;
 			return;
 		}
-		const std::string url = cap + std::string("/item/") + item_id.asString();
-		llinfos << "url: " << url << llendl;
+		std::string url = cap + std::string("/item/") + item_id.asString();
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
+		LLHTTPClient::ResponderPtr responder = this;
+		LLSD headers;
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+};
+
+class RemoveCategoryCommand: public AISCommand
+{
+public:
+	RemoveCategoryCommand(const LLUUID& item_id,
+						  LLPointer<LLInventoryCallback> callback):
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		std::string url = cap + std::string("/category/") + item_id.asString();
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
 		LLHTTPClient::ResponderPtr responder = this;
 		LLSD headers;
 		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
@@ -1279,10 +1301,11 @@ public:
 		std::string cap;
 		if (!getCap(cap))
 		{
+			llwarns << "No cap found" << llendl;
 			return;
 		}
 		std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
-		llinfos << "url: " << url << llendl;
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
 		LLCurl::ResponderPtr responder = this;
 		LLSD headers;
 		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
@@ -1296,13 +1319,13 @@ void remove_inventory_item(
 	LLPointer<LLInventoryCallback> cb)
 {
 	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
-	llinfos << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
 	if(obj)
 	{
 		std::string cap;
 		if (AISCommand::getCap(cap))
 		{
-			LLPointer<AISCommand> cmd_ptr = new RemoveObjectCommand(item_id, cb);
+			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
 			cmd_ptr->run_command();
 		}
 		else // no cap
@@ -1361,7 +1384,7 @@ void remove_inventory_category(
 	const LLUUID& cat_id,
 	LLPointer<LLInventoryCallback> cb)
 {
-	llinfos << "cat_id: [" << cat_id << "] " << llendl;
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] " << llendl;
 	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
 	if(obj)
 	{
@@ -1373,9 +1396,7 @@ void remove_inventory_category(
 		std::string cap;
 		if (AISCommand::getCap(cap))
 		{
-			std::string url = cap + std::string("/category/") + cat_id.asString();
-			llinfos << "url: " << url << llendl;
-			LLPointer<AISCommand> cmd_ptr = new RemoveObjectCommand(cat_id, cb);
+			LLPointer<AISCommand> cmd_ptr = new RemoveCategoryCommand(cat_id, cb);
 			cmd_ptr->run_command();
 		}
 		else // no cap
@@ -1385,7 +1406,7 @@ void remove_inventory_category(
 			LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id);
 			if(children != LLInventoryModel::CHILDREN_NO)
 			{
-				llinfos << "Will purge descendents first before deleting category " << cat_id << llendl;
+				LL_DEBUGS("Inventory") << "Will purge descendents first before deleting category " << cat_id << llendl;
 				LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); 
 				purge_descendents_of(cat_id, wrap_cb);
 				return;
@@ -1439,7 +1460,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 	LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id);
 	if(children == LLInventoryModel::CHILDREN_NO)
 	{
-		llinfos << "No descendents to purge for " << id << llendl;
+		LL_DEBUGS("Inventory") << "No descendents to purge for " << id << llendl;
 		return;
 	}
 	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id);
@@ -1448,8 +1469,8 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode())
 		{
 			// Something on the clipboard is in "cut mode" and needs to be preserved
-			llinfos << "purge_descendents_of clipboard case " << cat->getName()
-			<< " iterate and purge non hidden items" << llendl;
+			LL_DEBUGS("Inventory") << "purge_descendents_of clipboard case " << cat->getName()
+								   << " iterate and purge non hidden items" << llendl;
 			LLInventoryModel::cat_array_t* categories;
 			LLInventoryModel::item_array_t* items;
 			// Get the list of direct descendants in tha categoy passed as argument
@@ -1485,7 +1506,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 			else // no cap
 			{
 				// Fast purge
-				llinfos << "purge_descendents_of fast case " << cat->getName() << llendl;
+				LL_DEBUGS("Inventory") << "purge_descendents_of fast case " << cat->getName() << llendl;
 
 				// send it upstream
 				LLMessageSystem* msg = gMessageSystem;
-- 
cgit v1.2.3


From b0303445f1af83057e4d27d763f7b860f20f0143 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 21 May 2013 16:56:45 -0400
Subject: more merge fixing

---
 indra/viewer_components/updater/llupdatechecker.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index 891a53d011..cdb9b45682 100755
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -140,6 +140,7 @@ void LLUpdateChecker::Implementation::httpCompleted()
 
 	S32 status = getStatus();
 	const LLSD& content = getContent();
+	const std::string& reason = getReason();
 	if(status != 200)
 	{
 		std::string server_error;
-- 
cgit v1.2.3


From 6c56c77ec575141963c5de8dfa228253fe175bc3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 24 May 2013 08:53:21 -0400
Subject: SH-4027 WIP - initial implementation of item update via AIS.

---
 indra/llinventory/llinventory.cpp      |   2 +-
 indra/llinventory/llinventory.h        |   4 +-
 indra/llmessage/llhttpclient.cpp       |  12 +-
 indra/llmessage/llhttpclient.h         |   8 +
 indra/llmessage/llhttpconstants.h      |  37 ++-
 indra/llmessage/llurlrequest.cpp       |  11 +
 indra/newview/llappearancemgr.cpp      |   4 +-
 indra/newview/llinventorybridge.cpp    |  10 +-
 indra/newview/llinventoryfunctions.cpp |   9 +-
 indra/newview/llinventorymodel.cpp     |  93 +++++-
 indra/newview/llinventorymodel.h       |   6 +
 indra/newview/llviewerinventory.cpp    | 510 +++++++++++++++++++++++----------
 indra/newview/llviewerinventory.h      |  14 +
 13 files changed, 523 insertions(+), 197 deletions(-)
 mode change 100644 => 100755 indra/llmessage/llhttpconstants.h

diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index a4cd8333cf..641532ec29 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -261,7 +261,7 @@ void LLInventoryObject::updateServer(BOOL) const
 	llwarns << "LLInventoryObject::updateServer() called.  Doesn't do anything." << llendl;
 }
 
-inline
+// static
 void LLInventoryObject::correctInventoryName(std::string& name)
 {
 	LLStringUtil::replaceNonstandardASCII(name, ' ');
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 8b865f044d..17421b3f5e 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -86,16 +86,14 @@ public:
 	void setType(LLAssetType::EType type);
 	virtual void setCreationDate(time_t creation_date_utc); // only stored for items
 
-private:
 	// in place correction for inventory name string
-	void correctInventoryName(std::string& name);
+	static void correctInventoryName(std::string& name);
 
 	//--------------------------------------------------------------------
 	// File Support
 	//   Implemented here so that a minimal information set can be transmitted
 	//   between simulator and viewer.
 	//--------------------------------------------------------------------
-public:
 	// virtual BOOL importFile(LLFILE* fp);
 	virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const;
 	virtual BOOL importLegacyStream(std::istream& input_stream);
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 5830a5eca0..53cef54559 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -304,7 +304,7 @@ static void request(
 					gMessageSystem->mPort));
 	}
 
-	if (method == HTTP_PUT || method == HTTP_POST)
+	if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH)
 	{
 		if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
 		{
@@ -556,6 +556,16 @@ void LLHTTPClient::put(
 	request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
 }
 
+void LLHTTPClient::patch(
+	const std::string& url,
+	const LLSD& body,
+	ResponderPtr responder,
+	const LLSD& headers,
+	const F32 timeout)
+{
+	request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers);
+}
+
 void LLHTTPClient::post(
 	const std::string& url,
 	const LLSD& body,
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index a7236ba169..4e7495495f 100755
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -74,6 +74,14 @@ public:
 		ResponderPtr,
 		const LLSD& headers = LLSD(),
 		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
+	static void patch(
+		const std::string& url,
+		const LLSD& body,
+		ResponderPtr,
+		const LLSD& headers = LLSD(),
+		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
 	static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
 	static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
 
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h
old mode 100644
new mode 100755
index 8cc3459654..aa947af414
--- a/indra/llmessage/llhttpconstants.h
+++ b/indra/llmessage/llhttpconstants.h
@@ -2,31 +2,25 @@
  * @file llhttpconstants.h
  * @brief Constants for HTTP requests and responses
  *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2013, Linden Research, Inc.
- * 
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2001-2013, 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.
  * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
  * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
  * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
@@ -117,6 +111,7 @@ enum EHTTPMethod
 	HTTP_DELETE,
 	HTTP_MOVE, // Caller will need to set 'Destination' header
 	HTTP_OPTIONS,
+	HTTP_PATCH,
 	HTTP_METHOD_COUNT
 };
 
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 49cfef2771..cadff49cb8 100755
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -487,6 +487,17 @@ bool LLURLRequest::configure()
 		rv = true;
 		break;
 
+	case HTTP_PATCH:
+		// Disable the expect http 1.1 extension. POST and PUT default
+		// to turning this on, and I am not too sure what it means.
+		addHeader(HTTP_OUT_HEADER_EXPECT);
+
+		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
+		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
+		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "PATCH");
+		rv = true;
+		break;
+
 	case HTTP_POST:
 		// Disable the expect http 1.1 extension. POST and PUT default
 		// to turning this on, and I am not too sure what it means.
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index cfe9055aab..14eed6e1df 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2812,8 +2812,10 @@ struct WearablesOrderComparator
 		//items with ordering information but not for the associated wearables type
 		if (!item1_valid && item2_valid) 
 			return false;
+		else if (item1_valid && !item2_valid)
+			return true;
 
-		return true;
+		return item1->getName() < item2->getName();
 	}
 
 	U32 mControlSize;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c32abe507e..89c56ab82c 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1692,13 +1692,9 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
 	LLViewerInventoryItem* item = getItem();
 	if(item && (item->getName() != new_name))
 	{
-		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
-		new_item->rename(new_name);
-		new_item->updateServer(FALSE);
-		model->updateItem(new_item);
-
-		model->notifyObservers();
-		buildDisplayName();
+		LLSD updates;
+		updates["name"] = new_name;
+		update_inventory_item(item->getUUID(),updates, NULL);
 	}
 	// return FALSE because we either notified observers (& therefore
 	// rebuilt) or we didn't update.
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f1a4889f5a..b5fb226872 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -123,12 +123,9 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
 		return;
 	}
 
-	LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
-	new_cat->rename(new_name);
-	new_cat->updateServer(FALSE);
-	model->updateCategory(new_cat);
-
-	model->notifyObservers();
+	LLSD updates;
+	updates["name"] = new_name;
+	update_inventory_category(cat_id, updates, NULL);
 }
 
 void copy_inventory_category(LLInventoryModel* model,
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 73ef3e60da..06c614aeaa 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1196,6 +1196,36 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 		onObjectDeletedFromServer(*it, false);
 	}
 
+	if (update.has("item_id"))
+	{
+		// item has been modified or possibly created (would be better if we could distinguish these cases directly)
+		LLUUID item_id = update["item_id"].asUUID();
+		LLViewerInventoryItem *item = gInventory.getItem(item_id);
+		LLViewerInventoryCategory *cat = gInventory.getCategory(item_id);
+		if (item)
+		{
+			LLSD changes;
+			if (update.has("name") && update["name"] != item->getName())
+			{
+				changes["name"] = update["name"];
+			}
+			if (update.has("desc") && update["desc"] != item->getActualDescription())
+			{
+				changes["desc"] = update["desc"];
+			}
+			onItemUpdated(item_id,changes);
+		}
+		else if (cat)
+		{
+			llerrs << "don't handle cat update yet" << llendl;
+		}
+		else
+		{
+			llerrs << "don't handle creation case yet" << llendl;
+		}
+	
+	}
+
 	// TODO - how can we use this version info? Need to be sure all
 	// changes are going through AIS first, or at least through
 	// something with a reliable responder.
@@ -1212,10 +1242,71 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 		}
 	}
 #endif
-
 	
 }
 
+void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates)
+{
+	U32 mask = LLInventoryObserver::NONE;
+
+	LLPointer<LLViewerInventoryItem> item = gInventory.getItem(item_id);
+	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << llendl;
+	if(item)
+	{
+		for (LLSD::map_const_iterator it = updates.beginMap();
+			 it != updates.endMap(); ++it)
+		{
+			if (it->first == "name")
+			{
+				llinfos << "Updating name from " << item->getName() << " to " << it->second.asString() << llendl;
+				item->rename(it->second.asString());
+				mask |= LLInventoryObserver::LABEL;
+			}
+			else if (it->first == "desc")
+			{
+				llinfos << "Updating description from " << item->getActualDescription()
+						<< " to " << it->second.asString() << llendl;
+				item->setDescription(it->second.asString());
+			}
+			else
+			{
+				llerrs << "unhandled updates for field: " << it->first << llendl;
+			}
+		}
+		mask |= LLInventoryObserver::INTERNAL;
+		addChangedMask(mask, item->getUUID());
+		gInventory.notifyObservers(); // do we want to be able to make this optional?
+	}
+}
+
+void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates)
+{
+	U32 mask = LLInventoryObserver::NONE;
+
+	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(cat_id);
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << llendl;
+	if(cat)
+	{
+		for (LLSD::map_const_iterator it = updates.beginMap();
+			 it != updates.endMap(); ++it)
+		{
+			if (it->first == "name")
+			{
+				llinfos << "Updating name from " << cat->getName() << " to " << it->second.asString() << llendl;
+				cat->rename(it->second.asString());
+				mask |= LLInventoryObserver::LABEL;
+			}
+			else
+			{
+				llerrs << "unhandled updates for field: " << it->first << llendl;
+			}
+		}
+		mask |= LLInventoryObserver::INTERNAL;
+		addChangedMask(mask, cat->getUUID());
+		gInventory.notifyObservers(); // do we want to be able to make this optional?
+	}
+}
+
 // Update model after descendents have been purged.
 void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links)
 {
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 696d0a9163..515c99c0b4 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -339,6 +339,12 @@ public:
 	// Update model after all descendents removed from server.
 	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
 
+	// Update model after an existing item gets updated on server.
+	void onItemUpdated(const LLUUID& item_id, const LLSD& updates);
+
+	// Update model after an existing category gets updated on server.
+	void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates);
+
 	// Delete a particular inventory object by ID. Will purge one
 	// object from the internal data structures, maintaining a
 	// consistent internal state. No cache accounting, observer
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 50d67463c7..90fef3b5ed 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -259,6 +259,240 @@ public:
 LLInventoryHandler gInventoryHandler;
 
 
+///----------------------------------------------------------------------------
+/// Classes for AISv3 support.
+///----------------------------------------------------------------------------
+class AISCommand: public LLHTTPClient::Responder
+{
+public:
+	typedef boost::function<void()> command_func_type;
+
+	AISCommand(LLPointer<LLInventoryCallback> callback):
+		mCallback(callback)
+	{
+		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
+	}
+
+	virtual ~AISCommand()
+	{
+	}
+
+	void run_command()
+	{
+		mCommandFunc();
+	}
+
+	void setCommandFunc(command_func_type command_func)
+	{
+		mCommandFunc = command_func;
+	}
+	
+	// Need to do command-specific parsing to get an id here.  May or
+	// may not need to bother, since most LLInventoryCallbacks do
+	// their work in the destructor.
+	virtual bool getResponseUUID(const LLSD& content, LLUUID& id)
+	{
+		return false;
+	}
+	
+	/* virtual */ void httpSuccess()
+	{
+		// Command func holds a reference to self, need to release it
+		// after a success or final failure.
+		setCommandFunc(no_op);
+		
+		const LLSD& content = getContent();
+		if (!content.isMap())
+		{
+			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+			return;
+		}
+		mRetryPolicy->onSuccess();
+		
+		gInventory.onAISUpdateReceived("AISCommand", content);
+
+		if (mCallback)
+		{
+			LLUUID item_id; // will default to null if parse fails.
+			getResponseUUID(content,item_id);
+			mCallback->fire(item_id);
+		}
+	}
+
+	/*virtual*/ void httpFailure()
+	{
+		const LLSD& content = getContent();
+		S32 status = getStatus();
+		const std::string& reason = getReason();
+		const LLSD& headers = getResponseHeaders();
+		if (!content.isMap())
+		{
+			LL_DEBUGS("Inventory") << "Malformed response contents " << content
+								   << " status " << status << " reason " << reason << llendl;
+		}
+		else
+		{
+			LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
+								   << " status " << status << " reason " << reason << llendl;
+		}
+		mRetryPolicy->onFailure(status, headers);
+		F32 seconds_to_wait;
+		if (mRetryPolicy->shouldRetry(seconds_to_wait))
+		{
+			doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
+		}
+		else
+		{
+			// Command func holds a reference to self, need to release it
+			// after a success or final failure.
+			setCommandFunc(no_op);
+		}
+	}
+
+	static bool getCap(std::string& cap)
+	{
+		if (gAgent.getRegion())
+		{
+			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+		}
+		if (!cap.empty())
+		{
+			return true;
+		}
+		return false;
+	}
+
+private:
+	command_func_type mCommandFunc;
+	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
+	LLPointer<LLInventoryCallback> mCallback;
+};
+
+class RemoveItemCommand: public AISCommand
+{
+public:
+	RemoveItemCommand(const LLUUID& item_id,
+					  LLPointer<LLInventoryCallback> callback):
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		std::string url = cap + std::string("/item/") + item_id.asString();
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
+		LLHTTPClient::ResponderPtr responder = this;
+		LLSD headers;
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+};
+
+class RemoveCategoryCommand: public AISCommand
+{
+public:
+	RemoveCategoryCommand(const LLUUID& item_id,
+						  LLPointer<LLInventoryCallback> callback):
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		std::string url = cap + std::string("/category/") + item_id.asString();
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
+		LLHTTPClient::ResponderPtr responder = this;
+		LLSD headers;
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+};
+
+class PurgeDescendentsCommand: public AISCommand
+{
+public:
+	PurgeDescendentsCommand(const LLUUID& item_id,
+							LLPointer<LLInventoryCallback> callback):
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
+		LLCurl::ResponderPtr responder = this;
+		LLSD headers;
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+};
+
+class UpdateItemCommand: public AISCommand
+{
+public:
+	UpdateItemCommand(const LLUUID& item_id,
+					  const LLSD& updates,
+					  LLPointer<LLInventoryCallback> callback):
+		mUpdates(updates),
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		std::string url = cap + std::string("/item/") + item_id.asString();
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
+		LLCurl::ResponderPtr responder = this;
+		LLSD headers;
+		headers["Content-Type"] = "application/llsd+xml";
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+private:
+	LLSD mUpdates;
+};
+
+class UpdateCategoryCommand: public AISCommand
+{
+public:
+	UpdateCategoryCommand(const LLUUID& item_id,
+						  const LLSD& updates,
+						  LLPointer<LLInventoryCallback> callback):
+		mUpdates(updates),
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		std::string url = cap + std::string("/category/") + item_id.asString();
+		LL_DEBUGS("Inventory") << "url: " << url << llendl;
+		LLCurl::ResponderPtr responder = this;
+		LLSD headers;
+		headers["Content-Type"] = "application/llsd+xml";
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+private:
+	LLSD mUpdates;
+};
+
 ///----------------------------------------------------------------------------
 /// Class LLViewerInventoryItem
 ///----------------------------------------------------------------------------
@@ -456,6 +690,20 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_
 // virtual
 void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
 {
+	static const LLSD updates;
+	packUpdateMessage(msg,updates);
+}
+
+void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const
+{
+	for (LLSD::map_const_iterator it = updates.beginMap(); it != updates.endMap(); ++it)
+	{
+		if ((it->first != "desc") && (it->first != "name"))
+		{
+			llerrs << "unhandled field: " << it->first << llendl;
+		}
+	}
+	
 	msg->addUUIDFast(_PREHASH_ItemID, mUUID);
 	msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
 	mPermissions.packMessage(msg);
@@ -466,12 +714,29 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
 	msg->addS8Fast(_PREHASH_InvType, type);
 	msg->addU32Fast(_PREHASH_Flags, mFlags);
 	mSaleInfo.packMessage(msg);
-	msg->addStringFast(_PREHASH_Name, mName);
-	msg->addStringFast(_PREHASH_Description, mDescription);
+	if (updates.has("name"))
+	{
+		std::string new_name = updates["name"].asString();
+		LLInventoryObject::correctInventoryName(new_name);
+		msg->addStringFast(_PREHASH_Name, new_name);
+	}
+	else
+	{
+		msg->addStringFast(_PREHASH_Name, mName);
+	}
+	if (updates.has("desc"))
+	{
+		msg->addStringFast(_PREHASH_Description, updates["desc"].asString());
+	}
+	else
+	{
+		msg->addStringFast(_PREHASH_Description, mDescription);
+	}
 	msg->addS32Fast(_PREHASH_CreationDate, mCreationDate);
 	U32 crc = getCRC32();
 	msg->addU32Fast(_PREHASH_CRC, crc);
 }
+
 // virtual
 BOOL LLViewerInventoryItem::importFile(LLFILE* fp)
 {
@@ -583,6 +848,32 @@ void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCatego
 }
 
 
+void LLViewerInventoryCategory::packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const
+{
+	for (LLSD::map_const_iterator it = updates.beginMap(); it != updates.endMap(); ++it)
+	{
+		if (it->first != "name")
+		{
+			llerrs << "unhandled field: " << it->first << llendl;
+		}
+	}
+	
+	msg->addUUIDFast(_PREHASH_FolderID, mUUID);
+	msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
+	S8 type = static_cast<S8>(mPreferredType);
+	msg->addS8Fast(_PREHASH_Type, type);
+	if (updates.has("name"))
+	{
+		std::string new_name = updates["name"].asString();
+		LLInventoryObject::correctInventoryName(new_name);
+		msg->addStringFast(_PREHASH_Name, new_name);
+	}
+	else
+	{
+		msg->addStringFast(_PREHASH_Name, mName);
+	}
+}
+
 void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
 {
 	LLMessageSystem* msg = gMessageSystem;
@@ -1139,180 +1430,87 @@ void move_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
-class AISCommand: public LLHTTPClient::Responder
+// Note this only supports updating an existing item. Goes through AISv3
+// code path where available. Not all uses of item->updateServer() can
+// easily be switched to this paradigm.
+void update_inventory_item(
+	const LLUUID& item_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb)
 {
-public:
-	typedef boost::function<void()> command_func_type;
-
-	AISCommand(LLPointer<LLInventoryCallback> callback):
-		mCallback(callback)
-	{
-		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
-	}
-
-	virtual ~AISCommand()
-	{
-	}
-
-	void run_command()
-	{
-		mCommandFunc();
-	}
-
-	void setCommandFunc(command_func_type command_func)
-	{
-		mCommandFunc = command_func;
-	}
-	
-	// Need to do command-specific parsing to get an id here.  May or
-	// may not need to bother, since most LLInventoryCallbacks do
-	// their work in the destructor.
-	virtual bool getResponseUUID(const LLSD& content, LLUUID& id)
-	{
-		return false;
-	}
-	
-	/* virtual */ void httpSuccess()
-	{
-		// Command func holds a reference to self, need to release it
-		// after a success or final failure.
-		setCommandFunc(no_op);
-		
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		mRetryPolicy->onSuccess();
-		
-		gInventory.onAISUpdateReceived("AISCommand", content);
-
-		if (mCallback)
-		{
-			LLUUID item_id; // will default to null if parse fails.
-			getResponseUUID(content,item_id);
-			mCallback->fire(item_id);
-		}
-	}
-
-	/*virtual*/ void httpFailure()
+	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+	if(obj)
 	{
-		const LLSD& content = getContent();
-		S32 status = getStatus();
-		const std::string& reason = getReason();
-		const LLSD& headers = getResponseHeaders();
-		if (!content.isMap())
-		{
-			LL_DEBUGS("Inventory") << "Malformed response contents " << content
-								   << " status " << status << " reason " << reason << llendl;
-		}
-		else
-		{
-			LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
-								   << " status " << status << " reason " << reason << llendl;
-		}
-		mRetryPolicy->onFailure(status, headers);
-		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(seconds_to_wait))
+		std::string cap;
+		if (AISCommand::getCap(cap))
 		{
-			doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
+			LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
+			cmd_ptr->run_command();
 		}
-		else
+		else // no cap
 		{
-			// Command func holds a reference to self, need to release it
-			// after a success or final failure.
-			setCommandFunc(no_op);
-		}
-	}
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_UpdateInventoryItem);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->addUUIDFast(_PREHASH_TransactionID, obj->getTransactionID());
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addU32Fast(_PREHASH_CallbackID, 0);
+			obj->packUpdateMessage(msg, updates);
+			gAgent.sendReliableMessage();
 
-	static bool getCap(std::string& cap)
-	{
-		if (gAgent.getRegion())
-		{
-			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
-		}
-		if (!cap.empty())
-		{
-			return true;
+			gInventory.onItemUpdated(item_id, updates);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
 		}
-		return false;
 	}
+}
 
-private:
-	command_func_type mCommandFunc;
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-	LLPointer<LLInventoryCallback> mCallback;
-};
-
-class RemoveItemCommand: public AISCommand
+void update_inventory_category(
+	const LLUUID& cat_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb)
 {
-public:
-	RemoveItemCommand(const LLUUID& item_id,
-					  LLPointer<LLInventoryCallback> callback):
-		AISCommand(callback)
+	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+	if(obj)
 	{
-		std::string cap;
-		if (!getCap(cap))
+		if (LLFolderType::lookupIsProtectedType(obj->getPreferredType()))
 		{
-			llwarns << "No cap found" << llendl;
+			LLNotificationsUtil::add("CannotModifyProtectedCategories");
 			return;
 		}
-		std::string url = cap + std::string("/item/") + item_id.asString();
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLHTTPClient::ResponderPtr responder = this;
-		LLSD headers;
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-};
 
-class RemoveCategoryCommand: public AISCommand
-{
-public:
-	RemoveCategoryCommand(const LLUUID& item_id,
-						  LLPointer<LLInventoryCallback> callback):
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
+		//std::string cap;
+		// FIXME - restore this once the back-end work has been done.
+		if (0) // if (AISCommand::getCap(cap))
 		{
-			llwarns << "No cap found" << llendl;
-			return;
+			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, updates, cb);
+			cmd_ptr->run_command();
 		}
-		std::string url = cap + std::string("/category/") + item_id.asString();
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLHTTPClient::ResponderPtr responder = this;
-		LLSD headers;
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-};
-
-class PurgeDescendentsCommand: public AISCommand
-{
-public:
-	PurgeDescendentsCommand(const LLUUID& item_id,
-							LLPointer<LLInventoryCallback> callback):
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
+		else // no cap
 		{
-			llwarns << "No cap found" << llendl;
-			return;
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->nextBlockFast(_PREHASH_FolderData);
+			obj->packUpdateMessage(msg, updates);
+			gAgent.sendReliableMessage();
+
+			gInventory.onCategoryUpdated(cat_id, updates);
+			if (cb)
+			{
+				cb->fire(cat_id);
+			}
 		}
-		std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLCurl::ResponderPtr responder = this;
-		LLSD headers;
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-		setCommandFunc(cmd);
 	}
-};
+}
 
 void remove_inventory_item(
 	const LLUUID& item_id,
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 4e24dc87d1..c52b0c2d9d 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -139,6 +139,8 @@ public:
 	//void updateAssetOnServer() const;
 
 	virtual void packMessage(LLMessageSystem* msg) const;
+	// Contents of updates will take precedence over fields of item where they differ.
+	void packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const;
 	virtual void setTransactionID(const LLTransactionID& transaction_id);
 	struct comparePointers
 	{
@@ -224,6 +226,8 @@ public:
 	void determineFolderType();
 	void changeType(LLFolderType::EType new_folder_type);
 
+	void packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const;
+
 private:
 	friend class LLInventoryModel;
 	void localizeName(); // intended to be called from the LLInventoryModel
@@ -363,6 +367,16 @@ void move_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
+void update_inventory_item(
+	const LLUUID& item_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb);
+
+void update_inventory_category(
+	const LLUUID& cat_id,
+	const LLSD& updates,
+	LLPointer<LLInventoryCallback> cb);
+
 void remove_inventory_item(
 	const LLUUID& item_id,
 	LLPointer<LLInventoryCallback> cb);
-- 
cgit v1.2.3


From 34d2cd03765b6b9b582035a933f4ec11fb262ff4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 24 May 2013 15:51:33 -0400
Subject: SH-4207 WIP - use item updates with callback when updating link
 descriptions. Reworked updateAppearanceFromCOF() cof-validation stages.

---
 indra/llinventory/llinventory.cpp   |  9 +++-
 indra/llinventory/llinventory.h     |  1 +
 indra/newview/llappearancemgr.cpp   | 96 ++++++++++++++++++++-----------------
 indra/newview/llappearancemgr.h     | 12 +++--
 indra/newview/llinventorymodel.cpp  | 51 ++++----------------
 indra/newview/llinventorymodel.h    |  2 +-
 indra/newview/llviewerinventory.cpp |  6 ++-
 7 files changed, 82 insertions(+), 95 deletions(-)

diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 641532ec29..a529aa3af3 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -416,12 +416,17 @@ U32 LLInventoryItem::getCRC32() const
 	return crc;
 }
 
+// static
+void LLInventoryItem::correctInventoryDescription(std::string& desc)
+{
+	LLStringUtil::replaceNonstandardASCII(desc, ' ');
+	LLStringUtil::replaceChar(desc, '|', ' ');
+}
 
 void LLInventoryItem::setDescription(const std::string& d)
 {
 	std::string new_desc(d);
-	LLStringUtil::replaceNonstandardASCII(new_desc, ' ');
-	LLStringUtil::replaceChar(new_desc, '|', ' ');
+	LLInventoryItem::correctInventoryDescription(new_desc);
 	if( new_desc != mDescription )
 	{
 		mDescription = new_desc;
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 17421b3f5e..cc474f3d4c 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -171,6 +171,7 @@ public:
 	//--------------------------------------------------------------------
 public:
 	void setAssetUUID(const LLUUID& asset_id);
+	static void correctInventoryDescription(std::string& name);
 	void setDescription(const std::string& new_desc);
 	void setSaleInfo(const LLSaleInfo& sale_info);
 	void setPermissions(const LLPermissions& perm);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 14eed6e1df..83ad06a3c7 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -422,10 +422,12 @@ public:
 };
 
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
-														 bool enforce_item_restrictions):
+														 bool enforce_item_restrictions,
+														 bool enforce_ordering):
 	mFireCount(0),
 	mUpdateBaseOrder(update_base_outfit_ordering),
-	mEnforceItemRestrictions(enforce_item_restrictions)
+	mEnforceItemRestrictions(enforce_item_restrictions),
+	mEnforceOrdering(enforce_ordering)
 {
 	selfStartPhase("update_appearance_on_destroy");
 }
@@ -449,7 +451,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 
 		selfStopPhase("update_appearance_on_destroy");
 
-		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions);
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions, mEnforceOrdering);
 	}
 }
 
@@ -1918,8 +1920,22 @@ void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 							   -1, items_to_kill);
 }
 
+void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryModel::item_array_t items_to_kill;
+	findAllExcessOrDuplicateItems(getCOF(), items_to_kill);
+	if (items_to_kill.size()>0)
+	{
+		// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
+		// this should catch anything that gets through.
+		removeAll(items_to_kill, cb);
+		return;
+	}
+}
+
 void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
-											  bool enforce_item_restrictions)
+											  bool enforce_item_restrictions,
+											  bool enforce_ordering)
 {
 	if (mIsInUpdateAppearanceFromCOF)
 	{
@@ -1927,35 +1943,37 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 		return;
 	}
 
-	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
-	selfStartPhase("update_appearance_from_cof");
-
 	LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL;
 
 	if (enforce_item_restrictions)
 	{
-		LLInventoryModel::item_array_t items_to_kill;
-		findAllExcessOrDuplicateItems(getCOF(), items_to_kill);
-		if (items_to_kill.size()>0)
-		{
-			// The point here is just to call
-			// updateAppearanceFromCOF() again after excess items
-			// have been removed. That time we will set
-			// enforce_item_restrictions to false so we don't get
-			// caught in a perpetual loop.
-			LLPointer<LLInventoryCallback> cb(
-				new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false));
-
-			// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
-			// this should catch anything that gets through.
-			removeAll(items_to_kill, cb);
-			return;
-		}
+		// The point here is just to call
+		// updateAppearanceFromCOF() again after excess items
+		// have been removed. That time we will set
+		// enforce_item_restrictions to false so we don't get
+		// caught in a perpetual loop.
+		LLPointer<LLInventoryCallback> cb(
+			new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering));
+		enforceCOFItemRestrictions(cb);
+		return;
 	}
 
-	//checking integrity of the COF in terms of ordering of wearables, 
-	//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
-	updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering);
+	if (enforce_ordering)
+	{
+		//checking integrity of the COF in terms of ordering of wearables, 
+		//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
+
+		// As with enforce_item_restrictions handling above, we want
+		// to wait for the update callbacks, then (finally!) call
+		// updateAppearanceFromCOF() with no additional COF munging needed.
+		LLPointer<LLInventoryCallback> cb(
+			new LLUpdateAppearanceOnDestroy(false, false, false));
+		updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb);
+		return;
+	}
+
+	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
+	selfStartPhase("update_appearance_from_cof");
 
 	// update dirty flag to see if the state of the COF matches
 	// the saved outfit stored as a folder link
@@ -1966,11 +1984,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 	{
 		requestServerAppearanceUpdate();
 	}
-	// DRANO really should wait for the appearance message to set this.
-	// verify that deleting this line doesn't break anything.
-	//gAgentAvatarp->setIsUsingServerBakes(gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion());
-	
-	//dumpCat(getCOF(),"COF, start");
 
 	LLUUID current_outfit_id = getCOF();
 
@@ -2821,7 +2834,9 @@ struct WearablesOrderComparator
 	U32 mControlSize;
 };
 
-void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base_outfit_ordering)
+void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
+												 bool update_base_outfit_ordering,
+												 LLPointer<LLInventoryCallback> cb)
 {
 	if (cat_id.isNull())
 	{
@@ -2831,7 +2846,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 			const LLUUID base_outfit_id = getBaseOutfitUUID();
 			if (base_outfit_id.notNull())
 			{
-				updateClothingOrderingInfo(base_outfit_id,false);
+				updateClothingOrderingInfo(base_outfit_id,false,cb);
 			}
 		}
 	}
@@ -2843,7 +2858,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 	wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);
 	divvyWearablesByType(wear_items, items_by_type);
 
-	bool inventory_changed = false;
 	for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++)
 	{
 		
@@ -2862,17 +2876,11 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 			std::string new_order_str = build_order_string((LLWearableType::EType)type, i);
 			if (new_order_str == item->getActualDescription()) continue;
 
-			item->setDescription(new_order_str);
-			item->setComplete(TRUE);
- 			item->updateServer(FALSE);
-			gInventory.updateItem(item);
-			
-			inventory_changed = true;
+			LLSD updates;
+			updates["desc"] = new_order_str;
+			update_inventory_item(item->getUUID(),updates,cb);
 		}
 	}
-
-	//*TODO do we really need to notify observers?
-	if (inventory_changed) gInventory.notifyObservers();
 }
 
 class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 2cc76c4b4c..246401ae85 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -50,7 +50,8 @@ public:
 	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
 
 	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false,
-								 bool enforce_item_restrictions = true);
+								 bool enforce_item_restrictions = true,
+								 bool enforce_ordering = true);
 	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
@@ -68,6 +69,7 @@ public:
 								   LLInventoryModel::item_array_t& items_to_kill);
 	void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 									  LLInventoryModel::item_array_t& items_to_kill);
+	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
@@ -190,7 +192,9 @@ public:
 
 	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
 	// COF is processed if cat_id is not specified
-	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null, bool update_base_outfit_ordering = false);
+	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
+									bool update_base_outfit_ordering = false,
+									LLPointer<LLInventoryCallback> cb = NULL);
 
 	bool isOutfitLocked() { return mOutfitLocked; }
 
@@ -263,7 +267,8 @@ class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 {
 public:
 	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false,
-								bool enforce_item_restrictions = true);
+								bool enforce_item_restrictions = true,
+								bool enforce_ordering = true);
 	virtual ~LLUpdateAppearanceOnDestroy();
 	/* virtual */ void fire(const LLUUID& inv_item);
 
@@ -271,6 +276,7 @@ private:
 	U32 mFireCount;
 	bool mUpdateBaseOrder;
 	bool mEnforceItemRestrictions;
+	bool mEnforceOrdering;
 };
 
 class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 06c614aeaa..38fa3c36e3 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1213,7 +1213,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 			{
 				changes["desc"] = update["desc"];
 			}
-			onItemUpdated(item_id,changes);
+			onItemUpdated(item_id,changes,true);
 		}
 		else if (cat)
 		{
@@ -1245,7 +1245,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	
 }
 
-void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates)
+void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
 {
 	U32 mask = LLInventoryObserver::NONE;
 
@@ -1275,6 +1275,12 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates)
 		}
 		mask |= LLInventoryObserver::INTERNAL;
 		addChangedMask(mask, item->getUUID());
+		if (update_parent_version)
+		{
+			// Descendent count is unchanged, but folder version incremented.
+			LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0);
+			accountForUpdate(up);
+		}
 		gInventory.notifyObservers(); // do we want to be able to make this optional?
 	}
 }
@@ -1852,47 +1858,6 @@ void LLInventoryModel::accountForUpdate(
 	}
 }
 
-
-/*
-void LLInventoryModel::incrementCategoryVersion(const LLUUID& category_id)
-{
-	LLViewerInventoryCategory* cat = getCategory(category_id);
-	if(cat)
-	{
-		S32 version = cat->getVersion();
-		if(LLViewerInventoryCategory::VERSION_UNKNOWN != version)
-		{
-			cat->setVersion(version + 1);
-			llinfos << "IncrementVersion: " << cat->getName() << " "
-					<< cat->getVersion() << llendl;
-		}
-		else
-		{
-			llinfos << "Attempt to increment version when unknown: "
-					<< category_id << llendl;
-		}
-	}
-	else
-	{
-		llinfos << "Attempt to increment category: " << category_id << llendl;
-	}
-}
-void LLInventoryModel::incrementCategorySetVersion(
-	const std::set<LLUUID>& categories)
-{
-	if(!categories.empty())
-	{ 
-		std::set<LLUUID>::const_iterator it = categories.begin();
-		std::set<LLUUID>::const_iterator end = categories.end();
-		for(; it != end; ++it)
-		{
-			incrementCategoryVersion(*it);
-		}
-	}
-}
-*/
-
-
 LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren(
 	const LLUUID& cat_id) const
 {
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 515c99c0b4..fd2481b531 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -340,7 +340,7 @@ public:
 	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
 
 	// Update model after an existing item gets updated on server.
-	void onItemUpdated(const LLUUID& item_id, const LLSD& updates);
+	void onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version);
 
 	// Update model after an existing category gets updated on server.
 	void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 90fef3b5ed..62bcfd20a7 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -726,7 +726,9 @@ void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD&
 	}
 	if (updates.has("desc"))
 	{
-		msg->addStringFast(_PREHASH_Description, updates["desc"].asString());
+		std::string new_desc = updates["desc"].asString();
+		LLInventoryItem::correctInventoryDescription(new_desc);
+		msg->addStringFast(_PREHASH_Description, new_desc);
 	}
 	else
 	{
@@ -1461,7 +1463,7 @@ void update_inventory_item(
 			obj->packUpdateMessage(msg, updates);
 			gAgent.sendReliableMessage();
 
-			gInventory.onItemUpdated(item_id, updates);
+			gInventory.onItemUpdated(item_id, updates,false);
 			if (cb)
 			{
 				cb->fire(item_id);
-- 
cgit v1.2.3


From c498f53d9ab02a41886b55762883d116801fd39b Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Tue, 28 May 2013 11:51:11 -0500
Subject: Sh-4035: Updated implementation according to new specs. Fixed a
 couple of outstanding bugs.

---
 indra/llui/llfloater.cpp                           |  12 ++
 indra/llui/llpanel.cpp                             |   3 +-
 indra/llui/llpanel.h                               |   5 +-
 indra/newview/llfloatersidepanelcontainer.cpp      |  13 ++-
 indra/newview/llfloatersidepanelcontainer.h        |   3 +
 indra/newview/llsidepanelappearance.cpp            | 125 ++++++++++++---------
 indra/newview/llsidepanelappearance.h              |  14 ++-
 .../newview/skins/default/xui/en/notifications.xml |  30 ++++-
 8 files changed, 139 insertions(+), 66 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 28dfda8faf..ae4961559e 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -713,6 +713,18 @@ void LLFloater::closeFloater(bool app_quitting)
 {
 	llinfos << "Closing floater " << getName() << llendl;
 	
+	if (!app_quitting)
+	{
+		if ( mVerifyUponClose && !mForceCloseAfterVerify )
+		{
+			onClose( app_quitting );
+			if ( mForceCloseAfterVerify ) 
+			{			
+				return;
+			}			
+		}
+	}	
+
 	if (app_quitting)
 	{
 		LLFloater::sQuitting = true;
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 01165a5718..7b7920f866 100755
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -116,7 +116,8 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 	mXMLFilename(p.filename),
 	mVisibleSignal(NULL),
 	mCloseConfirmationSignal(NULL),
-	mVerifyUponClose(false)
+	mVerifyUponClose(false),
+	mForceCloseAfterVerify(false)
 	// *NOTE: Be sure to also change LLPanel::initFromParams().  We have too
 	// many classes derived from LLPanel to retrofit them all to pass in params.
 {
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 1b0beaa5c8..d48fab6dd9 100755
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -255,8 +255,6 @@ public:
 	boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
 	boost::signals2::connection setCloseConfirmationCallback( const commit_signal_t::slot_type& cb );
 
-public:
-	const BOOL confirmClose() const { return mVerifyUponClose; }
 
 protected:
 	// Override to set not found list
@@ -276,6 +274,9 @@ protected:
 	std::string		mXMLFilename;
 	//Specific close-down logic in subclass
 	BOOL			mVerifyUponClose;
+public:	
+	BOOL			mForceCloseAfterVerify;
+
 private:
 	BOOL			mBgVisible;				// any background at all?
 	BOOL			mBgOpaque;				// use opaque color or image
diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index d5bb8157cf..13a9ba1695 100755
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -70,7 +70,16 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key)
 {
 	getChild<LLPanel>(sMainPanelName)->onOpen(key);
 }
-
+void LLFloaterSidePanelContainer::onClose(bool app_quitting)
+{		
+	mForceCloseAfterVerify = true;  		
+	LLSidepanelAppearance* panel = getSidePanelAppearance();
+	if ( panel )
+	{		
+		panel->mRevertSet = true;
+		panel->onCloseFromAppearance( this );			
+	}
+}
 void LLFloaterSidePanelContainer::onClickCloseBtn()
 {
 	LLSidepanelAppearance* panel = getSidePanelAppearance();
@@ -127,7 +136,7 @@ void LLFloaterSidePanelContainer::showPanel(const std::string& floater_name, con
 			{
 				if ( panel->checkForDirtyEdits() )
 				{
-					panel->onClickConfirmExitWithoutSaveIntoAppearance();
+					panel->onClickConfirmExitWithoutSaveIntoAppearance( floaterp );
 				}
 				else
 				{
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index 974934b48f..dc85570f7e 100755
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -44,6 +44,8 @@ class LLSidepanelAppearance;
  */
 class LLFloaterSidePanelContainer : public LLFloater
 {
+	friend class LLSidePanelAppearance;
+
 private:
 	static const std::string sMainPanelName;
 
@@ -52,6 +54,7 @@ public:
 	~LLFloaterSidePanelContainer();
 
 	/*virtual*/ void onOpen(const LLSD& key);
+	/*virtual*/ void onClose(bool app_quitting);
 	/*virtual*/ void onClickCloseBtn();
 	/*virtual*/ BOOL postBuild();
 				void  onConfirmationClose( const LLSD &confirm );
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 858ed06544..70da576c83 100755
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -50,6 +50,7 @@
 #include "llviewerwearable.h"
 #include "llnotificationsutil.h"
 #include "llfloatersidepanelcontainer.h"
+#include "llviewerfoldertype.h"
 
 static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance");
 
@@ -85,58 +86,86 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notificat
 	return false;
 }
 
-bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response)
+void LLSidepanelAppearance::onCloseFromAppearance(LLFloaterSidePanelContainer* obj)
 {
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if ( option == 0 ) 
-	{	
-		//revert current edits
-		mEditWearable->revertChanges();					
-		//LLAppearanceMgr::getInstance()->wearBaseOutfit();				
-		toggleWearableEditPanel(FALSE);		
-		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
-		mLLFloaterSidePanelContainer->close();			
-		return true;
-	}
-	return false;
-}
-
-void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose()
-{
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	mLLFloaterSidePanelContainer = obj;	
+	if ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) 
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
 		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
 	}
 	else
-	{
-		showOutfitsInventoryPanel();
+	{		
+		LLVOAvatarSelf::onCustomizeEnd(FALSE);		
+		toggleWearableEditPanel(FALSE);
+		mLLFloaterSidePanelContainer->mForceCloseAfterVerify=false;
 	}
 }
-
-
-bool LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response)
+bool LLSidepanelAppearance::onSaveCommit(const LLSD& notification, const LLSD& response)
 {
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		std::string outfit_name = response["message"].asString();
+		LLStringUtil::trim(outfit_name);
+		std::string current_outfit_name;
+
+		LLAppearanceMgr::getInstance()->getBaseOutfitName(current_outfit_name);
+
+		if ( current_outfit_name == outfit_name )
+		{
+			LLAppearanceMgr::getInstance()->updateBaseOutfit();
+		}
+		else		
+		{
+			LLUUID outfit_folder = LLAppearanceMgr::getInstance()->makeNewOutfitLinks( outfit_name,FALSE );		
+		}		
+
+		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
+		mLLFloaterSidePanelContainer->close();		
+	}
+
+	return false;
+}
+bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response)
+{	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if ( option == 0 ) 
 	{	
-		//revert current edits
-		mEditWearable->revertChanges();
-		toggleWearableEditPanel(FALSE);		
+		std::string outfit_name;
+		if (!LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name))
+		{
+			outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT);
+		}
+
+		LLSD args;
+		args["DESC"] = outfit_name;
+
+		LLSD payload;
+		LLNotificationsUtil::add("SaveOutfitEither", args, payload, boost::bind(&LLSidepanelAppearance::onSaveCommit, this, _1, _2));
+		showOutfitEditPanel();
+		return false;
+	}
+	else if ( option == 1 )
+	{
+		mEditWearable->revertChanges();					
+		toggleWearableEditPanel(FALSE);	
+		showOutfitEditPanel();
 		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
-		//mLLFloaterSidePanelContainer->close();			
-		showOutfitsInventoryPanel();
-		return true;
+		mRevertSet = true;
+		return false;
 	}
+	mLLFloaterSidePanelContainer->mForceCloseAfterVerify = false;
+	//mRevertSet = true;
 	return false;
 }
 
-void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance()
+void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance( LLFloaterSidePanelContainer* obj )
 {
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
+	mLLFloaterSidePanelContainer = obj;	
+	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() ||  mEditWearable->isDirty() )
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
-		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance,pSelf,_1,_2) );
+		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
 	}
 	else
 	{
@@ -145,33 +174,19 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance()
 }
 void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
 {
-	/*
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() )
-	{
-		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
-		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) );
-	}
-	else
-		*/
-	{
-		showOutfitsInventoryPanel();
-	}
+	showOutfitsInventoryPanel();
 }
 
 void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
-{
-	mLLFloaterSidePanelContainer = obj;	
-	if (  /*LLAppearanceMgr::getInstance()->isOutfitDirty() && */
-		 /*!LLAppearanceMgr::getInstance()->isOutfitLocked() ||*/
-		 ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) )
+{	mLLFloaterSidePanelContainer = obj;	
+	if ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) 
 	{
 		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
 		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
 	}
 	else
-	{
+	{				
 		LLVOAvatarSelf::onCustomizeEnd(FALSE);		
-		toggleWearableEditPanel(FALSE);
 		mLLFloaterSidePanelContainer->close();
 	}
 }
@@ -183,7 +198,8 @@ LLSidepanelAppearance::LLSidepanelAppearance() :
 	mOutfitEdit(NULL),
 	mCurrOutfitPanel(NULL),
 	mOpened(false),
-	mSidePanelJustOpened(true)
+	mSidePanelJustOpened(true),
+	mRevertSet(false)
 {
 	LLOutfitObserver& outfit_observer =  LLOutfitObserver::instance();
 	outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
@@ -264,11 +280,15 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 	{
 		// No specific panel requested.
 		// If we're opened for the first time then show My Outfits.
-		// Else do nothing.
+		// Else show outfit edit panel
 		if (!mOpened)
 		{
 			showOutfitsInventoryPanel();
 		}
+		else
+		{
+			showOutfitEditPanel();
+		}
 	}
 	else
 	{
@@ -665,3 +685,4 @@ bool LLSidepanelAppearance::checkForDirtyEdits()
 {
 	return ( mEditWearable->isDirty() ) ? true : false;
 }
+
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index caf5be62e9..5042e92f4b 100755
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -50,7 +50,8 @@ public:
 
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onOpen(const LLSD& key);	
-				void onClose(LLFloaterSidePanelContainer* obj);
+	/*virtual*/	void onClose(LLFloaterSidePanelContainer* obj);
+
 	void onClickCloseBtn();
 
 	void refreshCurrentOutfitName(const std::string& name = "");
@@ -72,10 +73,9 @@ public:
 	bool callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response);
 	void onClickConfirmExitWithoutSaveViaBack();
 	bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response);
-	void onClickConfirmExitWithoutSaveViaClose();
 	bool checkForDirtyEdits();	
-	bool callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response);
-	void onClickConfirmExitWithoutSaveIntoAppearance();
+	void onClickConfirmExitWithoutSaveIntoAppearance(LLFloaterSidePanelContainer* obj);
+	void onCloseFromAppearance(LLFloaterSidePanelContainer* obj);
 
 private:
 	void onFilterEdit(const std::string& search_string);
@@ -88,6 +88,9 @@ private:
 	void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE);
 	void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE);
 
+
+	bool	onSaveCommit(const LLSD& notification, const LLSD& response);
+
 	LLFilterEditor*			mFilterEditor;
 	LLPanelOutfitsInventory* mPanelOutfitsInventory;
 	LLPanelOutfitEdit*		mOutfitEdit;
@@ -115,6 +118,9 @@ private:
 	bool mSidePanelJustOpened;
 	LLFloaterSidePanelContainer* mLLFloaterSidePanelContainer;
 
+public:
+
+	bool mRevertSet;
 };
 
 #endif //LL_LLSIDEPANELAPPEARANCE_H
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 07c8ecc4dd..860dabdcc8 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10118,13 +10118,33 @@ Cannot create large prims that intersect other players.  Please re-try when othe
    icon="alertmodal.tga"
    name="ConfirmExitWithoutSave"
    type="alertmodal">
-    Closing this window will discard any changes you have made.
+    You have not saved the changes to your outfit. Would you like to save it now?
     <tag>confirm</tag>
     <usetemplate
-     name="okcancelignore"
-     notext="Cancel"
-     yestext="OK"
-     ignoretext="Don't show me this again."/>
+     name="yesnocancelbuttons"
+     notext="Revert"
+     yestext="Yes"
+     canceltext="Dismiss"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   label="Save Outfit"
+   name="SaveOutfitEither"
+   type="alertmodal">
+    <unique/>
+    Save outfit (defaults to current outfit):
+    <tag>confirm</tag>
+    <form name="form">
+      <input name="message" type="text">
+        [DESC]
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="OK"
+       text="Save"/>     
+    </form>
   </notification>
 
 </notifications>
-- 
cgit v1.2.3


From faaf8ba5c75c925d9922dda8ce43293222cadb3b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 29 May 2013 14:54:59 -0400
Subject: SH-4222 FIX, SH-3635 WIP - start of stuck-appearance checker, always
 increment folder version when a contained item is updated.

---
 indra/newview/llagentwearables.cpp  |  1 +
 indra/newview/llagentwearables.h    |  2 ++
 indra/newview/llappearancemgr.cpp   |  6 ++++++
 indra/newview/llappearancemgr.h     |  2 ++
 indra/newview/llviewerinventory.cpp |  2 +-
 indra/newview/llvoavatar.cpp        |  2 +-
 indra/newview/llvoavatarself.cpp    | 16 ++++++++++++++++
 indra/newview/llvoavatarself.h      |  1 +
 8 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index b4c3e33e0e..80c8364223 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1897,6 +1897,7 @@ bool LLAgentWearables::changeInProgress() const
 void LLAgentWearables::notifyLoadingStarted()
 {
 	mCOFChangeInProgress = true;
+	mCOFChangeTimer.reset();
 	mLoadingStartedSignal();
 }
 
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 5be4648636..0adf545aab 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -77,6 +77,7 @@ public:
 	BOOL			isWearableCopyable(LLWearableType::EType type, U32 index /*= 0*/) const;
 	BOOL			areWearablesLoaded() const;
 	bool			isCOFChangeInProgress() const { return mCOFChangeInProgress; }
+	F32				getCOFChangeTime() const { return mCOFChangeTimer.getElapsedTimeF32(); }
 	void			updateWearablesLoaded();
 	void			checkWearablesLoaded() const;
 	bool			canMoveWearable(const LLUUID& item_id, bool closer_to_body) const;
@@ -237,6 +238,7 @@ private:
 	 * True if agent's outfit is being changed now.
 	 */
 	BOOL			mCOFChangeInProgress;
+	LLTimer			mCOFChangeTimer;
 	
 	//--------------------------------------------------------------------------------
 	// Support classes
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 83ad06a3c7..30b6169b46 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -547,6 +547,7 @@ public:
 	bool isMostRecent();
 	void handleLateArrivals();
 	void resetTime(F32 timeout);
+	static S32 countActive() { return sActiveHoldingPatterns.size(); }
 	
 private:
 	found_list_t mFoundList;
@@ -1836,6 +1837,11 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo
 	}
 }
 
+S32 LLAppearanceMgr::countActiveHoldingPatterns()
+{
+	return LLWearableHoldingPattern::countActive();
+}
+
 static void remove_non_link_items(LLInventoryModel::item_array_t &items)
 {
 	LLInventoryModel::item_array_t pruned_items;
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 246401ae85..3fb470ef14 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -120,6 +120,8 @@ public:
 
 	void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
 
+	S32 countActiveHoldingPatterns();
+
 	// For debugging - could be moved elsewhere.
 	void dumpCat(const LLUUID& cat_id, const std::string& msg);
 	void dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 62bcfd20a7..465a49d004 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1463,7 +1463,7 @@ void update_inventory_item(
 			obj->packUpdateMessage(msg, updates);
 			gAgent.sendReliableMessage();
 
-			gInventory.onItemUpdated(item_id, updates,false);
+			gInventory.onItemUpdated(item_id, updates,true);
 			if (cb)
 			{
 				cb->fire(item_id);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 8e7bed39c4..6df5fab42b 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6023,7 +6023,7 @@ void LLVOAvatar::startPhase(const std::string& phase_name)
 			return;
 		}
 	}
-	LL_DEBUGS("Avatar") << "started phase " << phase_name << llendl;
+	LL_DEBUGS("Avatar") << avString() << " started phase " << phase_name << llendl;
 	getPhases().startPhase(phase_name);
 }
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 52c44e6e1b..5b6fcc5d27 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -234,6 +234,22 @@ void LLVOAvatarSelf::initInstance()
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
 	doPeriodically(check_for_unsupported_baked_appearance, 120.0);
+	doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
+}
+
+bool LLVOAvatarSelf::checkStuckAppearance()
+{
+	if (gAgentWearables.isCOFChangeInProgress())
+	{
+		LL_DEBUGS("Avatar") << "checking for stuck appearance" << llendl;
+		F32 change_time = gAgentWearables.getCOFChangeTime();
+		LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << llendl;
+		S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns();
+		LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << llendl;
+	}
+
+	// Return false to continue running check periodically.
+	return LLApp::isExiting();
 }
 
 // virtual
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 3b7b6bac64..e8b9a25327 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -138,6 +138,7 @@ public:
 public:
 	/*virtual*/ BOOL 	updateCharacter(LLAgent &agent);
 	/*virtual*/ void 	idleUpdateTractorBeam();
+	bool				checkStuckAppearance();
 
 	//--------------------------------------------------------------------
 	// Loading state
-- 
cgit v1.2.3


From 7f2cf1fa9cf7c09af8eeab3aa077eb0a9922d631 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Thu, 30 May 2013 17:44:51 -0400
Subject: SH-4147 FIX Macro avatar hover gets reset on relog

Hover minimum enforcement was getting triggered on relog for macro avatars before
the joint offsets were applied when loading the avatar.

Added code to verify that all attachments in COF have been rezzed, and all
attached objects are not in the process of being rebuilt to the enforcement code.

This should verify that we only apply the hover value enforcement when all rigged meshes
are actually loaded before enforcing minimum hover value
---
 indra/newview/llappearancemgr.cpp |  9 +++++++
 indra/newview/llappearancemgr.h   |  2 ++
 indra/newview/llviewerobject.cpp  | 22 +++++++++++++++
 indra/newview/llviewerobject.h    |  1 +
 indra/newview/llvoavatar.cpp      | 56 ++++++++++++++++++++++++++++++++-------
 5 files changed, 80 insertions(+), 10 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 30b6169b46..d817f10aee 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3250,6 +3250,15 @@ void LLAppearanceMgr::incrementCofVersion(LLHTTPClient::ResponderPtr responder_p
 	LLHTTPClient::get(url, body, responder_ptr, headers, 30.0f);
 }
 
+U32 LLAppearanceMgr::getNumAttachmentsInCOF()
+{
+	const LLUUID cof = getCOF();
+	LLInventoryModel::item_array_t obj_items;
+	getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT);
+	return obj_items.size();
+}
+
+
 std::string LLAppearanceMgr::getAppearanceServiceURL() const
 {
 	if (gSavedSettings.getString("DebugAvatarAppearanceServiceURLOverride").empty())
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 3fb470ef14..b63e883426 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -206,6 +206,8 @@ public:
 
 	void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL);
 
+	U32 getNumAttachmentsInCOF();
+
 	// *HACK Remove this after server side texture baking is deployed on all sims.
 	void incrementCofVersionLegacy();
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 064e96e394..63de1ab77a 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -5038,6 +5038,28 @@ void LLViewerObject::clearDrawableState(U32 state, BOOL recursive)
 	}
 }
 
+BOOL LLViewerObject::isDrawableState(U32 state, BOOL recursive) const
+{
+	BOOL matches = FALSE;
+	if (mDrawable)
+	{
+		matches = mDrawable->isState(state);
+	}
+	if (recursive)
+	{
+		for (child_list_t::const_iterator iter = mChildList.begin();
+			 (iter != mChildList.end()) && matches; iter++)
+		{
+			LLViewerObject* child = *iter;
+			matches &= child->isDrawableState(state, recursive);
+		}
+	}
+
+	return matches;
+}
+
+
+
 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 // RN: these functions assume a 2-level hierarchy 
 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 316dbce7d0..0390cbc5b0 100755
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -394,6 +394,7 @@ public:
 
 	void setDrawableState(U32 state, BOOL recursive = TRUE);
 	void clearDrawableState(U32 state, BOOL recursive = TRUE);
+	BOOL isDrawableState(U32 state, BOOL recursive = TRUE) const;
 
 	// Called when the drawable shifts
 	virtual void onShift(const LLVector4a &shift_vector)	{ }
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6df5fab42b..310ff47cf5 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5220,24 +5220,60 @@ void LLVOAvatar::computeBodySize()
 	LLAvatarAppearance::computeBodySize();
 
 	// Certain configurations of avatars can force the overall height (with offset) to go negative.
-	// Enforce a constraint to make sure we don't go below 0.1 meters.
+	// Enforce a constraint to make sure we don't go below 1.1 meters (server-enforced limit)
 	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
+	const LLViewerObject * last_object = NULL;
 	if (isSelf() && getWearableData() && isFullyLoaded() && !LLApp::isQuitting())
 	{
-		LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0);
-		if (shape && !shape->getVolitile()) 
+		// Do not force a hover parameter change while we have pending attachments, which may be mesh-based with 
+		// joint offsets.
+		if (LLAppearanceMgr::instance().getNumAttachmentsInCOF() == getNumAttachments())
 		{
-			F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER);
-			if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f))
+			LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0);
+			BOOL loaded = TRUE;
+			for (attachment_map_t::const_iterator points_iter = mAttachmentPoints.begin();
+				 points_iter != mAttachmentPoints.end() && loaded;
+				 ++points_iter)
 			{
-				hover_value = -(mBodySize.mV[VZ] - 1.1f); // avoid floating point rounding making the above check continue to fail.
-				llassert(mBodySize.mV[VZ] + hover_value >= 1.1f);
+				const LLViewerJointAttachment *attachment_pt = (*points_iter).second;
+				if (attachment_pt) 
+				{
+					for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attach_iter = attachment_pt->mAttachedObjects.begin(); attach_iter != attachment_pt->mAttachedObjects.end(); attach_iter++) 
+					{
+						const LLViewerObject* object = (LLViewerObject*)*attach_iter;
+						if (object) 
+						{
+							last_object = object;
+							llwarns << "attachment at point: " << (*points_iter).first << " object exists: " << object->getAttachmentItemID() << llendl;
+							loaded &=!object->isDrawableState(LLDrawable::REBUILD_ALL);
+							if (!loaded && shape && !shape->getVolitile()) 
+							{
+								llwarns << "caught unloaded attachment! skipping enforcement" << llendl;
+							}
+						}
+					}
+				}
+			}
 
-				hover_value =  llmin(hover_value, 0.0f); // don't force the hover value to be greater than 0.
+			if (last_object) 
+			{
+				LL_DEBUGS("Avatar") << "scanned at least one object!"  << LL_ENDL;
+			}
+			if (loaded && shape && !shape->getVolitile()) 
+			{
+				F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER);
+				if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f))
+				{
+					hover_value = -(mBodySize.mV[VZ] - 1.1f); // avoid floating point rounding making the above check continue to fail.
+					llassert(mBodySize.mV[VZ] + hover_value >= 1.1f);
+
+					hover_value =  llmin(hover_value, 0.0f); // don't force the hover value to be greater than 0.
 
-				mAvatarOffset.mV[VZ] = hover_value;
-				shape->setVisualParamWeight(AVATAR_HOVER,hover_value, FALSE);
+					LL_DEBUGS("Avatar") << "changed hover value to: " << hover_value << " from: " << mAvatarOffset.mV[VZ] << LL_ENDL;
 
+					mAvatarOffset.mV[VZ] = hover_value;
+					shape->setVisualParamWeight(AVATAR_HOVER,hover_value, FALSE);
+				}
 			}
 		}
 	}
-- 
cgit v1.2.3


From 9552f733ef0b581158665a1a464b5be7d4bada2a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 31 May 2013 13:54:32 -0400
Subject: SH-3635 WIP

---
 indra/newview/llappearancemgr.cpp | 18 ++++++++++++++++++
 indra/newview/llappearancemgr.h   |  2 ++
 indra/newview/llviewerregion.cpp  |  2 +-
 indra/newview/llviewerstats.cpp   | 40 ++++++++++++++-------------------------
 indra/newview/llviewerstats.h     |  5 ++---
 indra/newview/llvoavatar.cpp      | 18 ++++++++++++------
 indra/newview/llvoavatarself.cpp  |  3 ++-
 7 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 30b6169b46..2288f633f4 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -397,6 +397,12 @@ public:
 		LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries)
 	{
 		addItems(src_items);
+		sInstanceCount++;
+	}
+
+	~LLCallAfterInventoryCopyMgr()
+	{
+		sInstanceCount--;
 	}
 	
 	virtual bool requestOperation(const LLUUID& item_id)
@@ -419,8 +425,15 @@ public:
 			);
 		return true;
 	}
+
+	static S32 getInstanceCount() { return sInstanceCount; }
+	
+private:
+	static S32 sInstanceCount;
 };
 
+S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
+
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
 														 bool enforce_item_restrictions,
 														 bool enforce_ordering):
@@ -2154,6 +2167,11 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 														   category->getUUID(), copy, append));
 }
 
+S32 LLAppearanceMgr::getActiveCopyOperations() const
+{
+	return LLCallAfterInventoryCopyMgr::getInstanceCount(); 
+}
+
 void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
 {
 	LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 3fb470ef14..4679ceaf57 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -71,6 +71,8 @@ public:
 									  LLInventoryModel::item_array_t& items_to_kill);
 	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
+	S32 getActiveCopyOperations() const;
+	
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
 							 LLPointer<LLInventoryCallback> cb);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e77b29aca4..b635087d66 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1877,7 +1877,7 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
 {
 	if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
 	{
-		llwarns << "getCapability called before caps received" << llendl;
+		llwarns << "getCapability called before caps received for " << name << llendl;
 	}
 	
 	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index b73411080a..68633fba6e 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -734,44 +734,28 @@ void send_stats()
 	LLHTTPClient::post(url, body, new ViewerStatsResponder());
 }
 
-LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
+LLTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
 {
 	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
 	if (iter == mPhaseMap.end())
 	{
-		LLFrameTimer timer;
+		LLTimer timer;
 		mPhaseMap[phase_name] = timer;
 	}
-	LLFrameTimer& timer = mPhaseMap[phase_name];
+	LLTimer& timer = mPhaseMap[phase_name];
 	return timer;
 }
 
 void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
 {
-	LLFrameTimer& timer = getPhaseTimer(phase_name);
-	lldebugs << "startPhase " << phase_name << llendl;
-	timer.unpause();
-}
-
-void LLViewerStats::PhaseMap::stopAllPhases()
-{
-	for (phase_map_t::iterator iter = mPhaseMap.begin();
-		 iter != mPhaseMap.end(); ++iter)
-	{
-		const std::string& phase_name = iter->first;
-		if (iter->second.getStarted())
-		{
-			// Going from started to paused state - record stats.
-			recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
-		}
-		lldebugs << "stopPhase (all) " << phase_name << llendl;
-		iter->second.pause();
-	}
+	LLTimer& timer = getPhaseTimer(phase_name);
+	timer.start();
+	LL_DEBUGS("Avatar") << "startPhase " << phase_name << llendl;
 }
 
 void LLViewerStats::PhaseMap::clearPhases()
 {
-	lldebugs << "clearPhases" << llendl;
+	LL_DEBUGS("Avatar") << "clearPhases" << llendl;
 
 	mPhaseMap.clear();
 }
@@ -796,7 +780,6 @@ LLViewerStats::PhaseMap::PhaseMap()
 {
 }
 
-
 void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
 {
 	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
@@ -809,6 +792,7 @@ void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
 		}
 	}
 }
+
 // static
 LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
 {
@@ -832,14 +816,18 @@ void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32
 bool LLViewerStats::PhaseMap::getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed)
 {
 	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
+	bool found = false;
 	if (iter != mPhaseMap.end())
 	{
+		found = true;
 		elapsed =  iter->second.getElapsedTimeF32();
 		completed = !iter->second.getStarted();
-		return true;
+		LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << llendl;
 	}
 	else
 	{
-		return false;
+		LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND"  << llendl;
 	}
+
+	return found;
 }
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 6b2461be41..eaa0b6beff 100755
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -279,7 +279,7 @@ public:
 
 	// Phase tracking (originally put in for avatar rezzing), tracking
 	// progress of active/completed phases for activities like outfit changing.
-	typedef std::map<std::string,LLFrameTimer>	phase_map_t;
+	typedef std::map<std::string,LLTimer>	phase_map_t;
 	typedef std::map<std::string,StatsAccumulator>	phase_stats_t;
 	class PhaseMap
 	{
@@ -288,11 +288,10 @@ public:
 		static phase_stats_t sStats;
 	public:
 		PhaseMap();
-		LLFrameTimer& 	getPhaseTimer(const std::string& phase_name);
+		LLTimer& 		getPhaseTimer(const std::string& phase_name);
 		bool 			getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed);
 		void			startPhase(const std::string& phase_name);
 		void			stopPhase(const std::string& phase_name);
-		void			stopAllPhases();
 		void			clearPhases();
 		LLSD			dumpPhases();
 		static StatsAccumulator& getPhaseStats(const std::string& phase_name);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6df5fab42b..2cbdf93eeb 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6013,9 +6013,12 @@ void LLVOAvatar::clearPhases()
 
 void LLVOAvatar::startPhase(const std::string& phase_name)
 {
-	F32 elapsed;
-	bool completed;
-	if (getPhases().getPhaseValues(phase_name, elapsed, completed))
+	F32 elapsed = 0.0;
+	bool completed = false;
+	bool found = getPhases().getPhaseValues(phase_name, elapsed, completed);
+	//LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name
+	//					<< " found " << found << " elapsed " << elapsed << " completed " << completed << llendl;
+	if (found)
 	{
 		if (!completed)
 		{
@@ -6029,9 +6032,12 @@ void LLVOAvatar::startPhase(const std::string& phase_name)
 
 void LLVOAvatar::stopPhase(const std::string& phase_name, bool err_check)
 {
-	F32 elapsed;
-	bool completed;
-	if (getPhases().getPhaseValues(phase_name, elapsed, completed))
+	F32 elapsed = 0.0;
+	bool completed = false;
+	bool found = getPhases().getPhaseValues(phase_name, elapsed, completed);
+	//LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name
+	//					<< " found " << found << " elapsed " << elapsed << " completed " << completed << llendl;
+	if (found)
 	{
 		if (!completed)
 		{
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 5b6fcc5d27..b2fcfb6250 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -246,6 +246,8 @@ bool LLVOAvatarSelf::checkStuckAppearance()
 		LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << llendl;
 		S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns();
 		LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << llendl;
+		S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations();
+		LL_DEBUGS("Avatar") << "active copy operations " << active_copies << llendl;
 	}
 
 	// Return false to continue running check periodically.
@@ -2369,7 +2371,6 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records,
 
 void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 {
-	// gAgentAvatarp->stopAllPhases();
 	static volatile bool reporting_started(false);
 	static volatile S32 report_sequence(0);
 
-- 
cgit v1.2.3


From 02d2808a419ce37df877756883b96147d06aa4d8 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 3 Jun 2013 13:21:42 -0400
Subject: SH-3635 WIP - unstick outfit change if stuck beyond a certain time
 range

---
 indra/newview/llvoavatarself.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index b2fcfb6250..232bf3e478 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -239,6 +239,9 @@ void LLVOAvatarSelf::initInstance()
 
 bool LLVOAvatarSelf::checkStuckAppearance()
 {
+	const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0;
+	const F32 UNCONDITIONAL_UNSTICK_INTERVAL = 600.0;
+	
 	if (gAgentWearables.isCOFChangeInProgress())
 	{
 		LL_DEBUGS("Avatar") << "checking for stuck appearance" << llendl;
@@ -248,6 +251,12 @@ bool LLVOAvatarSelf::checkStuckAppearance()
 		LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << llendl;
 		S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations();
 		LL_DEBUGS("Avatar") << "active copy operations " << active_copies << llendl;
+
+		if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) ||
+			(change_time > UNCONDITIONAL_UNSTICK_INTERVAL))
+		{
+			gAgentWearables.notifyLoadingFinished();
+		}
 	}
 
 	// Return false to continue running check periodically.
-- 
cgit v1.2.3


From c81b685b4217b3c321815e1993d39fb0b479a767 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Mon, 3 Jun 2013 16:10:46 -0400
Subject: Fix for sh-4221 Sometimes ctrl+q needed to be hit twice

---
 indra/llui/llfloater.cpp                      |  8 ++++----
 indra/llui/llfloater.h                        |  2 +-
 indra/llui/llpanel.cpp                        |  4 ++--
 indra/llui/llpanel.h                          |  2 +-
 indra/newview/llfloatersidepanelcontainer.cpp | 15 ++++++++++-----
 indra/newview/llfloatersidepanelcontainer.h   |  2 ++
 6 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index ae4961559e..63491aa296 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -704,9 +704,9 @@ void LLFloater::openFloater(const LLSD& key)
 	dirtyRect();
 }
 
-void LLFloater::verifyClose()
+void LLFloater::verifyClose( bool app_quitting )
 {
-	LLPanel::handleCloseConfirmation();
+	LLPanel::handleCloseConfirmation( app_quitting );
 }
 
 void LLFloater::closeFloater(bool app_quitting)
@@ -726,7 +726,7 @@ void LLFloater::closeFloater(bool app_quitting)
 	}	
 
 	if (app_quitting)
-	{
+	{	
 		LLFloater::sQuitting = true;
 	}
 	
@@ -2659,7 +2659,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
 		{
 			if ( floaterp->mVerifyUponClose )
 			{			
-				floaterp->verifyClose();
+				floaterp->verifyClose(app_quitting);
 			}
 			else
 			{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index bf71b527b3..8eb40ddd0b 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -225,7 +225,7 @@ public:
 
 	// If allowed, close the floater cleanly, releasing focus.
 	virtual void	closeFloater(bool app_quitting = false);
-	virtual void	verifyClose();
+	virtual void	verifyClose( bool app_quitting = false );
 
 	// Close the floater or its host. Use when hidding or toggling a floater instance.
 	virtual void	closeHostedFloater();
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 7b7920f866..b0bdbcb7d1 100755
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -354,11 +354,11 @@ void LLPanel::handleVisibilityChange ( BOOL new_visibility )
 }
 
 
-void LLPanel::handleCloseConfirmation( )
+void LLPanel::handleCloseConfirmation( bool app_quitting)
 {	
 	if (mCloseConfirmationSignal)
 	{
-		(*mCloseConfirmationSignal)(this, LLSD() ); 
+		(*mCloseConfirmationSignal)(this, LLSD( app_quitting ) ); 
 	}
 }
 void LLPanel::setFocus(BOOL b)
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index d48fab6dd9..02f8c0aba7 100755
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -116,7 +116,7 @@ public:
 	/*virtual*/ void	draw();	
 	/*virtual*/ BOOL	handleKeyHere( KEY key, MASK mask );
 	/*virtual*/ void 	handleVisibilityChange ( BOOL new_visibility );
-				void	handleCloseConfirmation( );
+				void	handleCloseConfirmation( bool app_quitting );
 
 
 	// From LLFocusableElement
diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index 13a9ba1695..02216420da 100755
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -40,7 +40,8 @@
 const std::string LLFloaterSidePanelContainer::sMainPanelName("main_panel");
 
 LLFloaterSidePanelContainer::LLFloaterSidePanelContainer(const LLSD& key, const Params& params)
-:	LLFloater(key, params)
+: LLFloater(key, params)
+, mAppQuiting( false )
 {
 	// Prevent transient floaters (e.g. IM windows) from hiding
 	// when this floater is clicked.
@@ -56,7 +57,8 @@ BOOL LLFloaterSidePanelContainer::postBuild()
 }
 
 void  LLFloaterSidePanelContainer::onConfirmationClose( const LLSD &confirm )
-{	
+{
+	mAppQuiting = confirm.asBoolean();
 	onClickCloseBtn();
 }
 
@@ -69,10 +71,12 @@ LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer()
 void LLFloaterSidePanelContainer::onOpen(const LLSD& key)
 {
 	getChild<LLPanel>(sMainPanelName)->onOpen(key);
+	mAppQuiting = false;
 }
-void LLFloaterSidePanelContainer::onClose(bool app_quitting)
-{		
-	mForceCloseAfterVerify = true;  		
+
+void LLFloaterSidePanelContainer::onClose( bool app_quitting )
+{
+	if (! mAppQuiting ) { mForceCloseAfterVerify = true; }
 	LLSidepanelAppearance* panel = getSidePanelAppearance();
 	if ( panel )
 	{		
@@ -80,6 +84,7 @@ void LLFloaterSidePanelContainer::onClose(bool app_quitting)
 		panel->onCloseFromAppearance( this );			
 	}
 }
+
 void LLFloaterSidePanelContainer::onClickCloseBtn()
 {
 	LLSidepanelAppearance* panel = getSidePanelAppearance();
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index dc85570f7e..f543cfd5c4 100755
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -89,6 +89,8 @@ public:
 
 private:
 	LLSidepanelAppearance* getSidePanelAppearance();
+private: 
+	bool mAppQuiting;
 };
 
 #endif // LL_LLFLOATERSIDEPANELCONTAINER_H
-- 
cgit v1.2.3


From 63940048eff9c9a1929574ba7581f4c835af35d3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 3 Jun 2013 17:09:25 -0400
Subject: SH-4166 WIP - COF-slammer infrastructure working for non-AIS case.

---
 indra/newview/llappearancemgr.cpp   | 56 +++++++++++++++++++++++--------------
 indra/newview/llappearancemgr.h     |  2 --
 indra/newview/llviewerinventory.cpp | 50 +++++++++++++++++++++++++++++++++
 indra/newview/llviewerinventory.h   |  7 +++++
 4 files changed, 92 insertions(+), 23 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 2288f633f4..0c09689a70 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1622,25 +1622,6 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLIn
 	}
 }
 
-void LLAppearanceMgr::removeCategoryContents(const LLUUID& category, bool keep_outfit_links,
-											 LLPointer<LLInventoryCallback> cb)
-{
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
-	gInventory.collectDescendents(category, cats, items,
-								  LLInventoryModel::EXCLUDE_TRASH);
-	for (S32 i = 0; i < items.count(); ++i)
-	{
-		LLViewerInventoryItem *item = items.get(i);
-		if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
-			continue;
-		if (item->getIsLinkType())
-		{
-			remove_inventory_item(item->getUUID(), cb);
-		}
-	}
-}
-
 // Keep the last N wearables of each type.  For viewer 2.0, N is 1 for
 // both body parts and clothing items.
 void LLAppearanceMgr::filterWearableItems(
@@ -1704,6 +1685,11 @@ void LLAppearanceMgr::removeAll(LLInventoryModel::item_array_t& items_to_kill,
 void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 {
 	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
+	if (!pcat)
+	{
+		llwarns << "no category found for id " << category << llendl;
+		return;
+	}
 	LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL;
 
 	const LLUUID cof = getCOF();
@@ -1769,6 +1755,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 
 	// Will link all the above items.
 	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+#if 0
 	linkAll(cof,all_items,link_waiter);
 
 	// Add link to outfit if category is an outfit. 
@@ -1785,7 +1772,34 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	// even in the non-append case, createBaseOutfitLink() already
 	// deletes the existing link, don't need to do it again here.
 	bool keep_outfit_links = true;
-	removeCategoryContents(cof, keep_outfit_links, link_waiter);
+	remove_folder_contents(cof, keep_outfit_links, link_waiter);
+#else
+	LLSD contents = LLSD::emptyArray();
+	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
+		 it != all_items.end(); ++it)
+	{
+		LLSD item_contents;
+		LLInventoryItem *item = *it;
+		item_contents["name"] = item->getName();
+		item_contents["desc"] = item->getActualDescription();
+		item_contents["linked_id"] = item->getLinkedUUID();
+		item_contents["type"] = LLAssetType::AT_LINK; 
+		contents.append(item_contents);
+	}
+	const LLUUID& base_id = append ? getBaseOutfitUUID() : category;
+	LLViewerInventoryCategory *base_cat = gInventory.getCategory(base_id);
+	if (base_cat)
+	{
+		LLSD base_contents;
+		base_contents["name"] = base_cat->getName();
+		base_contents["desc"] = "";
+		base_contents["linked_id"] = base_cat->getLinkedUUID();
+		base_contents["type"] = LLAssetType::AT_LINK_FOLDER; 
+		contents.append(base_contents);
+	}
+	llinfos << "slamming to: " << ll_pretty_print_sd(contents) << llendl;
+	slam_inventory_folder(getCOF(), contents, link_waiter);
+#endif
 
 	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
 }
@@ -2776,7 +2790,7 @@ bool LLAppearanceMgr::updateBaseOutfit()
 	updateClothingOrderingInfo();
 
 	// in a Base Outfit we do not remove items, only links
-	removeCategoryContents(base_outfit_id, false, NULL);
+	remove_folder_contents(base_outfit_id, false, NULL);
 
 	LLPointer<LLInventoryCallback> dirty_state_updater =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 4679ceaf57..97f3283818 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -235,8 +235,6 @@ private:
 								   LLInventoryModel::item_array_t& obj_items,
 								   LLInventoryModel::item_array_t& gest_items);
 
-	void removeCategoryContents(const LLUUID& category, bool keep_outfit_links,
-								LLPointer<LLInventoryCallback> cb);
 	static void onOutfitRename(const LLSD& notification, const LLSD& response);
 
 	void setOutfitLocked(bool locked);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 465a49d004..db8671d51b 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1828,6 +1828,54 @@ void create_new_item(const std::string& name,
 	
 }	
 
+void slam_inventory_folder(const LLUUID& folder_id,
+						   const LLSD& contents,
+						   LLPointer<LLInventoryCallback> cb)
+{
+	std::string cap;
+	if (AISCommand::getCap(cap))
+	{
+		//LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
+		//cmd_ptr->run_command();
+	}
+	else // no cap
+	{
+		for (LLSD::array_const_iterator it = contents.beginArray();
+			 it != contents.endArray();
+			 ++it)
+		{
+			const LLSD& item_contents = *it;
+			link_inventory_item(gAgent.getID(),
+								item_contents["linked_id"].asUUID(),
+								folder_id,
+								item_contents["name"].asString(),
+								item_contents["desc"].asString(),
+								LLAssetType::EType(item_contents["type"].asInteger()),
+								cb);
+		}
+		remove_folder_contents(folder_id,false,cb);
+	}
+}
+
+void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
+							LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryModel::cat_array_t cats;
+	LLInventoryModel::item_array_t items;
+	gInventory.collectDescendents(category, cats, items,
+								  LLInventoryModel::EXCLUDE_TRASH);
+	for (S32 i = 0; i < items.count(); ++i)
+	{
+		LLViewerInventoryItem *item = items.get(i);
+		if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
+			continue;
+		if (item->getIsLinkType())
+		{
+			remove_inventory_item(item->getUUID(), cb);
+		}
+	}
+}
+
 const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
 const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
 const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
@@ -2263,3 +2311,5 @@ BOOL LLViewerInventoryItem::regenerateLink()
 	gInventory.notifyObservers();
 	return TRUE;
 }
+
+
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index c52b0c2d9d..9af71dfc9c 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -407,4 +407,11 @@ void menu_create_inventory_item(LLInventoryPanel* root,
 								const LLSD& userdata,
 								const LLUUID& default_parent_uuid = LLUUID::null);
 
+void slam_inventory_folder(const LLUUID& folder_id,
+						   const LLSD& contents,
+						   LLPointer<LLInventoryCallback> cb);
+
+void remove_folder_contents(const LLUUID& folder_id, bool keep_outfit_links,
+							  LLPointer<LLInventoryCallback> cb);
+
 #endif // LL_LLVIEWERINVENTORY_H
-- 
cgit v1.2.3


From c5c2e7b405bbbcc3d1c1756e34c3069611f0e4a1 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Mon, 3 Jun 2013 18:08:48 -0400
Subject: SH-4035 spec change. If you revert after quiting, SL shutsdown.

---
 indra/llui/llfloater.cpp                    |  5 +++++
 indra/newview/llfloatersidepanelcontainer.h |  3 ++-
 indra/newview/llsidepanelappearance.cpp     | 10 ++++++++--
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 63491aa296..93eca8b62e 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -717,9 +717,13 @@ void LLFloater::closeFloater(bool app_quitting)
 	{
 		if ( mVerifyUponClose && !mForceCloseAfterVerify )
 		{
+
+			llinfos<<"prep#dogshit1"<<llendl;
 			onClose( app_quitting );
 			if ( mForceCloseAfterVerify ) 
 			{			
+
+				llinfos<<"prep#dogshit1b"<<llendl;
 				return;
 			}			
 		}
@@ -727,6 +731,7 @@ void LLFloater::closeFloater(bool app_quitting)
 
 	if (app_quitting)
 	{	
+		llinfos<<"prep#dogshit2"<<llendl;
 		LLFloater::sQuitting = true;
 	}
 	
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index f543cfd5c4..b276821805 100755
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -89,7 +89,8 @@ public:
 
 private:
 	LLSidepanelAppearance* getSidePanelAppearance();
-private: 
+
+public: 
 	bool mAppQuiting;
 };
 
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 70da576c83..775c148ea1 100755
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -151,11 +151,17 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica
 		toggleWearableEditPanel(FALSE);	
 		showOutfitEditPanel();
 		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
-		mRevertSet = true;
+		if ( !mLLFloaterSidePanelContainer->mAppQuiting ) 
+		{
+			mRevertSet = true; 			
+		}
+		else
+		{
+			mLLFloaterSidePanelContainer->closeFloater( true );
+		}
 		return false;
 	}
 	mLLFloaterSidePanelContainer->mForceCloseAfterVerify = false;
-	//mRevertSet = true;
 	return false;
 }
 
-- 
cgit v1.2.3


From 3340eb8c7146c6690876e1927c19a11188210814 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 5 Jun 2013 10:46:12 -0400
Subject: Updated to latest llappearanceutility package

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 06a70ea5ed..7cf6e23386 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1291,9 +1291,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>df8857aeb5f44dfd95f9f9f57814423a</string>
+              <string>ddd6a49dd5bbb76216f73feafa26e65c</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/275707/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130511.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/276989/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130605.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From f7c9739fd9bb4355765ecff4b92e879b38302e49 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 5 Jun 2013 15:13:48 -0400
Subject: SH-3635 WIP - COF slammer works in AISv3 regions. Extensive rework of
 onAISUpdateReceived.

---
 indra/llcommon/llsdutil.cpp         |   2 +-
 indra/llinventory/llinventory.cpp   |   6 ++
 indra/newview/llinventorymodel.cpp  | 167 ++++++++++++++++++++++++++++++------
 indra/newview/llinventorymodel.h    |   2 +-
 indra/newview/llviewerinventory.cpp |  32 ++++++-
 5 files changed, 179 insertions(+), 30 deletions(-)

diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 803417d368..562fd26658 100755
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -182,7 +182,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd)
 
 char* ll_pretty_print_sd(const LLSD& sd)
 {
-	const U32 bufferSize = 10 * 1024;
+	const U32 bufferSize = 100 * 1024;
 	static char buffer[bufferSize];
 	std::ostringstream stream;
 	//stream.rdbuf()->pubsetbuf(buffer, bufferSize);
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index a529aa3af3..77b837f8ac 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -50,6 +50,7 @@ static const std::string INV_DESC_LABEL("desc");
 static const std::string INV_PERMISSIONS_LABEL("permissions");
 static const std::string INV_SHADOW_ID_LABEL("shadow_id");
 static const std::string INV_ASSET_ID_LABEL("asset_id");
+static const std::string INV_LINKED_ID_LABEL("linked_id");
 static const std::string INV_SALE_INFO_LABEL("sale_info");
 static const std::string INV_FLAGS_LABEL("flags");
 static const std::string INV_CREATION_DATE_LABEL("created_at");
@@ -1109,6 +1110,11 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd)
 	{
 		mAssetUUID = sd[w];
 	}
+	w = INV_LINKED_ID_LABEL;
+	if (sd.has(w))
+	{
+		mAssetUUID = sd[w];
+	}
 	w = INV_ASSET_TYPE_LABEL;
 	if (sd.has(w))
 	{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 38fa3c36e3..1a5e76183c 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1172,77 +1172,188 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 {
 	LL_DEBUGS("Inventory") << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl;
 
+	// Track changes to descendent counts for accounting.
+	std::map<LLUUID,S32> cat_deltas;
+	typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
+	deferred_item_map_t items_created;
+	deferred_item_map_t items_updated;
+	std::set<LLUUID> objects_deleted;
+
+	// parse _categories_removed -> objects_deleted
 	uuid_vec_t cat_ids;
 	parse_llsd_uuid_array(update,"_categories_removed",cat_ids);
 	for (uuid_vec_t::const_iterator it = cat_ids.begin();
 		 it != cat_ids.end(); ++it)
 	{
-		onObjectDeletedFromServer(*it, false);
+		LLViewerInventoryCategory *cat = getCategory(*it);
+		cat_deltas[cat->getParentUUID()]--;
+		objects_deleted.insert(*it);
 	}
 
+	// parse _categories_items_removed -> objects_deleted
 	uuid_vec_t item_ids;
 	parse_llsd_uuid_array(update,"_category_items_removed",item_ids);
 	for (uuid_vec_t::const_iterator it = item_ids.begin();
 		 it != item_ids.end(); ++it)
 	{
-		onObjectDeletedFromServer(*it, false);
+		LLViewerInventoryItem *item = getItem(*it);
+		cat_deltas[item->getParentUUID()]--;
+		objects_deleted.insert(*it);
 	}
 
+	// parse _broken_links_removed -> objects_deleted
 	uuid_vec_t broken_link_ids;
 	parse_llsd_uuid_array(update,"_broken_links_removed",broken_link_ids);
 	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
 		 it != broken_link_ids.end(); ++it)
 	{
-		onObjectDeletedFromServer(*it, false);
+		LLViewerInventoryItem *item = getItem(*it);
+		cat_deltas[item->getParentUUID()]--;
+		objects_deleted.insert(*it);
 	}
 
-	if (update.has("item_id"))
+	// parse _created_items
+	uuid_vec_t created_item_ids;
+	parse_llsd_uuid_array(update,"_created_items",created_item_ids);
+
+	if (update.has("_embedded"))
 	{
-		// item has been modified or possibly created (would be better if we could distinguish these cases directly)
-		LLUUID item_id = update["item_id"].asUUID();
-		LLViewerInventoryItem *item = gInventory.getItem(item_id);
-		LLViewerInventoryCategory *cat = gInventory.getCategory(item_id);
-		if (item)
+		const LLSD& embedded = update["_embedded"];
+		for(LLSD::map_const_iterator it = embedded.beginMap(),
+				end = embedded.endMap();
+				it != end; ++it)
 		{
-			LLSD changes;
-			if (update.has("name") && update["name"] != item->getName())
+			const std::string& field = (*it).first;
+
+			// parse created links
+			if (field == "link")
 			{
-				changes["name"] = update["name"];
-			}
-			if (update.has("desc") && update["desc"] != item->getActualDescription())
+				const LLSD& links = embedded["link"];
+				for(LLSD::map_const_iterator linkit = links.beginMap(),
+						linkend = links.endMap();
+					linkit != linkend; ++linkit)
+				{
+					const LLUUID link_id((*linkit).first);
+					const LLSD& link_map = (*linkit).second;
+					uuid_vec_t::const_iterator pos =
+						std::find(created_item_ids.begin(),
+								  created_item_ids.end(),link_id);
+					if (pos != created_item_ids.end())
+					{
+						LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
+						BOOL rv = new_link->unpackMessage(link_map);
+						if (rv)
+						{
+							items_created[link_id] = new_link;
+							const LLUUID& parent_id = new_link->getParentUUID();
+							cat_deltas[parent_id]++;
+						}
+						else
+						{
+							llwarns << "failed to unpack" << llendl;
+						}
+					}
+					else
+					{
+						LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
+					}
+				}
+		}
+			else
 			{
-				changes["desc"] = update["desc"];
+				llwarns << "unrecognized embedded field " << field << llendl;
 			}
-			onItemUpdated(item_id,changes,true);
 		}
-		else if (cat)
+		
+	}
+
+	// Parse item update at the top level.
+	if (update.has("item_id"))
+	{
+		LLUUID item_id = update["item_id"].asUUID();
+		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+		BOOL rv = new_item->unpackMessage(update);
+		if (rv)
 		{
-			llerrs << "don't handle cat update yet" << llendl;
+			items_updated[item_id] = new_item;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			cat_deltas[new_item->getParentUUID()];
 		}
 		else
 		{
-			llerrs << "don't handle creation case yet" << llendl;
+			llerrs << "unpack failed" << llendl;
 		}
-	
 	}
 
+	// Do descendent/version accounting.
+	// Can remove this if/when we use the version info directly.
+	for (std::map<LLUUID,S32>::const_iterator catit = cat_deltas.begin();
+		 catit != cat_deltas.end(); ++catit)
+	{
+		const LLUUID cat_id(catit->first);
+		S32 delta = catit->second;
+		LLInventoryModel::LLCategoryUpdate up(cat_id, delta);
+		gInventory.accountForUpdate(up);
+	}
+	
 	// TODO - how can we use this version info? Need to be sure all
 	// changes are going through AIS first, or at least through
 	// something with a reliable responder.
-#if 0
 	const std::string& ucv = "_updated_category_versions";
 	if (update.has(ucv))
 	{
 		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
 				end = update[ucv].endMap();
-				it != end; ++it)
+			it != end; ++it)
 		{
 			const LLUUID id((*it).first);
 			S32 version = (*it).second.asInteger();
+			LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+			if (cat->getVersion() != version)
+			{
+				llwarns << "Possible version mismatch, viewer " << cat->getVersion()
+						<< " server " << version << llendl;
+			}
 		}
 	}
-#endif
+
+	// CREATE ITEMS
+	for (deferred_item_map_t::const_iterator create_it = items_created.begin();
+		 create_it != items_created.end(); ++create_it)
+	{
+		LLUUID item_id(create_it->first);
+		LLPointer<LLViewerInventoryItem> new_item = create_it->second;
+
+		// FIXME risky function since it calls updateServer() in some
+		// cases.  Maybe break out the update/create cases, in which
+		// case this is create.
+		LL_DEBUGS("Inventory") << "created item " << item_id << llendl;
+		gInventory.updateItem(new_item);
+	}
 	
+	// UPDATE ITEMS
+	for (deferred_item_map_t::const_iterator update_it = items_updated.begin();
+		 update_it != items_updated.end(); ++update_it)
+	{
+		LLUUID item_id(update_it->first);
+		LLPointer<LLViewerInventoryItem> new_item = update_it->second;
+		// FIXME risky function since it calls updateServer() in some
+		// cases.  Maybe break out the update/create cases, in which
+		// case this is update.
+		LL_DEBUGS("Inventory") << "updated item " << item_id << llendl;
+		gInventory.updateItem(new_item);
+	}
+
+	// DELETE OBJECTS
+	for (std::set<LLUUID>::const_iterator del_it = objects_deleted.begin();
+		 del_it != objects_deleted.end(); ++del_it)
+	{
+		LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
+		onObjectDeletedFromServer(*del_it, false, false);
+	}
+
 }
 
 void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
@@ -1395,7 +1506,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 
 // Update model after an item is confirmed as removed from
 // server. Works for categories or items.
-void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links)
+void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version)
 {
 	LLPointer<LLInventoryObject> obj = getObject(object_id);
 	if(obj)
@@ -1406,9 +1517,13 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f
 			onDescendentsPurgedFromServer(object_id, fix_broken_links);
 		}
 
+
 		// From item/cat removeFromServer()
-		LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
-		accountForUpdate(up);
+		if (update_parent_version)
+		{
+			LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
+			accountForUpdate(up);
+		}
 
 		// From purgeObject()
 		LLPreview::hide(object_id);
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index fd2481b531..a41a824906 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -334,7 +334,7 @@ public:
 		
 	// Update model after an item is confirmed as removed from
 	// server. Works for categories or items.
-	void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true);
+	void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true, bool update_parent_version = true);
 
 	// Update model after all descendents removed from server.
 	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index db8671d51b..0608c46051 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -493,6 +493,34 @@ private:
 	LLSD mUpdates;
 };
 
+class SlamFolderCommand: public AISCommand
+{
+public:
+	SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
+		mContents(contents),
+		AISCommand(callback)
+	{
+		std::string cap;
+		if (!getCap(cap))
+		{
+			llwarns << "No cap found" << llendl;
+			return;
+		}
+		LLUUID tid;
+		tid.generate();
+		std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
+		llinfos << url << llendl;
+		LLCurl::ResponderPtr responder = this;
+		LLSD headers;
+		headers["Content-Type"] = "application/llsd+xml";
+		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout);
+		setCommandFunc(cmd);
+	}
+private:
+	LLSD mContents;
+};
+
 ///----------------------------------------------------------------------------
 /// Class LLViewerInventoryItem
 ///----------------------------------------------------------------------------
@@ -1835,8 +1863,8 @@ void slam_inventory_folder(const LLUUID& folder_id,
 	std::string cap;
 	if (AISCommand::getCap(cap))
 	{
-		//LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
-		//cmd_ptr->run_command();
+		LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
+		cmd_ptr->run_command();
 	}
 	else // no cap
 	{
-- 
cgit v1.2.3


From ca806315a98627b29a4933cbf8b27431ca43dd0f Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 5 Jun 2013 15:52:44 -0400
Subject: SH-3635 WIP - logging cleanup, moved some big dumps into separate XML
 files

---
 indra/newview/llappearancemgr.cpp  | 18 ++++++------------
 indra/newview/llinventorymodel.cpp |  5 ++++-
 indra/newview/llvoavatar.cpp       |  9 +++++++++
 indra/newview/llvoavatar.h         |  1 +
 4 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 0c09689a70..646b2d18dd 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1797,7 +1797,10 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 		base_contents["type"] = LLAssetType::AT_LINK_FOLDER; 
 		contents.append(base_contents);
 	}
-	llinfos << "slamming to: " << ll_pretty_print_sd(contents) << llendl;
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents);
+	}
 	slam_inventory_folder(getCOF(), contents, link_waiter);
 #endif
 
@@ -2950,7 +2953,7 @@ protected:
 			//LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
 			if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 			{
-				dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
+				dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
 			}
 		}
 		else
@@ -2968,7 +2971,7 @@ protected:
 		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
 			const LLSD& content = getContent();
-			dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
+			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
 			debugCOF(content);
 		}
 		onFailure();
@@ -2992,15 +2995,6 @@ protected:
 		}
 	}	
 
-	void dumpContents(const std::string outprefix, const LLSD& content)
-	{
-		std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
-		std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
-		std::ofstream ofs(fullpath.c_str(), std::ios_base::out);
-		ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY);
-		LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL;
-	}
-
 	void debugCOF(const LLSD& content)
 	{
 		LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 1a5e76183c..c0c48d6695 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1170,7 +1170,10 @@ void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_ve
 
 void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
 {
-	LL_DEBUGS("Inventory") << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl;
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
+	}
 
 	// Track changes to descendent counts for accounting.
 	std::map<LLUUID,S32> cat_deltas;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2cbdf93eeb..1dbcabf2b3 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7416,6 +7416,15 @@ std::string get_sequential_numbered_file_name(const std::string& prefix,
 	return outfilename;
 }
 
+void dump_sequential_xml(const std::string outprefix, const LLSD& content)
+{
+	std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
+	std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
+	std::ofstream ofs(fullpath.c_str(), std::ios_base::out);
+	ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY);
+	LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL;
+}
+
 void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables )
 {
 	std::string outprefix(prefix);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 19ad49d3a1..fad2fd962c 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -998,6 +998,7 @@ extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
 
 std::string get_sequential_numbered_file_name(const std::string& prefix,
 											  const std::string& suffix);
+void dump_sequential_xml(const std::string outprefix, const LLSD& content);
 void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value);
 
 #endif // LL_VOAVATAR_H
-- 
cgit v1.2.3


From a07cee746cfb83c64618600ab288c09cd5297c94 Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 5 Jun 2013 17:34:25 -0400
Subject: Updated to latest llappearanceutility

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 7cf6e23386..5e76702302 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1291,9 +1291,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ddd6a49dd5bbb76216f73feafa26e65c</string>
+              <string>8a4043450403dc43c0b228118c4bb34b</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/276989/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130605.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/277034/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130605.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From b1769b6a60954152111cc5d0f596ff21cce84ffa Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 6 Jun 2013 13:55:27 -0400
Subject: SH-4234 FIX - the only persistent failure seen was caused by a broken
 link in the outfit. Modified updateIsDirty() to ignore broken links.

---
 indra/newview/llappearancemgr.cpp      | 19 ++++++++++++++++++-
 indra/newview/llinventoryfunctions.cpp |  7 +++++++
 indra/newview/llinventoryfunctions.h   |  7 +++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 722587ec0e..2698e2db35 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2611,7 +2611,7 @@ void LLAppearanceMgr::updateIsDirty()
 
 	if (base_outfit.notNull())
 	{
-		LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK);
+		LLIsValidItemLink collector;
 
 		LLInventoryModel::cat_array_t cof_cats;
 		LLInventoryModel::item_array_t cof_items;
@@ -2625,6 +2625,7 @@ void LLAppearanceMgr::updateIsDirty()
 
 		if(outfit_items.count() != cof_items.count())
 		{
+			LL_DEBUGS("Avatar") << "item count different" << llendl;
 			// Current outfit folder should have one more item than the outfit folder.
 			// this one item is the link back to the outfit folder itself.
 			mOutfitIsDirty = true;
@@ -2644,6 +2645,22 @@ void LLAppearanceMgr::updateIsDirty()
 				item1->getName() != item2->getName() ||
 				item1->getActualDescription() != item2->getActualDescription())
 			{
+				if (item1->getLinkedUUID() != item2->getLinkedUUID())
+				{
+					LL_DEBUGS("Avatar") << "link id different " << llendl;
+				}
+				else
+				{
+					if (item1->getName() != item2->getName())
+					{
+						LL_DEBUGS("Avatar") << "name different " << item1->getName() << " " << item2->getName() << llendl;
+					}
+					if (item1->getActualDescription() != item2->getActualDescription())
+					{
+						LL_DEBUGS("Avatar") << "desc different " << item1->getActualDescription()
+											<< " " << item2->getActualDescription() << llendl;
+					}
+				}
 				mOutfitIsDirty = true;
 				return;
 			}
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index b5fb226872..faa5d70952 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -738,6 +738,13 @@ bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item
 	return FALSE;
 }
 
+bool LLIsValidItemLink::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+	LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+	if (!vitem) return false;
+	return (vitem->getActualType() == LLAssetType::AT_LINK  && !vitem->getIsBrokenLink());
+}
+
 bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 {
 	if(mType == LLAssetType::AT_CATEGORY)
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index f1066a4dc9..6b3861aa79 100755
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -186,6 +186,13 @@ protected:
 	LLAssetType::EType mType;
 };
 
+class LLIsValidItemLink : public LLInventoryCollectFunctor
+{
+public:
+	virtual bool operator()(LLInventoryCategory* cat,
+							LLInventoryItem* item);
+};
+
 class LLIsTypeWithPermissions : public LLInventoryCollectFunctor
 {
 public:
-- 
cgit v1.2.3


From 5f1a43489b8fb54bf09d624fb48bad3079682b9d Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Thu, 6 Jun 2013 17:04:09 -0400
Subject: Use the codeticket number ($revision) instead of the nonexistent
 ${VERSION_VIEWER} to set a unique version in the debian changelogs and
 version strings.

---
 build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build.sh b/build.sh
index 1275f41fe1..dfb0ddad7a 100755
--- a/build.sh
+++ b/build.sh
@@ -279,7 +279,7 @@ then
       # mangle the changelog
       dch --force-bad-version \
           --distribution unstable \
-          --newversion "${VIEWER_VERSION}" \
+          --newversion "${revision}" \
           "Automated build #$build_id, repository $branch revision $revision." \
           >> "$build_log" 2>&1
 
-- 
cgit v1.2.3


From bee76e305214598b2cb148e399d86e28d80287ca Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 6 Jun 2013 17:59:16 -0400
Subject: SH-4166 WIP - fix for a permissions issue that was preventing
 cof-created links from being reordered in outfits.

---
 indra/newview/llinventorymodel.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index c0c48d6695..532d3a3495 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1247,6 +1247,13 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 						BOOL rv = new_link->unpackMessage(link_map);
 						if (rv)
 						{
+							LLPermissions default_perms;
+							default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
+							default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
+							new_link->setPermissions(default_perms);
+							LLSaleInfo default_sale_info;
+							new_link->setSaleInfo(default_sale_info);
+							//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl;
 							items_created[link_id] = new_link;
 							const LLUUID& parent_id = new_link->getParentUUID();
 							cat_deltas[parent_id]++;
-- 
cgit v1.2.3


From 36812775a4e3dc4badb64175582b43f9166b973b Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Thu, 6 Jun 2013 18:53:06 -0400
Subject: Updated llappearance-utility-source autobuild package to latest and
 changed debian changelog mangling to include codeticket number.

---
 autobuild.xml | 37 ++++++++++++++++++-------------------
 build.sh      |  6 +++++-
 2 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 5e76702302..f0d2d04c67 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -498,9 +498,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-	      <string>10352aab979c333a52dbad21b6e6fba9</string>
+              <string>10352aab979c333a52dbad21b6e6fba9</string>
               <key>url</key>
-	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/274403/arch/Darwin/installer/fmodex-4.44-darwin-20130419.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/274403/arch/Darwin/installer/fmodex-4.44-darwin-20130419.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -510,7 +510,7 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-          <string>79e45527aa9fb90b813599dff5ce01a7</string>
+              <string>79e45527aa9fb90b813599dff5ce01a7</string>
               <key>url</key>
               <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/274378/arch/Linux/installer/fmodex-4.44-linux-20130419.tar.bz2</string>
             </map>
@@ -522,9 +522,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-	      <string>0980cdf98a322a780ba739e324d0b955</string>
+              <string>0980cdf98a322a780ba739e324d0b955</string>
               <key>url</key>
-	      <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/274401/arch/CYGWIN/installer/fmodex-4.44-windows-20130419.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/274401/arch/CYGWIN/installer/fmodex-4.44-windows-20130419.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -747,7 +747,6 @@
           </map>
         </map>
       </map>
-
       <key>google_breakpad</key>
       <map>
         <key>license</key>
@@ -762,10 +761,10 @@
           <map>
             <key>archive</key>
             <map>
-           <key>hash</key>
-	   <string>aff5566e04003de0383941981198e04e</string>
-          <key>url</key>
-          <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130329.tar.bz2</string>
+              <key>hash</key>
+              <string>aff5566e04003de0383941981198e04e</string>
+              <key>url</key>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -774,10 +773,10 @@
           <map>
             <key>archive</key>
             <map>
-             <key>hash</key>
-	         <string>52257e5eb166a0b69c9c0c38f6e1920e</string>
-             <key>url</key>
-	         <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
+              <key>hash</key>
+              <string>52257e5eb166a0b69c9c0c38f6e1920e</string>
+              <key>url</key>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -787,9 +786,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-	      <string>d812a6dfcabe6528198a3191068dac09</string>
+              <string>d812a6dfcabe6528198a3191068dac09</string>
               <key>url</key>
-             <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/CYGWIN/installer/google_breakpad-0.0.0-rev1099-windows-20130329.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/CYGWIN/installer/google_breakpad-0.0.0-rev1099-windows-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -837,7 +836,7 @@
               <key>hash</key>
               <string>98994d5b0b4b3d43be22aa6a5c36e6fa</string>
               <key>url</key>
-		<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-mock-graham/rev/272961/arch/CYGWIN/installer/gmock-1.6.0-windows-20130327.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-mock-graham/rev/272961/arch/CYGWIN/installer/gmock-1.6.0-windows-20130327.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1291,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>8a4043450403dc43c0b228118c4bb34b</string>
+              <string>495feeabaaa38a96e8cc3d3d42c0e124</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/277034/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130605.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/277105/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130606.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/build.sh b/build.sh
index dfb0ddad7a..4b966acbe0 100755
--- a/build.sh
+++ b/build.sh
@@ -276,10 +276,14 @@ then
     then
       begin_section "Build Viewer Debian Package"
       local have_private_repo=false
+      
+      # Get the current version. 
+      local current_version=`dpkg-parsechangelog | grep ^Version | awk '{ print $2 }'`
+      
       # mangle the changelog
       dch --force-bad-version \
           --distribution unstable \
-          --newversion "${revision}" \
+          --newversion "${current_version}"+"${revision}" \
           "Automated build #$build_id, repository $branch revision $revision." \
           >> "$build_log" 2>&1
 
-- 
cgit v1.2.3


From d847b9dc3fdbc0a17ca4a1191955699505940f65 Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Thu, 6 Jun 2013 19:42:22 -0400
Subject: Can't use bash local keyword outside of functions.

---
 autobuild.xml | 4 ++--
 build.sh      | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index f0d2d04c67..331e3d8cec 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>495feeabaaa38a96e8cc3d3d42c0e124</string>
+              <string>55e009de4f87023a57e0a04a19f8a25b</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/277105/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130606.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/277110/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130606.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/build.sh b/build.sh
index 4b966acbe0..e4183f0ace 100755
--- a/build.sh
+++ b/build.sh
@@ -275,10 +275,10 @@ then
     if $build_viewer_deb && [ "$last_built_variant" == "Release" ]
     then
       begin_section "Build Viewer Debian Package"
-      local have_private_repo=false
+      have_private_repo=false
       
       # Get the current version. 
-      local current_version=`dpkg-parsechangelog | grep ^Version | awk '{ print $2 }'`
+      current_version=`dpkg-parsechangelog | grep ^Version | awk '{ print $2 }'`
       
       # mangle the changelog
       dch --force-bad-version \
-- 
cgit v1.2.3


From 41694a902dc8cfebebb6e23691d41cb5627fa5a1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 7 Jun 2013 10:35:07 -0400
Subject: SH-4216 WIP - broke up the onAISUpdateReceived monolith

---
 indra/newview/llinventorymodel.cpp | 252 ++++++++++++++++++++++---------------
 1 file changed, 149 insertions(+), 103 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 532d3a3495..3c7539a7f9 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1154,70 +1154,70 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
 	notifyObservers();
 }
 
-void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_vec_t& ids)
+class AISUpdate
 {
-	ids.clear();
-	if (content.has(name))
-	{
-		for(LLSD::array_const_iterator it = content[name].beginArray(),
-				end = content[name].endArray();
-				it != end; ++it)
-		{
-			ids.push_back((*it).asUUID());
-		}
-	}
-}
-
-void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
-{
-	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
-	{
-		dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
-	}
+public:
+	AISUpdate(const LLSD& update);
+	void parseUpdate(const LLSD& update);
+	void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids);
+	void parseLink(const LLUUID& link_id, const LLSD& link_map);
+	void parseCreatedLinks(const LLSD& links);
+	void doUpdate();
+private:
+	typedef std::map<LLUUID,S32> uuid_int_map_t;
+	uuid_int_map_t mCatDeltas;
+	uuid_int_map_t mCatVersions;
 
-	// Track changes to descendent counts for accounting.
-	std::map<LLUUID,S32> cat_deltas;
 	typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
-	deferred_item_map_t items_created;
-	deferred_item_map_t items_updated;
-	std::set<LLUUID> objects_deleted;
+	deferred_item_map_t mItemsCreated;
+	deferred_item_map_t mItemsUpdated;
 
-	// parse _categories_removed -> objects_deleted
+	std::set<LLUUID> mObjectsDeleted;
+	uuid_vec_t mItemsCreatedIds;
+};
+
+AISUpdate::AISUpdate(const LLSD& update)
+{
+	parseUpdate(update);
+}
+
+void AISUpdate::parseUpdate(const LLSD& update)
+{
+	// parse _categories_removed -> mObjectsDeleted
 	uuid_vec_t cat_ids;
-	parse_llsd_uuid_array(update,"_categories_removed",cat_ids);
+	parseUUIDArray(update,"_categories_removed",cat_ids);
 	for (uuid_vec_t::const_iterator it = cat_ids.begin();
 		 it != cat_ids.end(); ++it)
 	{
-		LLViewerInventoryCategory *cat = getCategory(*it);
-		cat_deltas[cat->getParentUUID()]--;
-		objects_deleted.insert(*it);
+		LLViewerInventoryCategory *cat = gInventory.getCategory(*it);
+		mCatDeltas[cat->getParentUUID()]--;
+		mObjectsDeleted.insert(*it);
 	}
 
-	// parse _categories_items_removed -> objects_deleted
+	// parse _categories_items_removed -> mObjectsDeleted
 	uuid_vec_t item_ids;
-	parse_llsd_uuid_array(update,"_category_items_removed",item_ids);
+	parseUUIDArray(update,"_category_items_removed",item_ids);
 	for (uuid_vec_t::const_iterator it = item_ids.begin();
 		 it != item_ids.end(); ++it)
 	{
-		LLViewerInventoryItem *item = getItem(*it);
-		cat_deltas[item->getParentUUID()]--;
-		objects_deleted.insert(*it);
+		LLViewerInventoryItem *item = gInventory.getItem(*it);
+		mCatDeltas[item->getParentUUID()]--;
+		mObjectsDeleted.insert(*it);
 	}
 
-	// parse _broken_links_removed -> objects_deleted
+	// parse _broken_links_removed -> mObjectsDeleted
 	uuid_vec_t broken_link_ids;
-	parse_llsd_uuid_array(update,"_broken_links_removed",broken_link_ids);
+	parseUUIDArray(update,"_broken_links_removed",broken_link_ids);
 	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
 		 it != broken_link_ids.end(); ++it)
 	{
-		LLViewerInventoryItem *item = getItem(*it);
-		cat_deltas[item->getParentUUID()]--;
-		objects_deleted.insert(*it);
+		LLViewerInventoryItem *item = gInventory.getItem(*it);
+		mCatDeltas[item->getParentUUID()]--;
+		mObjectsDeleted.insert(*it);
 	}
 
 	// parse _created_items
-	uuid_vec_t created_item_ids;
-	parse_llsd_uuid_array(update,"_created_items",created_item_ids);
+	parseUUIDArray(update,"_created_items",mItemsCreatedIds);
 
 	if (update.has("_embedded"))
 	{
@@ -1227,48 +1227,13 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 				it != end; ++it)
 		{
 			const std::string& field = (*it).first;
-
+			
 			// parse created links
 			if (field == "link")
 			{
 				const LLSD& links = embedded["link"];
-				for(LLSD::map_const_iterator linkit = links.beginMap(),
-						linkend = links.endMap();
-					linkit != linkend; ++linkit)
-				{
-					const LLUUID link_id((*linkit).first);
-					const LLSD& link_map = (*linkit).second;
-					uuid_vec_t::const_iterator pos =
-						std::find(created_item_ids.begin(),
-								  created_item_ids.end(),link_id);
-					if (pos != created_item_ids.end())
-					{
-						LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
-						BOOL rv = new_link->unpackMessage(link_map);
-						if (rv)
-						{
-							LLPermissions default_perms;
-							default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
-							default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
-							new_link->setPermissions(default_perms);
-							LLSaleInfo default_sale_info;
-							new_link->setSaleInfo(default_sale_info);
-							//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl;
-							items_created[link_id] = new_link;
-							const LLUUID& parent_id = new_link->getParentUUID();
-							cat_deltas[parent_id]++;
-						}
-						else
-						{
-							llwarns << "failed to unpack" << llendl;
-						}
-					}
-					else
-					{
-						LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
-					}
-				}
-		}
+				parseCreatedLinks(links);
+			}
 			else
 			{
 				llwarns << "unrecognized embedded field " << field << llendl;
@@ -1285,11 +1250,11 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 		BOOL rv = new_item->unpackMessage(update);
 		if (rv)
 		{
-			items_updated[item_id] = new_item;
+			mItemsUpdated[item_id] = new_item;
 			// This statement is here to cause a new entry with 0
 			// delta to be created if it does not already exist;
 			// otherwise has no effect.
-			cat_deltas[new_item->getParentUUID()];
+			mCatDeltas[new_item->getParentUUID()];
 		}
 		else
 		{
@@ -1297,10 +1262,86 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 		}
 	}
 
+	// Parse updated category versions.
+	const std::string& ucv = "_updated_category_versions";
+	if (update.has(ucv))
+	{
+		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
+				end = update[ucv].endMap();
+			it != end; ++it)
+		{
+			const LLUUID id((*it).first);
+			S32 version = (*it).second.asInteger();
+			mCatVersions[id] = version;
+		}
+	}
+}
+
+void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids)
+{
+	ids.clear();
+	if (content.has(name))
+	{
+		for(LLSD::array_const_iterator it = content[name].beginArray(),
+				end = content[name].endArray();
+				it != end; ++it)
+		{
+			ids.push_back((*it).asUUID());
+		}
+	}
+}
+
+void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map)
+{
+	LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
+	BOOL rv = new_link->unpackMessage(link_map);
+	if (rv)
+	{
+		LLPermissions default_perms;
+		default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
+		default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
+		new_link->setPermissions(default_perms);
+		LLSaleInfo default_sale_info;
+		new_link->setSaleInfo(default_sale_info);
+		//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl;
+		mItemsCreated[link_id] = new_link;
+		const LLUUID& parent_id = new_link->getParentUUID();
+		mCatDeltas[parent_id]++;
+	}
+	else
+	{
+		llwarns << "failed to parse" << llendl;
+	}
+}
+
+void AISUpdate::parseCreatedLinks(const LLSD& links)
+{
+	for(LLSD::map_const_iterator linkit = links.beginMap(),
+			linkend = links.endMap();
+		linkit != linkend; ++linkit)
+	{
+		const LLUUID link_id((*linkit).first);
+		const LLSD& link_map = (*linkit).second;
+		uuid_vec_t::const_iterator pos =
+			std::find(mItemsCreatedIds.begin(),
+					  mItemsCreatedIds.end(),link_id);
+		if (pos != mItemsCreatedIds.end())
+		{
+			parseLink(link_id,link_map);
+		}
+		else
+		{
+			LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
+		}
+	}
+}
+
+void AISUpdate::doUpdate()
+{
 	// Do descendent/version accounting.
 	// Can remove this if/when we use the version info directly.
-	for (std::map<LLUUID,S32>::const_iterator catit = cat_deltas.begin();
-		 catit != cat_deltas.end(); ++catit)
+	for (std::map<LLUUID,S32>::const_iterator catit = mCatDeltas.begin();
+		 catit != mCatDeltas.end(); ++catit)
 	{
 		const LLUUID cat_id(catit->first);
 		S32 delta = catit->second;
@@ -1311,27 +1352,22 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	// TODO - how can we use this version info? Need to be sure all
 	// changes are going through AIS first, or at least through
 	// something with a reliable responder.
-	const std::string& ucv = "_updated_category_versions";
-	if (update.has(ucv))
+	for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin();
+		 ucv_it != mCatVersions.end(); ++ucv_it)
 	{
-		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
-				end = update[ucv].endMap();
-			it != end; ++it)
+		const LLUUID id = ucv_it->first;
+		S32 version = ucv_it->second;
+		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+		if (cat->getVersion() != version)
 		{
-			const LLUUID id((*it).first);
-			S32 version = (*it).second.asInteger();
-			LLViewerInventoryCategory *cat = gInventory.getCategory(id);
-			if (cat->getVersion() != version)
-			{
-				llwarns << "Possible version mismatch, viewer " << cat->getVersion()
-						<< " server " << version << llendl;
-			}
+			llwarns << "Possible version mismatch, viewer " << cat->getVersion()
+					<< " server " << version << llendl;
 		}
 	}
 
 	// CREATE ITEMS
-	for (deferred_item_map_t::const_iterator create_it = items_created.begin();
-		 create_it != items_created.end(); ++create_it)
+	for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin();
+		 create_it != mItemsCreated.end(); ++create_it)
 	{
 		LLUUID item_id(create_it->first);
 		LLPointer<LLViewerInventoryItem> new_item = create_it->second;
@@ -1344,8 +1380,8 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	}
 	
 	// UPDATE ITEMS
-	for (deferred_item_map_t::const_iterator update_it = items_updated.begin();
-		 update_it != items_updated.end(); ++update_it)
+	for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin();
+		 update_it != mItemsUpdated.end(); ++update_it)
 	{
 		LLUUID item_id(update_it->first);
 		LLPointer<LLViewerInventoryItem> new_item = update_it->second;
@@ -1357,13 +1393,23 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	}
 
 	// DELETE OBJECTS
-	for (std::set<LLUUID>::const_iterator del_it = objects_deleted.begin();
-		 del_it != objects_deleted.end(); ++del_it)
+	for (std::set<LLUUID>::const_iterator del_it = mObjectsDeleted.begin();
+		 del_it != mObjectsDeleted.end(); ++del_it)
 	{
 		LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
-		onObjectDeletedFromServer(*del_it, false, false);
+		gInventory.onObjectDeletedFromServer(*del_it, false, false);
+	}
+}
+
+void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
+{
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
 	}
 
+	AISUpdate ais_update(update); // parse update llsd into stuff to do.
+	ais_update.doUpdate(); // execute the updates in the appropriate order.
 }
 
 void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
-- 
cgit v1.2.3


From 89e3959cf393ce9eeb058304264d4f55f4fe9ca2 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 7 Jun 2013 12:58:04 -0400
Subject: SH-4216 WIP - moved AISv3 commands and responders to llaisapi.* files

---
 indra/newview/CMakeLists.txt        |   2 +
 indra/newview/llaisapi.cpp          | 481 ++++++++++++++++++++++++++++++++++++
 indra/newview/llaisapi.h            | 143 +++++++++++
 indra/newview/llinventorymodel.cpp  | 248 +------------------
 indra/newview/llviewerinventory.cpp |   3 +
 5 files changed, 630 insertions(+), 247 deletions(-)
 create mode 100755 indra/newview/llaisapi.cpp
 create mode 100755 indra/newview/llaisapi.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4560951900..dc9370bd69 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -98,6 +98,7 @@ include_directories(SYSTEM
 set(viewer_SOURCE_FILES
     groupchatlistener.cpp
     llaccountingcostmanager.cpp
+    llaisapi.cpp
     llagent.cpp
     llagentaccess.cpp
     llagentcamera.cpp
@@ -679,6 +680,7 @@ set(viewer_HEADER_FILES
     ViewerInstall.cmake
     groupchatlistener.h
     llaccountingcostmanager.h
+    llaisapi.h
     llagent.h
     llagentaccess.h
     llagentcamera.h
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
new file mode 100755
index 0000000000..6adf35efb8
--- /dev/null
+++ b/indra/newview/llaisapi.cpp
@@ -0,0 +1,481 @@
+/** 
+ * @file llaisapi.cpp
+ * @brief classes and functions for interfacing with the v3+ ais inventory service. 
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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 "llviewerprecompiledheaders.h"
+#include "llaisapi.h"
+
+#include "llagent.h"
+#include "llcallbacklist.h"
+#include "llinventorymodel.h"
+#include "llsdutil.h"
+#include "llviewerregion.h"
+
+///----------------------------------------------------------------------------
+/// Classes for AISv3 support.
+///----------------------------------------------------------------------------
+
+// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
+AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback):
+	mCallback(callback)
+{
+	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
+}
+
+void AISCommand::run_command()
+{
+	mCommandFunc();
+}
+
+void AISCommand::setCommandFunc(command_func_type command_func)
+{
+	mCommandFunc = command_func;
+}
+	
+// virtual
+bool AISCommand::getResponseUUID(const LLSD& content, LLUUID& id)
+{
+	return false;
+}
+	
+/* virtual */
+void AISCommand::httpSuccess()
+{
+	// Command func holds a reference to self, need to release it
+	// after a success or final failure.
+	setCommandFunc(no_op);
+		
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+	mRetryPolicy->onSuccess();
+		
+	gInventory.onAISUpdateReceived("AISCommand", content);
+
+	if (mCallback)
+	{
+		LLUUID item_id; // will default to null if parse fails.
+		getResponseUUID(content,item_id);
+		mCallback->fire(item_id);
+	}
+}
+
+/*virtual*/
+void AISCommand::httpFailure()
+{
+	const LLSD& content = getContent();
+	S32 status = getStatus();
+	const std::string& reason = getReason();
+	const LLSD& headers = getResponseHeaders();
+	if (!content.isMap())
+	{
+		LL_DEBUGS("Inventory") << "Malformed response contents " << content
+							   << " status " << status << " reason " << reason << llendl;
+	}
+	else
+	{
+		LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
+							   << " status " << status << " reason " << reason << llendl;
+	}
+	mRetryPolicy->onFailure(status, headers);
+	F32 seconds_to_wait;
+	if (mRetryPolicy->shouldRetry(seconds_to_wait))
+	{
+		doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
+	}
+	else
+	{
+		// Command func holds a reference to self, need to release it
+		// after a success or final failure.
+		setCommandFunc(no_op);
+	}
+}
+
+//static
+bool AISCommand::getCap(std::string& cap)
+{
+	if (gAgent.getRegion())
+	{
+		cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
+	}
+	if (!cap.empty())
+	{
+		return true;
+	}
+	return false;
+}
+
+RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
+									 LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	std::string url = cap + std::string("/item/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LLHTTPClient::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
+											 LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	std::string url = cap + std::string("/category/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LLHTTPClient::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
+												 LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
+	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
+									 const LLSD& updates,
+									 LLPointer<LLInventoryCallback> callback):
+	mUpdates(updates),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	std::string url = cap + std::string("/item/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& item_id,
+											 const LLSD& updates,
+											 LLPointer<LLInventoryCallback> callback):
+	mUpdates(updates),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	std::string url = cap + std::string("/category/") + item_id.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
+	mContents(contents),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	LLUUID tid;
+	tid.generate();
+	std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
+	llinfos << url << llendl;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+AISUpdate::AISUpdate(const LLSD& update)
+{
+	parseUpdate(update);
+}
+
+void AISUpdate::parseUpdate(const LLSD& update)
+{
+	// parse _categories_removed -> mObjectsDeleted
+	uuid_vec_t cat_ids;
+	parseUUIDArray(update,"_categories_removed",cat_ids);
+	for (uuid_vec_t::const_iterator it = cat_ids.begin();
+		 it != cat_ids.end(); ++it)
+	{
+		LLViewerInventoryCategory *cat = gInventory.getCategory(*it);
+		mCatDeltas[cat->getParentUUID()]--;
+		mObjectsDeleted.insert(*it);
+	}
+
+	// parse _categories_items_removed -> mObjectsDeleted
+	uuid_vec_t item_ids;
+	parseUUIDArray(update,"_category_items_removed",item_ids);
+	for (uuid_vec_t::const_iterator it = item_ids.begin();
+		 it != item_ids.end(); ++it)
+	{
+		LLViewerInventoryItem *item = gInventory.getItem(*it);
+		mCatDeltas[item->getParentUUID()]--;
+		mObjectsDeleted.insert(*it);
+	}
+
+	// parse _broken_links_removed -> mObjectsDeleted
+	uuid_vec_t broken_link_ids;
+	parseUUIDArray(update,"_broken_links_removed",broken_link_ids);
+	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
+		 it != broken_link_ids.end(); ++it)
+	{
+		LLViewerInventoryItem *item = gInventory.getItem(*it);
+		mCatDeltas[item->getParentUUID()]--;
+		mObjectsDeleted.insert(*it);
+	}
+
+	// parse _created_items
+	parseUUIDArray(update,"_created_items",mItemsCreatedIds);
+
+	if (update.has("_embedded"))
+	{
+		const LLSD& embedded = update["_embedded"];
+		for(LLSD::map_const_iterator it = embedded.beginMap(),
+				end = embedded.endMap();
+				it != end; ++it)
+		{
+			const std::string& field = (*it).first;
+			
+			// parse created links
+			if (field == "link")
+			{
+				const LLSD& links = embedded["link"];
+				parseCreatedLinks(links);
+			}
+			else
+			{
+				llwarns << "unrecognized embedded field " << field << llendl;
+			}
+		}
+		
+	}
+
+	// Parse item update at the top level.
+	if (update.has("item_id"))
+	{
+		LLUUID item_id = update["item_id"].asUUID();
+		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+		BOOL rv = new_item->unpackMessage(update);
+		if (rv)
+		{
+			mItemsUpdated[item_id] = new_item;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			mCatDeltas[new_item->getParentUUID()];
+		}
+		else
+		{
+			llerrs << "unpack failed" << llendl;
+		}
+	}
+
+	// Parse updated category versions.
+	const std::string& ucv = "_updated_category_versions";
+	if (update.has(ucv))
+	{
+		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
+				end = update[ucv].endMap();
+			it != end; ++it)
+		{
+			const LLUUID id((*it).first);
+			S32 version = (*it).second.asInteger();
+			mCatVersions[id] = version;
+		}
+	}
+}
+
+void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids)
+{
+	ids.clear();
+	if (content.has(name))
+	{
+		for(LLSD::array_const_iterator it = content[name].beginArray(),
+				end = content[name].endArray();
+				it != end; ++it)
+		{
+			ids.push_back((*it).asUUID());
+		}
+	}
+}
+
+void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map)
+{
+	LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
+	BOOL rv = new_link->unpackMessage(link_map);
+	if (rv)
+	{
+		LLPermissions default_perms;
+		default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
+		default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
+		new_link->setPermissions(default_perms);
+		LLSaleInfo default_sale_info;
+		new_link->setSaleInfo(default_sale_info);
+		//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl;
+		mItemsCreated[link_id] = new_link;
+		const LLUUID& parent_id = new_link->getParentUUID();
+		mCatDeltas[parent_id]++;
+	}
+	else
+	{
+		llwarns << "failed to parse" << llendl;
+	}
+}
+
+void AISUpdate::parseCreatedLinks(const LLSD& links)
+{
+	for(LLSD::map_const_iterator linkit = links.beginMap(),
+			linkend = links.endMap();
+		linkit != linkend; ++linkit)
+	{
+		const LLUUID link_id((*linkit).first);
+		const LLSD& link_map = (*linkit).second;
+		uuid_vec_t::const_iterator pos =
+			std::find(mItemsCreatedIds.begin(),
+					  mItemsCreatedIds.end(),link_id);
+		if (pos != mItemsCreatedIds.end())
+		{
+			parseLink(link_id,link_map);
+		}
+		else
+		{
+			LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
+		}
+	}
+}
+
+void AISUpdate::doUpdate()
+{
+	// Do descendent/version accounting.
+	// Can remove this if/when we use the version info directly.
+	for (std::map<LLUUID,S32>::const_iterator catit = mCatDeltas.begin();
+		 catit != mCatDeltas.end(); ++catit)
+	{
+		const LLUUID cat_id(catit->first);
+		S32 delta = catit->second;
+		LLInventoryModel::LLCategoryUpdate up(cat_id, delta);
+		gInventory.accountForUpdate(up);
+	}
+	
+	// TODO - how can we use this version info? Need to be sure all
+	// changes are going through AIS first, or at least through
+	// something with a reliable responder.
+	for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin();
+		 ucv_it != mCatVersions.end(); ++ucv_it)
+	{
+		const LLUUID id = ucv_it->first;
+		S32 version = ucv_it->second;
+		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+		if (cat->getVersion() != version)
+		{
+			llwarns << "Possible version mismatch, viewer " << cat->getVersion()
+					<< " server " << version << llendl;
+		}
+	}
+
+	// CREATE ITEMS
+	for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin();
+		 create_it != mItemsCreated.end(); ++create_it)
+	{
+		LLUUID item_id(create_it->first);
+		LLPointer<LLViewerInventoryItem> new_item = create_it->second;
+
+		// FIXME risky function since it calls updateServer() in some
+		// cases.  Maybe break out the update/create cases, in which
+		// case this is create.
+		LL_DEBUGS("Inventory") << "created item " << item_id << llendl;
+		gInventory.updateItem(new_item);
+	}
+	
+	// UPDATE ITEMS
+	for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin();
+		 update_it != mItemsUpdated.end(); ++update_it)
+	{
+		LLUUID item_id(update_it->first);
+		LLPointer<LLViewerInventoryItem> new_item = update_it->second;
+		// FIXME risky function since it calls updateServer() in some
+		// cases.  Maybe break out the update/create cases, in which
+		// case this is update.
+		LL_DEBUGS("Inventory") << "updated item " << item_id << llendl;
+		gInventory.updateItem(new_item);
+	}
+
+	// DELETE OBJECTS
+	for (std::set<LLUUID>::const_iterator del_it = mObjectsDeleted.begin();
+		 del_it != mObjectsDeleted.end(); ++del_it)
+	{
+		LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
+		gInventory.onObjectDeletedFromServer(*del_it, false, false);
+	}
+}
+
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
new file mode 100755
index 0000000000..1f9555f004
--- /dev/null
+++ b/indra/newview/llaisapi.h
@@ -0,0 +1,143 @@
+/** 
+ * @file llaisapi.h
+ * @brief classes and functions for interfacing with the v3+ ais inventory service. 
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAISAPI_H
+#define LL_LLAISAPI_H
+
+#include "lluuid.h"
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include "llcurl.h"
+#include "llhttpclient.h"
+#include "llhttpretrypolicy.h"
+#include "llviewerinventory.h"
+
+class AISCommand: public LLHTTPClient::Responder
+{
+public:
+	typedef boost::function<void()> command_func_type;
+
+	AISCommand(LLPointer<LLInventoryCallback> callback);
+
+	virtual ~AISCommand() {}
+
+	void run_command();
+
+	void setCommandFunc(command_func_type command_func);
+	
+	// Need to do command-specific parsing to get an id here, for
+	// LLInventoryCallback::fire().  May or may not need to bother,
+	// since most LLInventoryCallbacks do their work in the
+	// destructor.
+	virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
+	
+	/* virtual */ void httpSuccess();
+
+	/*virtual*/ void httpFailure();
+
+	static bool getCap(std::string& cap);
+
+private:
+	command_func_type mCommandFunc;
+	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
+	LLPointer<LLInventoryCallback> mCallback;
+};
+
+class RemoveItemCommand: public AISCommand
+{
+public:
+	RemoveItemCommand(const LLUUID& item_id,
+					  LLPointer<LLInventoryCallback> callback);
+};
+
+class RemoveCategoryCommand: public AISCommand
+{
+public:
+	RemoveCategoryCommand(const LLUUID& item_id,
+						  LLPointer<LLInventoryCallback> callback);
+};
+
+class PurgeDescendentsCommand: public AISCommand
+{
+public:
+	PurgeDescendentsCommand(const LLUUID& item_id,
+							LLPointer<LLInventoryCallback> callback);
+};
+
+class UpdateItemCommand: public AISCommand
+{
+public:
+	UpdateItemCommand(const LLUUID& item_id,
+					  const LLSD& updates,
+					  LLPointer<LLInventoryCallback> callback);
+private:
+	LLSD mUpdates;
+};
+
+class UpdateCategoryCommand: public AISCommand
+{
+public:
+	UpdateCategoryCommand(const LLUUID& item_id,
+						  const LLSD& updates,
+						  LLPointer<LLInventoryCallback> callback);
+private:
+	LLSD mUpdates;
+};
+
+class SlamFolderCommand: public AISCommand
+{
+public:
+	SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback);
+	
+private:
+	LLSD mContents;
+};
+
+class AISUpdate
+{
+public:
+	AISUpdate(const LLSD& update);
+	void parseUpdate(const LLSD& update);
+	void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids);
+	void parseLink(const LLUUID& link_id, const LLSD& link_map);
+	void parseCreatedLinks(const LLSD& links);
+	void doUpdate();
+private:
+	typedef std::map<LLUUID,S32> uuid_int_map_t;
+	uuid_int_map_t mCatDeltas;
+	uuid_int_map_t mCatVersions;
+
+	typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
+	deferred_item_map_t mItemsCreated;
+	deferred_item_map_t mItemsUpdated;
+
+	std::set<LLUUID> mObjectsDeleted;
+	uuid_vec_t mItemsCreatedIds;
+};
+
+#endif
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 3c7539a7f9..6dc193292e 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 #include "llinventorymodel.h"
 
+#include "llaisapi.h"
 #include "llagent.h"
 #include "llagentwearables.h"
 #include "llappearancemgr.h"
@@ -1154,253 +1155,6 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
 	notifyObservers();
 }
 
-class AISUpdate
-{
-public:
-	AISUpdate(const LLSD& update);
-	void parseUpdate(const LLSD& update);
-	void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids);
-	void parseLink(const LLUUID& link_id, const LLSD& link_map);
-	void parseCreatedLinks(const LLSD& links);
-	void doUpdate();
-private:
-	typedef std::map<LLUUID,S32> uuid_int_map_t;
-	uuid_int_map_t mCatDeltas;
-	uuid_int_map_t mCatVersions;
-
-	typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
-	deferred_item_map_t mItemsCreated;
-	deferred_item_map_t mItemsUpdated;
-
-	std::set<LLUUID> mObjectsDeleted;
-	uuid_vec_t mItemsCreatedIds;
-};
-
-AISUpdate::AISUpdate(const LLSD& update)
-{
-	parseUpdate(update);
-}
-
-void AISUpdate::parseUpdate(const LLSD& update)
-{
-	// parse _categories_removed -> mObjectsDeleted
-	uuid_vec_t cat_ids;
-	parseUUIDArray(update,"_categories_removed",cat_ids);
-	for (uuid_vec_t::const_iterator it = cat_ids.begin();
-		 it != cat_ids.end(); ++it)
-	{
-		LLViewerInventoryCategory *cat = gInventory.getCategory(*it);
-		mCatDeltas[cat->getParentUUID()]--;
-		mObjectsDeleted.insert(*it);
-	}
-
-	// parse _categories_items_removed -> mObjectsDeleted
-	uuid_vec_t item_ids;
-	parseUUIDArray(update,"_category_items_removed",item_ids);
-	for (uuid_vec_t::const_iterator it = item_ids.begin();
-		 it != item_ids.end(); ++it)
-	{
-		LLViewerInventoryItem *item = gInventory.getItem(*it);
-		mCatDeltas[item->getParentUUID()]--;
-		mObjectsDeleted.insert(*it);
-	}
-
-	// parse _broken_links_removed -> mObjectsDeleted
-	uuid_vec_t broken_link_ids;
-	parseUUIDArray(update,"_broken_links_removed",broken_link_ids);
-	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
-		 it != broken_link_ids.end(); ++it)
-	{
-		LLViewerInventoryItem *item = gInventory.getItem(*it);
-		mCatDeltas[item->getParentUUID()]--;
-		mObjectsDeleted.insert(*it);
-	}
-
-	// parse _created_items
-	parseUUIDArray(update,"_created_items",mItemsCreatedIds);
-
-	if (update.has("_embedded"))
-	{
-		const LLSD& embedded = update["_embedded"];
-		for(LLSD::map_const_iterator it = embedded.beginMap(),
-				end = embedded.endMap();
-				it != end; ++it)
-		{
-			const std::string& field = (*it).first;
-			
-			// parse created links
-			if (field == "link")
-			{
-				const LLSD& links = embedded["link"];
-				parseCreatedLinks(links);
-			}
-			else
-			{
-				llwarns << "unrecognized embedded field " << field << llendl;
-			}
-		}
-		
-	}
-
-	// Parse item update at the top level.
-	if (update.has("item_id"))
-	{
-		LLUUID item_id = update["item_id"].asUUID();
-		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
-		BOOL rv = new_item->unpackMessage(update);
-		if (rv)
-		{
-			mItemsUpdated[item_id] = new_item;
-			// This statement is here to cause a new entry with 0
-			// delta to be created if it does not already exist;
-			// otherwise has no effect.
-			mCatDeltas[new_item->getParentUUID()];
-		}
-		else
-		{
-			llerrs << "unpack failed" << llendl;
-		}
-	}
-
-	// Parse updated category versions.
-	const std::string& ucv = "_updated_category_versions";
-	if (update.has(ucv))
-	{
-		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
-				end = update[ucv].endMap();
-			it != end; ++it)
-		{
-			const LLUUID id((*it).first);
-			S32 version = (*it).second.asInteger();
-			mCatVersions[id] = version;
-		}
-	}
-}
-
-void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids)
-{
-	ids.clear();
-	if (content.has(name))
-	{
-		for(LLSD::array_const_iterator it = content[name].beginArray(),
-				end = content[name].endArray();
-				it != end; ++it)
-		{
-			ids.push_back((*it).asUUID());
-		}
-	}
-}
-
-void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map)
-{
-	LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
-	BOOL rv = new_link->unpackMessage(link_map);
-	if (rv)
-	{
-		LLPermissions default_perms;
-		default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
-		default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
-		new_link->setPermissions(default_perms);
-		LLSaleInfo default_sale_info;
-		new_link->setSaleInfo(default_sale_info);
-		//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl;
-		mItemsCreated[link_id] = new_link;
-		const LLUUID& parent_id = new_link->getParentUUID();
-		mCatDeltas[parent_id]++;
-	}
-	else
-	{
-		llwarns << "failed to parse" << llendl;
-	}
-}
-
-void AISUpdate::parseCreatedLinks(const LLSD& links)
-{
-	for(LLSD::map_const_iterator linkit = links.beginMap(),
-			linkend = links.endMap();
-		linkit != linkend; ++linkit)
-	{
-		const LLUUID link_id((*linkit).first);
-		const LLSD& link_map = (*linkit).second;
-		uuid_vec_t::const_iterator pos =
-			std::find(mItemsCreatedIds.begin(),
-					  mItemsCreatedIds.end(),link_id);
-		if (pos != mItemsCreatedIds.end())
-		{
-			parseLink(link_id,link_map);
-		}
-		else
-		{
-			LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
-		}
-	}
-}
-
-void AISUpdate::doUpdate()
-{
-	// Do descendent/version accounting.
-	// Can remove this if/when we use the version info directly.
-	for (std::map<LLUUID,S32>::const_iterator catit = mCatDeltas.begin();
-		 catit != mCatDeltas.end(); ++catit)
-	{
-		const LLUUID cat_id(catit->first);
-		S32 delta = catit->second;
-		LLInventoryModel::LLCategoryUpdate up(cat_id, delta);
-		gInventory.accountForUpdate(up);
-	}
-	
-	// TODO - how can we use this version info? Need to be sure all
-	// changes are going through AIS first, or at least through
-	// something with a reliable responder.
-	for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin();
-		 ucv_it != mCatVersions.end(); ++ucv_it)
-	{
-		const LLUUID id = ucv_it->first;
-		S32 version = ucv_it->second;
-		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
-		if (cat->getVersion() != version)
-		{
-			llwarns << "Possible version mismatch, viewer " << cat->getVersion()
-					<< " server " << version << llendl;
-		}
-	}
-
-	// CREATE ITEMS
-	for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin();
-		 create_it != mItemsCreated.end(); ++create_it)
-	{
-		LLUUID item_id(create_it->first);
-		LLPointer<LLViewerInventoryItem> new_item = create_it->second;
-
-		// FIXME risky function since it calls updateServer() in some
-		// cases.  Maybe break out the update/create cases, in which
-		// case this is create.
-		LL_DEBUGS("Inventory") << "created item " << item_id << llendl;
-		gInventory.updateItem(new_item);
-	}
-	
-	// UPDATE ITEMS
-	for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin();
-		 update_it != mItemsUpdated.end(); ++update_it)
-	{
-		LLUUID item_id(update_it->first);
-		LLPointer<LLViewerInventoryItem> new_item = update_it->second;
-		// FIXME risky function since it calls updateServer() in some
-		// cases.  Maybe break out the update/create cases, in which
-		// case this is update.
-		LL_DEBUGS("Inventory") << "updated item " << item_id << llendl;
-		gInventory.updateItem(new_item);
-	}
-
-	// DELETE OBJECTS
-	for (std::set<LLUUID>::const_iterator del_it = mObjectsDeleted.begin();
-		 del_it != mObjectsDeleted.end(); ++del_it)
-	{
-		LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
-		gInventory.onObjectDeletedFromServer(*del_it, false, false);
-	}
-}
-
 void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
 {
 	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 0608c46051..57d7d4fef6 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -31,6 +31,7 @@
 #include "llsdserialize.h"
 #include "message.h"
 
+#include "llaisapi.h"
 #include "llagent.h"
 #include "llagentcamera.h"
 #include "llagentwearables.h"
@@ -258,6 +259,7 @@ public:
 };
 LLInventoryHandler gInventoryHandler;
 
+#if 0 // DELETE these when working in their new home
 
 ///----------------------------------------------------------------------------
 /// Classes for AISv3 support.
@@ -520,6 +522,7 @@ public:
 private:
 	LLSD mContents;
 };
+#endif
 
 ///----------------------------------------------------------------------------
 /// Class LLViewerInventoryItem
-- 
cgit v1.2.3


From d93ec94751e1c8c9a190b327720f432f9d9928c1 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 7 Jun 2013 14:43:18 -0500
Subject: sh-4109: Update agent appearance after attaching a rigged mesh

---
 indra/newview/llvovolume.cpp | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 8730ef66bb..b7f7a11a15 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -76,6 +76,7 @@
 #include "llviewershadermgr.h"
 #include "llvoavatar.h"
 #include "llvocache.h"
+#include "llappearancemgr.h"
 
 const S32 MIN_QUIET_FRAMES_COALESCE = 30;
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
@@ -4239,6 +4240,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	{
 		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST);
 
+		bool requiredAppearanceUpdate = false;
+
 		//get all the faces into a list
 		for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
 		{
@@ -4337,6 +4340,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								const int jointCnt = pSkinData->mJointNames.size();
 								const F32 pelvisZOffset = pSkinData->mPelvisOffset;
 								bool fullRig = (jointCnt>=20) ? true : false;
+								requiredAppearanceUpdate = true;
 								if ( fullRig )
 								{
 									for ( int i=0; i<jointCnt; ++i )
@@ -4361,12 +4365,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 													pelvisGotSet = true;											
 												}										
 											}										
-										}
+										}									
 									}
 								}							
 							}
 						}
-					}
+					}					
+					
+
 					//If we've set the pelvis to a new position we need to also rebuild some information that the
 					//viewer does at launch (e.g. body size etc.)
 					if ( pelvisGotSet )
@@ -4606,6 +4612,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 				drawablep->clearState(LLDrawable::RIGGED);
 			}
 		}
+
+		if ( requiredAppearanceUpdate && gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion() ) 
+		{ 
+			LLAppearanceMgr::instance().requestServerAppearanceUpdate();
+		}
 	}
 
 	group->mBufferUsage = useage;
-- 
cgit v1.2.3


From b3d3eee3b8af2c24822cceb99086635841469974 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 7 Jun 2013 17:25:43 -0500
Subject: Removed some debug tracking

---
 indra/llui/llfloater.cpp | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 93eca8b62e..f8b01e106b 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -716,22 +716,17 @@ void LLFloater::closeFloater(bool app_quitting)
 	if (!app_quitting)
 	{
 		if ( mVerifyUponClose && !mForceCloseAfterVerify )
-		{
-
-			llinfos<<"prep#dogshit1"<<llendl;
+		{			
 			onClose( app_quitting );
 			if ( mForceCloseAfterVerify ) 
-			{			
-
-				llinfos<<"prep#dogshit1b"<<llendl;
+			{
 				return;
 			}			
 		}
 	}	
 
 	if (app_quitting)
-	{	
-		llinfos<<"prep#dogshit2"<<llendl;
+	{		
 		LLFloater::sQuitting = true;
 	}
 	
-- 
cgit v1.2.3


From 6d46132ef5218cd17d8d201f16e5a7df4b1e39a6 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 10 Jun 2013 16:29:10 -0400
Subject: SH-4216 WIP - finished item/cat update and reorg of aisv3 code

---
 indra/llinventory/llinventory.cpp   |  11 +-
 indra/llinventory/llinventory.h     |   2 +-
 indra/newview/llaisapi.cpp          |   1 +
 indra/newview/llviewerinventory.cpp | 351 +++---------------------------------
 indra/newview/llviewerinventory.h   |   9 +-
 5 files changed, 38 insertions(+), 336 deletions(-)

diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 77b837f8ac..6336d02f22 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -1049,11 +1049,16 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
 
 LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
 
-bool LLInventoryItem::fromLLSD(const LLSD& sd)
+bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
 {
 	LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE);
-	mInventoryType = LLInventoryType::IT_NONE;
-	mAssetUUID.setNull();
+	if (is_new)
+	{
+		// If we're adding LLSD to an existing object, need avoid
+		// clobbering these fields.
+		mInventoryType = LLInventoryType::IT_NONE;
+		mAssetUUID.setNull();
+	}
 	std::string w;
 
 	w = INV_ITEM_ID_LABEL;
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index cc474f3d4c..b718f0f9b7 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -210,7 +210,7 @@ public:
 	void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size);
 	LLSD asLLSD() const;
 	void asLLSD( LLSD& sd ) const;
-	bool fromLLSD(const LLSD& sd);
+	bool fromLLSD(const LLSD& sd, bool is_new = true);
 
 	//--------------------------------------------------------------------
 	// Member Variables
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 6adf35efb8..393e5c0a68 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -202,6 +202,7 @@ UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
 	}
 	std::string url = cap + std::string("/item/") + item_id.asString();
 	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << llendl;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
 	headers["Content-Type"] = "application/llsd+xml";
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 57d7d4fef6..55575764b9 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -259,271 +259,6 @@ public:
 };
 LLInventoryHandler gInventoryHandler;
 
-#if 0 // DELETE these when working in their new home
-
-///----------------------------------------------------------------------------
-/// Classes for AISv3 support.
-///----------------------------------------------------------------------------
-class AISCommand: public LLHTTPClient::Responder
-{
-public:
-	typedef boost::function<void()> command_func_type;
-
-	AISCommand(LLPointer<LLInventoryCallback> callback):
-		mCallback(callback)
-	{
-		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
-	}
-
-	virtual ~AISCommand()
-	{
-	}
-
-	void run_command()
-	{
-		mCommandFunc();
-	}
-
-	void setCommandFunc(command_func_type command_func)
-	{
-		mCommandFunc = command_func;
-	}
-	
-	// Need to do command-specific parsing to get an id here.  May or
-	// may not need to bother, since most LLInventoryCallbacks do
-	// their work in the destructor.
-	virtual bool getResponseUUID(const LLSD& content, LLUUID& id)
-	{
-		return false;
-	}
-	
-	/* virtual */ void httpSuccess()
-	{
-		// Command func holds a reference to self, need to release it
-		// after a success or final failure.
-		setCommandFunc(no_op);
-		
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		mRetryPolicy->onSuccess();
-		
-		gInventory.onAISUpdateReceived("AISCommand", content);
-
-		if (mCallback)
-		{
-			LLUUID item_id; // will default to null if parse fails.
-			getResponseUUID(content,item_id);
-			mCallback->fire(item_id);
-		}
-	}
-
-	/*virtual*/ void httpFailure()
-	{
-		const LLSD& content = getContent();
-		S32 status = getStatus();
-		const std::string& reason = getReason();
-		const LLSD& headers = getResponseHeaders();
-		if (!content.isMap())
-		{
-			LL_DEBUGS("Inventory") << "Malformed response contents " << content
-								   << " status " << status << " reason " << reason << llendl;
-		}
-		else
-		{
-			LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
-								   << " status " << status << " reason " << reason << llendl;
-		}
-		mRetryPolicy->onFailure(status, headers);
-		F32 seconds_to_wait;
-		if (mRetryPolicy->shouldRetry(seconds_to_wait))
-		{
-			doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
-		}
-		else
-		{
-			// Command func holds a reference to self, need to release it
-			// after a success or final failure.
-			setCommandFunc(no_op);
-		}
-	}
-
-	static bool getCap(std::string& cap)
-	{
-		if (gAgent.getRegion())
-		{
-			cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
-		}
-		if (!cap.empty())
-		{
-			return true;
-		}
-		return false;
-	}
-
-private:
-	command_func_type mCommandFunc;
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-	LLPointer<LLInventoryCallback> mCallback;
-};
-
-class RemoveItemCommand: public AISCommand
-{
-public:
-	RemoveItemCommand(const LLUUID& item_id,
-					  LLPointer<LLInventoryCallback> callback):
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
-		{
-			llwarns << "No cap found" << llendl;
-			return;
-		}
-		std::string url = cap + std::string("/item/") + item_id.asString();
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLHTTPClient::ResponderPtr responder = this;
-		LLSD headers;
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-};
-
-class RemoveCategoryCommand: public AISCommand
-{
-public:
-	RemoveCategoryCommand(const LLUUID& item_id,
-						  LLPointer<LLInventoryCallback> callback):
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
-		{
-			llwarns << "No cap found" << llendl;
-			return;
-		}
-		std::string url = cap + std::string("/category/") + item_id.asString();
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLHTTPClient::ResponderPtr responder = this;
-		LLSD headers;
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-};
-
-class PurgeDescendentsCommand: public AISCommand
-{
-public:
-	PurgeDescendentsCommand(const LLUUID& item_id,
-							LLPointer<LLInventoryCallback> callback):
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
-		{
-			llwarns << "No cap found" << llendl;
-			return;
-		}
-		std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLCurl::ResponderPtr responder = this;
-		LLSD headers;
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-};
-
-class UpdateItemCommand: public AISCommand
-{
-public:
-	UpdateItemCommand(const LLUUID& item_id,
-					  const LLSD& updates,
-					  LLPointer<LLInventoryCallback> callback):
-		mUpdates(updates),
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
-		{
-			llwarns << "No cap found" << llendl;
-			return;
-		}
-		std::string url = cap + std::string("/item/") + item_id.asString();
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLCurl::ResponderPtr responder = this;
-		LLSD headers;
-		headers["Content-Type"] = "application/llsd+xml";
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-private:
-	LLSD mUpdates;
-};
-
-class UpdateCategoryCommand: public AISCommand
-{
-public:
-	UpdateCategoryCommand(const LLUUID& item_id,
-						  const LLSD& updates,
-						  LLPointer<LLInventoryCallback> callback):
-		mUpdates(updates),
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
-		{
-			llwarns << "No cap found" << llendl;
-			return;
-		}
-		std::string url = cap + std::string("/category/") + item_id.asString();
-		LL_DEBUGS("Inventory") << "url: " << url << llendl;
-		LLCurl::ResponderPtr responder = this;
-		LLSD headers;
-		headers["Content-Type"] = "application/llsd+xml";
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-private:
-	LLSD mUpdates;
-};
-
-class SlamFolderCommand: public AISCommand
-{
-public:
-	SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
-		mContents(contents),
-		AISCommand(callback)
-	{
-		std::string cap;
-		if (!getCap(cap))
-		{
-			llwarns << "No cap found" << llendl;
-			return;
-		}
-		LLUUID tid;
-		tid.generate();
-		std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
-		llinfos << url << llendl;
-		LLCurl::ResponderPtr responder = this;
-		LLSD headers;
-		headers["Content-Type"] = "application/llsd+xml";
-		F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout);
-		setCommandFunc(cmd);
-	}
-private:
-	LLSD mContents;
-};
-#endif
-
 ///----------------------------------------------------------------------------
 /// Class LLViewerInventoryItem
 ///----------------------------------------------------------------------------
@@ -718,23 +453,9 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_
 {
 	mTransactionID = transaction_id;
 }
-// virtual
-void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
-{
-	static const LLSD updates;
-	packUpdateMessage(msg,updates);
-}
 
-void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const
+void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
 {
-	for (LLSD::map_const_iterator it = updates.beginMap(); it != updates.endMap(); ++it)
-	{
-		if ((it->first != "desc") && (it->first != "name"))
-		{
-			llerrs << "unhandled field: " << it->first << llendl;
-		}
-	}
-	
 	msg->addUUIDFast(_PREHASH_ItemID, mUUID);
 	msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
 	mPermissions.packMessage(msg);
@@ -745,26 +466,8 @@ void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD&
 	msg->addS8Fast(_PREHASH_InvType, type);
 	msg->addU32Fast(_PREHASH_Flags, mFlags);
 	mSaleInfo.packMessage(msg);
-	if (updates.has("name"))
-	{
-		std::string new_name = updates["name"].asString();
-		LLInventoryObject::correctInventoryName(new_name);
-		msg->addStringFast(_PREHASH_Name, new_name);
-	}
-	else
-	{
-		msg->addStringFast(_PREHASH_Name, mName);
-	}
-	if (updates.has("desc"))
-	{
-		std::string new_desc = updates["desc"].asString();
-		LLInventoryItem::correctInventoryDescription(new_desc);
-		msg->addStringFast(_PREHASH_Description, new_desc);
-	}
-	else
-	{
-		msg->addStringFast(_PREHASH_Description, mDescription);
-	}
+	msg->addStringFast(_PREHASH_Name, mName);
+	msg->addStringFast(_PREHASH_Description, mDescription);
 	msg->addS32Fast(_PREHASH_CreationDate, mCreationDate);
 	U32 crc = getCRC32();
 	msg->addU32Fast(_PREHASH_CRC, crc);
@@ -881,30 +584,13 @@ void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCatego
 }
 
 
-void LLViewerInventoryCategory::packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const
+void LLViewerInventoryCategory::packMessage(LLMessageSystem* msg) const
 {
-	for (LLSD::map_const_iterator it = updates.beginMap(); it != updates.endMap(); ++it)
-	{
-		if (it->first != "name")
-		{
-			llerrs << "unhandled field: " << it->first << llendl;
-		}
-	}
-	
 	msg->addUUIDFast(_PREHASH_FolderID, mUUID);
 	msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
 	S8 type = static_cast<S8>(mPreferredType);
 	msg->addS8Fast(_PREHASH_Type, type);
-	if (updates.has("name"))
-	{
-		std::string new_name = updates["name"].asString();
-		LLInventoryObject::correctInventoryName(new_name);
-		msg->addStringFast(_PREHASH_Name, new_name);
-	}
-	else
-	{
-		msg->addStringFast(_PREHASH_Name, mName);
-	}
+	msg->addStringFast(_PREHASH_Name, mName);
 }
 
 void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
@@ -1475,10 +1161,16 @@ void update_inventory_item(
 	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
 	if(obj)
 	{
+		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+		new_item->copyViewerItem(obj);	
+		new_item->fromLLSD(updates,false);
+		
 		std::string cap;
 		if (AISCommand::getCap(cap))
 		{
-			LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
+			LLSD new_llsd;
+			new_item->asLLSD(new_llsd);
+			LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, new_llsd, cb);
 			cmd_ptr->run_command();
 		}
 		else // no cap
@@ -1488,13 +1180,15 @@ void update_inventory_item(
 			msg->nextBlockFast(_PREHASH_AgentData);
 			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-			msg->addUUIDFast(_PREHASH_TransactionID, obj->getTransactionID());
+			msg->addUUIDFast(_PREHASH_TransactionID, new_item->getTransactionID());
 			msg->nextBlockFast(_PREHASH_InventoryData);
 			msg->addU32Fast(_PREHASH_CallbackID, 0);
-			obj->packUpdateMessage(msg, updates);
+			new_item->packMessage(msg);
 			gAgent.sendReliableMessage();
 
-			gInventory.onItemUpdated(item_id, updates,true);
+			LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateItem(new_item);
 			if (cb)
 			{
 				cb->fire(item_id);
@@ -1518,11 +1212,14 @@ void update_inventory_category(
 			return;
 		}
 
+		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
+		new_cat->fromLLSD(updates);
 		//std::string cap;
 		// FIXME - restore this once the back-end work has been done.
 		if (0) // if (AISCommand::getCap(cap))
 		{
-			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, updates, cb);
+			LLSD new_llsd = new_cat->asLLSD();
+			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
 			cmd_ptr->run_command();
 		}
 		else // no cap
@@ -1533,10 +1230,12 @@ void update_inventory_category(
 			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 			msg->nextBlockFast(_PREHASH_FolderData);
-			obj->packUpdateMessage(msg, updates);
+			new_cat->packMessage(msg);
 			gAgent.sendReliableMessage();
 
-			gInventory.onCategoryUpdated(cat_id, updates);
+			LLInventoryModel::LLCategoryUpdate up(new_cat->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateCategory(new_cat);
 			if (cb)
 			{
 				cb->fire(cat_id);
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 9af71dfc9c..032efd9542 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -122,7 +122,7 @@ public:
 	virtual void updateServer(BOOL is_new) const;
 	void fetchFromServer(void) const;
 
-	//virtual void packMessage(LLMessageSystem* msg) const;
+	virtual void packMessage(LLMessageSystem* msg) const;
 	virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
 	virtual BOOL unpackMessage(LLSD item);
 	virtual BOOL importFile(LLFILE* fp);
@@ -138,9 +138,6 @@ public:
 	void setComplete(BOOL complete) { mIsComplete = complete; }
 	//void updateAssetOnServer() const;
 
-	virtual void packMessage(LLMessageSystem* msg) const;
-	// Contents of updates will take precedence over fields of item where they differ.
-	void packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const;
 	virtual void setTransactionID(const LLTransactionID& transaction_id);
 	struct comparePointers
 	{
@@ -202,6 +199,8 @@ public:
 	virtual void updateParentOnServer(BOOL restamp_children) const;
 	virtual void updateServer(BOOL is_new) const;
 
+	virtual void packMessage(LLMessageSystem* msg) const;
+
 	const LLUUID& getOwnerID() const { return mOwnerID; }
 
 	// Version handling
@@ -226,8 +225,6 @@ public:
 	void determineFolderType();
 	void changeType(LLFolderType::EType new_folder_type);
 
-	void packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const;
-
 private:
 	friend class LLInventoryModel;
 	void localizeName(); // intended to be called from the LLInventoryModel
-- 
cgit v1.2.3


From 56cf4297f3c603b8c39880ee20ce0fd6fb3341e5 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 13 Jun 2013 16:07:02 -0400
Subject: SH-4250 WIP - logging tweaks and cleanup

---
 indra/newview/llappearancemgr.cpp |  4 +++-
 indra/newview/llfriendcard.cpp    |  2 +-
 indra/newview/llimview.cpp        | 16 ++++++++--------
 indra/newview/lltexturefetch.cpp  |  3 +--
 indra/newview/llviewertexture.cpp | 21 +++++++++++++++++++++
 indra/newview/llviewertexture.h   |  2 ++
 indra/newview/llvoavatar.cpp      | 10 ++++++++--
 7 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 2698e2db35..f5f6faf6b6 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2625,7 +2625,7 @@ void LLAppearanceMgr::updateIsDirty()
 
 		if(outfit_items.count() != cof_items.count())
 		{
-			LL_DEBUGS("Avatar") << "item count different" << llendl;
+			LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.count() << " cof " << cof_items.count() << llendl;
 			// Current outfit folder should have one more item than the outfit folder.
 			// this one item is the link back to the outfit folder itself.
 			mOutfitIsDirty = true;
@@ -2666,6 +2666,8 @@ void LLAppearanceMgr::updateIsDirty()
 			}
 		}
 	}
+	llassert(!mOutfitIsDirty);
+	LL_DEBUGS("Avatar") << "clean" << llendl;
 }
 
 // *HACK: Must match name in Library or agent inventory
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 5c6ce9d311..0ce0534802 100755
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -86,7 +86,7 @@ const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollect
 
 	if (cats_count > 1)
 	{
-		LL_WARNS("LLFriendCardsManager")
+		LL_WARNS_ONCE("LLFriendCardsManager")
 			<< "There is more than one Friend card folder."
 			<< "The first folder will be used."
 			<< LL_ENDL;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 9c0af79923..aed0414c50 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -899,7 +899,7 @@ void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& m
 	LLIMSession* session = findIMSession(session_id);
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return;
 	}
 
@@ -921,7 +921,7 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id)
 	LLIMSession* session = findIMSession(session_id);
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return;
 	}
 
@@ -941,7 +941,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
 
 	if (!session) 
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return false;
 	}
 
@@ -1016,7 +1016,7 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id,
 
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return NULL;
 	}
 
@@ -1053,7 +1053,7 @@ const std::string LLIMModel::getName(const LLUUID& session_id) const
 
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return LLTrans::getString("no_session_message");
 	}
 
@@ -1065,7 +1065,7 @@ const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const
 	LLIMSession* session = findIMSession(session_id);
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return -1;
 	}
 
@@ -1089,7 +1089,7 @@ EInstantMessage LLIMModel::getType(const LLUUID& session_id) const
 	LLIMSession* session = findIMSession(session_id);
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return IM_COUNT;
 	}
 
@@ -1101,7 +1101,7 @@ LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const
 	LLIMSession* session = findIMSession(session_id);
 	if (!session)
 	{
-		llwarns << "session " << session_id << "does not exist " << llendl;
+		llwarns << "session " << session_id << " does not exist " << llendl;
 		return NULL;
 	}
 
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index f7fbb19bdc..70e2c0f2dc 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1382,7 +1382,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			//recordTextureStart(false);
 			//setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 
-			LL_DEBUGS("Texture") << mID << " does this happen?" << llendl;
 			return false;
 		}
 	}
@@ -2656,7 +2655,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		worker->unlockWorkMutex();										// -Mw
 	}
 	
- 	LL_DEBUGS("Texture") << "REQUESTED: " << id << " Discard: " << desired_discard << " size " << desired_size << llendl;
+ 	LL_DEBUGS("Texture") << "REQUESTED: " << id << " f_type " << fttype_to_string(f_type) << " Discard: " << desired_discard << " size " << desired_size << llendl;
 	return true;
 }
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 45b402f0f6..4c9ca8b1d7 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -901,6 +901,27 @@ void LLViewerTexture::updateBindStatsForTester()
 //end of LLViewerTexture
 //----------------------------------------------------------------------------------------------
 
+const std::string& fttype_to_string(const FTType& fttype)
+{
+	static const std::string ftt_unknown("FTT_UNKNOWN");
+	static const std::string ftt_default("FTT_DEFAULT");
+	static const std::string ftt_server_bake("FTT_SERVER_BAKE");
+	static const std::string ftt_host_bake("FTT_HOST_BAKE");
+	static const std::string ftt_map_tile("FTT_MAP_TILE");
+	static const std::string ftt_local_file("FTT_LOCAL_FILE");
+	static const std::string ftt_error("FTT_ERROR");
+	switch(fttype)
+	{
+		case FTT_UNKNOWN: return ftt_unknown; break;
+		case FTT_DEFAULT: return ftt_default; break;
+		case FTT_SERVER_BAKE: return ftt_server_bake; break;
+		case FTT_HOST_BAKE: return ftt_host_bake; break;
+		case FTT_MAP_TILE: return ftt_map_tile; break;
+		case FTT_LOCAL_FILE: return ftt_local_file; break;
+	}
+	return ftt_error;
+}
+
 //----------------------------------------------------------------------------------------------
 //start of LLViewerFetchedTexture
 //----------------------------------------------------------------------------------------------
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index bf6aadd218..e99d52741d 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -243,6 +243,8 @@ enum FTType
 	FTT_LOCAL_FILE // fetch directly from a local file.
 };
 
+const std::string& fttype_to_string(const FTType& fttype);
+
 //
 //textures are managed in gTextureList.
 //raw image data is fetched from remote or local cache
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 4593541f35..46b909c4a1 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1881,7 +1881,7 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 		const std::string url = getImageURL(te,uuid);
 		if (!url.empty())
 		{
-			LL_DEBUGS("Avatar") << avString() << "from URL " << url << llendl;
+			LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << llendl;
 			result = LLViewerTextureManager::getFetchedTextureFromUrl(
 				url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
 			if (result->isMissingAsset())
@@ -1891,7 +1891,7 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 		}
 		else
 		{
-			LL_DEBUGS("Avatar") << avString() << "from host " << uuid << llendl;
+			LL_DEBUGS("Avatar") << avString() << "get old-bake image from host " << uuid << llendl;
 			LLHost host = getObjectHost();
 			result = LLViewerTextureManager::getFetchedTexture(
 				uuid, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
@@ -7093,9 +7093,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			&& mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT
 			&& baked_index != BAKED_SKIRT)
 		{
+			LL_DEBUGS("Avatar") << avString() << "sb " << (S32) isUsingServerBakes() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << llendl;
 			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, 
 				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
 		}
+		else
+		{
+			LL_DEBUGS("Avatar") << avString() << "sb " << (S32) isUsingServerBakes() << " baked_index " << (S32) baked_index << " using texture id "
+								<< getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << llendl;
+		}
 	}
 
 	// runway - was
-- 
cgit v1.2.3


From 8c35b1b58bad66bfb5302e598536c0262263cbcb Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Fri, 14 Jun 2013 12:34:45 -0500
Subject: WIP: sh-4035 backed out changes to appearance window confirmation

---
 indra/llui/llfloater.cpp                           |  47 +-----
 indra/llui/llfloater.h                             |   5 +-
 indra/llui/llpanel.cpp                             |  23 +--
 indra/llui/llpanel.h                               |  11 +-
 indra/newview/llfloatersidepanelcontainer.cpp      |  96 +++----------
 indra/newview/llfloatersidepanelcontainer.h        |  16 +--
 indra/newview/llsidepanelappearance.cpp            | 160 +--------------------
 indra/newview/llsidepanelappearance.h              |  24 +---
 .../newview/skins/default/xui/en/notifications.xml |  34 +----
 9 files changed, 39 insertions(+), 377 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index f8b01e106b..0807b497a7 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -704,29 +704,11 @@ void LLFloater::openFloater(const LLSD& key)
 	dirtyRect();
 }
 
-void LLFloater::verifyClose( bool app_quitting )
-{
-	LLPanel::handleCloseConfirmation( app_quitting );
-}
-
 void LLFloater::closeFloater(bool app_quitting)
 {
 	llinfos << "Closing floater " << getName() << llendl;
-	
-	if (!app_quitting)
-	{
-		if ( mVerifyUponClose && !mForceCloseAfterVerify )
-		{			
-			onClose( app_quitting );
-			if ( mForceCloseAfterVerify ) 
-			{
-				return;
-			}			
-		}
-	}	
-
 	if (app_quitting)
-	{		
+	{
 		LLFloater::sQuitting = true;
 	}
 	
@@ -799,7 +781,7 @@ void LLFloater::closeFloater(bool app_quitting)
 		dirtyRect();
 
 		// Close callbacks
-		onClose(app_quitting);	
+		onClose(app_quitting);
 		mCloseSignal(this, LLSD(app_quitting));
 		
 		// Hide or Destroy
@@ -1639,7 +1621,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
 
 
 // virtual
-void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
+void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
 {
 	LLMultiFloater* hostp = getHost();
 	if (hostp)
@@ -1806,19 +1788,11 @@ void LLFloater::initRectControl()
 void LLFloater::closeFrontmostFloater()
 {
 	LLFloater* floater_to_close = gFloaterView->getFrontmostClosableFloater();
-	if( floater_to_close )
+	if(floater_to_close)
 	{
-		if ( floater_to_close->mVerifyUponClose )
-		{			
-			floater_to_close->verifyClose();
-			//Closing of the window handle in the subclass - so bug out here.
-			return;
-		}
-		else
-		{
-			floater_to_close->closeFloater();
-		}
+		floater_to_close->closeFloater();
 	}
+
 	// if nothing took focus after closing focused floater
 	// give it to next floater (to allow closing multiple windows via keyboard in rapid succession)
 	if (gFocusMgr.getKeyboardFocus() == NULL)
@@ -2657,14 +2631,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
 		if (floaterp->canClose() && !floaterp->isDead() &&
 			(app_quitting || floaterp->getVisible()))
 		{
-			if ( floaterp->mVerifyUponClose )
-			{			
-				floaterp->verifyClose(app_quitting);
-			}
-			else
-			{
-				floaterp->closeFloater(app_quitting);
-			}
+			floaterp->closeFloater(app_quitting);
 		}
 	}
 }
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 8eb40ddd0b..1d0d3cb050 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -225,7 +225,6 @@ public:
 
 	// If allowed, close the floater cleanly, releasing focus.
 	virtual void	closeFloater(bool app_quitting = false);
-	virtual void	verifyClose( bool app_quitting = false );
 
 	// Close the floater or its host. Use when hidding or toggling a floater instance.
 	virtual void	closeHostedFloater();
@@ -304,9 +303,9 @@ public:
 
 	/*virtual*/ void setVisible(BOOL visible); // do not override
 	/*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
-				void handleCloseConfirmation( );
+	
 	void			setFrontmost(BOOL take_focus = TRUE);
-    virtual void	setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());    
+     virtual void	setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
 	
 	// Defaults to false.
 	virtual BOOL	canSaveAs() const { return FALSE; }
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index b0bdbcb7d1..67472ad166 100755
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -114,10 +114,7 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 	mCommitCallbackRegistrar(false),
 	mEnableCallbackRegistrar(false),
 	mXMLFilename(p.filename),
-	mVisibleSignal(NULL),
-	mCloseConfirmationSignal(NULL),
-	mVerifyUponClose(false),
-	mForceCloseAfterVerify(false)
+	mVisibleSignal(NULL)
 	// *NOTE: Be sure to also change LLPanel::initFromParams().  We have too
 	// many classes derived from LLPanel to retrofit them all to pass in params.
 {
@@ -130,7 +127,6 @@ LLPanel::LLPanel(const LLPanel::Params& p)
 LLPanel::~LLPanel()
 {
 	delete mVisibleSignal;
-	delete mCloseConfirmationSignal;
 }
 
 // virtual
@@ -353,14 +349,6 @@ void LLPanel::handleVisibilityChange ( BOOL new_visibility )
 		(*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass BOOL as LLSD
 }
 
-
-void LLPanel::handleCloseConfirmation( bool app_quitting)
-{	
-	if (mCloseConfirmationSignal)
-	{
-		(*mCloseConfirmationSignal)(this, LLSD( app_quitting ) ); 
-	}
-}
 void LLPanel::setFocus(BOOL b)
 {
 	if( b && !hasFocus())
@@ -971,17 +959,10 @@ boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::
 	{
 		mVisibleSignal = new commit_signal_t();
 	}
+
 	return mVisibleSignal->connect(cb);
 }
 
-boost::signals2::connection LLPanel::setCloseConfirmationCallback( const commit_signal_t::slot_type& cb )
-{
-	if (!mCloseConfirmationSignal)
-	{
-		mCloseConfirmationSignal = new commit_signal_t();
-	}	
-	return mCloseConfirmationSignal->connect(cb);
-}
 static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 02f8c0aba7..e63b41f97c 100755
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -116,8 +116,6 @@ public:
 	/*virtual*/ void	draw();	
 	/*virtual*/ BOOL	handleKeyHere( KEY key, MASK mask );
 	/*virtual*/ void 	handleVisibilityChange ( BOOL new_visibility );
-				void	handleCloseConfirmation( bool app_quitting );
-
 
 	// From LLFocusableElement
 	/*virtual*/ void	setFocus( BOOL b );
@@ -253,8 +251,6 @@ public:
 	std::string getXMLFilename() { return mXMLFilename; };
 	
 	boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
-	boost::signals2::connection setCloseConfirmationCallback( const commit_signal_t::slot_type& cb );
-
 
 protected:
 	// Override to set not found list
@@ -264,7 +260,6 @@ protected:
 	EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
 
 	commit_signal_t* mVisibleSignal;		// Called when visibility changes, passes new visibility as LLSD()
-	commit_signal_t* mCloseConfirmationSignal; 
 
 	std::string		mHelpTopic;         // the name of this panel's help topic to display in the Help Viewer
 	typedef std::deque<const LLCallbackMap::map_t*> factory_stack_t;
@@ -272,11 +267,7 @@ protected:
 
 	// for setting the xml filename when building panel in context dependent cases
 	std::string		mXMLFilename;
-	//Specific close-down logic in subclass
-	BOOL			mVerifyUponClose;
-public:	
-	BOOL			mForceCloseAfterVerify;
-
+	
 private:
 	BOOL			mBgVisible;				// any background at all?
 	BOOL			mBgOpaque;				// use opaque color or image
diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index 02216420da..5f9556a870 100755
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -40,29 +40,13 @@
 const std::string LLFloaterSidePanelContainer::sMainPanelName("main_panel");
 
 LLFloaterSidePanelContainer::LLFloaterSidePanelContainer(const LLSD& key, const Params& params)
-: LLFloater(key, params)
-, mAppQuiting( false )
+:	LLFloater(key, params)
 {
 	// Prevent transient floaters (e.g. IM windows) from hiding
 	// when this floater is clicked.
 	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this);
-	//We want this container to handle the shutdown logic of the sidepanelappearance.
-	mVerifyUponClose = TRUE;
 }
 
-BOOL LLFloaterSidePanelContainer::postBuild()
-{
-	setCloseConfirmationCallback( boost::bind(&LLFloaterSidePanelContainer::onConfirmationClose,this,_2));
-	return TRUE;
-}
-
-void  LLFloaterSidePanelContainer::onConfirmationClose( const LLSD &confirm )
-{
-	mAppQuiting = confirm.asBoolean();
-	onClickCloseBtn();
-}
-
-
 LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer()
 {
 	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::GLOBAL, this);
@@ -71,34 +55,26 @@ LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer()
 void LLFloaterSidePanelContainer::onOpen(const LLSD& key)
 {
 	getChild<LLPanel>(sMainPanelName)->onOpen(key);
-	mAppQuiting = false;
-}
-
-void LLFloaterSidePanelContainer::onClose( bool app_quitting )
-{
-	if (! mAppQuiting ) { mForceCloseAfterVerify = true; }
-	LLSidepanelAppearance* panel = getSidePanelAppearance();
-	if ( panel )
-	{		
-		panel->mRevertSet = true;
-		panel->onCloseFromAppearance( this );			
-	}
 }
 
 void LLFloaterSidePanelContainer::onClickCloseBtn()
 {
-	LLSidepanelAppearance* panel = getSidePanelAppearance();
-	if ( panel )
-	{
-		panel->onClose( this );			
-	}
-	else
+	LLPanelOutfitEdit* panel_outfit_edit =
+		dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
+	if (panel_outfit_edit)
 	{
-		LLFloater::onClickCloseBtn();
+		LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
+		if (parent == this )
+		{
+			LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
+			if ( panel_appearance )
+			{
+				panel_appearance->getWearable()->onClose();
+				panel_appearance->showOutfitsInventoryPanel();
+			}
+		}
 	}
-}
-void LLFloaterSidePanelContainer::close()
-{
+	
 	LLFloater::onClickCloseBtn();
 }
 
@@ -109,7 +85,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na
 
 	if (!getVisible())
 	{
-		openFloater();
+	openFloater();
 	}
 
 	LLPanel* panel = NULL;
@@ -130,30 +106,10 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na
 
 void LLFloaterSidePanelContainer::showPanel(const std::string& floater_name, const LLSD& key)
 {
-	//If we're already open then check whether anything is dirty	 
-	LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>(floater_name);	
+	LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>(floater_name);
 	if (floaterp)
 	{
-		if ( floaterp->getVisible() )
-		{
-			LLSidepanelAppearance* panel = floaterp->getSidePanelAppearance();
-			if ( panel )
-			{
-				if ( panel->checkForDirtyEdits() )
-				{
-					panel->onClickConfirmExitWithoutSaveIntoAppearance( floaterp );
-				}
-				else
-				{
-					//or a call into some new f() that just shows inv panel?
-					floaterp->openChildPanel(sMainPanelName, key);
-				}
-			}
-		}
-		else
-		{
-			floaterp->openChildPanel(sMainPanelName, key);
-		}
+		floaterp->openChildPanel(sMainPanelName, key);
 	}
 }
 
@@ -177,19 +133,3 @@ LLPanel* LLFloaterSidePanelContainer::getPanel(const std::string& floater_name,
 
 	return NULL;
 }
-
-LLSidepanelAppearance* LLFloaterSidePanelContainer::getSidePanelAppearance()
-{
-	LLSidepanelAppearance* panel_appearance = NULL;
-	LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
-	if (panel_outfit_edit)
-	{
-		LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
-		if (parent == this )
-		{
-			panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
-		}
-	}
-	return panel_appearance;			
-
-}
diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h
index b276821805..491723471f 100755
--- a/indra/newview/llfloatersidepanelcontainer.h
+++ b/indra/newview/llfloatersidepanelcontainer.h
@@ -30,8 +30,6 @@
 
 #include "llfloater.h"
 
-class LLSidepanelAppearance;
-
 /**
  * Class LLFloaterSidePanelContainer
  *
@@ -44,8 +42,6 @@ class LLSidepanelAppearance;
  */
 class LLFloaterSidePanelContainer : public LLFloater
 {
-	friend class LLSidePanelAppearance;
-
 private:
 	static const std::string sMainPanelName;
 
@@ -54,15 +50,11 @@ public:
 	~LLFloaterSidePanelContainer();
 
 	/*virtual*/ void onOpen(const LLSD& key);
-	/*virtual*/ void onClose(bool app_quitting);
+
 	/*virtual*/ void onClickCloseBtn();
-	/*virtual*/ BOOL postBuild();
-				void  onConfirmationClose( const LLSD &confirm );
 
 	LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params);
 
-	void close();
-
 	static void showPanel(const std::string& floater_name, const LLSD& key);
 
 	static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key);
@@ -86,12 +78,6 @@ public:
 		}
 		return panel;
 	}
-
-private:
-	LLSidepanelAppearance* getSidePanelAppearance();
-
-public: 
-	bool mAppQuiting;
 };
 
 #endif // LL_LLFLOATERSIDEPANELCONTAINER_H
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 775c148ea1..d25d203feb 100755
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -48,9 +48,6 @@
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
 #include "llviewerwearable.h"
-#include "llnotificationsutil.h"
-#include "llfloatersidepanelcontainer.h"
-#include "llviewerfoldertype.h"
 
 static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance");
 
@@ -73,139 +70,13 @@ private:
 	LLSidepanelAppearance *mPanel;
 };
 
-bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if ( option == 0 ) 
-	{		
-		LLAppearanceMgr::instance().setOutfitDirty( true );		
-		showOutfitsInventoryPanel();
-		LLAppearanceMgr::getInstance()->wearBaseOutfit();		
-		return true;
-	}
-	return false;
-}
-
-void LLSidepanelAppearance::onCloseFromAppearance(LLFloaterSidePanelContainer* obj)
-{
-	mLLFloaterSidePanelContainer = obj;	
-	if ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) 
-	{
-		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
-		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
-	}
-	else
-	{		
-		LLVOAvatarSelf::onCustomizeEnd(FALSE);		
-		toggleWearableEditPanel(FALSE);
-		mLLFloaterSidePanelContainer->mForceCloseAfterVerify=false;
-	}
-}
-bool LLSidepanelAppearance::onSaveCommit(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option)
-	{
-		std::string outfit_name = response["message"].asString();
-		LLStringUtil::trim(outfit_name);
-		std::string current_outfit_name;
-
-		LLAppearanceMgr::getInstance()->getBaseOutfitName(current_outfit_name);
-
-		if ( current_outfit_name == outfit_name )
-		{
-			LLAppearanceMgr::getInstance()->updateBaseOutfit();
-		}
-		else		
-		{
-			LLUUID outfit_folder = LLAppearanceMgr::getInstance()->makeNewOutfitLinks( outfit_name,FALSE );		
-		}		
-
-		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
-		mLLFloaterSidePanelContainer->close();		
-	}
-
-	return false;
-}
-bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response)
-{	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if ( option == 0 ) 
-	{	
-		std::string outfit_name;
-		if (!LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name))
-		{
-			outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT);
-		}
-
-		LLSD args;
-		args["DESC"] = outfit_name;
-
-		LLSD payload;
-		LLNotificationsUtil::add("SaveOutfitEither", args, payload, boost::bind(&LLSidepanelAppearance::onSaveCommit, this, _1, _2));
-		showOutfitEditPanel();
-		return false;
-	}
-	else if ( option == 1 )
-	{
-		mEditWearable->revertChanges();					
-		toggleWearableEditPanel(FALSE);	
-		showOutfitEditPanel();
-		LLVOAvatarSelf::onCustomizeEnd( FALSE );	
-		if ( !mLLFloaterSidePanelContainer->mAppQuiting ) 
-		{
-			mRevertSet = true; 			
-		}
-		else
-		{
-			mLLFloaterSidePanelContainer->closeFloater( true );
-		}
-		return false;
-	}
-	mLLFloaterSidePanelContainer->mForceCloseAfterVerify = false;
-	return false;
-}
-
-void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance( LLFloaterSidePanelContainer* obj )
-{
-	mLLFloaterSidePanelContainer = obj;	
-	if ( LLAppearanceMgr::getInstance()->isOutfitDirty() ||  mEditWearable->isDirty() )
-	{
-		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
-		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
-	}
-	else
-	{
-		showOutfitsInventoryPanel();
-	}
-}
-void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack()
-{
-	showOutfitsInventoryPanel();
-}
-
-void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj)
-{	mLLFloaterSidePanelContainer = obj;	
-	if ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) 
-	{
-		LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this;
-		LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) );
-	}
-	else
-	{				
-		LLVOAvatarSelf::onCustomizeEnd(FALSE);		
-		mLLFloaterSidePanelContainer->close();
-	}
-}
-
 LLSidepanelAppearance::LLSidepanelAppearance() :
 	LLPanel(),
 	mFilterSubString(LLStringUtil::null),
 	mFilterEditor(NULL),
 	mOutfitEdit(NULL),
 	mCurrOutfitPanel(NULL),
-	mOpened(false),
-	mSidePanelJustOpened(true),
-	mRevertSet(false)
+	mOpened(false)
 {
 	LLOutfitObserver& outfit_observer =  LLOutfitObserver::instance();
 	outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
@@ -214,8 +85,6 @@ LLSidepanelAppearance::LLSidepanelAppearance() :
 
 	gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true));
 	gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false));
-
-
 }
 
 LLSidepanelAppearance::~LLSidepanelAppearance()
@@ -250,8 +119,8 @@ BOOL LLSidepanelAppearance::postBuild()
 	{
 		LLButton* back_btn = mOutfitEdit->getChild<LLButton>("back_btn");
 		if (back_btn)
-		{			
-			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack, this));
+		{
+			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this));
 		}
 
 	}
@@ -275,7 +144,6 @@ BOOL LLSidepanelAppearance::postBuild()
 
 	setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2));
 
-
 	return TRUE;
 }
 
@@ -286,15 +154,11 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 	{
 		// No specific panel requested.
 		// If we're opened for the first time then show My Outfits.
-		// Else show outfit edit panel
+		// Else do nothing.
 		if (!mOpened)
 		{
 			showOutfitsInventoryPanel();
 		}
-		else
-		{
-			showOutfitEditPanel();
-		}
 	}
 	else
 	{
@@ -319,12 +183,6 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 
 void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 {
-	//handle leaving and subsequent user verification of discarding any unsaved data
-	if ( mSidePanelJustOpened )
-	{
-		mSidePanelJustOpened = false;
-	}
-
 	LLSD visibility;
 	visibility["visible"] = new_visibility.asBoolean();
 	visibility["reset_accordion"] = false;
@@ -333,9 +191,8 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 
 void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
 {
-	if (new_visibility["visible"].asBoolean() )
+	if (new_visibility["visible"].asBoolean())
 	{
-
 		const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
 		const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
 
@@ -596,6 +453,7 @@ void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *dat
 	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data);
 	if (panel)
 	{
+		panel->showOutfitsInventoryPanel();
 		panel->showWearableEditPanel(wearable, disable_camera_switch);
 	}
 }
@@ -686,9 +544,3 @@ void LLSidepanelAppearance::updateScrollingPanelList()
 		mEditWearable->updateScrollingPanelList();
 	}
 }
-
-bool LLSidepanelAppearance::checkForDirtyEdits()
-{
-	return ( mEditWearable->isDirty() ) ? true : false;
-}
-
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 5042e92f4b..762f557a80 100755
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -38,11 +38,9 @@ class LLCurrentlyWornFetchObserver;
 class LLPanelEditWearable;
 class LLViewerWearable;
 class LLPanelOutfitsInventory;
-class LLFloaterSidePanelContainer;
 
 class LLSidepanelAppearance : public LLPanel
-{	
-
+{
 	LOG_CLASS(LLSidepanelAppearance);
 public:
 	LLSidepanelAppearance();
@@ -50,9 +48,6 @@ public:
 
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onOpen(const LLSD& key);	
-	/*virtual*/	void onClose(LLFloaterSidePanelContainer* obj);
-
-	void onClickCloseBtn();
 
 	void refreshCurrentOutfitName(const std::string& name = "");
 
@@ -70,12 +65,6 @@ public:
 	void updateScrollingPanelList();
 	void updateToVisibility( const LLSD& new_visibility );
 	LLPanelEditWearable* getWearable(){ return mEditWearable; }
-	bool callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response);
-	void onClickConfirmExitWithoutSaveViaBack();
-	bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response);
-	bool checkForDirtyEdits();	
-	void onClickConfirmExitWithoutSaveIntoAppearance(LLFloaterSidePanelContainer* obj);
-	void onCloseFromAppearance(LLFloaterSidePanelContainer* obj);
 
 private:
 	void onFilterEdit(const std::string& search_string);
@@ -88,9 +77,6 @@ private:
 	void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE);
 	void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE);
 
-
-	bool	onSaveCommit(const LLSD& notification, const LLSD& response);
-
 	LLFilterEditor*			mFilterEditor;
 	LLPanelOutfitsInventory* mPanelOutfitsInventory;
 	LLPanelOutfitEdit*		mOutfitEdit;
@@ -99,7 +85,6 @@ private:
 	LLButton*					mOpenOutfitBtn;
 	LLButton*					mEditAppearanceBtn;
 	LLButton*					mNewOutfitBtn;
-	
 	LLPanel*					mCurrOutfitPanel;
 
 	LLTextBox*					mCurrentLookName;
@@ -114,13 +99,6 @@ private:
 
 	// Gets set to true when we're opened for the first time.
 	bool mOpened;
-	// Set to true if sidepanel has just been opened
-	bool mSidePanelJustOpened;
-	LLFloaterSidePanelContainer* mLLFloaterSidePanelContainer;
-
-public:
-
-	bool mRevertSet;
 };
 
 #endif //LL_LLSIDEPANELAPPEARANCE_H
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 860dabdcc8..c3d8a528c5 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10114,37 +10114,5 @@ Cannot create large prims that intersect other players.  Please re-try when othe
   </notification>
 
 
-  <notification
-   icon="alertmodal.tga"
-   name="ConfirmExitWithoutSave"
-   type="alertmodal">
-    You have not saved the changes to your outfit. Would you like to save it now?
-    <tag>confirm</tag>
-    <usetemplate
-     name="yesnocancelbuttons"
-     notext="Revert"
-     yestext="Yes"
-     canceltext="Dismiss"/>
-  </notification>
-
-  <notification
-   icon="alertmodal.tga"
-   label="Save Outfit"
-   name="SaveOutfitEither"
-   type="alertmodal">
-    <unique/>
-    Save outfit (defaults to current outfit):
-    <tag>confirm</tag>
-    <form name="form">
-      <input name="message" type="text">
-        [DESC]
-      </input>
-      <button
-       default="true"
-       index="0"
-       name="OK"
-       text="Save"/>     
-    </form>
-  </notification>
-
+ 
 </notifications>
-- 
cgit v1.2.3


From 2d0b329003d0350c12ce4686f1261e68ce39573b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 17 Jun 2013 16:20:17 -0400
Subject: SH-4238 WIP - postpone calling notifyObservers until all deletes are
 processed.

---
 indra/newview/llaisapi.cpp         |  4 +++-
 indra/newview/llinventorymodel.cpp | 13 +++++++++----
 indra/newview/llinventorymodel.h   |  7 +++++--
 3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 393e5c0a68..21f6482a06 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -476,7 +476,9 @@ void AISUpdate::doUpdate()
 		 del_it != mObjectsDeleted.end(); ++del_it)
 	{
 		LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
-		gInventory.onObjectDeletedFromServer(*del_it, false, false);
+		gInventory.onObjectDeletedFromServer(*del_it, false, false, false);
 	}
+
+	gInventory.notifyObservers();
 }
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 6dc193292e..aadf87ab35 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1157,6 +1157,7 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
 
 void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
 {
+	LLTimer timer;
 	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 	{
 		dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
@@ -1164,6 +1165,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 
 	AISUpdate ais_update(update); // parse update llsd into stuff to do.
 	ais_update.doUpdate(); // execute the updates in the appropriate order.
+	llinfos << "elapsed: " << timer.getElapsedTimeF32() << llendl;
 }
 
 void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
@@ -1316,7 +1318,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 
 // Update model after an item is confirmed as removed from
 // server. Works for categories or items.
-void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version)
+void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version, bool do_notify_observers)
 {
 	LLPointer<LLInventoryObject> obj = getObject(object_id);
 	if(obj)
@@ -1337,13 +1339,13 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f
 
 		// From purgeObject()
 		LLPreview::hide(object_id);
-		deleteObject(object_id, fix_broken_links);
+		deleteObject(object_id, fix_broken_links, do_notify_observers);
 	}
 }
 
 
 // Delete a particular inventory object by ID.
-void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links)
+void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, bool do_notify_observers)
 {
 	lldebugs << "LLInventoryModel::deleteObject()" << llendl;
 	LLPointer<LLInventoryObject> obj = getObject(id);
@@ -1402,7 +1404,10 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links)
 	{
 		updateLinkedObjectsFromPurge(id);
 	}
-	notifyObservers();
+	if (do_notify_observers)
+	{
+		notifyObservers();
+	}
 }
 
 void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index a41a824906..5de951ed05 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -334,7 +334,10 @@ public:
 		
 	// Update model after an item is confirmed as removed from
 	// server. Works for categories or items.
-	void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true, bool update_parent_version = true);
+	void onObjectDeletedFromServer(const LLUUID& item_id,
+								   bool fix_broken_links = true,
+								   bool update_parent_version = true,
+								   bool do_notify_observers = true);
 
 	// Update model after all descendents removed from server.
 	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
@@ -349,7 +352,7 @@ public:
 	// object from the internal data structures, maintaining a
 	// consistent internal state. No cache accounting, observer
 	// notification, or server update is performed.
-	void deleteObject(const LLUUID& id, bool fix_broken_links = true);
+	void deleteObject(const LLUUID& id, bool fix_broken_links = true, bool do_notify_observers = true);
 	/// move Item item_id to Trash
 	void removeItem(const LLUUID& item_id);
 	/// move Category category_id to Trash
-- 
cgit v1.2.3


From 1a42b98a8f55662aed448e9bcd5035082140bbcf Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 17 Jun 2013 16:56:59 -0400
Subject: SH-4237 WIP - logging cleanup in onAIS handling

---
 indra/newview/llaisapi.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 21f6482a06..e57bbbb0be 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -315,7 +315,7 @@ void AISUpdate::parseUpdate(const LLSD& update)
 			}
 			else
 			{
-				llwarns << "unrecognized embedded field " << field << llendl;
+				//LL_DEBUGS("Inventory") << "unhandled embedded field " << field << llendl;
 			}
 		}
 		
@@ -439,8 +439,9 @@ void AISUpdate::doUpdate()
 		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
 		if (cat->getVersion() != version)
 		{
-			llwarns << "Possible version mismatch, viewer " << cat->getVersion()
-					<< " server " << version << llendl;
+			llwarns << "Possible version mismatch for category " << cat->getName()
+					<< ", viewer version " << cat->getVersion()
+					<< " server version " << version << llendl;
 		}
 	}
 
-- 
cgit v1.2.3


From c67db8e75511de879c69de0faf06a88ac3cc731d Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Mon, 17 Jun 2013 18:52:03 -0400
Subject: SH-4274 FIX Adding RegionHandshakeReply flags for SSA

Adding a flag to hint to the sim that this viewer knows how to handle
AvatarAppearance messages for self in SSA-enabled regions.
---
 indra/newview/llviewerregion.cpp | 6 +++++-
 indra/newview/llviewerregion.h   | 2 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b8b53aa6e4..48c050f403 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1568,7 +1568,11 @@ void LLViewerRegion::unpackRegionHandshake()
 	msg->addUUID("AgentID", gAgent.getID());
 	msg->addUUID("SessionID", gAgent.getSessionID());
 	msg->nextBlock("RegionInfo");
-	msg->addU32("Flags", 0x0 );
+
+	U32 flags = 0;
+	flags |= REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE;
+
+	msg->addU32("Flags", flags );
 	msg->sendReliable(host);
 }
 
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index b5fe4677b7..5ac2a83aaf 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -49,6 +49,8 @@
 #define WATER 2
 const U32	MAX_OBJECT_CACHE_ENTRIES = 50000;
 
+// Region handshake flags
+const U32 REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE = 1U << 2;
 
 class LLEventPoll;
 class LLVLComposition;
-- 
cgit v1.2.3


From 425ff28e4bc38ba3f7bfeade4a72dce4eba63b54 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Tue, 18 Jun 2013 10:00:05 -0500
Subject: SH-4275: Fixed regression - appearances are no longer broadcasted
 before exiting appearance editor

---
 indra/newview/llsidepanelappearance.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index d25d203feb..e082859767 100755
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -452,8 +452,7 @@ void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *dat
 	LLFloaterSidePanelContainer::showPanel("appearance", LLSD());
 	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data);
 	if (panel)
-	{
-		panel->showOutfitsInventoryPanel();
+	{	
 		panel->showWearableEditPanel(wearable, disable_camera_switch);
 	}
 }
-- 
cgit v1.2.3


From 27fc270c73fdf3db5c07e9ed43b7f4d0994b2cc2 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 18 Jun 2013 16:51:37 -0400
Subject: SH-4262 WIP - fix for the reordering bug in AIS regions.

---
 indra/newview/llaisapi.cpp          | 7 +++++++
 indra/newview/llappearancemgr.cpp   | 5 +++++
 indra/newview/llviewerinventory.cpp | 3 ++-
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 393e5c0a68..aad12a9cc9 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -326,6 +326,12 @@ void AISUpdate::parseUpdate(const LLSD& update)
 	{
 		LLUUID item_id = update["item_id"].asUUID();
 		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+		LLViewerInventoryItem *curr_item = gInventory.getItem(item_id);
+		if (curr_item)
+		{
+			// Default to current values where not provided.
+			new_item->copyViewerItem(curr_item);
+		}
 		BOOL rv = new_item->unpackMessage(update);
 		if (rv)
 		{
@@ -468,6 +474,7 @@ void AISUpdate::doUpdate()
 		// cases.  Maybe break out the update/create cases, in which
 		// case this is update.
 		LL_DEBUGS("Inventory") << "updated item " << item_id << llendl;
+		//LL_DEBUGS("Inventory") << ll_pretty_print_sd(new_item->asLLSD()) << llendl;
 		gInventory.updateItem(new_item);
 	}
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index f5f6faf6b6..16552f0082 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3434,7 +3434,12 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b
 	swap_item->setDescription(item->getActualDescription());
 	item->setDescription(tmp);
 
+	// LL_DEBUGS("Inventory") << "swap, item "
+	// 					   << ll_pretty_print_sd(item->asLLSD())
+	// 					   << " swap_item "
+	// 					   << ll_pretty_print_sd(swap_item->asLLSD()) << llendl;
 
+	// FIXME switch to use AISv3 where supported.
 	//items need to be updated on a dataserver
 	item->setComplete(TRUE);
 	item->updateServer(FALSE);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 55575764b9..26aecd39d1 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -360,7 +360,8 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const
 	if(gAgent.getID() != mPermissions.getOwner())
 	{
 		// *FIX: deal with this better.
-		llwarns << "LLViewerInventoryItem::updateServer() - for unowned item"
+		llwarns << "LLViewerInventoryItem::updateServer() - for unowned item "
+			    << ll_pretty_print_sd(this->asLLSD())
 				<< llendl;
 		return;
 	}
-- 
cgit v1.2.3


From f88594599c01edff981b6d070f84566fcb7d4ecf Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 18 Jun 2013 16:54:37 -0400
Subject: SH-4237 WIP - removed somewhat misleading warning

---
 indra/newview/llaisapi.cpp | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 7e751ad6c7..8037654812 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -313,12 +313,7 @@ void AISUpdate::parseUpdate(const LLSD& update)
 				const LLSD& links = embedded["link"];
 				parseCreatedLinks(links);
 			}
-			else
-			{
-				llwarns << "unrecognized embedded field " << field << llendl;
-			}
 		}
-		
 	}
 
 	// Parse item update at the top level.
-- 
cgit v1.2.3


From 4ffc162492a3fe882af0899ba70e835c80367d09 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 19 Jun 2013 16:17:33 -0400
Subject: SH-4263 FIX - added yet another level of callback kludgery to
 updateAppearanceFromCOF()

---
 indra/newview/llappearancemgr.cpp | 57 ++++++++++++++++++++++++---------------
 indra/newview/llappearancemgr.h   |  7 +++--
 2 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 16552f0082..cb32bf9c40 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -436,11 +436,14 @@ S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
 
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
 														 bool enforce_item_restrictions,
-														 bool enforce_ordering):
+														 bool enforce_ordering,
+														 nullary_func_t post_update_func 
+	):
 	mFireCount(0),
 	mUpdateBaseOrder(update_base_outfit_ordering),
 	mEnforceItemRestrictions(enforce_item_restrictions),
-	mEnforceOrdering(enforce_ordering)
+	mEnforceOrdering(enforce_ordering),
+	mPostUpdateFunc(post_update_func)
 {
 	selfStartPhase("update_appearance_on_destroy");
 }
@@ -464,7 +467,10 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 
 		selfStopPhase("update_appearance_on_destroy");
 
-		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions, mEnforceOrdering);
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder,
+															mEnforceItemRestrictions,
+															mEnforceOrdering,
+															mPostUpdateFunc);
 	}
 }
 
@@ -473,29 +479,34 @@ LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnD
 {
 }
 
-LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy()
+void edit_wearable_and_customize_avatar(LLUUID item_id)
 {
-	if (!LLApp::isExiting())
+	// Start editing the item if previously requested.
+	gAgentWearables.editWearableIfRequested(item_id);
+	
+	// TODO: camera mode may not be changed if a debug setting is tweaked
+	if( gAgentCamera.cameraCustomizeAvatar() )
 	{
-		LLAppearanceMgr::instance().updateAppearanceFromCOF();
-		
-		// Start editing the item if previously requested.
-		gAgentWearables.editWearableIfRequested(mItemID);
-		
-		// TODO: camera mode may not be changed if a debug setting is tweaked
-		if( gAgentCamera.cameraCustomizeAvatar() )
+		// If we're in appearance editing mode, the current tab may need to be refreshed
+		LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(
+			LLFloaterSidePanelContainer::getPanel("appearance"));
+		if (panel)
 		{
-			// If we're in appearance editing mode, the current tab may need to be refreshed
-			LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(
-				LLFloaterSidePanelContainer::getPanel("appearance"));
-			if (panel)
-			{
-				panel->showDefaultSubpart();
-			}
+			panel->showDefaultSubpart();
 		}
 	}
 }
 
+LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy()
+{
+	if (!LLApp::isExiting())
+	{
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(
+			false,true,true,
+			boost::bind(edit_wearable_and_customize_avatar, mItemID));
+	}
+}
+
 
 struct LLFoundData
 {
@@ -1971,7 +1982,8 @@ void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback>
 
 void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 											  bool enforce_item_restrictions,
-											  bool enforce_ordering)
+											  bool enforce_ordering,
+											  nullary_func_t post_update_func)
 {
 	if (mIsInUpdateAppearanceFromCOF)
 	{
@@ -1989,7 +2001,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 		// enforce_item_restrictions to false so we don't get
 		// caught in a perpetual loop.
 		LLPointer<LLInventoryCallback> cb(
-			new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering));
+			new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering, post_update_func));
 		enforceCOFItemRestrictions(cb);
 		return;
 	}
@@ -2003,7 +2015,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 		// to wait for the update callbacks, then (finally!) call
 		// updateAppearanceFromCOF() with no additional COF munging needed.
 		LLPointer<LLInventoryCallback> cb(
-			new LLUpdateAppearanceOnDestroy(false, false, false));
+			new LLUpdateAppearanceOnDestroy(false, false, false, post_update_func));
 		updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb);
 		return;
 	}
@@ -2120,6 +2132,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 	{
 		doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollFetchCompletion,holder));
 	}
+	post_update_func();
 }
 
 void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 9eb26767c4..a257f30ea5 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -51,7 +51,8 @@ public:
 
 	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false,
 								 bool enforce_item_restrictions = true,
-								 bool enforce_ordering = true);
+								 bool enforce_ordering = true,
+								 nullary_func_t post_update_func = no_op);
 	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
@@ -272,7 +273,8 @@ class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 public:
 	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false,
 								bool enforce_item_restrictions = true,
-								bool enforce_ordering = true);
+								bool enforce_ordering = true,
+								nullary_func_t post_update_func = no_op);
 	virtual ~LLUpdateAppearanceOnDestroy();
 	/* virtual */ void fire(const LLUUID& inv_item);
 
@@ -281,6 +283,7 @@ private:
 	bool mUpdateBaseOrder;
 	bool mEnforceItemRestrictions;
 	bool mEnforceOrdering;
+	nullary_func_t mPostUpdateFunc;
 };
 
 class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback
-- 
cgit v1.2.3


From 01ffa6788793cdecff313b704422f0e814452489 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 21 Jun 2013 21:21:57 -0400
Subject: SH-4240 FIX Users can set their hover height to 0

Adjusted the startup conditions, and relogging should apply the enforcement
as appropriate now. Note that this affects the startup enforcement and should
re-test the macro avatar loading bug.
---
 indra/newview/lltoolmorph.cpp      | 4 ++--
 indra/newview/llviewerwearable.cpp | 6 ++++--
 indra/newview/llviewerwearable.h   | 6 +++---
 indra/newview/llvoavatar.cpp       | 6 +++---
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index fa94b52362..71e0509d03 100755
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -151,7 +151,7 @@ void LLVisualParamHint::preRender(BOOL clear_depth)
 	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
 	if (wearable)
 	{
-		wearable->setVolitile(TRUE);
+		wearable->setVolatile(TRUE);
 	}
 	mLastParamWeight = mVisualParam->getWeight();
 	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
@@ -250,7 +250,7 @@ BOOL LLVisualParamHint::render()
 	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
 	if (wearable)
 	{
-		wearable->setVolitile(FALSE);
+		wearable->setVolatile(FALSE);
 	}
 
 	gAgentAvatarp->updateVisualParams();
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index e8425dc76a..76f94935b8 100644
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -72,14 +72,16 @@ private:
 static std::string asset_id_to_filename(const LLUUID &asset_id);
 
 LLViewerWearable::LLViewerWearable(const LLTransactionID& transaction_id) :
-	LLWearable()
+	LLWearable(),
+	mVolatile(FALSE)
 {
 	mTransactionID = transaction_id;
 	mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
 }
 
 LLViewerWearable::LLViewerWearable(const LLAssetID& asset_id) :
-	LLWearable()
+	LLWearable(),
+	mVolatile(FALSE)
 {
 	mAssetID = asset_id;
 	mTransactionID.setNull();
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
index 047b2ce143..ef8c29323e 100644
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -68,8 +68,8 @@ public:
 	
 	void				setParamsToDefaults();
 	void				setTexturesToDefaults();
-	void				setVolitile(BOOL volitle) { mVolitle = volitle; } // TRUE when doing preview renders, some updates will be suppressed.
-	BOOL				getVolitile() { return mVolitle; }
+	void				setVolatile(BOOL is_volatile) { mVolatile = is_volatile; } // TRUE when doing preview renders, some updates will be suppressed.
+	BOOL				getVolatile() { return mVolatile; }
 
 	/*virtual*/ LLUUID	getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const;
 
@@ -98,7 +98,7 @@ protected:
 	LLAssetID			mAssetID;
 	LLTransactionID		mTransactionID;
 
-	BOOL 				mVolitle; // True when rendering preview images. Can suppress some updates.
+	BOOL 				mVolatile; // True when rendering preview images. Can suppress some updates.
 
 	LLUUID				mItemID;  // ID of the inventory item in the agent's inventory	
 };
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 46b909c4a1..8c20533b4c 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5223,7 +5223,7 @@ void LLVOAvatar::computeBodySize()
 	// Enforce a constraint to make sure we don't go below 1.1 meters (server-enforced limit)
 	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
 	const LLViewerObject * last_object = NULL;
-	if (isSelf() && getWearableData() && isFullyLoaded() && !LLApp::isQuitting())
+	if (isSelf() && getWearableData() && !LLApp::isQuitting())
 	{
 		// Do not force a hover parameter change while we have pending attachments, which may be mesh-based with 
 		// joint offsets.
@@ -5246,7 +5246,7 @@ void LLVOAvatar::computeBodySize()
 							last_object = object;
 							llwarns << "attachment at point: " << (*points_iter).first << " object exists: " << object->getAttachmentItemID() << llendl;
 							loaded &=!object->isDrawableState(LLDrawable::REBUILD_ALL);
-							if (!loaded && shape && !shape->getVolitile()) 
+							if (!loaded && shape && !shape->getVolatile()) 
 							{
 								llwarns << "caught unloaded attachment! skipping enforcement" << llendl;
 							}
@@ -5259,7 +5259,7 @@ void LLVOAvatar::computeBodySize()
 			{
 				LL_DEBUGS("Avatar") << "scanned at least one object!"  << LL_ENDL;
 			}
-			if (loaded && shape && !shape->getVolitile()) 
+			if (loaded && shape && !shape->getVolatile()) 
 			{
 				F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER);
 				if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f))
-- 
cgit v1.2.3


From 3e0e236f33a866a3962295a99495fd1159532ba8 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 24 Jun 2013 15:42:27 -0400
Subject: SH-4243 WIP - cleaned up callback structure for createNewCategory,
 modified makeNewOutfitLinks() to wait for category creation before
 populating.

---
 indra/newview/llappearancemgr.cpp         | 49 ++++++++++++++-------
 indra/newview/llappearancemgr.h           |  4 +-
 indra/newview/llfloateropenobject.cpp     | 21 +++------
 indra/newview/llfloateropenobject.h       | 11 +----
 indra/newview/llinventorymodel.cpp        | 72 ++++++++++++++-----------------
 indra/newview/llinventorymodel.h          |  9 +---
 indra/newview/llpaneloutfitsinventory.cpp |  2 +-
 indra/newview/llstartup.cpp               |  4 +-
 indra/newview/llviewerinventory.cpp       |  3 +-
 indra/newview/llviewerinventory.h         |  6 ++-
 10 files changed, 89 insertions(+), 92 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index cb32bf9c40..93b0e6f4e7 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1466,6 +1466,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 		{
 			case LLAssetType::AT_LINK:
 			{
+				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << llendl;
 				//getActualDescription() is used for a new description 
 				//to propagate ordering information saved in descriptions of links
 				link_inventory_item(gAgent.getID(),
@@ -1482,6 +1483,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 				// Skip copying outfit links.
 				if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
 				{
+					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << llendl;
 					link_inventory_item(gAgent.getID(),
 										item->getLinkedUUID(),
 										dst_id,
@@ -1496,7 +1498,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 			case LLAssetType::AT_BODYPART:
 			case LLAssetType::AT_GESTURE:
 			{
-				llinfos << "copying inventory item " << item->getName() << llendl;
+				LL_DEBUGS("Avatar") << "copying inventory item " << item->getName() << llendl;
 				copy_inventory_item(gAgent.getID(),
 									item->getPermissions().getOwner(),
 									item->getUUID(),
@@ -2815,11 +2817,14 @@ bool LLAppearanceMgr::updateBaseOutfit()
 		llassert(!isOutfitLocked());
 		return false;
 	}
+
+
 	setOutfitLocked(true);
 
 	gAgentWearables.notifyLoadingStarted();
 
 	const LLUUID base_outfit_id = getBaseOutfitUUID();
+	LL_DEBUGS("Avatar") << "updating base outfit to " << base_outfit_id << llendl;
 	if (base_outfit_id.isNull()) return false;
 
 	updateClothingOrderingInfo();
@@ -3334,12 +3339,14 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
 		return;
 	}
 	
+	LL_DEBUGS("Avatar") << "called" << llendl;
 	LLSD key;
 	
 	//EXT-7727. For new accounts inventory callback is created during login process
 	// and may be processed after login process is finished
 	if (show_panel)
 	{
+		LL_DEBUGS("Avatar") << "showing panel" << llendl;
 		LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key);
 		
 	}
@@ -3358,32 +3365,44 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
 	// link, since, the COF version has changed. There is a race
 	// condition in initial outfit setup which can lead to rez
 	// failures - SH-3860.
+	LL_DEBUGS("Avatar") << "requesting appearance update after createBaseOutfitLink" << llendl;
 	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
 	LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb);
 }
 
-LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
+void LLAppearanceMgr::onOutfitFolderCreated(const LLSD& result, bool show_panel)
 {
-	if (!isAgentAvatarValid()) return LLUUID::null;
-
-	gAgentWearables.notifyLoadingStarted();
-
-	// First, make a folder in the My Outfits directory.
-	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	LLUUID folder_id = gInventory.createNewCategory(
-		parent_id,
-		LLFolderType::FT_OUTFIT,
-		new_folder_name);
+	LL_DEBUGS("Avatar") << ll_pretty_print_sd(result) << llendl;
 
-	updateClothingOrderingInfo();
+	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func,
+																		 boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,result,show_panel));
+	updateClothingOrderingInfo(LLUUID::null, false, cb);
+}
 
+void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLSD& result, bool show_panel)
+{
+	LLUUID folder_id = result["folder_id"].asUUID();
 	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func,
 																		 boost::bind(show_created_outfit,folder_id,show_panel));
 	shallowCopyCategoryContents(getCOF(),folder_id, cb);
+}
+
+void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
+{
+	if (!isAgentAvatarValid()) return;
 
-	dumpCat(folder_id,"COF, new outfit");
+	LL_DEBUGS("Avatar") << "creating new outfit" << llendl;
 
-	return folder_id;
+	gAgentWearables.notifyLoadingStarted();
+
+	// First, make a folder in the My Outfits directory.
+	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+	llsd_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
+	gInventory.createNewCategory(
+		parent_id,
+		LLFolderType::FT_OUTFIT,
+		new_folder_name,
+		func);
 }
 
 void LLAppearanceMgr::wearBaseOutfit()
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index a257f30ea5..d4993780aa 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -186,7 +186,9 @@ public:
 	void removeItemFromAvatar(const LLUUID& item_id);
 
 
-	LLUUID makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);
+	void onOutfitFolderCreated(const LLSD& result, bool show_panel);
+	void onOutfitFolderCreatedAndClothingOrdered(const LLSD& result, bool show_panel);
+	void makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel = true);
 
 	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
 
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 4bfef8b45f..1c086976ba 100755
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -162,21 +162,17 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 	{
 		parent_category_id = gInventory.getRootFolderID();
 	}
-	
-	LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear);
-	
+
+	llsd_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear);
 	LLUUID category_id = gInventory.createNewCategory(parent_category_id, 
 													  LLFolderType::FT_NONE, 
 													  name,
-													  callbackCreateInventoryCategory,
-													  (void*)cat_data);
+													  func);
 
 	//If we get a null category ID, we are using a capability in createNewCategory and we will
 	//handle the following in the callbackCreateInventoryCategory routine.
 	if ( category_id.notNull() )
 	{
-		delete cat_data;
-		
 		LLCatAndWear* data = new LLCatAndWear;
 		data->mCatID = category_id;
 		data->mWear = wear;
@@ -198,20 +194,18 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 }
 
 // static
-void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data)
+void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, LLUUID object_id, bool wear)
 {
-	LLCategoryCreate* cat_data = (LLCategoryCreate*)data;
-	
-	LLUUID category_id = result["folder_id"].asUUID();
 	LLCatAndWear* wear_data = new LLCatAndWear;
+	LLUUID category_id = result["folder_id"].asUUID();
 
 	wear_data->mCatID = category_id;
-	wear_data->mWear = cat_data->mWear;
+	wear_data->mWear = wear;
 	wear_data->mFolderResponded = true;
 	
 	// Copy and/or move the items into the newly created folder.
 	// Ignore any "you're going to break this item" messages.
-	BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE,
+	BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
 													callbackMoveInventory, 
 													(void*)wear_data);
 	if (!success)
@@ -221,7 +215,6 @@ void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, vo
 		
 		LLNotificationsUtil::add("OpenObjectCannotCopy");
 	}
-	delete cat_data;	
 }
 
 // static
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index bf7fe69c65..1d7eecd107 100755
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -45,15 +45,6 @@ public:
 	
 	void dirty();
 	
-	class LLCategoryCreate
-	{
-		public:
-			LLCategoryCreate(LLUUID object_id, bool wear) : mObjectID(object_id), mWear(wear) {}
-		public:
-			LLUUID mObjectID;
-			bool mWear;
-	};
-	
 	struct LLCatAndWear
 	{
 		LLUUID mCatID;
@@ -72,7 +63,7 @@ protected:
 
 	void onClickMoveToInventory();
 	void onClickMoveAndWear();
-	static void callbackCreateInventoryCategory(const LLSD& result, void* data);
+	static void callbackCreateInventoryCategory(const LLSD& result, LLUUID object_id, bool wear);
 	static void callbackMoveInventory(S32 result, void* data);
 
 private:
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index aadf87ab35..82d58523ce 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -472,11 +472,9 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 	LOG_CLASS(LLCreateInventoryCategoryResponder);
 public:
 	LLCreateInventoryCategoryResponder(LLInventoryModel* model, 
-									   void (*callback)(const LLSD&, void*),
-									   void* user_data) :
-										mModel(model),
-										mCallback(callback), 
-										mData(user_data) 
+									   boost::optional<llsd_func_type> callback):
+		mModel(model),
+		mCallback(callback) 
 	{
 	}
 	
@@ -497,7 +495,7 @@ protected:
 		}
 		LLUUID category_id = content["folder_id"].asUUID();
 		
-		
+		LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << llendl;
 		// Add the category to the internal representation
 		LLPointer<LLViewerInventoryCategory> cat =
 		new LLViewerInventoryCategory( category_id, 
@@ -510,17 +508,15 @@ protected:
 		LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
 		mModel->accountForUpdate(update);
 		mModel->updateCategory(cat);
-		
-		if (mCallback && mData)
+
+		if (mCallback)
 		{
-			mCallback(content, mData);
+			mCallback.get()(content);
 		}
-		
 	}
 	
 private:
-	void (*mCallback)(const LLSD&, void*);
-	void* mData;
+	boost::optional<llsd_func_type> mCallback;
 	LLInventoryModel* mModel;
 };
 
@@ -531,8 +527,7 @@ private:
 LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 										   LLFolderType::EType preferred_type,
 										   const std::string& pname,
-										   void (*callback)(const LLSD&, void*),	//Default to NULL
-										   void* user_data)							//Default to NULL
+										   boost::optional<llsd_func_type> callback)
 {
 	
 	LLUUID id;
@@ -559,33 +554,32 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 		name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
 	}
 	
-	if ( callback && user_data )  //callback required for acked message.
+	LLViewerRegion* viewer_region = gAgent.getRegion();
+	std::string url;
+	if ( viewer_region )
+		url = viewer_region->getCapability("CreateInventoryCategory");
+	
+	if (!url.empty() && callback.get_ptr())
 	{
-		LLViewerRegion* viewer_region = gAgent.getRegion();
-		std::string url;
-		if ( viewer_region )
-			url = viewer_region->getCapability("CreateInventoryCategory");
+		//Let's use the new capability.
 		
-		if (!url.empty())
-		{
-			//Let's use the new capability.
-			
-			LLSD request, body;
-			body["folder_id"] = id;
-			body["parent_id"] = parent_id;
-			body["type"] = (LLSD::Integer) preferred_type;
-			body["name"] = name;
-			
-			request["message"] = "CreateInventoryCategory";
-			request["payload"] = body;
-			
-	//		viewer_region->getCapAPI().post(request);
-			LLHTTPClient::post(
-							   url,
-							   body,
-							   new LLCreateInventoryCategoryResponder(this, callback, user_data) );
-			return LLUUID::null;
-		}
+		LLSD request, body;
+		body["folder_id"] = id;
+		body["parent_id"] = parent_id;
+		body["type"] = (LLSD::Integer) preferred_type;
+		body["name"] = name;
+		
+		request["message"] = "CreateInventoryCategory";
+		request["payload"] = body;
+
+		LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << llendl;
+		//		viewer_region->getCapAPI().post(request);
+		LLHTTPClient::post(
+			url,
+			body,
+			new LLCreateInventoryCategoryResponder(this, callback) );
+
+		return LLUUID::null;
 	}
 
 	// Add the category to the internal representation
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 5de951ed05..f28211cfa1 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -34,6 +34,7 @@
 #include "llhttpclient.h"
 #include "lluuid.h"
 #include "llpermissionsflags.h"
+#include "llviewerinventory.h"
 #include "llstring.h"
 #include "llmd5.h"
 #include <map>
@@ -45,14 +46,9 @@ class LLInventoryObserver;
 class LLInventoryObject;
 class LLInventoryItem;
 class LLInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
 class LLMessageSystem;
 class LLInventoryCollectFunctor;
 
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // LLInventoryModel
 //
@@ -394,8 +390,7 @@ public:
 	LLUUID createNewCategory(const LLUUID& parent_id,
 							 LLFolderType::EType preferred_type,
 							 const std::string& name,
-							 void (*callback)(const LLSD&, void*) = NULL,
-							 void* user_data = NULL );
+							 boost::optional<llsd_func_type> callback = boost::optional<llsd_func_type>());
 protected:
 	// Internal methods that add inventory and make sure that all of
 	// the internal data structures are consistent. These methods
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index d6c927ab58..21b77ef471 100755
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -184,7 +184,7 @@ bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD&
 		LLStringUtil::trim(outfit_name);
 		if( !outfit_name.empty() )
 		{
-			LLUUID outfit_folder = LLAppearanceMgr::getInstance()->makeNewOutfitLinks(outfit_name);
+			LLAppearanceMgr::getInstance()->makeNewOutfitLinks(outfit_name);
 
 			LLSidepanelAppearance* panel_appearance = getAppearanceSP();
 			if (panel_appearance)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 8890df199b..84d42c6345 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2613,10 +2613,10 @@ void LLStartUp::saveInitialOutfit()
 	
 	if (sWearablesLoadedCon.connected())
 	{
-		lldebugs << "sWearablesLoadedCon is connected, disconnecting" << llendl;
+		LL_DEBUGS("Avatar") << "sWearablesLoadedCon is connected, disconnecting" << llendl;
 		sWearablesLoadedCon.disconnect();
 	}
-	lldebugs << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << llendl;
+	LL_DEBUGS("Avatar") << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << llendl;
 	LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false);
 }
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 26aecd39d1..9725ea6456 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -69,8 +69,9 @@
 #include "llclipboard.h"
 #include "llhttpretrypolicy.h"
 
-// Two do-nothing ops for use in callbacks.
+// do-nothing ops for use in callbacks.
 void no_op_inventory_func(const LLUUID&) {} 
+void no_op_llsd_func(const LLSD&) {}
 void no_op() {}
 
 ///----------------------------------------------------------------------------
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 032efd9542..de1f3daa1e 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -263,9 +263,11 @@ private:
 };
 
 typedef boost::function<void(const LLUUID&)> inventory_func_type;
-void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func
-
+typedef boost::function<void(const LLSD&)> llsd_func_type;
 typedef boost::function<void()> nullary_func_type;
+
+void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func
+void no_op_llsd_func(const LLSD&); // likewise for LLSD
 void no_op(); // A do-nothing nullary func.
 
 // Shim between inventory callback and boost function/callable
-- 
cgit v1.2.3


From bbdd2a34d01d938226c7935a3d52ec0a7c483e90 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 25 Jun 2013 10:00:46 -0400
Subject: SH-4243 FIX - removed wait for category creation, since
 callback-based cap only works correctly if a recent fix is deployed
 server-side. May revisit at some point.

---
 indra/newview/llappearancemgr.cpp | 25 ++++++++++++-------------
 indra/newview/llappearancemgr.h   |  4 ++--
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 93b0e6f4e7..c068a6358f 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3370,20 +3370,19 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
 	LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb);
 }
 
-void LLAppearanceMgr::onOutfitFolderCreated(const LLSD& result, bool show_panel)
+void LLAppearanceMgr::onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel)
 {
-	LL_DEBUGS("Avatar") << ll_pretty_print_sd(result) << llendl;
-
-	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func,
-																		 boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,result,show_panel));
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func,
+										 boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,folder_id,show_panel));
 	updateClothingOrderingInfo(LLUUID::null, false, cb);
 }
 
-void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLSD& result, bool show_panel)
+void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel)
 {
-	LLUUID folder_id = result["folder_id"].asUUID();
-	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(no_op_inventory_func,
-																		 boost::bind(show_created_outfit,folder_id,show_panel));
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func,
+										 boost::bind(show_created_outfit,folder_id,show_panel));
 	shallowCopyCategoryContents(getCOF(),folder_id, cb);
 }
 
@@ -3397,12 +3396,12 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
 
 	// First, make a folder in the My Outfits directory.
 	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	llsd_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
-	gInventory.createNewCategory(
+	//llsd_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
+	LLUUID folder_id = gInventory.createNewCategory(
 		parent_id,
 		LLFolderType::FT_OUTFIT,
-		new_folder_name,
-		func);
+		new_folder_name);
+	onOutfitFolderCreated(folder_id, show_panel);
 }
 
 void LLAppearanceMgr::wearBaseOutfit()
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index d4993780aa..beed6e824a 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -186,8 +186,8 @@ public:
 	void removeItemFromAvatar(const LLUUID& item_id);
 
 
-	void onOutfitFolderCreated(const LLSD& result, bool show_panel);
-	void onOutfitFolderCreatedAndClothingOrdered(const LLSD& result, bool show_panel);
+	void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
+	void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel);
 	void makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel = true);
 
 	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
-- 
cgit v1.2.3


From ffd7b0d7e7ef13510d7299e601a71c7fedb0a4d1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 25 Jun 2013 17:52:02 -0400
Subject: SH-4305 WIP

---
 indra/newview/llappearancemgr.cpp     | 78 +++++++++++++++++++++++++++++++----
 indra/newview/llappearancemgr.h       |  4 ++
 indra/newview/llfloateropenobject.cpp |  5 +--
 indra/newview/llfloateropenobject.h   |  2 +-
 indra/newview/llinventorymodel.cpp    |  8 ++--
 indra/newview/llinventorymodel.h      |  2 +-
 6 files changed, 83 insertions(+), 16 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index c068a6358f..f19500c98d 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -53,6 +53,7 @@
 #include "llsdutil.h"
 #include "llsdserialize.h"
 #include "llhttpretrypolicy.h"
+#include "llaisapi.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -1449,6 +1450,53 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds
 	gInventory.notifyObservers();
 }
 
+void LLAppearanceMgr::copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+										bool include_folder_links, LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryModel::cat_array_t* cats;
+	LLInventoryModel::item_array_t* items;
+	LLSD contents = LLSD::emptyArray();
+	gInventory.getDirectDescendentsOf(src_id, cats, items);
+	llinfos << "copying " << items->count() << " items" << llendl;
+	for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
+		 iter != items->end();
+		 ++iter)
+	{
+		const LLViewerInventoryItem* item = (*iter);
+		switch (item->getActualType())
+		{
+			case LLAssetType::AT_LINK:
+			{
+				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << llendl;
+				//getActualDescription() is used for a new description 
+				//to propagate ordering information saved in descriptions of links
+				LLSD item_contents;
+				item_contents["name"] = item->getName();
+				item_contents["desc"] = item->getActualDescription();
+				item_contents["linked_id"] = item->getLinkedUUID();
+				item_contents["type"] = LLAssetType::AT_LINK; 
+				contents.append(item_contents);
+				break;
+			}
+			case LLAssetType::AT_LINK_FOLDER:
+			{
+				LLViewerInventoryCategory *catp = item->getLinkedCategory();
+				if (catp && include_folder_links)
+				{
+					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << llendl;
+					LLSD base_contents;
+					base_contents["name"] = catp->getName();
+					base_contents["desc"] = ""; // categories don't have descriptions.
+					base_contents["linked_id"] = catp->getLinkedUUID();
+					base_contents["type"] = LLAssetType::AT_LINK_FOLDER; 
+					contents.append(base_contents);
+				}
+				break;
+			}
+		}
+	}
+	slam_inventory_folder(dst_id, contents, cb);
+}
 // Copy contents of src_id to dst_id.
 void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
 													  LLPointer<LLInventoryCallback> cb)
@@ -3383,7 +3431,8 @@ void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& fold
 	LLPointer<LLInventoryCallback> cb =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func,
 										 boost::bind(show_created_outfit,folder_id,show_panel));
-	shallowCopyCategoryContents(getCOF(),folder_id, cb);
+	bool copy_folder_links = false;
+	copyCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);
 }
 
 void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
@@ -3396,12 +3445,27 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
 
 	// First, make a folder in the My Outfits directory.
 	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	//llsd_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
-	LLUUID folder_id = gInventory.createNewCategory(
-		parent_id,
-		LLFolderType::FT_OUTFIT,
-		new_folder_name);
-	onOutfitFolderCreated(folder_id, show_panel);
+	std::string cap;
+	if (AISCommand::getCap(cap))
+	{
+		// cap-based category creation was buggy until recently. use
+		// existence of AIS as an indicator the fix is present. Does
+		// not actually use AIS to create the category.
+		inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
+		LLUUID folder_id = gInventory.createNewCategory(
+			parent_id,
+			LLFolderType::FT_OUTFIT,
+			new_folder_name,
+			func);
+	}
+	else
+	{		
+		LLUUID folder_id = gInventory.createNewCategory(
+			parent_id,
+			LLFolderType::FT_OUTFIT,
+			new_folder_name);
+		onOutfitFolderCreated(folder_id, show_panel);
+	}
 }
 
 void LLAppearanceMgr::wearBaseOutfit()
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index beed6e824a..4d7c536b3d 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -73,6 +73,10 @@ public:
 	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
 	S32 getActiveCopyOperations() const;
+
+	// Copy all links via the slam command (single inventory operation where supported)
+	void copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+						   bool include_folder_links, LLPointer<LLInventoryCallback> cb);
 	
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 1c086976ba..9986bdbd7f 100755
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -163,7 +163,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 		parent_category_id = gInventory.getRootFolderID();
 	}
 
-	llsd_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear);
+	inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear);
 	LLUUID category_id = gInventory.createNewCategory(parent_category_id, 
 													  LLFolderType::FT_NONE, 
 													  name,
@@ -194,10 +194,9 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
 }
 
 // static
-void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, LLUUID object_id, bool wear)
+void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear)
 {
 	LLCatAndWear* wear_data = new LLCatAndWear;
-	LLUUID category_id = result["folder_id"].asUUID();
 
 	wear_data->mCatID = category_id;
 	wear_data->mWear = wear;
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 1d7eecd107..8e472804a4 100755
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -63,7 +63,7 @@ protected:
 
 	void onClickMoveToInventory();
 	void onClickMoveAndWear();
-	static void callbackCreateInventoryCategory(const LLSD& result, LLUUID object_id, bool wear);
+	static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear);
 	static void callbackMoveInventory(S32 result, void* data);
 
 private:
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 82d58523ce..e1fd2e02fa 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -472,7 +472,7 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 	LOG_CLASS(LLCreateInventoryCategoryResponder);
 public:
 	LLCreateInventoryCategoryResponder(LLInventoryModel* model, 
-									   boost::optional<llsd_func_type> callback):
+									   boost::optional<inventory_func_type> callback):
 		mModel(model),
 		mCallback(callback) 
 	{
@@ -511,12 +511,12 @@ protected:
 
 		if (mCallback)
 		{
-			mCallback.get()(content);
+			mCallback.get()(category_id);
 		}
 	}
 	
 private:
-	boost::optional<llsd_func_type> mCallback;
+	boost::optional<inventory_func_type> mCallback;
 	LLInventoryModel* mModel;
 };
 
@@ -527,7 +527,7 @@ private:
 LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 										   LLFolderType::EType preferred_type,
 										   const std::string& pname,
-										   boost::optional<llsd_func_type> callback)
+										   boost::optional<inventory_func_type> callback)
 {
 	
 	LLUUID id;
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index f28211cfa1..ee0d4e1994 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -390,7 +390,7 @@ public:
 	LLUUID createNewCategory(const LLUUID& parent_id,
 							 LLFolderType::EType preferred_type,
 							 const std::string& name,
-							 boost::optional<llsd_func_type> callback = boost::optional<llsd_func_type>());
+							 boost::optional<inventory_func_type> callback = boost::optional<inventory_func_type>());
 protected:
 	// Internal methods that add inventory and make sure that all of
 	// the internal data structures are consistent. These methods
-- 
cgit v1.2.3


From e2e198d9b36f4ef90ef7ca088e643b1fc399c53e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 26 Jun 2013 10:50:07 -0400
Subject: SH-4305 WIP - fix for compiler grumbling on linux build.

---
 indra/newview/llappearancemgr.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index f19500c98d..8a0814734c 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1493,6 +1493,11 @@ void LLAppearanceMgr::copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_
 				}
 				break;
 			}
+			default:
+			{
+				// Linux refuses to compile unless all possible enums are handled. Really, Linux?
+				break;
+			}
 		}
 	}
 	slam_inventory_folder(dst_id, contents, cb);
-- 
cgit v1.2.3


From cbb83180e8ea6c1f64c77049ea62f2977f55e2f1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 26 Jun 2013 11:27:13 -0400
Subject: SH-4305 WIP - one more case where we need to use slammer to update
 category

---
 indra/newview/llappearancemgr.cpp | 16 ++++------------
 indra/newview/llappearancemgr.h   |  5 +++--
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 8a0814734c..5f061ca290 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1450,7 +1450,7 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds
 	gInventory.notifyObservers();
 }
 
-void LLAppearanceMgr::copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
 										bool include_folder_links, LLPointer<LLInventoryCallback> cb)
 {
 	LLInventoryModel::cat_array_t* cats;
@@ -2882,14 +2882,12 @@ bool LLAppearanceMgr::updateBaseOutfit()
 
 	updateClothingOrderingInfo();
 
-	// in a Base Outfit we do not remove items, only links
-	remove_folder_contents(base_outfit_id, false, NULL);
-
 	LLPointer<LLInventoryCallback> dirty_state_updater =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
 
 	//COF contains only links so we copy to the Base Outfit only links
-	shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater);
+	bool copy_folder_links = false;
+	slamCategoryLinks(getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater);
 
 	return true;
 }
@@ -2937,12 +2935,6 @@ struct WearablesOrderComparator
 
 	bool operator()(const LLInventoryItem* item1, const LLInventoryItem* item2)
 	{
-		if (!item1 || !item2)
-		{
-			llwarning("either item1 or item2 is NULL", 0);
-			return true;
-		}
-		
 		const std::string& desc1 = item1->getActualDescription();
 		const std::string& desc2 = item2->getActualDescription();
 		
@@ -3437,7 +3429,7 @@ void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& fold
 		new LLBoostFuncInventoryCallback(no_op_inventory_func,
 										 boost::bind(show_created_outfit,folder_id,show_panel));
 	bool copy_folder_links = false;
-	copyCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);
+	slamCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);
 }
 
 void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 4d7c536b3d..ddef3b4a9b 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -74,8 +74,9 @@ public:
 
 	S32 getActiveCopyOperations() const;
 
-	// Copy all links via the slam command (single inventory operation where supported)
-	void copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+	// Replace category contents with copied links via the slam_inventory_folder
+	// command (single inventory operation where supported)
+	void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
 						   bool include_folder_links, LLPointer<LLInventoryCallback> cb);
 	
 	// Copy all items and the src category itself.
-- 
cgit v1.2.3


From fd2893e23d002124c49416b7e7a497a1105d2fc4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 26 Jun 2013 12:19:38 -0400
Subject: SH-4305 WIP - cleanup

---
 indra/newview/llappearancemgr.cpp    | 20 ----------------
 indra/newview/llappearancemgr.h      | 13 +----------
 indra/newview/llinventorybridge.cpp  | 44 ------------------------------------
 indra/newview/llviewerfoldertype.cpp |  6 +----
 4 files changed, 2 insertions(+), 81 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 5f061ca290..9c10c20cfe 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1821,25 +1821,6 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 
 	// Will link all the above items.
 	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-#if 0
-	linkAll(cof,all_items,link_waiter);
-
-	// Add link to outfit if category is an outfit. 
-	if (!append)
-	{
-		createBaseOutfitLink(category, link_waiter);
-	}
-
-	// Remove current COF contents.  Have to do this after creating
-	// the link_waiter so links can be followed for any items that get
-	// carried over (e.g. keeping old shape if the new outfit does not
-	// contain one)
-
-	// even in the non-append case, createBaseOutfitLink() already
-	// deletes the existing link, don't need to do it again here.
-	bool keep_outfit_links = true;
-	remove_folder_contents(cof, keep_outfit_links, link_waiter);
-#else
 	LLSD contents = LLSD::emptyArray();
 	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
 		 it != all_items.end(); ++it)
@@ -1868,7 +1849,6 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 		dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents);
 	}
 	slam_inventory_folder(getCOF(), contents, link_waiter);
-#endif
 
 	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
 }
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index ddef3b4a9b..4b633ee9bd 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -73,11 +73,6 @@ public:
 	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
 	S32 getActiveCopyOperations() const;
-
-	// Replace category contents with copied links via the slam_inventory_folder
-	// command (single inventory operation where supported)
-	void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
-						   bool include_folder_links, LLPointer<LLInventoryCallback> cb);
 	
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
@@ -191,9 +186,7 @@ public:
 	void removeItemFromAvatar(const LLUUID& item_id);
 
 
-	void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
-	void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel);
-	void makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel = true);
+	void makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);
 
 	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
 
@@ -306,10 +299,6 @@ private:
 	LLUUID mItemID;
 };
 
-class 
-
-#define SUPPORT_ENSEMBLES 0
-
 LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
 
 // Invoke a given callable after category contents are fully fetched.
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 89c56ab82c..09a96c82b5 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2436,29 +2436,6 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 						LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
 					}
 				}
-				else
-				{
-#if SUPPORT_ENSEMBLES
-					// BAP - should skip if dup.
-					if (move_is_into_current_outfit)
-					{
-						LLAppearanceMgr::instance().addEnsembleLink(inv_cat);
-					}
-					else
-					{
-						LLPointer<LLInventoryCallback> cb = NULL;
-						const std::string empty_description = "";
-						link_inventory_item(
-							gAgent.getID(),
-							cat_id,
-							mUUID,
-							inv_cat->getName(),
-							empty_description,
-							LLAssetType::AT_LINK_FOLDER,
-							cb);
-					}
-#endif
-				}
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
@@ -2850,17 +2827,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		modifyOutfit(FALSE);
 		return;
 	}
-#if SUPPORT_ENSEMBLES
-	else if ("wearasensemble" == action)
-	{
-		LLInventoryModel* model = getInventoryModel();
-		if(!model) return;
-		LLViewerInventoryCategory* cat = getCategory();
-		if(!cat) return;
-		LLAppearanceMgr::instance().addEnsembleLink(cat,true);
-		return;
-	}
-#endif
 	else if ("addtooutfit" == action)
 	{
 		modifyOutfit(TRUE);
@@ -3382,16 +3348,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 				items.push_back(std::string("New Clothes"));
 				items.push_back(std::string("New Body Parts"));
 			}
-#if SUPPORT_ENSEMBLES
-			// Changing folder types is an unfinished unsupported feature
-			// and can lead to unexpected behavior if enabled.
-			items.push_back(std::string("Change Type"));
-			const LLViewerInventoryCategory *cat = getCategory();
-			if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
-			{
-				disabled_items.push_back(std::string("Change Type"));
-			}
-#endif
 			getClipboardEntries(false, items, disabled_items, flags);
 		}
 		else
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index a179b61cff..4e028d2163 100755
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -139,14 +139,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 		 
 	addEntry(LLFolderType::FT_NONE, 				new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE,     false, "default"));
 
-#if SUPPORT_ENSEMBLES
-	initEnsemblesFromFile();
-#else
 	for (U32 type = (U32)LLFolderType::FT_ENSEMBLE_START; type <= (U32)LLFolderType::FT_ENSEMBLE_END; ++type)
 	{
 		addEntry((LLFolderType::EType)type, 		new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE,     false));
-	}	
-#endif
+	}
 }
 
 bool LLViewerFolderDictionary::initEnsemblesFromFile()
-- 
cgit v1.2.3


From 1f133213b9d7645169db84d0e26ec166163ba564 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 26 Jun 2013 15:44:28 -0400
Subject: SH-4300 WIP - removed unused update_base_outfit stuff in
 updateClothingOrderingInfo()

---
 indra/newview/llappearancemgr.cpp | 29 ++++++++---------------------
 indra/newview/llappearancemgr.h   | 18 +++++++++++-------
 2 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 9c10c20cfe..82d12ae60c 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -435,13 +435,11 @@ private:
 
 S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
 
-LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
-														 bool enforce_item_restrictions,
+LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions,
 														 bool enforce_ordering,
 														 nullary_func_t post_update_func 
 	):
 	mFireCount(0),
-	mUpdateBaseOrder(update_base_outfit_ordering),
 	mEnforceItemRestrictions(enforce_item_restrictions),
 	mEnforceOrdering(enforce_ordering),
 	mPostUpdateFunc(post_update_func)
@@ -468,8 +466,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 
 		selfStopPhase("update_appearance_on_destroy");
 
-		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder,
-															mEnforceItemRestrictions,
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(mEnforceItemRestrictions,
 															mEnforceOrdering,
 															mPostUpdateFunc);
 	}
@@ -503,7 +500,7 @@ LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOn
 	if (!LLApp::isExiting())
 	{
 		LLAppearanceMgr::instance().updateAppearanceFromCOF(
-			false,true,true,
+			true,true,
 			boost::bind(edit_wearable_and_customize_avatar, mItemID));
 	}
 }
@@ -2015,8 +2012,7 @@ void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback>
 	}
 }
 
-void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
-											  bool enforce_item_restrictions,
+void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 											  bool enforce_ordering,
 											  nullary_func_t post_update_func)
 {
@@ -2036,7 +2032,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 		// enforce_item_restrictions to false so we don't get
 		// caught in a perpetual loop.
 		LLPointer<LLInventoryCallback> cb(
-			new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering, post_update_func));
+			new LLUpdateAppearanceOnDestroy(false, enforce_ordering, post_update_func));
 		enforceCOFItemRestrictions(cb);
 		return;
 	}
@@ -2050,8 +2046,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 		// to wait for the update callbacks, then (finally!) call
 		// updateAppearanceFromCOF() with no additional COF munging needed.
 		LLPointer<LLInventoryCallback> cb(
-			new LLUpdateAppearanceOnDestroy(false, false, false, post_update_func));
-		updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb);
+			new LLUpdateAppearanceOnDestroy(false, false, post_update_func));
+		updateClothingOrderingInfo(LLUUID::null, cb);
 		return;
 	}
 
@@ -2938,20 +2934,11 @@ struct WearablesOrderComparator
 };
 
 void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
-												 bool update_base_outfit_ordering,
 												 LLPointer<LLInventoryCallback> cb)
 {
 	if (cat_id.isNull())
 	{
 		cat_id = getCOF();
-		if (update_base_outfit_ordering)
-		{
-			const LLUUID base_outfit_id = getBaseOutfitUUID();
-			if (base_outfit_id.notNull())
-			{
-				updateClothingOrderingInfo(base_outfit_id,false,cb);
-			}
-		}
 	}
 
 	// COF is processed if cat_id is not specified
@@ -3400,7 +3387,7 @@ void LLAppearanceMgr::onOutfitFolderCreated(const LLUUID& folder_id, bool show_p
 	LLPointer<LLInventoryCallback> cb =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func,
 										 boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,folder_id,show_panel));
-	updateClothingOrderingInfo(LLUUID::null, false, cb);
+	updateClothingOrderingInfo(LLUUID::null, cb);
 }
 
 void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 4b633ee9bd..59dc598ee5 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -49,8 +49,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 public:
 	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
 
-	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false,
-								 bool enforce_item_restrictions = true,
+	void updateAppearanceFromCOF(bool enforce_item_restrictions = true,
 								 bool enforce_ordering = true,
 								 nullary_func_t post_update_func = no_op);
 	bool needToSaveCOF();
@@ -73,7 +72,12 @@ public:
 	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
 	S32 getActiveCopyOperations() const;
-	
+
+	// Replace category contents with copied links via the slam_inventory_folder
+	// command (single inventory operation where supported)
+	void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+						   bool include_folder_links, LLPointer<LLInventoryCallback> cb);
+ 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
 							 LLPointer<LLInventoryCallback> cb);
@@ -186,6 +190,9 @@ public:
 	void removeItemFromAvatar(const LLUUID& item_id);
 
 
+	void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
+	void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel);
+
 	void makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);
 
 	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
@@ -198,7 +205,6 @@ public:
 	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
 	// COF is processed if cat_id is not specified
 	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
-									bool update_base_outfit_ordering = false,
 									LLPointer<LLInventoryCallback> cb = NULL);
 
 	bool isOutfitLocked() { return mOutfitLocked; }
@@ -271,8 +277,7 @@ public:
 class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 {
 public:
-	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false,
-								bool enforce_item_restrictions = true,
+	LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions = true,
 								bool enforce_ordering = true,
 								nullary_func_t post_update_func = no_op);
 	virtual ~LLUpdateAppearanceOnDestroy();
@@ -280,7 +285,6 @@ public:
 
 private:
 	U32 mFireCount;
-	bool mUpdateBaseOrder;
 	bool mEnforceItemRestrictions;
 	bool mEnforceOrdering;
 	nullary_func_t mPostUpdateFunc;
-- 
cgit v1.2.3


From 5be12cf0be170c5d886694db11605d197e418190 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 26 Jun 2013 17:40:41 -0400
Subject: SH-4300 WIP - set wearable ordering desc fields in slammer during
 updateCOF(), should need to go item-by-item fairly rarely.

---
 indra/newview/llappearancemgr.cpp | 78 +++++++++++++++++++++++++++++----------
 indra/newview/llappearancemgr.h   |  4 ++
 2 files changed, 63 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 82d12ae60c..5322646629 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1816,16 +1816,35 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	all_items += obj_items;
 	all_items += gest_items;
 
+	// Find any wearables that need description set to enforce ordering.
+	desc_map_t desc_map;
+	getWearableOrderingDescUpdates(wear_items, desc_map);
+
 	// Will link all the above items.
 	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
 	LLSD contents = LLSD::emptyArray();
+
 	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
 		 it != all_items.end(); ++it)
 	{
 		LLSD item_contents;
 		LLInventoryItem *item = *it;
+
+		std::string desc;
+		desc_map_t::const_iterator desc_iter = desc_map.find(item->getUUID());
+		if (desc_iter != desc_map.end())
+		{
+			desc = desc_iter->second;
+			LL_DEBUGS("Avatar") << item->getName() << " overriding desc to: " << desc
+								<< " (was: " << item->getActualDescription() << ")" << llendl;
+		}
+		else
+		{
+			desc = item->getActualDescription();
+		}
+
 		item_contents["name"] = item->getName();
-		item_contents["desc"] = item->getActualDescription();
+		item_contents["desc"] = desc;
 		item_contents["linked_id"] = item->getLinkedUUID();
 		item_contents["type"] = LLAssetType::AT_LINK; 
 		contents.append(item_contents);
@@ -2933,45 +2952,66 @@ struct WearablesOrderComparator
 	U32 mControlSize;
 };
 
-void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
-												 LLPointer<LLInventoryCallback> cb)
+void LLAppearanceMgr::getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items,
+													 desc_map_t& desc_map)
 {
-	if (cat_id.isNull())
-	{
-		cat_id = getCOF();
-	}
-
-	// COF is processed if cat_id is not specified
-	LLInventoryModel::item_array_t wear_items;
-	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
-
 	wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);
 	divvyWearablesByType(wear_items, items_by_type);
 
 	for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++)
 	{
-		
 		U32 size = items_by_type[type].size();
 		if (!size) continue;
-
+		
 		//sinking down invalid items which need reordering
 		std::sort(items_by_type[type].begin(), items_by_type[type].end(), WearablesOrderComparator((LLWearableType::EType) type));
-
+		
 		//requesting updates only for those links which don't have "valid" descriptions
 		for (U32 i = 0; i < size; i++)
 		{
 			LLViewerInventoryItem* item = items_by_type[type][i];
 			if (!item) continue;
-
+			
 			std::string new_order_str = build_order_string((LLWearableType::EType)type, i);
 			if (new_order_str == item->getActualDescription()) continue;
+			
+			LL_DEBUGS("Avatar") << item->getName() << " need to update desc to: " << new_order_str
+								<< " (from: " << item->getActualDescription() << ")" << llendl;
 
-			LLSD updates;
-			updates["desc"] = new_order_str;
-			update_inventory_item(item->getUUID(),updates,cb);
+			desc_map[item->getUUID()] = new_order_str;
 		}
 	}
 }
+void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
+												 LLPointer<LLInventoryCallback> cb)
+{
+	// COF is processed if cat_id is not specified
+	if (cat_id.isNull())
+	{
+		cat_id = getCOF();
+	}
+
+	LLInventoryModel::item_array_t wear_items;
+	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
+
+	// Identify items for which desc needs to change.
+	desc_map_t desc_map;
+	getWearableOrderingDescUpdates(wear_items, desc_map);
+
+	for (desc_map_t::const_iterator it = desc_map.begin();
+		 it != desc_map.end(); ++it)
+	{
+		LLSD updates;
+		const LLUUID& item_id = it->first;
+		const std::string& new_order_str = it->second;
+		LLViewerInventoryItem *item = gInventory.getItem(item_id);
+		LL_DEBUGS("Avatar") << item->getName() << " updating desc to: " << new_order_str
+			<< " (was: " << item->getActualDescription() << ")" << llendl;
+		updates["desc"] = new_order_str;
+		update_inventory_item(item_id,updates,cb);
+	}
+		
+}
 
 class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
 {
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 59dc598ee5..3293212719 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -202,6 +202,10 @@ public:
 	//Divvy items into arrays by wearable type
 	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
 
+	typedef std::map<LLUUID,std::string> desc_map_t;
+
+	void getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items, desc_map_t& desc_map);
+
 	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
 	// COF is processed if cat_id is not specified
 	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
-- 
cgit v1.2.3


From ec00f7f14fbf16992b71ddd54e583ba07fdfd523 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Wed, 26 Jun 2013 17:57:10 -0400
Subject: SH-4226 FIX wearing petite outfit gives appearance responder errors

Requesting appearance updates on updateGeometry for the avatar was spamming
the back-end and causing the throttling mechanism to get hit. Removing that
caused a re-introduction of SH-4109, so added a callback to link creation
in the COF for attachments to request an appearance update.

This should cause us to request an appearance update once per attachment
attached, where before we were seeing up to 8 redundant requests.
---
 indra/newview/llappearancemgr.cpp |  3 ++-
 indra/newview/llvovolume.cpp      | 15 ++-------------
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index cb32bf9c40..57a836c070 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3578,7 +3578,8 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
 		   // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF.
 		   // it will trigger gAgentWariables.notifyLoadingFinished()
 		   // But it is not acceptable solution. See EXT-7777
-		   LLAppearanceMgr::addCOFItemLink(item_id);  // Add COF link for item.
+		   LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy();
+		   LLAppearanceMgr::addCOFItemLink(item_id, cb);  // Add COF link for item.
 	   }
 	   else
 	   {
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index b7f7a11a15..8730ef66bb 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -76,7 +76,6 @@
 #include "llviewershadermgr.h"
 #include "llvoavatar.h"
 #include "llvocache.h"
-#include "llappearancemgr.h"
 
 const S32 MIN_QUIET_FRAMES_COALESCE = 30;
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
@@ -4240,8 +4239,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	{
 		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST);
 
-		bool requiredAppearanceUpdate = false;
-
 		//get all the faces into a list
 		for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
 		{
@@ -4340,7 +4337,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								const int jointCnt = pSkinData->mJointNames.size();
 								const F32 pelvisZOffset = pSkinData->mPelvisOffset;
 								bool fullRig = (jointCnt>=20) ? true : false;
-								requiredAppearanceUpdate = true;
 								if ( fullRig )
 								{
 									for ( int i=0; i<jointCnt; ++i )
@@ -4365,14 +4361,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 													pelvisGotSet = true;											
 												}										
 											}										
-										}									
+										}
 									}
 								}							
 							}
 						}
-					}					
-					
-
+					}
 					//If we've set the pelvis to a new position we need to also rebuild some information that the
 					//viewer does at launch (e.g. body size etc.)
 					if ( pelvisGotSet )
@@ -4612,11 +4606,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 				drawablep->clearState(LLDrawable::RIGGED);
 			}
 		}
-
-		if ( requiredAppearanceUpdate && gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion() ) 
-		{ 
-			LLAppearanceMgr::instance().requestServerAppearanceUpdate();
-		}
 	}
 
 	group->mBufferUsage = useage;
-- 
cgit v1.2.3


From 4c75140008527ac9e5260978f4a256d84711644b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 27 Jun 2013 11:43:06 -0400
Subject: SH-4300 WIP - added order validation

---
 indra/newview/llappearancemgr.cpp | 38 ++++++++++++++++++++++++++++++++++----
 indra/newview/llappearancemgr.h   |  2 ++
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 5322646629..98909c258a 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1821,7 +1821,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	getWearableOrderingDescUpdates(wear_items, desc_map);
 
 	// Will link all the above items.
-	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+	// link_waiter enforce flags are false because we've already fixed everything up in updateCOF().
+	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false);
 	LLSD contents = LLSD::emptyArray();
 
 	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
@@ -2070,6 +2071,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 		return;
 	}
 
+	llassert(validateClothingOrderingInfo());
+
 	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
 	selfStartPhase("update_appearance_from_cof");
 
@@ -2975,13 +2978,40 @@ void LLAppearanceMgr::getWearableOrderingDescUpdates(LLInventoryModel::item_arra
 			std::string new_order_str = build_order_string((LLWearableType::EType)type, i);
 			if (new_order_str == item->getActualDescription()) continue;
 			
-			LL_DEBUGS("Avatar") << item->getName() << " need to update desc to: " << new_order_str
-								<< " (from: " << item->getActualDescription() << ")" << llendl;
-
 			desc_map[item->getUUID()] = new_order_str;
 		}
 	}
 }
+
+bool LLAppearanceMgr::validateClothingOrderingInfo(LLUUID cat_id)
+{
+	// COF is processed if cat_id is not specified
+	if (cat_id.isNull())
+	{
+		cat_id = getCOF();
+	}
+
+	LLInventoryModel::item_array_t wear_items;
+	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
+
+	// Identify items for which desc needs to change.
+	desc_map_t desc_map;
+	getWearableOrderingDescUpdates(wear_items, desc_map);
+
+	for (desc_map_t::const_iterator it = desc_map.begin();
+		 it != desc_map.end(); ++it)
+	{
+		const LLUUID& item_id = it->first;
+		const std::string& new_order_str = it->second;
+		LLViewerInventoryItem *item = gInventory.getItem(item_id);
+		llwarns << "Order validation fails: " << item->getName()
+				<< " needs to update desc to: " << new_order_str
+				<< " (from: " << item->getActualDescription() << ")" << llendl;
+	}
+	
+	return desc_map.size() == 0;
+}
+
 void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
 												 LLPointer<LLInventoryCallback> cb)
 {
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 3293212719..84a0afbb40 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -208,6 +208,8 @@ public:
 
 	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
 	// COF is processed if cat_id is not specified
+	bool validateClothingOrderingInfo(LLUUID cat_id = LLUUID::null);
+	
 	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
 									LLPointer<LLInventoryCallback> cb = NULL);
 
-- 
cgit v1.2.3


From 8090388a27dc7dfe9b9bb712db91227ecfea2116 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 27 Jun 2013 14:41:06 -0400
Subject: SH-4300 WIP - removed outfit autopopulate

---
 indra/newview/llagentwearables.cpp      |  18 --
 indra/newview/llagentwearables.h        |   6 -
 indra/newview/llagentwearablesfetch.cpp | 394 --------------------------------
 indra/newview/llagentwearablesfetch.h   |  41 ----
 indra/newview/llappearancemgr.cpp       |  21 --
 indra/newview/llappearancemgr.h         |   3 -
 6 files changed, 483 deletions(-)
 mode change 100644 => 100755 indra/newview/llagentwearables.cpp

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
old mode 100644
new mode 100755
index 80c8364223..8e60bf1c6d
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1861,24 +1861,6 @@ void LLAgentWearables::updateServer()
 	gAgent.sendAgentSetAppearance();
 }
 
-void LLAgentWearables::populateMyOutfitsFolder(void)
-{	
-	llinfos << "starting outfit population" << llendl;
-
-	const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(my_outfits_id);
-	outfits->mMyOutfitsID = my_outfits_id;
-	
-	// Get the complete information on the items in the inventory and 
-	// setup an observer that will wait for that to happen.
-	gInventory.addObserver(outfits);
-	outfits->startFetch();
-	if (outfits->isFinished())
-	{
-		outfits->done();
-	}
-}
-
 boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)
 {
 	return mLoadingStartedSignal.connect(cb);
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 0adf545aab..b0ac988341 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -171,12 +171,6 @@ protected:
 	//--------------------------------------------------------------------
 	// Outfits
 	//--------------------------------------------------------------------
-public:
-	
-	// Should only be called if we *know* we've never done so before, since users may
-	// not want the Library outfits to stay in their quick outfit selector and can delete them.
-	void			populateMyOutfitsFolder();
-
 private:
 	void			makeNewOutfitDone(S32 type, U32 index); 
 
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 2d2d730396..014c610a5c 100755
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -35,46 +35,6 @@
 #include "llvoavatarself.h"
 
 
-void order_my_outfits_cb()
-{
-	if (!LLApp::isRunning())
-	{
-		llwarns << "called during shutdown, skipping" << llendl;
-		return;
-	}
-		
-	const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	if (my_outfits_id.isNull()) return;
-
-	LLInventoryModel::cat_array_t* cats;
-	LLInventoryModel::item_array_t* items;
-	gInventory.getDirectDescendentsOf(my_outfits_id, cats, items);
-	if (!cats) return;
-
-	//My Outfits should at least contain saved initial outfit and one another outfit
-	if (cats->size() < 2)
-	{
-		llwarning("My Outfits category was not populated properly", 0);
-		return;
-	}
-
-	llinfos << "Starting updating My Outfits with wearables ordering information" << llendl;
-
-	for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin();
-		 outfit_iter != cats->end(); ++outfit_iter)
-	{
-		const LLUUID& cat_id = (*outfit_iter)->getUUID();
-		if (cat_id.isNull()) continue;
-
-		// saved initial outfit already contains wearables ordering information
-		if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue;
-
-		LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id);
-	}
-
-	llinfos << "Finished updating My Outfits with wearables ordering information" << llendl;
-}
-
 LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
 	LLInventoryFetchDescendentsObserver(cof_id)
 {
@@ -244,357 +204,3 @@ void LLInitialWearablesFetch::processWearablesMessage()
 	}
 }
 
-LLLibraryOutfitsFetch::LLLibraryOutfitsFetch(const LLUUID& my_outfits_id) : 
-	LLInventoryFetchDescendentsObserver(my_outfits_id),
-	mCurrFetchStep(LOFS_FOLDER), 
-	mOutfitsPopulated(false) 
-{
-	llinfos << "created" << llendl;
-
-	mMyOutfitsID = LLUUID::null;
-	mClothingID = LLUUID::null;
-	mLibraryClothingID = LLUUID::null;
-	mImportedClothingID = LLUUID::null;
-	mImportedClothingName = "Imported Library Clothing";
-}
-
-LLLibraryOutfitsFetch::~LLLibraryOutfitsFetch()
-{
-	llinfos << "destroyed" << llendl;
-}
-
-void LLLibraryOutfitsFetch::done()
-{
-	llinfos << "start" << llendl;
-
-	// Delay this until idle() routine, since it's a heavy operation and
-	// we also can't have it run within notifyObservers.
-	doOnIdleOneTime(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this));
-	gInventory.removeObserver(this); // Prevent doOnIdleOneTime from being added twice.
-}
-
-void LLLibraryOutfitsFetch::doneIdle()
-{
-	llinfos << "start" << llendl;
-
-	gInventory.addObserver(this); // Add this back in since it was taken out during ::done()
-	
-	switch (mCurrFetchStep)
-	{
-		case LOFS_FOLDER:
-			folderDone();
-			mCurrFetchStep = LOFS_OUTFITS;
-			break;
-		case LOFS_OUTFITS:
-			outfitsDone();
-			mCurrFetchStep = LOFS_LIBRARY;
-			break;
-		case LOFS_LIBRARY:
-			libraryDone();
-			mCurrFetchStep = LOFS_IMPORTED;
-			break;
-		case LOFS_IMPORTED:
-			importedFolderDone();
-			mCurrFetchStep = LOFS_CONTENTS;
-			break;
-		case LOFS_CONTENTS:
-			contentsDone();
-			break;
-		default:
-			llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl;
-			mOutfitsPopulated = TRUE;
-			break;
-	}
-
-	// We're completely done.  Cleanup.
-	if (mOutfitsPopulated)
-	{
-		gInventory.removeObserver(this);
-		delete this;
-		return;
-	}
-}
-
-void LLLibraryOutfitsFetch::folderDone()
-{
-	llinfos << "start" << llendl;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
-	// Early out if we already have items in My Outfits
-	// except the case when My Outfits contains just initial outfit
-	if (cat_array.count() > 1)
-	{
-		mOutfitsPopulated = true;
-		return;
-	}
-
-	mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
-	mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);
-
-	// If Library->Clothing->Initial Outfits exists, use that.
-	LLNameCategoryCollector matchFolderFunctor("Initial Outfits");
-	cat_array.clear();
-	gInventory.collectDescendentsIf(mLibraryClothingID,
-									cat_array, wearable_array, 
-									LLInventoryModel::EXCLUDE_TRASH,
-									matchFolderFunctor);
-	if (cat_array.count() > 0)
-	{
-		const LLViewerInventoryCategory *cat = cat_array.get(0);
-		mLibraryClothingID = cat->getUUID();
-	}
-
-	mComplete.clear();
-	
-	// Get the complete information on the items in the inventory.
-	uuid_vec_t folders;
-	folders.push_back(mClothingID);
-	folders.push_back(mLibraryClothingID);
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-void LLLibraryOutfitsFetch::outfitsDone()
-{
-	llinfos << "start" << llendl;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	uuid_vec_t folders;
-	
-	// Collect the contents of the Library's Clothing folder
-	gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
-	llassert(cat_array.count() > 0);
-	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
-		 iter != cat_array.end();
-		 ++iter)
-	{
-		const LLViewerInventoryCategory *cat = iter->get();
-		
-		// Get the names and id's of every outfit in the library, skip "Ruth"
-		// because it's a low quality legacy outfit
-		if (cat->getName() != "Ruth")
-		{
-			// Get the name of every outfit in the library 
-			folders.push_back(cat->getUUID());
-			mLibraryClothingFolders.push_back(cat->getUUID());
-		}
-	}
-	cat_array.clear();
-	wearable_array.clear();
-
-	// Check if you already have an "Imported Library Clothing" folder
-	LLNameCategoryCollector matchFolderFunctor(mImportedClothingName);
-	gInventory.collectDescendentsIf(mClothingID, 
-									cat_array, wearable_array, 
-									LLInventoryModel::EXCLUDE_TRASH,
-									matchFolderFunctor);
-	if (cat_array.size() > 0)
-	{
-		const LLViewerInventoryCategory *cat = cat_array.get(0);
-		mImportedClothingID = cat->getUUID();
-	}
-	
-	mComplete.clear();
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-class LLLibraryOutfitsCopyDone: public LLInventoryCallback
-{
-public:
-	LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher):
-	mFireCount(0), mLibraryOutfitsFetcher(fetcher)
-	{
-	}
-	
-	virtual ~LLLibraryOutfitsCopyDone()
-	{
-		if (!LLApp::isExiting() && mLibraryOutfitsFetcher)
-		{
-			gInventory.addObserver(mLibraryOutfitsFetcher);
-			mLibraryOutfitsFetcher->done();
-		}
-	}
-	
-	/* virtual */ void fire(const LLUUID& inv_item)
-	{
-		mFireCount++;
-	}
-private:
-	U32 mFireCount;
-	LLLibraryOutfitsFetch * mLibraryOutfitsFetcher;
-};
-
-// Copy the clothing folders from the library into the imported clothing folder
-void LLLibraryOutfitsFetch::libraryDone()
-{
-	llinfos << "start" << llendl;
-
-	if (mImportedClothingID != LLUUID::null)
-	{
-		// Skip straight to fetching the contents of the imported folder
-		importedFolderFetch();
-		return;
-	}
-
-	// Remove observer; next autopopulation step will be triggered externally by LLLibraryOutfitsCopyDone.
-	gInventory.removeObserver(this);
-	
-	LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this);
-	mImportedClothingID = gInventory.createNewCategory(mClothingID,
-													   LLFolderType::FT_NONE,
-													   mImportedClothingName);
-	// Copy each folder from library into clothing unless it already exists.
-	for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
-		 iter != mLibraryClothingFolders.end();
-		 ++iter)
-	{
-		const LLUUID& src_folder_id = (*iter); // Library clothing folder ID
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id);
-		if (!cat)
-		{
-			llwarns << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << llendl;
-			continue;
-		}
-		
-		if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id))
-		{
-			llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl;
-			continue;
-		}
-		
-		// Don't copy the category if it already exists.
-		LLNameCategoryCollector matchFolderFunctor(cat->getName());
-		LLInventoryModel::cat_array_t cat_array;
-		LLInventoryModel::item_array_t wearable_array;
-		gInventory.collectDescendentsIf(mImportedClothingID, 
-										cat_array, wearable_array, 
-										LLInventoryModel::EXCLUDE_TRASH,
-										matchFolderFunctor);
-		if (cat_array.size() > 0)
-		{
-			continue;
-		}
-
-		LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID,
-															LLFolderType::FT_NONE,
-															cat->getName());
-		LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter);
-	}
-}
-
-void LLLibraryOutfitsFetch::importedFolderFetch()
-{
-	llinfos << "start" << llendl;
-
-	// Fetch the contents of the Imported Clothing Folder
-	uuid_vec_t folders;
-	folders.push_back(mImportedClothingID);
-	
-	mComplete.clear();
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-void LLLibraryOutfitsFetch::importedFolderDone()
-{
-	llinfos << "start" << llendl;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	uuid_vec_t folders;
-	
-	// Collect the contents of the Imported Clothing folder
-	gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, 
-								  LLInventoryModel::EXCLUDE_TRASH);
-	
-	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
-		 iter != cat_array.end();
-		 ++iter)
-	{
-		const LLViewerInventoryCategory *cat = iter->get();
-		
-		// Get the name of every imported outfit
-		folders.push_back(cat->getUUID());
-		mImportedClothingFolders.push_back(cat->getUUID());
-	}
-	
-	mComplete.clear();
-	setFetchIDs(folders);
-	startFetch();
-	if (isFinished())
-	{
-		done();
-	}
-}
-
-void LLLibraryOutfitsFetch::contentsDone()
-{		
-	llinfos << "start" << llendl;
-
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	
-	LLPointer<LLInventoryCallback> order_myoutfits_on_destroy = new LLBoostFuncInventoryCallback(no_op_inventory_func, order_my_outfits_cb);
-
-	for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin();
-		 folder_iter != mImportedClothingFolders.end();
-		 ++folder_iter)
-	{
-		const LLUUID &folder_id = (*folder_iter);
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
-		if (!cat)
-		{
-			llwarns << "Library folder import for uuid:" << folder_id << " failed to find folder." << llendl;
-			continue;
-		}
-
-		//initial outfit should be already in My Outfits
-		if (cat->getName() == LLStartUp::getInitialOutfitName()) continue;
-		
-		// First, make a folder in the My Outfits directory.
-		LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName());
-		
-		cat_array.clear();
-		wearable_array.clear();
-		// Collect the contents of each imported clothing folder, so we can create new outfit links for it
-		gInventory.collectDescendents(folder_id, cat_array, wearable_array, 
-									  LLInventoryModel::EXCLUDE_TRASH);
-		
-		for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
-			 wearable_iter != wearable_array.end();
-			 ++wearable_iter)
-		{
-			const LLViewerInventoryItem *item = wearable_iter->get();
-			link_inventory_item(gAgent.getID(),
-								item->getLinkedUUID(),
-								new_outfit_folder_id,
-								item->getName(),
-								item->getDescription(),
-								LLAssetType::AT_LINK,
-								order_myoutfits_on_destroy);
-		}
-	}
-
-	mOutfitsPopulated = true;
-}
-
diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h
index bedc445c0e..81b03110ae 100755
--- a/indra/newview/llagentwearablesfetch.h
+++ b/indra/newview/llagentwearablesfetch.h
@@ -70,45 +70,4 @@ private:
 	initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
 };
 
-//--------------------------------------------------------------------
-// InitialWearablesFetch
-// 
-// This grabs outfits from the Library and copies those over to the user's
-// outfits folder, typically during first-ever login.
-//--------------------------------------------------------------------
-class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver
-{
-public:
-	enum ELibraryOutfitFetchStep
-	{
-		LOFS_FOLDER = 0,
-		LOFS_OUTFITS,
-		LOFS_LIBRARY,
-		LOFS_IMPORTED,
-		LOFS_CONTENTS
-	};
-
-	LLLibraryOutfitsFetch(const LLUUID& my_outfits_id);
-	~LLLibraryOutfitsFetch();
-
-	virtual void done();
-	void doneIdle();
-	LLUUID mMyOutfitsID;
-	void importedFolderFetch();
-protected:
-	void folderDone();
-	void outfitsDone();
-	void libraryDone();
-	void importedFolderDone();
-	void contentsDone();
-	enum ELibraryOutfitFetchStep mCurrFetchStep;
-	uuid_vec_t mLibraryClothingFolders;
-	uuid_vec_t mImportedClothingFolders;
-	bool mOutfitsPopulated;
-	LLUUID mClothingID;
-	LLUUID mLibraryClothingID;
-	LLUUID mImportedClothingID;
-	std::string mImportedClothingName;
-};
-
 #endif // LL_AGENTWEARABLESINITIALFETCH_H
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 98909c258a..28099f59f3 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2815,23 +2815,6 @@ void LLAppearanceMgr::copyLibraryGestures()
 	}
 }
 
-void LLAppearanceMgr::autopopulateOutfits()
-{
-	// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
-	// then auto-populate outfits from the library into the My Outfits folder.
-
-	LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL;
-
-	static bool check_populate_my_outfits = true;
-	if (check_populate_my_outfits && 
-		(LLInventoryModel::getIsFirstTimeInViewer2() 
-		 || gSavedSettings.getBOOL("MyOutfitsAutofill")))
-	{
-		gAgentWearables.populateMyOutfitsFolder();
-	}
-	check_populate_my_outfits = false;
-}
-
 // Handler for anything that's deferred until avatar de-clouds.
 void LLAppearanceMgr::onFirstFullyVisible()
 {
@@ -2839,10 +2822,6 @@ void LLAppearanceMgr::onFirstFullyVisible()
 	gAgentAvatarp->reportAvatarRezTime();
 	gAgentAvatarp->debugAvatarVisible();
 
-	// The auto-populate is failing at the point of generating outfits
-	// folders, so don't do the library copy until that is resolved.
-	// autopopulateOutfits();
-
 	// If this is the first time we've ever logged in,
 	// then copy default gestures from the library.
 	if (gAgent.isFirstLogin()) {
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 84a0afbb40..b2917cced4 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -173,9 +173,6 @@ public:
 	// Called when self avatar is first fully visible.
 	void onFirstFullyVisible();
 
-	// Create initial outfits from library.
-	void autopopulateOutfits();
-
 	// Copy initial gestures from library.
 	void copyLibraryGestures();
 	
-- 
cgit v1.2.3


From 47fb1fc67b9cc1d3a31359da871cb6477701173b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 27 Jun 2013 15:30:14 -0400
Subject: SH-4300 WIP - added callback for a non-callback case of
 updateClothingOrderingInfo. Also removed some wrong code for drag-and-drop
 corresponding to a case that's not allowed anyway.

---
 indra/newview/llappearancemgr.cpp   | 30 ++++++++++++++++++++----------
 indra/newview/llinventorybridge.cpp | 25 ++++++-------------------
 2 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 28099f59f3..f427214dbb 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2839,6 +2839,22 @@ void appearance_mgr_update_dirty_state()
 	}
 }
 
+void update_base_outfit_after_ordering()
+{
+	LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
+	
+	LLPointer<LLInventoryCallback> dirty_state_updater =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
+
+	//COF contains only links so we copy to the Base Outfit only links
+	const LLUUID base_outfit_id = app_mgr.getBaseOutfitUUID();
+	bool copy_folder_links = false;
+	app_mgr.slamCategoryLinks(app_mgr.getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater);
+
+}
+
+// Save COF changes - update the contents of the current base outfit
+// to match the current COF. Fails if no current base outfit is set.
 bool LLAppearanceMgr::updateBaseOutfit()
 {
 	if (isOutfitLocked())
@@ -2848,23 +2864,17 @@ bool LLAppearanceMgr::updateBaseOutfit()
 		return false;
 	}
 
-
 	setOutfitLocked(true);
 
 	gAgentWearables.notifyLoadingStarted();
 
 	const LLUUID base_outfit_id = getBaseOutfitUUID();
-	LL_DEBUGS("Avatar") << "updating base outfit to " << base_outfit_id << llendl;
 	if (base_outfit_id.isNull()) return false;
+	LL_DEBUGS("Avatar") << "saving cof to base outfit " << base_outfit_id << llendl;
 
-	updateClothingOrderingInfo();
-
-	LLPointer<LLInventoryCallback> dirty_state_updater =
-		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
-
-	//COF contains only links so we copy to the Base Outfit only links
-	bool copy_folder_links = false;
-	slamCategoryLinks(getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater);
+	LLPointer<LLInventoryCallback> cb =
+		new LLBoostFuncInventoryCallback(no_op_inventory_func, update_base_outfit_after_ordering);
+	updateClothingOrderingInfo(LLUUID::null, cb);
 
 	return true;
 }
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 09a96c82b5..cb3f40a5bb 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2416,26 +2416,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 					}
 				}
 			}
-			// if target is an outfit or current outfit folder we use link
-			if (move_is_into_current_outfit || move_is_into_outfit)
+			// if target is current outfit folder we use link
+			if (move_is_into_current_outfit &&
+				inv_cat->getPreferredType() == LLFolderType::FT_NONE)
 			{
-				if (inv_cat->getPreferredType() == LLFolderType::FT_NONE)
-				{
-					if (move_is_into_current_outfit)
-					{
-						// traverse category and add all contents to currently worn.
-						BOOL append = true;
-						LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
-					}
-					else
-					{
-						// Recursively create links in target outfit.
-						LLInventoryModel::cat_array_t cats;
-						LLInventoryModel::item_array_t items;
-						model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
-						LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
-					}
-				}
+				// traverse category and add all contents to currently worn.
+				BOOL append = true;
+				LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
 			}
 			else if (move_is_into_outbox && !move_is_from_outbox)
 			{
-- 
cgit v1.2.3


From cda919cdbf048aef6f4d10ff804c6e2dad495eef Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 27 Jun 2013 15:37:57 -0400
Subject: SH-4300 WIP - comment

---
 indra/newview/llappearancemgr.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index f427214dbb..c162885961 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2874,6 +2874,8 @@ bool LLAppearanceMgr::updateBaseOutfit()
 
 	LLPointer<LLInventoryCallback> cb =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func, update_base_outfit_after_ordering);
+	// Really shouldn't be needed unless there's a race condition -
+	// updateAppearanceFromCOF() already calls updateClothingOrderingInfo.
 	updateClothingOrderingInfo(LLUUID::null, cb);
 
 	return true;
-- 
cgit v1.2.3


From 62a6009fa265cd56c8711300a830446b03532785 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 27 Jun 2013 16:15:47 -0400
Subject: Log slamming calls

---
 indra/newview/llviewerinventory.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 9725ea6456..c934dd991b 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1567,11 +1567,15 @@ void slam_inventory_folder(const LLUUID& folder_id,
 	std::string cap;
 	if (AISCommand::getCap(cap))
 	{
+		LL_DEBUGS("Avatar") << "using AISv3 to slam folder, id " << folder_id
+							<< " new contents: " << ll_pretty_print_sd(contents) << llendl;
 		LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
 		cmd_ptr->run_command();
 	}
 	else // no cap
 	{
+		LL_DEBUGS("Avatar") << "using item-by-item calls to slam folder, id " << folder_id
+							<< " new contents: " << ll_pretty_print_sd(contents) << llendl;
 		for (LLSD::array_const_iterator it = contents.beginArray();
 			 it != contents.endArray();
 			 ++it)
-- 
cgit v1.2.3


From 39b734a00199eb7d24edf06f9c496161819ebde7 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 28 Jun 2013 11:59:03 -0400
Subject: SH-4240 FIX users can set hover height to 0

removing minimum height enforcement, as changes are local-only and would not
be visible by other users in this repro, unless the user explicitly saved
the changes. Since there are many ways to get around the enforcement, and the
enforced minimums won't be visible to other users, its simpler to allow
users to use the full range of the hover slider.

NOTE: this means that a user's avatar can be underground, leading to the
camera pointing up at the sky. this is a known issue.
---
 indra/llappearance/llavatarappearance.h |  2 +-
 indra/newview/llvoavatar.cpp            | 66 ---------------------------------
 indra/newview/llvoavatar.h              |  3 --
 3 files changed, 1 insertion(+), 70 deletions(-)

diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 0a6a236d34..bf13680496 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -137,7 +137,7 @@ public:
 	typedef std::map<std::string, LLJoint*> joint_map_t;
 	joint_map_t			mJointMap;
 	
-	virtual void		computeBodySize();
+	void		computeBodySize();
 
 
 protected:
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 8c20533b4c..2fd26eae80 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5214,72 +5214,6 @@ void LLVOAvatar::updateVisualParams()
 	updateHeadOffset();
 }
 
-/*virtual*/ 
-void LLVOAvatar::computeBodySize()
-{
-	LLAvatarAppearance::computeBodySize();
-
-	// Certain configurations of avatars can force the overall height (with offset) to go negative.
-	// Enforce a constraint to make sure we don't go below 1.1 meters (server-enforced limit)
-	// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
-	const LLViewerObject * last_object = NULL;
-	if (isSelf() && getWearableData() && !LLApp::isQuitting())
-	{
-		// Do not force a hover parameter change while we have pending attachments, which may be mesh-based with 
-		// joint offsets.
-		if (LLAppearanceMgr::instance().getNumAttachmentsInCOF() == getNumAttachments())
-		{
-			LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0);
-			BOOL loaded = TRUE;
-			for (attachment_map_t::const_iterator points_iter = mAttachmentPoints.begin();
-				 points_iter != mAttachmentPoints.end() && loaded;
-				 ++points_iter)
-			{
-				const LLViewerJointAttachment *attachment_pt = (*points_iter).second;
-				if (attachment_pt) 
-				{
-					for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attach_iter = attachment_pt->mAttachedObjects.begin(); attach_iter != attachment_pt->mAttachedObjects.end(); attach_iter++) 
-					{
-						const LLViewerObject* object = (LLViewerObject*)*attach_iter;
-						if (object) 
-						{
-							last_object = object;
-							llwarns << "attachment at point: " << (*points_iter).first << " object exists: " << object->getAttachmentItemID() << llendl;
-							loaded &=!object->isDrawableState(LLDrawable::REBUILD_ALL);
-							if (!loaded && shape && !shape->getVolatile()) 
-							{
-								llwarns << "caught unloaded attachment! skipping enforcement" << llendl;
-							}
-						}
-					}
-				}
-			}
-
-			if (last_object) 
-			{
-				LL_DEBUGS("Avatar") << "scanned at least one object!"  << LL_ENDL;
-			}
-			if (loaded && shape && !shape->getVolatile()) 
-			{
-				F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER);
-				if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f))
-				{
-					hover_value = -(mBodySize.mV[VZ] - 1.1f); // avoid floating point rounding making the above check continue to fail.
-					llassert(mBodySize.mV[VZ] + hover_value >= 1.1f);
-
-					hover_value =  llmin(hover_value, 0.0f); // don't force the hover value to be greater than 0.
-
-					LL_DEBUGS("Avatar") << "changed hover value to: " << hover_value << " from: " << mAvatarOffset.mV[VZ] << LL_ENDL;
-
-					mAvatarOffset.mV[VZ] = hover_value;
-					shape->setVisualParamWeight(AVATAR_HOVER,hover_value, FALSE);
-				}
-			}
-		}
-	}
-}
-
-
 //-----------------------------------------------------------------------------
 // isActive()
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index fad2fd962c..48b5a6e873 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -212,9 +212,6 @@ public:
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
 	virtual void			updateVisualParams();
 
-	/*virtual*/ void		computeBodySize();
-
-
 
 /**                    Inherited
  **                                                                            **
-- 
cgit v1.2.3


From 8f4f7452308d41467b021ae0da821b33f559dd79 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 3 Jul 2013 12:45:56 -0400
Subject: SH-4226 WIP - try to be smarter about when to send appearance update
 requests, removed many redundant calls

---
 indra/newview/llappearancemgr.cpp   | 413 +++++++++++++++++++++---------------
 indra/newview/llappearancemgr.h     |   5 +-
 indra/newview/llhttpretrypolicy.cpp |   5 +
 indra/newview/llhttpretrypolicy.h   |   4 +
 indra/newview/llvoavatar.cpp        |  15 +-
 5 files changed, 270 insertions(+), 172 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 12c8c82af4..485c47b2f7 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3037,158 +3037,274 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
 class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
 {
 	LOG_CLASS(RequestAgentUpdateAppearanceResponder);
+
+	friend class LLAppearanceMgr;
+	
 public:
-	RequestAgentUpdateAppearanceResponder()
-	{
-		bool retry_on_4xx = true;
-		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx);
-	}
+	RequestAgentUpdateAppearanceResponder();
 
-	virtual ~RequestAgentUpdateAppearanceResponder()
-	{
-	}
+	virtual ~RequestAgentUpdateAppearanceResponder();
+
+private:
+	// Called when sendServerAppearanceUpdate called. May or may not
+	// trigger a request depending on various bits of state.
+	void onRequestRequested();
+
+	// Post the actual appearance request to cap.
+	void sendRequest();
+
+	void debugCOF(const LLSD& content);
 
 protected:
 	// Successful completion.
-	/* virtual */ void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		if (content["success"].asBoolean())
-		{
-			//LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
-			if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
-			{
-				dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
-			}
-		}
-		else
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
-		}
-	}
+	/* virtual */ void httpSuccess();
 
 	// Error
-	/*virtual*/ void httpFailure()
+	/*virtual*/ void httpFailure();
+
+	void onFailure();
+	void onSuccess();
+
+	S32 mInFlightCounter;
+	LLTimer mInFlightTimer;
+	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
+};
+
+RequestAgentUpdateAppearanceResponder::RequestAgentUpdateAppearanceResponder()
+{
+	bool retry_on_4xx = true;
+	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx);
+	mInFlightCounter = 0;
+}
+
+RequestAgentUpdateAppearanceResponder::~RequestAgentUpdateAppearanceResponder()
+{
+}
+
+void RequestAgentUpdateAppearanceResponder::onRequestRequested()
+{
+	// If we have already received an update for this or higher cof version, ignore.
+	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
+	S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
+	S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
+	LL_DEBUGS("Avatar") << "cof_version " << cof_version
+						<< " last_rcv " << last_rcv
+						<< " last_req " << last_req
+						<< " in flight " << mInFlightCounter << llendl;
+	if ((mInFlightCounter>0) && (mInFlightTimer.hasExpired()))
+	{
+		LL_WARNS("Avatar") << "in flight timer expired, resetting " << llendl;
+		mInFlightCounter = 0;
+	}
+	if (cof_version < last_rcv)
 	{
-		LL_WARNS("Avatar") << "appearance update request failed, status "
-						   << getStatus() << " reason " << getReason() << LL_ENDL;
+		LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
+							<< " will not request for " << cof_version << llendl;
+		return;
+	}
+	if (mInFlightCounter>0 && last_req >= cof_version)
+	{
+		LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req 
+							<< " will not request for " << cof_version << llendl;
+		return;
+	}
 
-		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
-		{
-			const LLSD& content = getContent();
-			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
-			debugCOF(content);
-		}
-		onFailure();
+	// Actually send the request.
+	LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << llendl;
+	mRetryPolicy->reset();
+	sendRequest();
+}
+	
+void RequestAgentUpdateAppearanceResponder::sendRequest()
+{
+	if (gAgentAvatarp->isEditingAppearance()) 
+	{
+		// don't send out appearance updates if in appearance editing mode
+		return;
 	}
 
-	void onFailure()
+	if (!gAgent.getRegion())
 	{
-		F32 seconds_to_wait;
-		mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
-		if (mRetryPolicy->shouldRetry(seconds_to_wait))
-		{
-			llinfos << "retrying" << llendl;
-			doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate,
-										LLAppearanceMgr::getInstance(),
-										LLHTTPClient::ResponderPtr(this)),
-										seconds_to_wait);
-		}
-		else
+		llwarns << "Region not set, cannot request server appearance update" << llendl;
+		return;
+	}
+	if (gAgent.getRegion()->getCentralBakeVersion()==0)
+	{
+		llwarns << "Region does not support baking" << llendl;
+	}
+	std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");	
+	if (url.empty())
+	{
+		llwarns << "No cap for UpdateAvatarAppearance." << llendl;
+		return;
+	}
+	
+	LLSD body;
+	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
+	if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
+	{
+		body = LLAppearanceMgr::instance().dumpCOF();
+	}
+	else
+	{
+		body["cof_version"] = cof_version;
+		if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
 		{
-			llwarns << "giving up after too many retries" << llendl;
+			body["cof_version"] = cof_version+999;
 		}
-	}	
+	}
+	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl;
+
+	mInFlightCounter++;
+	mInFlightTimer.setTimerExpirySec(30.0);
+	LLHTTPClient::post(url, body, this);
+	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
+	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+}
 
-	void debugCOF(const LLSD& content)
+void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
+{
+	LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
+					   << " ================================= " << llendl;
+	std::set<LLUUID> ais_items, local_items;
+	const LLSD& cof_raw = content["cof_raw"];
+	for (LLSD::array_const_iterator it = cof_raw.beginArray();
+		 it != cof_raw.endArray(); ++it)
 	{
-		LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
-						   << " ================================= " << llendl;
-		std::set<LLUUID> ais_items, local_items;
-		const LLSD& cof_raw = content["cof_raw"];
-		for (LLSD::array_const_iterator it = cof_raw.beginArray();
-			 it != cof_raw.endArray(); ++it)
+		const LLSD& item = *it;
+		if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF())
 		{
-			const LLSD& item = *it;
-			if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF())
+			ais_items.insert(item["item_id"].asUUID());
+			if (item["type"].asInteger() == 24) // link
 			{
-				ais_items.insert(item["item_id"].asUUID());
-				if (item["type"].asInteger() == 24) // link
-				{
-					LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
-									   << " linked_item_id: " << item["asset_id"].asUUID()
-									   << " name: " << item["name"].asString()
-									   << llendl; 
-				}
-				else if (item["type"].asInteger() == 25) // folder link
-				{
-					LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
-									   << " linked_item_id: " << item["asset_id"].asUUID()
-									   << " name: " << item["name"].asString()
-									   << llendl; 
+				LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
+								   << " linked_item_id: " << item["asset_id"].asUUID()
+								   << " name: " << item["name"].asString()
+								   << llendl; 
+			}
+			else if (item["type"].asInteger() == 25) // folder link
+			{
+				LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
+								   << " linked_item_id: " << item["asset_id"].asUUID()
+								   << " name: " << item["name"].asString()
+								   << llendl; 
 					
-				}
-				else
-				{
-					LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID()
-									   << " linked_item_id: " << item["asset_id"].asUUID()
-									   << " name: " << item["name"].asString()
-									   << " type: " << item["type"].asInteger()
-									   << llendl; 
-				}
 			}
-		}
-		LL_INFOS("Avatar") << llendl;
-		LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() 
-						   << " ================================= " << llendl;
-		LLInventoryModel::cat_array_t cat_array;
-		LLInventoryModel::item_array_t item_array;
-		gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
-									  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
-		for (S32 i=0; i<item_array.count(); i++)
-		{
-			const LLViewerInventoryItem* inv_item = item_array.get(i).get();
-			local_items.insert(inv_item->getUUID());
-			LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
-							   << " linked_item_id: " << inv_item->getLinkedUUID()
-							   << " name: " << inv_item->getName()
-							   << " parent: " << inv_item->getParentUUID()
-							   << llendl;
-		}
-		LL_INFOS("Avatar") << " ================================= " << llendl;
-		S32 local_only = 0, ais_only = 0;
-		for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
-		{
-			if (ais_items.find(*it) == ais_items.end())
+			else
 			{
-				LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl;
-				local_only++;
+				LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID()
+								   << " linked_item_id: " << item["asset_id"].asUUID()
+								   << " name: " << item["name"].asString()
+								   << " type: " << item["type"].asInteger()
+								   << llendl; 
 			}
 		}
-		for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
+	}
+	LL_INFOS("Avatar") << llendl;
+	LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() 
+					   << " ================================= " << llendl;
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
+	gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
+								  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
+	for (S32 i=0; i<item_array.count(); i++)
+	{
+		const LLViewerInventoryItem* inv_item = item_array.get(i).get();
+		local_items.insert(inv_item->getUUID());
+		LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
+						   << " linked_item_id: " << inv_item->getLinkedUUID()
+						   << " name: " << inv_item->getName()
+						   << " parent: " << inv_item->getParentUUID()
+						   << llendl;
+	}
+	LL_INFOS("Avatar") << " ================================= " << llendl;
+	S32 local_only = 0, ais_only = 0;
+	for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
+	{
+		if (ais_items.find(*it) == ais_items.end())
 		{
-			if (local_items.find(*it) == local_items.end())
-			{
-				LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl;
-				ais_only++;
-			}
+			LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl;
+			local_only++;
 		}
-		if (local_only==0 && ais_only==0)
+	}
+	for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
+	{
+		if (local_items.find(*it) == local_items.end())
 		{
-			LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
-							   << content["observed"].asInteger()
-							   << " rcv " << content["expected"].asInteger()
-							   << ")" << llendl;
+			LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl;
+			ais_only++;
 		}
 	}
+	if (local_only==0 && ais_only==0)
+	{
+		LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
+						   << content["observed"].asInteger()
+						   << " rcv " << content["expected"].asInteger()
+						   << ")" << llendl;
+	}
+}
+
+/* virtual */ void RequestAgentUpdateAppearanceResponder::httpSuccess()
+{
+	const LLSD& content = getContent();
+	if (!content.isMap())
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+		return;
+	}
+	if (content["success"].asBoolean())
+	{
+		//LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
+		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+		{
+			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
+		}
+
+		onSuccess();
+	}
+	else
+	{
+		failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
+	}
+}
+
+void RequestAgentUpdateAppearanceResponder::onSuccess()
+{
+	mInFlightCounter = llmax(mInFlightCounter-1,0);
+}
+
+/*virtual*/ void RequestAgentUpdateAppearanceResponder::httpFailure()
+{
+	LL_WARNS("Avatar") << "appearance update request failed, status "
+					   << getStatus() << " reason " << getReason() << LL_ENDL;
+
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+		const LLSD& content = getContent();
+		dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
+		debugCOF(content);
+	}
+	onFailure();
+}
+
+void RequestAgentUpdateAppearanceResponder::onFailure()
+{
+	mInFlightCounter = llmax(mInFlightCounter-1,0);
+
+	F32 seconds_to_wait;
+	mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
+	if (mRetryPolicy->shouldRetry(seconds_to_wait))
+	{
+		llinfos << "retrying" << llendl;
+		doAfterInterval(boost::bind(&RequestAgentUpdateAppearanceResponder::sendRequest,this),
+						seconds_to_wait);
+	}
+	else
+	{
+		llwarns << "giving up after too many retries" << llendl;
+	}
+}	
 
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-};
 
 LLSD LLAppearanceMgr::dumpCOF() const
 {
@@ -3253,53 +3369,9 @@ LLSD LLAppearanceMgr::dumpCOF() const
 	return result;
 }
 
-void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr responder_ptr)
+void LLAppearanceMgr::requestServerAppearanceUpdate()
 {
-	if (gAgentAvatarp->isEditingAppearance()) 
-	{
-		// don't send out appearance updates if in appearance editing mode
-		return;
-	}
-
-	if (!gAgent.getRegion())
-	{
-		llwarns << "Region not set, cannot request server appearance update" << llendl;
-		return;
-	}
-	if (gAgent.getRegion()->getCentralBakeVersion()==0)
-	{
-		llwarns << "Region does not support baking" << llendl;
-	}
-	std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");	
-	if (url.empty())
-	{
-		llwarns << "No cap for UpdateAvatarAppearance." << llendl;
-		return;
-	}
-	
-	LLSD body;
-	S32 cof_version = getCOFVersion();
-	if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
-	{
-		body = dumpCOF();
-	}
-	else
-	{
-		body["cof_version"] = cof_version;
-		if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
-		{
-			body["cof_version"] = cof_version+999;
-		}
-	}
-	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl;
-	
-	if (!responder_ptr.get())
-	{
-		responder_ptr = new RequestAgentUpdateAppearanceResponder;
-	}
-	LLHTTPClient::post(url, body, responder_ptr);
-	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
-	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+	mAppearanceResponder->onRequestRequested();
 }
 
 class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
@@ -3635,7 +3707,8 @@ LLAppearanceMgr::LLAppearanceMgr():
 	mAttachmentInvLinkEnabled(false),
 	mOutfitIsDirty(false),
 	mOutfitLocked(false),
-	mIsInUpdateAppearanceFromCOF(false)
+	mIsInUpdateAppearanceFromCOF(false),
+	mAppearanceResponder(new RequestAgentUpdateAppearanceResponder)
 {
 	LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
 
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index b2917cced4..13a2a62717 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -38,6 +38,7 @@
 class LLWearableHoldingPattern;
 class LLInventoryCallback;
 class LLOutfitUnLockTimer;
+class RequestAgentUpdateAppearanceResponder;
 
 class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 {
@@ -214,7 +215,7 @@ public:
 
 	bool isInUpdateAppearanceFromCOF() { return mIsInUpdateAppearanceFromCOF; }
 
-	void requestServerAppearanceUpdate(LLCurl::ResponderPtr responder_ptr = NULL);
+	void requestServerAppearanceUpdate();
 
 	void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL);
 
@@ -255,6 +256,8 @@ private:
 	bool mOutfitIsDirty;
 	bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.
 
+	LLPointer<RequestAgentUpdateAppearanceResponder> mAppearanceResponder;
+
 	/**
 	 * Lock for blocking operations on outfit until server reply or timeout exceed
 	 * to avoid unsynchronized outfit state or performing duplicate operations.
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 1512b46103..ae429f11f8 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -45,6 +45,11 @@ void LLAdaptiveRetryPolicy::init()
 	mShouldRetry = true;
 }
 
+void LLAdaptiveRetryPolicy::reset()
+{
+	init();
+}
+
 bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time)
 {
 	return (headers.has(HTTP_IN_HEADER_RETRY_AFTER)
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
index 5b1a1d79e0..cf79e0b401 100755
--- a/indra/newview/llhttpretrypolicy.h
+++ b/indra/newview/llhttpretrypolicy.h
@@ -53,6 +53,8 @@ public:
 	virtual void onFailure(const LLCore::HttpResponse *response) = 0;
 
 	virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
+
+	virtual void reset() = 0;
 };
 
 // Very general policy with geometric back-off after failures,
@@ -64,6 +66,8 @@ public:
 
 	// virtual
 	void onSuccess();
+
+	void reset();
 	
 	// virtual
 	void onFailure(S32 status, const LLSD& headers);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2fd26eae80..74fb51b943 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7014,7 +7014,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
-	mLastUpdateReceivedCOFVersion = this_update_cof_version;
+	// No backsies zone - if we get here, the message should be valid and usable.
+	if (appearance_version > 0)
+	{
+		// Note:
+		// RequestAgentUpdateAppearanceResponder::onRequestRequested()
+		// assumes that cof version is only updated with server-bake
+		// appearance messages.
+		mLastUpdateReceivedCOFVersion = this_update_cof_version;
+	}
 		
 	setIsUsingServerBakes(appearance_version > 0);
 
@@ -7061,6 +7069,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		LL_DEBUGS("Avatar") << avString() << " handle visual params, num_params " << num_params << LL_ENDL;
 		BOOL params_changed = FALSE;
 		BOOL interp_params = FALSE;
+		S32 params_changed_count = 0;
 		
 		for( S32 i = 0; i < num_params; i++ )
 		{
@@ -7070,12 +7079,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			if (is_first_appearance_message || (param->getWeight() != newWeight))
 			{
 				params_changed = TRUE;
+				params_changed_count++;
 				if(is_first_appearance_message)
 				{
+					//LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << llendl;
 					param->setWeight(newWeight, FALSE);
 				}
 				else
 				{
+					//LL_DEBUGS("Avatar") << std::setprecision(5) << " param target " << i << " " << param->getWeight() << " -> " << newWeight << llendl;
 					interp_params = TRUE;
 					param->setAnimationTarget(newWeight, FALSE);
 				}
@@ -7087,6 +7099,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << ").  Processing what we can.  object: " << getID() << llendl;
 		}
 
+		LL_DEBUGS("Avatar") << "Changed " << params_changed_count << " params" << llendl;
 		if (params_changed)
 		{
 			if (interp_params)
-- 
cgit v1.2.3


From ca16e3ad26bcbf409ead1eb9acec4e23c992f6c1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 3 Jul 2013 13:34:11 -0400
Subject: SH-4226 WIP - small tweaks

---
 indra/newview/llappearancemgr.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 485c47b2f7..d994b7ca42 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3156,7 +3156,7 @@ void RequestAgentUpdateAppearanceResponder::sendRequest()
 	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl;
 
 	mInFlightCounter++;
-	mInFlightTimer.setTimerExpirySec(30.0);
+	mInFlightTimer.setTimerExpirySec(60.0);
 	LLHTTPClient::post(url, body, this);
 	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
 	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
@@ -3254,7 +3254,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 	}
 	if (content["success"].asBoolean())
 	{
-		//LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
+		LL_DEBUGS("Avatar") << "succeeded" << llendl;
 		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
 			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
-- 
cgit v1.2.3


From 6ba85bd6b300b471ec5f86af462f297bb54522e2 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 3 Jul 2013 16:01:32 -0400
Subject: SH-4305 WIP - unlock and set loading complete after base outfit
 saved.

---
 indra/newview/llappearancemgr.cpp | 2 ++
 indra/newview/llappearancemgr.h   | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index d994b7ca42..a0f8cbe911 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2836,6 +2836,8 @@ void appearance_mgr_update_dirty_state()
 	if (LLAppearanceMgr::instanceExists())
 	{
 		LLAppearanceMgr::getInstance()->updateIsDirty();
+		LLAppearanceMgr::getInstance()->setOutfitLocked(false);
+		gAgentWearables.notifyLoadingFinished();
 	}
 }
 
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 13a2a62717..8c8b5e2489 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -171,6 +171,8 @@ public:
 	// should only be necessary to do on initial login.
 	void updateIsDirty();
 
+	void setOutfitLocked(bool locked);
+
 	// Called when self avatar is first fully visible.
 	void onFirstFullyVisible();
 
@@ -250,8 +252,6 @@ private:
 
 	static void onOutfitRename(const LLSD& notification, const LLSD& response);
 
-	void setOutfitLocked(bool locked);
-
 	bool mAttachmentInvLinkEnabled;
 	bool mOutfitIsDirty;
 	bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.
-- 
cgit v1.2.3


From d079f0dcdc0d317813cda282496a1edae3feed64 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 10 Jul 2013 13:02:09 -0700
Subject: SH-4319 WIP - set using server bakes on receiving a cached texture
 response in a non-bake region

---
 indra/newview/llagentwearables.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 8e60bf1c6d..93ccec7d49 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1443,6 +1443,7 @@ void LLAgentWearables::queryWearableCache()
 	{
 		return;
 	}
+	gAgentAvatarp->setIsUsingServerBakes(false);
 
 	// Look up affected baked textures.
 	// If they exist:
-- 
cgit v1.2.3


From a85fa3b10a406218cabfecc0d592e816f8dfdb53 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Thu, 11 Jul 2013 15:15:04 -0700
Subject: Adding support for COPY methods to httpclient.  Implementing
 viewer-side use of AISv3 COPY library folder operation. (SH-4304)

---
 indra/llmessage/llhttpclient.cpp    |  13 +
 indra/llmessage/llhttpclient.h      |  18 +-
 indra/llmessage/llhttpconstants.cpp |   6 +-
 indra/llmessage/llhttpconstants.h   |   1 +
 indra/llmessage/llurlrequest.cpp    |  10 +-
 indra/newview/llaisapi.cpp          | 588 ++++++++++++++++++++++++++++--------
 indra/newview/llaisapi.h            |  55 +++-
 indra/newview/llappearancemgr.cpp   |  76 ++++-
 indra/newview/llinventorymodel.cpp  |  24 +-
 indra/newview/llviewerinventory.cpp |  62 ++--
 indra/newview/llviewerinventory.h   |   4 +-
 indra/newview/llviewerregion.cpp    |  19 +-
 indra/newview/llviewerregion.h      |   1 +
 13 files changed, 689 insertions(+), 188 deletions(-)

diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 53cef54559..70c890a8de 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -631,6 +631,19 @@ void LLHTTPClient::move(
 	request(url, HTTP_MOVE, NULL, responder, timeout, headers);
 }
 
+// static
+void LLHTTPClient::copy(
+	const std::string& url,
+	const std::string& destination,
+	ResponderPtr responder,
+	const LLSD& hdrs,
+	const F32 timeout)
+{
+	LLSD headers = hdrs;
+	headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+	request(url, HTTP_COPY, NULL, responder, timeout, headers);
+}
+
 
 void LLHTTPClient::setPump(LLPumpIO& pump)
 {
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index 4e7495495f..5ace2d74c9 100755
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -119,7 +119,7 @@ public:
 		const LLSD& headers = LLSD(),
 		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
 		///< sends a DELETE method, but we can't call it delete in c++
-	
+
 	/**
 	 * @brief Send a MOVE webdav method
 	 *
@@ -136,6 +136,22 @@ public:
 		const LLSD& headers = LLSD(),
 		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
 
+	/**
+	 * @brief Send a COPY webdav method
+	 *
+	 * @param url The complete serialized (and escaped) url to get.
+	 * @param destination The complete serialized destination url.
+	 * @param responder The responder that will handle the result.
+	 * @param headers A map of key:value headers to pass to the request
+	 * @param timeout The number of seconds to give the server to respond.
+	 */
+	static void copy(
+		const std::string& url,
+		const std::string& destination,
+		ResponderPtr responder,
+		const LLSD& headers = LLSD(),
+		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
 	//@}
 
 	/**
diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp
index 016f1f1970..01f4a080b0 100755
--- a/indra/llmessage/llhttpconstants.cpp
+++ b/indra/llmessage/llhttpconstants.cpp
@@ -133,6 +133,8 @@ const std::string HTTP_VERB_POST("POST");
 const std::string HTTP_VERB_DELETE("DELETE");
 const std::string HTTP_VERB_MOVE("MOVE");
 const std::string HTTP_VERB_OPTIONS("OPTIONS");
+const std::string HTTP_VERB_PATCH("PATCH");
+const std::string HTTP_VERB_COPY("COPY");
 
 const std::string& httpMethodAsVerb(EHTTPMethod method)
 {
@@ -145,7 +147,9 @@ const std::string& httpMethodAsVerb(EHTTPMethod method)
 		HTTP_VERB_POST,
 		HTTP_VERB_DELETE,
 		HTTP_VERB_MOVE,
-		HTTP_VERB_OPTIONS
+		HTTP_VERB_OPTIONS,
+		HTTP_VERB_PATCH,
+		HTTP_VERB_COPY
 	};
 	if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT))
 	{
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h
index aa947af414..4aa3cc6394 100755
--- a/indra/llmessage/llhttpconstants.h
+++ b/indra/llmessage/llhttpconstants.h
@@ -112,6 +112,7 @@ enum EHTTPMethod
 	HTTP_MOVE, // Caller will need to set 'Destination' header
 	HTTP_OPTIONS,
 	HTTP_PATCH,
+	HTTP_COPY,
 	HTTP_METHOD_COUNT
 };
 
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index cadff49cb8..7bf930aeb0 100755
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -516,13 +516,19 @@ bool LLURLRequest::configure()
 		break;
 
 	case HTTP_DELETE:
-		// Set the handle for an http post
+		// Set the handle for an http delete
 		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
 		rv = true;
 		break;
 
+	case HTTP_COPY:
+		// Set the handle for an http copy
+		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "COPY");
+		rv = true;
+		break;
+
 	case HTTP_MOVE:
-		// Set the handle for an http post
+		// Set the handle for an http move
 		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "MOVE");
 		// *NOTE: should we check for the Destination header?
 		rv = true;
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 6d5f1951f9..cb8700865a 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -40,14 +40,25 @@
 
 // AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
 AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback):
+	mCommandFunc(NULL),
 	mCallback(callback)
 {
 	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
 }
 
-void AISCommand::run_command()
+bool AISCommand::run_command()
 {
-	mCommandFunc();
+	if (NULL == mCommandFunc)
+	{
+		// This may happen if a command failed to initiate itself.
+		LL_WARNS("Inventory") << "AIS command attempted with null command function" << LL_ENDL;
+		return false;
+	}
+	else
+	{
+		mCommandFunc();
+		return true;
+	}
 }
 
 void AISCommand::setCommandFunc(command_func_type command_func)
@@ -80,9 +91,9 @@ void AISCommand::httpSuccess()
 
 	if (mCallback)
 	{
-		LLUUID item_id; // will default to null if parse fails.
-		getResponseUUID(content,item_id);
-		mCallback->fire(item_id);
+		LLUUID id; // will default to null if parse fails.
+		getResponseUUID(content,id);
+		mCallback->fire(id);
 	}
 }
 
@@ -96,12 +107,12 @@ void AISCommand::httpFailure()
 	if (!content.isMap())
 	{
 		LL_DEBUGS("Inventory") << "Malformed response contents " << content
-							   << " status " << status << " reason " << reason << llendl;
+							   << " status " << status << " reason " << reason << LL_ENDL;
 	}
 	else
 	{
 		LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
-							   << " status " << status << " reason " << reason << llendl;
+							   << " status " << status << " reason " << reason << LL_ENDL;
 	}
 	mRetryPolicy->onFailure(status, headers);
 	F32 seconds_to_wait;
@@ -113,12 +124,23 @@ void AISCommand::httpFailure()
 	{
 		// Command func holds a reference to self, need to release it
 		// after a success or final failure.
+		// *TODO: Notify user?  This seems bad.
 		setCommandFunc(no_op);
 	}
 }
 
 //static
-bool AISCommand::getCap(std::string& cap)
+bool AISCommand::isAPIAvailable()
+{
+	if (gAgent.getRegion())
+	{
+		return gAgent.getRegion()->isCapabilityAvailable("InventoryAPIv3");
+	}
+	return false;
+}
+
+//static
+bool AISCommand::getInvCap(std::string& cap)
 {
 	if (gAgent.getRegion())
 	{
@@ -131,18 +153,39 @@ bool AISCommand::getCap(std::string& cap)
 	return false;
 }
 
+//static
+bool AISCommand::getLibCap(std::string& cap)
+{
+	if (gAgent.getRegion())
+	{
+		cap = gAgent.getRegion()->getCapability("LibraryAPIv3");
+	}
+	if (!cap.empty())
+	{
+		return true;
+	}
+	return false;
+}
+
+//static
+void AISCommand::getCapabilityNames(LLSD& capabilityNames)
+{
+	capabilityNames.append("InventoryAPIv3");
+	capabilityNames.append("LibraryAPIv3");
+}
+
 RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
 									 LLPointer<LLInventoryCallback> callback):
 	AISCommand(callback)
 {
 	std::string cap;
-	if (!getCap(cap))
+	if (!getInvCap(cap))
 	{
 		llwarns << "No cap found" << llendl;
 		return;
 	}
 	std::string url = cap + std::string("/item/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
 	LLHTTPClient::ResponderPtr responder = this;
 	LLSD headers;
 	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
@@ -155,13 +198,13 @@ RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
 	AISCommand(callback)
 {
 	std::string cap;
-	if (!getCap(cap))
+	if (!getInvCap(cap))
 	{
 		llwarns << "No cap found" << llendl;
 		return;
 	}
 	std::string url = cap + std::string("/category/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
 	LLHTTPClient::ResponderPtr responder = this;
 	LLSD headers;
 	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
@@ -174,13 +217,13 @@ PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
 	AISCommand(callback)
 {
 	std::string cap;
-	if (!getCap(cap))
+	if (!getInvCap(cap))
 	{
 		llwarns << "No cap found" << llendl;
 		return;
 	}
 	std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
-	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
 	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
@@ -195,14 +238,14 @@ UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
 	AISCommand(callback)
 {
 	std::string cap;
-	if (!getCap(cap))
+	if (!getInvCap(cap))
 	{
 		llwarns << "No cap found" << llendl;
 		return;
 	}
 	std::string url = cap + std::string("/item/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << llendl;
-	LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << llendl;
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << LL_ENDL;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
 	headers["Content-Type"] = "application/llsd+xml";
@@ -218,13 +261,13 @@ UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& item_id,
 	AISCommand(callback)
 {
 	std::string cap;
-	if (!getCap(cap))
+	if (!getInvCap(cap))
 	{
 		llwarns << "No cap found" << llendl;
 		return;
 	}
 	std::string url = cap + std::string("/category/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << llendl;
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
 	headers["Content-Type"] = "application/llsd+xml";
@@ -238,7 +281,7 @@ SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& conten
 	AISCommand(callback)
 {
 	std::string cap;
-	if (!getCap(cap))
+	if (!getInvCap(cap))
 	{
 		llwarns << "No cap found" << llendl;
 		return;
@@ -255,146 +298,335 @@ SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& conten
 	setCommandFunc(cmd);
 }
 
+CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id,
+													   const LLUUID& dest_id,
+													   LLPointer<LLInventoryCallback> callback):
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getLibCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL;
+	LLUUID tid;
+	tid.generate();
+	std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString();
+	llinfos << url << llendl;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::copy, url, dest_id.asString(), responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
+bool CopyLibraryCategoryCommand::getResponseUUID(const LLSD& content, LLUUID& id)
+{
+	if (content.has("category_id"))
+	{
+		id = content["category_id"];
+		return true;
+	}
+	return false;
+}
+
 AISUpdate::AISUpdate(const LLSD& update)
 {
 	parseUpdate(update);
 }
 
+void AISUpdate::clearParseResults()
+{
+	mCatDescendentDeltas.clear();
+	mCatDescendentsKnown.clear();
+	mCatVersionsUpdated.clear();
+	mItemsCreated.clear();
+	mItemsUpdated.clear();
+	mCategoriesCreated.clear();
+	mCategoriesUpdated.clear();
+	mObjectsDeletedIds.clear();
+	mItemIds.clear();
+	mCategoryIds.clear();
+}
+
 void AISUpdate::parseUpdate(const LLSD& update)
 {
-	// parse _categories_removed -> mObjectsDeleted
-	uuid_vec_t cat_ids;
+	clearParseResults();
+	parseMeta(update);
+	parseContent(update);
+}
+
+void AISUpdate::parseMeta(const LLSD& update)
+{
+	// parse _categories_removed -> mObjectsDeletedIds
+	uuid_list_t cat_ids;
 	parseUUIDArray(update,"_categories_removed",cat_ids);
-	for (uuid_vec_t::const_iterator it = cat_ids.begin();
+	for (uuid_list_t::const_iterator it = cat_ids.begin();
 		 it != cat_ids.end(); ++it)
 	{
 		LLViewerInventoryCategory *cat = gInventory.getCategory(*it);
-		mCatDeltas[cat->getParentUUID()]--;
-		mObjectsDeleted.insert(*it);
+		mCatDescendentDeltas[cat->getParentUUID()]--;
+		mObjectsDeletedIds.insert(*it);
 	}
 
-	// parse _categories_items_removed -> mObjectsDeleted
-	uuid_vec_t item_ids;
+	// parse _categories_items_removed -> mObjectsDeletedIds
+	uuid_list_t item_ids;
 	parseUUIDArray(update,"_category_items_removed",item_ids);
-	for (uuid_vec_t::const_iterator it = item_ids.begin();
+	parseUUIDArray(update,"_removed_items",item_ids);
+	for (uuid_list_t::const_iterator it = item_ids.begin();
 		 it != item_ids.end(); ++it)
 	{
 		LLViewerInventoryItem *item = gInventory.getItem(*it);
-		mCatDeltas[item->getParentUUID()]--;
-		mObjectsDeleted.insert(*it);
+		mCatDescendentDeltas[item->getParentUUID()]--;
+		mObjectsDeletedIds.insert(*it);
 	}
 
-	// parse _broken_links_removed -> mObjectsDeleted
-	uuid_vec_t broken_link_ids;
+	// parse _broken_links_removed -> mObjectsDeletedIds
+	uuid_list_t broken_link_ids;
 	parseUUIDArray(update,"_broken_links_removed",broken_link_ids);
-	for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
+	for (uuid_list_t::const_iterator it = broken_link_ids.begin();
 		 it != broken_link_ids.end(); ++it)
 	{
 		LLViewerInventoryItem *item = gInventory.getItem(*it);
-		mCatDeltas[item->getParentUUID()]--;
-		mObjectsDeleted.insert(*it);
+		mCatDescendentDeltas[item->getParentUUID()]--;
+		mObjectsDeletedIds.insert(*it);
 	}
 
 	// parse _created_items
-	parseUUIDArray(update,"_created_items",mItemsCreatedIds);
+	parseUUIDArray(update,"_created_items",mItemIds);
+
+	// parse _created_categories
+	parseUUIDArray(update,"_created_categories",mCategoryIds);
 
-	if (update.has("_embedded"))
+	// Parse updated category versions.
+	const std::string& ucv = "_updated_category_versions";
+	if (update.has(ucv))
 	{
-		const LLSD& embedded = update["_embedded"];
-		for(LLSD::map_const_iterator it = embedded.beginMap(),
-				end = embedded.endMap();
-				it != end; ++it)
+		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
+				end = update[ucv].endMap();
+			it != end; ++it)
 		{
-			const std::string& field = (*it).first;
-			
-			// parse created links
-			if (field == "link")
-			{
-				const LLSD& links = embedded["link"];
-				parseCreatedLinks(links);
-			}
+			const LLUUID id((*it).first);
+			S32 version = (*it).second.asInteger();
+			mCatVersionsUpdated[id] = version;
 		}
 	}
+}
 
-	// Parse item update at the top level.
-	if (update.has("item_id"))
+void AISUpdate::parseContent(const LLSD& update)
+{
+	if (update.has("linked_id"))
 	{
-		LLUUID item_id = update["item_id"].asUUID();
-		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
-		LLViewerInventoryItem *curr_item = gInventory.getItem(item_id);
-		if (curr_item)
+		parseLink(update);
+	}
+	else if (update.has("item_id"))
+	{
+		parseItem(update);
+	}
+
+	if (update.has("category_id"))
+	{
+		parseCategory(update);
+	}
+	else
+	{
+		if (update.has("_embedded"))
 		{
-			// Default to current values where not provided.
-			new_item->copyViewerItem(curr_item);
+			parseEmbedded(update["_embedded"]);
 		}
-		BOOL rv = new_item->unpackMessage(update);
-		if (rv)
+	}
+}
+
+void AISUpdate::parseItem(const LLSD& item_map)
+{
+	LLUUID item_id = item_map["item_id"].asUUID();
+	LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+	LLViewerInventoryItem *curr_item = gInventory.getItem(item_id);
+	if (curr_item)
+	{
+		// Default to current values where not provided.
+		new_item->copyViewerItem(curr_item);
+	}
+	BOOL rv = new_item->unpackMessage(item_map);
+	if (rv)
+	{
+		if (curr_item)
 		{
 			mItemsUpdated[item_id] = new_item;
 			// This statement is here to cause a new entry with 0
 			// delta to be created if it does not already exist;
 			// otherwise has no effect.
-			mCatDeltas[new_item->getParentUUID()];
+			mCatDescendentDeltas[new_item->getParentUUID()];
 		}
 		else
 		{
-			llerrs << "unpack failed" << llendl;
+			mItemsCreated[item_id] = new_item;
+			mCatDescendentDeltas[new_item->getParentUUID()]++;
 		}
 	}
+	else
+	{
+		// *TODO: Wow, harsh.  Should we just complain and get out?
+		llerrs << "unpack failed" << llendl;
+	}
+}
 
-	// Parse updated category versions.
-	const std::string& ucv = "_updated_category_versions";
-	if (update.has(ucv))
+void AISUpdate::parseLink(const LLSD& link_map)
+{
+	LLUUID item_id = link_map["item_id"].asUUID();
+	LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
+	LLViewerInventoryItem *curr_link = gInventory.getItem(item_id);
+	if (curr_link)
 	{
-		for(LLSD::map_const_iterator it = update[ucv].beginMap(),
-				end = update[ucv].endMap();
-			it != end; ++it)
+		// Default to current values where not provided.
+		new_link->copyViewerItem(curr_link);
+	}
+	BOOL rv = new_link->unpackMessage(link_map);
+	if (rv)
+	{
+		const LLUUID& parent_id = new_link->getParentUUID();
+		if (curr_link)
 		{
-			const LLUUID id((*it).first);
-			S32 version = (*it).second.asInteger();
-			mCatVersions[id] = version;
+			mItemsUpdated[item_id] = new_link;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			mCatDescendentDeltas[parent_id];
+		}
+		else
+		{
+			LLPermissions default_perms;
+			default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
+			default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
+			new_link->setPermissions(default_perms);
+			LLSaleInfo default_sale_info;
+			new_link->setSaleInfo(default_sale_info);
+			//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << LL_ENDL;
+			mItemsCreated[item_id] = new_link;
+			mCatDescendentDeltas[parent_id]++;
 		}
 	}
+	else
+	{
+		// *TODO: Wow, harsh.  Should we just complain and get out?
+		llerrs << "unpack failed" << llendl;
+	}
 }
 
-void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids)
+
+void AISUpdate::parseCategory(const LLSD& category_map)
 {
-	ids.clear();
-	if (content.has(name))
+	LLUUID category_id = category_map["category_id"].asUUID();
+
+	// Check descendent count first, as it may be needed
+	// to populate newly created categories
+	if (category_map.has("_embedded"))
 	{
-		for(LLSD::array_const_iterator it = content[name].beginArray(),
-				end = content[name].endArray();
-				it != end; ++it)
+		parseDescendentCount(category_id, category_map["_embedded"]);
+	}
+
+	LLPointer<LLViewerInventoryCategory> new_cat(new LLViewerInventoryCategory(category_id));
+	LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id);
+	if (curr_cat)
+	{
+		// Default to current values where not provided.
+		new_cat->copyViewerCategory(curr_cat);
+	}
+	BOOL rv = new_cat->unpackMessage(category_map);
+	// *NOTE: unpackMessage does not unpack version or descendent count.
+	//if (category_map.has("version"))
+	//{
+	//	mCatVersionsUpdated[category_id] = category_map["version"].asInteger();
+	//}
+	if (rv)
+	{
+		if (curr_cat)
+		{
+			mCategoriesUpdated[category_id] = new_cat;
+			// This statement is here to cause a new entry with 0
+			// delta to be created if it does not already exist;
+			// otherwise has no effect.
+			mCatDescendentDeltas[new_cat->getParentUUID()];
+		}
+		else
 		{
-			ids.push_back((*it).asUUID());
+			// Set version/descendents for newly created categories.
+			if (category_map.has("version"))
+			{
+				S32 version = category_map["version"].asInteger();
+				LL_DEBUGS("Inventory") << "Setting version to " << version
+									   << " for new category " << category_id << LL_ENDL;
+				new_cat->setVersion(version);
+			}
+			uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id);
+			if (mCatDescendentsKnown.end() != lookup_it)
+			{
+				S32 descendent_count = lookup_it->second;
+				LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count 
+									   << " for new category " << category_id << LL_ENDL;
+				new_cat->setDescendentCount(descendent_count);
+			}
+			mCategoriesCreated[category_id] = new_cat;
+			mCatDescendentDeltas[new_cat->getParentUUID()]++;
 		}
 	}
+	else
+	{
+		// *TODO: Wow, harsh.  Should we just complain and get out?
+		llerrs << "unpack failed" << llendl;
+	}
+
+	// Check for more embedded content.
+	if (category_map.has("_embedded"))
+	{
+		parseEmbedded(category_map["_embedded"]);
+	}
 }
 
-void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map)
+void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embedded)
 {
-	LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
-	BOOL rv = new_link->unpackMessage(link_map);
-	if (rv)
+	// We can only determine true descendent count if this contains all descendent types.
+	if (embedded.has("category") &&
+		embedded.has("link") &&
+		embedded.has("item"))
 	{
-		LLPermissions default_perms;
-		default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null);
-		default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE);
-		new_link->setPermissions(default_perms);
-		LLSaleInfo default_sale_info;
-		new_link->setSaleInfo(default_sale_info);
-		//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl;
-		mItemsCreated[link_id] = new_link;
-		const LLUUID& parent_id = new_link->getParentUUID();
-		mCatDeltas[parent_id]++;
+		mCatDescendentsKnown[category_id]  = embedded["category"].size();
+		mCatDescendentsKnown[category_id] += embedded["link"].size();
+		mCatDescendentsKnown[category_id] += embedded["item"].size();
 	}
-	else
+}
+
+void AISUpdate::parseEmbedded(const LLSD& embedded)
+{
+	if (embedded.has("link"))
+	{
+		parseEmbeddedLinks(embedded["link"]);
+	}
+	if (embedded.has("item"))
+	{
+		parseEmbeddedItems(embedded["item"]);
+	}
+	if (embedded.has("category"))
 	{
-		llwarns << "failed to parse" << llendl;
+		parseEmbeddedCategories(embedded["category"]);
+	}
+}
+
+void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids)
+{
+	if (content.has(name))
+	{
+		for(LLSD::array_const_iterator it = content[name].beginArray(),
+				end = content[name].endArray();
+				it != end; ++it)
+		{
+			ids.insert((*it).asUUID());
+		}
 	}
 }
 
-void AISUpdate::parseCreatedLinks(const LLSD& links)
+void AISUpdate::parseEmbeddedLinks(const LLSD& links)
 {
 	for(LLSD::map_const_iterator linkit = links.beginMap(),
 			linkend = links.endMap();
@@ -402,47 +634,134 @@ void AISUpdate::parseCreatedLinks(const LLSD& links)
 	{
 		const LLUUID link_id((*linkit).first);
 		const LLSD& link_map = (*linkit).second;
-		uuid_vec_t::const_iterator pos =
-			std::find(mItemsCreatedIds.begin(),
-					  mItemsCreatedIds.end(),link_id);
-		if (pos != mItemsCreatedIds.end())
+		if (mItemIds.end() == mItemIds.find(link_id))
+		{
+			LL_DEBUGS("Inventory") << "Ignoring link not in items list " << link_id << LL_ENDL;
+		}
+		else
+		{
+			parseLink(link_map);
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedItems(const LLSD& items)
+{
+	// Special case: this may be a single item (_embedded in a link)
+	if (items.has("item_id"))
+	{
+		if (mItemIds.end() != mItemIds.find(items["item_id"].asUUID()))
+		{
+			parseContent(items);
+		}
+		return;
+	}
+
+	for(LLSD::map_const_iterator itemit = items.beginMap(),
+			itemend = items.endMap();
+		itemit != itemend; ++itemit)
+	{
+		const LLUUID item_id((*itemit).first);
+		const LLSD& item_map = (*itemit).second;
+		if (mItemIds.end() == mItemIds.find(item_id))
+		{
+			LL_DEBUGS("Inventory") << "Ignoring item not in items list " << item_id << LL_ENDL;
+		}
+		else
+		{
+			parseItem(item_map);
+		}
+	}
+}
+
+void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
+{
+	for(LLSD::map_const_iterator categoryit = categories.beginMap(),
+			categoryend = categories.endMap();
+		categoryit != categoryend; ++categoryit)
+	{
+		const LLUUID category_id((*categoryit).first);
+		const LLSD& category_map = (*categoryit).second;
+		if (mCategoryIds.end() == mCategoryIds.find(category_id))
 		{
-			parseLink(link_id,link_map);
+			LL_DEBUGS("Inventory") << "Ignoring category not in categories list " << category_id << LL_ENDL;
 		}
 		else
 		{
-			LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
+			parseCategory(category_map);
 		}
 	}
 }
 
 void AISUpdate::doUpdate()
 {
-	// Do descendent/version accounting.
-	// Can remove this if/when we use the version info directly.
-	for (std::map<LLUUID,S32>::const_iterator catit = mCatDeltas.begin();
-		 catit != mCatDeltas.end(); ++catit)
+	// Do version/descendent accounting.
+	for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
+		 catit != mCatDescendentDeltas.end(); ++catit)
 	{
 		const LLUUID cat_id(catit->first);
-		S32 delta = catit->second;
-		LLInventoryModel::LLCategoryUpdate up(cat_id, delta);
-		gInventory.accountForUpdate(up);
+		// Don't account for update if we just created this category.
+		if (mCategoriesCreated.find(cat_id) != mCategoriesCreated.end())
+		{
+			LL_DEBUGS("Inventory") << "Skipping version increment for new category " << cat_id << LL_ENDL;
+			continue;
+		}
+
+		// Don't account for update unless AIS told us it updated that category.
+		if (mCatVersionsUpdated.find(cat_id) == mCatVersionsUpdated.end())
+		{
+			LL_DEBUGS("Inventory") << "Skipping version increment for non-updated category " << cat_id << LL_ENDL;
+			continue;
+		}
+
+		// If we have a known descendent count, set that now.
+		LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+		if (cat)
+		{
+			S32 descendent_delta = catit->second;
+			S32 old_count = cat->getDescendentCount();
+			LL_DEBUGS("Inventory") << "Updating descendent count for " << cat_id
+								   << " with delta " << descendent_delta << " from "
+								   << old_count << " to " << (old_count+descendent_delta) << LL_ENDL;
+			LLInventoryModel::LLCategoryUpdate up(cat_id, descendent_delta);
+			gInventory.accountForUpdate(up);
+		}
+		else
+		{
+			LL_DEBUGS("Inventory") << "Skipping version accounting for unknown category " << cat_id << LL_ENDL;
+		}
 	}
-	
-	// TODO - how can we use this version info? Need to be sure all
-	// changes are going through AIS first, or at least through
-	// something with a reliable responder.
-	for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin();
-		 ucv_it != mCatVersions.end(); ++ucv_it)
+
+	// CREATE CATEGORIES
+	for (deferred_category_map_t::const_iterator create_it = mCategoriesCreated.begin();
+		 create_it != mCategoriesCreated.end(); ++create_it)
 	{
-		const LLUUID id = ucv_it->first;
-		S32 version = ucv_it->second;
-		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
-		if (cat->getVersion() != version)
+		LLUUID category_id(create_it->first);
+		LLPointer<LLViewerInventoryCategory> new_category = create_it->second;
+
+		gInventory.updateCategory(new_category);
+		LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL;
+	}
+
+	// UPDATE CATEGORIES
+	for (deferred_category_map_t::const_iterator update_it = mCategoriesUpdated.begin();
+		 update_it != mCategoriesUpdated.end(); ++update_it)
+	{
+		LLUUID category_id(update_it->first);
+		LLPointer<LLViewerInventoryCategory> new_category = update_it->second;
+		// Since this is a copy of the category *before* the accounting update, above,
+		// we need to transfer back the updated version/descendent count.
+		LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID());
+		if (NULL == curr_cat)
 		{
-			llwarns << "Possible version mismatch for category " << cat->getName()
-					<< ", viewer version " << cat->getVersion()
-					<< " server version " << version << llendl;
+			LL_WARNS("Inventory") << "Failed to update unknown category " << new_category->getUUID() << LL_ENDL;
+		}
+		else
+		{
+			new_category->setVersion(curr_cat->getVersion());
+			new_category->setDescendentCount(curr_cat->getDescendentCount());
+			gInventory.updateCategory(new_category);
+			LL_DEBUGS("Inventory") << "updated category " << category_id << LL_ENDL;
 		}
 	}
 
@@ -456,7 +775,7 @@ void AISUpdate::doUpdate()
 		// FIXME risky function since it calls updateServer() in some
 		// cases.  Maybe break out the update/create cases, in which
 		// case this is create.
-		LL_DEBUGS("Inventory") << "created item " << item_id << llendl;
+		LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL;
 		gInventory.updateItem(new_item);
 	}
 	
@@ -469,19 +788,36 @@ void AISUpdate::doUpdate()
 		// FIXME risky function since it calls updateServer() in some
 		// cases.  Maybe break out the update/create cases, in which
 		// case this is update.
-		LL_DEBUGS("Inventory") << "updated item " << item_id << llendl;
-		//LL_DEBUGS("Inventory") << ll_pretty_print_sd(new_item->asLLSD()) << llendl;
+		LL_DEBUGS("Inventory") << "updated item " << item_id << LL_ENDL;
+		//LL_DEBUGS("Inventory") << ll_pretty_print_sd(new_item->asLLSD()) << LL_ENDL;
 		gInventory.updateItem(new_item);
 	}
 
 	// DELETE OBJECTS
-	for (std::set<LLUUID>::const_iterator del_it = mObjectsDeleted.begin();
-		 del_it != mObjectsDeleted.end(); ++del_it)
+	for (std::set<LLUUID>::const_iterator del_it = mObjectsDeletedIds.begin();
+		 del_it != mObjectsDeletedIds.end(); ++del_it)
 	{
-		LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
+		LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL;
 		gInventory.onObjectDeletedFromServer(*del_it, false, false, false);
 	}
 
+	// TODO - how can we use this version info? Need to be sure all
+	// changes are going through AIS first, or at least through
+	// something with a reliable responder.
+	for (uuid_int_map_t::iterator ucv_it = mCatVersionsUpdated.begin();
+		 ucv_it != mCatVersionsUpdated.end(); ++ucv_it)
+	{
+		const LLUUID id = ucv_it->first;
+		S32 version = ucv_it->second;
+		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+		if (cat->getVersion() != version)
+		{
+			llwarns << "Possible version mismatch for category " << cat->getName()
+					<< ", viewer version " << cat->getVersion()
+					<< " server version " << version << llendl;
+		}
+	}
+
 	gInventory.notifyObservers();
 }
 
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index 1f9555f004..f4e219e9e6 100755
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -31,7 +31,6 @@
 #include <map>
 #include <set>
 #include <string>
-#include <vector>
 #include "llcurl.h"
 #include "llhttpclient.h"
 #include "llhttpretrypolicy.h"
@@ -46,7 +45,7 @@ public:
 
 	virtual ~AISCommand() {}
 
-	void run_command();
+	bool run_command();
 
 	void setCommandFunc(command_func_type command_func);
 	
@@ -54,13 +53,17 @@ public:
 	// LLInventoryCallback::fire().  May or may not need to bother,
 	// since most LLInventoryCallbacks do their work in the
 	// destructor.
-	virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
 	
 	/* virtual */ void httpSuccess();
+	/* virtual */ void httpFailure();
 
-	/*virtual*/ void httpFailure();
+	static bool isAPIAvailable();
+	static bool getInvCap(std::string& cap);
+	static bool getLibCap(std::string& cap);
+	static void getCapabilityNames(LLSD& capabilityNames);
 
-	static bool getCap(std::string& cap);
+protected:
+	virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
 
 private:
 	command_func_type mCommandFunc;
@@ -118,26 +121,52 @@ private:
 	LLSD mContents;
 };
 
+class CopyLibraryCategoryCommand: public AISCommand
+{
+public:
+	CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback);
+
+protected:
+	/* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id);
+};
+
 class AISUpdate
 {
 public:
 	AISUpdate(const LLSD& update);
 	void parseUpdate(const LLSD& update);
-	void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids);
-	void parseLink(const LLUUID& link_id, const LLSD& link_map);
-	void parseCreatedLinks(const LLSD& links);
+	void parseMeta(const LLSD& update);
+	void parseContent(const LLSD& update);
+	void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
+	void parseLink(const LLSD& link_map);
+	void parseItem(const LLSD& link_map);
+	void parseCategory(const LLSD& link_map);
+	void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
+	void parseEmbedded(const LLSD& embedded);
+	void parseEmbeddedLinks(const LLSD& links);
+	void parseEmbeddedItems(const LLSD& links);
+	void parseEmbeddedCategories(const LLSD& links);
 	void doUpdate();
 private:
+	void clearParseResults();
+
 	typedef std::map<LLUUID,S32> uuid_int_map_t;
-	uuid_int_map_t mCatDeltas;
-	uuid_int_map_t mCatVersions;
+	uuid_int_map_t mCatDescendentDeltas;
+	uuid_int_map_t mCatDescendentsKnown;
+	uuid_int_map_t mCatVersionsUpdated;
 
 	typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
 	deferred_item_map_t mItemsCreated;
 	deferred_item_map_t mItemsUpdated;
-
-	std::set<LLUUID> mObjectsDeleted;
-	uuid_vec_t mItemsCreatedIds;
+	typedef std::map<LLUUID,LLPointer<LLViewerInventoryCategory> > deferred_category_map_t;
+	deferred_category_map_t mCategoriesCreated;
+	deferred_category_map_t mCategoriesUpdated;
+
+	// These keep track of uuid's mentioned in meta values.
+	// Useful for filtering out which content we are interested in.
+	uuid_list_t mObjectsDeletedIds;
+	uuid_list_t mItemIds;
+	uuid_list_t mCategoryIds;
 };
 
 #endif
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index a0f8cbe911..fc07932860 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -435,6 +435,50 @@ private:
 
 S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
 
+class LLWearCategoryAfterCopy: public LLInventoryCallback
+{
+public:
+	LLWearCategoryAfterCopy(bool append):
+		mAppend(append)
+	{}
+
+	// virtual
+	void fire(const LLUUID& id)
+	{
+		// Wear the inventory category.
+		LLInventoryCategory* cat = gInventory.getCategory(id);
+		LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(cat, mAppend);
+	}
+
+private:
+	bool mAppend;
+};
+
+class LLTrackPhaseWrapper : public LLInventoryCallback
+{
+public:
+	LLTrackPhaseWrapper(const std::string& phase_name, LLPointer<LLInventoryCallback> cb = NULL):
+		mTrackingPhase(phase_name),
+		mCB(cb)
+	{
+		selfStartPhase(mTrackingPhase);
+	}
+
+	// virtual
+	void fire(const LLUUID& id)
+	{
+		selfStopPhase(mTrackingPhase);
+		if (mCB)
+		{
+			mCB->fire(id);
+		}
+	}
+
+protected:
+	std::string mTrackingPhase;
+	LLPointer<LLInventoryCallback> mCB;
+};
+
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions,
 														 bool enforce_ordering,
 														 nullary_func_t post_update_func 
@@ -2244,10 +2288,31 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 	LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategory( " << category->getName()
 			 << " )" << LL_ENDL;
 
-	selfStartPhase("wear_inventory_category_fetch");
-	callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
-														   &LLAppearanceMgr::instance(),
-														   category->getUUID(), copy, append));
+	// If we are copying from library, attempt to use AIS to copy the category.
+	bool ais_ran=false;
+	if (copy && AISCommand::isAPIAvailable())
+	{
+		LLUUID parent_id;
+		parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
+		if (parent_id.isNull())
+		{
+			parent_id = gInventory.getRootFolderID();
+		}
+
+		LLPointer<LLInventoryCallback> copy_cb = new LLWearCategoryAfterCopy(append);
+		LLPointer<LLInventoryCallback> track_cb = new LLTrackPhaseWrapper(
+													std::string("wear_inventory_category_callback"), copy_cb);
+		LLPointer<AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb);
+		ais_ran=cmd_ptr->run_command();
+	}
+
+	if (!ais_ran)
+	{
+		selfStartPhase("wear_inventory_category_fetch");
+		callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
+															   &LLAppearanceMgr::instance(),
+															   category->getUUID(), copy, append));
+	}
 }
 
 S32 LLAppearanceMgr::getActiveCopyOperations() const
@@ -3544,8 +3609,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
 
 	// First, make a folder in the My Outfits directory.
 	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	std::string cap;
-	if (AISCommand::getCap(cap))
+	if (AISCommand::isAPIAvailable())
 	{
 		// cap-based category creation was buggy until recently. use
 		// existence of AIS as an indicator the fix is present. Does
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index e1fd2e02fa..0d99bea3fc 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1718,7 +1718,6 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
 	LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
 	if(cat)
 	{
-		bool accounted = false;
 		S32 version = cat->getVersion();
 		if(version != LLViewerInventoryCategory::VERSION_UNKNOWN)
 		{
@@ -1733,22 +1732,27 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
 			}
 			if(descendents_server == descendents_actual)
 			{
-				accounted = true;
 				descendents_actual += update.mDescendentDelta;
 				cat->setDescendentCount(descendents_actual);
 				cat->setVersion(++version);
-				lldebugs << "accounted: '" << cat->getName() << "' "
+				LL_DEBUGS("Inventory") << "accounted: '" << cat->getName() << "' "
 						 << version << " with " << descendents_actual
-						 << " descendents." << llendl;
+						 << " descendents." << LL_ENDL;
+			}
+			else
+			{
+				// Error condition, this means that the category did not register that
+				// it got new descendents (perhaps because it is still being loaded)
+				// which means its descendent count will be wrong.
+				llwarns << "Accounting failed for '" << cat->getName() << "' version:"
+						 << version << " due to mismatched descendent count:  server == "
+						 << descendents_server << ", viewer == " << descendents_actual << llendl;
 			}
 		}
-		if(!accounted)
+		else
 		{
-			// Error condition, this means that the category did not register that
-			// it got new descendents (perhaps because it is still being loaded)
-			// which means its descendent count will be wrong.
-			llwarns << "Accounting failed for '" << cat->getName() << "' version:"
-					 << version << llendl;
+			llwarns << "Accounting failed for '" << cat->getName() << "' version: unknown (" 
+					<< version << ")" << llendl;
 		}
 	}
 	else
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index c934dd991b..5beae8ec24 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -430,7 +430,7 @@ void LLViewerInventoryItem::fetchFromServer(void) const
 }
 
 // virtual
-BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
+BOOL LLViewerInventoryItem::unpackMessage(const LLSD& item)
 {
 	BOOL rv = LLInventoryItem::fromLLSD(item);
 
@@ -866,6 +866,21 @@ void LLViewerInventoryCategory::localizeName()
 	LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName);
 }
 
+// virtual
+BOOL LLViewerInventoryCategory::unpackMessage(const LLSD& category)
+{
+	BOOL rv = LLInventoryCategory::fromLLSD(category);
+	localizeName();
+	return rv;
+}
+
+// virtual
+void LLViewerInventoryCategory::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
+{
+	LLInventoryCategory::unpackMessage(msg, block, block_num);
+	localizeName();
+}
+
 ///----------------------------------------------------------------------------
 /// Local function definitions
 ///----------------------------------------------------------------------------
@@ -1159,24 +1174,22 @@ void update_inventory_item(
 	const LLSD& updates,
 	LLPointer<LLInventoryCallback> cb)
 {
-	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
-	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
-	if(obj)
+	bool ais_ran = false;
+	if (AISCommand::isAPIAvailable())
 	{
-		LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
-		new_item->copyViewerItem(obj);	
-		new_item->fromLLSD(updates,false);
-		
-		std::string cap;
-		if (AISCommand::getCap(cap))
-		{
-			LLSD new_llsd;
-			new_item->asLLSD(new_llsd);
-			LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, new_llsd, cb);
-			cmd_ptr->run_command();
-		}
-		else // no cap
+		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
+		ais_ran = cmd_ptr->run_command();
+	}
+	if (!ais_ran)
+	{
+		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+		if(obj)
 		{
+			LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+			new_item->copyViewerItem(obj);
+			new_item->fromLLSD(updates,false);
+
 			LLMessageSystem* msg = gMessageSystem;
 			msg->newMessageFast(_PREHASH_UpdateInventoryItem);
 			msg->nextBlockFast(_PREHASH_AgentData);
@@ -1216,9 +1229,8 @@ void update_inventory_category(
 
 		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
 		new_cat->fromLLSD(updates);
-		//std::string cap;
 		// FIXME - restore this once the back-end work has been done.
-		if (0) // if (AISCommand::getCap(cap))
+		if (0) // if (AISCommand::isAPIAvailable())
 		{
 			LLSD new_llsd = new_cat->asLLSD();
 			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
@@ -1254,8 +1266,7 @@ void remove_inventory_item(
 	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
 	if(obj)
 	{
-		std::string cap;
-		if (AISCommand::getCap(cap))
+		if (AISCommand::isAPIAvailable())
 		{
 			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
 			cmd_ptr->run_command();
@@ -1325,8 +1336,7 @@ void remove_inventory_category(
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
 			return;
 		}
-		std::string cap;
-		if (AISCommand::getCap(cap))
+		if (AISCommand::isAPIAvailable())
 		{
 			LLPointer<AISCommand> cmd_ptr = new RemoveCategoryCommand(cat_id, cb);
 			cmd_ptr->run_command();
@@ -1429,8 +1439,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		}
 		else
 		{
-			std::string cap;
-			if (AISCommand::getCap(cap))
+			if (AISCommand::isAPIAvailable())
 			{
 				LLPointer<AISCommand> cmd_ptr = new PurgeDescendentsCommand(id, cb);
 				cmd_ptr->run_command();
@@ -1564,8 +1573,7 @@ void slam_inventory_folder(const LLUUID& folder_id,
 						   const LLSD& contents,
 						   LLPointer<LLInventoryCallback> cb)
 {
-	std::string cap;
-	if (AISCommand::getCap(cap))
+	if (AISCommand::isAPIAvailable())
 	{
 		LL_DEBUGS("Avatar") << "using AISv3 to slam folder, id " << folder_id
 							<< " new contents: " << ll_pretty_print_sd(contents) << llendl;
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index de1f3daa1e..0d4ffaa575 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -124,7 +124,7 @@ public:
 
 	virtual void packMessage(LLMessageSystem* msg) const;
 	virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
-	virtual BOOL unpackMessage(LLSD item);
+	virtual BOOL unpackMessage(const LLSD& item);
 	virtual BOOL importFile(LLFILE* fp);
 	virtual BOOL importLegacyStream(std::istream& input_stream);
 
@@ -224,6 +224,8 @@ public:
 	bool importFileLocal(LLFILE* fp);
 	void determineFolderType();
 	void changeType(LLFolderType::EType new_folder_type);
+	virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
+	virtual BOOL unpackMessage(const LLSD& category);
 
 private:
 	friend class LLInventoryModel;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index dca1a5b542..ad046accd0 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -30,6 +30,7 @@
 
 // linden libraries
 #include "indra_constants.h"
+#include "llaisapi.h"
 #include "llavatarnamecache.h"		// name lookup cap url
 #include "llfloaterreg.h"
 #include "llmath.h"
@@ -1645,7 +1646,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 		capabilityNames.append("FetchInventory2");
 		capabilityNames.append("FetchInventoryDescendents2");
 		capabilityNames.append("IncrementCOFVersion");
-		capabilityNames.append("InventoryAPIv3");
+		AISCommand::getCapabilityNames(capabilityNames);
 	}
 
 	capabilityNames.append("GetDisplayNames");
@@ -1893,6 +1894,22 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
 	return iter->second;
 }
 
+bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const
+{
+	if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
+	{
+		llwarns << "isCapabilityAvailable called before caps received for " << name << llendl;
+	}
+	
+	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
+	if(iter == mImpl->mCapabilities.end())
+	{
+		return false;
+	}
+
+	return true;
+}
+
 bool LLViewerRegion::capabilitiesReceived() const
 {
 	return mCapabilitiesReceived;
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 5ac2a83aaf..4fb1b7402c 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -244,6 +244,7 @@ public:
 	S32 getNumSeedCapRetries();
 	void setCapability(const std::string& name, const std::string& url);
 	void setCapabilityDebug(const std::string& name, const std::string& url);
+	bool isCapabilityAvailable(const std::string& name) const;
 	// implements LLCapabilityProvider
     virtual std::string getCapability(const std::string& name) const;
 
-- 
cgit v1.2.3


From a428acf331dc63b2d6bac10101a8339e91a73adc Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 16 Jul 2013 17:08:24 -0400
Subject: SH-4333 FIX - turned on category patch now that AISv3 has it

---
 indra/newview/llaisapi.cpp          | 2 +-
 indra/newview/llappearancemgr.cpp   | 5 ++++-
 indra/newview/llviewerinventory.cpp | 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index cb8700865a..9389aeb3b4 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -794,7 +794,7 @@ void AISUpdate::doUpdate()
 	}
 
 	// DELETE OBJECTS
-	for (std::set<LLUUID>::const_iterator del_it = mObjectsDeletedIds.begin();
+	for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin();
 		 del_it != mObjectsDeletedIds.end(); ++del_it)
 	{
 		LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index fc07932860..3818bd8aec 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2115,7 +2115,10 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 		return;
 	}
 
-	llassert(validateClothingOrderingInfo());
+	if (!validateClothingOrderingInfo())
+	{
+		llwarns << "Clothing ordering error" << llendl;
+	}
 
 	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
 	selfStartPhase("update_appearance_from_cof");
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 5beae8ec24..5b4ca97319 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1230,7 +1230,7 @@ void update_inventory_category(
 		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
 		new_cat->fromLLSD(updates);
 		// FIXME - restore this once the back-end work has been done.
-		if (0) // if (AISCommand::isAPIAvailable())
+		if (AISCommand::isAPIAvailable())
 		{
 			LLSD new_llsd = new_cat->asLLSD();
 			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
-- 
cgit v1.2.3


From 7af477f796f9926dfec4aaa1336047b41144fbbb Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 17 Jul 2013 15:32:06 -0400
Subject: SH-4344 FIX - return the lowest UUID for a child of root with the
 desired preferred type. Also removed some duplicate code between
 findCategoryUUIDForType and findLibraryCategoryUUIDForType

---
 indra/newview/llinventorymodel.cpp | 63 ++++++++++++--------------------------
 indra/newview/llinventorymodel.h   |  5 +++
 2 files changed, 25 insertions(+), 43 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 0d99bea3fc..be1a396fff 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -388,16 +388,13 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
 	mItemLock[cat_id] = false;
 }
 
-// findCategoryUUIDForType() returns the uuid of the category that
-// specifies 'type' as what it defaults to containing. The category is
-// not necessarily only for that type. *NOTE: This will create a new
-// inventory category on the fly if one does not exist.
-const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*, 
-					  bool find_in_library*/)
+const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
+	LLFolderType::EType preferred_type,
+	bool create_folder,
+	const LLUUID& root_id)
 {
 	LLUUID rv = LLUUID::null;
 	
-	const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID();
 	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
 	{
 		rv = root_id;
@@ -413,14 +410,17 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe
 			{
 				if(cats->get(i)->getPreferredType() == preferred_type)
 				{
-					rv = cats->get(i)->getUUID();
-					break;
+					const LLUUID& folder_id = cats->get(i)->getUUID();
+					if (rv.isNull() || folder_id < rv)
+					{
+						rv = folder_id;
+					}
 				}
 			}
 		}
 	}
 	
-	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/))
+	if(rv.isNull() && isInventoryUsable() && create_folder)
 	{
 		if(root_id.notNull())
 		{
@@ -430,41 +430,18 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe
 	return rv;
 }
 
-const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
+// findCategoryUUIDForType() returns the uuid of the category that
+// specifies 'type' as what it defaults to containing. The category is
+// not necessarily only for that type. *NOTE: This will create a new
+// inventory category on the fly if one does not exist.
+const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
 {
-	LLUUID rv = LLUUID::null;
-
-	const LLUUID &root_id = gInventory.getLibraryRootFolderID();
-	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
-	{
-		rv = root_id;
-	}
-	else if (root_id.notNull())
-	{
-		cat_array_t* cats = NULL;
-		cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
-		if(cats)
-		{
-			S32 count = cats->count();
-			for(S32 i = 0; i < count; ++i)
-			{
-				if(cats->get(i)->getPreferredType() == preferred_type)
-				{
-					rv = cats->get(i)->getUUID();
-					break;
-				}
-			}
-		}
-	}
+	return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getRootFolderID());
+}
 
-	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/))
-	{
-		if(root_id.notNull())
-		{
-			return createNewCategory(root_id, preferred_type, LLStringUtil::null);
-		}
-	}
-	return rv;
+const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
+{
+	return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getLibraryRootFolderID());
 }
 
 class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index ee0d4e1994..2852a8da45 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -230,6 +230,11 @@ public:
 	// Find
 	//--------------------------------------------------------------------
 public:
+	const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
+		LLFolderType::EType preferred_type,
+		bool create_folder,
+		const LLUUID& root_id);
+
 	// Returns the uuid of the category that specifies 'type' as what it 
 	// defaults to containing. The category is not necessarily only for that type. 
 	//    NOTE: If create_folder is true, this will create a new inventory category 
-- 
cgit v1.2.3


From 47fabf5770bbb1b2f8272bb77ebdc993cda7c033 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 17 Jul 2013 18:13:24 -0400
Subject: fix for build failure mac, linux

---
 indra/newview/llinventorymodel.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 2852a8da45..7afe1dea35 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -230,7 +230,7 @@ public:
 	// Find
 	//--------------------------------------------------------------------
 public:
-	const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
+	const LLUUID findCategoryUUIDForTypeInRoot(
 		LLFolderType::EType preferred_type,
 		bool create_folder,
 		const LLUUID& root_id);
-- 
cgit v1.2.3


From a1ece43905db86cb6953ce9848228122637e5708 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Thu, 18 Jul 2013 16:31:50 -0400
Subject: SH-3875 FIX Failure to bake face wrinkles

Wrinkles have been a deprecated/non-functional feature for a few years now.
Removing the user-facing sliders to prevent confusion.
---
 indra/llcharacter/llvisualparam.h      |  1 +
 indra/newview/character/avatar_lad.xml |  8 ++++----
 indra/newview/llagent.cpp              |  3 ++-
 indra/newview/llvoavatar.cpp           | 12 ++++++++----
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index 60ea7a369a..a4d9f93e56 100755
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -47,6 +47,7 @@ enum EVisualParamGroup
 	VISUAL_PARAM_GROUP_TWEAKABLE,
 	VISUAL_PARAM_GROUP_ANIMATABLE,
 	VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT,
+	VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE, // deprecated params that used to be tweakable.
 	NUM_VISUAL_PARAM_GROUPS
 };
 
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index 284e9c44b2..d2ee09bcb5 100755
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -7564,7 +7564,7 @@ render_pass="bump">
 
       <param
        id="868"
-       group="0"
+       group="3"
        wearable="shirt"
        edit_group="shirt"
        edit_group_order="8"
@@ -8687,7 +8687,7 @@ render_pass="bump">
 
       <param
        id="869"
-       group="0"
+       group="3"
        wearable="pants"
        edit_group="pants"
        edit_group_order="6"
@@ -9608,7 +9608,7 @@ render_pass="bump">
 
     <param
      id="163"
-     group="0"
+     group="3"
      wearable="skin"
      edit_group="skin_facedetail"
      edit_group_order="3"
@@ -11667,7 +11667,7 @@ render_pass="bump">
 
     <param
      id="877"
-     group="0"
+     group="3"
      name="Jacket Wrinkles"
      label="Jacket Wrinkles"
      wearable="jacket"
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 21625815b9..1c27811351 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4419,7 +4419,8 @@ void LLAgent::sendAgentSetAppearance()
 		 param;
 		 param = (LLViewerVisualParam*)gAgentAvatarp->getNextVisualParam())
 	{
-		if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) // do not transmit params of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ||
+			param->getGroup() == VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE) // do not transmit params of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		{
 			msg->nextBlockFast(_PREHASH_VisualParam );
 			
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 74fb51b943..96afd2e15d 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6797,7 +6797,8 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
 	LLVisualParam* param = getFirstVisualParam();
 	for (S32 i = 0; i < params_for_dump.size(); i++)
 	{
-		while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && 
+						 (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		{
 			param = getNextVisualParam();
 		}
@@ -6851,7 +6852,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 		{
 			for( S32 i = 0; i < num_blocks; i++ )
 			{
-				while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+				while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && 
+								 (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 				{
 					param = getNextVisualParam();
 				}
@@ -6872,7 +6874,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 			}
 		}
 
-		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) +
+											 getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		if (num_blocks != expected_tweakable_count)
 		{
 			LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << ").  Processing what we can.  object: " << getID() << llendl;
@@ -7093,7 +7096,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 				}
 			}
 		}
-		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+		const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) +
+											 getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
 		if (num_params != expected_tweakable_count)
 		{
 			LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << ").  Processing what we can.  object: " << getID() << llendl;
-- 
cgit v1.2.3


From 3d8d4227f1930f986c3b70227de98c12830c874a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 19 Jul 2013 17:22:53 -0400
Subject: SH-3889 WIP - added callbacks to control ordering of operations after
 wearable save.

---
 indra/newview/llagentwearables.cpp    | 29 ++++++++++-------------
 indra/newview/llagentwearables.h      |  4 ++--
 indra/newview/llpaneleditwearable.cpp | 22 +++++-------------
 indra/newview/llviewerinventory.cpp   | 43 +++++++++++++++++++++++++++++++++++
 indra/newview/llviewerinventory.h     |  4 ++++
 indra/newview/llvoavatarself.cpp      | 12 ++++++++--
 indra/newview/llvoavatarself.h        |  2 ++
 7 files changed, 79 insertions(+), 37 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 93ccec7d49..8c33a778e3 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -209,7 +209,7 @@ LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCal
  * @param wearable The wearable data.
  * @param todo Bitmask of actions to take on completion.
  */
-LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback(
+LLAgentWearables::AddWearableToAgentInventoryCallback::AddWearableToAgentInventoryCallback(
 	LLPointer<LLRefCount> cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo, const std::string description) :
 	mType(type),
 	mIndex(index),	
@@ -221,7 +221,7 @@ LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInvento
 	llinfos << "constructor" << llendl;
 }
 
-void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
+void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
 {
 	if (mTodo & CALL_CREATESTANDARDDONE)
 	{
@@ -317,12 +317,12 @@ void LLAgentWearables::sendAgentWearablesUpdate()
 				if (wearable->getItemID().isNull())
 				{
 					LLPointer<LLInventoryCallback> cb =
-						new addWearableToAgentInventoryCallback(
+						new AddWearableToAgentInventoryCallback(
 							LLPointer<LLRefCount>(NULL),
 							(LLWearableType::EType)type,
 							index,
 							wearable,
-							addWearableToAgentInventoryCallback::CALL_NONE);
+							AddWearableToAgentInventoryCallback::CALL_NONE);
 					addWearableToAgentInventory(cb, wearable);
 				}
 				else
@@ -419,23 +419,18 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
 										  item->getFlags(),
 										  item->getCreationDate());
 			template_item->setTransactionID(new_wearable->getTransactionID());
-			template_item->updateServer(FALSE);
-			gInventory.updateItem(template_item);
-			if (name_changed)
-			{
-				gInventory.notifyObservers();
-			}
+			update_inventory_item(template_item, gAgentAvatarp->mEndCustomizeCallback);
 		}
 		else
 		{
 			// Add a new inventory item (shouldn't ever happen here)
-			U32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
+			U32 todo = AddWearableToAgentInventoryCallback::CALL_NONE;
 			if (send_update)
 			{
-				todo |= addWearableToAgentInventoryCallback::CALL_UPDATE;
+				todo |= AddWearableToAgentInventoryCallback::CALL_UPDATE;
 			}
 			LLPointer<LLInventoryCallback> cb =
-				new addWearableToAgentInventoryCallback(
+				new AddWearableToAgentInventoryCallback(
 					LLPointer<LLRefCount>(NULL),
 					type,
 					index,
@@ -484,12 +479,12 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type,
 		old_wearable,
 		trunc_name);
 	LLPointer<LLInventoryCallback> cb =
-		new addWearableToAgentInventoryCallback(
+		new AddWearableToAgentInventoryCallback(
 			LLPointer<LLRefCount>(NULL),
 			type,
 			index,
 			new_wearable,
-			addWearableToAgentInventoryCallback::CALL_WEARITEM,
+			AddWearableToAgentInventoryCallback::CALL_WEARITEM,
 			description
 			);
 	LLUUID category_id;
@@ -909,12 +904,12 @@ void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type,
 	// destory content.) JC
 	const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 	LLPointer<LLInventoryCallback> cb =
-		new addWearableToAgentInventoryCallback(
+		new AddWearableToAgentInventoryCallback(
 			LLPointer<LLRefCount>(NULL),
 			type,
 			index,
 			new_wearable,
-			addWearableToAgentInventoryCallback::CALL_RECOVERDONE);
+			AddWearableToAgentInventoryCallback::CALL_RECOVERDONE);
 	addWearableToAgentInventory(cb, new_wearable, lost_and_found_id, TRUE);
 }
 
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index b0ac988341..8a1b470e22 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -249,7 +249,7 @@ private:
 		~sendAgentWearablesUpdateCallback();
 	};
 
-	class addWearableToAgentInventoryCallback : public LLInventoryCallback
+	class AddWearableToAgentInventoryCallback : public LLInventoryCallback
 	{
 	public:
 		enum ETodo
@@ -262,7 +262,7 @@ private:
 			CALL_WEARITEM = 16
 		};
 
-		addWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
+		AddWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
 											LLWearableType::EType type,
 											U32 index,
 											LLViewerWearable* wearable,
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 580e31591c..a1222424ee 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1079,13 +1079,8 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 
         if (force_save_as)
         {
-			// FIXME race condition if removeCOFItemLinks does not
-			// complete immediately.  Looks like we're counting on the
-			// fact that updateAppearanceFromCOF will get called after
-			// we exit customize mode.
-
 			// the name of the wearable has changed, re-save wearable with new name
-			LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID());
+			LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),gAgentAvatarp->mEndCustomizeCallback);
 			gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE);
 			mNameEditor->setText(mWearableItem->getName());
         }
@@ -1096,24 +1091,19 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 			// version so texture baking service knows appearance has changed.
 			if (link_item)
 			{
-				// FIXME - two link-modifying calls here plus one
-				// inventory change request, none of which use a
-				// callback. When does a new appearance request go out
-				// and how is it synced with these changes?  As above,
-				// we seem to be implicitly depending on
-				// updateAppearanceFromCOF() to be called when we
-				// exit customize mode.
-
 				// Create new link
+				LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
+									<< " removing old link at " << link_item->getUUID()
+									<< " wearable item id " << mWearablePtr->getItemID() << llendl;
 				link_inventory_item( gAgent.getID(),
 									 link_item->getLinkedUUID(),
 									 LLAppearanceMgr::instance().getCOF(),
 									 link_item->getName(),
 									 description,
 									 LLAssetType::AT_LINK,
-									 NULL);
+									 gAgentAvatarp->mEndCustomizeCallback);
 				// Remove old link
-				remove_inventory_item(link_item->getUUID(), NULL);
+				remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
 			}
 			gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
         }
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 5b4ca97319..bff6767617 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1166,6 +1166,49 @@ void move_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
+// Should call this with an update_item that's been copied and
+// modified from an original source item, rather than modifying the
+// source item directly.
+void update_inventory_item(
+	LLViewerInventoryItem *update_item,
+	LLPointer<LLInventoryCallback> cb)
+{
+	const LLUUID& item_id = update_item->getUUID();
+	bool ais_ran = false;
+	if (AISCommand::isAPIAvailable())
+	{
+		LLSD updates = update_item->asLLSD();
+		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
+		ais_ran = cmd_ptr->run_command();
+	}
+	if (!ais_ran)
+	{
+		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << llendl;
+		if(obj)
+		{
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_UpdateInventoryItem);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->addUUIDFast(_PREHASH_TransactionID, update_item->getTransactionID());
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addU32Fast(_PREHASH_CallbackID, 0);
+			update_item->packMessage(msg);
+			gAgent.sendReliableMessage();
+
+			LLInventoryModel::LLCategoryUpdate up(update_item->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateItem(update_item);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
+		}
+	}
+}
+
 // Note this only supports updating an existing item. Goes through AISv3
 // code path where available. Not all uses of item->updateServer() can
 // easily be switched to this paradigm.
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 0d4ffaa575..6bc6343f3f 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -368,6 +368,10 @@ void move_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
+void update_inventory_item(
+	LLViewerInventoryItem *update_item,
+	LLPointer<LLInventoryCallback> cb);
+
 void update_inventory_item(
 	const LLUUID& item_id,
 	const LLSD& updates,
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 232bf3e478..05bd3101ea 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2978,6 +2978,11 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch)
 {
 	if (isAgentAvatarValid())
 	{
+		if (!gAgentAvatarp->mEndCustomizeCallback.get())
+		{
+			gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy;
+		}
+		
 		gAgentAvatarp->mIsEditingAppearance = true;
 		gAgentAvatarp->mUseLocalAppearance = true;
 
@@ -3017,8 +3022,11 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch)
 			gAgentCamera.changeCameraToDefault();
 			gAgentCamera.resetView();
 		}
-	
-		LLAppearanceMgr::instance().updateAppearanceFromCOF();	
+
+		// Dereferencing the previous callback will cause
+		// updateAppearanceFromCOF to be called, whenever all refs
+		// have resolved.
+		gAgentAvatarp->mEndCustomizeCallback = NULL;
 	}
 }
 
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index e8b9a25327..3cbf2b5cf5 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -32,6 +32,7 @@
 #include "llvoavatar.h"
 
 struct LocalTextureData;
+class LLInventoryCallback;
 
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -342,6 +343,7 @@ private:
 public:
 	static void		onCustomizeStart(bool disable_camera_switch = false);
 	static void		onCustomizeEnd(bool disable_camera_switch = false);
+	LLPointer<LLInventoryCallback> mEndCustomizeCallback;
 
 	//--------------------------------------------------------------------
 	// Visibility
-- 
cgit v1.2.3


From 28a5015074e3f6e0ba961dc260edcb9662e6f14b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 22 Jul 2013 17:07:45 -0400
Subject: SH-4333 WIP - do version accounting for category when updated

---
 indra/newview/llaisapi.cpp | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 9389aeb3b4..f8c9447b17 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -548,6 +548,8 @@ void AISUpdate::parseCategory(const LLSD& category_map)
 			// delta to be created if it does not already exist;
 			// otherwise has no effect.
 			mCatDescendentDeltas[new_cat->getParentUUID()];
+			// Capture update for the category itself as well.
+			mCatDescendentDeltas[category_id];
 		}
 		else
 		{
@@ -699,6 +701,8 @@ void AISUpdate::doUpdate()
 	for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
 		 catit != mCatDescendentDeltas.end(); ++catit)
 	{
+		LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << llendl;
+
 		const LLUUID cat_id(catit->first);
 		// Don't account for update if we just created this category.
 		if (mCategoriesCreated.find(cat_id) != mCategoriesCreated.end())
@@ -720,7 +724,8 @@ void AISUpdate::doUpdate()
 		{
 			S32 descendent_delta = catit->second;
 			S32 old_count = cat->getDescendentCount();
-			LL_DEBUGS("Inventory") << "Updating descendent count for " << cat_id
+			LL_DEBUGS("Inventory") << "Updating descendent count for "
+								   << cat->getName() << " " << cat_id
 								   << " with delta " << descendent_delta << " from "
 								   << old_count << " to " << (old_count+descendent_delta) << LL_ENDL;
 			LLInventoryModel::LLCategoryUpdate up(cat_id, descendent_delta);
@@ -761,7 +766,7 @@ void AISUpdate::doUpdate()
 			new_category->setVersion(curr_cat->getVersion());
 			new_category->setDescendentCount(curr_cat->getDescendentCount());
 			gInventory.updateCategory(new_category);
-			LL_DEBUGS("Inventory") << "updated category " << category_id << LL_ENDL;
+			LL_DEBUGS("Inventory") << "updated category " << new_category->getName() << " " << category_id << LL_ENDL;
 		}
 	}
 
-- 
cgit v1.2.3


From a1fadad9c0bd1ba261f827d6da572db5621f5bed Mon Sep 17 00:00:00 2001
From: prep <prep@lindenlab.com>
Date: Wed, 24 Jul 2013 16:01:36 -0400
Subject: Sh-4321 # Fixes for detach deformations. General code cleanup as
 well.

---
 indra/llappearance/llpolyskeletaldistortion.cpp | 12 ++--
 indra/llcharacter/lljoint.cpp                   | 43 +++++++-------
 indra/llcharacter/lljoint.h                     |  7 +--
 indra/newview/llvoavatar.cpp                    | 74 ++++++++++---------------
 indra/newview/llvoavatar.h                      |  1 -
 indra/newview/llvoavatarself.cpp                |  5 --
 indra/newview/llvovolume.cpp                    | 51 +++++++++--------
 7 files changed, 89 insertions(+), 104 deletions(-)

diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index 4ba16691c2..eb86f77d97 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -192,7 +192,7 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
 {
 	LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
 
-        F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
+	F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
 
         LLJoint* joint;
         joint_vec_map_t::iterator iter;
@@ -204,8 +204,10 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
                 joint = iter->first;
                 LLVector3 newScale = joint->getScale();
                 LLVector3 scaleDelta = iter->second;
-                newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
-                joint->setScale(newScale);
+                newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);				                
+				//An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached
+				joint->storeScaleForReset( newScale );				
+				joint->setScale(newScale);
         }
 
         for (iter = mJointOffsets.begin();
@@ -214,8 +216,8 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
         {
                 joint = iter->first;
                 LLVector3 newPosition = joint->getPosition();
-                LLVector3 positionDelta = iter->second;
-                newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
+                LLVector3 positionDelta = iter->second;				
+                newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);		
                 joint->setPosition(newPosition);
         }
 
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 09a7c11a22..672d9faee4 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -48,8 +48,11 @@ void LLJoint::init()
 	mParent = NULL;
 	mXform.setScaleChildOffset(TRUE);
 	mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
+	mOldXform.setScaleChildOffset(TRUE);
+	mOldXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
 	mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
 	mUpdateXform = TRUE;
+	mResetAfterRestoreOldXform = false;	
 }
 
 LLJoint::LLJoint() :
@@ -57,7 +60,6 @@ LLJoint::LLJoint() :
 {
 	init();
 	touch();
-	mResetAfterRestoreOldXform = false;
 }
 
 LLJoint::LLJoint(S32 joint_num) :
@@ -65,7 +67,6 @@ LLJoint::LLJoint(S32 joint_num) :
 {
 	init();
 	touch();
-	mResetAfterRestoreOldXform = false;
 }
 
 
@@ -78,7 +79,6 @@ LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
 {
 	init();
 	mUpdateXform = FALSE;
-	// *TODO: mResetAfterRestoreOldXform is not initialized!!!
 
 	setName(name);
 	if (parent)
@@ -239,11 +239,8 @@ const LLVector3& LLJoint::getPosition()
 //--------------------------------------------------------------------
 void LLJoint::setPosition( const LLVector3& pos )
 {
-//	if (mXform.getPosition() != pos)
-	{
-		mXform.setPosition(pos);
-		touch(MATRIX_DIRTY | POSITION_DIRTY);
-	}
+	mXform.setPosition(pos);
+	touch(MATRIX_DIRTY | POSITION_DIRTY);
 }
 
 
@@ -251,10 +248,9 @@ void LLJoint::setPosition( const LLVector3& pos )
 // setPosition()
 //--------------------------------------------------------------------
 void LLJoint::setDefaultFromCurrentXform( void )
-{
+{	
 	mDefaultXform = mXform;
-	touch(MATRIX_DIRTY | POSITION_DIRTY);
-	
+	touch(ALL_DIRTY);	
 }
 
 //--------------------------------------------------------------------
@@ -263,26 +259,29 @@ void LLJoint::setDefaultFromCurrentXform( void )
 void LLJoint::storeCurrentXform( const LLVector3& pos )
 {
 	mOldXform = mXform;
-	mResetAfterRestoreOldXform = true;
+	mResetAfterRestoreOldXform = true;	
 	setPosition( pos );
+
+	touch(ALL_DIRTY);	
 }
+
 //--------------------------------------------------------------------
-// restoreOldXform()
+// storeScaleForReset()
 //--------------------------------------------------------------------
-void LLJoint::restoreOldXform( void )
+void LLJoint::storeScaleForReset( const LLVector3& scale )
 {
-	mResetAfterRestoreOldXform = false;
-	mXform = mOldXform;
+	mOldXform.setScale( scale );
 }
 //--------------------------------------------------------------------
 // restoreOldXform()
 //--------------------------------------------------------------------
-void LLJoint::restoreToDefaultXform( void )
+void LLJoint::restoreOldXform( void )
 {	
-	mXform = mDefaultXform;
-	setPosition( mXform.getPosition() );	
+	mXform = mOldXform;
+	mXform.setScaleChildOffset( mOldXform.getScaleChildOffset() );
+	mResetAfterRestoreOldXform = false;
+	mDirtyFlags = ALL_DIRTY;
 }
-
 //--------------------------------------------------------------------
 // getWorldPosition()
 //--------------------------------------------------------------------
@@ -404,7 +403,7 @@ void LLJoint::setWorldRotation( const LLQuaternion& rot )
 //--------------------------------------------------------------------
 const LLVector3& LLJoint::getScale()
 {
-	return mXform.getScale();
+	return mXform.getScale();	
 }
 
 //--------------------------------------------------------------------
@@ -413,7 +412,7 @@ const LLVector3& LLJoint::getScale()
 void LLJoint::setScale( const LLVector3& scale )
 {
 //	if (mXform.getScale() != scale)
-	{
+	{	
 		mXform.setScale(scale);
 		touch();
 	}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 2b1e2005c6..aeb16f796a 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -84,6 +84,7 @@ protected:
 	LLXformMatrix		mDefaultXform;
 
 	LLUUID				mId;
+
 public:
 	U32				mDirtyFlags;
 	BOOL			mUpdateXform;
@@ -160,7 +161,7 @@ public:
 	// get/set local scale
 	const LLVector3& getScale();
 	void setScale( const LLVector3& scale );
-
+	void storeScaleForReset( const LLVector3& scale );
 	// get/set world matrix
 	const LLMatrix4 &getWorldMatrix();
 	void setWorldMatrix( const LLMatrix4& mat );
@@ -185,7 +186,6 @@ public:
 	S32 getJointNum() const { return mJointNum; }
 	
 	void restoreOldXform( void );
-	void restoreToDefaultXform( void );
 	void setDefaultFromCurrentXform( void );
 	void storeCurrentXform( const LLVector3& pos );
 
@@ -196,8 +196,7 @@ public:
 
 	//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
 	const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
-	//Setter for joint reset flag
-	void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
+	
 };
 #endif // LL_LLJOINT_H
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 96afd2e15d..83b7ac9e75 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -106,7 +106,7 @@ extern F32 SPEED_ADJUST_MAX;
 extern F32 SPEED_ADJUST_MAX_SEC;
 extern F32 ANIM_SPEED_MAX;
 extern F32 ANIM_SPEED_MIN;
-
+extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
 
 // #define OUTPUT_BREAST_DATA
 
@@ -1234,6 +1234,7 @@ LLTexLayerSet* LLVOAvatar::createTexLayerSet()
 
 const LLVector3 LLVOAvatar::getRenderPosition() const
 {
+
 	if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
 	{
 		return getPositionAgent();
@@ -1256,6 +1257,8 @@ const LLVector3 LLVOAvatar::getRenderPosition() const
 	{
 		return getPosition() * mDrawable->getParent()->getRenderMatrix();
 	}
+	
+	
 }
 
 void LLVOAvatar::updateDrawable(BOOL force_damped)
@@ -2992,7 +2995,7 @@ bool LLVOAvatar::isVisuallyMuted() const
 // called on both your avatar and other avatars
 //------------------------------------------------------------------------
 BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
-{
+{	
 	// clear debug text
 	mDebugText.clear();
 
@@ -3540,9 +3543,9 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount,
 {
 	mHasPelvisOffset = hasOffset;
 	if ( mHasPelvisOffset )
-	{
+	{	
 		//Store off last pelvis to foot value
-		mLastPelvisToFoot = mPelvisToFoot;
+		mLastPelvisToFoot = mPelvisToFoot;		
 		mPelvisOffset	  = offsetAmount;
 		mLastPelvisFixup  = mPelvisFixup;
 		mPelvisFixup	  = pelvisFixup;
@@ -3552,18 +3555,16 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount,
 // postPelvisSetRecalc
 //------------------------------------------------------------------------
 void LLVOAvatar::postPelvisSetRecalc( void )
-{	
-	computeBodySize(); 
-	mRoot->touch();
-	mRoot->updateWorldMatrixChildren();	
-	dirtyMesh();
-	updateHeadOffset();
+{		
+	mRoot->updateWorldMatrixChildren();			
+	computeBodySize();
+	dirtyMesh(2);
 }
 //------------------------------------------------------------------------
-// pelisPoke
+// setPelvisOffset
 //------------------------------------------------------------------------
 void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
-{	
+{		
 	mHasPelvisOffset  = true;
 	mLastPelvisFixup  = mPelvisFixup;	
 	mPelvisFixup	  = pelvisFixupAmount;	
@@ -4925,22 +4926,6 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
 
 	return jointp;
 }
-
-//-----------------------------------------------------------------------------
-// resetJointPositions
-//-----------------------------------------------------------------------------
-void LLVOAvatar::resetJointPositions( void )
-{
-	avatar_joint_list_t::iterator iter = mSkeleton.begin();
-	avatar_joint_list_t::iterator end  = mSkeleton.end();
-	for (; iter != end; ++iter)
-	{
-		(*iter)->restoreOldXform();
-		(*iter)->setId( LLUUID::null );
-	}
-	mHasPelvisOffset = false;
-	mPelvisFixup	 = mLastPelvisFixup;
-}
 //-----------------------------------------------------------------------------
 // resetSpecificJointPosition
 //-----------------------------------------------------------------------------
@@ -4967,28 +4952,25 @@ void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
 // resetJointPositionsToDefault
 //-----------------------------------------------------------------------------
 void LLVOAvatar::resetJointPositionsToDefault( void )
-{
+{	
 	//Subsequent joints are relative to pelvis
 	avatar_joint_list_t::iterator iter = mSkeleton.begin();
 	avatar_joint_list_t::iterator end  = mSkeleton.end();
 	for (; iter != end; ++iter)
 	{
 		LLJoint* pJoint = (*iter);
-		if ( pJoint->doesJointNeedToBeReset() )
-		{
+		if ( pJoint && pJoint->doesJointNeedToBeReset() )
+		{			
 			pJoint->setId( LLUUID::null );
-			//restore joints to default positions, however skip over the pelvis
-			// *TODO: How does this pointer check skip over pelvis?
-			if ( pJoint )
-			{
-				pJoint->restoreOldXform();
-			}
-		}
+			pJoint->restoreOldXform();
+		}		
 	}
+
 	//make sure we don't apply the joint offset
 	mHasPelvisOffset = false;
 	mPelvisFixup	 = mLastPelvisFixup;
-	postPelvisSetRecalc();
+
+	postPelvisSetRecalc();	
 }
 //-----------------------------------------------------------------------------
 // getCharacterPosition()
@@ -5604,10 +5586,10 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 		{
 			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
 			if (pSkinData 
-				&& pSkinData->mJointNames.size() > 20				// full rig
-				&& pSkinData->mAlternateBindMatrix.size() > 0)
-					{
-						LLVOAvatar::resetJointPositionsToDefault();
+				&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG	// full rig
+				&& pSkinData->mAlternateBindMatrix.size() > 0 )
+					{				
+						LLVOAvatar::resetJointPositionsToDefault();							
 						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing 
 						//This handles the case where we detach a replacement rig.
 						if ( gAgentCamera.cameraCustomizeAvatar() )
@@ -5625,6 +5607,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
 {
+
 	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end();
 		 ++iter)
@@ -5633,7 +5616,9 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
 		
 		if (attachment->isObjectAttached(viewer_object))
 		{
+		
 			cleanupAttachedMesh( viewer_object );
+		
 			attachment->removeObject(viewer_object);
 			lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
 			return TRUE;
@@ -6942,7 +6927,7 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 {
 	LL_DEBUGS("Avatar") << "starts" << llendl;
-	
+
 	bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
 	std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_";
 	if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages"))
@@ -7153,7 +7138,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	}
 
 	updateMeshTextures();
-
 	//if (enable_verbose_dumps) dumpArchetypeXML(dump_prefix + "process_end");
 }
 
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 48b5a6e873..90ade85177 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -199,7 +199,6 @@ public:
 
 	virtual LLJoint*		getJoint(const std::string &name);
 	
-	void					resetJointPositions( void );
 	void					resetJointPositionsToDefault( void );
 	void					resetSpecificJointPosition( const std::string& name );
 	
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 05bd3101ea..a710c95233 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -671,11 +671,6 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
 	}
 	return LLVOAvatar::getJoint(name);
 }
-//virtual
-void LLVOAvatarSelf::resetJointPositions( void )
-{
-	return LLVOAvatar::resetJointPositions();
-}
 // virtual
 BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake )
 {
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 8730ef66bb..135c2e1eca 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -81,7 +81,7 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30;
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
 const F32 FORCE_CULL_AREA = 8.f;
 const F32 MAX_LOD_DISTANCE = 24.f;
-
+U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20;
 
 BOOL gAnimateTextures = TRUE;
 //extern BOOL gHideSelectedObjects;
@@ -4236,6 +4236,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	bool emissive = false;
 
+	//Determine if we've received skininfo that contains an
+	//alternate bind matrix - if it does then apply the translational component
+	//to the joints of the avatar.
+	bool pelvisGotSet = false;
+
 	{
 		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST);
 
@@ -4317,18 +4322,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 					is_rigged = true;
 				
 					//get drawpool of avatar with rigged face
-					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
-				
-					//Determine if we've received skininfo that contains an
-					//alternate bind matrix - if it does then apply the translational component
-					//to the joints of the avatar.
-					bool pelvisGotSet = false;
-
+					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);				
+					
 					if ( pAvatarVO )
 					{
-						LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
+						LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						
 						const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
-					
 						if ( pSkinData )
 						{
 							const int bindCnt = pSkinData->mAlternateBindMatrix.size();								
@@ -4336,43 +4335,42 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{					
 								const int jointCnt = pSkinData->mJointNames.size();
 								const F32 pelvisZOffset = pSkinData->mPelvisOffset;
-								bool fullRig = (jointCnt>=20) ? true : false;
+								bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								
 								if ( fullRig )
-								{
+								{								
 									for ( int i=0; i<jointCnt; ++i )
 									{
 										std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
-										//llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl;
 										LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint );
 										if ( pJoint && pJoint->getId() != currentId )
 										{   									
 											pJoint->setId( currentId );
 											const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									
+											
 											//Set the joint position
-											pJoint->storeCurrentXform( jointPos );																																
+											pJoint->storeCurrentXform( jointPos );					
+									
 											//If joint is a pelvis then handle old/new pelvis to foot values
 											if ( lookingForJoint == "mPelvis" )
 											{	
-												pJoint->storeCurrentXform( jointPos );																																
 												if ( !pAvatarVO->hasPelvisOffset() )
 												{										
 													pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset );
-													//Trigger to rebuild viewer AV
 													pelvisGotSet = true;											
 												}										
 											}										
-										}
-									}
+										}										
+									}																
 								}							
 							}
 						}
 					}
-					//If we've set the pelvis to a new position we need to also rebuild some information that the
-					//viewer does at launch (e.g. body size etc.)
-					if ( pelvisGotSet )
+					
+					//Rebuild body data if we altered joints/pelvis
+					if ( pelvisGotSet && pAvatarVO ) 
 					{
 						pAvatarVO->postPelvisSetRecalc();
-					}
+					}		
 
 					if (pool)
 					{
@@ -4605,7 +4603,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 			{
 				drawablep->clearState(LLDrawable::RIGGED);
 			}
+			
 		}
+
+		
+		
+			
+		
+					
+
+		
 	}
 
 	group->mBufferUsage = useage;
-- 
cgit v1.2.3


From 8b612cab394dc46b52a359b2b24863c49a5bd2d7 Mon Sep 17 00:00:00 2001
From: "prep@lindenlab.com" <prep@lindenlab.com>
Date: Tue, 6 Aug 2013 16:44:01 -0500
Subject: Fixes for SH-4321. Also removed some unnecessary transform updates,
 and unused joint resetting code

---
 indra/llcharacter/lljoint.cpp | 13 ++++--------
 indra/llcharacter/lljoint.h   |  1 +
 indra/newview/llvoavatar.cpp  | 49 +++++++++++++++++++------------------------
 indra/newview/llvoavatar.h    |  3 +--
 4 files changed, 27 insertions(+), 39 deletions(-)

diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 672d9faee4..5cd33fe709 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -248,20 +248,18 @@ void LLJoint::setPosition( const LLVector3& pos )
 // setPosition()
 //--------------------------------------------------------------------
 void LLJoint::setDefaultFromCurrentXform( void )
-{	
+{		
 	mDefaultXform = mXform;
-	touch(ALL_DIRTY);	
 }
 
 //--------------------------------------------------------------------
 // storeCurrentXform()
 //--------------------------------------------------------------------
 void LLJoint::storeCurrentXform( const LLVector3& pos )
-{
+{	
 	mOldXform = mXform;
 	mResetAfterRestoreOldXform = true;	
 	setPosition( pos );
-
 	touch(ALL_DIRTY);	
 }
 
@@ -277,10 +275,9 @@ void LLJoint::storeScaleForReset( const LLVector3& scale )
 //--------------------------------------------------------------------
 void LLJoint::restoreOldXform( void )
 {	
-	mXform = mOldXform;
-	mXform.setScaleChildOffset( mOldXform.getScaleChildOffset() );
+	mXform = mDefaultXform;
 	mResetAfterRestoreOldXform = false;
-	mDirtyFlags = ALL_DIRTY;
+	mDirtyFlags = ALL_DIRTY;	
 }
 //--------------------------------------------------------------------
 // getWorldPosition()
@@ -298,8 +295,6 @@ LLVector3 LLJoint::getLastWorldPosition()
 {
 	return mXform.getWorldPosition();
 }
-
-
 //--------------------------------------------------------------------
 // setWorldPosition()
 //--------------------------------------------------------------------
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index aeb16f796a..a6a439a965 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -196,6 +196,7 @@ public:
 
 	//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
 	const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
+	void setJointResetFlag( bool val ) { mResetAfterRestoreOldXform = val; }
 	
 };
 #endif // LL_LLJOINT_H
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 83b7ac9e75..a0a2ce0caf 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1294,6 +1294,8 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
 		mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition();
 		mDrawable->setPositionGroup(pos_group);
 	}
+	
+	
 }
 
 void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
@@ -3510,6 +3512,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	//mesh vertices need to be reskinned
 	mNeedsSkin = TRUE;
 
+
+		
+	
 	return TRUE;
 }
 //-----------------------------------------------------------------------------
@@ -4927,28 +4932,6 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
 	return jointp;
 }
 //-----------------------------------------------------------------------------
-// resetSpecificJointPosition
-//-----------------------------------------------------------------------------
-void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
-{
-	LLJoint* pJoint = mRoot->findJoint( name );
-	
-	if ( pJoint  && pJoint->doesJointNeedToBeReset() )
-	{
-		pJoint->restoreOldXform();
-		pJoint->setId( LLUUID::null );
-		//If we're reseting the pelvis position make sure not to apply offset
-		if ( name == "mPelvis" )
-		{
-			mHasPelvisOffset = false;
-		}
-	}
-	else
-	{
-		llinfos<<"Did not find "<< name.c_str()<<llendl;
-	}
-}
-//-----------------------------------------------------------------------------
 // resetJointPositionsToDefault
 //-----------------------------------------------------------------------------
 void LLVOAvatar::resetJointPositionsToDefault( void )
@@ -4956,20 +4939,30 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
 	//Subsequent joints are relative to pelvis
 	avatar_joint_list_t::iterator iter = mSkeleton.begin();
 	avatar_joint_list_t::iterator end  = mSkeleton.end();
+
+	LLJoint* pJointPelvis = getJoint("mPelvis");
+	
 	for (; iter != end; ++iter)
 	{
 		LLJoint* pJoint = (*iter);
-		if ( pJoint && pJoint->doesJointNeedToBeReset() )
+		//Reset joints except for pelvis
+		if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() )
 		{			
 			pJoint->setId( LLUUID::null );
 			pJoint->restoreOldXform();
 		}		
-	}
-
+		else
+		if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() )
+		{
+			pJoint->setId( LLUUID::null );
+			pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );
+			pJoint->setJointResetFlag( false );
+		}		
+	}	
+		
 	//make sure we don't apply the joint offset
 	mHasPelvisOffset = false;
 	mPelvisFixup	 = mLastPelvisFixup;
-
 	postPelvisSetRecalc();	
 }
 //-----------------------------------------------------------------------------
@@ -5125,7 +5118,7 @@ BOOL LLVOAvatar::loadSkeletonNode ()
 			{
 				attachment->setOriginalPosition(info->mPosition);
 			}
-
+			
 			if (info->mHasRotation)
 			{
 				LLQuaternion rotation;
@@ -5195,7 +5188,6 @@ void LLVOAvatar::updateVisualParams()
 	dirtyMesh();
 	updateHeadOffset();
 }
-
 //-----------------------------------------------------------------------------
 // isActive()
 //-----------------------------------------------------------------------------
@@ -5534,6 +5526,7 @@ void LLVOAvatar::lazyAttach()
 
 void LLVOAvatar::resetHUDAttachments()
 {
+
 	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end();
 		 ++iter)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 90ade85177..8bf31e3cb3 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -200,7 +200,6 @@ public:
 	virtual LLJoint*		getJoint(const std::string &name);
 	
 	void					resetJointPositionsToDefault( void );
-	void					resetSpecificJointPosition( const std::string& name );
 	
 	/*virtual*/ const LLUUID&	getID() const;
 	/*virtual*/ void			addDebugText(const std::string& text);
@@ -209,7 +208,7 @@ public:
 	/*virtual*/ F32				getPixelArea() const;
 	/*virtual*/ LLVector3d		getPosGlobalFromAgent(const LLVector3 &position);
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
-	virtual void			updateVisualParams();
+	virtual void				updateVisualParams();
 
 
 /**                    Inherited
-- 
cgit v1.2.3


From faa0866ca37313beae19e7f05e5917f4da0c1a0b Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Thu, 8 Aug 2013 13:21:18 -0400
Subject: SH-4401 FIX back-end changes to handle new visual param groups.

---
 autobuild.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 331e3d8cec..a15ca1e260 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>55e009de4f87023a57e0a04a19f8a25b</string>
+              <string>fa7b79adc95946028580a609e33d885e</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/277110/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130606.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/279662/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130808.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
-- 
cgit v1.2.3


From 0e8a966f3ba6db8a789b8053bc0eb70584c526fd Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Thu, 8 Aug 2013 17:13:53 -0400
Subject: Moved commented out capabilities debugging code into ifdef'd block
 and added a comment describing the use of it.

---
 indra/newview/llviewerregion.cpp | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ad046accd0..7150089380 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -76,6 +76,11 @@
 	#pragma warning(disable:4355)
 #endif
 
+// When we receive a base grant of capabilities that has a different number of 
+// capabilities than the original base grant received for the region, print 
+// out the two lists of capabilities for analysis.
+//#define DEBUG_CAPS_GRANTS
+
 const F32 WATER_TEXTURE_SCALE = 8.f;			//  Number of times to repeat the water texture across a region
 const S16 MAX_MAP_DIST = 10;
 // The server only keeps our pending agent info for 60 seconds.
@@ -328,25 +333,18 @@ private:
 				<< "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size()
 				<< " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
 				<< LL_ENDL;
+#ifdef DEBUG_CAPS_GRANTS
+			LL_WARNS2("AppInit", "Capabilities")
+				<< "Initial Base capabilities: " << LL_ENDL;
 
-			//LL_WARNS2("AppInit", "Capabilities")
-			//	<< "Initial Base capabilities: " << LL_ENDL;
-
-			//log_capabilities(regionp->getRegionImpl()->mCapabilities);
+			log_capabilities(regionp->getRegionImpl()->mCapabilities);
 
-			//LL_WARNS2("AppInit", "Capabilities")
-			//				<< "Latest base capabilities: " << LL_ENDL;
+			LL_WARNS2("AppInit", "Capabilities")
+							<< "Latest base capabilities: " << LL_ENDL;
 
-			//log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
+			log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
 
-			// *TODO 
-			//add cap debug versus original check?
-			//CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin();
-			//while (iter!=regionp->getRegionImpl()->mCapabilities.end() )
-			//{
-			//	llinfos<<"BaseCapabilitiesCompleteTracker Original "<<iter->first<<" "<< iter->second<<llendl;
-			//	++iter;
-			//}
+#endif
 
 			if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() )
 			{
-- 
cgit v1.2.3


From 3ed3b88892adb4234c375d2d6bd5f0d2da5566c7 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Fri, 9 Aug 2013 13:36:36 -0700
Subject: Refactoring link creation calls in preparation for adding AIS v3
 hook.

---
 indra/llcommon/llpointer.h              | 126 +++++++++++++++++++
 indra/llinventory/llinventory.h         |   1 +
 indra/newview/llagentwearables.cpp      |   8 +-
 indra/newview/llagentwearablesfetch.cpp |  15 +--
 indra/newview/llappearancemgr.cpp       | 103 ++++------------
 indra/newview/llappearancemgr.h         |  13 +-
 indra/newview/llinventorybridge.cpp     |  32 +----
 indra/newview/llpaneleditwearable.cpp   |  15 +--
 indra/newview/llviewerinventory.cpp     | 212 ++++++++++++++++++++++----------
 indra/newview/llviewerinventory.h       |  27 ++--
 10 files changed, 336 insertions(+), 216 deletions(-)

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 88c09c8dca..dd43e3aaa2 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -171,4 +171,130 @@ protected:
 	Type*	mPointer;
 };
 
+template <class Type> class LLConstPointer
+{
+public:
+	LLConstPointer() : 
+		mPointer(NULL)
+	{
+	}
+
+	LLConstPointer(const Type* ptr) : 
+		mPointer(ptr)
+	{
+		ref();
+	}
+
+	LLConstPointer(const LLConstPointer<Type>& ptr) : 
+		mPointer(ptr.mPointer)
+	{
+		ref();
+	}
+
+	// support conversion up the type hierarchy.  See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLConstPointer(const LLConstPointer<Subclass>& ptr) : 
+		mPointer(ptr.get())
+	{
+		ref();
+	}
+
+	~LLConstPointer()
+	{
+		unref();
+	}
+
+	const Type*	get() const						{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }
+	const Type&	operator*() const				{ return *mPointer; }
+
+	operator BOOL()  const						{ return (mPointer != NULL); }
+	operator bool()  const						{ return (mPointer != NULL); }
+	bool operator!() const						{ return (mPointer == NULL); }
+	bool isNull() const							{ return (mPointer == NULL); }
+	bool notNull() const						{ return (mPointer != NULL); }
+
+	operator const Type*()       const			{ return mPointer; }
+	bool operator !=(const Type* ptr) const     { return (mPointer != ptr); 	}
+	bool operator ==(const Type* ptr) const     { return (mPointer == ptr); 	}
+	bool operator ==(const LLConstPointer<Type>& ptr) const           { return (mPointer == ptr.mPointer); 	}
+	bool operator < (const LLConstPointer<Type>& ptr) const           { return (mPointer < ptr.mPointer); 	}
+	bool operator > (const LLConstPointer<Type>& ptr) const           { return (mPointer > ptr.mPointer); 	}
+
+	LLConstPointer<Type>& operator =(const Type* ptr)                   
+	{
+		if( mPointer != ptr )
+		{
+			unref(); 
+			mPointer = ptr; 
+			ref();
+		}
+
+		return *this; 
+	}
+
+	LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)  
+	{ 
+		if( mPointer != ptr.mPointer )
+		{
+			unref(); 
+			mPointer = ptr.mPointer;
+			ref();
+		}
+		return *this; 
+	}
+
+	// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)  
+	{ 
+		if( mPointer != ptr.get() )
+		{
+			unref(); 
+			mPointer = ptr.get();
+			ref();
+		}
+		return *this; 
+	}
+	
+	// Just exchange the pointers, which will not change the reference counts.
+	static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
+	{
+		const Type* temp = a.mPointer;
+		a.mPointer = b.mPointer;
+		b.mPointer = temp;
+	}
+
+protected:
+#ifdef LL_LIBRARY_INCLUDE
+	void ref();                             
+	void unref();
+#else
+	void ref()                             
+	{ 
+		if (mPointer)
+		{
+			mPointer->ref();
+		}
+	}
+
+	void unref()
+	{
+		if (mPointer)
+		{
+			const Type *tempp = mPointer;
+			mPointer = NULL;
+			tempp->unref();
+			if (mPointer != NULL)
+			{
+				llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+				unref();
+			}
+		}
+	}
+#endif
+protected:
+	const Type*	mPointer;
+};
+
 #endif
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index b718f0f9b7..dd504fb155 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -48,6 +48,7 @@ class LLInventoryObject : public LLRefCount
 {
 public:
 	typedef std::list<LLPointer<LLInventoryObject> > object_list_t;
+	typedef std::list<LLConstPointer<LLInventoryObject> > const_object_list_t;
 
 	//--------------------------------------------------------------------
 	// Initialization
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 8c33a778e3..f3c9998a7d 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -952,15 +952,15 @@ public:
 	/* virtual */ void fire(const LLUUID& inv_item)
 	{
 		llinfos << "One item created " << inv_item.asString() << llendl;
-		LLViewerInventoryItem *item = gInventory.getItem(inv_item);
-		mItemsToLink.put(item);
+		LLConstPointer<LLInventoryObject> item = gInventory.getItem(inv_item);
+		mItemsToLink.push_back(item);
 		updatePendingWearable(inv_item);
 	}
 	~OnWearableItemCreatedCB()
 	{
 		llinfos << "All items created" << llendl;
 		LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-		LLAppearanceMgr::instance().linkAll(LLAppearanceMgr::instance().getCOF(),
+		link_inventory_array(LLAppearanceMgr::instance().getCOF(),
 											mItemsToLink,
 											link_waiter);
 	}
@@ -1011,7 +1011,7 @@ public:
 	}
 	
 private:
-	LLInventoryModel::item_array_t mItemsToLink;
+	LLInventoryObject::const_object_list_t mItemsToLink;
 	std::vector<LLViewerWearable*> mWearablesAwaitingItems;
 };
 
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 014c610a5c..a2a667e660 100755
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -117,26 +117,21 @@ public:
 
 		// Link to all fetched items in COF.
 		LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+		LLInventoryObject::const_object_list_t item_array;
 		for (uuid_vec_t::iterator it = mIDs.begin();
 			 it != mIDs.end();
 			 ++it)
 		{
 			LLUUID id = *it;
-			LLViewerInventoryItem *item = gInventory.getItem(*it);
+			LLConstPointer<LLInventoryObject> item = gInventory.getItem(*it);
 			if (!item)
 			{
-				llwarns << "fetch failed!" << llendl;
+				llwarns << "fetch failed for item " << (*it) << "!" << llendl;
 				continue;
 			}
-
-			link_inventory_item(gAgent.getID(),
-								item->getLinkedUUID(),
-								LLAppearanceMgr::instance().getCOF(),
-								item->getName(),
-								item->getDescription(),
-								LLAssetType::AT_LINK,
-								link_waiter);
+			item_array.push_back(item);
 		}
+		link_inventory_array(LLAppearanceMgr::instance().getCOF(), item_array, link_waiter);
 	}
 };
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 3818bd8aec..c4bc6f648f 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -909,20 +909,15 @@ void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLView
 	}
 
 	LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL;
-	LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
+	LLConstPointer<LLInventoryObject> itemp = gInventory.getItem(item_id);
 	wearable->setItemID(item_id);
-	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_link_cb,_1,type,wearable,holder));
 	holder->eraseTypeToRecover(type);
 	llassert(itemp);
 	if (itemp)
 	{
-		link_inventory_item( gAgent.getID(),
-							 item_id,
-							 LLAppearanceMgr::instance().getCOF(),
-							 itemp->getName(),
-							 itemp->getDescription(),
-							 LLAssetType::AT_LINK,
-							 cb);
+		LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_link_cb,_1,type,wearable,holder));
+
+		link_inventory_object(LLAppearanceMgr::instance().getCOF(), itemp, cb);
 	}
 }
 
@@ -1551,6 +1546,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 	LLInventoryModel::item_array_t* items;
 	gInventory.getDirectDescendentsOf(src_id, cats, items);
 	llinfos << "copying " << items->count() << " items" << llendl;
+	LLInventoryObject::const_object_list_t link_array;
 	for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
 		 iter != items->end();
 		 ++iter)
@@ -1561,14 +1557,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 			case LLAssetType::AT_LINK:
 			{
 				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << llendl;
-				//getActualDescription() is used for a new description 
-				//to propagate ordering information saved in descriptions of links
-				link_inventory_item(gAgent.getID(),
-									item->getLinkedUUID(),
-									dst_id,
-									item->getName(),
-									item->getActualDescription(),
-									LLAssetType::AT_LINK, cb);
+				link_array.push_back(LLConstPointer<LLInventoryObject>(item));
 				break;
 			}
 			case LLAssetType::AT_LINK_FOLDER:
@@ -1578,12 +1567,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 				if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
 				{
 					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << llendl;
-					link_inventory_item(gAgent.getID(),
-										item->getLinkedUUID(),
-										dst_id,
-										item->getName(),
-										item->getDescription(),
-										LLAssetType::AT_LINK_FOLDER, cb);
+					link_array.push_back(LLConstPointer<LLInventoryObject>(item));
 				}
 				break;
 			}
@@ -1606,6 +1590,11 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 				break;
 		}
 	}
+	if (!link_array.empty())
+	{
+		const bool resolve_links = true;
+		link_inventory_array(dst_id, link_array, cb, resolve_links);
+	}
 }
 
 BOOL LLAppearanceMgr::getCanMakeFolderIntoOutfit(const LLUUID& folder_id)
@@ -1753,42 +1742,6 @@ void LLAppearanceMgr::filterWearableItems(
 	}
 }
 
-// Create links to all listed items.
-void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
-							  LLInventoryModel::item_array_t& items,
-							  LLPointer<LLInventoryCallback> cb)
-{
-	for (S32 i=0; i<items.count(); i++)
-	{
-		const LLInventoryItem* item = items.get(i).get();
-		link_inventory_item(gAgent.getID(),
-							item->getLinkedUUID(),
-							cat_uuid,
-							item->getName(),
-							item->getActualDescription(),
-							LLAssetType::AT_LINK,
-							cb);
-
-		const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
-		const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND";
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		LL_DEBUGS("Avatar") << self_av_string() << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << LL_ENDL;
-#endif
-	}
-}
-
-void LLAppearanceMgr::removeAll(LLInventoryModel::item_array_t& items_to_kill,
-							   LLPointer<LLInventoryCallback> cb)
-{
-	for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin();
-		 it != items_to_kill.end();
-		 ++it)
-	{
-		LLViewerInventoryItem *item = *it;
-		remove_inventory_item(item->getUUID(), cb);
-	}
-}
-
 void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 {
 	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
@@ -1934,8 +1887,7 @@ void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointer<LLI
 
 	if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
 	{
-		link_inventory_item(gAgent.getID(), category, cof, catp->getName(), "",
-							LLAssetType::AT_LINK_FOLDER, link_waiter);
+		link_inventory_object(cof, catp, link_waiter);
 		new_outfit_name = catp->getName();
 	}
 	
@@ -2027,7 +1979,7 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list,
 S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 												 LLAssetType::EType type,
 												 S32 max_items,
-												 LLInventoryModel::item_array_t& items_to_kill)
+												 LLInventoryObject::object_list_t& items_to_kill)
 {
 	S32 to_kill_count = 0;
 
@@ -2045,7 +1997,7 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 		 it != kill_items.end();
 		 ++it)
 	{
-		items_to_kill.push_back(*it);
+		items_to_kill.push_back(LLPointer<LLInventoryObject>(*it));
 		to_kill_count++;
 	}
 	return to_kill_count;
@@ -2053,7 +2005,7 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 	
 
 void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
-													LLInventoryModel::item_array_t& items_to_kill)
+													LLInventoryObject::object_list_t& items_to_kill)
 {
 	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART,
 							   1, items_to_kill);
@@ -2065,14 +2017,13 @@ void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 
 void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb)
 {
-	LLInventoryModel::item_array_t items_to_kill;
+	LLInventoryObject::object_list_t items_to_kill;
 	findAllExcessOrDuplicateItems(getCOF(), items_to_kill);
 	if (items_to_kill.size()>0)
 	{
 		// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
 		// this should catch anything that gets through.
-		removeAll(items_to_kill, cb);
-		return;
+		remove_inventory_items(items_to_kill, cb);
 	}
 }
 
@@ -2525,7 +2476,7 @@ void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id,
 void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
 									 LLPointer<LLInventoryCallback> cb,
 									 const std::string description)
-{		
+{
 	const LLViewerInventoryItem *vitem = dynamic_cast<const LLViewerInventoryItem*>(item);
 	if (!vitem)
 	{
@@ -2577,18 +2528,10 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
 
 	if (!linked_already)
 	{
-		std::string link_description = description;
-		if (vitem->getIsLinkType())
-		{
-			link_description = vitem->getActualDescription();
-		}
-		link_inventory_item( gAgent.getID(),
-							 vitem->getLinkedUUID(),
-							 getCOF(),
-							 vitem->getName(),
-							 link_description,
-							 LLAssetType::AT_LINK,
-							 cb);
+		LLInventoryObject::const_object_list_t obj_array;
+		obj_array.push_back(LLConstPointer<LLInventoryObject>(vitem));
+		const bool resolve_links = true;
+		link_inventory_array(getCOF(), obj_array, cb, resolve_links);
 	}
 }
 
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 8c8b5e2489..346577ab9a 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -67,9 +67,9 @@ public:
 	S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
 								   LLAssetType::EType type,
 								   S32 max_items,
-								   LLInventoryModel::item_array_t& items_to_kill);
+								   LLInventoryObject::object_list_t& items_to_kill);
 	void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
-									  LLInventoryModel::item_array_t& items_to_kill);
+									  LLInventoryObject::object_list_t& items_to_kill);
 	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
 	S32 getActiveCopyOperations() const;
@@ -139,15 +139,6 @@ public:
 	void registerAttachment(const LLUUID& item_id);
 	void setAttachmentInvLinkEnable(bool val);
 
-	// utility function for bulk linking.
-	void linkAll(const LLUUID& category,
-				 LLInventoryModel::item_array_t& items,
-				 LLPointer<LLInventoryCallback> cb);
-
-	// And bulk removal.
-	void removeAll(LLInventoryModel::item_array_t& items,
-				   LLPointer<LLInventoryCallback> cb);
-
 	// Add COF link to individual item.
 	void addCOFItemLink(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
 	void addCOFItemLink(const LLInventoryItem *item, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index cb3f40a5bb..0481bf5f45 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3223,28 +3223,9 @@ void LLFolderBridge::pasteLinkFromClipboard()
 					dropToOutfit(item, move_is_into_current_outfit);
 				}
 			}
-			else if (LLInventoryCategory *cat = model->getCategory(object_id))
+			else if (LLConstPointer<LLInventoryObject> obj = model->getObject(object_id))
 			{
-				const std::string empty_description = "";
-				link_inventory_item(
-					gAgent.getID(),
-					cat->getUUID(),
-					parent_id,
-					cat->getName(),
-					empty_description,
-					LLAssetType::AT_LINK_FOLDER,
-					LLPointer<LLInventoryCallback>(NULL));
-			}
-			else if (LLInventoryItem *item = model->getItem(object_id))
-			{
-				link_inventory_item(
-					gAgent.getID(),
-					item->getLinkedUUID(),
-					parent_id,
-					item->getName(),
-					item->getDescription(),
-					LLAssetType::AT_LINK,
-					LLPointer<LLInventoryCallback>(NULL));
+				link_inventory_object(parent_id, obj, LLPointer<LLInventoryCallback>(NULL));
 			}
 		}
 		// Change mode to paste for next paste
@@ -3830,14 +3811,7 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
 	else
 	{
 		LLPointer<LLInventoryCallback> cb = NULL;
-		link_inventory_item(
-			gAgent.getID(),
-			inv_item->getLinkedUUID(),
-			mUUID,
-			inv_item->getName(),
-			inv_item->getDescription(),
-			LLAssetType::AT_LINK,
-			cb);
+		link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
 	}
 }
 
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index a1222424ee..0532370ff2 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1095,13 +1095,14 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 				LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
 									<< " removing old link at " << link_item->getUUID()
 									<< " wearable item id " << mWearablePtr->getItemID() << llendl;
-				link_inventory_item( gAgent.getID(),
-									 link_item->getLinkedUUID(),
-									 LLAppearanceMgr::instance().getCOF(),
-									 link_item->getName(),
-									 description,
-									 LLAssetType::AT_LINK,
-									 gAgentAvatarp->mEndCustomizeCallback);
+
+				LLInventoryObject::const_object_list_t obj_array;
+				obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
+				const bool resolve_links = true;
+				link_inventory_array(LLAppearanceMgr::instance().getCOF(),
+									 obj_array, 
+									 gAgentAvatarp->mEndCustomizeCallback,
+									 resolve_links);
 				// Remove old link
 				remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
 			}
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index bff6767617..33186a5a88 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1074,77 +1074,133 @@ void copy_inventory_item(
 	gAgent.sendReliableMessage();
 }
 
-void link_inventory_item(
-	const LLUUID& agent_id,
-	const LLUUID& item_id,
-	const LLUUID& parent_id,
-	const std::string& new_name,
-	const std::string& new_description,
-	const LLAssetType::EType asset_type,
-	LLPointer<LLInventoryCallback> cb)
+// Create link to single inventory object.
+void link_inventory_object(const LLUUID& category,
+			 LLConstPointer<LLInventoryObject> baseobj,
+			 LLPointer<LLInventoryCallback> cb)
 {
-	const LLInventoryObject *baseobj = gInventory.getObject(item_id);
 	if (!baseobj)
 	{
-		llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
-		return;
-	}
-	if (baseobj && baseobj->getIsLinkType())
-	{
-		llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
+		llwarns << "Attempt to link to non-existent object" << llendl;
 		return;
 	}
 
-	if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
-	{
-		// Fail if item can be found but is of a type that can't be linked.
-		// Arguably should fail if the item can't be found too, but that could
-		// be a larger behavioral change.
-		llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
-		return;
-	}
-	
-	LLUUID transaction_id;
-	LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
-	if (dynamic_cast<const LLInventoryCategory *>(baseobj))
-	{
-		inv_type = LLInventoryType::IT_CATEGORY;
-	}
-	else
+	LLInventoryObject::const_object_list_t obj_array;
+	obj_array.push_back(baseobj);
+	link_inventory_array(category, obj_array, cb);
+}
+
+void link_inventory_object(const LLUUID& category,
+			 const LLUUID& id,
+			 LLPointer<LLInventoryCallback> cb)
+{
+	LLConstPointer<LLInventoryObject> baseobj = gInventory.getObject(id);
+	link_inventory_object(category, baseobj, cb);
+}
+
+// Create links to all listed inventory objects.
+void link_inventory_array(const LLUUID& category,
+			 LLInventoryObject::const_object_list_t& baseobj_array,
+			 LLPointer<LLInventoryCallback> cb,
+			 bool resolve_links /* = false */)
+{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	const LLViewerInventoryCategory *cat = gInventory.getCategory(category);
+	const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND";
+#endif
+	LLInventoryObject::const_object_list_t::const_iterator it = baseobj_array.begin();
+	LLInventoryObject::const_object_list_t::const_iterator end = baseobj_array.end();
+	for (; it != end; ++it)
 	{
-		const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj);
-		if (baseitem)
+		const LLInventoryObject* baseobj = *it;
+		if (!baseobj)
 		{
-			inv_type = baseitem->getInventoryType();
+			llwarns << "attempt to link to unknown object" << llendl;
+			continue;
+		}
+		if (!resolve_links && baseobj->getIsLinkType())
+		{
+			llwarns << "attempt to create a link to a link, linked-to-object's ID " << baseobj->getUUID() << llendl;
+			continue;
 		}
-	}
 
-#if 1 // debugging stuff
-	LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
-	lldebugs << "cat: " << cat << llendl;
-	
+		if (!LLAssetType::lookupCanLink(baseobj->getType()))
+		{
+			// Fail if item can be found but is of a type that can't be linked.
+			// Arguably should fail if the item can't be found too, but that could
+			// be a larger behavioral change.
+			llwarns << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << llendl;
+			continue;
+		}
+		
+		LLUUID transaction_id;
+		LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
+		LLAssetType::EType asset_type = LLAssetType::AT_NONE;
+		std::string new_desc;
+		LLUUID linkee_id;
+		if (dynamic_cast<const LLInventoryCategory *>(baseobj))
+		{
+			inv_type = LLInventoryType::IT_CATEGORY;
+			asset_type = LLAssetType::AT_LINK_FOLDER;
+			linkee_id = baseobj->getUUID();
+		}
+		else
+		{
+			const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj);
+			if (baseitem)
+			{
+				inv_type = baseitem->getInventoryType();
+				new_desc = baseitem->getActualDescription();
+				switch (baseitem->getActualType())
+				{
+					case LLAssetType::AT_LINK:
+					case LLAssetType::AT_LINK_FOLDER:
+						linkee_id = baseobj->getLinkedUUID();
+						asset_type = baseitem->getActualType();
+						break;
+					default:
+						linkee_id = baseobj->getUUID();
+						asset_type = LLAssetType::AT_LINK;
+						break;
+				}
+			}
+			else
+			{
+				llwarns << "could not convert object into an item or category: " << baseobj->getUUID() << llendl;
+				continue;
+			}
+		}
+
+		LLMessageSystem* msg = gMessageSystem;
+		msg->newMessageFast(_PREHASH_LinkInventoryItem);
+		msg->nextBlock(_PREHASH_AgentData);
+		{
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		}
+		msg->nextBlock(_PREHASH_InventoryBlock);
+		{
+			msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
+			msg->addUUIDFast(_PREHASH_FolderID, category);
+			msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
+			msg->addUUIDFast(_PREHASH_OldItemID, linkee_id);
+			msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
+			msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
+			msg->addStringFast(_PREHASH_Name, baseobj->getName());
+			msg->addStringFast(_PREHASH_Description, new_desc);
+		}
+		gAgent.sendReliableMessage();
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+		LL_DEBUGS("Inventory") << "Linking Object [ name:" << baseobj->getName() 
+							   << " UUID:" << baseobj->getUUID() 
+							   << " ] into Category [ name:" << cat_name 
+							   << " UUID:" << category << " ] " << LL_ENDL;
 #endif
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_LinkInventoryItem);
-	msg->nextBlock(_PREHASH_AgentData);
-	{
-		msg->addUUIDFast(_PREHASH_AgentID, agent_id);
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 	}
-	msg->nextBlock(_PREHASH_InventoryBlock);
-	{
-		msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
-		msg->addUUIDFast(_PREHASH_FolderID, parent_id);
-		msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
-		msg->addUUIDFast(_PREHASH_OldItemID, item_id);
-		msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
-		msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
-		msg->addStringFast(_PREHASH_Name, new_name);
-		msg->addStringFast(_PREHASH_Description, new_description);
-	}
-	gAgent.sendReliableMessage();
 }
 
+
+
 void move_inventory_item(
 	const LLUUID& agent_id,
 	const LLUUID& session_id,
@@ -1301,14 +1357,41 @@ void update_inventory_category(
 	}
 }
 
+void remove_inventory_items(
+	LLInventoryObject::object_list_t& items_to_kill,
+	LLPointer<LLInventoryCallback> cb)
+{
+	for (LLInventoryObject::object_list_t::iterator it = items_to_kill.begin();
+		 it != items_to_kill.end();
+		 ++it)
+	{
+		remove_inventory_item(*it, cb);
+	}
+}
+
 void remove_inventory_item(
 	const LLUUID& item_id,
 	LLPointer<LLInventoryCallback> cb)
 {
-	LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
-	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+	LLPointer<LLInventoryObject> obj = gInventory.getItem(item_id);
+	if (obj)
+	{
+		remove_inventory_item(obj, cb);
+	}
+	else
+	{
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << llendl;
+	}
+}
+
+void remove_inventory_item(
+	LLPointer<LLInventoryObject> obj,
+	LLPointer<LLInventoryCallback> cb)
+{
 	if(obj)
 	{
+		const LLUUID item_id(obj->getUUID());
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << obj->getName() << llendl;
 		if (AISCommand::isAPIAvailable())
 		{
 			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
@@ -1336,7 +1419,8 @@ void remove_inventory_item(
 	}
 	else
 	{
-		llwarns << "remove_inventory_item called for invalid or nonexistent item " << item_id << llendl;
+		// *TODO: Clean up callback?
+		llwarns << "remove_inventory_item called for invalid or nonexistent item." << llendl;
 	}
 }
 
@@ -1632,13 +1716,7 @@ void slam_inventory_folder(const LLUUID& folder_id,
 			 ++it)
 		{
 			const LLSD& item_contents = *it;
-			link_inventory_item(gAgent.getID(),
-								item_contents["linked_id"].asUUID(),
-								folder_id,
-								item_contents["name"].asString(),
-								item_contents["desc"].asString(),
-								LLAssetType::EType(item_contents["type"].asInteger()),
-								cb);
+			link_inventory_object(folder_id, item_contents["linked_id"].asUUID(), cb);
 		}
 		remove_folder_contents(folder_id,false,cb);
 	}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 6bc6343f3f..cc715ae21d 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -351,14 +351,17 @@ void copy_inventory_item(
 	const std::string& new_name,
 	LLPointer<LLInventoryCallback> cb);
 
-void link_inventory_item(
-	const LLUUID& agent_id,
-	const LLUUID& item_id,
-	const LLUUID& parent_id,
-	const std::string& new_name,
-	const std::string& new_description,
-	const LLAssetType::EType asset_type,
-	LLPointer<LLInventoryCallback> cb);
+// utility functions for inventory linking.
+void link_inventory_object(const LLUUID& category,
+			 LLConstPointer<LLInventoryObject> baseobj,
+			 LLPointer<LLInventoryCallback> cb);
+void link_inventory_object(const LLUUID& category,
+			 const LLUUID& id,
+			 LLPointer<LLInventoryCallback> cb);
+void link_inventory_array(const LLUUID& category,
+			 LLInventoryObject::const_object_list_t& baseobj_array,
+			 LLPointer<LLInventoryCallback> cb,
+			 bool resolve_links = false);
 
 void move_inventory_item(
 	const LLUUID& agent_id,
@@ -382,6 +385,14 @@ void update_inventory_category(
 	const LLSD& updates,
 	LLPointer<LLInventoryCallback> cb);
 
+void remove_inventory_items(
+	LLInventoryObject::object_list_t& items,
+	LLPointer<LLInventoryCallback> cb);
+
+void remove_inventory_item(
+	LLPointer<LLInventoryObject> obj,
+	LLPointer<LLInventoryCallback> cb);
+
 void remove_inventory_item(
 	const LLUUID& item_id,
 	LLPointer<LLInventoryCallback> cb);
-- 
cgit v1.2.3


From c1af1a692a6bd0f3cdfb3f49cc2451717481b685 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Fri, 9 Aug 2013 14:52:54 -0700
Subject: Routing link creating through AISv3 when available.

---
 indra/newview/llaisapi.cpp          | 37 ++++++++++++++-------
 indra/newview/llaisapi.h            |  9 +++++
 indra/newview/llviewerinventory.cpp | 65 +++++++++++++++++++++++++------------
 3 files changed, 79 insertions(+), 32 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index f8c9447b17..73aaebc050 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -100,20 +100,9 @@ void AISCommand::httpSuccess()
 /*virtual*/
 void AISCommand::httpFailure()
 {
-	const LLSD& content = getContent();
+	LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
 	S32 status = getStatus();
-	const std::string& reason = getReason();
 	const LLSD& headers = getResponseHeaders();
-	if (!content.isMap())
-	{
-		LL_DEBUGS("Inventory") << "Malformed response contents " << content
-							   << " status " << status << " reason " << reason << LL_ENDL;
-	}
-	else
-	{
-		LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content)
-							   << " status " << status << " reason " << reason << LL_ENDL;
-	}
 	mRetryPolicy->onFailure(status, headers);
 	F32 seconds_to_wait;
 	if (mRetryPolicy->shouldRetry(seconds_to_wait))
@@ -276,6 +265,30 @@ UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& item_id,
 	setCommandFunc(cmd);
 }
 
+CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id,
+							 				   const LLSD& new_inventory,
+							 				   LLPointer<LLInventoryCallback> callback):
+	mNewInventory(new_inventory),
+	AISCommand(callback)
+{
+	std::string cap;
+	if (!getInvCap(cap))
+	{
+		llwarns << "No cap found" << llendl;
+		return;
+	}
+	LLUUID tid;
+	tid.generate();
+	std::string url = cap + std::string("/category/") + parent_id.asString() + "?tid=" + tid.asString();
+	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+	LLCurl::ResponderPtr responder = this;
+	LLSD headers;
+	headers["Content-Type"] = "application/llsd+xml";
+	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	command_func_type cmd = boost::bind(&LLHTTPClient::post, url, mNewInventory, responder, headers, timeout);
+	setCommandFunc(cmd);
+}
+
 SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
 	mContents(contents),
 	AISCommand(callback)
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index f4e219e9e6..5d31129a16 100755
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -130,6 +130,15 @@ protected:
 	/* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id);
 };
 
+class CreateInventoryCommand: public AISCommand
+{
+public:
+	CreateInventoryCommand(const LLUUID& parent_id, const LLSD& new_inventory, LLPointer<LLInventoryCallback> callback);
+
+private:
+	LLSD mNewInventory;
+};
+
 class AISUpdate
 {
 public:
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 33186a5a88..dc17da9009 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1110,6 +1110,7 @@ void link_inventory_array(const LLUUID& category,
 #endif
 	LLInventoryObject::const_object_list_t::const_iterator it = baseobj_array.begin();
 	LLInventoryObject::const_object_list_t::const_iterator end = baseobj_array.end();
+	LLSD links = LLSD::emptyArray();
 	for (; it != end; ++it)
 	{
 		const LLInventoryObject* baseobj = *it;
@@ -1133,7 +1134,6 @@ void link_inventory_array(const LLUUID& category,
 			continue;
 		}
 		
-		LLUUID transaction_id;
 		LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
 		LLAssetType::EType asset_type = LLAssetType::AT_NONE;
 		std::string new_desc;
@@ -1171,25 +1171,14 @@ void link_inventory_array(const LLUUID& category,
 			}
 		}
 
-		LLMessageSystem* msg = gMessageSystem;
-		msg->newMessageFast(_PREHASH_LinkInventoryItem);
-		msg->nextBlock(_PREHASH_AgentData);
-		{
-			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		}
-		msg->nextBlock(_PREHASH_InventoryBlock);
-		{
-			msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
-			msg->addUUIDFast(_PREHASH_FolderID, category);
-			msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
-			msg->addUUIDFast(_PREHASH_OldItemID, linkee_id);
-			msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
-			msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
-			msg->addStringFast(_PREHASH_Name, baseobj->getName());
-			msg->addStringFast(_PREHASH_Description, new_desc);
-		}
-		gAgent.sendReliableMessage();
+		LLSD link = LLSD::emptyMap();
+		link["linked_id"] = linkee_id;
+		link["type"] = (S8)asset_type;
+		link["inv_type"] = (S8)inv_type;
+		link["name"] = baseobj->getName();
+		link["desc"] = new_desc;
+		links.append(link);
+
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 		LL_DEBUGS("Inventory") << "Linking Object [ name:" << baseobj->getName() 
 							   << " UUID:" << baseobj->getUUID() 
@@ -1197,6 +1186,42 @@ void link_inventory_array(const LLUUID& category,
 							   << " UUID:" << category << " ] " << LL_ENDL;
 #endif
 	}
+
+	bool ais_ran = false;
+	if (AISCommand::isAPIAvailable())
+	{
+		LLSD new_inventory = LLSD::emptyMap();
+		new_inventory["links"] = links;
+		LLPointer<AISCommand> cmd_ptr = new CreateInventoryCommand(category, new_inventory, cb);
+		ais_ran = cmd_ptr->run_command();
+	}
+
+	if (!ais_ran)
+	{
+		LLMessageSystem* msg = gMessageSystem;
+		for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter )
+		{
+			msg->newMessageFast(_PREHASH_LinkInventoryItem);
+			msg->nextBlock(_PREHASH_AgentData);
+			{
+				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			}
+			msg->nextBlock(_PREHASH_InventoryBlock);
+			{
+				LLSD link = (*iter);
+				msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
+				msg->addUUIDFast(_PREHASH_FolderID, category);
+				msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
+				msg->addUUIDFast(_PREHASH_OldItemID, link["linked_id"].asUUID());
+				msg->addS8Fast(_PREHASH_Type, link["type"].asInteger());
+				msg->addS8Fast(_PREHASH_InvType, link["inv_type"].asInteger());
+				msg->addStringFast(_PREHASH_Name, link["name"].asString());
+				msg->addStringFast(_PREHASH_Description, link["desc"].asString());
+			}
+			gAgent.sendReliableMessage();
+		}
+	}
 }
 
 
-- 
cgit v1.2.3


From 6128cd9f705ca5565cafbe4b969c767b138cd1f6 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 12 Aug 2013 13:45:51 -0400
Subject: cat version debug statement

---
 indra/newview/llaisapi.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index f8c9447b17..e710df4920 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -815,6 +815,7 @@ void AISUpdate::doUpdate()
 		const LLUUID id = ucv_it->first;
 		S32 version = ucv_it->second;
 		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+		LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << llendl;
 		if (cat->getVersion() != version)
 		{
 			llwarns << "Possible version mismatch for category " << cat->getName()
-- 
cgit v1.2.3


From 2157cf5e71f40ae4cc9eedaea6811a4c55718747 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 14 Aug 2013 14:25:22 -0400
Subject: SH-4422 FIX - fixed some recently introduced issues with link
 description fields, which among other things reduces the number of appearance
 requests sent.

---
 indra/newview/llappearancemgr.cpp     | 14 +++++++-------
 indra/newview/llpaneleditwearable.cpp |  4 +---
 indra/newview/llviewerinventory.cpp   | 12 ++++--------
 indra/newview/llviewerinventory.h     |  5 ++---
 4 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index c4bc6f648f..939d817201 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1592,8 +1592,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 	}
 	if (!link_array.empty())
 	{
-		const bool resolve_links = true;
-		link_inventory_array(dst_id, link_array, cb, resolve_links);
+		link_inventory_array(dst_id, link_array, cb);
 	}
 }
 
@@ -2528,10 +2527,10 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
 
 	if (!linked_already)
 	{
-		LLInventoryObject::const_object_list_t obj_array;
-		obj_array.push_back(LLConstPointer<LLInventoryObject>(vitem));
-		const bool resolve_links = true;
-		link_inventory_array(getCOF(), obj_array, cb, resolve_links);
+		LLViewerInventoryItem *copy_item = new LLViewerInventoryItem;
+		copy_item->copyViewerItem(vitem);
+		copy_item->setDescription(description);
+		link_inventory_object(getCOF(), copy_item, cb);
 	}
 }
 
@@ -2735,7 +2734,8 @@ void LLAppearanceMgr::updateIsDirty()
 					if (item1->getActualDescription() != item2->getActualDescription())
 					{
 						LL_DEBUGS("Avatar") << "desc different " << item1->getActualDescription()
-											<< " " << item2->getActualDescription() << llendl;
+											<< " " << item2->getActualDescription() 
+											<< " names " << item1->getName() << " " << item2->getName() << llendl;
 					}
 				}
 				mOutfitIsDirty = true;
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 0532370ff2..582998c973 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1098,11 +1098,9 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 
 				LLInventoryObject::const_object_list_t obj_array;
 				obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
-				const bool resolve_links = true;
 				link_inventory_array(LLAppearanceMgr::instance().getCOF(),
 									 obj_array, 
-									 gAgentAvatarp->mEndCustomizeCallback,
-									 resolve_links);
+									 gAgentAvatarp->mEndCustomizeCallback);
 				// Remove old link
 				remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
 			}
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index dc17da9009..b623b23e1a 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1101,8 +1101,7 @@ void link_inventory_object(const LLUUID& category,
 // Create links to all listed inventory objects.
 void link_inventory_array(const LLUUID& category,
 			 LLInventoryObject::const_object_list_t& baseobj_array,
-			 LLPointer<LLInventoryCallback> cb,
-			 bool resolve_links /* = false */)
+			 LLPointer<LLInventoryCallback> cb)
 {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	const LLViewerInventoryCategory *cat = gInventory.getCategory(category);
@@ -1119,11 +1118,6 @@ void link_inventory_array(const LLUUID& category,
 			llwarns << "attempt to link to unknown object" << llendl;
 			continue;
 		}
-		if (!resolve_links && baseobj->getIsLinkType())
-		{
-			llwarns << "attempt to create a link to a link, linked-to-object's ID " << baseobj->getUUID() << llendl;
-			continue;
-		}
 
 		if (!LLAssetType::lookupCanLink(baseobj->getType()))
 		{
@@ -1741,7 +1735,9 @@ void slam_inventory_folder(const LLUUID& folder_id,
 			 ++it)
 		{
 			const LLSD& item_contents = *it;
-			link_inventory_object(folder_id, item_contents["linked_id"].asUUID(), cb);
+			LLViewerInventoryItem *item = new LLViewerInventoryItem;
+			item->fromLLSD(item_contents);
+			link_inventory_object(folder_id, item, cb);
 		}
 		remove_folder_contents(folder_id,false,cb);
 	}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index cc715ae21d..b647f4756a 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -359,9 +359,8 @@ void link_inventory_object(const LLUUID& category,
 			 const LLUUID& id,
 			 LLPointer<LLInventoryCallback> cb);
 void link_inventory_array(const LLUUID& category,
-			 LLInventoryObject::const_object_list_t& baseobj_array,
-			 LLPointer<LLInventoryCallback> cb,
-			 bool resolve_links = false);
+						  LLInventoryObject::const_object_list_t& baseobj_array,
+						  LLPointer<LLInventoryCallback> cb);
 
 void move_inventory_item(
 	const LLUUID& agent_id,
-- 
cgit v1.2.3


From f669fdaf8128bb29c3aa372403ce3e276388b62e Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 16 Aug 2013 19:47:58 -0400
Subject: merge cleanup - one file did not merge cleanly.

---
 indra/newview/llviewertexture.h | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index e99d52741d..b43243c3f2 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -141,12 +141,15 @@ public:
 
 	LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
 	
+	S32 getFullWidth() const { return mFullWidth; }
+	S32 getFullHeight() const { return mFullHeight; }	
 	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
-	virtual void addFace(LLFace* facep) ;
-	virtual void removeFace(LLFace* facep) ; 
-	S32 getNumFaces() const;
-	const ll_face_list_t* getFaceList() const {return &mFaceList;}
+	virtual void addFace(U32 channel, LLFace* facep) ;
+	virtual void removeFace(U32 channel, LLFace* facep) ; 
+	S32 getTotalNumFaces() const;
+	S32 getNumFaces(U32 ch) const;
+	const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];}
 
 	virtual void addVolume(LLVOVolume* volumep);
 	virtual void removeVolume(LLVOVolume* volumep);
@@ -183,8 +186,8 @@ protected:
 	mutable F32 mAdditionalDecodePriority;  // priority add to mDecodePriority.
 	LLFrameTimer mLastReferencedTimer;	
 
-	ll_face_list_t    mFaceList ; //reverse pointer pointing to the faces using this image as texture
-	U32               mNumFaces ;
+	ll_face_list_t    mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture
+	U32               mNumFaces[LLRender::NUM_TEXTURE_CHANNELS];
 	LLFrameTimer      mLastFaceListUpdateTimer ;
 
 	ll_volume_list_t  mVolumeList;
@@ -453,7 +456,7 @@ protected:
 	LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture.
 
 	FTType mFTType; // What category of image is this - map tile, server bake, etc?
-	mutable BOOL mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
+	mutable S8 mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		
 
 	typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
 	S8              mLoadedCallbackDesiredDiscardLevel;
@@ -500,6 +503,7 @@ public:
 	static LLPointer<LLViewerFetchedTexture> sWhiteImagep;	// Texture to show NOTHING (whiteness)
 	static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
 	static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
+	static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface
 };
 
 //
@@ -557,12 +561,12 @@ public:
 	void addMediaToFace(LLFace* facep) ;
 	void removeMediaFromFace(LLFace* facep) ;
 
-	/*virtual*/ void addFace(LLFace* facep) ;
-	/*virtual*/ void removeFace(LLFace* facep) ; 
+	/*virtual*/ void addFace(U32 ch, LLFace* facep) ;
+	/*virtual*/ void removeFace(U32 ch, LLFace* facep) ; 
 
 	/*virtual*/ F32  getMaxVirtualSize() ;
 private:
-	void switchTexture(LLFace* facep) ;
+	void switchTexture(U32 ch, LLFace* facep) ;
 	BOOL findFaces() ;
 	void stopPlaying() ;
 
-- 
cgit v1.2.3


From cc999b225ecfe035f785f3d2629cbf64e7640e3a Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Mon, 19 Aug 2013 11:55:49 -0400
Subject: merge cleanup, making sure our branch has the latest autobuild
 changes.

---
 autobuild.xml | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index a15ca1e260..93de5d3d66 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -522,9 +522,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>0980cdf98a322a780ba739e324d0b955</string>
+              <string>91752db72202807cffb33c1ec3fd90fc</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/274401/arch/CYGWIN/installer/fmodex-4.44-windows-20130419.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/276321/arch/CYGWIN/installer/fmodex-4.44-windows-20130521.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1808,9 +1808,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>24e735ae005f3ce7a21a09cc02cece17</string>
+              <string>2994f1e028fb200c454c12b5f7ca9108</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/Darwin/installer/slvoice-3.2.0002.10426-darwin-20110601.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/270464/arch/Darwin/installer/slvoice-4.5.0009.17865-darwin-20130215.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1820,9 +1820,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>8a0bc982367d6fdc20a28b391cd40566</string>
+              <string>957773fff7148ffaca42b1ea4a18d192</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/Linux/installer/slvoice-3.2.0002.10426-linux-20110601.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/270512/arch/Linux/installer/slvoice-4.5.0009.17865-linux-20130216.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1832,9 +1832,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>1e821cc7d25eabad013b7f3db260dd6b</string>
+              <string>24710eda136bfd42d6333e5609c2c74f</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/231678/arch/CYGWIN/installer/slvoice-3.2.0002.10426-windows-20110601.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-slvoice/rev/270464/arch/CYGWIN/installer/slvoice-4.5.0009.17865-windows-20130214.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
-- 
cgit v1.2.3


From 0094c4299f6fb627c0a759374ede39450efdc8d0 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 19 Aug 2013 14:49:11 -0400
Subject: moved LLTrackPhaseWrapper to do its work in destructor

---
 indra/newview/llappearancemgr.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 939d817201..2e7ec0b2d5 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -467,13 +467,18 @@ public:
 	// virtual
 	void fire(const LLUUID& id)
 	{
-		selfStopPhase(mTrackingPhase);
 		if (mCB)
 		{
 			mCB->fire(id);
 		}
 	}
 
+	// virtual
+	~LLTrackPhaseWrapper()
+	{
+		selfStopPhase(mTrackingPhase);
+	}
+
 protected:
 	std::string mTrackingPhase;
 	LLPointer<LLInventoryCallback> mCB;
-- 
cgit v1.2.3


From 3a0cd466f1182f5868dc21b951d78796542abd7d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 29 Aug 2013 14:59:40 -0400
Subject: SH-4455 WIP - restrict use of LLWearableHoldingPattern metrics. When
 changing wearables, bail out if current wearables already match those
 requested.

---
 indra/newview/llagentwearables.cpp |  68 ++++++++++++++++++------
 indra/newview/llagentwearables.h   |   2 +-
 indra/newview/llappearancemgr.cpp  | 106 +++++++++++++++++++++++--------------
 indra/newview/llappearancemgr.h    |   2 +-
 indra/newview/llwearablelist.cpp   |   1 +
 5 files changed, 121 insertions(+), 58 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index f3c9998a7d..326c584c32 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1230,29 +1230,67 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 
 // Assumes existing wearables are not dirty.
 void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items,
-										 const LLDynamicArray< LLViewerWearable* >& wearables,
-										 BOOL remove)
+										 const LLDynamicArray< LLViewerWearable* >& wearables)
 {
 	llinfos << "setWearableOutfit() start" << llendl;
 
+	S32 count = wearables.count();
+	llassert(items.count() == count);
+
+	// Check for whether outfit already matches the one requested (!)
+	S32 i;
+
+	S32 matched = 0, mismatched = 0;
+	std::vector<S32> type_counts(LLWearableType::WT_COUNT,0);
+	for (i = 0; i < count; i++)
+	{
+		LLViewerWearable* new_wearable = wearables[i];
+		LLPointer<LLInventoryItem> new_item = items[i];
+		const LLWearableType::EType type = new_wearable->getType();
+		S32 index = type_counts[type];
+		LLViewerWearable *curr_wearable = dynamic_cast<LLViewerWearable*>(getWearable(type,index));
+		if (new_wearable && curr_wearable &&
+			new_wearable->getAssetID() == curr_wearable->getAssetID())
+		{
+			matched++;
+		}
+		else
+		{
+			LL_DEBUGS("Avatar") << "mismatch, type " << type << " index " << index
+								<< " names " << (curr_wearable ? curr_wearable->getName() : "NONE")  << ","
+								<< " names " << (new_wearable ? new_wearable->getName() : "NONE")  << llendl;
+			mismatched++;
+		}
+		type_counts[type]++;
+	}
+	LL_DEBUGS("Avatar") << "matched " << matched << " mismatched " << mismatched << llendl;
+	for (S32 j=0; j<LLWearableType::WT_COUNT; j++)
+	{
+		LLWearableType::EType type = (LLWearableType::EType) j;
+		if (getWearableCount(type) != type_counts[j])
+		{
+			LL_DEBUGS("Avatar") << "count mismatch for type " << j << " current " << getWearableCount(j) << " requested " << type_counts[j] << llendl; 
+			mismatched++;
+		}
+	}
+	if (mismatched == 0)
+	{
+		LL_DEBUGS("Avatar") << "nothing to do" << llendl;
+		return;
+	}
+	
+	
 	// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
-	if (remove)
+	// note: shirt is the first non-body part wearable item. Update if wearable order changes.
+	// This loop should remove all clothing, but not any body parts
+	for (S32 type = 0; type < (S32)LLWearableType::WT_COUNT; type++)
 	{
-		// note: shirt is the first non-body part wearable item. Update if wearable order changes.
-		// This loop should remove all clothing, but not any body parts
-		for (S32 type = 0; type < (S32)LLWearableType::WT_COUNT; type++)
+		if (LLWearableType::getAssetType((LLWearableType::EType)type) == LLAssetType::AT_CLOTHING)
 		{
-			if (LLWearableType::getAssetType((LLWearableType::EType)type) == LLAssetType::AT_CLOTHING)
-			{
-				removeWearable((LLWearableType::EType)type, true, 0);
-			}
+			removeWearable((LLWearableType::EType)type, true, 0);
 		}
 	}
 
-	S32 count = wearables.count();
-	llassert(items.count() == count);
-
-	S32 i;
 	for (i = 0; i < count; i++)
 	{
 		LLViewerWearable* new_wearable = wearables[i];
@@ -1307,7 +1345,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 
 	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
 
-	lldebugs << "setWearableOutfit() end" << llendl;
+	LL_DEBUGS("Avatar") << "setWearableOutfit() end" << llendl;
 }
 
 
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 8a1b470e22..96fe4b80c0 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -108,7 +108,7 @@ private:
 	/*virtual*/void	wearableUpdated(LLWearable *wearable, BOOL removed);
 public:
 	void			setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false);
-	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove);
+	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables);
 	void			setWearableName(const LLUUID& item_id, const std::string& new_name);
 	// *TODO: Move this into llappearance/LLWearableData ?
 	void			addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 2e7ec0b2d5..eada358e8d 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -619,6 +619,7 @@ public:
 	void handleLateArrivals();
 	void resetTime(F32 timeout);
 	static S32 countActive() { return sActiveHoldingPatterns.size(); }
+	S32 index() { return mIndex; }
 	
 private:
 	found_list_t mFoundList;
@@ -632,12 +633,15 @@ private:
 	bool mFired;
 	typedef std::set<LLWearableHoldingPattern*> type_set_hp;
 	static type_set_hp sActiveHoldingPatterns;
+	static S32 sNextIndex;
+	S32 mIndex;
 	bool mIsMostRecent;
 	std::set<LLViewerWearable*> mLateArrivals;
 	bool mIsAllComplete;
 };
 
 LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPatterns;
+S32 LLWearableHoldingPattern::sNextIndex = 0;
 
 LLWearableHoldingPattern::LLWearableHoldingPattern():
 	mResolved(0),
@@ -645,10 +649,10 @@ LLWearableHoldingPattern::LLWearableHoldingPattern():
 	mIsMostRecent(true),
 	mIsAllComplete(false)
 {
-	if (sActiveHoldingPatterns.size()>0)
+	if (countActive()>0)
 	{
 		llinfos << "Creating LLWearableHoldingPattern when "
-				<< sActiveHoldingPatterns.size()
+				<< countActive()
 				<< " other attempts are active."
 				<< " Flagging others as invalid."
 				<< llendl;
@@ -660,7 +664,9 @@ LLWearableHoldingPattern::LLWearableHoldingPattern():
 		}
 			 
 	}
+	mIndex = sNextIndex++;
 	sActiveHoldingPatterns.insert(this);
+	LL_DEBUGS("Avatar") << "HP " << index() << " created" << llendl;
 	selfStartPhase("holding_pattern");
 }
 
@@ -671,6 +677,7 @@ LLWearableHoldingPattern::~LLWearableHoldingPattern()
 	{
 		selfStopPhase("holding_pattern");
 	}
+	LL_DEBUGS("Avatar") << "HP " << index() << " deleted" << llendl;
 }
 
 bool LLWearableHoldingPattern::isMostRecent()
@@ -718,7 +725,7 @@ void LLWearableHoldingPattern::checkMissingWearables()
 	if (!isMostRecent())
 	{
 		// runway why don't we actually skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 
 	std::vector<S32> found_by_type(LLWearableType::WT_COUNT,0);
@@ -736,7 +743,7 @@ void LLWearableHoldingPattern::checkMissingWearables()
 	{
 		if (requested_by_type[type] > found_by_type[type])
 		{
-			llwarns << self_av_string() << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
+			llwarns << self_av_string() << "HP " << index() << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
 		}
 		if (found_by_type[type] > 0)
 			continue;
@@ -753,13 +760,16 @@ void LLWearableHoldingPattern::checkMissingWearables()
 			mTypesToRecover.insert(type);
 			mTypesToLink.insert(type);
 			recoverMissingWearable((LLWearableType::EType)type);
-			llwarns << self_av_string() << "need to replace " << type << llendl; 
+			llwarns << self_av_string() << "HP " << index() << " need to replace wearable of type " << type << llendl; 
 		}
 	}
 
 	resetTime(60.0F);
 
-	selfStartPhase("get_missing_wearables");
+	if (isMostRecent())
+	{
+		selfStartPhase("get_missing_wearables");
+	}
 	if (!pollMissingWearables())
 	{
 		doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this));
@@ -776,13 +786,13 @@ void LLWearableHoldingPattern::onAllComplete()
 	if (!isMostRecent())
 	{
 		// runway need to skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 
 	// Activate all gestures in this folder
 	if (mGestItems.count() > 0)
 	{
-		LL_DEBUGS("Avatar") << self_av_string() << "Activating " << mGestItems.count() << " gestures" << LL_ENDL;
+		LL_DEBUGS("Avatar") << self_av_string() << "HP " << index() << " activating " << mGestItems.count() << " gestures" << LL_ENDL;
 		
 		LLGestureMgr::instance().activateGestures(mGestItems);
 		
@@ -799,13 +809,13 @@ void LLWearableHoldingPattern::onAllComplete()
 	}
 
 	// Update wearables.
-	LL_INFOS("Avatar") << self_av_string() << "Updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
-	LLAppearanceMgr::instance().updateAgentWearables(this, false);
+	LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
+	LLAppearanceMgr::instance().updateAgentWearables(this);
 	
 	// Update attachments to match those requested.
 	if (isAgentAvatarValid())
 	{
-		LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.count() << " attachments" << LL_ENDL;
+		LL_DEBUGS("Avatar") << self_av_string() << "HP " << index() << " updating " << mObjItems.count() << " attachments" << LL_ENDL;
 		LLAgentWearables::userUpdateAttachments(mObjItems);
 	}
 
@@ -823,12 +833,15 @@ void LLWearableHoldingPattern::onAllComplete()
 
 void LLWearableHoldingPattern::onFetchCompletion()
 {
-	selfStopPhase("get_wearables");
+	if (isMostRecent())
+	{
+		selfStopPhase("get_wearables");
+	}
 		
 	if (!isMostRecent())
 	{
 		// runway skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 
 	checkMissingWearables();
@@ -840,7 +853,7 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
 	if (!isMostRecent())
 	{
 		// runway skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 
 	bool completed = isFetchCompleted();
@@ -849,14 +862,14 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
 
 	if (done)
 	{
-		LL_INFOS("Avatar") << self_av_string() << "polling, done status: " << completed << " timed out " << timed_out
+		LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " polling, done status: " << completed << " timed out " << timed_out
 				<< " elapsed " << mWaitTime.getElapsedTimeF32() << LL_ENDL;
 
 		mFired = true;
 		
 		if (timed_out)
 		{
-			llwarns << self_av_string() << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
+			llwarns << self_av_string() << "HP " << index() << " exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
 		}
 
 		onFetchCompletion();
@@ -868,11 +881,11 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L
 {
 	if (!holder->isMostRecent())
 	{
-		llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << "HP " << holder->index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 		// runway skip here?
 	}
 
-	llinfos << "Recovered item link for type " << type << llendl;
+	llinfos << "HP " << holder->index() << " recovered item link for type " << type << llendl;
 	holder->eraseTypeToLink(type);
 	// Add wearable to FoundData for actual wearing
 	LLViewerInventoryItem *item = gInventory.getItem(item_id);
@@ -896,12 +909,12 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L
 		}
 		else
 		{
-			llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl;
+			llwarns << self_av_string() << "HP " << holder->index() << " inventory item not found for recovered wearable" << llendl;
 		}
 	}
 	else
 	{
-		llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl;
+		llwarns << self_av_string() << "HP " << holder->index() << " inventory link not found for recovered wearable" << llendl;
 	}
 }
 
@@ -910,10 +923,10 @@ void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLView
 	if (!holder->isMostRecent())
 	{
 		// runway skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << holder->index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 
-	LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL;
+	LL_DEBUGS("Avatar") << self_av_string() << "HP " << holder->index() << " recovered item for type " << type << LL_ENDL;
 	LLConstPointer<LLInventoryObject> itemp = gInventory.getItem(item_id);
 	wearable->setItemID(item_id);
 	holder->eraseTypeToRecover(type);
@@ -931,13 +944,13 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
 	if (!isMostRecent())
 	{
 		// runway skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 	
 		// Try to recover by replacing missing wearable with a new one.
 	LLNotificationsUtil::add("ReplacedMissingWearable");
-	lldebugs << "Wearable " << LLWearableType::getTypeLabel(type)
-			 << " could not be downloaded.  Replaced inventory item with default wearable." << llendl;
+	LL_DEBUGS("Avatar") << "HP " << index() << " wearable " << LLWearableType::getTypeLabel(type)
+						<< " could not be downloaded.  Replaced inventory item with default wearable." << llendl;
 	LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
 
 	// Add a new one in the lost and found folder.
@@ -970,7 +983,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
 		if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable))
 		{
 			// Wearable link that was never resolved; remove links to it from COF
-			LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
+			LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
 			LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID);
 		}
 	}
@@ -981,7 +994,7 @@ bool LLWearableHoldingPattern::pollMissingWearables()
 	if (!isMostRecent())
 	{
 		// runway skip here?
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 	
 	bool timed_out = isTimedOut();
@@ -990,7 +1003,7 @@ bool LLWearableHoldingPattern::pollMissingWearables()
 
 	if (!done)
 	{
-		LL_INFOS("Avatar") << self_av_string() << "polling missing wearables, waiting for items " << mTypesToRecover.size()
+		LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " polling missing wearables, waiting for items " << mTypesToRecover.size()
 				<< " links " << mTypesToLink.size()
 				<< " wearables, timed out " << timed_out
 				<< " elapsed " << mWaitTime.getElapsedTimeF32()
@@ -999,7 +1012,10 @@ bool LLWearableHoldingPattern::pollMissingWearables()
 
 	if (done)
 	{
-		selfStopPhase("get_missing_wearables");
+		if (isMostRecent())
+		{
+			selfStopPhase("get_missing_wearables");
+		}
 
 		gAgentAvatarp->debugWearablesLoaded();
 
@@ -1030,14 +1046,14 @@ void LLWearableHoldingPattern::handleLateArrivals()
 	}
 	if (!isMostRecent())
 	{
-		llwarns << self_av_string() << "Late arrivals not handled - outfit change no longer valid" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " late arrivals not handled - outfit change no longer valid" << llendl;
 	}
 	if (!mIsAllComplete)
 	{
-		llwarns << self_av_string() << "Late arrivals not handled - in middle of missing wearables processing" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " late arrivals not handled - in middle of missing wearables processing" << llendl;
 	}
 
-	LL_INFOS("Avatar") << self_av_string() << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL;
+	LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL;
 
 	// Update mFoundList using late-arriving wearables.
 	std::set<LLWearableType::EType> replaced_types;
@@ -1100,7 +1116,7 @@ void LLWearableHoldingPattern::handleLateArrivals()
 	mLateArrivals.clear();
 
 	// Update appearance based on mFoundList
-	LLAppearanceMgr::instance().updateAgentWearables(this, false);
+	LLAppearanceMgr::instance().updateAgentWearables(this);
 }
 
 void LLWearableHoldingPattern::resetTime(F32 timeout)
@@ -1113,19 +1129,19 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLViewerWearable *wearable)
 {
 	if (!isMostRecent())
 	{
-		llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
 	}
 	
 	mResolved += 1;  // just counting callbacks, not successes.
-	LL_DEBUGS("Avatar") << self_av_string() << "resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL;
+	LL_DEBUGS("Avatar") << self_av_string() << "HP " << index() << " resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL;
 	if (!wearable)
 	{
-		llwarns << self_av_string() << "no wearable found" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " " << "no wearable found" << llendl;
 	}
 
 	if (mFired)
 	{
-		llwarns << self_av_string() << "called after holder fired" << llendl;
+		llwarns << self_av_string() << "HP " << index() << " " << "called after holder fired" << llendl;
 		if (wearable)
 		{
 			mLateArrivals.insert(wearable);
@@ -1151,7 +1167,9 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLViewerWearable *wearable)
 			// Failing this means inventory or asset server are corrupted in a way we don't handle.
 			if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType))
 			{
-				llwarns << self_av_string() << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
+				llwarns << self_av_string() << "HP " << index() << " "
+						<< "recovered wearable but type invalid. inventory wearable type: "
+						<< data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
 				break;
 			}
 
@@ -1898,9 +1916,10 @@ void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointer<LLI
 	updatePanelOutfitName(new_outfit_name);
 }
 
-void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, bool append)
+void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder)
 {
-	lldebugs << "updateAgentWearables()" << llendl;
+	LL_DEBUGS("Avatar") << "starts" << llendl;
+	LLTimer timer;
 	LLInventoryItem::item_array_t items;
 	LLDynamicArray< LLViewerWearable* > wearables;
 
@@ -1926,8 +1945,9 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo
 
 	if(wearables.count() > 0)
 	{
-		gAgentWearables.setWearableOutfit(items, wearables, !append);
+		gAgentWearables.setWearableOutfit(items, wearables);
 	}
+	LL_DEBUGS("Avatar") << "ends, elapsed " << timer.getElapsedTimeF32() << llendl;
 }
 
 S32 LLAppearanceMgr::countActiveHoldingPatterns()
@@ -2114,6 +2134,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 	sortItemsByActualDescription(wear_items);
 
 
+	LL_DEBUGS("Avatar") << "HP block starts" << llendl;
+	LLTimer hp_block_timer;
 	LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
 
 	holder->setObjItems(obj_items);
@@ -2188,6 +2210,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 		doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollFetchCompletion,holder));
 	}
 	post_update_func();
+
+	LL_DEBUGS("Avatar") << "HP block ends, elapsed " << hp_block_timer.getElapsedTimeF32() << llendl;
 }
 
 void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 346577ab9a..3a90c3840a 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -126,7 +126,7 @@ public:
 	void purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb = NULL);
 	void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter);
 
-	void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
+	void updateAgentWearables(LLWearableHoldingPattern* holder);
 
 	S32 countActiveHoldingPatterns();
 
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index ef1a953f59..49b3c27ea0 100755
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -81,6 +81,7 @@ void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& weara
 	LLViewerWearable* instance = get_if_there(mList, assetID, (LLViewerWearable*)NULL );
 	if( instance )
 	{
+		LL_DEBUGS("Avatar") << "wearable " << assetID << " found in LLWearableList" << llendl;
 		asset_arrived_callback( instance, userdata );
 	}
 	else
-- 
cgit v1.2.3


From f426f8a694429209ca0eeea9156173e8a12ddc46 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 29 Aug 2013 17:08:30 -0400
Subject: SH-4455 WIP - versioned some metrics whose usage has changed, added
 name and item id checks in setWearableOutfit()

---
 indra/newview/llagentwearables.cpp | 52 +++++++++++++++++++++++++-------------
 indra/newview/llappearancemgr.cpp  |  8 +++---
 2 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 326c584c32..8501436b5b 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1237,31 +1237,49 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	S32 count = wearables.count();
 	llassert(items.count() == count);
 
-	// Check for whether outfit already matches the one requested (!)
-	S32 i;
-
+	// Check for whether outfit already matches the one requested
 	S32 matched = 0, mismatched = 0;
-	std::vector<S32> type_counts(LLWearableType::WT_COUNT,0);
-	for (i = 0; i < count; i++)
+	const S32 arr_size = LLWearableType::WT_COUNT;
+	S32 type_counts[arr_size];
+	std::fill(type_counts,type_counts+arr_size,0);
+	for (S32 i = 0; i < count; i++)
 	{
 		LLViewerWearable* new_wearable = wearables[i];
 		LLPointer<LLInventoryItem> new_item = items[i];
+
 		const LLWearableType::EType type = new_wearable->getType();
-		S32 index = type_counts[type];
-		LLViewerWearable *curr_wearable = dynamic_cast<LLViewerWearable*>(getWearable(type,index));
-		if (new_wearable && curr_wearable &&
-			new_wearable->getAssetID() == curr_wearable->getAssetID())
+		if (type < 0 || type>=LLWearableType::WT_COUNT)
 		{
-			matched++;
+			llwarns << "invalid type " << type << llendl;
+			mismatched++;
+			continue;
 		}
-		else
+		S32 index = type_counts[type];
+		type_counts[type]++;
+
+		LLViewerWearable *curr_wearable = dynamic_cast<LLViewerWearable*>(getWearable(type,index));
+		if (!new_wearable || !curr_wearable ||
+			new_wearable->getAssetID() != curr_wearable->getAssetID())
 		{
 			LL_DEBUGS("Avatar") << "mismatch, type " << type << " index " << index
 								<< " names " << (curr_wearable ? curr_wearable->getName() : "NONE")  << ","
 								<< " names " << (new_wearable ? new_wearable->getName() : "NONE")  << llendl;
 			mismatched++;
+			continue;
 		}
-		type_counts[type]++;
+
+		if (curr_wearable->getName() != new_item->getName() ||
+			curr_wearable->getItemID() != new_item->getUUID())
+		{
+			LL_DEBUGS("Avatar") << "mismatch on name or inventory id, names "
+								<< curr_wearable->getName() << " vs " << new_item->getName()
+								<< " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID()
+								<< llendl;
+			mismatched++;
+			continue;
+		}
+		// If we got here, everything matches.
+		matched++;
 	}
 	LL_DEBUGS("Avatar") << "matched " << matched << " mismatched " << mismatched << llendl;
 	for (S32 j=0; j<LLWearableType::WT_COUNT; j++)
@@ -1275,7 +1293,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	}
 	if (mismatched == 0)
 	{
-		LL_DEBUGS("Avatar") << "nothing to do" << llendl;
+		LL_DEBUGS("Avatar") << "no changes, bailing out" << llendl;
 		return;
 	}
 	
@@ -1283,15 +1301,15 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
 	// note: shirt is the first non-body part wearable item. Update if wearable order changes.
 	// This loop should remove all clothing, but not any body parts
-	for (S32 type = 0; type < (S32)LLWearableType::WT_COUNT; type++)
+	for (S32 j = 0; j < (S32)LLWearableType::WT_COUNT; j++)
 	{
-		if (LLWearableType::getAssetType((LLWearableType::EType)type) == LLAssetType::AT_CLOTHING)
+		if (LLWearableType::getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING)
 		{
-			removeWearable((LLWearableType::EType)type, true, 0);
+			removeWearable((LLWearableType::EType)j, true, 0);
 		}
 	}
 
-	for (i = 0; i < count; i++)
+	for (S32 i = 0; i < count; i++)
 	{
 		LLViewerWearable* new_wearable = wearables[i];
 		LLPointer<LLInventoryItem> new_item = items[i];
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index eada358e8d..7fbe84312e 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -768,7 +768,7 @@ void LLWearableHoldingPattern::checkMissingWearables()
 
 	if (isMostRecent())
 	{
-		selfStartPhase("get_missing_wearables");
+		selfStartPhase("get_missing_wearables_2");
 	}
 	if (!pollMissingWearables())
 	{
@@ -835,7 +835,7 @@ void LLWearableHoldingPattern::onFetchCompletion()
 {
 	if (isMostRecent())
 	{
-		selfStopPhase("get_wearables");
+		selfStopPhase("get_wearables_2");
 	}
 		
 	if (!isMostRecent())
@@ -1014,7 +1014,7 @@ bool LLWearableHoldingPattern::pollMissingWearables()
 	{
 		if (isMostRecent())
 		{
-			selfStopPhase("get_missing_wearables");
+			selfStopPhase("get_missing_wearables_2");
 		}
 
 		gAgentAvatarp->debugWearablesLoaded();
@@ -2185,7 +2185,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 		}
 	}
 
-	selfStartPhase("get_wearables");
+	selfStartPhase("get_wearables_2");
 
 	for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin();
 		 it != holder->getFoundList().end(); ++it)
-- 
cgit v1.2.3


From 497e84202e169356e66fc91cd8f74b26b34b0c56 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 30 Aug 2013 11:14:17 -0400
Subject: SH-4456 FIX - added info to metrics for viewer version tags.

---
 indra/newview/llvoavatarself.cpp | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index a710c95233..ac59aa0907 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -63,6 +63,7 @@
 #include "llsdutil.h"
 #include "llstartup.h"
 #include "llsdserialize.h"
+#include "llversioninfo.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -2373,11 +2374,29 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records,
 	return result;
 }
 
+// Valid characters for tsdb are alphanumeric, _-./. Others must be cleaned out.
+void sanitize_for_tsdb_tag(std::string& s)
+{
+	for (std::string::iterator it = s.begin(); it != s.end(); ++it)
+	{
+		if (std::isalnum(*it) || *it == '.' || *it == '_' || *it == '-' || *it == '/')
+		{
+			continue;
+		}
+		*it = '_';
+	}
+}
+
 void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 {
 	static volatile bool reporting_started(false);
 	static volatile S32 report_sequence(0);
 
+	std::string viewer_version_channel = LLVersionInfo::getChannel();
+	sanitize_for_tsdb_tag(viewer_version_channel);
+	std::string viewer_version_short = LLVersionInfo::getShortVersion();
+	std::string viewer_version_build = llformat("%d", LLVersionInfo::getBuild());
+
 	LLSD msg; // = metricsData();
 	msg["message"] = "ViewerAppearanceChangeMetrics";
 	msg["session_id"] = gAgentSessionID;
@@ -2386,6 +2405,9 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	msg["initial"] = !reporting_started;
 	msg["break"] = false;
 	msg["duration"] = mTimeSinceLastRezMessage.getElapsedTimeF32();
+	msg["viewer_version_channel"] = viewer_version_channel;
+	msg["viewer_version_short"] = viewer_version_short;
+	msg["viewer_version_build"] = viewer_version_build;
 
 	// Status of our own rezzing.
 	msg["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
-- 
cgit v1.2.3


From 726a26d4bc3b66dafbc8bdfe238c52a0eff23a74 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 30 Aug 2013 19:05:23 -0400
Subject: SH-4458 FIX "Pant flares rendering as tights after SSA rollout"

probably not related to SSA rollout, but we were not triggering the
callbacks for baked texture loads, since the avatar object was adding
paused callbacks to the callback list without properly setting the
flag to indicate paused callbacks.
---
 indra/newview/llvoavatar.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7909570883..0bd51d9c15 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6328,6 +6328,9 @@ void LLVOAvatar::updateMeshTextures()
 				}
 				baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), 
 					src_callback_list, paused );
+
+                               // this could add paused texture callbacks
+                               mLoadedCallbacksPaused |= paused; 
 			}
 		}
 		else if (layerset && isUsingLocalAppearance())
@@ -6677,6 +6680,9 @@ void LLVOAvatar::onFirstTEMessageReceived()
 				LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL;
 				image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), 
 					src_callback_list, paused );
+
+                               // this could add paused texture callbacks
+                               mLoadedCallbacksPaused |= paused; 
 			}
 		}
 
-- 
cgit v1.2.3


From f878b032e8c96c4e4ae752864d7641bba2ea4102 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Mon, 9 Sep 2013 13:13:22 -0700
Subject: Using transaction_id instead of raw asset_id during aisv3 patch

---
 indra/newview/llaisapi.cpp          | 4 ++--
 indra/newview/llaisapi.h            | 2 +-
 indra/newview/llviewerinventory.cpp | 6 ++++++
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 85b304d90e..6f6e6ebb35 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -243,7 +243,7 @@ UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
 	setCommandFunc(cmd);
 }
 
-UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& item_id,
+UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id,
 											 const LLSD& updates,
 											 LLPointer<LLInventoryCallback> callback):
 	mUpdates(updates),
@@ -255,7 +255,7 @@ UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& item_id,
 		llwarns << "No cap found" << llendl;
 		return;
 	}
-	std::string url = cap + std::string("/category/") + item_id.asString();
+	std::string url = cap + std::string("/category/") + cat_id.asString();
 	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index 5d31129a16..f3a662c280 100755
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -105,7 +105,7 @@ private:
 class UpdateCategoryCommand: public AISCommand
 {
 public:
-	UpdateCategoryCommand(const LLUUID& item_id,
+	UpdateCategoryCommand(const LLUUID& cat_id,
 						  const LLSD& updates,
 						  LLPointer<LLInventoryCallback> callback);
 private:
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index b623b23e1a..ede6eb8490 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1253,6 +1253,12 @@ void update_inventory_item(
 	if (AISCommand::isAPIAvailable())
 	{
 		LLSD updates = update_item->asLLSD();
+		// Replace asset_id with transaction_id (hash_id)
+		if (updates.has("asset_id"))
+		{
+			updates.erase("asset_id");
+			updates["hash_id"] = update_item->getTransactionID();
+		}
 		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
 		ais_ran = cmd_ptr->run_command();
 	}
-- 
cgit v1.2.3


From 3a44c5c2a3e04ed8e7174bedb5753d29e6581019 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Tue, 10 Sep 2013 14:58:40 -0700
Subject: Fix for SH-4470 when modifying (no copy) or (no transfer) wearables.

---
 indra/newview/llviewerinventory.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index ede6eb8490..b6a5534815 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1253,12 +1253,17 @@ void update_inventory_item(
 	if (AISCommand::isAPIAvailable())
 	{
 		LLSD updates = update_item->asLLSD();
-		// Replace asset_id with transaction_id (hash_id)
+		// Replace asset_id and/or shadow_id with transaction_id (hash_id)
 		if (updates.has("asset_id"))
 		{
 			updates.erase("asset_id");
 			updates["hash_id"] = update_item->getTransactionID();
 		}
+		if (updates.has("shadow_id"))
+		{
+			updates.erase("shadow_id");
+			updates["hash_id"] = update_item->getTransactionID();
+		}
 		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
 		ais_ran = cmd_ptr->run_command();
 	}
-- 
cgit v1.2.3


From dad3090afcd56d1122ca5d6016001bc5226de4da Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 11 Sep 2013 10:45:14 -0400
Subject: SH-4422 WIP - avoid redundant calls to updateAppearanceFromCOF() if
 rezzing an attachment that's already linked in COF

---
 indra/newview/llappearancemgr.cpp | 13 +++++++++++--
 indra/newview/llappearancemgr.h   |  1 +
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 7fbe84312e..359d5aaa5c 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2590,6 +2590,12 @@ LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& i
 	return result;
 }
 
+bool LLAppearanceMgr::isLinkedInCOF(const LLUUID& item_id)
+{
+	LLInventoryModel::item_array_t links = LLAppearanceMgr::instance().findCOFItemLinks(item_id);
+	return links.size() > 0;
+}
+
 void LLAppearanceMgr::removeAllClothesFromAvatar()
 {
 	// Fetch worn clothes (i.e. the ones in COF).
@@ -3799,8 +3805,11 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
 		   // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF.
 		   // it will trigger gAgentWariables.notifyLoadingFinished()
 		   // But it is not acceptable solution. See EXT-7777
-		   LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy();
-		   LLAppearanceMgr::addCOFItemLink(item_id, cb);  // Add COF link for item.
+		   if (!isLinkedInCOF(item_id))
+		   {
+			   LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy();
+			   LLAppearanceMgr::addCOFItemLink(item_id, cb);  // Add COF link for item.
+		   }
 	   }
 	   else
 	   {
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 3a90c3840a..2a882fd977 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -145,6 +145,7 @@ public:
 
 	// Find COF entries referencing the given item.
 	LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id);
+	bool isLinkedInCOF(const LLUUID& item_id);
 
 	// Remove COF entries
 	void removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL);
-- 
cgit v1.2.3


From 25b078f9688a42d3ef01c63ebb9d9dcc9844df21 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 13 Sep 2013 11:18:28 -0400
Subject: log spam cleanup

---
 indra/newview/llmeshrepository.cpp | 2 +-
 indra/newview/llviewerstats.cpp    | 8 ++++----
 indra/newview/llvoavatar.cpp       | 6 +++---
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a888445060..6bdc99ad5e 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1930,8 +1930,8 @@ void LLMeshLODResponder::completedRaw(const LLChannelDescriptors& channels,
 		}
 		else
 		{
-			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint
 			llwarns << "Unhandled status " << dumpResponse() << llendl;
+			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint
 		}
 		return;
 	}
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 68633fba6e..f0c4d4ef3d 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -750,12 +750,12 @@ void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
 {
 	LLTimer& timer = getPhaseTimer(phase_name);
 	timer.start();
-	LL_DEBUGS("Avatar") << "startPhase " << phase_name << llendl;
+	//LL_DEBUGS("Avatar") << "startPhase " << phase_name << llendl;
 }
 
 void LLViewerStats::PhaseMap::clearPhases()
 {
-	LL_DEBUGS("Avatar") << "clearPhases" << llendl;
+	//LL_DEBUGS("Avatar") << "clearPhases" << llendl;
 
 	mPhaseMap.clear();
 }
@@ -822,11 +822,11 @@ bool LLViewerStats::PhaseMap::getPhaseValues(const std::string& phase_name, F32&
 		found = true;
 		elapsed =  iter->second.getElapsedTimeF32();
 		completed = !iter->second.getStarted();
-		LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << llendl;
+		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << llendl;
 	}
 	else
 	{
-		LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND"  << llendl;
+		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND"  << llendl;
 	}
 
 	return found;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 0bd51d9c15..93247a3625 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -717,7 +717,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
 	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
 
-	lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl;
+	LL_DEBUGS("Avatar") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl;
 
 	mPelvisp = NULL;
 
@@ -813,7 +813,7 @@ LLVOAvatar::~LLVOAvatar()
 
 	logPendingPhases();
 	
-	lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
+	LL_DEBUGS("Avatar") << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
 
 	std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer());
 	mAttachmentPoints.clear();
@@ -825,7 +825,7 @@ LLVOAvatar::~LLVOAvatar()
 
 	getPhases().clearPhases();
 	
-	lldebugs << "LLVOAvatar Destructor end" << llendl;
+	LL_DEBUGS("Avatar") << "LLVOAvatar Destructor end" << llendl;
 }
 
 void LLVOAvatar::markDead()
-- 
cgit v1.2.3


From c2ddc68afe0d9f122ee846ec1de1b4394f04998f Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Tue, 17 Sep 2013 22:30:02 -0700
Subject: Updating AISv3 api to match recent changes

---
 indra/newview/llaisapi.cpp | 60 ++++++++++++++++++++++++++++++++--------------
 indra/newview/llaisapi.h   |  6 +++--
 2 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 6f6e6ebb35..14978662f6 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -602,29 +602,37 @@ void AISUpdate::parseCategory(const LLSD& category_map)
 void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embedded)
 {
 	// We can only determine true descendent count if this contains all descendent types.
-	if (embedded.has("category") &&
-		embedded.has("link") &&
-		embedded.has("item"))
+	if (embedded.has("categories") &&
+		embedded.has("links") &&
+		embedded.has("items"))
 	{
-		mCatDescendentsKnown[category_id]  = embedded["category"].size();
-		mCatDescendentsKnown[category_id] += embedded["link"].size();
-		mCatDescendentsKnown[category_id] += embedded["item"].size();
+		mCatDescendentsKnown[category_id]  = embedded["categories"].size();
+		mCatDescendentsKnown[category_id] += embedded["links"].size();
+		mCatDescendentsKnown[category_id] += embedded["items"].size();
 	}
 }
 
 void AISUpdate::parseEmbedded(const LLSD& embedded)
 {
-	if (embedded.has("link"))
+	if (embedded.has("links")) // _embedded in a category
 	{
-		parseEmbeddedLinks(embedded["link"]);
+		parseEmbeddedLinks(embedded["links"]);
 	}
-	if (embedded.has("item"))
+	if (embedded.has("items")) // _embedded in a category
 	{
-		parseEmbeddedItems(embedded["item"]);
+		parseEmbeddedItems(embedded["items"]);
 	}
-	if (embedded.has("category"))
+	if (embedded.has("item")) // _embedded in a link
 	{
-		parseEmbeddedCategories(embedded["category"]);
+		parseEmbeddedItem(embedded["item"]);
+	}
+	if (embedded.has("categories")) // _embedded in a category
+	{
+		parseEmbeddedCategories(embedded["categories"]);
+	}
+	if (embedded.has("category")) // _embedded in a link
+	{
+		parseEmbeddedCategory(embedded["category"]);
 	}
 }
 
@@ -660,18 +668,21 @@ void AISUpdate::parseEmbeddedLinks(const LLSD& links)
 	}
 }
 
-void AISUpdate::parseEmbeddedItems(const LLSD& items)
+void AISUpdate::parseEmbeddedItem(const LLSD& item)
 {
-	// Special case: this may be a single item (_embedded in a link)
-	if (items.has("item_id"))
+	// a single item (_embedded in a link)
+	if (item.has("item_id"))
 	{
-		if (mItemIds.end() != mItemIds.find(items["item_id"].asUUID()))
+		if (mItemIds.end() != mItemIds.find(item["item_id"].asUUID()))
 		{
-			parseContent(items);
+			parseItem(item);
 		}
-		return;
 	}
+}
 
+void AISUpdate::parseEmbeddedItems(const LLSD& items)
+{
+	// a map of items (_embedded in a category)
 	for(LLSD::map_const_iterator itemit = items.beginMap(),
 			itemend = items.endMap();
 		itemit != itemend; ++itemit)
@@ -689,8 +700,21 @@ void AISUpdate::parseEmbeddedItems(const LLSD& items)
 	}
 }
 
+void AISUpdate::parseEmbeddedCategory(const LLSD& category)
+{
+	// a single category (_embedded in a link)
+	if (category.has("category_id"))
+	{
+		if (mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID()))
+		{
+			parseCategory(category);
+		}
+	}
+}
+
 void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
 {
+	// a map of categories (_embedded in a category)
 	for(LLSD::map_const_iterator categoryit = categories.beginMap(),
 			categoryend = categories.endMap();
 		categoryit != categoryend; ++categoryit)
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index f3a662c280..5a2ec94af9 100755
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -153,8 +153,10 @@ public:
 	void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
 	void parseEmbedded(const LLSD& embedded);
 	void parseEmbeddedLinks(const LLSD& links);
-	void parseEmbeddedItems(const LLSD& links);
-	void parseEmbeddedCategories(const LLSD& links);
+	void parseEmbeddedItems(const LLSD& items);
+	void parseEmbeddedCategories(const LLSD& categories);
+	void parseEmbeddedItem(const LLSD& item);
+	void parseEmbeddedCategory(const LLSD& category);
 	void doUpdate();
 private:
 	void clearParseResults();
-- 
cgit v1.2.3


From 36bb33b12ab090e2acbc7e00039cdff682882fa4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 18 Sep 2013 17:03:34 -0400
Subject: sunshine cleanup annotations

---
 indra/llappearance/llavatarappearance.h |  3 +++
 indra/llappearance/lltexglobalcolor.cpp |  1 +
 indra/llappearance/lltexglobalcolor.h   |  1 +
 indra/llappearance/lltexlayerparams.cpp |  5 +++++
 indra/llappearance/lltexlayerparams.h   |  4 ++++
 indra/newview/llagent.cpp               |  2 ++
 indra/newview/llagent.h                 |  2 ++
 indra/newview/llagentwearables.cpp      |  1 +
 indra/newview/llagentwearables.h        |  1 +
 indra/newview/llassetuploadresponders.h |  1 +
 indra/newview/llviewertexlayer.cpp      |  1 +
 indra/newview/llviewertexlayer.h        | 17 +++++++++++++++++
 indra/newview/llviewertexture.cpp       |  2 ++
 indra/newview/llvoavatar.cpp            |  6 ++++++
 indra/newview/llvoavatar.h              |  2 ++
 indra/newview/llvoavatarself.cpp        | 10 ++++++++++
 indra/newview/llvoavatarself.h          |  2 ++
 17 files changed, 61 insertions(+)
 mode change 100644 => 100755 indra/llappearance/llavatarappearance.h
 mode change 100644 => 100755 indra/llappearance/lltexlayerparams.cpp
 mode change 100644 => 100755 indra/llappearance/lltexlayerparams.h
 mode change 100644 => 100755 indra/newview/llviewertexlayer.cpp
 mode change 100644 => 100755 indra/newview/llviewertexlayer.h

diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
old mode 100644
new mode 100755
index bf13680496..3cb28c1137
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -225,6 +225,7 @@ public:
 	// Composites
 	//--------------------------------------------------------------------
 public:
+	// SUNSHINE CLEANUP no upload
 	virtual void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0;
 
 /********************************************************************************
@@ -256,6 +257,7 @@ protected:
 	// Clothing colors (convenience functions to access visual parameters)
 	//--------------------------------------------------------------------
 public:
+	// SUNSHINE CLEANUP no upload
 	void			setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake);
 	LLColor4		getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te);
 	static BOOL		teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name);
@@ -265,6 +267,7 @@ public:
 	//--------------------------------------------------------------------
 public:
 	LLColor4		getGlobalColor(const std::string& color_name ) const;
+	// SUNSHINE CLEANUP no upload
 	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0;
 protected:
 	LLTexGlobalColor* mTexSkinColor;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
index f38b982104..958f5f3069 100644
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -103,6 +103,7 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
 	return new_param;
 }
 
+	// SUNSHINE CLEANUP no upload
 void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
 {
 	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake);
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
index 2867479876..b9d12c801e 100644
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -75,6 +75,7 @@ public:
 	LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
 protected:
+		// SUNSHINE CLEANUP no upload
 	/*virtual*/ void onGlobalColorChanged(bool upload_bake);
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
old mode 100644
new mode 100755
index 6aae9a8cc1..cd48dcece4
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -160,6 +160,7 @@ BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
 	return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; 	
 }
 
+// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
 {
 	if (mIsAnimating || mTexLayer == NULL)
@@ -184,6 +185,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
 	}
 }
 
+// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake)
 { 
 	// do not animate dummy parameters
@@ -202,6 +204,7 @@ void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake
 	}
 }
 
+// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake)
 {
 	if (mNext)
@@ -449,6 +452,8 @@ LLColor4 LLTexLayerParamColor::getNetColor() const
 	}
 }
 
+
+// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
 {
 	if (mIsAnimating)
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
old mode 100644
new mode 100755
index b38d28d3eb..c1ea8a9fb6
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -83,8 +83,11 @@ public:
 	// LLVisualParam Virtual functions
 	///*virtual*/ BOOL		parseData(LLXmlTreeNode* node);
 	/*virtual*/ void		apply( ESex avatar_sex ) {}
+	// SUNSHINE CLEANUP no upload_bake
 	/*virtual*/ void		setWeight(F32 weight, BOOL upload_bake);
+	// SUNSHINE CLEANUP no upload_bake
 	/*virtual*/ void		setAnimationTarget(F32 target_value, BOOL upload_bake); 
+	// SUNSHINE CLEANUP no upload_bake
 	/*virtual*/ void		animate(F32 delta, BOOL upload_bake);
 
 	// LLViewerVisualParam Virtual functions
@@ -190,6 +193,7 @@ public:
 	// New functions
 	LLColor4				getNetColor() const;
 protected:
+		// SUNSHINE CLEANUP no upload
 	virtual void onGlobalColorChanged(bool upload_bake) {}
 private:
 	LL_ALIGN_16(LLVector4a				mAvgDistortionVec);
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 5f87d73c40..c13082efdc 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3612,6 +3612,7 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **)
 }
 */
 
+// SUNSHINE CLEANUP dead code?
 //static
 void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data)
 {
@@ -4300,6 +4301,7 @@ void LLAgent::dumpSentAppearance(const std::string& dump_prefix)
 //-----------------------------------------------------------------------------
 // sendAgentSetAppearance()
 //-----------------------------------------------------------------------------
+// SUNSHINE CLEANUP dead
 void LLAgent::sendAgentSetAppearance()
 {
 	if (gAgentQueryManager.mNumPendingQueries > 0) 
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index f5f26f69d8..3681b81afa 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -844,6 +844,7 @@ private:
 public:
 	void			sendMessage(); // Send message to this agent's region
 	void			sendReliableMessage();
+	// SUNSHINE CLEANUP dead code
 	void 			dumpSentAppearance(const std::string& dump_prefix);
 	void			sendAgentSetAppearance();
 	void 			sendAgentDataUpdateRequest();
@@ -859,6 +860,7 @@ public:
 	static void		processAgentGroupDataUpdate(LLMessageSystem *msg, void **);
 	static void		processAgentDropGroup(LLMessageSystem *msg, void **);
 	static void		processScriptControlChange(LLMessageSystem *msg, void **);
+	// SUNSHINE CLEANUP dead code?
 	static void		processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data);
 	
 /**                    Messaging
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 8501436b5b..0bb126ffd1 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1488,6 +1488,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
 	updateServer();
 }
 
+// SUNSHINE CLEANUP dead?
 void LLAgentWearables::queryWearableCache()
 {
 	if (!areWearablesLoaded() || (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()))
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 96fe4b80c0..fd9f6f74a1 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -158,6 +158,7 @@ protected:
 	//--------------------------------------------------------------------
 public:
 	// Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant)
+	// SUNSHINE CLEANUP - should be able to remove dependency on this.
 	static void		processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
 
 protected:
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index abfdc4ca77..7c48f2f06b 100755
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -116,6 +116,7 @@ private:
 	Impl* mImpl;
 };
 
+// SUNSHINE CLEANUP no upload bakes, remove class.
 struct LLBakedUploadData;
 class LLSendTexLayerResponder : public LLAssetUploadResponder
 {
diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
old mode 100644
new mode 100755
index 777e1f9c76..c17e85f7a6
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -272,6 +272,7 @@ BOOL LLViewerTexLayerSetBuffer::uploadPending() const
 	return mUploadPending;
 }
 
+// SUNSHINE CLEANUP no upload
 BOOL LLViewerTexLayerSetBuffer::uploadNeeded() const
 {
 	return mNeedsUpload;
diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h
old mode 100644
new mode 100755
index 959c883da8..aa4bad3422
--- a/indra/newview/llviewertexlayer.h
+++ b/indra/newview/llviewertexlayer.h
@@ -119,25 +119,41 @@ protected:
 	// Uploads
 	//--------------------------------------------------------------------
 public:
+	// SUNSHINE CLEANUP no upload
 	void					requestUpload();
+	// SUNSHINE CLEANUP no upload
 	void					cancelUpload();
+	// SUNSHINE CLEANUP no upload
 	BOOL					uploadNeeded() const; 			// We need to upload a new texture
+	// SUNSHINE CLEANUP no upload
 	BOOL					uploadInProgress() const; 		// We have started uploading a new texture and are awaiting the result
+	// SUNSHINE CLEANUP no upload
 	BOOL					uploadPending() const; 			// We are expecting a new texture to be uploaded at some point
+	// SUNSHINE CLEANUP no upload
 	static void				onTextureUploadComplete(const LLUUID& uuid,
 													void* userdata,
 													S32 result, LLExtStat ext_status);
 protected:
+	// SUNSHINE CLEANUP no upload
 	BOOL					isReadyToUpload() const;
+	// SUNSHINE CLEANUP no upload
 	void					doUpload(); 					// Does a read back and upload.
+	// SUNSHINE CLEANUP no upload
 	void					conditionalRestartUploadTimer();
 private:
+	// SUNSHINE CLEANUP no upload
 	BOOL					mNeedsUpload; 					// Whether we need to send our baked textures to the server
+	// SUNSHINE CLEANUP no upload
 	U32						mNumLowresUploads; 				// Number of times we've sent a lowres version of our baked textures to the server
+	// SUNSHINE CLEANUP no upload
 	BOOL					mUploadPending; 				// Whether we have received back the new baked textures
+	// SUNSHINE CLEANUP no upload
 	LLUUID					mUploadID; 						// The current upload process (null if none).
+	// SUNSHINE CLEANUP no upload
 	LLFrameTimer    		mNeedsUploadTimer; 				// Tracks time since upload was requested and performed.
+	// SUNSHINE CLEANUP no upload
 	S32						mUploadFailCount;				// Number of consecutive upload failures
+	// SUNSHINE CLEANUP no upload
 	LLFrameTimer    		mUploadRetryTimer; 				// Tracks time since last upload failure.
 
 	//--------------------------------------------------------------------
@@ -162,6 +178,7 @@ private:
 //
 // Used by LLTexLayerSetBuffer for a callback.
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// SUNSHINE CLEANUP no upload
 struct LLBakedUploadData
 {
 	LLBakedUploadData(const LLVOAvatarSelf* avatar,
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 7e35af7e63..80f25b7d4c 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -964,6 +964,8 @@ LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type,
 	mFTType = f_type;
 	if (mFTType == FTT_HOST_BAKE)
 	{
+		// SUNSHINE CLEANUP
+		llassert(false);
 		mCanUseHTTP = false;
 	}
 	generateGLTexture() ;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 93247a3625..8e293d0c06 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1897,6 +1897,8 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 		}
 		else
 		{
+			// SUNSHINE CLEANUP
+			llassert(false);
 			LL_DEBUGS("Avatar") << avString() << "get old-bake image from host " << uuid << llendl;
 			LLHost host = getObjectHost();
 			result = LLViewerTextureManager::getFetchedTexture(
@@ -5345,6 +5347,7 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
 //-----------------------------------------------------------------------------
 // updateSexDependentLayerSets()
 //-----------------------------------------------------------------------------
+// SUNSHINE CLEANUP no upload_bake
 void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
 {
 	invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
@@ -5829,6 +5832,7 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const
 
 
 // virtual
+// SUNSHINE CLEANUP no upload_result
 void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
 {
 }
@@ -5838,6 +5842,7 @@ void LLVOAvatar::invalidateAll()
 }
 
 // virtual
+// SUNSHINE CLEANUP no upload_bake
 void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake )
 {
 	if (global_color == mTexSkinColor)
@@ -7611,6 +7616,7 @@ void LLVOAvatar::startAppearanceAnimation()
 }
 
 //virtual
+// SUNSHINE CLEANUP dead code
 void LLVOAvatar::bodySizeChanged()
 {
 	if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF())
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 8d047045cb..13c0332d35 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -402,6 +402,7 @@ public:
 	// Global colors
 	//--------------------------------------------------------------------
 public:
+		// SUNSHINE CLEANUP no upload
 	/*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake);
 
 	//--------------------------------------------------------------------
@@ -562,6 +563,7 @@ protected:
 	// Composites
 	//--------------------------------------------------------------------
 public:
+		// SUNSHINE CLEANUP no upload
 	virtual void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
 	virtual void	invalidateAll();
 	virtual void	setCompositeUpdatesEnabled(bool b) {}
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index ac59aa0907..f6b29f2eb4 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -673,6 +673,7 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
 	return LLVOAvatar::getJoint(name);
 }
 // virtual
+// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake )
 {
 	if (!which_param)
@@ -684,6 +685,7 @@ BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32
 }
 
 // virtual
+// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake )
 {
 	if (!param_name)
@@ -695,12 +697,14 @@ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BO
 }
 
 // virtual
+// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake )
 {
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
 	return setParamWeight(param,weight,upload_bake);
 }
 
+// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake )
 {
 	if (!param)
@@ -794,6 +798,8 @@ U32  LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
 {
 	U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp);
 
+	// SUNSHINE CLEANUP - does this become relevant again if we don't have to wait for appearance message to tell us where bakes are coming from?
+
 #if 0
 	// DRANO - it's not clear this does anything useful. If we wait
 	// until an appearance message has been received, we already have
@@ -1065,6 +1071,7 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
 // forces an update to any baked textures relevant to type.
 // will force an upload of the resulting bake if the second parameter is TRUE
 //-----------------------------------------------------------------------------
+// SUNSHINE CLEANUP no upload_result
 void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_result )
 {
 	for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin();
@@ -1620,6 +1627,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const
 	return false;
 }
 
+// SUNSHINE CLEANUP no upload_bake
 void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
 {
 	LLViewerTexLayerSet *layer_set = dynamic_cast<LLViewerTexLayerSet*>(layerset);
@@ -2690,6 +2698,8 @@ void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTexture
 //-----------------------------------------------------------------------------
 void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 {
+	// SUNSHINE CLEANUP
+	llassert(false);
 	// Baked textures live on other sims.
 	LLHost target_host = getObjectHost();	
 	setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) );
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 3cbf2b5cf5..7eeaaf5fe5 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -248,6 +248,7 @@ protected:
 	// Layers
 	//--------------------------------------------------------------------
 public:
+	// SUNSHINE CLEANUP
 	void 				requestLayerSetUploads();
 	void				requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i);
 	void				requestLayerSetUpdate(LLAvatarAppearanceDefines::ETextureIndex i);
@@ -259,6 +260,7 @@ public:
 	// Composites
 	//--------------------------------------------------------------------
 public:
+		// SUNSHINE CLEANUP no upload
 	/* virtual */ void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
 	/* virtual */ void	invalidateAll();
 	/* virtual */ void	setCompositeUpdatesEnabled(bool b); // only works for self
-- 
cgit v1.2.3


From 497d3f4bfc2b6b45574ef871c11c6fb8e6145d63 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 18 Sep 2013 17:04:34 -0400
Subject: sunshine cleanup annotations

---
 indra/newview/llagent.cpp      | 1 +
 indra/newview/llvoavatar.cpp   | 2 ++
 indra/newview/llvoavatar.h     | 1 +
 indra/newview/llvoavatarself.h | 1 +
 4 files changed, 5 insertions(+)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index c13082efdc..2bcd7d300e 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -811,6 +811,7 @@ void LLAgent::standUp()
 }
 
 
+// SUNSHINE CLEANUP - are there any cases we still want to handle here?
 void LLAgent::handleServerBakeRegionTransition(const LLUUID& region_id)
 {
 	llinfos << "called" << llendl;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 8e293d0c06..1d25bc1e29 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6896,6 +6896,7 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 	}
 }
 
+// SUNSHINE CLEANUP - OK to remove the version = 0 case, assume we're at least 1?
 bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32& appearance_version)
 {
 	appearance_version = -1;
@@ -6926,6 +6927,7 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 	return true;
 }
 
+// SUNSHINE CLEANUP - if we can assume server baking, we can simplify some code here.
 //-----------------------------------------------------------------------------
 // processAvatarAppearance()
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 13c0332d35..9722b77956 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -649,6 +649,7 @@ public:
 
 	// True if this avatar should fetch its baked textures via the new
 	// appearance mechanism.
+	// SUNSHINE CLEANUP - always true, remove?
 	BOOL				isUsingServerBakes() const;
 	void 				setIsUsingServerBakes(BOOL newval);
 
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 7eeaaf5fe5..b4981e9823 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -196,6 +196,7 @@ public:
 	// Loading status
 	//--------------------------------------------------------------------
 public:
+	// SUNSHINE CLEANUP
 	/*virtual*/ bool	hasPendingBakedUploads() const;
 	S32					getLocalDiscardLevel(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const;
 	bool				areTexturesCurrent() const;
-- 
cgit v1.2.3


From 67193b259a5f4cae029b3e08aecf71c1a7041046 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 18 Sep 2013 17:27:40 -0400
Subject: sunshine cleanup annotations

---
 indra/newview/llagentwearables.cpp | 2 ++
 indra/newview/llagentwearables.h   | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 0bb126ffd1..5cc2435761 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -304,6 +304,7 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy
 	gInventory.notifyObservers();
 }
 
+// SUNSHINE CLEANUP dead?
 void LLAgentWearables::sendAgentWearablesUpdate()
 {
 	// First make sure that we have inventory items for each wearable
@@ -1908,6 +1909,7 @@ void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id)
 	}
 }
 
+// SUNSHINE CLEANUP - both of these funcs seem to be dead code, so this one should go too.
 void LLAgentWearables::updateServer()
 {
 	sendAgentWearablesUpdate();
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index fd9f6f74a1..8cab9f847b 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -163,6 +163,7 @@ public:
 
 protected:
 	/*virtual*/ void	invalidateBakedTextureHash(LLMD5& hash) const;
+	// SUNSHINE CLEANUP dead
 	void			sendAgentWearablesUpdate();
 	void			sendAgentWearablesRequest();
 	void			queryWearableCache();
@@ -244,6 +245,7 @@ private:
 	protected:
 		~createStandardWearablesAllDoneCallback();
 	};
+	// SUNSHINE CLEANUP - should be dead if sendAgentWearablesUpdate is no longer needed.
 	class sendAgentWearablesUpdateCallback : public LLRefCount
 	{
 	protected:
-- 
cgit v1.2.3


From 0bb3f482af4088cc145344689ff51ebfd59f0bac Mon Sep 17 00:00:00 2001
From: Logan Dethrow <log@lindenlab.com>
Date: Wed, 18 Sep 2013 18:34:44 -0400
Subject: Backed out revision 9038e63bc38d, which added viewer version
 information to what is sent in an appearance metric message. We are taking
 another approach to get the same information in a more consistent, reliable
 way.

---
 indra/newview/llvoavatarself.cpp | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index ac59aa0907..a710c95233 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -63,7 +63,6 @@
 #include "llsdutil.h"
 #include "llstartup.h"
 #include "llsdserialize.h"
-#include "llversioninfo.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -2374,29 +2373,11 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records,
 	return result;
 }
 
-// Valid characters for tsdb are alphanumeric, _-./. Others must be cleaned out.
-void sanitize_for_tsdb_tag(std::string& s)
-{
-	for (std::string::iterator it = s.begin(); it != s.end(); ++it)
-	{
-		if (std::isalnum(*it) || *it == '.' || *it == '_' || *it == '-' || *it == '/')
-		{
-			continue;
-		}
-		*it = '_';
-	}
-}
-
 void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 {
 	static volatile bool reporting_started(false);
 	static volatile S32 report_sequence(0);
 
-	std::string viewer_version_channel = LLVersionInfo::getChannel();
-	sanitize_for_tsdb_tag(viewer_version_channel);
-	std::string viewer_version_short = LLVersionInfo::getShortVersion();
-	std::string viewer_version_build = llformat("%d", LLVersionInfo::getBuild());
-
 	LLSD msg; // = metricsData();
 	msg["message"] = "ViewerAppearanceChangeMetrics";
 	msg["session_id"] = gAgentSessionID;
@@ -2405,9 +2386,6 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	msg["initial"] = !reporting_started;
 	msg["break"] = false;
 	msg["duration"] = mTimeSinceLastRezMessage.getElapsedTimeF32();
-	msg["viewer_version_channel"] = viewer_version_channel;
-	msg["viewer_version_short"] = viewer_version_short;
-	msg["viewer_version_build"] = viewer_version_build;
 
 	// Status of our own rezzing.
 	msg["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
-- 
cgit v1.2.3


From 82f147367fb5e4ee4bbe53db01856ea375058825 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 19 Sep 2013 11:10:59 -0400
Subject: SH-3455 WIP - removing bake upload code

---
 indra/llappearance/llavatarappearance.cpp       |  8 ++---
 indra/llappearance/llavatarappearance.h         |  6 ++--
 indra/llappearance/lldriverparam.cpp            | 28 +++++++--------
 indra/llappearance/lldriverparam.h              |  8 ++---
 indra/llappearance/llpolymorph.cpp              |  2 +-
 indra/llappearance/llpolyskeletaldistortion.cpp |  2 +-
 indra/llappearance/lltexglobalcolor.cpp         |  4 +--
 indra/llappearance/lltexglobalcolor.h           |  2 +-
 indra/llappearance/lltexlayerparams.cpp         | 32 ++++++++---------
 indra/llappearance/lltexlayerparams.h           | 14 ++++----
 indra/llappearance/llviewervisualparam.cpp      |  2 +-
 indra/llappearance/llwearable.cpp               | 18 +++++-----
 indra/llappearance/llwearable.h                 |  6 ++--
 indra/llcharacter/llcharacter.cpp               | 14 ++++----
 indra/llcharacter/llcharacter.h                 |  6 ++--
 indra/llcharacter/llvisualparam.cpp             | 18 +++++-----
 indra/llcharacter/llvisualparam.h               |  8 ++---
 indra/newview/llagent.cpp                       |  2 +-
 indra/newview/llagentwearables.cpp              | 10 +++---
 indra/newview/llagentwearables.h                |  2 +-
 indra/newview/llbreastmotion.cpp                |  3 +-
 indra/newview/llemote.cpp                       | 12 +++----
 indra/newview/llpaneleditwearable.cpp           |  8 ++---
 indra/newview/llphysicsmotion.cpp               |  8 ++---
 indra/newview/llscrollingpanelparam.cpp         |  6 ++--
 indra/newview/llscrollingpanelparambase.cpp     |  2 +-
 indra/newview/lltoolmorph.cpp                   |  6 ++--
 indra/newview/llviewerwearable.cpp              |  8 ++---
 indra/newview/llviewerwearable.h                |  4 +--
 indra/newview/llvoavatar.cpp                    | 48 ++++++++++++-------------
 indra/newview/llvoavatar.h                      |  6 ++--
 indra/newview/llvoavatarself.cpp                | 34 +++++++++---------
 indra/newview/llvoavatarself.h                  | 10 +++---
 33 files changed, 172 insertions(+), 175 deletions(-)
 mode change 100644 => 100755 indra/llappearance/llavatarappearance.cpp
 mode change 100644 => 100755 indra/llappearance/lldriverparam.cpp
 mode change 100644 => 100755 indra/llappearance/lldriverparam.h
 mode change 100644 => 100755 indra/llappearance/lltexglobalcolor.cpp
 mode change 100644 => 100755 indra/llappearance/lltexglobalcolor.h
 mode change 100644 => 100755 indra/llappearance/llwearable.cpp
 mode change 100644 => 100755 indra/llappearance/llwearable.h
 mode change 100644 => 100755 indra/newview/llviewerwearable.cpp
 mode change 100644 => 100755 indra/newview/llviewerwearable.h

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
old mode 100644
new mode 100755
index e3497c107d..05cd7e8c41
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -1361,14 +1361,14 @@ BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name )
 	return TRUE;
 }
 
-void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
+void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color)
 {
 	U32 param_name[3];
 	if( teToColorParams( te, param_name ) )
 	{
-		setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
-		setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
-		setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
+		setVisualParamWeight( param_name[0], new_color.mV[VX]);
+		setVisualParamWeight( param_name[1], new_color.mV[VY]);
+		setVisualParamWeight( param_name[2], new_color.mV[VZ]);
 	}
 }
 
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 3cb28c1137..d7bfe0d7c7 100755
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -226,7 +226,7 @@ public:
 	//--------------------------------------------------------------------
 public:
 	// SUNSHINE CLEANUP no upload
-	virtual void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0;
+	virtual void	invalidateComposite(LLTexLayerSet* layerset) = 0;
 
 /********************************************************************************
  **                                                                            **
@@ -258,7 +258,7 @@ protected:
 	//--------------------------------------------------------------------
 public:
 	// SUNSHINE CLEANUP no upload
-	void			setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake);
+	void			setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color);
 	LLColor4		getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te);
 	static BOOL		teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name);
 
@@ -268,7 +268,7 @@ public:
 public:
 	LLColor4		getGlobalColor(const std::string& color_name ) const;
 	// SUNSHINE CLEANUP no upload
-	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0;
+	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0;
 protected:
 	LLTexGlobalColor* mTexSkinColor;
 	LLTexGlobalColor* mTexHairColor;
diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
old mode 100644
new mode 100755
index 1f7e8b8652..83dbcfd6bf
--- a/indra/llappearance/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -178,7 +178,7 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
 	mID = info->mID;
 	info->mDriverParam = this;
 
-	setWeight(getDefaultWeight(), FALSE );
+	setWeight(getDefaultWeight());
 
 	return TRUE;
 }
@@ -195,7 +195,7 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
 	return new_param;
 }
 
-void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
+void LLDriverParam::setWeight(F32 weight)
 {
 	F32 min_weight = getMinWeight();
 	F32 max_weight = getMaxWeight();
@@ -254,7 +254,7 @@ void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
 					driven_weight = driven_min;
 				}
 				
-				setDrivenWeight(driven,driven_weight,upload_bake);
+				setDrivenWeight(driven,driven_weight);
 				continue;
 			}
 			else 
@@ -278,13 +278,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
 					driven_weight = driven_min;
 				}
 
-				setDrivenWeight(driven,driven_weight,upload_bake);
+				setDrivenWeight(driven,driven_weight);
 				continue;
 			}
 		}
 
 		driven_weight = getDrivenWeight(driven, mCurWeight);
-		setDrivenWeight(driven,driven_weight,upload_bake);
+		setDrivenWeight(driven,driven_weight);
 	}
 }
 
@@ -430,9 +430,9 @@ const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const
 //-----------------------------------------------------------------------------
 // setAnimationTarget()
 //-----------------------------------------------------------------------------
-void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
+void LLDriverParam::setAnimationTarget( F32 target_value)
 {
-	LLVisualParam::setAnimationTarget(target_value, upload_bake);
+	LLVisualParam::setAnimationTarget(target_value);
 
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
@@ -441,16 +441,16 @@ void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
 
 		// this isn't normally necessary, as driver params handle interpolation of their driven params
 		// but texture params need to know to assume their final value at beginning of interpolation
-		driven->mParam->setAnimationTarget(driven_weight, upload_bake);
+		driven->mParam->setAnimationTarget(driven_weight);
 	}
 }
 
 //-----------------------------------------------------------------------------
 // stopAnimating()
 //-----------------------------------------------------------------------------
-void LLDriverParam::stopAnimating(BOOL upload_bake)
+void LLDriverParam::stopAnimating()
 {
-	LLVisualParam::stopAnimating(upload_bake);
+	LLVisualParam::stopAnimating();
 
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
@@ -530,7 +530,7 @@ void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type)
 		LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type);
 		if (wearable)
 		{
-			wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false);
+			wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID));
 		}
 	}
 }
@@ -593,7 +593,7 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight
 	return driven_weight;
 }
 
-void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake)
+void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight)
 {
 	bool use_self = false;
 	if(mWearablep &&
@@ -610,10 +610,10 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bo
 	if (use_self)
 	{
 		// call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values
-		mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake );
+		mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight);
 	}
 	else
 	{
-		driven->mParam->setWeight( driven_weight, upload_bake );
+		driven->mParam->setWeight( driven_weight);
 	}
 }
diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h
old mode 100644
new mode 100755
index 040c9cf5be..5a45c8f30d
--- a/indra/llappearance/lldriverparam.h
+++ b/indra/llappearance/lldriverparam.h
@@ -110,9 +110,9 @@ public:
 
 	// LLVisualParam Virtual functions
 	/*virtual*/ void				apply( ESex sex ) {} // apply is called separately for each driven param.
-	/*virtual*/ void				setWeight(F32 weight, BOOL upload_bake);
-	/*virtual*/ void				setAnimationTarget( F32 target_value, BOOL upload_bake );
-	/*virtual*/ void				stopAnimating(BOOL upload_bake);
+	/*virtual*/ void				setWeight(F32 weight);
+	/*virtual*/ void				setAnimationTarget( F32 target_value);
+	/*virtual*/ void				stopAnimating();
 	/*virtual*/ BOOL				linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
 	/*virtual*/ void				resetDrivenParams();
 	
@@ -129,7 +129,7 @@ public:
 
 protected:
 	F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
-	void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
+	void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight);
 
 
 	LL_ALIGN_16(LLVector4a	mDefaultVec); // temp holder
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index 93c2f15a53..84df3f1830 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -342,7 +342,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
 		return FALSE;
 	mInfo = info;
 	mID = info->mID;
-	setWeight(getDefaultWeight(), FALSE );
+	setWeight(getDefaultWeight());
 
 	LLAvatarAppearance* avatarp = mMesh->getAvatar();
 	LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index eb86f77d97..2a5866afe4 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -130,7 +130,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
                 return FALSE;
         mInfo = info;
         mID = info->mID;
-        setWeight(getDefaultWeight(), FALSE );
+        setWeight(getDefaultWeight());
 
         LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
         for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
old mode 100644
new mode 100755
index 958f5f3069..b9539e45b8
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -104,9 +104,9 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
 }
 
 	// SUNSHINE CLEANUP no upload
-void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
+void LLTexParamGlobalColor::onGlobalColorChanged()
 {
-	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake);
+	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
old mode 100644
new mode 100755
index b9d12c801e..3a6f852baf
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -76,7 +76,7 @@ public:
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
 protected:
 		// SUNSHINE CLEANUP no upload
-	/*virtual*/ void onGlobalColorChanged(bool upload_bake);
+	/*virtual*/ void onGlobalColorChanged();
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
 };
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index cd48dcece4..6d4001958e 100755
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -161,7 +161,7 @@ BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
 }
 
 // SUNSHINE CLEANUP no upload_bake
-void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
+void LLTexLayerParamAlpha::setWeight(F32 weight)
 {
 	if (mIsAnimating || mTexLayer == NULL)
 	{
@@ -179,37 +179,37 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
 		if ((mAvatarAppearance->getSex() & getSex()) &&
 			(mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
-			mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+			mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
 			mTexLayer->invalidateMorphMasks();
 		}
 	}
 }
 
 // SUNSHINE CLEANUP no upload_bake
-void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value)
 { 
 	// do not animate dummy parameters
 	if (mIsDummy)
 	{
-		setWeight(target_value, upload_bake);
+		setWeight(target_value);
 		return;
 	}
 
 	mTargetWeight = target_value; 
-	setWeight(target_value, upload_bake); 
+	setWeight(target_value); 
 	mIsAnimating = TRUE;
 	if (mNext)
 	{
-		mNext->setAnimationTarget(target_value, upload_bake);
+		mNext->setAnimationTarget(target_value);
 	}
 }
 
 // SUNSHINE CLEANUP no upload_bake
-void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake)
+void LLTexLayerParamAlpha::animate(F32 delta)
 {
 	if (mNext)
 	{
-		mNext->animate(delta, upload_bake);
+		mNext->animate(delta);
 	}
 }
 
@@ -454,7 +454,7 @@ LLColor4 LLTexLayerParamColor::getNetColor() const
 
 
 // SUNSHINE CLEANUP no upload_bake
-void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
+void LLTexLayerParamColor::setWeight(F32 weight)
 {
 	if (mIsAnimating)
 	{
@@ -479,10 +479,10 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
 
 		if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
-			onGlobalColorChanged(upload_bake);
+			onGlobalColorChanged();
 			if (mTexLayer)
 			{
-				mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+				mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
 			}
 		}
 
@@ -490,23 +490,23 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
 	}
 }
 
-void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLTexLayerParamColor::setAnimationTarget(F32 target_value)
 { 
 	// set value first then set interpolating flag to ignore further updates
 	mTargetWeight = target_value; 
-	setWeight(target_value, upload_bake);
+	setWeight(target_value);
 	mIsAnimating = TRUE;
 	if (mNext)
 	{
-		mNext->setAnimationTarget(target_value, upload_bake);
+		mNext->setAnimationTarget(target_value);
 	}
 }
 
-void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake)
+void LLTexLayerParamColor::animate(F32 delta)
 {
 	if (mNext)
 	{
-		mNext->animate(delta, upload_bake);
+		mNext->animate(delta);
 	}
 }
 
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index c1ea8a9fb6..86d1ea9e67 100755
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -84,11 +84,11 @@ public:
 	///*virtual*/ BOOL		parseData(LLXmlTreeNode* node);
 	/*virtual*/ void		apply( ESex avatar_sex ) {}
 	// SUNSHINE CLEANUP no upload_bake
-	/*virtual*/ void		setWeight(F32 weight, BOOL upload_bake);
+	/*virtual*/ void		setWeight(F32 weight);
 	// SUNSHINE CLEANUP no upload_bake
-	/*virtual*/ void		setAnimationTarget(F32 target_value, BOOL upload_bake); 
+	/*virtual*/ void		setAnimationTarget(F32 target_value); 
 	// SUNSHINE CLEANUP no upload_bake
-	/*virtual*/ void		animate(F32 delta, BOOL upload_bake);
+	/*virtual*/ void		animate(F32 delta);
 
 	// LLViewerVisualParam Virtual functions
 	/*virtual*/ F32					getTotalDistortion()									{ return 1.f; }
@@ -177,9 +177,9 @@ public:
 	// LLVisualParam Virtual functions
 	///*virtual*/ BOOL			parseData(LLXmlTreeNode* node);
 	/*virtual*/ void			apply( ESex avatar_sex ) {}
-	/*virtual*/ void			setWeight(F32 weight, BOOL upload_bake);
-	/*virtual*/ void			setAnimationTarget(F32 target_value, BOOL upload_bake);
-	/*virtual*/ void			animate(F32 delta, BOOL upload_bake);
+	/*virtual*/ void			setWeight(F32 weight);
+	/*virtual*/ void			setAnimationTarget(F32 target_value);
+	/*virtual*/ void			animate(F32 delta);
 
 
 	// LLViewerVisualParam Virtual functions
@@ -194,7 +194,7 @@ public:
 	LLColor4				getNetColor() const;
 protected:
 		// SUNSHINE CLEANUP no upload
-	virtual void onGlobalColorChanged(bool upload_bake) {}
+	virtual void onGlobalColorChanged() {}
 private:
 	LL_ALIGN_16(LLVector4a				mAvgDistortionVec);
 } LL_ALIGN_POSTFIX(16);
diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp
index cc81bcf118..0d8d1dbeca 100644
--- a/indra/llappearance/llviewervisualparam.cpp
+++ b/indra/llappearance/llviewervisualparam.cpp
@@ -137,7 +137,7 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info)
 		return FALSE;
 	mInfo = info;
 	mID = info->mID;
-	setWeight(getDefaultWeight(), FALSE );
+	setWeight(getDefaultWeight());
 	return TRUE;
 }
 
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
old mode 100644
new mode 100755
index d86a460511..525a782ba0
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -524,7 +524,7 @@ void LLWearable::revertValues()
 		LLVisualParam *param = getVisualParam(id);
 		if(param &&  !dynamic_cast<LLDriverParam*>(param) )
 		{
-			setVisualParamWeight(id, value, TRUE);
+			setVisualParamWeight(id, value);
 		}
 	}
 
@@ -536,7 +536,7 @@ void LLWearable::revertValues()
 		LLVisualParam *param = getVisualParam(id);
 		if(param &&  dynamic_cast<LLDriverParam*>(param) )
 		{
-			setVisualParamWeight(id, value, TRUE);
+			setVisualParamWeight(id, value);
 		}
 	}
 
@@ -646,12 +646,12 @@ void LLWearable::addVisualParam(LLVisualParam *param)
 }
 
 
-void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake)
+void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
 {
 	if( is_in_map(mVisualParamIndexMap, param_index ) )
 	{
 		LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
-		wearable_param->setWeight(value, upload_bake);
+		wearable_param->setWeight(value);
 	}
 	else
 	{
@@ -692,14 +692,14 @@ void LLWearable::getVisualParams(visual_param_vec_t &list)
 	}
 }
 
-void LLWearable::animateParams(F32 delta, BOOL upload_bake)
+void LLWearable::animateParams(F32 delta)
 {
 	for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
 		 iter != mVisualParamIndexMap.end();
 		 ++iter)
 	{
 		LLVisualParam *param = (LLVisualParam*) iter->second;
-		param->animate(delta, upload_bake);
+		param->animate(delta);
 	}
 }
 
@@ -717,14 +717,14 @@ LLColor4 LLWearable::getClothesColor(S32 te) const
 	return color;
 }
 
-void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake )
+void LLWearable::setClothesColor( S32 te, const LLColor4& new_color)
 {
 	U32 param_name[3];
 	if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) )
 	{
 		for( U8 index = 0; index < 3; index++ )
 		{
-			setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake);
+			setVisualParamWeight(param_name[index], new_color.mV[index]);
 		}
 	}
 }
@@ -743,7 +743,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp)
 			S32 param_id = param->getID();
 			F32 weight = getVisualParamWeight(param_id);
 
-			avatarp->setVisualParamWeight( param_id, weight, FALSE );
+			avatarp->setVisualParamWeight( param_id, weight);
 		}
 	}
 }
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
old mode 100644
new mode 100755
index 6f5a1e14e8..84509a60fd
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -95,14 +95,14 @@ public:
 
 	void				setLocalTextureObject(S32 index, LLLocalTextureObject &lto);
 	void				addVisualParam(LLVisualParam *param);
-	void 				setVisualParamWeight(S32 index, F32 value, BOOL upload_bake);
+	void 				setVisualParamWeight(S32 index, F32 value);
 	F32					getVisualParamWeight(S32 index) const;
 	LLVisualParam*		getVisualParam(S32 index) const;
 	void				getVisualParams(visual_param_vec_t &list);
-	void				animateParams(F32 delta, BOOL upload_bake);
+	void				animateParams(F32 delta);
 
 	LLColor4			getClothesColor(S32 te) const;
-	void 				setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake );
+	void 				setClothesColor( S32 te, const LLColor4& new_color);
 
 	virtual void		revertValues();
 	virtual void		saveValues();
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 85cf1cd3f5..2aebbc9274 100755
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -286,13 +286,13 @@ void LLCharacter::removeAnimationData(std::string name)
 //-----------------------------------------------------------------------------
 // setVisualParamWeight()
 //-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight)
 {
 	S32 index = which_param->getID();
 	visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
 	if (index_iter != mVisualParamIndexMap.end())
 	{
-		index_iter->second->setWeight(weight, upload_bake);
+		index_iter->second->setWeight(weight);
 		return TRUE;
 	}
 	return FALSE;
@@ -301,7 +301,7 @@ BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 wei
 //-----------------------------------------------------------------------------
 // setVisualParamWeight()
 //-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight)
 {
 	std::string tname(param_name);
 	LLStringUtil::toLower(tname);
@@ -309,7 +309,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
 	visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
 	if (name_iter != mVisualParamNameMap.end())
 	{
-		name_iter->second->setWeight(weight, upload_bake);
+		name_iter->second->setWeight(weight);
 		return TRUE;
 	}
 	llwarns << "LLCharacter::setVisualParamWeight() Invalid visual parameter: " << param_name << llendl;
@@ -319,12 +319,12 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
 //-----------------------------------------------------------------------------
 // setVisualParamWeight()
 //-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight)
 {
 	visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
 	if (index_iter != mVisualParamIndexMap.end())
 	{
-		index_iter->second->setWeight(weight, upload_bake);
+		index_iter->second->setWeight(weight);
 		return TRUE;
 	}
 	llwarns << "LLCharacter::setVisualParamWeight() Invalid visual parameter index: " << index << llendl;
@@ -394,7 +394,7 @@ void LLCharacter::clearVisualParamWeights()
 	{
 		if (param->isTweakable())
 		{
-			param->setWeight( param->getDefaultWeight(), FALSE );
+			param->setWeight( param->getDefaultWeight());
 		}
 	}
 }
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 5740dbce77..ebc5d80a1f 100755
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -190,9 +190,9 @@ public:
 	void addVisualParam(LLVisualParam *param);
 	void addSharedVisualParam(LLVisualParam *param);
 
-	virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
-	virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
-	virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
+	virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
+	virtual BOOL setVisualParamWeight(const char* param_name, F32 weight);
+	virtual BOOL setVisualParamWeight(S32 index, F32 weight);
 
 	// get visual param weight by param or name
 	F32 getVisualParamWeight(LLVisualParam *distortion);
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index f7cb0f76b7..624e16e2ca 100755
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -220,7 +220,7 @@ BOOL LLVisualParam::parseData(LLXmlTreeNode *node)
 //-----------------------------------------------------------------------------
 // setWeight()
 //-----------------------------------------------------------------------------
-void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
+void LLVisualParam::setWeight(F32 weight)
 {
 	if (mIsAnimating)
 	{
@@ -238,19 +238,19 @@ void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
 	
 	if (mNext)
 	{
-		mNext->setWeight(weight, upload_bake);
+		mNext->setWeight(weight);
 	}
 }
 
 //-----------------------------------------------------------------------------
 // setAnimationTarget()
 //-----------------------------------------------------------------------------
-void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLVisualParam::setAnimationTarget(F32 target_value)
 {
 	// don't animate dummy parameters
 	if (mIsDummy)
 	{
-		setWeight(target_value, upload_bake);
+		setWeight(target_value);
 		mTargetWeight = mCurWeight;
 		return;
 	}
@@ -270,7 +270,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
 
 	if (mNext)
 	{
-		mNext->setAnimationTarget(target_value, upload_bake);
+		mNext->setAnimationTarget(target_value);
 	}
 }
 
@@ -287,24 +287,24 @@ void LLVisualParam::setNextParam( LLVisualParam *next )
 //-----------------------------------------------------------------------------
 // animate()
 //-----------------------------------------------------------------------------
-void LLVisualParam::animate( F32 delta, BOOL upload_bake )
+void LLVisualParam::animate( F32 delta)
 {
 	if (mIsAnimating)
 	{
 		F32 new_weight = ((mTargetWeight - mCurWeight) * delta) + mCurWeight;
-		setWeight(new_weight, upload_bake);
+		setWeight(new_weight);
 	}
 }
 
 //-----------------------------------------------------------------------------
 // stopAnimating()
 //-----------------------------------------------------------------------------
-void LLVisualParam::stopAnimating(BOOL upload_bake)
+void LLVisualParam::stopAnimating()
 { 
 	if (mIsAnimating && isTweakable())
 	{
 		mIsAnimating = FALSE; 
-		setWeight(mTargetWeight, upload_bake);
+		setWeight(mTargetWeight);
 	}
 }
 
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index a4d9f93e56..6c3bf2901a 100755
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -120,10 +120,10 @@ public:
 	//virtual BOOL			parseData( LLXmlTreeNode *node ) = 0;
 	virtual void			apply( ESex avatar_sex ) = 0;
 	//  Default functions
-	virtual void			setWeight(F32 weight, BOOL upload_bake);
-	virtual void			setAnimationTarget( F32 target_value, BOOL upload_bake );
-	virtual void			animate(F32 delta, BOOL upload_bake);
-	virtual void			stopAnimating(BOOL upload_bake);
+	virtual void			setWeight(F32 weight);
+	virtual void			setAnimationTarget( F32 target_value);
+	virtual void			animate(F32 delta);
+	virtual void			stopAnimating();
 
 	virtual BOOL			linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
 	virtual void			resetDrivenParams();
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 2bcd7d300e..fe608d657b 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3671,7 +3671,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
 					else
 					{
 						// no cache of this bake. request upload.
-						gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE);
+						gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index));
 					}
 				}
 			}
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 5cc2435761..d59138c624 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -849,7 +849,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
 			gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i);
 			if (asset_id.isNull())
 			{
-				LLViewerWearable::removeFromAvatar(type, FALSE);
+				LLViewerWearable::removeFromAvatar(type);
 			}
 			else
 			{
@@ -1205,7 +1205,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 			if (old_wearable)
 			{
 				popWearable(old_wearable);
-				old_wearable->removeFromAvatar(TRUE);
+				old_wearable->removeFromAvatar();
 			}
 		}
 		clearWearableType(type);
@@ -1218,7 +1218,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 		if (old_wearable)
 		{
 			popWearable(old_wearable);
-			old_wearable->removeFromAvatar(TRUE);
+			old_wearable->removeFromAvatar();
 		}
 	}
 
@@ -1776,7 +1776,7 @@ bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) co
 	return !(((type == LLWearableType::WT_SHAPE) || (type == LLWearableType::WT_SKIN) || (type == LLWearableType::WT_HAIR) || (type == LLWearableType::WT_EYES))
 			 && (getWearableCount(type) <= 1) );		  
 }
-void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
+void LLAgentWearables::animateAllWearableParams(F32 delta)
 {
 	for( S32 type = 0; type < LLWearableType::WT_COUNT; ++type )
 	{
@@ -1786,7 +1786,7 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
 			llassert(wearable);
 			if (wearable)
 			{
-				wearable->animateParams(delta, upload_bake);
+				wearable->animateParams(delta);
 			}
 		}
 	}
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 8cab9f847b..af4b8cd2dd 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -85,7 +85,7 @@ public:
 	// Note: False for shape, skin, eyes, and hair, unless you have MORE than 1.
 	bool			canWearableBeRemoved(const LLViewerWearable* wearable) const;
 
-	void			animateAllWearableParams(F32 delta, BOOL upload_bake);
+	void			animateAllWearableParams(F32 delta);
 
 	//--------------------------------------------------------------------
 	// Accessors
diff --git a/indra/newview/llbreastmotion.cpp b/indra/newview/llbreastmotion.cpp
index 9a8cd5ceae..3a88bab3b3 100755
--- a/indra/newview/llbreastmotion.cpp
+++ b/indra/newview/llbreastmotion.cpp
@@ -340,8 +340,7 @@ BOOL LLBreastMotion::onUpdate(F32 time, U8* joint_mask)
 		if (mBreastParamsDriven[i])
 		{
 			mCharacter->setVisualParamWeight(mBreastParamsDriven[i],
-											 new_local_pt[i],
-											 FALSE);
+											 new_local_pt[i]);
 		}
 	}
 
diff --git a/indra/newview/llemote.cpp b/indra/newview/llemote.cpp
index 510ff69acf..b9ef297c00 100755
--- a/indra/newview/llemote.cpp
+++ b/indra/newview/llemote.cpp
@@ -79,13 +79,13 @@ BOOL LLEmote::onActivate()
 	LLVisualParam* default_param = mCharacter->getVisualParam( "Express_Closed_Mouth" );
 	if( default_param )
 	{
-		default_param->setWeight( default_param->getMaxWeight(), FALSE );
+		default_param->setWeight( default_param->getMaxWeight());
 	}
 
 	mParam = mCharacter->getVisualParam(mName.c_str());
 	if (mParam)
 	{
-		mParam->setWeight(0.f, FALSE);
+		mParam->setWeight(0.f);
 		mCharacter->updateVisualParams();
 	}
 	
@@ -101,7 +101,7 @@ BOOL LLEmote::onUpdate(F32 time, U8* joint_mask)
 	if( mParam )
 	{
 		F32 weight = mParam->getMinWeight() + mPose.getWeight() * (mParam->getMaxWeight() - mParam->getMinWeight());
-		mParam->setWeight(weight, FALSE);
+		mParam->setWeight(weight);
 
 		// Cross fade against the default parameter
 		LLVisualParam* default_param = mCharacter->getVisualParam( "Express_Closed_Mouth" );
@@ -110,7 +110,7 @@ BOOL LLEmote::onUpdate(F32 time, U8* joint_mask)
 			F32 default_param_weight = default_param->getMinWeight() + 
 				(1.f - mPose.getWeight()) * ( default_param->getMaxWeight() - default_param->getMinWeight() );
 			
-			default_param->setWeight( default_param_weight, FALSE );
+			default_param->setWeight( default_param_weight);
 		}
 
 		mCharacter->updateVisualParams();
@@ -127,13 +127,13 @@ void LLEmote::onDeactivate()
 {
 	if( mParam )
 	{
-		mParam->setWeight( mParam->getDefaultWeight(), FALSE );
+		mParam->setWeight( mParam->getDefaultWeight());
 	}
 
 	LLVisualParam* default_param = mCharacter->getVisualParam( "Express_Closed_Mouth" );
 	if( default_param )
 	{
-		default_param->setWeight( default_param->getMaxWeight(), FALSE );
+		default_param->setWeight( default_param->getMaxWeight());
 	}
 
 	mCharacter->updateVisualParams();
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 582998c973..022fd6c062 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -943,11 +943,11 @@ void LLPanelEditWearable::onCommitSexChange()
         LLViewerWearable*     wearable = gAgentWearables.getViewerWearable(type, index);
         if (wearable)
         {
-                wearable->setVisualParamWeight(param->getID(), is_new_sex_male, FALSE);
+                wearable->setVisualParamWeight(param->getID(), is_new_sex_male);
         }
-        param->setWeight( is_new_sex_male, FALSE );
+        param->setWeight( is_new_sex_male);
 
-        gAgentAvatarp->updateSexDependentLayerSets( FALSE );
+        gAgentAvatarp->updateSexDependentLayerSets();
 
         gAgentAvatarp->updateVisualParams();
 
@@ -1006,7 +1006,7 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl)
                         const LLColor4& new_color = LLColor4(ctrl->getValue());
                         if( old_color != new_color )
                         {
-                                getWearable()->setClothesColor(entry->mTextureIndex, new_color, TRUE);
+                                getWearable()->setClothesColor(entry->mTextureIndex, new_color);
                                 LLVisualParamHint::requestHintUpdates();
                                 gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
                         }
diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
index 18b85cc9c3..8746f58f55 100755
--- a/indra/newview/llphysicsmotion.cpp
+++ b/indra/newview/llphysicsmotion.cpp
@@ -668,9 +668,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time)
 			if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) &&
 			    (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT))
 			{
-				mCharacter->setVisualParamWeight(driver_param,
-								 0,
-								 FALSE);
+				mCharacter->setVisualParamWeight(driver_param, 0);
 			}
 			S32 num_driven = driver_param->getDrivenParamsCount();
 			for (S32 i = 0; i < num_driven; ++i)
@@ -770,7 +768,5 @@ void LLPhysicsMotion::setParamValue(const LLViewerVisualParam *param,
 	// Scale from [0,1] to [value_min_local,value_max_local]
         const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_rescaled;
 
-        mCharacter->setVisualParamWeight(param,
-                                         new_value_local,
-                                         FALSE);
+        mCharacter->setVisualParamWeight(param, new_value_local);
 }
diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
index a7e24b86b1..bfa453a0ae 100755
--- a/indra/newview/llscrollingpanelparam.cpp
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -266,7 +266,7 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint )
 			if (slider->getMinValue() < new_percent
 				&& new_percent < slider->getMaxValue())
 			{
-				mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE);
+				mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight);
 				mWearable->writeToAvatar(gAgentAvatarp);
 				gAgentAvatarp->updateVisualParams();
 
@@ -299,7 +299,7 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata )
 			if (slider->getMinValue() < new_percent
 				&& new_percent < slider->getMaxValue())
 			{
-				self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE);
+				self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
 				self->mWearable->writeToAvatar(gAgentAvatarp);
 				slider->setValue( self->weightToPercent( new_weight ) );
 			}
@@ -333,7 +333,7 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata )
 				if (slider->getMinValue() < new_percent
 					&& new_percent < slider->getMaxValue())
 				{
-					self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE);
+					self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
 					self->mWearable->writeToAvatar(gAgentAvatarp);
 					slider->setValue( self->weightToPercent( new_weight ) );
 				}
diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp
index 8e083ddb6c..fe7a362723 100755
--- a/indra/newview/llscrollingpanelparambase.cpp
+++ b/indra/newview/llscrollingpanelparambase.cpp
@@ -93,7 +93,7 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata)
 	F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
 	if (current_weight != new_weight )
 	{
-		self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
+		self->mWearable->setVisualParamWeight( param->getID(), new_weight);
 		self->mWearable->writeToAvatar(gAgentAvatarp);
 		gAgentAvatarp->updateVisualParams();
 	}
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 71e0509d03..2d458db36b 100755
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -154,8 +154,8 @@ void LLVisualParamHint::preRender(BOOL clear_depth)
 		wearable->setVolatile(TRUE);
 	}
 	mLastParamWeight = mVisualParam->getWeight();
-	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
-	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
+	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight);
+	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight);
 	gAgentAvatarp->setVisualParamWeight("Blink_Left", 0.f);
 	gAgentAvatarp->setVisualParamWeight("Blink_Right", 0.f);
 	gAgentAvatarp->updateComposites();
@@ -246,7 +246,7 @@ BOOL LLVisualParamHint::render()
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	}
 	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
-	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight, FALSE);
+	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
 	LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr;
 	if (wearable)
 	{
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
old mode 100644
new mode 100755
index 76f94935b8..770fc69969
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -266,7 +266,7 @@ void LLViewerWearable::setParamsToDefaults()
 	{
 		if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) )
 		{
-			setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE);
+			setVisualParamWeight(param->getID(),param->getDefaultWeight());
 		}
 	}
 }
@@ -361,7 +361,7 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
 	ESex new_sex = avatarp->getSex();
 	if( old_sex != new_sex )
 	{
-		viewer_avatar->updateSexDependentLayerSets( FALSE );
+		viewer_avatar->updateSexDependentLayerSets();
 	}	
 	
 //	if( upload_bake )
@@ -373,7 +373,7 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
 
 // Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values.
 // static 
-void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake )
+void LLViewerWearable::removeFromAvatar( LLWearableType::EType type)
 {
 	if (!isAgentAvatarValid()) return;
 
@@ -392,7 +392,7 @@ void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload
 		if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->isTweakable() ) )
 		{
 			S32 param_id = param->getID();
-			gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake );
+			gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight());
 		}
 	}
 
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
old mode 100644
new mode 100755
index ef8c29323e..2e59596f12
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -61,8 +61,8 @@ public:
 	BOOL				isOldVersion() const;
 
 	/*virtual*/ void	writeToAvatar(LLAvatarAppearance *avatarp);
-	void				removeFromAvatar( BOOL upload_bake )	{ LLViewerWearable::removeFromAvatar( mType, upload_bake ); }
-	static void			removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); 
+	void				removeFromAvatar()	{ LLViewerWearable::removeFromAvatar( mType); }
+	static void			removeFromAvatar( LLWearableType::EType type); 
 
 	/*virtual*/ EImportResult	importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
 	
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 1d25bc1e29..bb8682d1fd 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1067,7 +1067,7 @@ void LLVOAvatar::restoreGL()
 	gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
 	for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++)
 	{
-		gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i), FALSE);
+		gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i));
 	}
 	gAgentAvatarp->updateMeshTextures();
 }
@@ -2132,8 +2132,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 				
 				if ( mLipSyncActive )
 				{
-					if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight(), FALSE);
-					if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight(), FALSE);
+					if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight());
+					if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight());
 					
 					mLipSyncActive = false;
 					LLCharacter::updateVisualParams();
@@ -2296,7 +2296,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 			{
 				if (param->isTweakable())
 				{
-					param->stopAnimating(FALSE);
+					param->stopAnimating();
 				}
 			}
 			updateVisualParams();
@@ -2319,7 +2319,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 				{
 					if (param->isTweakable())
 					{
-						param->animate(morph_amt, FALSE);
+						param->animate(morph_amt);
 					}
 				}
 			}
@@ -2372,7 +2372,7 @@ void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
 			F32 ooh_weight = mOohMorph->getMinWeight()
 				+ ooh_morph_amount * (mOohMorph->getMaxWeight() - mOohMorph->getMinWeight());
 
-			mOohMorph->setWeight( ooh_weight, FALSE );
+			mOohMorph->setWeight( ooh_weight);
 		}
 
 		if( mAahMorph )
@@ -2380,7 +2380,7 @@ void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
 			F32 aah_weight = mAahMorph->getMinWeight()
 				+ aah_morph_amount * (mAahMorph->getMaxWeight() - mAahMorph->getMinWeight());
 
-			mAahMorph->setWeight( aah_weight, FALSE );
+			mAahMorph->setWeight( aah_weight);
 		}
 
 		mLipSyncActive = true;
@@ -5348,11 +5348,11 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
 // updateSexDependentLayerSets()
 //-----------------------------------------------------------------------------
 // SUNSHINE CLEANUP no upload_bake
-void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
+void LLVOAvatar::updateSexDependentLayerSets()
 {
-	invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
-	invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
-	invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
+	invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
+	invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet);
+	invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet);
 }
 
 //-----------------------------------------------------------------------------
@@ -5832,8 +5832,8 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const
 
 
 // virtual
-// SUNSHINE CLEANUP no upload_result
-void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
+// SUNSHINE CLEANUP no upload_result, no-op
+void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset)
 {
 }
 
@@ -5843,18 +5843,18 @@ void LLVOAvatar::invalidateAll()
 
 // virtual
 // SUNSHINE CLEANUP no upload_bake
-void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake )
+void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
 {
 	if (global_color == mTexSkinColor)
 	{
-		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
-		invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
-		invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
+		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
+		invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet);
+		invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet);
 	}
 	else if (global_color == mTexHairColor)
 	{
-		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
-		invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, upload_bake );
+		invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
+		invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet);
 		
 		// ! BACKWARDS COMPATIBILITY !
 		// Fix for dealing with avatars from viewers that don't bake hair.
@@ -5876,7 +5876,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL
 	else if (global_color == mTexEyeColor)
 	{
 //		llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; 
-		invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet,  upload_bake );
+		invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet);
 	}
 	updateMeshTextures();
 }
@@ -7078,13 +7078,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 				if(is_first_appearance_message)
 				{
 					//LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << llendl;
-					param->setWeight(newWeight, FALSE);
+					param->setWeight(newWeight);
 				}
 				else
 				{
 					//LL_DEBUGS("Avatar") << std::setprecision(5) << " param target " << i << " " << param->getWeight() << " -> " << newWeight << llendl;
 					interp_params = TRUE;
-					param->setAnimationTarget(newWeight, FALSE);
+					param->setAnimationTarget(newWeight);
 				}
 			}
 		}
@@ -7107,7 +7107,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			ESex new_sex = getSex();
 			if( old_sex != new_sex )
 			{
-				updateSexDependentLayerSets( FALSE );
+				updateSexDependentLayerSets();
 			}	
 		}
 
@@ -7650,7 +7650,7 @@ void LLVOAvatar::setIsUsingServerBakes(BOOL newval)
 	mUseServerBakes = newval;
 	LLVisualParam* appearance_version_param = getVisualParam(11000);
 	llassert(appearance_version_param);
-	appearance_version_param->setWeight(newval ? 1.0 : 0.0, false);
+	appearance_version_param->setWeight(newval ? 1.0 : 0.0);
 }
 
 // virtual
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 9722b77956..216ab730e7 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -403,7 +403,7 @@ public:
 	//--------------------------------------------------------------------
 public:
 		// SUNSHINE CLEANUP no upload
-	/*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake);
+	/*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color);
 
 	//--------------------------------------------------------------------
 	// Visibility
@@ -564,7 +564,7 @@ protected:
 	//--------------------------------------------------------------------
 public:
 		// SUNSHINE CLEANUP no upload
-	virtual void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
+	virtual void	invalidateComposite(LLTexLayerSet* layerset);
 	virtual void	invalidateAll();
 	virtual void	setCompositeUpdatesEnabled(bool b) {}
 	virtual void 	setCompositeUpdatesEnabled(U32 index, bool b) {}
@@ -601,7 +601,7 @@ private:
 public:
 	void			debugColorizeSubMeshes(U32 i, const LLColor4& color);
 	virtual void 	updateMeshTextures();
-	void 			updateSexDependentLayerSets(BOOL upload_bake);
+	void 			updateSexDependentLayerSets();
 	virtual void	dirtyMesh(); // Dirty the avatar mesh
 	void 			updateMeshData();
 protected:
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index f6b29f2eb4..4f2af2c8ee 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -674,38 +674,38 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
 }
 // virtual
 // SUNSHINE CLEANUP no upload_bake
-BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight)
 {
 	if (!which_param)
 	{
 		return FALSE;
 	}
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID());
-	return setParamWeight(param,weight,upload_bake);
+	return setParamWeight(param,weight);
 }
 
 // virtual
 // SUNSHINE CLEANUP no upload_bake
-BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight)
 {
 	if (!param_name)
 	{
 		return FALSE;
 	}
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name);
-	return setParamWeight(param,weight,upload_bake);
+	return setParamWeight(param,weight);
 }
 
 // virtual
 // SUNSHINE CLEANUP no upload_bake
-BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight)
 {
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
-	return setParamWeight(param,weight,upload_bake);
+	return setParamWeight(param,weight);
 }
 
 // SUNSHINE CLEANUP no upload_bake
-BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake )
+BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight)
 {
 	if (!param)
 	{
@@ -729,12 +729,12 @@ BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight
 			LLViewerWearable *wearable = gAgentWearables.getViewerWearable(type,count);
 			if (wearable)
 			{
-				wearable->setVisualParamWeight(param->getID(), weight, upload_bake);
+				wearable->setVisualParamWeight(param->getID(), weight);
 			}
 		}
 	}
 
-	return LLCharacter::setVisualParamWeight(param,weight,upload_bake);
+	return LLCharacter::setVisualParamWeight(param,weight);
 }
 
 /*virtual*/ 
@@ -747,7 +747,7 @@ void LLVOAvatarSelf::updateVisualParams()
 void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
 {
 	// Animate all top-level wearable visual parameters
-	gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE);
+	gAgentWearables.animateAllWearableParams(calcMorphAmount());
 
 	// apply wearable visual params to avatar
 	for (U32 type = 0; type < LLWearableType::WT_COUNT; type++)
@@ -890,7 +890,7 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
 		{
 			LLViewerTexLayerSet *layerset = getTexLayerSet(i);
 			layerset->setUpdatesEnabled(TRUE);
-			invalidateComposite(layerset, FALSE);
+			invalidateComposite(layerset);
 		}
 		updateMeshTextures();
 		if (getRegion() && !getRegion()->getCentralBakeVersion())
@@ -1094,7 +1094,7 @@ void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_re
 					if (layerset)
 					{
 						layerset->setUpdatesEnabled(true);
-						invalidateComposite(layerset, upload_result);
+						invalidateComposite(layerset);
 					}
 					break;
 				}
@@ -1628,7 +1628,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const
 }
 
 // SUNSHINE CLEANUP no upload_bake
-void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
+void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset)
 {
 	LLViewerTexLayerSet *layer_set = dynamic_cast<LLViewerTexLayerSet*>(layerset);
 	if( !layer_set || !layer_set->getUpdatesEnabled() )
@@ -1640,6 +1640,7 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_r
 	layer_set->requestUpdate();
 	layer_set->invalidateMorphMasks();
 
+#if 0 // SUNSHINE CLEANUP
 	if( upload_result  && (getRegion() && !getRegion()->getCentralBakeVersion()))
 	{
 		llassert(isSelf());
@@ -1649,6 +1650,7 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_r
 		layer_set->requestUpload();
 		updateMeshTextures();
 	}
+#endif
 }
 
 void LLVOAvatarSelf::invalidateAll()
@@ -1656,7 +1658,7 @@ void LLVOAvatarSelf::invalidateAll()
 	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
 	{
 		LLViewerTexLayerSet *layerset = getTexLayerSet(i);
-		invalidateComposite(layerset, TRUE);
+		invalidateComposite(layerset);
 	}
 	//mDebugSelfLoadTimer.reset();
 }
@@ -2899,7 +2901,7 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
 				if (layer_set)
 				{
 					llinfos << "TAT: rebake - matched entry " << (S32)index << llendl;
-					gAgentAvatarp->invalidateComposite(layer_set, TRUE);
+					gAgentAvatarp->invalidateComposite(layer_set);
 					found = TRUE;
 					LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
 				}
@@ -2936,7 +2938,7 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 				layer_set->cancelUpload();
 			}
 
-			invalidateComposite(layer_set, TRUE);
+			invalidateComposite(layer_set);
 			LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
 		}
 		else
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index b4981e9823..32d9012862 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -97,9 +97,9 @@ public:
 	
 				void		resetJointPositions( void );
 	
-	/*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
-	/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
-	/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
+	/*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
+	/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight);
+	/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight);
 	/*virtual*/ void updateVisualParams();
 	/*virtual*/ void idleUpdateAppearanceAnimation();
 
@@ -111,7 +111,7 @@ public:
 
 private:
 	// helper function. Passed in param is assumed to be in avatar's parameter list.
-	BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE );
+	BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight);
 
 
 
@@ -262,7 +262,7 @@ public:
 	//--------------------------------------------------------------------
 public:
 		// SUNSHINE CLEANUP no upload
-	/* virtual */ void	invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
+	/* virtual */ void	invalidateComposite(LLTexLayerSet* layerset);
 	/* virtual */ void	invalidateAll();
 	/* virtual */ void	setCompositeUpdatesEnabled(bool b); // only works for self
 	/* virtual */ void  setCompositeUpdatesEnabled(U32 index, bool b);
-- 
cgit v1.2.3


From d58e7cfbfcec163345e87c0c5e5f74d01075246b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 19 Sep 2013 13:59:20 -0400
Subject: SH-3455 WIP - removing bake upload code

---
 indra/llappearance/llavatarappearance.cpp |   1 -
 indra/llappearance/llavatarappearance.h   |   4 -
 indra/llappearance/lltexglobalcolor.cpp   |   1 -
 indra/llappearance/lltexglobalcolor.h     |   1 -
 indra/llappearance/lltexlayerparams.cpp   |   4 -
 indra/llappearance/lltexlayerparams.h     |   4 -
 indra/newview/llagent.cpp                 | 268 +-----------------------------
 indra/newview/llagent.h                   |   5 -
 indra/newview/llagentwearables.cpp        |   5 +-
 indra/newview/llstartup.cpp               |   1 -
 indra/newview/llviewermessage.cpp         |   4 -
 indra/newview/llviewerwearable.cpp        |  10 --
 indra/newview/llvoavatar.cpp              |  16 +-
 indra/newview/llvoavatar.h                |   2 +-
 indra/newview/llvoavatarself.cpp          |   9 -
 15 files changed, 4 insertions(+), 331 deletions(-)

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 05cd7e8c41..f10ae813fd 100755
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -491,7 +491,6 @@ void LLAvatarAppearance::computeBodySize()
 	if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
 	{
 		mBodySize = new_body_size;
-		bodySizeChanged();
 	}
 }
 
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index d7bfe0d7c7..3d99bb0cc7 100755
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -144,7 +144,6 @@ protected:
 	static BOOL			parseSkeletonFile(const std::string& filename);
 	virtual void		buildCharacter();
 	virtual BOOL		loadAvatar();
-	virtual void		bodySizeChanged() = 0;
 
 	BOOL				setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
 	BOOL				allocateCharacterJoints(U32 num);
@@ -225,7 +224,6 @@ public:
 	// Composites
 	//--------------------------------------------------------------------
 public:
-	// SUNSHINE CLEANUP no upload
 	virtual void	invalidateComposite(LLTexLayerSet* layerset) = 0;
 
 /********************************************************************************
@@ -257,7 +255,6 @@ protected:
 	// Clothing colors (convenience functions to access visual parameters)
 	//--------------------------------------------------------------------
 public:
-	// SUNSHINE CLEANUP no upload
 	void			setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color);
 	LLColor4		getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te);
 	static BOOL		teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name);
@@ -267,7 +264,6 @@ public:
 	//--------------------------------------------------------------------
 public:
 	LLColor4		getGlobalColor(const std::string& color_name ) const;
-	// SUNSHINE CLEANUP no upload
 	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0;
 protected:
 	LLTexGlobalColor* mTexSkinColor;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
index b9539e45b8..432e2e9f49 100755
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -103,7 +103,6 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
 	return new_param;
 }
 
-	// SUNSHINE CLEANUP no upload
 void LLTexParamGlobalColor::onGlobalColorChanged()
 {
 	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor);
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
index 3a6f852baf..1b0c91b5ca 100755
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -75,7 +75,6 @@ public:
 	LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
 protected:
-		// SUNSHINE CLEANUP no upload
 	/*virtual*/ void onGlobalColorChanged();
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index 6d4001958e..80aded450d 100755
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -160,7 +160,6 @@ BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
 	return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; 	
 }
 
-// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamAlpha::setWeight(F32 weight)
 {
 	if (mIsAnimating || mTexLayer == NULL)
@@ -185,7 +184,6 @@ void LLTexLayerParamAlpha::setWeight(F32 weight)
 	}
 }
 
-// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value)
 { 
 	// do not animate dummy parameters
@@ -204,7 +202,6 @@ void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value)
 	}
 }
 
-// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamAlpha::animate(F32 delta)
 {
 	if (mNext)
@@ -453,7 +450,6 @@ LLColor4 LLTexLayerParamColor::getNetColor() const
 }
 
 
-// SUNSHINE CLEANUP no upload_bake
 void LLTexLayerParamColor::setWeight(F32 weight)
 {
 	if (mIsAnimating)
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index 86d1ea9e67..e1a8c28265 100755
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -83,11 +83,8 @@ public:
 	// LLVisualParam Virtual functions
 	///*virtual*/ BOOL		parseData(LLXmlTreeNode* node);
 	/*virtual*/ void		apply( ESex avatar_sex ) {}
-	// SUNSHINE CLEANUP no upload_bake
 	/*virtual*/ void		setWeight(F32 weight);
-	// SUNSHINE CLEANUP no upload_bake
 	/*virtual*/ void		setAnimationTarget(F32 target_value); 
-	// SUNSHINE CLEANUP no upload_bake
 	/*virtual*/ void		animate(F32 delta);
 
 	// LLViewerVisualParam Virtual functions
@@ -193,7 +190,6 @@ public:
 	// New functions
 	LLColor4				getNetColor() const;
 protected:
-		// SUNSHINE CLEANUP no upload
 	virtual void onGlobalColorChanged() {}
 private:
 	LL_ALIGN_16(LLVector4a				mAvgDistortionVec);
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index fe608d657b..845ef6e9a5 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3613,83 +3613,6 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **)
 }
 */
 
-// SUNSHINE CLEANUP dead code?
-//static
-void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data)
-{
-	gAgentQueryManager.mNumPendingQueries--;
-	if (gAgentQueryManager.mNumPendingQueries == 0)
-	{
-		selfStopPhase("fetch_texture_cache_entries");
-	}
-
-	if (!isAgentAvatarValid() || gAgentAvatarp->isDead())
-	{
-		llwarns << "No avatar for user in cached texture update!" << llendl;
-		return;
-	}
-
-	if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance())
-	{
-		// ignore baked textures when in customize mode
-		return;
-	}
-
-	S32 query_id;
-	mesgsys->getS32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, query_id);
-
-	S32 num_texture_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_WearableData);
-
-
-	S32 num_results = 0;
-	for (S32 texture_block = 0; texture_block < num_texture_blocks; texture_block++)
-	{
-		LLUUID texture_id;
-		U8 texture_index;
-
-		mesgsys->getUUIDFast(_PREHASH_WearableData, _PREHASH_TextureID, texture_id, texture_block);
-		mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block);
-
-
-		if ((S32)texture_index < TEX_NUM_INDICES )
-		{	
-			const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearanceDictionary::instance().getTexture((ETextureIndex)texture_index);
-			if (texture_entry)
-			{
-				EBakedTextureIndex baked_index = texture_entry->mBakedTextureIndex;
-
-				if (gAgentQueryManager.mActiveCacheQueries[baked_index] == query_id)
-				{
-					if (texture_id.notNull())
-					{
-						//llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl;
-						gAgentAvatarp->setCachedBakedTexture((ETextureIndex)texture_index, texture_id);
-						//gAgentAvatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id );
-						gAgentQueryManager.mActiveCacheQueries[baked_index] = 0;
-						num_results++;
-					}
-					else
-					{
-						// no cache of this bake. request upload.
-						gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index));
-					}
-				}
-			}
-		}
-	}
-	llinfos << "Received cached texture response for " << num_results << " textures." << llendl;
-	gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");
-
-	gAgentAvatarp->updateMeshTextures();
-
-	if (gAgentQueryManager.mNumPendingQueries == 0)
-	{
-		// RN: not sure why composites are disabled at this point
-		gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
-		gAgent.sendAgentSetAppearance();
-	}
-}
-
 BOOL LLAgent::anyControlGrabbed() const
 {
 	for (U32 i = 0; i < TOTAL_CONTROLS; i++)
@@ -4260,196 +4183,6 @@ void LLAgent::requestLeaveGodMode()
 	sendReliableMessage();
 }
 
-// For debugging, trace agent state at times appearance message are sent out.
-void LLAgent::dumpSentAppearance(const std::string& dump_prefix)
-{
-	std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml");
-
-	LLAPRFile outfile;
-	std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
-	outfile.open(fullpath, LL_APR_WB );
-	apr_file_t* file = outfile.getFileHandle();
-	if (!file)
-	{
-		return;
-	}
-	else
-	{
-		LL_DEBUGS("Avatar") << "dumping sent appearance message to " << fullpath << llendl;
-	}
-
-	LLVisualParam* appearance_version_param = gAgentAvatarp->getVisualParam(11000);
-	if (appearance_version_param)
-	{
-		F32 value = appearance_version_param->getWeight();
-		dump_visual_param(file, appearance_version_param, value);
-	}
-	for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
-		 iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
-		 ++iter)
-	{
-		const ETextureIndex index = iter->first;
-		const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
-		if (texture_dict->mIsBakedTexture)
-		{
-			LLTextureEntry* entry = gAgentAvatarp->getTE((U8) index);
-			const LLUUID& uuid = entry->getID();
-			apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", index, uuid.asString().c_str());
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-// sendAgentSetAppearance()
-//-----------------------------------------------------------------------------
-// SUNSHINE CLEANUP dead
-void LLAgent::sendAgentSetAppearance()
-{
-	if (gAgentQueryManager.mNumPendingQueries > 0) 
-	{
-		return;
-	}
-
-	if (!isAgentAvatarValid() || gAgentAvatarp->isEditingAppearance() || (getRegion() && getRegion()->getCentralBakeVersion())) return;
-
-	// At this point we have a complete appearance to send and are in a non-baking region.
-	// DRANO FIXME
-	//gAgentAvatarp->setIsUsingServerBakes(FALSE);
-	S32 sb_count, host_count, both_count, neither_count;
-	gAgentAvatarp->bakedTextureOriginCounts(sb_count, host_count, both_count, neither_count);
-	if (both_count != 0 || neither_count != 0)
-	{
-		llwarns << "bad bake texture state " << sb_count << "," << host_count << "," << both_count << "," << neither_count << llendl;
-	}
-	if (sb_count != 0 && host_count == 0)
-	{
-		gAgentAvatarp->setIsUsingServerBakes(true);
-	}
-	else if (sb_count == 0 && host_count != 0)
-	{
-		gAgentAvatarp->setIsUsingServerBakes(false);
-	}
-	else if (sb_count + host_count > 0)
-	{
-		llwarns << "unclear baked texture state, not sending appearance" << llendl;
-		return;
-	}
-	
-	
-	LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL;
-	//dumpAvatarTEs( "sendAgentSetAppearance()" );
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_AgentSetAppearance);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, getID());
-	msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
-
-	// correct for the collision tolerance (to make it look like the 
-	// agent is actually walking on the ground/object)
-	// NOTE -- when we start correcting all of the other Havok geometry 
-	// to compensate for the COLLISION_TOLERANCE ugliness we will have 
-	// to tweak this number again
-	const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset;
-	msg->addVector3Fast(_PREHASH_Size, body_size);
-	
-	LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mV[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL;	
-
-	// To guard against out of order packets
-	// Note: always start by sending 1.  This resets the server's count. 0 on the server means "uninitialized"
-	mAppearanceSerialNum++;
-	msg->addU32Fast(_PREHASH_SerialNum, mAppearanceSerialNum );
-
-	// is texture data current relative to wearables?
-	// KLW - TAT this will probably need to check the local queue.
-	BOOL textures_current = gAgentAvatarp->areTexturesCurrent();
-
-	for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ )
-	{
-		const ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
-
-		// if we're not wearing a skirt, we don't need the texture to be baked
-		if (texture_index == TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
-		{
-			continue;
-		}
-
-		// IMG_DEFAULT_AVATAR means not baked. 0 index should be ignored for baked textures
-		if (!gAgentAvatarp->isTextureDefined(texture_index, 0))
-		{
-			LL_DEBUGS("Avatar") << "texture not current for baked " << (S32)baked_index << " local " << (S32)texture_index << llendl;
-			textures_current = FALSE;
-			break;
-		}
-	}
-
-	// only update cache entries if we have all our baked textures
-
-	// FIXME DRANO need additional check for not in appearance editing
-	// mode, if still using local composites need to set using local
-	// composites to false, and update mesh textures.
-	if (textures_current)
-	{
-		bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
-		std::string dump_prefix = gAgentAvatarp->getFullname() + "_sent_appearance";
-		if (enable_verbose_dumps)
-		{
-			dumpSentAppearance(dump_prefix);
-		}
-		LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL;
-		for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
-		{
-			BOOL generate_valid_hash = TRUE;
-			if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLAvatarAppearanceDefines::EBakedTextureIndex)baked_index))
-			{
-				generate_valid_hash = FALSE;
-				LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL;
-			}
-
-			const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);
-			if (hash.notNull())
-			{
-				ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index);
-				msg->nextBlockFast(_PREHASH_WearableData);
-				msg->addUUIDFast(_PREHASH_CacheID, hash);
-				msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index);
-			}
-		}
-		msg->nextBlockFast(_PREHASH_ObjectData);
-		gAgentAvatarp->sendAppearanceMessage( gMessageSystem );
-	}
-	else
-	{
-		// If the textures aren't baked, send NULL for texture IDs
-		// This means the baked texture IDs on the server will be untouched.
-		// Once all textures are baked, another AvatarAppearance message will be sent to update the TEs
-		msg->nextBlockFast(_PREHASH_ObjectData);
-		gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0);
-	}
-
-
-	S32 transmitted_params = 0;
-	for (LLViewerVisualParam* param = (LLViewerVisualParam*)gAgentAvatarp->getFirstVisualParam();
-		 param;
-		 param = (LLViewerVisualParam*)gAgentAvatarp->getNextVisualParam())
-	{
-		if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ||
-			param->getGroup() == VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE) // do not transmit params of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
-		{
-			msg->nextBlockFast(_PREHASH_VisualParam );
-			
-			// We don't send the param ids.  Instead, we assume that the receiver has the same params in the same sequence.
-			const F32 param_value = param->getWeight();
-			const U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight());
-			msg->addU8Fast(_PREHASH_ParamValue, new_weight );
-			transmitted_params++;
-		}
-	}
-
-//	llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl;
-	sendReliableMessage();
-}
-
 void LLAgent::sendAgentDataUpdateRequest()
 {
 	gMessageSystem->newMessageFast(_PREHASH_AgentDataUpdateRequest);
@@ -4601,6 +4334,7 @@ LLAgentQueryManager::LLAgentQueryManager() :
 {
 	for (U32 i = 0; i < BAKED_NUM_INDICES; i++)
 	{
+		// SUNSHINE CLEANUP
 		mActiveCacheQueries[i] = 0;
 	}
 }
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 3681b81afa..eca9a3f229 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -844,9 +844,6 @@ private:
 public:
 	void			sendMessage(); // Send message to this agent's region
 	void			sendReliableMessage();
-	// SUNSHINE CLEANUP dead code
-	void 			dumpSentAppearance(const std::string& dump_prefix);
-	void			sendAgentSetAppearance();
 	void 			sendAgentDataUpdateRequest();
 	void 			sendAgentUserInfoRequest();
 	// IM to Email and Online visibility
@@ -860,8 +857,6 @@ public:
 	static void		processAgentGroupDataUpdate(LLMessageSystem *msg, void **);
 	static void		processAgentDropGroup(LLMessageSystem *msg, void **);
 	static void		processScriptControlChange(LLMessageSystem *msg, void **);
-	// SUNSHINE CLEANUP dead code?
-	static void		processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data);
 	
 /**                    Messaging
  **                                                                            **
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index d59138c624..96bfc43fb8 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -522,8 +522,6 @@ void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U3
 	{
 		wearable->revertValues();
 	}
-
-	gAgent.sendAgentSetAppearance();
 }
 
 void LLAgentWearables::saveAllWearables()
@@ -921,7 +919,7 @@ void LLAgentWearables::recoverMissingWearableDone()
 	if (areWearablesLoaded())
 	{
 		// Make sure that the server's idea of the avatar's wearables actually match the wearables.
-		gAgent.sendAgentSetAppearance();
+		//gAgent.sendAgentSetAppearance();
 	}
 	else
 	{
@@ -1913,7 +1911,6 @@ void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id)
 void LLAgentWearables::updateServer()
 {
 	sendAgentWearablesUpdate();
-	gAgent.sendAgentSetAppearance();
 }
 
 boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 1c9276bab9..3abc08ec2d 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2370,7 +2370,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 	msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair,	process_remove_name_value);
 	msg->setHandlerFuncFast(_PREHASH_AvatarAnimation,		process_avatar_animation);
 	msg->setHandlerFuncFast(_PREHASH_AvatarAppearance,		process_avatar_appearance);
-	msg->setHandlerFunc("AgentCachedTextureResponse",	LLAgent::processAgentCachedTextureResponse);
 	msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatarSelf::processRebakeAvatarTextures);
 	msg->setHandlerFuncFast(_PREHASH_CameraConstraint,		process_camera_constraint);
 	msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse,		process_avatar_sit_response);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index aecffb4ff5..c7c0e26533 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4087,10 +4087,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
 
 		gAgent.setTeleportState( LLAgent::TELEPORT_START_ARRIVAL );
 
-		// set the appearance on teleport since the new sim does not
-		// know what you look like.
-		gAgent.sendAgentSetAppearance();
-
 		if (isAgentAvatarValid())
 		{
 			// Chat the "back" SLURL. (DEV-4907)
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index 770fc69969..d56a7b5dc5 100755
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -363,11 +363,6 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
 	{
 		viewer_avatar->updateSexDependentLayerSets();
 	}	
-	
-//	if( upload_bake )
-//	{
-//		gAgent.sendAgentSetAppearance();
-//	}
 }
 
 
@@ -403,11 +398,6 @@ void LLViewerWearable::removeFromAvatar( LLWearableType::EType type)
 
 	gAgentAvatarp->updateVisualParams();
 	gAgentAvatarp->wearableUpdated(type, FALSE);
-
-//	if( upload_bake )
-//	{
-//		gAgent.sendAgentSetAppearance();
-//	}
 }
 
 // Does not copy mAssetID.
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index bb8682d1fd..987beedd9e 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2300,10 +2300,6 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
 				}
 			}
 			updateVisualParams();
-			if (isSelf())
-			{
-				gAgent.sendAgentSetAppearance();
-			}
 		}
 		else
 		{
@@ -4123,6 +4119,7 @@ bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const
 	return allTexturesCompletelyDownloaded(baked_ids);
 }
 
+// SUNSHINE CLEANUP
 void LLVOAvatar::bakedTextureOriginCounts(S32 &sb_count, // server-bake, has origin URL.
 										  S32 &host_count, // host-based bake, has host.
 										  S32 &both_count, // error - both host and URL set.
@@ -7617,17 +7614,6 @@ void LLVOAvatar::startAppearanceAnimation()
 	}
 }
 
-//virtual
-// SUNSHINE CLEANUP dead code
-void LLVOAvatar::bodySizeChanged()
-{
-	if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF())
-	{	// notify simulator of change in size
-		// but not if we are in the middle of updating appearance
-		gAgent.sendAgentSetAppearance();
-	}
-}
-
 BOOL LLVOAvatar::isUsingServerBakes() const
 {
 #if 1
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 216ab730e7..c8f9f9bd8d 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -634,7 +634,6 @@ public:
 	void 			processAvatarAppearance(LLMessageSystem* mesgsys);
 	void 			hideSkirt();
 	void			startAppearanceAnimation();
-	/*virtual*/ void bodySizeChanged();
 	
 	//--------------------------------------------------------------------
 	// Appearance morphing
@@ -651,6 +650,7 @@ public:
 	// appearance mechanism.
 	// SUNSHINE CLEANUP - always true, remove?
 	BOOL				isUsingServerBakes() const;
+	// SUNSHINE CLEANUP - always true, remove?
 	void 				setIsUsingServerBakes(BOOL newval);
 
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 4f2af2c8ee..4c568c9bed 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1101,13 +1101,6 @@ void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_re
 			}
 		}
 	}
-	
-	// Physics type has no associated baked textures, but change of params needs to be sent to
-	// other avatars.
-	if (type == LLWearableType::WT_PHYSICS)
-	  {
-	    gAgent.sendAgentSetAppearance();
-	  }
 }
 
 //-----------------------------------------------------------------------------
@@ -2728,8 +2721,6 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 	// RN: throttle uploads
 	if (!hasPendingBakedUploads())
 	{
-		gAgent.sendAgentSetAppearance();
-
 		if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
 		{
 			LLSD args;
-- 
cgit v1.2.3


From 48bc05e93ffbd29b3e49c288577bda1712a88392 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 19 Sep 2013 16:14:59 -0400
Subject: SH-3455 WIP - removing bake upload code

---
 indra/newview/llagent.cpp                 |  18 --
 indra/newview/llagent.h                   |  20 --
 indra/newview/llagentwearables.cpp        |  68 +----
 indra/newview/llagentwearables.h          |   1 -
 indra/newview/llassetuploadresponders.cpp |  51 ----
 indra/newview/llassetuploadresponders.h   |  22 --
 indra/newview/lltextureview.cpp           |  10 +-
 indra/newview/llviewertexlayer.cpp        | 403 +-----------------------------
 indra/newview/llviewertexlayer.h          |  64 -----
 indra/newview/llvoavatarself.cpp          | 153 +++---------
 indra/newview/llvoavatarself.h            |   7 +-
 11 files changed, 43 insertions(+), 774 deletions(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 845ef6e9a5..18ff2d7c02 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4325,24 +4325,6 @@ void LLAgent::renderAutoPilotTarget()
 
 /********************************************************************************/
 
-LLAgentQueryManager gAgentQueryManager;
-
-LLAgentQueryManager::LLAgentQueryManager() :
-	mWearablesCacheQueryID(0),
-	mNumPendingQueries(0),
-	mUpdateSerialNum(0)
-{
-	for (U32 i = 0; i < BAKED_NUM_INDICES; i++)
-	{
-		// SUNSHINE CLEANUP
-		mActiveCacheQueries[i] = 0;
-	}
-}
-
-LLAgentQueryManager::~LLAgentQueryManager()
-{
-}
-
 //-----------------------------------------------------------------------------
 // LLTeleportRequest
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index eca9a3f229..a4385d33cb 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -885,24 +885,4 @@ inline bool operator==(const LLGroupData &a, const LLGroupData &b)
 	return (a.mID == b.mID);
 }
 
-class LLAgentQueryManager
-{
-	friend class LLAgent;
-	friend class LLAgentWearables;
-	
-public:
-	LLAgentQueryManager();
-	virtual ~LLAgentQueryManager();
-	
-	BOOL 			hasNoPendingQueries() const 	{ return getNumPendingQueries() == 0; }
-	S32 			getNumPendingQueries() const 	{ return mNumPendingQueries; }
-private:
-	S32				mNumPendingQueries;
-	S32				mWearablesCacheQueryID;
-	U32				mUpdateSerialNum;
-	S32		    	mActiveCacheQueries[LLAvatarAppearanceDefines::BAKED_NUM_INDICES];
-};
-
-extern LLAgentQueryManager gAgentQueryManager;
-
 #endif
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 96bfc43fb8..bffdb0a49b 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -807,7 +807,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
 
 	if (isAgentAvatarValid() && (agent_id == gAgentAvatarp->getID()))
 	{
-		gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum);
+		U32 unused_update_serial_num;
+		gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, unused_update_serial_num);
 		
 		const S32 NUM_BODY_PARTS = 4;
 		S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
@@ -1199,7 +1200,6 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 		for (S32 i=max_entry; i>=0; i--)
 		{
 			LLViewerWearable* old_wearable = getViewerWearable(type,i);
-			//queryWearableCache(); // moved below
 			if (old_wearable)
 			{
 				popWearable(old_wearable);
@@ -1211,7 +1211,6 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 	else
 	{
 		LLViewerWearable* old_wearable = getViewerWearable(type, index);
-		//queryWearableCache(); // moved below
 
 		if (old_wearable)
 		{
@@ -1220,8 +1219,6 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 		}
 	}
 
-	queryWearableCache();
-
 	// Update the server
 	updateServer();
 	gInventory.notifyObservers();
@@ -1357,7 +1354,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	mWearablesLoaded = TRUE; 
 	checkWearablesLoaded();
 	notifyLoadingFinished();
-	queryWearableCache();
 	updateServer();
 
 	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
@@ -1481,71 +1477,11 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
 	}
 
 	//llinfos << "LLVOAvatar::setWearableItem()" << llendl;
-	queryWearableCache();
 	//new_wearable->writeToAvatar(TRUE);
 
 	updateServer();
 }
 
-// SUNSHINE CLEANUP dead?
-void LLAgentWearables::queryWearableCache()
-{
-	if (!areWearablesLoaded() || (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()))
-	{
-		return;
-	}
-	gAgentAvatarp->setIsUsingServerBakes(false);
-
-	// Look up affected baked textures.
-	// If they exist:
-	//		disallow updates for affected layersets (until dataserver responds with cache request.)
-	//		If cache miss, turn updates back on and invalidate composite.
-	//		If cache hit, modify baked texture entries.
-	//
-	// Cache requests contain list of hashes for each baked texture entry.
-	// Response is list of valid baked texture assets. (same message)
-
-	gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture);
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	gMessageSystem->addS32Fast(_PREHASH_SerialNum, gAgentQueryManager.mWearablesCacheQueryID);
-
-	S32 num_queries = 0;
-	for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
-	{
-		LLUUID hash_id = computeBakedTextureHash((EBakedTextureIndex) baked_index);
-		if (hash_id.notNull())
-		{
-			num_queries++;
-			// *NOTE: make sure at least one request gets packed
-
-			ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
-
-			//llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl;
-			gMessageSystem->nextBlockFast(_PREHASH_WearableData);
-			gMessageSystem->addUUIDFast(_PREHASH_ID, hash_id);
-			gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)te_index);
-		}
-
-		gAgentQueryManager.mActiveCacheQueries[baked_index] = gAgentQueryManager.mWearablesCacheQueryID;
-	}
-	//VWR-22113: gAgent.getRegion() can return null if invalid, seen here on logout
-	if(gAgent.getRegion())
-	{
-		if (isAgentAvatarValid())
-		{
-			selfStartPhase("fetch_texture_cache_entries");
-			gAgentAvatarp->outputRezTiming("Fetching textures from cache");
-		}
-
-		LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL;
-		gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
-		gAgentQueryManager.mNumPendingQueries++;
-		gAgentQueryManager.mWearablesCacheQueryID++;
-	}
-}
-
 // virtual
 void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const
 {
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index af4b8cd2dd..0583c76dc4 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -166,7 +166,6 @@ protected:
 	// SUNSHINE CLEANUP dead
 	void			sendAgentWearablesUpdate();
 	void			sendAgentWearablesRequest();
-	void			queryWearableCache();
 	void 			updateServer();
 	static void		onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata);
 
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index ea511b18e2..457ee6916d 100755
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -450,57 +450,6 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
 	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE);
 }
 
-LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
-												 const LLUUID& vfile_id,
-												 LLAssetType::EType asset_type,
-												 LLBakedUploadData * baked_upload_data) : 
-	LLAssetUploadResponder(post_data, vfile_id, asset_type),
-	mBakedUploadData(baked_upload_data)
-{
-}
-
-LLSendTexLayerResponder::~LLSendTexLayerResponder()
-{
-	// mBakedUploadData is normally deleted by calls to LLViewerTexLayerSetBuffer::onTextureUploadComplete() below
-	if (mBakedUploadData)
-	{	// ...but delete it in the case where uploadComplete() is never called
-		delete mBakedUploadData;
-		mBakedUploadData = NULL;
-	}
-}
-
-
-// Baked texture upload completed
-void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
-{
-	LLUUID item_id = mPostData["item_id"];
-
-	std::string result = content["state"];
-	LLUUID new_id = content["new_asset"];
-
-	llinfos << "result: " << result << " new_id: " << new_id << llendl;
-	if (result == "complete"
-		&& mBakedUploadData != NULL)
-	{	// Invoke 
-		LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE);
-		mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
-	}
-	else
-	{	// Invoke the original callback with an error result
-		LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
-		mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
-	}
-}
-
-void LLSendTexLayerResponder::httpFailure()
-{
-	llwarns << dumpResponse() << llendl;
-	
-	// Invoke the original callback with an error result
-	LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
-	mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
-}
-
 LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
 	const LLSD& post_data,
 	const LLUUID& vfile_id,
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index 7c48f2f06b..7fbebc7481 100755
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -116,28 +116,6 @@ private:
 	Impl* mImpl;
 };
 
-// SUNSHINE CLEANUP no upload bakes, remove class.
-struct LLBakedUploadData;
-class LLSendTexLayerResponder : public LLAssetUploadResponder
-{
-	LOG_CLASS(LLSendTexLayerResponder);
-public:
-	LLSendTexLayerResponder(const LLSD& post_data,
-							const LLUUID& vfile_id,
-							LLAssetType::EType asset_type,
-							LLBakedUploadData * baked_upload_data);
-
-	~LLSendTexLayerResponder();
-
-	virtual void uploadComplete(const LLSD& content);
-
-protected:
-	virtual void httpFailure();
-
-private:
-	LLBakedUploadData * mBakedUploadData;
-};
-
 class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder
 {
 public:
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index e80136b286..dea1c6c1b2 100755
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -431,15 +431,7 @@ void LLAvatarTexBar::draw()
 		if (!layerset_buffer) continue;
 
 		LLColor4 text_color = LLColor4::white;
-		
-		if (layerset_buffer->uploadNeeded())
-		{
-			text_color = LLColor4::red;
-		}
- 		if (layerset_buffer->uploadInProgress())
-		{
-			text_color = LLColor4::magenta;
-		}
+
 		std::string text = layerset_buffer->dumpTextureInfo();
 		LLFontGL::getFontMonospace()->renderUTF8(text, 0, l_offset, v_offset + line_height*line_num,
 												 text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
index c17e85f7a6..67aa105863 100755
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -37,7 +37,6 @@
 #include "llglslshader.h"
 #include "llvoavatarself.h"
 #include "pipeline.h"
-#include "llassetuploadresponders.h"
 #include "llviewercontrol.h"
 
 static const S32 BAKE_UPLOAD_ATTEMPTS = 7;
@@ -46,22 +45,6 @@ static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power o
 // runway consolidate
 extern std::string self_av_string();
 
-
-//-----------------------------------------------------------------------------
-// LLBakedUploadData()
-//-----------------------------------------------------------------------------
-LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
-									 LLViewerTexLayerSet* layerset,
-									 const LLUUID& id,
-									 bool highest_res) :
-	mAvatar(avatar),
-	mTexLayerSet(layerset),
-	mID(id),
-	mStartTime(LLFrameTimer::getTotalTime()),		// Record starting time
-	mIsHighestRes(highest_res)
-{ 
-}
-
 //-----------------------------------------------------------------------------
 // LLViewerTexLayerSetBuffer
 // The composite image that a LLViewerTexLayerSet writes to.  Each LLViewerTexLayerSet has one.
@@ -75,15 +58,10 @@ LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner,
 	// ORDER_LAST => must render these after the hints are created.
 	LLTexLayerSetBuffer(owner),
 	LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), 
-	mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
-	mNeedsUpload(FALSE),
-	mNumLowresUploads(0),
-	mUploadFailCount(0),
 	mNeedsUpdate(TRUE),
 	mNumLowresUpdates(0)
 {
 	LLViewerTexLayerSetBuffer::sGLByteCount += getSize();
-	mNeedsUploadTimer.start();
 	mNeedsUpdateTimer.start();
 }
 
@@ -126,33 +104,6 @@ void LLViewerTexLayerSetBuffer::requestUpdate()
 	restartUpdateTimer();
 	mNeedsUpdate = TRUE;
 	mNumLowresUpdates = 0;
-	// If we're in the middle of uploading a baked texture, we don't care about it any more.
-	// When it's downloaded, ignore it.
-	mUploadID.setNull();
-}
-
-void LLViewerTexLayerSetBuffer::requestUpload()
-{
-	conditionalRestartUploadTimer();
-	mNeedsUpload = TRUE;
-	mNumLowresUploads = 0;
-	mUploadPending = TRUE;
-}
-
-void LLViewerTexLayerSetBuffer::conditionalRestartUploadTimer()
-{
-	// If we requested a new upload but haven't even uploaded
-	// a low res version of our last upload request, then
-	// keep the timer ticking instead of resetting it.
-	if (mNeedsUpload && (mNumLowresUploads == 0))
-	{
-		mNeedsUploadTimer.unpause();
-	}
-	else
-	{
-		mNeedsUploadTimer.reset();
-		mNeedsUploadTimer.start();
-	}
 }
 
 void LLViewerTexLayerSetBuffer::restartUpdateTimer()
@@ -161,25 +112,16 @@ void LLViewerTexLayerSetBuffer::restartUpdateTimer()
 	mNeedsUpdateTimer.start();
 }
 
-void LLViewerTexLayerSetBuffer::cancelUpload()
-{
-	mNeedsUpload = FALSE;
-	mUploadPending = FALSE;
-	mNeedsUploadTimer.pause();
-	mUploadRetryTimer.reset();
-}
-
 // virtual
 BOOL LLViewerTexLayerSetBuffer::needsRender()
 {
 	llassert(mTexLayerSet->getAvatarAppearance() == gAgentAvatarp);
 	if (!isAgentAvatarValid()) return FALSE;
 
-	const BOOL upload_now = mNeedsUpload && isReadyToUpload();
 	const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
 
-	// Don't render if we don't want to (or aren't ready to) upload or update.
-	if (!(update_now || upload_now))
+	// Don't render if we don't want to (or aren't ready to) update.
+	if (!update_now)
 	{
 		return FALSE;
 	}
@@ -190,11 +132,10 @@ BOOL LLViewerTexLayerSetBuffer::needsRender()
 		return FALSE;
 	}
 
-	// Don't render if we are trying to create a shirt texture but aren't wearing a skirt.
+	// Don't render if we are trying to create a skirt texture but aren't wearing a skirt.
 	if (gAgentAvatarp->getBakedTE(getViewerTexLayerSet()) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED && 
 		!gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
 	{
-		cancelUpload();
 		return FALSE;
 	}
 
@@ -222,36 +163,7 @@ void LLViewerTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
 // virtual
 void LLViewerTexLayerSetBuffer::midRenderTexLayerSet(BOOL success)
 {
-	// do we need to upload, and do we have sufficient data to create an uploadable composite?
-	// TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
-	const BOOL upload_now = mNeedsUpload && isReadyToUpload();
 	const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
-
-	if(upload_now)
-	{
-		if (!success)
-		{
-			llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl;
-			mUploadPending = FALSE;
-		}
-		else
-		{
-			LLViewerTexLayerSet* layer_set = getViewerTexLayerSet();
-			if (layer_set->isVisible())
-			{
-				layer_set->getAvatar()->debugBakedTextureUpload(layer_set->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish.
-				doUpload();
-			}
-			else
-			{
-				mUploadPending = FALSE;
-				mNeedsUpload = FALSE;
-				mNeedsUploadTimer.pause();
-				layer_set->getAvatar()->setNewBakedTexture(layer_set->getBakedTexIndex(),IMG_INVISIBLE);
-			}
-		}
-	}
-	
 	if (update_now)
 	{
 		doUpdate();
@@ -267,61 +179,6 @@ BOOL LLViewerTexLayerSetBuffer::isInitialized(void) const
 	return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
 }
 
-BOOL LLViewerTexLayerSetBuffer::uploadPending() const
-{
-	return mUploadPending;
-}
-
-// SUNSHINE CLEANUP no upload
-BOOL LLViewerTexLayerSetBuffer::uploadNeeded() const
-{
-	return mNeedsUpload;
-}
-
-BOOL LLViewerTexLayerSetBuffer::uploadInProgress() const
-{
-	return !mUploadID.isNull();
-}
-
-BOOL LLViewerTexLayerSetBuffer::isReadyToUpload() const
-{
-	if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.
-	if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) return FALSE; // Don't upload if avatar is being edited.
-
-	BOOL ready = FALSE;
-	if (getViewerTexLayerSet()->isLocalTextureDataFinal())
-	{
-		// If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry)
-		if (mUploadFailCount == 0)
-		{
-			ready = TRUE;
-		}
-		else
-		{
-			ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1));
-		}
-	}
-	else
-	{
-		// Upload if we've hit a timeout.  Upload is a pretty expensive process so we need to make sure
-		// we aren't doing uploads too frequently.
-		const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
-		if (texture_timeout != 0)
-		{
-			// The timeout period increases exponentially between every lowres upload in order to prevent
-			// spamming the server with frequent uploads.
-			const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
-
-			// If we hit our timeout and have textures available at even lower resolution, then upload.
-			const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
-			const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable();
-			ready = has_lower_lod && is_upload_textures_timeout;
-		}
-	}
-
-	return ready;
-}
-
 BOOL LLViewerTexLayerSetBuffer::isReadyToUpdate() const
 {
 	// If we requested an update and have the final LOD ready, then update.
@@ -359,159 +216,6 @@ BOOL LLViewerTexLayerSetBuffer::requestUpdateImmediate()
 	return result;
 }
 
-// Create the baked texture, send it out to the server, then wait for it to come
-// back so we can switch to using it.
-void LLViewerTexLayerSetBuffer::doUpload()
-{
-	LLViewerTexLayerSet* layer_set = getViewerTexLayerSet();
-	LL_DEBUGS("Avatar") << "Uploading baked " << layer_set->getBodyRegionName() << llendl;
-	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES);
-
-	// Don't need caches since we're baked now.  (note: we won't *really* be baked 
-	// until this image is sent to the server and the Avatar Appearance message is received.)
-	layer_set->deleteCaches();
-
-	// Get the COLOR information from our texture
-	U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
-	glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
-	stop_glerror();
-
-	// Get the MASK information from our texture
-	LLGLSUIDefault gls_ui;
-	LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 );
-	U8* baked_mask_data = baked_mask_image->getData(); 
-	layer_set->gatherMorphMaskAlpha(baked_mask_data,
-									mOrigin.mX, mOrigin.mY,
-									mFullWidth, mFullHeight);
-
-
-	// Create the baked image from our color and mask information
-	const S32 baked_image_components = 5; // red green blue [bump] clothing
-	LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components );
-	U8* baked_image_data = baked_image->getData();
-	S32 i = 0;
-	for (S32 u=0; u < mFullWidth; u++)
-	{
-		for (S32 v=0; v < mFullHeight; v++)
-		{
-			baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
-			baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
-			baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
-			baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
-			baked_image_data[5*i + 4] = baked_mask_data[i];
-			i++;
-		}
-	}
-	
-	LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
-	const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask)
-	if (compressedImage->encode(baked_image, comment_text))
-	{
-		LLTransactionID tid;
-		tid.generate();
-		const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-		if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(),
-							   gVFS, asset_id, LLAssetType::AT_TEXTURE))
-		{
-			// Read back the file and validate.
-			BOOL valid = FALSE;
-			LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
-			S32 file_size = 0;
-			LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE);
-			file_size = file.getSize();
-			U8* data = integrity_test->allocateData(file_size);
-			file.read(data, file_size);
-			if (data)
-			{
-				valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data'
-			}
-			else
-			{
-				integrity_test->setLastError("Unable to read entire file");
-			}
-			
-			if (valid)
-			{
-				const bool highest_lod = layer_set->isLocalTextureDataFinal();
-				// Baked_upload_data is owned by the responder and deleted after the request completes.
-				LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, 
-																			 layer_set, 
-																			 asset_id,
-																			 highest_lod);
-				// upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
-				mUploadID = asset_id;
-
-				// Upload the image
-				const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
-				if(!url.empty()
-					&& !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method
-					&& (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing.
-				{
-					LLSD body = LLSD::emptyMap();
-					// The responder will call LLViewerTexLayerSetBuffer::onTextureUploadComplete()
-					LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data));
-					llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl;
-				} 
-				else
-				{
-					gAssetStorage->storeAssetData(tid,
-												  LLAssetType::AT_TEXTURE,
-												  LLViewerTexLayerSetBuffer::onTextureUploadComplete,
-												  baked_upload_data,
-												  TRUE,		// temp_file
-												  TRUE,		// is_priority
-												  TRUE);	// store_local
-					llinfos << "Baked texture upload via Asset Store." <<  llendl;
-				}
-
-				if (highest_lod)
-				{
-					// Sending the final LOD for the baked texture.  All done, pause 
-					// the upload timer so we know how long it took.
-					mNeedsUpload = FALSE;
-					mNeedsUploadTimer.pause();
-				}
-				else
-				{
-					// Sending a lower level LOD for the baked texture.  Restart the upload timer.
-					mNumLowresUploads++;
-					mNeedsUploadTimer.unpause();
-					mNeedsUploadTimer.reset();
-				}
-
-				// Print out notification that we uploaded this texture.
-				if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
-				{
-					const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
-					LLSD args;
-					args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32());
-					args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32());
-					args["BODYREGION"] = layer_set->getBodyRegionName();
-					args["RESOLUTION"] = lod_str;
-					LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args);
-					LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
-				}
-			}
-			else
-			{
-				// The read back and validate operation failed.  Remove the uploaded file.
-				mUploadPending = FALSE;
-				LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
-				file.remove();
-				llinfos << "Unable to create baked upload file (reason: corrupted)." << llendl;
-			}
-		}
-	}
-	else
-	{
-		// The VFS write file operation failed.
-		mUploadPending = FALSE;
-		llinfos << "Unable to create baked upload file (reason: failed to write file)" << llendl;
-	}
-
-	delete [] baked_color_data;
-}
-
 // Mostly bookkeeping; don't need to actually "do" anything since
 // render() will actually do the update.
 void LLViewerTexLayerSetBuffer::doUpdate()
@@ -548,82 +252,6 @@ void LLViewerTexLayerSetBuffer::doUpdate()
 	}
 }
 
-// static
-void LLViewerTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
-												  void* userdata,
-												  S32 result,
-												  LLExtStat ext_status) // StoreAssetData callback (not fixed)
-{
-	LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
-
-	if (isAgentAvatarValid() &&
-		!gAgentAvatarp->isDead() &&
-		(baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures.
-		(baked_upload_data->mTexLayerSet->hasComposite()))
-	{
-		LLViewerTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getViewerComposite();
-		S32 failures = layerset_buffer->mUploadFailCount;
-		layerset_buffer->mUploadFailCount = 0;
-
-		if (layerset_buffer->mUploadID.isNull())
-		{
-			// The upload got canceled, we should be in the
-			// process of baking a new texture so request an
-			// upload with the new data
-
-			// BAP: does this really belong in this callback, as
-			// opposed to where the cancellation takes place?
-			// suspect this does nothing.
-			layerset_buffer->requestUpload();
-		}
-		else if (baked_upload_data->mID == layerset_buffer->mUploadID)
-		{
-			// This is the upload we're currently waiting for.
-			layerset_buffer->mUploadID.setNull();
-			const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName());
-			const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res ";
-			if (result >= 0)
-			{
-				layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later
-				LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->getViewerTexLayerSet());
-				// Update baked texture info with the new UUID
-				U64 now = LLFrameTimer::getTotalTime();		// Record starting time
-				llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
-				gAgentAvatarp->setNewBakedTexture(baked_te, uuid);
-			}
-			else
-			{	
-				++failures;
-				S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes
-				llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl;
-				if (failures < max_attempts)
-				{
-					layerset_buffer->mUploadFailCount = failures;
-					layerset_buffer->mUploadRetryTimer.start();
-					layerset_buffer->requestUpload();
-				}
-			}
-		}
-		else
-		{
-			llinfos << "Received baked texture out of date, ignored." << llendl;
-		}
-
-		gAgentAvatarp->dirtyMesh();
-	}
-	else
-	{
-		// Baked texture failed to upload (in which case since we
-		// didn't set the new baked texture, it means that they'll try
-		// and rebake it at some point in the future (after login?)),
-		// or this response to upload is out of date, in which case a
-		// current response should be on the way or already processed.
-		llwarns << "Baked upload failed" << llendl;
-	}
-
-	delete baked_upload_data;
-}
-
 //-----------------------------------------------------------------------------
 // LLViewerTexLayerSet
 // An ordered set of texture layers that get composited into a single texture.
@@ -665,20 +293,6 @@ void LLViewerTexLayerSet::requestUpdate()
 	}
 }
 
-void LLViewerTexLayerSet::requestUpload()
-{
-	createComposite();
-	getViewerComposite()->requestUpload();
-}
-
-void LLViewerTexLayerSet::cancelUpload()
-{
-	if(mComposite)
-	{
-		getViewerComposite()->cancelUpload();
-	}
-}
-
 void LLViewerTexLayerSet::updateComposite()
 {
 	createComposite();
@@ -727,18 +341,17 @@ const LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() const
 }
 
 
+// SUNSHINE CLEANUP - this used to have a bunch of upload related stuff, doesn't really serve a purpose now.
 const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const
 {
 	if (!isAgentAvatarValid()) return "";
 
-	const BOOL is_high_res = !mNeedsUpload;
-	const U32 num_low_res = mNumLowresUploads;
-	const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32();
+	const BOOL is_high_res = TRUE; 
+	const U32 num_low_res = 0;
+	const U32 upload_time = 0;
 	const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet());
 
-	std::string status 				= "CREATING ";
-	if (!uploadNeeded()) status 	= "DONE     ";
-	if (uploadInProgress()) status 	= "UPLOADING";
+	std::string status = "DONE     ";
 
 	std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
 								status.c_str(),
diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h
index aa4bad3422..027ae255ec 100755
--- a/indra/newview/llviewertexlayer.h
+++ b/indra/newview/llviewertexlayer.h
@@ -47,8 +47,6 @@ public:
 	virtual ~LLViewerTexLayerSet();
 
 	/*virtual*/void				requestUpdate();
-	void						requestUpload();
-	void						cancelUpload();
 	BOOL						isLocalTextureDataAvailable() const;
 	BOOL						isLocalTextureDataFinal() const;
 	void						updateComposite();
@@ -115,47 +113,6 @@ protected:
 	virtual void			postRender(BOOL success) { postRenderTexLayerSet(success); }
 	virtual BOOL			render() { return renderTexLayerSet(); }
 	
-	//--------------------------------------------------------------------
-	// Uploads
-	//--------------------------------------------------------------------
-public:
-	// SUNSHINE CLEANUP no upload
-	void					requestUpload();
-	// SUNSHINE CLEANUP no upload
-	void					cancelUpload();
-	// SUNSHINE CLEANUP no upload
-	BOOL					uploadNeeded() const; 			// We need to upload a new texture
-	// SUNSHINE CLEANUP no upload
-	BOOL					uploadInProgress() const; 		// We have started uploading a new texture and are awaiting the result
-	// SUNSHINE CLEANUP no upload
-	BOOL					uploadPending() const; 			// We are expecting a new texture to be uploaded at some point
-	// SUNSHINE CLEANUP no upload
-	static void				onTextureUploadComplete(const LLUUID& uuid,
-													void* userdata,
-													S32 result, LLExtStat ext_status);
-protected:
-	// SUNSHINE CLEANUP no upload
-	BOOL					isReadyToUpload() const;
-	// SUNSHINE CLEANUP no upload
-	void					doUpload(); 					// Does a read back and upload.
-	// SUNSHINE CLEANUP no upload
-	void					conditionalRestartUploadTimer();
-private:
-	// SUNSHINE CLEANUP no upload
-	BOOL					mNeedsUpload; 					// Whether we need to send our baked textures to the server
-	// SUNSHINE CLEANUP no upload
-	U32						mNumLowresUploads; 				// Number of times we've sent a lowres version of our baked textures to the server
-	// SUNSHINE CLEANUP no upload
-	BOOL					mUploadPending; 				// Whether we have received back the new baked textures
-	// SUNSHINE CLEANUP no upload
-	LLUUID					mUploadID; 						// The current upload process (null if none).
-	// SUNSHINE CLEANUP no upload
-	LLFrameTimer    		mNeedsUploadTimer; 				// Tracks time since upload was requested and performed.
-	// SUNSHINE CLEANUP no upload
-	S32						mUploadFailCount;				// Number of consecutive upload failures
-	// SUNSHINE CLEANUP no upload
-	LLFrameTimer    		mUploadRetryTimer; 				// Tracks time since last upload failure.
-
 	//--------------------------------------------------------------------
 	// Updates
 	//--------------------------------------------------------------------
@@ -172,26 +129,5 @@ private:
 	LLFrameTimer    		mNeedsUpdateTimer; 				// Tracks time since update was requested and performed.
 };
 
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// LLBakedUploadData
-//
-// Used by LLTexLayerSetBuffer for a callback.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// SUNSHINE CLEANUP no upload
-struct LLBakedUploadData
-{
-	LLBakedUploadData(const LLVOAvatarSelf* avatar,
-					  LLViewerTexLayerSet* layerset, 
-					  const LLUUID& id,
-					  bool highest_res);
-	~LLBakedUploadData() {}
-	const LLUUID				mID;
-	const LLVOAvatarSelf*		mAvatar; // note: backlink only; don't LLPointer 
-	LLViewerTexLayerSet*		mTexLayerSet;
-   	const U64					mStartTime;	// for measuring baked texture upload time
-   	const bool					mIsHighestRes; // whether this is a "final" bake, or intermediate low res
-};
-
 #endif  // LL_VIEWER_TEXLAYER_H
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 4c568c9bed..4cea3d3f58 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -673,7 +673,6 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
 	return LLVOAvatar::getJoint(name);
 }
 // virtual
-// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight)
 {
 	if (!which_param)
@@ -685,7 +684,6 @@ BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32
 }
 
 // virtual
-// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight)
 {
 	if (!param_name)
@@ -697,14 +695,12 @@ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight)
 }
 
 // virtual
-// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight)
 {
 	LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
 	return setParamWeight(param,weight);
 }
 
-// SUNSHINE CLEANUP no upload_bake
 BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight)
 {
 	if (!param)
@@ -893,10 +889,6 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
 			invalidateComposite(layerset);
 		}
 		updateMeshTextures();
-		if (getRegion() && !getRegion()->getCentralBakeVersion())
-		{
-			requestLayerSetUploads();
-		}
 	}
 }
 
@@ -1512,15 +1504,6 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const
 	return TRUE;
 }
 
-BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const
-{
-	const LLViewerTexLayerSet *layerset = getLayerSet(index);
-	if (!layerset) return FALSE;
-	const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite();
-	if (!layerset_buffer) return FALSE;
-	return !layerset_buffer->uploadNeeded();
-}
-
 BOOL LLVOAvatarSelf::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const
 {
 	LLUUID id;
@@ -1578,49 +1561,11 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex t
 	return isTextureVisible(type,index);
 }
 
-
-//-----------------------------------------------------------------------------
-// requestLayerSetUploads()
-//-----------------------------------------------------------------------------
-void LLVOAvatarSelf::requestLayerSetUploads()
-{
-	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-	{
-		requestLayerSetUpload((EBakedTextureIndex)i);
-	}
-}
-
-void LLVOAvatarSelf::requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i)
-{
-	ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex;
-	const BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index));
-	LLViewerTexLayerSet *layerset = getLayerSet(i);
-	if (!layer_baked && layerset)
-	{
-		layerset->requestUpload();
-	}
-}
-
 bool LLVOAvatarSelf::areTexturesCurrent() const
 {
-	return !hasPendingBakedUploads() && gAgentWearables.areWearablesLoaded();
-}
-
-// virtual
-bool LLVOAvatarSelf::hasPendingBakedUploads() const
-{
-	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-	{
-		LLViewerTexLayerSet* layerset = getTexLayerSet(i);
-		if (layerset && layerset->getViewerComposite() && layerset->getViewerComposite()->uploadPending())
-		{
-			return true;
-		}
-	}
-	return false;
+	return gAgentWearables.areWearablesLoaded();
 }
 
-// SUNSHINE CLEANUP no upload_bake
 void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset)
 {
 	LLViewerTexLayerSet *layer_set = dynamic_cast<LLViewerTexLayerSet*>(layerset);
@@ -2694,7 +2639,9 @@ void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTexture
 void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 {
 	// SUNSHINE CLEANUP
+	// If we reinstate processUpdateMessage(), this needs to be updated for server-bake textures.
 	llassert(false);
+
 	// Baked textures live on other sims.
 	LLHost target_host = getObjectHost();	
 	setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) );
@@ -2719,40 +2666,37 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 	
 	//	dumpAvatarTEs( "setNewBakedTexture() send" );
 	// RN: throttle uploads
-	if (!hasPendingBakedUploads())
-	{
-		if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
+	if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
+	{
+		LLSD args;
+		args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+		args["TIME"] = llformat("%d",(U32)mDebugSelfLoadTimer.getElapsedTimeF32());
+		if (isAllLocalTextureDataFinal())
+		{
+			LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args);
+			LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
+								<< "sec ]"
+								<< avString() 
+								<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
+								<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
+								<< " Notification " << "AvatarRezSelfBakedDoneNotification"
+								<< llendl;
+		}
+		else
 		{
-			LLSD args;
-			args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
-			args["TIME"] = llformat("%d",(U32)mDebugSelfLoadTimer.getElapsedTimeF32());
-			if (isAllLocalTextureDataFinal())
-			{
-				LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args);
-				LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
-						<< "sec ]"
-						<< avString() 
-						<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
-						<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
-						<< " Notification " << "AvatarRezSelfBakedDoneNotification"
-						<< llendl;
-			}
-			else
-			{
-				args["STATUS"] = debugDumpAllLocalTextureDataInfo();
-				LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args);
-				LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
-						<< "sec ]"
-						<< avString() 
-						<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
-						<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
-						<< " Notification " << "AvatarRezSelfBakedUpdateNotification"
-						<< llendl;
-			}
+			args["STATUS"] = debugDumpAllLocalTextureDataInfo();
+			LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args);
+			LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
+								<< "sec ]"
+								<< avString() 
+								<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
+								<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
+								<< " Notification " << "AvatarRezSelfBakedUpdateNotification"
+								<< llendl;
 		}
-
-		outputRezDiagnostics();
 	}
+
+	outputRezDiagnostics();
 }
 
 // FIXME: This is not called consistently. Something may be broken.
@@ -2830,40 +2774,6 @@ void LLVOAvatarSelf::reportAvatarRezTime() const
 	// TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow.
 }
 
-//-----------------------------------------------------------------------------
-// setCachedBakedTexture()
-// A baked texture id was received from a cache query, make it active
-//-----------------------------------------------------------------------------
-void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid )
-{
-	setTETexture( te, uuid );
-
-	/* switch(te)
-		case TEX_HEAD_BAKED:
-			if( mHeadLayerSet )
-				mHeadLayerSet->cancelUpload(); */
-	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-	{
-		LLViewerTexLayerSet *layerset = getTexLayerSet(i);
-		if ( mBakedTextureDatas[i].mTextureIndex == te && layerset)
-		{
-			if (mInitialBakeIDs[i] != LLUUID::null)
-			{
-				if (mInitialBakeIDs[i] == uuid)
-				{
-					llinfos << "baked texture correctly loaded at login! " << i << llendl;
-				}
-				else
-				{
-					llwarns << "baked texture does not match id loaded at login!" << i << llendl;
-				}
-				mInitialBakeIDs[i] = LLUUID::null;
-			}
-			layerset->cancelUpload();
-		}
-	}
-}
-
 // static
 void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
 {
@@ -2926,7 +2836,6 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 			if (slam_for_debug)
 			{
 				layer_set->setUpdatesEnabled(TRUE);
-				layer_set->cancelUpload();
 			}
 
 			invalidateComposite(layer_set);
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 32d9012862..6ed3640e9e 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -197,12 +197,10 @@ public:
 	//--------------------------------------------------------------------
 public:
 	// SUNSHINE CLEANUP
-	/*virtual*/ bool	hasPendingBakedUploads() const;
 	S32					getLocalDiscardLevel(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const;
 	bool				areTexturesCurrent() const;
 	BOOL				isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const;
 	BOOL				isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const;
-	BOOL				isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const;
 	// If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index
 	/*virtual*/ BOOL    isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const;
 	/*virtual*/ BOOL	isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const;
@@ -237,9 +235,9 @@ private:
 	//--------------------------------------------------------------------
 public:
 	LLAvatarAppearanceDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const;
+	// SUNSHINE CLEANUP - dead?
 	void				setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid);
 	void				setNewBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid);
-	void				setCachedBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid);
 	void				forceBakeAllTextures(bool slam_for_debug = false);
 	static void			processRebakeAvatarTextures(LLMessageSystem* msg, void**);
 protected:
@@ -249,9 +247,6 @@ protected:
 	// Layers
 	//--------------------------------------------------------------------
 public:
-	// SUNSHINE CLEANUP
-	void 				requestLayerSetUploads();
-	void				requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i);
 	void				requestLayerSetUpdate(LLAvatarAppearanceDefines::ETextureIndex i);
 	LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
 	LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::ETextureIndex index) const;
-- 
cgit v1.2.3


From 9a8afee83f40e7239d98e6cc8cf3297408f51920 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 19 Sep 2013 17:52:58 -0400
Subject: SH-3455 WIP - removing bake upload code

---
 indra/newview/llagentwearables.cpp    |  5 ++---
 indra/newview/llappearancemgr.cpp     |  2 +-
 indra/newview/lllocalbitmaps.cpp      |  2 +-
 indra/newview/llpaneleditwearable.cpp | 10 +++++-----
 indra/newview/llviewerwearable.cpp    |  2 +-
 indra/newview/llvoavatar.cpp          |  3 ---
 indra/newview/llvoavatar.h            |  3 +--
 indra/newview/llvoavatarself.cpp      | 15 +--------------
 indra/newview/llvoavatarself.h        |  4 +---
 9 files changed, 13 insertions(+), 33 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index bffdb0a49b..2d3823a6e2 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -441,7 +441,7 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
 			return;
 		}
 
-		gAgentAvatarp->wearableUpdated( type, TRUE );
+		gAgentAvatarp->wearableUpdated(type);
 
 		if (send_update)
 		{
@@ -716,8 +716,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
 {
 	if (isAgentAvatarValid())
 	{
-		const BOOL upload_result = removed;
-		gAgentAvatarp->wearableUpdated(wearable->getType(), upload_result);
+		gAgentAvatarp->wearableUpdated(wearable->getType());
 	}
 
 	LLWearableData::wearableUpdated(wearable, removed);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 359d5aaa5c..0bf2527195 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3692,7 +3692,7 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b
 	bool result = false;
 	if (result = gAgentWearables.moveWearable(item, closer_to_body))
 	{
-		gAgentAvatarp->wearableUpdated(item->getWearableType(), FALSE);
+		gAgentAvatarp->wearableUpdated(item->getWearableType());
 	}
 
 	setOutfitDirty(true);
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 2d9385390b..88fe389c55 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -540,7 +540,7 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp
 					{
 						U32 index = gAgentWearables.getWearableIndex(wearable);
 						gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
-						gAgentAvatarp->wearableUpdated(type, FALSE);
+						gAgentAvatarp->wearableUpdated(type);
 
 						/* telling the manager to rebake once update cycle is fully done */
 						LLLocalBitmapMgr::setNeedsRebake();
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 022fd6c062..0be5c19387 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -982,7 +982,7 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
                                 U32 index = gAgentWearables.getWearableIndex(getWearable());
                                 gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
                                 LLVisualParamHint::requestHintUpdates();
-                                gAgentAvatarp->wearableUpdated(type, FALSE);
+                                gAgentAvatarp->wearableUpdated(type);
                         }
                 }
                 else
@@ -1008,7 +1008,7 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl)
                         {
                                 getWearable()->setClothesColor(entry->mTextureIndex, new_color);
                                 LLVisualParamHint::requestHintUpdates();
-                                gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+                                gAgentAvatarp->wearableUpdated(getWearable()->getType());
                         }
                 }
                 else
@@ -1122,7 +1122,7 @@ void LLPanelEditWearable::revertChanges()
         mNameEditor->setText(mWearableItem->getName());
         updatePanelPickerControls(mWearablePtr->getType());
         updateTypeSpecificControls(mWearablePtr->getType());
-        gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE);
+        gAgentAvatarp->wearableUpdated(mWearablePtr->getType());
 }
 
 void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BOOL disable_camera_switch)
@@ -1584,7 +1584,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
                 LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
                 U32 index = gAgentWearables.getWearableIndex(getWearable());
                 gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
-                gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+                gAgentAvatarp->wearableUpdated(getWearable()->getType());
         }
         else
         {
@@ -1601,7 +1601,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
 
                 U32 index = gAgentWearables.getWearableIndex(getWearable());
                 gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
-                gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+                gAgentAvatarp->wearableUpdated(getWearable()->getType());
         }
 
         updatePanelPickerControls(getWearable()->getType());
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index d56a7b5dc5..e7fb6aec98 100755
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -397,7 +397,7 @@ void LLViewerWearable::removeFromAvatar( LLWearableType::EType type)
 	}
 
 	gAgentAvatarp->updateVisualParams();
-	gAgentAvatarp->wearableUpdated(type, FALSE);
+	gAgentAvatarp->wearableUpdated(type);
 }
 
 // Does not copy mAssetID.
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 987beedd9e..63fdff2320 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5344,7 +5344,6 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
 //-----------------------------------------------------------------------------
 // updateSexDependentLayerSets()
 //-----------------------------------------------------------------------------
-// SUNSHINE CLEANUP no upload_bake
 void LLVOAvatar::updateSexDependentLayerSets()
 {
 	invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet);
@@ -5829,7 +5828,6 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const
 
 
 // virtual
-// SUNSHINE CLEANUP no upload_result, no-op
 void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset)
 {
 }
@@ -5839,7 +5837,6 @@ void LLVOAvatar::invalidateAll()
 }
 
 // virtual
-// SUNSHINE CLEANUP no upload_bake
 void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
 {
 	if (global_color == mTexSkinColor)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index c8f9f9bd8d..a4b5db3034 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -402,7 +402,6 @@ public:
 	// Global colors
 	//--------------------------------------------------------------------
 public:
-		// SUNSHINE CLEANUP no upload
 	/*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color);
 
 	//--------------------------------------------------------------------
@@ -563,7 +562,6 @@ protected:
 	// Composites
 	//--------------------------------------------------------------------
 public:
-		// SUNSHINE CLEANUP no upload
 	virtual void	invalidateComposite(LLTexLayerSet* layerset);
 	virtual void	invalidateAll();
 	virtual void	setCompositeUpdatesEnabled(bool b) {}
@@ -666,6 +664,7 @@ private:
 	F32				mLastAppearanceBlendTime;
 	BOOL			mIsEditingAppearance; // flag for if we're actively in appearance editing mode
 	BOOL			mUseLocalAppearance; // flag for if we're using a local composite
+	// SUNSHINE CLEANUP - always true, remove?
 	BOOL			mUseServerBakes; // flag for if baked textures should be fetched from baking service (false if they're temporary uploads)
 
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 4cea3d3f58..17e6f4e53e 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1063,8 +1063,7 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
 // forces an update to any baked textures relevant to type.
 // will force an upload of the resulting bake if the second parameter is TRUE
 //-----------------------------------------------------------------------------
-// SUNSHINE CLEANUP no upload_result
-void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_result )
+void LLVOAvatarSelf::wearableUpdated(LLWearableType::EType type)
 {
 	for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin();
 		 baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end();
@@ -1577,18 +1576,6 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset)
 
 	layer_set->requestUpdate();
 	layer_set->invalidateMorphMasks();
-
-#if 0 // SUNSHINE CLEANUP
-	if( upload_result  && (getRegion() && !getRegion()->getCentralBakeVersion()))
-	{
-		llassert(isSelf());
-
-		ETextureIndex baked_te = getBakedTE( layer_set );
-		setTEImage( baked_te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR) );
-		layer_set->requestUpload();
-		updateMeshTextures();
-	}
-#endif
 }
 
 void LLVOAvatarSelf::invalidateAll()
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 6ed3640e9e..1f0fdd101a 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -196,7 +196,6 @@ public:
 	// Loading status
 	//--------------------------------------------------------------------
 public:
-	// SUNSHINE CLEANUP
 	S32					getLocalDiscardLevel(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const;
 	bool				areTexturesCurrent() const;
 	BOOL				isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const;
@@ -256,7 +255,6 @@ public:
 	// Composites
 	//--------------------------------------------------------------------
 public:
-		// SUNSHINE CLEANUP no upload
 	/* virtual */ void	invalidateComposite(LLTexLayerSet* layerset);
 	/* virtual */ void	invalidateAll();
 	/* virtual */ void	setCompositeUpdatesEnabled(bool b); // only works for self
@@ -300,7 +298,7 @@ protected:
  **/
 
 public:
-	void				wearableUpdated(LLWearableType::EType type, BOOL upload_result);
+	void				wearableUpdated(LLWearableType::EType type);
 protected:
 	U32 getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const;
 
-- 
cgit v1.2.3


From 7e7965af19960c613b1b4d22806682587a2cdd82 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 20 Sep 2013 15:54:26 -0400
Subject: SH-3943 FIX beard morph masks applied inconsistently on login to
 server bake region

Looks like we were caching bad morph masks that were generated on login. Adjusting
algorithms to always replace the cache when we have invalidated the other channels
of the baked texture.
---
 indra/llappearance/lltexlayer.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index f951a982e5..59765b3833 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1550,10 +1550,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
 		}
 
 		U32 cache_index = alpha_mask_crc.getCRC();
-		U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL);
-		if (!alpha_data)
+		U8* alpha_data = NULL; 
+                // We believe we need to generate morph masks, do not assume that the cached version is accurate.
+                // We can get bad morph masks during login, on minimize, and occasional gl errors.
+                // We should only be doing this when we believe something has changed with respect to the user's appearance.
 		{
-			// clear out a slot if we have filled our cache
+                       LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << llendl;
+                        // clear out a slot if we have filled our cache
 			S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
 			while ((S32)mAlphaCache.size() >= max_cache_entries)
 			{
-- 
cgit v1.2.3


From a91b7353b67d3076c87b41097335848364906f7b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 23 Sep 2013 14:54:44 -0400
Subject: SH-3455 WIP - post-SSA cleanup

---
 indra/newview/llagentwearables.cpp      |  7 ++-----
 indra/newview/llagentwearables.h        |  8 ++------
 indra/newview/llagentwearablesfetch.cpp |  3 +++
 indra/newview/llvoavatarself.cpp        | 21 +--------------------
 4 files changed, 8 insertions(+), 31 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 2d3823a6e2..e8d5f9bee5 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -194,11 +194,6 @@ LLAgentWearables::createStandardWearablesAllDoneCallback::~createStandardWearabl
 	gAgentWearables.createStandardWearablesAllDone();
 }
 
-LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback()
-{
-	gAgentWearables.sendAgentWearablesUpdate();
-}
-
 /**
  * @brief Construct a callback for dealing with the wearables.
  *
@@ -776,6 +771,8 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
 	return getWearableFromItemID(item_id) != NULL;
 }
 
+// SUNSHINE CLEANUP ?
+
 // MULTI-WEARABLE: DEPRECATED (see backwards compatibility)
 // static
 // ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 0583c76dc4..81bfef0f8e 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -165,7 +165,9 @@ protected:
 	/*virtual*/ void	invalidateBakedTextureHash(LLMD5& hash) const;
 	// SUNSHINE CLEANUP dead
 	void			sendAgentWearablesUpdate();
+	// SUNSHINE CLEANUP remove?
 	void			sendAgentWearablesRequest();
+	// SUNSHINE CLEANUP dead
 	void 			updateServer();
 	static void		onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata);
 
@@ -244,12 +246,6 @@ private:
 	protected:
 		~createStandardWearablesAllDoneCallback();
 	};
-	// SUNSHINE CLEANUP - should be dead if sendAgentWearablesUpdate is no longer needed.
-	class sendAgentWearablesUpdateCallback : public LLRefCount
-	{
-	protected:
-		~sendAgentWearablesUpdateCallback();
-	};
 
 	class AddWearableToAgentInventoryCallback : public LLInventoryCallback
 	{
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index a2a667e660..a10382b830 100755
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -70,6 +70,7 @@ void LLInitialWearablesFetch::add(InitialWearableData &data)
 	mAgentInitialWearables.push_back(data);
 }
 
+// SUNSHINE CLEANUP - should not have to wait for this message to start resolving appearance. Where to hook in instead?
 void LLInitialWearablesFetch::processContents()
 {
 	if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted.
@@ -94,6 +95,7 @@ void LLInitialWearablesFetch::processContents()
 	}
 	else
 	{
+		// SUNSHINE CLEANUP - remove?
 		// if we're constructing the COF from the wearables message, we don't have a proper outfit link
 		LLAppearanceMgr::instance().setOutfitDirty(true);
 		processWearablesMessage();
@@ -135,6 +137,7 @@ public:
 	}
 };
 
+// SUNSHINE CLEANUP - remove dependency on this?
 void LLInitialWearablesFetch::processWearablesMessage()
 {
 	if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 17e6f4e53e..569a2a04cc 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2178,25 +2178,6 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const
 	return text;
 }
 
-
-#if 0
-// Dump avatar metrics data.
-LLSD LLVOAvatarSelf::metricsData()
-{
-	// runway - add region info
-	LLSD result;
-	result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
-	result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32();
-	result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32();
-	result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32();
-	result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32();
-	result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32();
-	result["startup"] = LLStartUp::getPhases().dumpPhases();
-	
-	return result;
-}
-#endif
-
 class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
 {
 	LOG_CLASS(ViewerAppearanceChangeMetricsResponder);
@@ -2332,7 +2313,7 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	std::string viewer_version_short = LLVersionInfo::getShortVersion();
 	std::string viewer_version_build = llformat("%d", LLVersionInfo::getBuild());
 
-	LLSD msg; // = metricsData();
+	LLSD msg;
 	msg["message"] = "ViewerAppearanceChangeMetrics";
 	msg["session_id"] = gAgentSessionID;
 	msg["agent_id"] = gAgentID;
-- 
cgit v1.2.3


From 029642b2bc3a0bc0bec45af5df5d1e0b1b928b91 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 23 Sep 2013 16:48:49 -0400
Subject: SH-3455 WIP - post-SSA cleanup, including removal of mUseServerBakes
 and related methods

---
 indra/llappearance/llavatarappearance.h |  1 -
 indra/llappearance/llwearabledata.cpp   |  7 ---
 indra/newview/llagent.cpp               | 37 ---------------
 indra/newview/llagent.h                 |  1 -
 indra/newview/llagentwearables.cpp      |  5 +-
 indra/newview/llviewertexlayer.cpp      |  6 +--
 indra/newview/llviewerwearable.cpp      | 17 -------
 indra/newview/llvoavatar.cpp            | 74 ++++++-----------------------
 indra/newview/llvoavatar.h              | 10 ----
 indra/newview/llvoavatarself.cpp        | 82 ++-------------------------------
 indra/newview/llvoavatarself.h          |  1 -
 11 files changed, 22 insertions(+), 219 deletions(-)
 mode change 100644 => 100755 indra/llappearance/llwearabledata.cpp

diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 3d99bb0cc7..1e898026c0 100755
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -107,7 +107,6 @@ public:
 public:
 	virtual bool 	isSelf() const { return false; } // True if this avatar is for this viewer's agent
 	virtual BOOL	isValid() const;
-	virtual BOOL	isUsingServerBakes() const = 0;
 	virtual BOOL	isUsingLocalAppearance() const = 0;
 	virtual BOOL	isEditingAppearance() const = 0;
 
diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
old mode 100644
new mode 100755
index 68fdcca782..d70bbf286a
--- a/indra/llappearance/llwearabledata.cpp
+++ b/indra/llappearance/llwearabledata.cpp
@@ -119,13 +119,6 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
 void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
 {
 	wearable->setUpdated();
-	// FIXME DRANO avoid updating params via wearables when rendering server-baked appearance.
-#if 0
-	if (mAvatarAppearance->isUsingServerBakes() && !mAvatarAppearance->isUsingLocalAppearance())
-	{
-		return;
-	}
-#endif
 	if (!removed)
 	{
 		pullCrossWearableValues(wearable->getType());
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 18ff2d7c02..29cf231d45 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -811,30 +811,6 @@ void LLAgent::standUp()
 }
 
 
-// SUNSHINE CLEANUP - are there any cases we still want to handle here?
-void LLAgent::handleServerBakeRegionTransition(const LLUUID& region_id)
-{
-	llinfos << "called" << llendl;
-
-
-	// Old-style appearance entering a server-bake region.
-	if (isAgentAvatarValid() &&
-		!gAgentAvatarp->isUsingServerBakes() &&
-		(mRegionp->getCentralBakeVersion()>0))
-	{
-		llinfos << "update requested due to region transition" << llendl;
-		LLAppearanceMgr::instance().requestServerAppearanceUpdate();
-	}
-	// new-style appearance entering a non-bake region,
-	// need to check for existence of the baking service.
-	else if (isAgentAvatarValid() &&
-			 gAgentAvatarp->isUsingServerBakes() &&
-			 mRegionp->getCentralBakeVersion()==0)
-	{
-		gAgentAvatarp->checkForUnsupportedServerBakeAppearance();
-	}
-}
-
 //-----------------------------------------------------------------------------
 // setRegion()
 //-----------------------------------------------------------------------------
@@ -930,19 +906,6 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
 	{
 		LLEnvManagerNew::instance().onRegionCrossing();
 	}
-
-	// If the newly entered region is using server bakes, and our
-	// current appearance is non-baked, request appearance update from
-	// server.
-	if (mRegionp->capabilitiesReceived())
-	{
-		handleServerBakeRegionTransition(mRegionp->getRegionID());
-	}
-	else
-	{
-		// Need to handle via callback after caps arrive.
-		mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::handleServerBakeRegionTransition,this,_1));
-	}
 }
 
 
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index a4385d33cb..d0a48207b5 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -609,7 +609,6 @@ private:
 
 	void            handleTeleportFinished();
 	void            handleTeleportFailed();
-	void			handleServerBakeRegionTransition(const LLUUID& region_id);
 
 	//--------------------------------------------------------------------
 	// Teleport State
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index e8d5f9bee5..0ec0fa632d 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -771,13 +771,12 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
 	return getWearableFromItemID(item_id) != NULL;
 }
 
-// SUNSHINE CLEANUP ?
-
 // MULTI-WEARABLE: DEPRECATED (see backwards compatibility)
-// static
 // ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume
 // that viewers have a Current Outfit Folder and won't need this message, and thus
 // we can remove/ignore this whole function. EXCEPT gAgentWearables.notifyLoadingStarted
+
+// static
 void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data)
 {
 	// We should only receive this message a single time.  Ignore subsequent AgentWearablesUpdates
diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
index 67aa105863..ad29a6bd8e 100755
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -341,22 +341,20 @@ const LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() const
 }
 
 
-// SUNSHINE CLEANUP - this used to have a bunch of upload related stuff, doesn't really serve a purpose now.
+// SUNSHINE CLEANUP - this used to have a bunch of upload related stuff, doesn't really serve much purpose now.
 const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const
 {
 	if (!isAgentAvatarValid()) return "";
 
 	const BOOL is_high_res = TRUE; 
 	const U32 num_low_res = 0;
-	const U32 upload_time = 0;
 	const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet());
 
 	std::string status = "DONE     ";
 
-	std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
+	std::string text = llformat("[%s] [HiRes:%d LoRes:%d] %s",
 								status.c_str(),
 								is_high_res, num_low_res,
-								upload_time, 
 								local_texture_info.c_str());
 	return text;
 }
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index e7fb6aec98..d6036dbecb 100755
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -322,16 +322,6 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
 
 	if (!viewer_avatar->isValid()) return;
 
-#if 0
-	// FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables.
-	// Ideally would avoid calling this func in the first place.
-	if (viewer_avatar->isUsingServerBakes() &&
-		!viewer_avatar->isUsingLocalAppearance())
-	{
-		return;
-	}
-#endif
-
 	ESex old_sex = avatarp->getSex();
 
 	LLWearable::writeToAvatar(avatarp);
@@ -470,13 +460,6 @@ void LLViewerWearable::setItemID(const LLUUID& item_id)
 
 void LLViewerWearable::revertValues()
 {
-#if 0
-	// DRANO avoid overwrite when not in local appearance
-	if (isAgentAvatarValid() && gAgentAvatarp->isUsingServerBakes() && !gAgentAvatarp->isUsingLocalAppearance())
-	{
-		return;
-	}
-#endif
 	LLWearable::revertValues();
 
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 63fdff2320..34ca8199be 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -707,7 +707,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mLastRezzedStatus(-1),
 	mIsEditingAppearance(FALSE),
 	mUseLocalAppearance(FALSE),
-	mUseServerBakes(FALSE), // FIXME DRANO consider using boost::optional, defaulting to unknown.
 	mLastUpdateRequestCOFVersion(-1),
 	mLastUpdateReceivedCOFVersion(-1)
 {
@@ -3013,7 +3012,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 										  isSelf() ? (all_local_downloaded ? "L" : "l") : "-",
 										  all_baked_downloaded ? "B" : "b",
 										  mUseLocalAppearance, mIsEditingAppearance,
-										  mUseServerBakes, central_bake_version);
+										  1, central_bake_version);
 		std::string origin_string = bakedTextureOriginInfo();
 		debug_line += " [" + origin_string + "]";
 		S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion();
@@ -4388,19 +4387,6 @@ void LLVOAvatar::updateTextures()
 		{
 			const S32 boost_level = getAvatarBakedBoostLevel();
 			imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE);
-			// Spam if this is a baked texture, not set to default image, without valid host info
-			if (isIndexBakedTexture((ETextureIndex)texture_index)
-				&& imagep->getID() != IMG_DEFAULT_AVATAR
-				&& imagep->getID() != IMG_INVISIBLE
-				&& !isUsingServerBakes() 
-				&& !imagep->getTargetHost().isOk())
-			{
-				LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
-										 << imagep->getID() << " for avatar "
-										 << (isSelf() ? "<myself>" : getID().asString()) 
-										 << " on host " << getRegion()->getHost() << llendl;
-			}
-
 			addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );			
 		}
 	}
@@ -4532,22 +4518,19 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid)
 {
 	llassert(isIndexBakedTexture(ETextureIndex(te)));
 	std::string url = "";
-	if (isUsingServerBakes())
+	const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL();
+	if (appearance_service_url.empty())
 	{
-		const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL();
-		if (appearance_service_url.empty())
-		{
-			// Probably a server-side issue if we get here:
-			llwarns << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << llendl;
-			return url;
-		}
+		// Probably a server-side issue if we get here:
+		llwarns << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << llendl;
+		return url;
+	}
 	
-		const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te);
-		if (texture_entry != NULL)
-		{
-			url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString();
-			//llinfos << "baked texture url: " << url << llendl;
-		}
+	const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te);
+	if (texture_entry != NULL)
+	{
+		url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString();
+		//llinfos << "baked texture url: " << url << llendl;
 	}
 	return url;
 }
@@ -6070,7 +6053,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse
 	}
 	record["grid_x"] = LLSD::Integer(grid_x);
 	record["grid_y"] = LLSD::Integer(grid_y);
-	record["is_using_server_bakes"] = ((bool) isUsingServerBakes());
+	record["is_using_server_bakes"] = true;
 	record["is_self"] = isSelf();
 	
 	if (isAgentAvatarValid())
@@ -7013,8 +6996,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		mLastUpdateReceivedCOFVersion = this_update_cof_version;
 	}
 		
-	setIsUsingServerBakes(appearance_version > 0);
-
 	applyParsedTEMessage(contents.mTEContents);
 
 	// prevent the overwriting of valid baked textures with invalid baked textures
@@ -7024,13 +7005,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			&& mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT
 			&& baked_index != BAKED_SKIRT)
 		{
-			LL_DEBUGS("Avatar") << avString() << "sb " << (S32) isUsingServerBakes() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << llendl;
+			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << llendl;
 			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, 
 				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
 		}
 		else
 		{
-			LL_DEBUGS("Avatar") << avString() << "sb " << (S32) isUsingServerBakes() << " baked_index " << (S32) baked_index << " using texture id "
+			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using texture id "
 								<< getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << llendl;
 		}
 	}
@@ -7611,31 +7592,6 @@ void LLVOAvatar::startAppearanceAnimation()
 	}
 }
 
-BOOL LLVOAvatar::isUsingServerBakes() const
-{
-#if 1
-	// Sanity check - visual param for appearance version should match mUseServerBakes
-	LLVisualParam* appearance_version_param = getVisualParam(11000);
-	llassert(appearance_version_param);
-	F32 wt = appearance_version_param->getWeight();
-	F32 expect_wt = mUseServerBakes ? 1.0 : 0.0;
-	if (!is_approx_equal(wt,expect_wt))
-	{
-		llwarns << "wt " << wt << " differs from expected " << expect_wt << llendl;
-	}
-#endif
-
-	return mUseServerBakes;
-}
-
-void LLVOAvatar::setIsUsingServerBakes(BOOL newval)
-{
-	mUseServerBakes = newval;
-	LLVisualParam* appearance_version_param = getVisualParam(11000);
-	llassert(appearance_version_param);
-	appearance_version_param->setWeight(newval ? 1.0 : 0.0);
-}
-
 // virtual
 void LLVOAvatar::removeMissingBakedTextures()
 {	
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index a4b5db3034..c7f80a1017 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -644,14 +644,6 @@ public:
 	// editing or when waiting for a subsequent server rebake.
 	/*virtual*/ BOOL	isUsingLocalAppearance() const { return mUseLocalAppearance; }
 
-	// True if this avatar should fetch its baked textures via the new
-	// appearance mechanism.
-	// SUNSHINE CLEANUP - always true, remove?
-	BOOL				isUsingServerBakes() const;
-	// SUNSHINE CLEANUP - always true, remove?
-	void 				setIsUsingServerBakes(BOOL newval);
-
-
 	// True if we are currently in appearance editing mode. Often but
 	// not always the same as isUsingLocalAppearance().
 	/*virtual*/ BOOL	isEditingAppearance() const { return mIsEditingAppearance; }
@@ -664,8 +656,6 @@ private:
 	F32				mLastAppearanceBlendTime;
 	BOOL			mIsEditingAppearance; // flag for if we're actively in appearance editing mode
 	BOOL			mUseLocalAppearance; // flag for if we're using a local composite
-	// SUNSHINE CLEANUP - always true, remove?
-	BOOL			mUseServerBakes; // flag for if baked textures should be fetched from baking service (false if they're temporary uploads)
 
 	//--------------------------------------------------------------------
 	// Visibility
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 569a2a04cc..88241304cd 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -189,15 +189,6 @@ bool update_avatar_rez_metrics()
 	return false;
 }
 
-bool check_for_unsupported_baked_appearance()
-{
-	if (!isAgentAvatarValid())
-		return true;
-
-	gAgentAvatarp->checkForUnsupportedServerBakeAppearance();
-	return false;
-}
-
 void LLVOAvatarSelf::initInstance()
 {
 	BOOL status = TRUE;
@@ -234,7 +225,6 @@ void LLVOAvatarSelf::initInstance()
 
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
-	doPeriodically(check_for_unsupported_baked_appearance, 120.0);
 	doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
 }
 
@@ -708,14 +698,6 @@ BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight
 		return FALSE;
 	}
 
-#if 0
-	// FIXME DRANO - kludgy way to avoid overwriting avatar state from wearables.
-	if (isUsingServerBakes() && !isUsingLocalAppearance())
-	{
-		return FALSE;
-	}
-#endif
-
 	if (param->getCrossWearable())
 	{
 		LLWearableType::EType type = (LLWearableType::EType)param->getWearableType();
@@ -794,7 +776,9 @@ U32  LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
 {
 	U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp);
 
-	// SUNSHINE CLEANUP - does this become relevant again if we don't have to wait for appearance message to tell us where bakes are coming from?
+	// SUNSHINE CLEANUP - does this become relevant again if we don't
+	// have to wait for appearance message to tell us where bakes are
+	// coming from?
 
 #if 0
 	// DRANO - it's not clear this does anything useful. If we wait
@@ -2376,66 +2360,6 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	}
 }
 
-class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(CheckAgentAppearanceServiceResponder);
-public:
-	CheckAgentAppearanceServiceResponder()
-	{
-	}
-	
-	virtual ~CheckAgentAppearanceServiceResponder()
-	{
-	}
-
-private:
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("Avatar") << "OK" << llendl;
-	}
-
-	// Error
-	/*virtual*/ void httpFailure()
-	{
-		if (isAgentAvatarValid())
-		{
-			LL_DEBUGS("Avatar") << "failed, will rebake "
-					<< dumpResponse() << LL_ENDL;
-			forceAppearanceUpdate();
-		}
-	}
-
-public:
-	static void forceAppearanceUpdate()
-	{
-		// Trying to rebake immediately after crossing region boundary
-		// seems to be failure prone; adding a delay factor. Yes, this
-		// fix is ad-hoc and not guaranteed to work in all cases.
-		doAfterInterval(boost::bind(&LLVOAvatarSelf::forceBakeAllTextures,
-									gAgentAvatarp.get(), true), 5.0);
-	}
-};
-
-void LLVOAvatarSelf::checkForUnsupportedServerBakeAppearance()
-{
-	// Need to check only if we have a server baked appearance and are
-	// in a non-baking region.
-	if (!gAgentAvatarp->isUsingServerBakes())
-		return;
-	if (!gAgent.getRegion() || gAgent.getRegion()->getCentralBakeVersion()!=0)
-		return;
-
-	// if baked image service is unknown, need to refresh.
-	if (LLAppearanceMgr::instance().getAppearanceServiceURL().empty())
-	{
-		CheckAgentAppearanceServiceResponder::forceAppearanceUpdate();
-	}
-	// query baked image service to check status.
-	std::string image_url = gAgentAvatarp->getImageURL(TEX_HEAD_BAKED,
-													   getTE(TEX_HEAD_BAKED)->getID());
-	LLHTTPClient::head(image_url, new CheckAgentAppearanceServiceResponder);
-}
-
 const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const
 {
 	if (canGrabBakedTexture(baked_index))
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 1f0fdd101a..7eaa239890 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -401,7 +401,6 @@ public:
 	const std::string		debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer
 	const std::string		debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD
 	void					sendViewerAppearanceChangeMetrics(); // send data associated with completing a change.
-	void 					checkForUnsupportedServerBakeAppearance();
 private:
 	LLFrameTimer    		mDebugSelfLoadTimer;
 	F32						mDebugTimeWearablesLoaded;
-- 
cgit v1.2.3


From d50be6a8a959b8d7b0f5c8a68b99d3929c17dced Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 23 Sep 2013 17:17:29 -0400
Subject: SH-3455 WIP - post-SSA cleanup

---
 indra/newview/llagentwearables.cpp | 10 ----------
 indra/newview/llagentwearables.h   |  1 -
 indra/newview/llviewerwearable.cpp |  7 -------
 indra/newview/llviewerwearable.h   |  4 +---
 4 files changed, 1 insertion(+), 21 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 0ec0fa632d..77fd66e4ba 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1477,16 +1477,6 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
 	updateServer();
 }
 
-// virtual
-void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const
-{
-	// Add some garbage into the hash so that it becomes invalid.
-	if (isAgentAvatarValid())
-	{
-		hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES);
-	}
-}
-
 // User has picked "remove from avatar" from a menu.
 // static
 void LLAgentWearables::userRemoveWearable(const LLWearableType::EType &type, const U32 &index)
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 81bfef0f8e..96c7d890b4 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -162,7 +162,6 @@ public:
 	static void		processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
 
 protected:
-	/*virtual*/ void	invalidateBakedTextureHash(LLMD5& hash) const;
 	// SUNSHINE CLEANUP dead
 	void			sendAgentWearablesUpdate();
 	// SUNSHINE CLEANUP remove?
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index d6036dbecb..143eab133d 100755
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -497,13 +497,6 @@ void LLViewerWearable::refreshName()
 	}
 }
 
-// virtual
-void LLViewerWearable::addToBakedTextureHash(LLMD5& hash) const
-{
-	LLUUID asset_id = getAssetID();
-	hash.update((const unsigned char*)asset_id.mData, UUID_BYTES);
-}
-
 struct LLWearableSaveData
 {
 	LLWearableType::EType mType;
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
index 2e59596f12..fb92bca5cc 100755
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -90,9 +90,7 @@ public:
 	// the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem,
 	// not the wearable asset itself.
 	void				refreshName();
-
-	// Update the baked texture hash.
-	/*virtual*/void		addToBakedTextureHash(LLMD5& hash) const;
+	/*virtual*/void		addToBakedTextureHash(LLMD5& hash) const {}
 
 protected:
 	LLAssetID			mAssetID;
-- 
cgit v1.2.3


From da398cb12f05f32441e4ca843448ea8f4e2acc95 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 23 Sep 2013 18:15:25 -0400
Subject: SH-3455 WIP - post-SSA cleanup

---
 indra/newview/llviewertexlayer.cpp |  6 +----
 indra/newview/llviewertexture.cpp  |  4 +--
 indra/newview/llvoavatar.cpp       | 52 ++++++--------------------------------
 indra/newview/llvoavatar.h         |  2 --
 4 files changed, 10 insertions(+), 54 deletions(-)

diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
index ad29a6bd8e..f20ab48fab 100755
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -341,7 +341,6 @@ const LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() const
 }
 
 
-// SUNSHINE CLEANUP - this used to have a bunch of upload related stuff, doesn't really serve much purpose now.
 const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const
 {
 	if (!isAgentAvatarValid()) return "";
@@ -350,10 +349,7 @@ const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const
 	const U32 num_low_res = 0;
 	const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet());
 
-	std::string status = "DONE     ";
-
-	std::string text = llformat("[%s] [HiRes:%d LoRes:%d] %s",
-								status.c_str(),
+	std::string text = llformat("[HiRes:%d LoRes:%d] %s",
 								is_high_res, num_low_res,
 								local_texture_info.c_str());
 	return text;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 80f25b7d4c..18cfa82421 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -964,9 +964,7 @@ LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type,
 	mFTType = f_type;
 	if (mFTType == FTT_HOST_BAKE)
 	{
-		// SUNSHINE CLEANUP
-		llassert(false);
-		mCanUseHTTP = false;
+		llwarns << "Unsupported fetch type " << mFTType << llendl;
 	}
 	generateGLTexture() ;
 }
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 34ca8199be..68ab25abca 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1884,24 +1884,17 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 	if (!result)
 	{
 		const std::string url = getImageURL(te,uuid);
-		if (!url.empty())
+		if (url.empty())
 		{
-			LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << llendl;
-			result = LLViewerTextureManager::getFetchedTextureFromUrl(
-				url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
-			if (result->isMissingAsset())
-			{
-				result->setIsMissingAsset(false);
-			}
+			llwarns << "unable to determine URL for te " << te << " uuid " << uuid << llendl;
+			return NULL;
 		}
-		else
+		LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << llendl;
+		result = LLViewerTextureManager::getFetchedTextureFromUrl(
+			url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
+		if (result->isMissingAsset())
 		{
-			// SUNSHINE CLEANUP
-			llassert(false);
-			LL_DEBUGS("Avatar") << avString() << "get old-bake image from host " << uuid << llendl;
-			LLHost host = getObjectHost();
-			result = LLViewerTextureManager::getFetchedTexture(
-				uuid, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
+			result->setIsMissingAsset(false);
 		}
 	}
 	return result;
@@ -4118,35 +4111,6 @@ bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const
 	return allTexturesCompletelyDownloaded(baked_ids);
 }
 
-// SUNSHINE CLEANUP
-void LLVOAvatar::bakedTextureOriginCounts(S32 &sb_count, // server-bake, has origin URL.
-										  S32 &host_count, // host-based bake, has host.
-										  S32 &both_count, // error - both host and URL set.
-										  S32 &neither_count) // error - neither set.
-{
-	sb_count = host_count = both_count = neither_count = 0;
-	
-	std::set<LLUUID> baked_ids;
-	collectBakedTextureUUIDs(baked_ids);
-	for (std::set<LLUUID>::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it)
-	{
-		LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
-		bool has_url = false, has_host = false;
-		if (!imagep->getUrl().empty())
-		{
-			has_url = true;
-		}
-		if (imagep->getTargetHost().isOk())
-		{
-			has_host = true;
-		}
-		if (has_url && !has_host) sb_count++;
-		else if (has_host && !has_url) host_count++;
-		else if (has_host && has_url) both_count++;
-		else if (!has_host && !has_url) neither_count++;
-	}
-}
-
 std::string LLVOAvatar::bakedTextureOriginInfo()
 {
 	std::string result;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index c7f80a1017..d297ce2b91 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -142,8 +142,6 @@ public:
 	bool 						allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const;
 	bool 						allLocalTexturesCompletelyDownloaded() const;
 	bool 						allBakedTexturesCompletelyDownloaded() const;
-	void 						bakedTextureOriginCounts(S32 &sb_count, S32 &host_count,
-														 S32 &both_count, S32 &neither_count);
 	std::string 				bakedTextureOriginInfo();
 	void 						collectLocalTextureUUIDs(std::set<LLUUID>& ids) const;
 	void 						collectBakedTextureUUIDs(std::set<LLUUID>& ids) const;
-- 
cgit v1.2.3


From 259394b541b43c6f4fcba2417009dd0447a17def Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Mon, 23 Sep 2013 17:03:19 -0600
Subject: fix the bug that texture aux channel data can not be reloaded.

---
 indra/newview/llviewertexture.cpp | 46 +++++++++++++++++++++++++++++++++++----
 indra/newview/llviewertexture.h   |  2 ++
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 7e35af7e63..831551a0a7 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -989,6 +989,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 {
 	mOrigWidth = 0;
 	mOrigHeight = 0;
+	mHasAux = FALSE;
 	mNeedsAux = FALSE;
 	mRequestedDiscardLevel = -1;
 	mRequestedDownloadPriority = 0.f;
@@ -1823,7 +1824,11 @@ bool LLViewerFetchedTexture::updateFetch()
 		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage,
 																		   mLastHttpGetStatus);
 		if (mRawImage.notNull()) sRawCount++;
-		if (mAuxRawImage.notNull()) sAuxCount++;
+		if (mAuxRawImage.notNull())
+		{
+			mHasAux = TRUE;
+			sAuxCount++;
+		}
 		if (finished)
 		{
 			mIsFetching = FALSE;
@@ -2152,8 +2157,16 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
 	}
 	if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
 	{
-		// We need aux data, but we've already loaded the image, and it didn't have any
-		llwarns << "No aux data available for callback for image:" << getID() << llendl;
+		if(mHasAux)
+		{
+			//trigger a refetch
+			forceToRefetchTexture();
+		}
+		else
+		{
+			// We need aux data, but we've already loaded the image, and it didn't have any
+			llwarns << "No aux data available for callback for image:" << getID() << llendl;
+		}
 	}
 	mLastCallBackActiveTime = sCurrentTime ;
 }
@@ -2604,7 +2617,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
 
 void LLViewerFetchedTexture::destroyRawImage()
 {	
-	if (mAuxRawImage.notNull())
+	if (mAuxRawImage.notNull() && !needsToSaveRawImage())
 	{
 		sAuxCount--;
 		mAuxRawImage = NULL;
@@ -2760,6 +2773,25 @@ void LLViewerFetchedTexture::saveRawImage()
 	mLastReferencedSavedRawImageTime = sCurrentTime ;
 }
 
+//force to refetch the texture to the discard level 
+void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard)
+{
+	F32 kept_time = 60.0; //seconds
+	if(mForceToSaveRawImage)
+	{
+		desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel);
+		kept_time = llmax(kept_time, mKeptSavedRawImageTime);
+	}
+
+	//trigger a new fetch.
+	mForceToSaveRawImage = TRUE ;
+	mDesiredSavedRawDiscardLevel = desired_discard ;
+	mKeptSavedRawImageTime = kept_time ;
+	mLastReferencedSavedRawImageTime = sCurrentTime ;
+	mSavedRawImage = NULL ;
+	mSavedRawDiscardLevel = -1 ;
+}
+
 void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) 
 { 
 	mKeptSavedRawImageTime = kept_time ;
@@ -2807,6 +2839,12 @@ void LLViewerFetchedTexture::destroySavedRawImage()
 	mDesiredSavedRawDiscardLevel = -1 ;
 	mLastReferencedSavedRawImageTime = 0.0f ;
 	mKeptSavedRawImageTime = 0.f ;
+	
+	if(mAuxRawImage.notNull())
+	{
+		sAuxCount--;
+		mAuxRawImage = NULL;
+	}
 }
 
 LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() 
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index d9a537d304..31430c31e0 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -388,6 +388,7 @@ public:
 	BOOL        isCachedRawImageReady() const {return mCachedRawImageReady ;}
 	BOOL        isRawImageValid()const { return mIsRawImageValid ; }	
 	void        forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
+	void        forceToRefetchTexture(S32 desired_discard = 0);
 	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
 	void        destroySavedRawImage() ;
 	LLImageRaw* getSavedRawImage() ;
@@ -449,6 +450,7 @@ protected:
 	S8  mMinDesiredDiscardLevel;	// The minimum discard level we'd like to have
 
 	S8  mNeedsAux;					// We need to decode the auxiliary channels
+	S8  mHasAux;                    // We have aux channels
 	S8  mDecodingAux;				// Are we decoding high components
 	S8  mIsRawImageValid;
 	S8  mHasFetcher;				// We've made a fecth request
-- 
cgit v1.2.3


From 3bf07ac65f046ef53db7b3eb6312f837ac92219b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 24 Sep 2013 09:35:46 -0400
Subject: merge fix

---
 indra/newview/llvoavatarself.cpp | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 6f238571a4..992ebdb1b4 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2278,11 +2278,6 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	static volatile bool reporting_started(false);
 	static volatile S32 report_sequence(0);
 
-	std::string viewer_version_channel = LLVersionInfo::getChannel();
-	sanitize_for_tsdb_tag(viewer_version_channel);
-	std::string viewer_version_short = LLVersionInfo::getShortVersion();
-	std::string viewer_version_build = llformat("%d", LLVersionInfo::getBuild());
-
 	LLSD msg;
 	msg["message"] = "ViewerAppearanceChangeMetrics";
 	msg["session_id"] = gAgentSessionID;
-- 
cgit v1.2.3


From 19ba8d8413c4541da2d76656776545334a09a38f Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 24 Sep 2013 15:39:43 -0400
Subject: SH-3455 WIP - removed some handling for appearance version < 1

---
 indra/newview/llviewerregion.cpp |  2 +-
 indra/newview/llvoavatar.cpp     | 39 ++++++++++++++-------------------------
 indra/newview/llvoavatarself.cpp |  1 +
 3 files changed, 16 insertions(+), 26 deletions(-)

diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7150089380..814b5e2265 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -387,7 +387,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mSimAccess( SIM_ACCESS_MIN ),
 	mBillableFactor(1.0),
 	mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT),
-	mCentralBakeVersion(0),
+	mCentralBakeVersion(1),
 	mClassID(0),
 	mCPURatio(0),
 	mColoName("unknown"),
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 68ab25abca..49bbf97a23 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6837,7 +6837,6 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 	}
 }
 
-// SUNSHINE CLEANUP - OK to remove the version = 0 case, assume we're at least 1?
 bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32& appearance_version)
 {
 	appearance_version = -1;
@@ -6848,19 +6847,18 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 	{
 		llwarns << "inconsistent appearance_version settings - field: " <<
 			contents.mAppearanceVersion << ", param: " <<  contents.mParamAppearanceVersion << llendl;
-		return false;
 	}
-	if (contents.mParamAppearanceVersion >= 0) // use visual param if available.
+	if (contents.mParamAppearanceVersion > 0) // use visual param if available.
 	{
 		appearance_version = contents.mParamAppearanceVersion;
 	}
-	if (contents.mAppearanceVersion >= 0)
+	else if (contents.mAppearanceVersion > 0)
 	{
 		appearance_version = contents.mAppearanceVersion;
 	}
-	if (appearance_version < 0) // still not set, go with 0.
+	else // still not set, go with 0.
 	{
-		appearance_version = 0;
+		appearance_version = 1;
 	}
 	LL_DEBUGS("Avatar") << "appearance version info - field " << contents.mAppearanceVersion
 						<< " param: " << contents.mParamAppearanceVersion
@@ -6899,6 +6897,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		llwarns << "bad appearance version info, discarding" << llendl;
 		return;
 	}
+	llassert(appearance_version > 0);
+
 	S32 this_update_cof_version = contents.mCOFVersion;
 	S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion;
 
@@ -6908,15 +6908,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version
 				<< " last_update_request_cof_version " << last_update_request_cof_version
 				<<  " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << llendl;
-
-		if (getRegion() && (getRegion()->getCentralBakeVersion()==0))
-		{
-			llwarns << avString() << "Received AvatarAppearance message for self in non-server-bake region" << llendl;
-		}
-		if( mFirstTEMessageReceived && (appearance_version == 0))
-		{
-			return;
-		}
 	}
 	else
 	{
@@ -6925,7 +6916,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 
 	// Check for stale update.
 	if (isSelf()
-		&& (appearance_version>0)
 		&& (this_update_cof_version < last_update_request_cof_version))
 	{
 		llwarns << "Stale appearance update, wanted version " << last_update_request_cof_version
@@ -6939,6 +6929,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
+	// SUNSHINE CLEANUP - is this case OK now?
 	S32 num_params = contents.mParamWeights.size();
 	if (num_params <= 1)
 	{
@@ -6950,15 +6941,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
-	// No backsies zone - if we get here, the message should be valid and usable.
-	if (appearance_version > 0)
-	{
-		// Note:
-		// RequestAgentUpdateAppearanceResponder::onRequestRequested()
-		// assumes that cof version is only updated with server-bake
-		// appearance messages.
-		mLastUpdateReceivedCOFVersion = this_update_cof_version;
-	}
+	// No backsies zone - if we get here, the message should be valid and usable, will process.
+
+	// Note:
+	// RequestAgentUpdateAppearanceResponder::onRequestRequested()
+	// assumes that cof version is only updated with server-bake
+	// appearance messages.
+	mLastUpdateReceivedCOFVersion = this_update_cof_version;
 		
 	applyParsedTEMessage(contents.mTEContents);
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 992ebdb1b4..97429329a8 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2808,6 +2808,7 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch)
 	if (isAgentAvatarValid())
 	{
 		gAgentAvatarp->mIsEditingAppearance = false;
+		// SUNSHINE CLEANUP - should no longer happen
 		if (gAgentAvatarp->getRegion() && !gAgentAvatarp->getRegion()->getCentralBakeVersion())
 		{
 			// FIXME DRANO - move to sendAgentSetAppearance, make conditional on upload complete.
-- 
cgit v1.2.3


From ab0c38612f5d055b41fdf08efa9ab8f2c30ec6b8 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Tue, 24 Sep 2013 20:22:19 +0000
Subject: SH-2728 SH-4010 FIX pants flare issues

When wearing multiple layers of pants, the morph masks for all layers would be composited,
resulting in the smallest intersection of all layers. Instead we should only be applying the
top layer. This change will affect all consumers of the llappearance library.
---
 indra/llappearance/lltexlayer.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index 59765b3833..510d8ce879 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1776,13 +1776,11 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
 /*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
 {
 	U32 num_wearables = updateWearableCache();
-	for (U32 i = 0; i < num_wearables; i++)
+	U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
+	LLTexLayer *layer = getLayer(i);
+	if (layer)
 	{
-		LLTexLayer *layer = getLayer(i);
-		if (layer)
-		{
-			layer->addAlphaMask(data, originX, originY, width, height);
-		}
+		layer->addAlphaMask(data, originX, originY, width, height);
 	}
 }
 
-- 
cgit v1.2.3


From ac6797c71ad2f75f9f34b3d6b8da4948825e6d57 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 25 Sep 2013 13:01:55 -0400
Subject: SH-3455 WIP - moved setAvatarObject() to run after the self av
 constructor. Disabled sendAgentWearablesUpdate.

---
 indra/newview/llagentwearables.cpp | 9 +++++++--
 indra/newview/llviewerobject.cpp   | 2 ++
 indra/newview/llvoavatarself.cpp   | 2 --
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 77fd66e4ba..5a059008c4 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -182,9 +182,11 @@ void LLAgentWearables::initClass()
 void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
 {
 	llassert(avatar);
-	avatar->outputRezTiming("Sending wearables request");
-	sendAgentWearablesRequest();
 	setAvatarAppearance(avatar);
+	gAgentWearables.notifyLoadingStarted();
+	callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(),
+						   boost::bind(&LLAppearanceMgr::updateAppearanceFromCOF,
+									   LLAppearanceMgr::getInstance(), true, true, no_op));
 }
 
 // wearables
@@ -302,6 +304,8 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy
 // SUNSHINE CLEANUP dead?
 void LLAgentWearables::sendAgentWearablesUpdate()
 {
+	return; // try as NO_OP // SUNSHINE CLEANUP
+#if 0
 	// First make sure that we have inventory items for each wearable
 	for (S32 type=0; type < LLWearableType::WT_COUNT; ++type)
 	{
@@ -372,6 +376,7 @@ void LLAgentWearables::sendAgentWearablesUpdate()
 		lldebugs << "       " << LLWearableType::getTypeLabel((LLWearableType::EType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
 	}
 	gAgent.sendReliableMessage();
+#endif
 }
 
 void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update,
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 91efed1508..dc8acc91a9 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -57,6 +57,7 @@
 #include "llaudiosourcevo.h"
 #include "llagent.h"
 #include "llagentcamera.h"
+#include "llagentwearables.h"
 #include "llbbox.h"
 #include "llbox.h"
 #include "llcylinder.h"
@@ -140,6 +141,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
 			{
 				gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp);
 				gAgentAvatarp->initInstance();
+				gAgentWearables.setAvatarObject(gAgentAvatarp);
 			}
 			else 
 			{
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 97429329a8..498f8c8277 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -161,8 +161,6 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 	mRegionCrossingCount(0),
 	mInitialBakesLoaded(false)
 {
-	gAgentWearables.setAvatarObject(this);
-
 	mMotionController.mIsSelf = TRUE;
 
 	lldebugs << "Marking avatar as self " << id << llendl;
-- 
cgit v1.2.3


From 39900843c99dbfc01f8a28fb071edc9a77c471be Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 26 Sep 2013 16:24:25 -0400
Subject: SH-3455 WIP

---
 indra/newview/llagentwearables.cpp    | 203 +++++-----------------------------
 indra/newview/llagentwearables.h      |  18 +--
 indra/newview/llpaneleditwearable.cpp |   2 +-
 indra/newview/llstartup.cpp           |   4 +-
 4 files changed, 34 insertions(+), 193 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 5a059008c4..a97396ae1c 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -126,13 +126,6 @@ void LLAgentWearables::dump()
 			
 		}
 	}
-	llinfos << "Total items awaiting wearable update " << mItemsAwaitingWearableUpdate.size() << llendl;
-	for (std::set<LLUUID>::iterator it = mItemsAwaitingWearableUpdate.begin();
-		 it != mItemsAwaitingWearableUpdate.end();
-		 ++it)
-	{
-		llinfos << (*it).asString() << llendl;
-	}
 }
 
 struct LLAgentDumper
@@ -189,12 +182,6 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
 									   LLAppearanceMgr::getInstance(), true, true, no_op));
 }
 
-// wearables
-LLAgentWearables::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback()
-{
-	llinfos << "destructor - all done?" << llendl;
-	gAgentWearables.createStandardWearablesAllDone();
-}
 
 /**
  * @brief Construct a callback for dealing with the wearables.
@@ -222,6 +209,8 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i
 {
 	if (mTodo & CALL_CREATESTANDARDDONE)
 	{
+		// SUNSHINE CLEANUP
+		llassert(false); // does not appear to ever be used.
 		llinfos << "callback fired, inv_item " << inv_item.asString() << llendl;
 	}
 
@@ -230,10 +219,6 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i
 
 	gAgentWearables.addWearabletoAgentInventoryDone(mType, mIndex, inv_item, mWearable);
 
-	if (mTodo & CALL_UPDATE)
-	{
-		gAgentWearables.sendAgentWearablesUpdate();
-	}
 	if (mTodo & CALL_RECOVERDONE)
 	{
 		LLAppearanceMgr::instance().addCOFItemLink(inv_item);
@@ -244,8 +229,10 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i
 	 */
 	if (mTodo & CALL_CREATESTANDARDDONE)
 	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item);
-		gAgentWearables.createStandardWearablesDone(mType, mIndex);
+		// SUNSHINE CLEANUP
+		llassert(false); // does not appear to ever be used.
+		//LLAppearanceMgr::instance().addCOFItemLink(inv_item);
+		//gAgentWearables.createStandardWearablesDone(mType, mIndex);
 	}
 	if (mTodo & CALL_MAKENEWOUTFITDONE)
 	{
@@ -379,7 +366,7 @@ void LLAgentWearables::sendAgentWearablesUpdate()
 #endif
 }
 
-void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update,
+void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index,
 									const std::string new_name)
 {
 	LLViewerWearable* old_wearable = getViewerWearable(type, index);
@@ -426,10 +413,6 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
 		{
 			// Add a new inventory item (shouldn't ever happen here)
 			U32 todo = AddWearableToAgentInventoryCallback::CALL_NONE;
-			if (send_update)
-			{
-				todo |= AddWearableToAgentInventoryCallback::CALL_UPDATE;
-			}
 			LLPointer<LLInventoryCallback> cb =
 				new AddWearableToAgentInventoryCallback(
 					LLPointer<LLRefCount>(NULL),
@@ -442,11 +425,6 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
 		}
 
 		gAgentAvatarp->wearableUpdated(type);
-
-		if (send_update)
-		{
-			sendAgentWearablesUpdate();
-		}
 	}
 }
 
@@ -534,9 +512,10 @@ void LLAgentWearables::saveAllWearables()
 	for (S32 i=0; i < LLWearableType::WT_COUNT; i++)
 	{
 		for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++)
-			saveWearable((LLWearableType::EType)i, j, FALSE);
+			saveWearable((LLWearableType::EType)i, j);
 	}
-	sendAgentWearablesUpdate();
+	// SUNSHINE CLEANUP - check ok
+	//sendAgentWearablesUpdate();
 }
 
 // Called when the user changes the name of a wearable inventory item that is currently being worn.
@@ -565,7 +544,8 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string&
 				old_wearable->setName(old_name);
 
 				setWearable((LLWearableType::EType)i,j,new_wearable);
-				sendAgentWearablesUpdate();
+				// SUNSHINE CLEANUP - verify ok
+				//sendAgentWearablesUpdate();
 				break;
 			}
 		}
@@ -736,23 +716,13 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
 			wearable->setDefinitionVersion(22);
 			U32 index = getWearableIndex(wearable);
 			llinfos << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << llendl;
-			saveWearable(wearable->getType(),index,TRUE);
+			saveWearable(wearable->getType(),index);
 		}
 
 		checkWearableAgainstInventory(viewer_wearable);
 	}
 }
 
-BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const
-{
-	return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end();
-}
-
-U32 LLAgentWearables::itemUpdatePendingCount() const
-{
-	return mItemsAwaitingWearableUpdate.size();
-}
-
 const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 index) const
 {
 	const LLViewerWearable *wearable = getViewerWearable(type,index);
@@ -776,116 +746,6 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
 	return getWearableFromItemID(item_id) != NULL;
 }
 
-// MULTI-WEARABLE: DEPRECATED (see backwards compatibility)
-// ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume
-// that viewers have a Current Outfit Folder and won't need this message, and thus
-// we can remove/ignore this whole function. EXCEPT gAgentWearables.notifyLoadingStarted
-
-// static
-void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data)
-{
-	// We should only receive this message a single time.  Ignore subsequent AgentWearablesUpdates
-	// that may result from AgentWearablesRequest having been sent more than once.
-	if (mInitialWearablesUpdateReceived)
-		return;
-
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->startPhase("process_initial_wearables_update");
-		gAgentAvatarp->outputRezTiming("Received initial wearables update");
-	}
-
-	// notify subscribers that wearables started loading. See EXT-7777
-	// *TODO: find more proper place to not be called from deprecated method.
-	// Seems such place is found: LLInitialWearablesFetch::processContents()
-	gAgentWearables.notifyLoadingStarted();
-
-	mInitialWearablesUpdateReceived = true;
-
-	LLUUID agent_id;
-	gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
-
-	if (isAgentAvatarValid() && (agent_id == gAgentAvatarp->getID()))
-	{
-		U32 unused_update_serial_num;
-		gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, unused_update_serial_num);
-		
-		const S32 NUM_BODY_PARTS = 4;
-		S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
-		if (num_wearables < NUM_BODY_PARTS)
-		{
-			// Transitional state.  Avatars should always have at least their body parts (hair, eyes, shape and skin).
-			// The fact that they don't have any here (only a dummy is sent) implies that either:
-			// 1. This account existed before we had wearables
-			// 2. The database has gotten messed up
-			// 3. This is the account's first login (i.e. the wearables haven't been generated yet).
-			return;
-		}
-
-		// Get the UUID of the current outfit folder (will be created if it doesn't exist)
-		const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-		LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch(current_outfit_id);
-		
-		//lldebugs << "processAgentInitialWearablesUpdate()" << llendl;
-		// Add wearables
-		// MULTI-WEARABLE: DEPRECATED: Message only supports one wearable per type, will be ignored in future.
-		gAgentWearables.mItemsAwaitingWearableUpdate.clear();
-		for (S32 i=0; i < num_wearables; i++)
-		{
-			// Parse initial wearables data from message system
-			U8 type_u8 = 0;
-			gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i);
-			if (type_u8 >= LLWearableType::WT_COUNT)
-			{
-				continue;
-			}
-			const LLWearableType::EType type = (LLWearableType::EType) type_u8;
-			
-			LLUUID item_id;
-			gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i);
-			
-			LLUUID asset_id;
-			gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i);
-			if (asset_id.isNull())
-			{
-				LLViewerWearable::removeFromAvatar(type);
-			}
-			else
-			{
-				LLAssetType::EType asset_type = LLWearableType::getAssetType(type);
-				if (asset_type == LLAssetType::AT_NONE)
-				{
-					continue;
-				}
-				
-				// MULTI-WEARABLE: DEPRECATED: this message only supports one wearable per type. Should be ignored in future versions
-				
-				// Store initial wearables data until we know whether we have the current outfit folder or need to use the data.
-				LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id);
-				outfit->add(wearable_data);
-			}
-			
-			lldebugs << "       " << LLWearableType::getTypeLabel(type) << llendl;
-		}
-		
-		// Get the complete information on the items in the inventory and set up an observer
-		// that will trigger when the complete information is fetched.
-		outfit->startFetch();
-		if(outfit->isFinished())
-		{
-			// everything is already here - call done.
-			outfit->done();
-		}
-		else
-		{
-			// it's all on it's way - add an observer, and the inventory
-			// will call done for us when everything is here.
-			gInventory.addObserver(outfit);
-		}
-		
-	}
-}
-
 // Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the
 // database.  If for some reason, we can't load one of those assets, we can try to reconstruct it so that
 // the user isn't left without a shape, for example.  (We can do that only after the inventory has loaded.)
@@ -1063,6 +923,8 @@ void LLAgentWearables::createStandardWearables()
 	}
 }
 
+// SUNSHINE CLEANUP apparently unused.
+#if 0
 void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
 {
 	llinfos << "type " << type << " index " << index << llendl;
@@ -1070,22 +932,7 @@ void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
 	if (!isAgentAvatarValid()) return;
 	gAgentAvatarp->updateVisualParams();
 }
-
-void LLAgentWearables::createStandardWearablesAllDone()
-{
-	// ... because sendAgentWearablesUpdate will notify inventory
-	// observers.
-	llinfos << "all done?" << llendl;
-
-	mWearablesLoaded = TRUE; 
-	checkWearablesLoaded();
-	notifyLoadingFinished();
-	
-	updateServer();
-
-	// Treat this as the first texture entry message, if none received yet
-	gAgentAvatarp->onFirstTEMessageReceived();
-}
+#endif
 
 void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
 {
@@ -1220,7 +1067,8 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 	}
 
 	// Update the server
-	updateServer();
+	// SUNSHINE CLEANUP
+	// updateServer();
 	gInventory.notifyObservers();
 }
 
@@ -1354,7 +1202,8 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	mWearablesLoaded = TRUE; 
 	checkWearablesLoaded();
 	notifyLoadingFinished();
-	updateServer();
+	// SUNSHINE CLEANUP
+	//updateServer();
 
 	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
 
@@ -1479,7 +1328,8 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
 	//llinfos << "LLVOAvatar::setWearableItem()" << llendl;
 	//new_wearable->writeToAvatar(TRUE);
 
-	updateServer();
+	// SUNSHINE CLEANUP
+	//updateServer();
 }
 
 // User has picked "remove from avatar" from a menu.
@@ -1650,10 +1500,11 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra
 	}
 }
 
+// SUNSHINE CLEANUP - itemUpdatePendingCount() was always 0, so this should be removed as useless.
 void LLAgentWearables::checkWearablesLoaded() const
 {
 #ifdef SHOW_ASSERT
-	U32 item_pend_count = itemUpdatePendingCount();
+	U32 item_pend_count = 0; //itemUpdatePendingCount();
 	if (mWearablesLoaded)
 	{
 		llassert(item_pend_count==0);
@@ -1677,14 +1528,14 @@ bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_bod
 
 BOOL LLAgentWearables::areWearablesLoaded() const
 {
-	checkWearablesLoaded();
 	return mWearablesLoaded;
 }
 
 // MULTI-WEARABLE: DEPRECATED: item pending count relies on old messages that don't support multi-wearables. do not trust to be accurate
+// SUNSHINE CLEANUP - itemUpdatePendingCount was always 0 due to longstanding bug, might as well remove (or fix) this.
 void LLAgentWearables::updateWearablesLoaded()
 {
-	mWearablesLoaded = (itemUpdatePendingCount()==0);
+	mWearablesLoaded = true; //(itemUpdatePendingCount()==0);
 	if (mWearablesLoaded)
 	{
 		notifyLoadingFinished();
@@ -1834,10 +1685,12 @@ void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id)
 }
 
 // SUNSHINE CLEANUP - both of these funcs seem to be dead code, so this one should go too.
+#if 0
 void LLAgentWearables::updateServer()
 {
 	sendAgentWearablesUpdate();
 }
+#endif
 
 boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)
 {
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 96c7d890b4..87170eeb72 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -62,9 +62,6 @@ public:
 
 	// LLInitClass interface
 	static void initClass();
-protected:
-	void			createStandardWearablesDone(S32 type, U32 index/* = 0*/);
-	void			createStandardWearablesAllDone();
 	
 	//--------------------------------------------------------------------
 	// Queries
@@ -156,18 +153,13 @@ protected:
 	//--------------------------------------------------------------------
 	// Server Communication
 	//--------------------------------------------------------------------
-public:
-	// Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant)
-	// SUNSHINE CLEANUP - should be able to remove dependency on this.
-	static void		processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
-
 protected:
 	// SUNSHINE CLEANUP dead
 	void			sendAgentWearablesUpdate();
 	// SUNSHINE CLEANUP remove?
 	void			sendAgentWearablesRequest();
-	// SUNSHINE CLEANUP dead
-	void 			updateServer();
+	// SUNSHINE CLEANUP dead?
+	//void 			updateServer();
 	static void		onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata);
 
 	//--------------------------------------------------------------------
@@ -181,7 +173,7 @@ private:
 	//--------------------------------------------------------------------
 public:	
 	void			saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, const std::string& description, BOOL save_in_lost_and_found);
-	void			saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE,
+	void			saveWearable(const LLWearableType::EType type, const U32 index,
 								 const std::string new_name = "");
 	void			saveAllWearables();
 	void			revertWearable(const LLWearableType::EType type, const U32 index);
@@ -199,9 +191,6 @@ public:
 	static void		userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
 	static void		userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
 
-	BOOL			itemUpdatePending(const LLUUID& item_id) const;
-	U32				itemUpdatePendingCount() const;
-
 	//--------------------------------------------------------------------
 	// Signals
 	//--------------------------------------------------------------------
@@ -228,7 +217,6 @@ private:
 private:
 	static BOOL		mInitialWearablesUpdateReceived;
 	BOOL			mWearablesLoaded;
-	std::set<LLUUID>	mItemsAwaitingWearableUpdate;
 
 	/**
 	 * True if agent's outfit is being changed now.
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 0be5c19387..d1864c2c4b 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1104,7 +1104,7 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 				// Remove old link
 				remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
 			}
-			gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
+			gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name);
         }
 
 	
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3abc08ec2d..4be0f6b40b 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2444,8 +2444,8 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 	// msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
 	//					LLFloaterRate::processReputationIndividualReply);
 
-	msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
-						LLAgentWearables::processAgentInitialWearablesUpdate );
+	//msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
+	//					LLAgentWearables::processAgentInitialWearablesUpdate );
 
 	msg->setHandlerFunc("ScriptControlChange",
 						LLAgent::processScriptControlChange );
-- 
cgit v1.2.3


From 2248cbf2b873d3bf264ddbec22ea731bee9a9b96 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 26 Sep 2013 17:27:01 -0400
Subject: SH-3455 WIP - removed llagentwearablesfetch files, among other
 changes

---
 indra/newview/CMakeLists.txt            |   2 -
 indra/newview/llagentwearables.cpp      | 177 +--------------------------
 indra/newview/llagentwearables.h        |  14 ---
 indra/newview/llagentwearablesfetch.cpp | 204 --------------------------------
 indra/newview/llagentwearablesfetch.h   |  73 ------------
 5 files changed, 5 insertions(+), 465 deletions(-)
 delete mode 100755 indra/newview/llagentwearablesfetch.cpp
 delete mode 100755 indra/newview/llagentwearablesfetch.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 7e50e761ae..9f9b9c68a3 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -110,7 +110,6 @@ set(viewer_SOURCE_FILES
     llagentpilot.cpp
     llagentui.cpp
     llagentwearables.cpp
-    llagentwearablesfetch.cpp
     llanimstatelabels.cpp
     llappcorehttp.cpp
     llappearancemgr.cpp
@@ -695,7 +694,6 @@ set(viewer_HEADER_FILES
     llagentpilot.h
     llagentui.h
     llagentwearables.h
-    llagentwearablesfetch.h
     llanimstatelabels.h
     llappcorehttp.h
     llappearance.h
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index a97396ae1c..5b18a45431 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -30,7 +30,6 @@
 #include "llaccordionctrltab.h"
 #include "llagent.h"
 #include "llagentcamera.h"
-#include "llagentwearablesfetch.h"
 #include "llappearancemgr.h"
 #include "llcallbacklist.h"
 #include "llfloatersidepanelcontainer.h"
@@ -207,13 +206,6 @@ LLAgentWearables::AddWearableToAgentInventoryCallback::AddWearableToAgentInvento
 
 void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
 {
-	if (mTodo & CALL_CREATESTANDARDDONE)
-	{
-		// SUNSHINE CLEANUP
-		llassert(false); // does not appear to ever be used.
-		llinfos << "callback fired, inv_item " << inv_item.asString() << llendl;
-	}
-
 	if (inv_item.isNull())
 		return;
 
@@ -227,13 +219,6 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i
 	/*
 	 * Do this for every one in the loop
 	 */
-	if (mTodo & CALL_CREATESTANDARDDONE)
-	{
-		// SUNSHINE CLEANUP
-		llassert(false); // does not appear to ever be used.
-		//LLAppearanceMgr::instance().addCOFItemLink(inv_item);
-		//gAgentWearables.createStandardWearablesDone(mType, mIndex);
-	}
 	if (mTodo & CALL_MAKENEWOUTFITDONE)
 	{
 		gAgentWearables.makeNewOutfitDone(mType, mIndex);
@@ -288,84 +273,6 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy
 	gInventory.notifyObservers();
 }
 
-// SUNSHINE CLEANUP dead?
-void LLAgentWearables::sendAgentWearablesUpdate()
-{
-	return; // try as NO_OP // SUNSHINE CLEANUP
-#if 0
-	// First make sure that we have inventory items for each wearable
-	for (S32 type=0; type < LLWearableType::WT_COUNT; ++type)
-	{
-		for (U32 index=0; index < getWearableCount((LLWearableType::EType)type); ++index)
-		{
-			LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type,index);
-			if (wearable)
-			{
-				if (wearable->getItemID().isNull())
-				{
-					LLPointer<LLInventoryCallback> cb =
-						new AddWearableToAgentInventoryCallback(
-							LLPointer<LLRefCount>(NULL),
-							(LLWearableType::EType)type,
-							index,
-							wearable,
-							AddWearableToAgentInventoryCallback::CALL_NONE);
-					addWearableToAgentInventory(cb, wearable);
-				}
-				else
-				{
-					gInventory.addChangedMask(LLInventoryObserver::LABEL,
-											  wearable->getItemID());
-				}
-			}
-		}
-	}
-
-	// Then make sure the inventory is in sync with the avatar.
-	gInventory.notifyObservers();
-
-	// Send the AgentIsNowWearing 
-	gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
-
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
-	lldebugs << "sendAgentWearablesUpdate()" << llendl;
-	// MULTI-WEARABLE: DEPRECATED: HACK: index to 0- server database tables don't support concept of multiwearables.
-	for (S32 type=0; type < LLWearableType::WT_COUNT; ++type)
-	{
-		gMessageSystem->nextBlockFast(_PREHASH_WearableData);
-
-		U8 type_u8 = (U8)type;
-		gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8);
-
-		LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type, 0);
-		if (wearable)
-		{
-			//llinfos << "Sending wearable " << wearable->getName() << llendl;
-			LLUUID item_id = wearable->getItemID();
-			const LLViewerInventoryItem *item = gInventory.getItem(item_id);
-			if (item && item->getIsLinkType())
-			{
-				// Get the itemID that this item points to.  i.e. make sure
-				// we are storing baseitems, not their links, in the database.
-				item_id = item->getLinkedUUID();
-			}
-			gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);			
-		}
-		else
-		{
-			//llinfos << "Not wearing wearable type " << LLWearableType::getTypeName((LLWearableType::EType)i) << llendl;
-			gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
-		}
-
-		lldebugs << "       " << LLWearableType::getTypeLabel((LLWearableType::EType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
-	}
-	gAgent.sendReliableMessage();
-#endif
-}
-
 void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index,
 									const std::string new_name)
 {
@@ -514,8 +421,6 @@ void LLAgentWearables::saveAllWearables()
 		for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++)
 			saveWearable((LLWearableType::EType)i, j);
 	}
-	// SUNSHINE CLEANUP - check ok
-	//sendAgentWearablesUpdate();
 }
 
 // Called when the user changes the name of a wearable inventory item that is currently being worn.
@@ -544,8 +449,6 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string&
 				old_wearable->setName(old_name);
 
 				setWearable((LLWearableType::EType)i,j,new_wearable);
-				// SUNSHINE CLEANUP - verify ok
-				//sendAgentWearablesUpdate();
 				break;
 			}
 		}
@@ -666,15 +569,6 @@ LLViewerWearable*	LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_i
 	return NULL;
 }
 
-void LLAgentWearables::sendAgentWearablesRequest()
-{
-	gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest);
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	gAgent.sendReliableMessage();
-}
-
 LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/)
 {
 	return dynamic_cast<LLViewerWearable*> (getWearable(type, index));
@@ -775,18 +669,8 @@ void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type,
 
 void LLAgentWearables::recoverMissingWearableDone()
 {
-	// Have all the wearables that the avatar was wearing at log-in arrived or been fabricated?
-	updateWearablesLoaded();
-	if (areWearablesLoaded())
-	{
-		// Make sure that the server's idea of the avatar's wearables actually match the wearables.
-		//gAgent.sendAgentSetAppearance();
-	}
-	else
-	{
-		gInventory.addChangedMask(LLInventoryObserver::LABEL, LLUUID::null);
-		gInventory.notifyObservers();
-	}
+	gInventory.addChangedMask(LLInventoryObserver::LABEL, LLUUID::null);
+	gInventory.notifyObservers();
 }
 
 void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index)
@@ -923,17 +807,6 @@ void LLAgentWearables::createStandardWearables()
 	}
 }
 
-// SUNSHINE CLEANUP apparently unused.
-#if 0
-void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
-{
-	llinfos << "type " << type << " index " << index << llendl;
-
-	if (!isAgentAvatarValid()) return;
-	gAgentAvatarp->updateVisualParams();
-}
-#endif
-
 void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
 {
 	LLUUID first_item_id = getWearableItemID((LLWearableType::EType)type, index);
@@ -1066,9 +939,6 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 		}
 	}
 
-	// Update the server
-	// SUNSHINE CLEANUP
-	// updateServer();
 	gInventory.notifyObservers();
 }
 
@@ -1200,10 +1070,10 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 
 	// Start rendering & update the server
 	mWearablesLoaded = TRUE; 
-	checkWearablesLoaded();
+
+	// SUNSHINE CLEANUP - these checks for done never worked. Should they be modified?
+	//checkWearablesLoaded();
 	notifyLoadingFinished();
-	// SUNSHINE CLEANUP
-	//updateServer();
 
 	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
 
@@ -1324,12 +1194,6 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
 		llinfos << "Replaced current element 0 for type " << type
 				<< " size is now " << getWearableCount(type) << llendl;
 	}
-
-	//llinfos << "LLVOAvatar::setWearableItem()" << llendl;
-	//new_wearable->writeToAvatar(TRUE);
-
-	// SUNSHINE CLEANUP
-	//updateServer();
 }
 
 // User has picked "remove from avatar" from a menu.
@@ -1500,18 +1364,6 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra
 	}
 }
 
-// SUNSHINE CLEANUP - itemUpdatePendingCount() was always 0, so this should be removed as useless.
-void LLAgentWearables::checkWearablesLoaded() const
-{
-#ifdef SHOW_ASSERT
-	U32 item_pend_count = 0; //itemUpdatePendingCount();
-	if (mWearablesLoaded)
-	{
-		llassert(item_pend_count==0);
-	}
-#endif
-}
-
 // Returns false if the given wearable is already topmost/bottommost
 // (depending on closer_to_body parameter).
 bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) const
@@ -1531,17 +1383,6 @@ BOOL LLAgentWearables::areWearablesLoaded() const
 	return mWearablesLoaded;
 }
 
-// MULTI-WEARABLE: DEPRECATED: item pending count relies on old messages that don't support multi-wearables. do not trust to be accurate
-// SUNSHINE CLEANUP - itemUpdatePendingCount was always 0 due to longstanding bug, might as well remove (or fix) this.
-void LLAgentWearables::updateWearablesLoaded()
-{
-	mWearablesLoaded = true; //(itemUpdatePendingCount()==0);
-	if (mWearablesLoaded)
-	{
-		notifyLoadingFinished();
-	}
-}
-
 bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) const
 {
 	if (!wearable) return false;
@@ -1684,14 +1525,6 @@ void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id)
 	}
 }
 
-// SUNSHINE CLEANUP - both of these funcs seem to be dead code, so this one should go too.
-#if 0
-void LLAgentWearables::updateServer()
-{
-	sendAgentWearablesUpdate();
-}
-#endif
-
 boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)
 {
 	return mLoadingStartedSignal.connect(cb);
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 87170eeb72..a7b033a37d 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -42,7 +42,6 @@
 class LLInventoryItem;
 class LLVOAvatarSelf;
 class LLViewerWearable;
-class LLInitialWearablesFetch;
 class LLViewerObject;
 
 class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearableData
@@ -51,7 +50,6 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 	// Constructors / destructors / Initializers
 	//--------------------------------------------------------------------
 public:
-	friend class LLInitialWearablesFetch;
 
 	LLAgentWearables();
 	virtual ~LLAgentWearables();
@@ -149,18 +147,6 @@ private:
 	void			removeWearableFinal(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/);
 protected:
 	static bool		onRemoveWearableDialog(const LLSD& notification, const LLSD& response);
-	
-	//--------------------------------------------------------------------
-	// Server Communication
-	//--------------------------------------------------------------------
-protected:
-	// SUNSHINE CLEANUP dead
-	void			sendAgentWearablesUpdate();
-	// SUNSHINE CLEANUP remove?
-	void			sendAgentWearablesRequest();
-	// SUNSHINE CLEANUP dead?
-	//void 			updateServer();
-	static void		onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata);
 
 	//--------------------------------------------------------------------
 	// Outfits
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
deleted file mode 100755
index a10382b830..0000000000
--- a/indra/newview/llagentwearablesfetch.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/** 
- * @file llagentwearablesfetch.cpp
- * @brief LLAgentWearblesFetch class implementation
- *
- * $LicenseInfo:firstyear=2001&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 "llviewerprecompiledheaders.h"
-#include "llagentwearablesfetch.h"
-
-#include "llagent.h"
-#include "llagentwearables.h"
-#include "llappearancemgr.h"
-#include "llinventoryfunctions.h"
-#include "llstartup.h"
-#include "llvoavatarself.h"
-
-
-LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
-	LLInventoryFetchDescendentsObserver(cof_id)
-{
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->startPhase("initial_wearables_fetch");
-		gAgentAvatarp->outputRezTiming("Initial wearables fetch started");
-	}
-}
-
-LLInitialWearablesFetch::~LLInitialWearablesFetch()
-{
-}
-
-// virtual
-void LLInitialWearablesFetch::done()
-{
-	// Delay processing the actual results of this so it's not handled within
-	// gInventory.notifyObservers.  The results will be handled in the next
-	// idle tick instead.
-	gInventory.removeObserver(this);
-	doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this));
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->stopPhase("initial_wearables_fetch");
-		gAgentAvatarp->outputRezTiming("Initial wearables fetch done");
-	}
-}
-
-void LLInitialWearablesFetch::add(InitialWearableData &data)
-
-{
-	mAgentInitialWearables.push_back(data);
-}
-
-// SUNSHINE CLEANUP - should not have to wait for this message to start resolving appearance. Where to hook in instead?
-void LLInitialWearablesFetch::processContents()
-{
-	if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted.
-	{
-		delete this;
-		return ;
-	}
-
-	// Fetch the wearable items from the Current Outfit Folder
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t wearable_array;
-	LLFindWearables is_wearable;
-	llassert_always(mComplete.size() != 0);
-	gInventory.collectDescendentsIf(mComplete.front(), cat_array, wearable_array, 
-									LLInventoryModel::EXCLUDE_TRASH, is_wearable);
-
-	LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
-	if (wearable_array.count() > 0)
-	{
-		gAgentWearables.notifyLoadingStarted();
-		LLAppearanceMgr::instance().updateAppearanceFromCOF();
-	}
-	else
-	{
-		// SUNSHINE CLEANUP - remove?
-		// if we're constructing the COF from the wearables message, we don't have a proper outfit link
-		LLAppearanceMgr::instance().setOutfitDirty(true);
-		processWearablesMessage();
-	}
-	delete this;
-}
-
-class LLFetchAndLinkObserver: public LLInventoryFetchItemsObserver
-{
-public:
-	LLFetchAndLinkObserver(uuid_vec_t& ids):
-		LLInventoryFetchItemsObserver(ids)
-	{
-	}
-	~LLFetchAndLinkObserver()
-	{
-	}
-	virtual void done()
-	{
-		gInventory.removeObserver(this);
-
-		// Link to all fetched items in COF.
-		LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-		LLInventoryObject::const_object_list_t item_array;
-		for (uuid_vec_t::iterator it = mIDs.begin();
-			 it != mIDs.end();
-			 ++it)
-		{
-			LLUUID id = *it;
-			LLConstPointer<LLInventoryObject> item = gInventory.getItem(*it);
-			if (!item)
-			{
-				llwarns << "fetch failed for item " << (*it) << "!" << llendl;
-				continue;
-			}
-			item_array.push_back(item);
-		}
-		link_inventory_array(LLAppearanceMgr::instance().getCOF(), item_array, link_waiter);
-	}
-};
-
-// SUNSHINE CLEANUP - remove dependency on this?
-void LLInitialWearablesFetch::processWearablesMessage()
-{
-	if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
-	{
-		const LLUUID current_outfit_id = LLAppearanceMgr::instance().getCOF();
-		uuid_vec_t ids;
-		for (U8 i = 0; i < mAgentInitialWearables.size(); ++i)
-		{
-			// Populate the current outfit folder with links to the wearables passed in the message
-			InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback.
-			
-			if (wearable_data->mAssetID.notNull())
-			{
-				ids.push_back(wearable_data->mItemID);
-			}
-			else
-			{
-				llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID "
-				<< wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
-				delete wearable_data;
-			}
-		}
-
-		// Add all current attachments to the requested items as well.
-		if (isAgentAvatarValid())
-		{
-			for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
-				 iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
-			{
-				LLViewerJointAttachment* attachment = iter->second;
-				if (!attachment) continue;
-				for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-					 attachment_iter != attachment->mAttachedObjects.end();
-					 ++attachment_iter)
-				{
-					LLViewerObject* attached_object = (*attachment_iter);
-					if (!attached_object) continue;
-					const LLUUID& item_id = attached_object->getAttachmentItemID();
-					if (item_id.isNull()) continue;
-					ids.push_back(item_id);
-				}
-			}
-		}
-
-		// Need to fetch the inventory items for ids, then create links to them after they arrive.
-		LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids);
-		fetcher->startFetch();
-		// If no items to be fetched, done will never be triggered.
-		// TODO: Change LLInventoryFetchItemsObserver::fetchItems to trigger done() on this condition.
-		if (fetcher->isFinished())
-		{
-			fetcher->done();
-		}
-		else
-		{
-			gInventory.addObserver(fetcher);
-		}
-	}
-	else
-	{
-		LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL;
-	}
-}
-
diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h
deleted file mode 100755
index 81b03110ae..0000000000
--- a/indra/newview/llagentwearablesfetch.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/** 
- * @file llagentwearablesinitialfetch.h
- * @brief LLAgentWearablesInitialFetch class header file
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLAGENTWEARABLESINITIALFETCH_H
-#define LL_LLAGENTWEARABLESINITIALFETCH_H
-
-#include "llinventoryobserver.h"
-#include "llwearabletype.h"
-#include "lluuid.h"
-
-//--------------------------------------------------------------------
-// InitialWearablesFetch
-// 
-// This grabs contents from the COF and processes them.
-// The processing is handled in idle(), i.e. outside of done(),
-// to avoid gInventory.notifyObservers recursion.
-//--------------------------------------------------------------------
-class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
-{
-	LOG_CLASS(LLInitialWearablesFetch);
-
-public:
-	LLInitialWearablesFetch(const LLUUID& cof_id);
-	~LLInitialWearablesFetch();
-	virtual void done();
-
-	struct InitialWearableData
-	{
-		LLWearableType::EType mType;
-		LLUUID mItemID;
-		LLUUID mAssetID;
-		InitialWearableData(LLWearableType::EType type, LLUUID& itemID, LLUUID& assetID) :
-			mType(type),
-			mItemID(itemID),
-			mAssetID(assetID)
-		{}
-	};
-
-	void add(InitialWearableData &data);
-
-protected:
-	void processWearablesMessage();
-	void processContents();
-
-private:
-	typedef std::vector<InitialWearableData> initial_wearable_data_vec_t;
-	initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
-};
-
-#endif // LL_AGENTWEARABLESINITIALFETCH_H
-- 
cgit v1.2.3


From 2d7dd7db24fefe9dcd8bde83a92304936a5f77ed Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 1 Oct 2013 07:54:30 -0400
Subject: SH-3455 WIP - dead code removal

---
 indra/newview/llagentwearables.cpp | 2 +-
 indra/newview/llagentwearables.h   | 6 ------
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 5b18a45431..eda0ff71ba 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -655,7 +655,7 @@ void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type,
 
 	// Add a new one in the lost and found folder.
 	// (We used to overwrite the "not found" one, but that could potentially
-	// destory content.) JC
+	// destroy content.) JC
 	const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 	LLPointer<LLInventoryCallback> cb =
 		new AddWearableToAgentInventoryCallback(
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index a7b033a37d..8fb2783fff 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -214,12 +214,6 @@ private:
 	// Support classes
 	//--------------------------------------------------------------------------------
 private:
-	class createStandardWearablesAllDoneCallback : public LLRefCount
-	{
-	protected:
-		~createStandardWearablesAllDoneCallback();
-	};
-
 	class AddWearableToAgentInventoryCallback : public LLInventoryCallback
 	{
 	public:
-- 
cgit v1.2.3


From 230db3e83b4c018d381ad5f4fe77e7f7f384f397 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 4 Oct 2013 12:08:15 -0400
Subject: SH-3455 WIP

---
 indra/newview/llagentwearables.cpp |  40 --------
 indra/newview/llstartup.cpp        |   6 +-
 indra/newview/llviewermenu.cpp     |   1 +
 indra/newview/llvoavatar.cpp       |  11 ++-
 indra/newview/llvoavatarself.cpp   | 184 +------------------------------------
 indra/newview/llvoavatarself.h     |  11 +--
 6 files changed, 12 insertions(+), 241 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index eda0ff71ba..798b733efb 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -211,11 +211,6 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i
 
 	gAgentWearables.addWearabletoAgentInventoryDone(mType, mIndex, inv_item, mWearable);
 
-	if (mTodo & CALL_RECOVERDONE)
-	{
-		LLAppearanceMgr::instance().addCOFItemLink(inv_item);
-		gAgentWearables.recoverMissingWearableDone();
-	}
 	/*
 	 * Do this for every one in the loop
 	 */
@@ -640,39 +635,6 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
 	return getWearableFromItemID(item_id) != NULL;
 }
 
-// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the
-// database.  If for some reason, we can't load one of those assets, we can try to reconstruct it so that
-// the user isn't left without a shape, for example.  (We can do that only after the inventory has loaded.)
-void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type, U32 index)
-{
-	// Try to recover by replacing missing wearable with a new one.
-	LLNotificationsUtil::add("ReplacedMissingWearable");
-	lldebugs << "Wearable " << LLWearableType::getTypeLabel(type) << " could not be downloaded.  Replaced inventory item with default wearable." << llendl;
-	LLViewerWearable* new_wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
-
-	setWearable(type,index,new_wearable);
-	//new_wearable->writeToAvatar(TRUE);
-
-	// Add a new one in the lost and found folder.
-	// (We used to overwrite the "not found" one, but that could potentially
-	// destroy content.) JC
-	const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
-	LLPointer<LLInventoryCallback> cb =
-		new AddWearableToAgentInventoryCallback(
-			LLPointer<LLRefCount>(NULL),
-			type,
-			index,
-			new_wearable,
-			AddWearableToAgentInventoryCallback::CALL_RECOVERDONE);
-	addWearableToAgentInventory(cb, new_wearable, lost_and_found_id, TRUE);
-}
-
-void LLAgentWearables::recoverMissingWearableDone()
-{
-	gInventory.addChangedMask(LLInventoryObserver::LABEL, LLUUID::null);
-	gInventory.notifyObservers();
-}
-
 void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index)
 {
 	LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)wearable_type, wearable_index);
@@ -1071,8 +1033,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	// Start rendering & update the server
 	mWearablesLoaded = TRUE; 
 
-	// SUNSHINE CLEANUP - these checks for done never worked. Should they be modified?
-	//checkWearablesLoaded();
 	notifyLoadingFinished();
 
 	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 4be0f6b40b..239227b904 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2062,6 +2062,7 @@ bool idle_startup()
 		const F32 wearables_time = wearables_timer.getElapsedTimeF32();
 		const F32 MAX_WEARABLES_TIME = 10.f;
 
+#if 0
 		if (!gAgent.isGenderChosen() && isAgentAvatarValid())
 		{
 			// No point in waiting for clothing, we don't even
@@ -2077,6 +2078,7 @@ bool idle_startup()
 			LLStartUp::setStartupState( STATE_CLEANUP );
 			return TRUE;
 		}
+#endif
 		
 		display_startup();
 
@@ -2370,7 +2372,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 	msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair,	process_remove_name_value);
 	msg->setHandlerFuncFast(_PREHASH_AvatarAnimation,		process_avatar_animation);
 	msg->setHandlerFuncFast(_PREHASH_AvatarAppearance,		process_avatar_appearance);
-	msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatarSelf::processRebakeAvatarTextures);
 	msg->setHandlerFuncFast(_PREHASH_CameraConstraint,		process_camera_constraint);
 	msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse,		process_avatar_sit_response);
 	msg->setHandlerFunc("SetFollowCamProperties",			process_set_follow_cam_properties);
@@ -2444,9 +2445,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 	// msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
 	//					LLFloaterRate::processReputationIndividualReply);
 
-	//msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
-	//					LLAgentWearables::processAgentInitialWearablesUpdate );
-
 	msg->setHandlerFunc("ScriptControlChange",
 						LLAgent::processScriptControlChange );
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 49eb7dc94a..e1faf3b29b 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7719,6 +7719,7 @@ void handle_buy_currency_test(void*)
 	LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
 }
 
+// SUNSHINE CLEANUP - is only the request update at the end needed now?
 void handle_rebake_textures(void*)
 {
 	if (!isAgentAvatarValid()) return;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 49bbf97a23..df54f26ae7 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6856,7 +6856,7 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 	{
 		appearance_version = contents.mAppearanceVersion;
 	}
-	else // still not set, go with 0.
+	else // still not set, go with 1.
 	{
 		appearance_version = 1;
 	}
@@ -6866,7 +6866,6 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 	return true;
 }
 
-// SUNSHINE CLEANUP - if we can assume server baking, we can simplify some code here.
 //-----------------------------------------------------------------------------
 // processAvatarAppearance()
 //-----------------------------------------------------------------------------
@@ -6898,11 +6897,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 	llassert(appearance_version > 0);
+	if (appearance_version > 1)
+	{
+		llwarns << "unsupported appearance version " << appearance_version << ", discarding appearance message" << llendl;
+		return;
+	}
 
 	S32 this_update_cof_version = contents.mCOFVersion;
 	S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion;
 
-	// Only now that we have result of appearance_version can we decide whether to bail out.
 	if( isSelf() )
 	{
 		LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version
@@ -6941,7 +6944,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
-	// No backsies zone - if we get here, the message should be valid and usable, will process.
+	// No backsies zone - if we get here, the message should be valid and usable, will be processed.
 
 	// Note:
 	// RequestAgentUpdateAppearanceResponder::onRequestRequested()
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 498f8c8277..d7ff78d2a6 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -764,58 +764,6 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id)
 	}
 }
 
-//virtual
-U32  LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
-													 void **user_data,
-													 U32 block_num,
-													 const EObjectUpdateType update_type,
-													 LLDataPacker *dp)
-{
-	U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp);
-
-	// SUNSHINE CLEANUP - does this become relevant again if we don't
-	// have to wait for appearance message to tell us where bakes are
-	// coming from?
-
-#if 0
-	// DRANO - it's not clear this does anything useful. If we wait
-	// until an appearance message has been received, we already have
-	// the texture ids. If we don't wait, we don't yet know where to
-	// look for baked textures, because we haven't received the
-	// appearance version data from the appearance message. This looks
-	// like an old optimization that's incompatible with server-side
-	// texture baking.
-	
-	// FIXME DRANO - skipping in the case of !mFirstAppearanceMessageReceived prevents us from trying to
-	// load textures before we know where they come from (ie, from baking service or not);
-	// unknown impact on performance.
-	if (mInitialBakesLoaded == false && retval == 0x0 && mFirstAppearanceMessageReceived)
-	{
-		// call update textures to force the images to be created
-		updateMeshTextures();
-
-		// unpack the texture UUIDs to the texture slots
-		retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num);
-
-		// need to trigger a few operations to get the avatar to use the new bakes
-		for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
-		{
-			const LLAvatarAppearanceDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex;
-			LLUUID texture_id = getTEImage(te)->getID();
-			setNewBakedTexture(te, texture_id);
-			mInitialBakeIDs[i] = texture_id;
-		}
-
-		onFirstTEMessageReceived();
-
-		mInitialBakesLoaded = true;
-	}
-#endif
-
-	return retval;
-}
-
-
 void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index)
 {
 	if (te >= TEX_NUM_INDICES)
@@ -2492,81 +2440,6 @@ ETextureIndex LLVOAvatarSelf::getBakedTE( const LLViewerTexLayerSet* layerset )
 	return TEX_HEAD_BAKED;
 }
 
-
-void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid)
-{
-	ETextureIndex index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(i);
-	setNewBakedTexture(index, uuid);
-}
-
-
-//-----------------------------------------------------------------------------
-// setNewBakedTexture()
-// A new baked texture has been successfully uploaded and we can start using it now.
-//-----------------------------------------------------------------------------
-void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
-{
-	// SUNSHINE CLEANUP
-	// If we reinstate processUpdateMessage(), this needs to be updated for server-bake textures.
-	llassert(false);
-
-	// Baked textures live on other sims.
-	LLHost target_host = getObjectHost();	
-	setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) );
-	updateMeshTextures();
-	dirtyMesh();
-
-	LLVOAvatar::cullAvatarsByPixelArea();
-
-	/* switch(te)
-		case TEX_HEAD_BAKED:
-			llinfos << "New baked texture: HEAD" << llendl; */
-	const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(te);
-	if (texture_dict->mIsBakedTexture)
-	{
-		debugBakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish.
-		llinfos << "New baked texture: " << texture_dict->mName << " UUID: " << uuid <<llendl;
-	}
-	else
-	{
-		llwarns << "New baked texture: unknown te " << te << llendl;
-	}
-	
-	//	dumpAvatarTEs( "setNewBakedTexture() send" );
-	// RN: throttle uploads
-	if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
-	{
-		LLSD args;
-		args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
-		args["TIME"] = llformat("%d",(U32)mDebugSelfLoadTimer.getElapsedTimeF32());
-		if (isAllLocalTextureDataFinal())
-		{
-			LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args);
-			LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
-								<< "sec ]"
-								<< avString() 
-								<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
-								<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
-								<< " Notification " << "AvatarRezSelfBakedDoneNotification"
-								<< llendl;
-		}
-		else
-		{
-			args["STATUS"] = debugDumpAllLocalTextureDataInfo();
-			LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args);
-			LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
-								<< "sec ]"
-								<< avString() 
-								<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
-								<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
-								<< " Notification " << "AvatarRezSelfBakedUpdateNotification"
-								<< llendl;
-		}
-	}
-
-	outputRezDiagnostics();
-}
-
 // FIXME: This is not called consistently. Something may be broken.
 void LLVOAvatarSelf::outputRezDiagnostics() const
 {
@@ -2642,55 +2515,7 @@ void LLVOAvatarSelf::reportAvatarRezTime() const
 	// TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow.
 }
 
-// static
-void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
-{
-	LLUUID texture_id;
-	msg->getUUID("TextureData", "TextureID", texture_id);
-	if (!isAgentAvatarValid()) return;
-
-	// If this is a texture corresponding to one of our baked entries, 
-	// just rebake that layer set.
-	BOOL found = FALSE;
-
-	/* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] =
-			TEX_HEAD_BAKED,
-			TEX_UPPER_BAKED, */
-	for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
-		 iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
-		 ++iter)
-	{
-		const ETextureIndex index = iter->first;
-		const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
-		if (texture_dict->mIsBakedTexture)
-		{
-			if (texture_id == gAgentAvatarp->getTEImage(index)->getID())
-			{
-				LLViewerTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index);
-				if (layer_set)
-				{
-					llinfos << "TAT: rebake - matched entry " << (S32)index << llendl;
-					gAgentAvatarp->invalidateComposite(layer_set);
-					found = TRUE;
-					LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
-				}
-			}
-		}
-	}
-
-	// If texture not found, rebake all entries.
-	if (!found)
-	{
-		gAgentAvatarp->forceBakeAllTextures();
-	}
-	else
-	{
-		// Not sure if this is necessary, but forceBakeAllTextures() does it.
-		gAgentAvatarp->updateMeshTextures();
-	}
-}
-
-
+// SUNSHINE CLEANUP - not clear we need any of this, may be sufficient to request server appearance in llviewermenu.cpp:handle_rebake_textures()
 void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 {
 	llinfos << "TAT: forced full rebake. " << llendl;
@@ -2806,13 +2631,6 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch)
 	if (isAgentAvatarValid())
 	{
 		gAgentAvatarp->mIsEditingAppearance = false;
-		// SUNSHINE CLEANUP - should no longer happen
-		if (gAgentAvatarp->getRegion() && !gAgentAvatarp->getRegion()->getCentralBakeVersion())
-		{
-			// FIXME DRANO - move to sendAgentSetAppearance, make conditional on upload complete.
-			gAgentAvatarp->mUseLocalAppearance = false;
-		}
-
 		gAgentAvatarp->invalidateAll();
 
 		if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch)
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 7eaa239890..0eb80d1fad 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -103,12 +103,6 @@ public:
 	/*virtual*/ void updateVisualParams();
 	/*virtual*/ void idleUpdateAppearanceAnimation();
 
-	/*virtual*/ U32  processUpdateMessage(LLMessageSystem *mesgsys,
-													 void **user_data,
-													 U32 block_num,
-													 const EObjectUpdateType update_type,
-													 LLDataPacker *dp);
-
 private:
 	// helper function. Passed in param is assumed to be in avatar's parameter list.
 	BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight);
@@ -234,11 +228,8 @@ private:
 	//--------------------------------------------------------------------
 public:
 	LLAvatarAppearanceDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const;
-	// SUNSHINE CLEANUP - dead?
-	void				setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid);
-	void				setNewBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid);
+	// SUNSHINE CLEANUP - dead? or update to just call request appearance update?
 	void				forceBakeAllTextures(bool slam_for_debug = false);
-	static void			processRebakeAvatarTextures(LLMessageSystem* msg, void**);
 protected:
 	/*virtual*/ void	removeMissingBakedTextures();
 
-- 
cgit v1.2.3


From f20fadeafab79b940da7addecd21de2f0962ced5 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 8 Oct 2013 15:23:47 -0600
Subject: fix a texture issue that unpaused callbacks never get fired.

---
 indra/newview/llviewertexture.cpp | 19 +++++++++++++------
 indra/newview/llviewertexture.h   |  3 ++-
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 831551a0a7..5330c4da86 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1046,7 +1046,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	mLastReferencedSavedRawImageTime = 0.0f ;
 	mKeptSavedRawImageTime = 0.f ;
 	mLastCallBackActiveTime = 0.f;
-
+	mForceCallbackFetch = FALSE;
 	mInDebug = FALSE;
 
 	mFTType = FTT_UNKNOWN;
@@ -2281,6 +2281,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
 	}
 	mPauseLoadedCallBacks = FALSE ;
 	mLastCallBackActiveTime = sCurrentTime ;
+	mForceCallbackFetch = TRUE;
 	if(need_raw)
 	{
 		mSaveRawImage = TRUE ;
@@ -2321,6 +2322,7 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s
 bool LLViewerFetchedTexture::doLoadedCallbacks()
 {
 	static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds
+	static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds
 
 	if (mNeedsCreateTexture)
 	{
@@ -2525,6 +2527,9 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 		}
 	}
 
+	// Done with any raw image data at this point (will be re-created if we still have callbacks)
+	destroyRawImage();
+
 	//
 	// If we have no callbacks, take us off of the image callback list.
 	//
@@ -2532,10 +2537,13 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 	{
 		gTextureList.mCallbackList.erase(this);
 	}
+	else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching)
+	{
+		//wait for long enough but no fetching request issued, force one.
+		forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f);
+		mForceCallbackFetch = FALSE; //fire once.
+	}
 
-	// Done with any raw image data at this point (will be re-created if we still have callbacks)
-	destroyRawImage();
-	
 	return res;
 }
 
@@ -2774,9 +2782,8 @@ void LLViewerFetchedTexture::saveRawImage()
 }
 
 //force to refetch the texture to the discard level 
-void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard)
+void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time)
 {
-	F32 kept_time = 60.0; //seconds
 	if(mForceToSaveRawImage)
 	{
 		desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel);
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 31430c31e0..7e45fcaf4b 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -388,7 +388,7 @@ public:
 	BOOL        isCachedRawImageReady() const {return mCachedRawImageReady ;}
 	BOOL        isRawImageValid()const { return mIsRawImageValid ; }	
 	void        forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
-	void        forceToRefetchTexture(S32 desired_discard = 0);
+	void        forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
 	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
 	void        destroySavedRawImage() ;
 	LLImageRaw* getSavedRawImage() ;
@@ -423,6 +423,7 @@ private:
 	BOOL  mFullyLoaded;
 	BOOL  mInDebug;
 	BOOL  mInFastCacheList;
+	BOOL  mForceCallbackFetch;
 
 protected:		
 	std::string mLocalFileName;
-- 
cgit v1.2.3


From b486f6a72c94468f4667d364636d56ea545be188 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 11 Oct 2013 16:52:45 -0400
Subject: SH-4458 SH-3652 FIX Pants flare does not load properly upon an avatar
 returning

Viewer added a new callback when the avatar returned without resetting the
timer for last reference to the saved raw image. This created a time window
in which new callbacks could get cleared out due to the raw image getting destroyed.

Since the callback was removed, pants flare was not properly applied. Appears
to be working now.
---
 indra/newview/llviewertexture.cpp | 1 +
 indra/newview/llvoavatar.cpp      | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5330c4da86..5ab628ab2c 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2169,6 +2169,7 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
 		}
 	}
 	mLastCallBackActiveTime = sCurrentTime ;
+        mLastReferencedSavedRawImageTime = sCurrentTime;
 }
 
 void LLViewerFetchedTexture::clearCallbackEntryList()
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 93247a3625..110f571397 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6316,6 +6316,8 @@ void LLVOAvatar::updateMeshTextures()
 				// we'll consider it loaded and use it (rather than
 				// doing compositing).
 				useBakedTexture( baked_img->getID() );
+                                mLoadedCallbacksPaused |= !isVisible();
+                                checkTextureLoading();
 			}
 			else
 			{
@@ -6331,6 +6333,7 @@ void LLVOAvatar::updateMeshTextures()
 
                                // this could add paused texture callbacks
                                mLoadedCallbacksPaused |= paused; 
+                               checkTextureLoading();
 			}
 		}
 		else if (layerset && isUsingLocalAppearance())
-- 
cgit v1.2.3


From 20af6640d4077725034bd7e9d0e8982778cea09a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 15 Oct 2013 11:17:20 -0400
Subject: SH-3455 WIP - llstartup cleanup

---
 indra/newview/llagent.cpp          |  4 +--
 indra/newview/llagent.h            | 11 ++++----
 indra/newview/llagentwearables.cpp |  4 ---
 indra/newview/llappearancemgr.cpp  |  2 +-
 indra/newview/llstartup.cpp        | 58 ++++++++++++++++++++++++++------------
 5 files changed, 49 insertions(+), 30 deletions(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 29cf231d45..072e5a82b4 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -407,7 +407,7 @@ LLAgent::LLAgent() :
 	mNextFidgetTime(0.f),
 	mCurrentFidget(0),
 	mFirstLogin(FALSE),
-	mGenderChosen(FALSE),
+	mOutfitChosen(FALSE),
 	
 	mVoiceConnected(false),
 
@@ -1853,7 +1853,7 @@ BOOL LLAgent::needsRenderAvatar()
 		return FALSE;
 	}
 
-	return mShowAvatar && mGenderChosen;
+	return mShowAvatar && mOutfitChosen;
 }
 
 // TRUE if we need to render your own avatar's head.
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index d0a48207b5..f2a42347b7 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -161,12 +161,13 @@ public:
 	// Gender
 	//--------------------------------------------------------------------
 public:
-	// On the very first login, gender isn't chosen until the user clicks
-	// in a dialog.  We don't render the avatar until they choose.
-	BOOL 			isGenderChosen() const 	{ return mGenderChosen; }
-	void			setGenderChosen(BOOL b)	{ mGenderChosen = b; }
+	// On the very first login, outfit needs to be chosen by some
+	// mechanism, usually by loading the requested initial outfit.  We
+	// don't render the avatar until the choice is made.
+	BOOL 			isOutfitChosen() const 	{ return mOutfitChosen; }
+	void			setOutfitChosen(BOOL b)	{ mOutfitChosen = b; }
 private:
-	BOOL			mGenderChosen;
+	BOOL			mOutfitChosen;
 
 /**                    Identity
  **                                                                            **
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 798b733efb..96ce8d1f6d 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -175,10 +175,6 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
 {
 	llassert(avatar);
 	setAvatarAppearance(avatar);
-	gAgentWearables.notifyLoadingStarted();
-	callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(),
-						   boost::bind(&LLAppearanceMgr::updateAppearanceFromCOF,
-									   LLAppearanceMgr::getInstance(), true, true, no_op));
 }
 
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 0bf2527195..43ba66f8c5 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -4004,7 +4004,7 @@ public:
 			LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false);
 
 			// *TODOw: This may not be necessary if initial outfit is chosen already -- josh
-			gAgent.setGenderChosen(TRUE);
+			gAgent.setOutfitChosen(TRUE);
 		}
 
 		// release avatar picker keyboard focus
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 239227b904..09147afb23 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2020,7 +2020,7 @@ bool idle_startup()
 	{
 		display_startup();
 		F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
-
+		
 		// We now have an inventory skeleton, so if this is a user's first
 		// login, we can start setting up their clothing and avatar 
 		// appearance.  This helps to avoid the generic "Ruth" avatar in
@@ -2029,20 +2029,42 @@ bool idle_startup()
 			&& !sInitialOutfit.empty()    // registration set up an outfit
 			&& !sInitialOutfitGender.empty() // and a gender
 			&& isAgentAvatarValid()	  // can't wear clothes without object
-			&& !gAgent.isGenderChosen() ) // nothing already loading
+			&& !gAgent.isOutfitChosen()) // nothing already loading
 		{
 			// Start loading the wearables, textures, gestures
 			LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
 		}
+		// If not first login, we need to fetch COF contents and
+		// compute appearance from that.
+		if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isOutfitChosen())
+		{
+			gAgentWearables.notifyLoadingStarted();
+			callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(),
+								   boost::bind(&LLAppearanceMgr::updateAppearanceFromCOF,
+											   LLAppearanceMgr::getInstance(), true, true, no_op));
+			LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
+			gAgent.setOutfitChosen(TRUE);
+		}
 
 		display_startup();
 
 		// wait precache-delay and for agent's avatar or a lot longer.
-		if(((timeout_frac > 1.f) && isAgentAvatarValid())
-		   || (timeout_frac > 3.f))
+		if ((timeout_frac > 1.f) && isAgentAvatarValid())
 		{
 			LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
 		}
+		else if (timeout_frac > 10.f) 
+		{
+			// If we exceed the wait above while isAgentAvatarValid is
+			// not true yet, we will change startup state and
+			// eventually (once avatar does get created) wind up at
+			// the gender chooser. This should occur only in very
+			// unusual circumstances, so set the timeout fairly high
+			// to minimize mistaken hits here.
+			llwarns << "Wait for valid avatar state exceeded " 
+					<< timeout.getElapsedTimeF32() << " will invoke gender chooser" << llendl; 
+			LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
+		}
 		else
 		{
 			update_texture_fetch();
@@ -2062,12 +2084,11 @@ bool idle_startup()
 		const F32 wearables_time = wearables_timer.getElapsedTimeF32();
 		const F32 MAX_WEARABLES_TIME = 10.f;
 
-#if 0
-		if (!gAgent.isGenderChosen() && isAgentAvatarValid())
+		if (!gAgent.isOutfitChosen() && isAgentAvatarValid())
 		{
-			// No point in waiting for clothing, we don't even
-			// know what gender we are.  Pop a dialog to ask and
-			// proceed to draw the world. JC
+			// No point in waiting for clothing, we don't even know
+			// what outfit we want.  Pop up a gender chooser dialog to
+			// ask and proceed to draw the world. JC
 			//
 			// *NOTE: We might hit this case even if we have an
 			// initial outfit, but if the load hasn't started
@@ -2078,13 +2099,12 @@ bool idle_startup()
 			LLStartUp::setStartupState( STATE_CLEANUP );
 			return TRUE;
 		}
-#endif
 		
 		display_startup();
 
-		if (wearables_time > MAX_WEARABLES_TIME)
+		if (gAgent.isOutfitChosen() && (wearables_time > MAX_WEARABLES_TIME))
 		{
-			LLNotificationsUtil::add("ClothingLoading");
+			llwarns << "wearables_time " << wearables_time << "exceeded max wait of " << MAX_WEARABLES_TIME << llendl;
 			LLViewerStats::getInstance()->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG);
 			LLStartUp::setStartupState( STATE_CLEANUP );
 			return TRUE;
@@ -2096,7 +2116,7 @@ bool idle_startup()
 			if (isAgentAvatarValid()
 				&& gAgentAvatarp->isFullyLoaded())
 			{
-				//llinfos << "avatar fully loaded" << llendl;
+				LL_DEBUGS("Avatar") << "avatar fully loaded" << llendl;
 				LLStartUp::setStartupState( STATE_CLEANUP );
 				return TRUE;
 			}
@@ -2107,7 +2127,7 @@ bool idle_startup()
 			if ( gAgentWearables.areWearablesLoaded() )
 			{
 				// We have our clothing, proceed.
-				//llinfos << "wearables loaded" << llendl;
+				LL_DEBUGS("Avatar") << "wearables loaded" << llendl;
 				LLStartUp::setStartupState( STATE_CLEANUP );
 				return TRUE;
 			}
@@ -2601,9 +2621,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 		lldebugs << "initial outfit category id: " << cat_id << llendl;
 	}
 
-	// This is really misnamed -- it means we have started loading
-	// an outfit/shape that will give the avatar a gender eventually. JC
-	gAgent.setGenderChosen(TRUE);
+	gAgent.setOutfitChosen(TRUE);
 }
 
 //static
@@ -3364,7 +3382,11 @@ bool process_login_success_response()
 		flag = login_flags["gendered"].asString();
 		if(flag == "Y")
 		{
-			gAgent.setGenderChosen(TRUE);
+			// We don't care about this flag anymore; now base whether
+			// outfit is chosen on COF contents, initial outfit
+			// requested and available, etc.
+
+			//gAgent.setGenderChosen(TRUE);
 		}
 		
 		bool pacific_daylight_time = false;
-- 
cgit v1.2.3


From b42c70173c032d3362fce438a49100fbe7608a4d Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Wed, 16 Oct 2013 15:28:10 -0400
Subject: SH-3455 BUILDFIX Updating linux appearance utility to use the new
 refactor

Eliminated some unnecessary functions that the refactor took care of,
linux build should be fixed.
---
 autobuild.xml                           |  4 ++--
 indra/llappearance/llavatarappearance.h |  7 -------
 indra/llappearance/lltexglobalcolor.cpp |  5 -----
 indra/llappearance/lltexglobalcolor.h   |  2 --
 indra/llappearance/lltexlayerparams.cpp | 17 -----------------
 5 files changed, 2 insertions(+), 33 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index d8014a4ebe..1ea76edd7f 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>fa7b79adc95946028580a609e33d885e</string>
+              <string>bda18a1f808eb248d69ff14fa2c69862</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/279662/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130808.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/282464/arch/Linux/installer/llappearanceutility_source-0.1-linux-20131016.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 1e898026c0..1c212873f4 100755
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -219,12 +219,6 @@ public:
  **                                                                            **
  *******************************************************************************/
 
-	//--------------------------------------------------------------------
-	// Composites
-	//--------------------------------------------------------------------
-public:
-	virtual void	invalidateComposite(LLTexLayerSet* layerset) = 0;
-
 /********************************************************************************
  **                                                                            **
  **                    MESHES
@@ -263,7 +257,6 @@ public:
 	//--------------------------------------------------------------------
 public:
 	LLColor4		getGlobalColor(const std::string& color_name ) const;
-	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0;
 protected:
 	LLTexGlobalColor* mTexSkinColor;
 	LLTexGlobalColor* mTexHairColor;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
index 432e2e9f49..0e77b29cce 100755
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -103,11 +103,6 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
 	return new_param;
 }
 
-void LLTexParamGlobalColor::onGlobalColorChanged()
-{
-	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor);
-}
-
 //-----------------------------------------------------------------------------
 // LLTexGlobalColorInfo
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
index 1b0c91b5ca..02ba14a959 100755
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -74,8 +74,6 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
 public:
 	LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
-protected:
-	/*virtual*/ void onGlobalColorChanged();
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
 };
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index 80aded450d..5e9d9a658b 100755
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -178,7 +178,6 @@ void LLTexLayerParamAlpha::setWeight(F32 weight)
 		if ((mAvatarAppearance->getSex() & getSex()) &&
 			(mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
-			mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
 			mTexLayer->invalidateMorphMasks();
 		}
 	}
@@ -466,22 +465,6 @@ void LLTexLayerParamColor::setWeight(F32 weight)
 	if (cur_u8 != new_u8)
 	{
 		mCurWeight = new_weight;
-
-		if (info->mNumColors <= 0)
-		{
-			// This will happen when we set the default weight the first time.
-			return;
-		}
-
-		if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
-		{
-			onGlobalColorChanged();
-			if (mTexLayer)
-			{
-				mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
-			}
-		}
-
 //		llinfos << "param " << mName << " = " << new_weight << llendl;
 	}
 }
-- 
cgit v1.2.3


From dba221e0ac89b1505ddd3b896946286d5d1cf3d8 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 17 Oct 2013 16:12:37 -0400
Subject: SH-4160 WIP, build fix

---
 indra/llappearance/lltexlayerparams.cpp |  1 -
 indra/newview/llinventoryobserver.cpp   | 84 ---------------------------------
 indra/newview/llinventoryobserver.h     | 38 ---------------
 3 files changed, 123 deletions(-)

diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index 5e9d9a658b..36147f01e0 100755
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -456,7 +456,6 @@ void LLTexLayerParamColor::setWeight(F32 weight)
 		return;
 	}
 
-	const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
 	F32 min_weight = getMinWeight();
 	F32 max_weight = getMaxWeight();
 	F32 new_weight = llclamp(weight, min_weight, max_weight);
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 9db175ec2e..6042ab996d 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -465,38 +465,6 @@ void LLInventoryFetchComboObserver::startFetch()
 	mFetchDescendents->startFetch();
 }
 
-void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
-{
-	if (id.notNull())
-	{
-		mMIA.push_back(id);
-	}
-}
-
-void LLInventoryExistenceObserver::changed(U32 mask)
-{
-	// scan through the incomplete items and move or erase them as
-	// appropriate.
-	if (!mMIA.empty())
-	{
-		for (uuid_vec_t::iterator it = mMIA.begin(); it < mMIA.end(); )
-		{
-			LLViewerInventoryItem* item = gInventory.getItem(*it);
-			if (!item)
-			{
-				++it;
-				continue;
-			}
-			mExist.push_back(*it);
-			it = mMIA.erase(it);
-		}
-		if (mMIA.empty())
-		{
-			done();
-		}
-	}
-}
-
 void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 {
 	if(!(mask & LLInventoryObserver::ADD))
@@ -633,58 +601,6 @@ void LLInventoryCategoryAddedObserver::changed(U32 mask)
 	}
 }
 
-
-LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) :
-	mTransactionID(transaction_id)
-{
-}
-
-void LLInventoryTransactionObserver::changed(U32 mask)
-{
-	if (mask & LLInventoryObserver::ADD)
-	{
-		// This could be it - see if we are processing a bulk update
-		LLMessageSystem* msg = gMessageSystem;
-		if (msg->getMessageName()
-		   && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
-		{
-			// we have a match for the message - now check the
-			// transaction id.
-			LLUUID id;
-			msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
-			if (id == mTransactionID)
-			{
-				// woo hoo, we found it
-				uuid_vec_t folders;
-				uuid_vec_t items;
-				S32 count;
-				count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
-				S32 i;
-				for (i = 0; i < count; ++i)
-				{
-					msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
-					if (id.notNull())
-					{
-						folders.push_back(id);
-					}
-				}
-				count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
-				for (i = 0; i < count; ++i)
-				{
-					msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
-					if (id.notNull())
-					{
-						items.push_back(id);
-					}
-				}
-
-				// call the derived class the implements this method.
-				done(folders, items);
-			}
-		}
-	}
-}
-
 void LLInventoryCategoriesObserver::changed(U32 mask)
 {
 	if (!mCategoryMap.size())
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index aa1eae84d7..73288242eb 100755
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -151,25 +151,6 @@ protected:
 	LLInventoryFetchDescendentsObserver *mFetchDescendents;
 };
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryExistenceObserver
-//
-//   Used as a base class for doing something when all the
-//   observed item ids exist in the inventory somewhere.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryExistenceObserver : public LLInventoryObserver
-{
-public:
-	LLInventoryExistenceObserver() {}
-	/*virtual*/ void changed(U32 mask);
-
-	void watchItem(const LLUUID& id);
-protected:
-	virtual void done() = 0;
-	uuid_vec_t mExist;
-	uuid_vec_t mMIA;
-};
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryMovedObserver
 //
@@ -240,25 +221,6 @@ protected:
 	cat_vec_t	mAddedCategories;
 };
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryTransactionObserver
-//
-//   Base class for doing something when an inventory transaction completes.
-//   NOTE: This class is not quite complete. Avoid using unless you fix up its
-//   functionality gaps.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryTransactionObserver : public LLInventoryObserver
-{
-public:
-	LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
-	/*virtual*/ void changed(U32 mask);
-
-protected:
-	virtual void done(const uuid_vec_t& folders, const uuid_vec_t& items) = 0;
-
-	LLTransactionID mTransactionID;
-};
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryCompletionObserver
 //
-- 
cgit v1.2.3


From d560427a773625297ba351ca248aa73a9adb18ca Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 25 Oct 2013 14:47:04 -0400
Subject: SH-4571 WIP - send dummy wearables data on login, to help earlier
 release viewers that still rely on the presence of the message

---
 indra/newview/llagentwearables.cpp | 34 ++++++++++++++++++++++++++++++++++
 indra/newview/llagentwearables.h   |  5 +++++
 indra/newview/llstartup.cpp        |  2 ++
 3 files changed, 41 insertions(+)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 96ce8d1f6d..e4004f108c 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -765,6 +765,40 @@ void LLAgentWearables::createStandardWearables()
 	}
 }
 
+// We no longer need this message in the current viewer, but send
+// it for now to maintain compatibility with release viewers. Can
+// remove this function once the SH-3455 changesets are universally deployed.
+void LLAgentWearables::sendDummyAgentWearablesUpdate()
+{
+	LL_DEBUGS("Avatar") << "sendAgentWearablesUpdate()" << llendl;
+
+	// Send the AgentIsNowWearing 
+	gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
+	
+	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+	// Send 4 standardized nonsense item ids (same as returned by the modified sim, not that it especially matters).
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(1));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("db5a4e5f-9da3-44c8-992d-1181c5795498"));			
+
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(2));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("6969c7cc-f72f-4a76-a19b-c293cce8ce4f"));			
+
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(3));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("7999702b-b291-48f9-8903-c91dfb828408"));			
+
+	gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+	gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(4));
+	gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("566cb59e-ef60-41d7-bfa6-e0f293fbea40"));			
+
+	gAgent.sendReliableMessage();
+}
+
 void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
 {
 	LLUUID first_item_id = getWearableItemID((LLWearableType::EType)type, index);
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 8fb2783fff..a93b6d9241 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -164,6 +164,11 @@ public:
 	void			saveAllWearables();
 	void			revertWearable(const LLWearableType::EType type, const U32 index);
 
+	// We no longer need this message in the current viewer, but send
+	// it for now to maintain compatibility with release viewers. Can
+	// remove this function once the SH-3455 changesets are universally deployed.
+	void			sendDummyAgentWearablesUpdate();
+
 	//--------------------------------------------------------------------
 	// Static UI hooks
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 09147afb23..61d0855119 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2044,6 +2044,7 @@ bool idle_startup()
 											   LLAppearanceMgr::getInstance(), true, true, no_op));
 			LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
 			gAgent.setOutfitChosen(TRUE);
+			gAgentWearables.sendDummyAgentWearablesUpdate();
 		}
 
 		display_startup();
@@ -2622,6 +2623,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 	}
 
 	gAgent.setOutfitChosen(TRUE);
+	gAgentWearables.sendDummyAgentWearablesUpdate();
 }
 
 //static
-- 
cgit v1.2.3


From b1838f02bc6c4a052c68fc6bbf3106e3a796a1a2 Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Fri, 25 Oct 2013 16:43:36 -0400
Subject: SH-4572 FIX changing clothing parameters do not take effect in edit
 appearance

fix, new back-end utility and restoring the necessary functionality.
---
 autobuild.xml                           |  4 ++--
 indra/llappearance/llavatarappearance.h |  7 +++++++
 indra/llappearance/lltexglobalcolor.cpp |  5 +++++
 indra/llappearance/lltexglobalcolor.h   |  2 ++
 indra/llappearance/lltexlayerparams.cpp | 19 +++++++++++++++++++
 5 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 1ea76edd7f..599dd1e53b 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>bda18a1f808eb248d69ff14fa2c69862</string>
+              <string>43826f8f0a5ce5bcdbfed9ea0b6f4ebb</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/282464/arch/Linux/installer/llappearanceutility_source-0.1-linux-20131016.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/283022/arch/Linux/installer/llappearanceutility_source-0.1-linux-20131025.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 1c212873f4..1e898026c0 100755
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -219,6 +219,12 @@ public:
  **                                                                            **
  *******************************************************************************/
 
+	//--------------------------------------------------------------------
+	// Composites
+	//--------------------------------------------------------------------
+public:
+	virtual void	invalidateComposite(LLTexLayerSet* layerset) = 0;
+
 /********************************************************************************
  **                                                                            **
  **                    MESHES
@@ -257,6 +263,7 @@ public:
 	//--------------------------------------------------------------------
 public:
 	LLColor4		getGlobalColor(const std::string& color_name ) const;
+	virtual void	onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0;
 protected:
 	LLTexGlobalColor* mTexSkinColor;
 	LLTexGlobalColor* mTexHairColor;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
index 0e77b29cce..432e2e9f49 100755
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -103,6 +103,11 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
 	return new_param;
 }
 
+void LLTexParamGlobalColor::onGlobalColorChanged()
+{
+	mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor);
+}
+
 //-----------------------------------------------------------------------------
 // LLTexGlobalColorInfo
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
index 02ba14a959..1b0c91b5ca 100755
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -74,6 +74,8 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
 public:
 	LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+protected:
+	/*virtual*/ void onGlobalColorChanged();
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
 };
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index 36147f01e0..9608e2d391 100755
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -178,6 +178,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight)
 		if ((mAvatarAppearance->getSex() & getSex()) &&
 			(mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
 		{
+			mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
 			mTexLayer->invalidateMorphMasks();
 		}
 	}
@@ -464,6 +465,24 @@ void LLTexLayerParamColor::setWeight(F32 weight)
 	if (cur_u8 != new_u8)
 	{
 		mCurWeight = new_weight;
+
+                const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
+
+		if (info->mNumColors <= 0)
+		{
+			// This will happen when we set the default weight the first time.
+			return;
+		}
+
+		if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
+		{
+			onGlobalColorChanged();
+			if (mTexLayer)
+			{
+				mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
+			}
+		}
+
 //		llinfos << "param " << mName << " = " << new_weight << llendl;
 	}
 }
-- 
cgit v1.2.3


From 854aec1231ff3bd579ae6aec2302c8f9e1d7d958 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Mon, 28 Oct 2013 11:02:33 -0600
Subject: a try to fix the blurry texture problem.

---
 indra/newview/llviewertexture.cpp | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 1f42590884..f22074a8d6 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1889,7 +1889,7 @@ bool LLViewerFetchedTexture::updateFetch()
 			if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
 			{
 				// We finished but received no data
-				if (current_discard < 0)
+				if (getDiscardLevel() < 0)
 				{
 					if (getFTType() != FTT_MAP_TILE)
 					{
@@ -1906,8 +1906,17 @@ bool LLViewerFetchedTexture::updateFetch()
 				else
 				{
 					//llwarns << mID << ": Setting min discard to " << current_discard << llendl;
-					mMinDiscardLevel = current_discard;
-					desired_discard = current_discard;
+					if(current_discard >= 0)
+					{
+						mMinDiscardLevel = current_discard;
+						desired_discard = current_discard;
+					}
+					else
+					{
+						S32 dis_level = getDiscardLevel();
+						mMinDiscardLevel = dis_level;
+						desired_discard = dis_level;
+					}
 				}
 				destroyRawImage();
 			}
-- 
cgit v1.2.3


From 2dbf6569a77c37d7c7ecc684dd417ddbbb7c6bab Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 29 Oct 2013 15:50:22 -0400
Subject: SH-4586 WIP - possible fix for some COF mismatches

---
 indra/newview/llstartup.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 61d0855119..d440ba246a 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -313,6 +313,12 @@ void update_texture_fetch()
 	gTextureList.updateImages(0.10f);
 }
 
+void set_flags_and_update_appearance()
+{
+	LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
+	LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op);
+}
+
 // Returns false to skip other idle processing. Should only return
 // true when all initialization done.
 bool idle_startup()
@@ -2039,12 +2045,9 @@ bool idle_startup()
 		if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isOutfitChosen())
 		{
 			gAgentWearables.notifyLoadingStarted();
-			callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(),
-								   boost::bind(&LLAppearanceMgr::updateAppearanceFromCOF,
-											   LLAppearanceMgr::getInstance(), true, true, no_op));
-			LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
 			gAgent.setOutfitChosen(TRUE);
 			gAgentWearables.sendDummyAgentWearablesUpdate();
+			callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance);
 		}
 
 		display_startup();
-- 
cgit v1.2.3


From 6ed4c84a30e8f4044ccaedba114e13e07ae5c46d Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Wed, 30 Oct 2013 15:12:38 -0400
Subject: SH-4548 WIP Changes to avatar physics are propogated to observers

There was a broken linkage between the chest driver & driven parameters.
Fixed some cross-wearable flags to make sure the params are stored & linked
properly.

Will test to make sure params get properly transmitted next.
---
 indra/newview/character/avatar_lad.xml | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index e28bb6969a..594880a831 100755
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -4371,7 +4371,7 @@
      group="1"
      sex="female"
      name="Breast_Physics_UpDown_Driven"
-     wearable="shape"
+     wearable="physics"
      edit_group="driven"
      value_default="0"
      value_min="-3"
@@ -4384,7 +4384,7 @@
      group="1"
      sex="female"
      name="Breast_Physics_InOut_Driven"
-     wearable="shape"
+     wearable="physics"
      edit_group="driven"
      value_default="0"
      value_min="-1.25"
@@ -4397,7 +4397,6 @@
      group="1"
      name="Belly_Physics_Torso_UpDown_Driven"
      wearable="physics"
-     cross_wearable="true"
      edit_group="driven"
      value_default="0"
      value_min="-1"
@@ -4410,7 +4409,6 @@
      group="1"
      name="Breast_Physics_LeftRight_Driven"
      wearable="physics"
-     cross_wearable="true"
      edit_group="driven"
      value_default="0"
      value_min="-2"
-- 
cgit v1.2.3


From e26268add0d10cb7609afd9070f00d0331b78c4e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 1 Nov 2013 11:02:51 -0400
Subject: SH-4595 WIP - reworked descendents of LLInventoryAddedObserver to use
 gInventory.getAddedIDs(). LLInventoryAddedObserver isn't really needed
 anymore, but leaving it in as a debugging point at least for now.

---
 indra/llcommon/lluuid.h               | 13 ++++++++-----
 indra/newview/llinventorymodel.cpp    | 18 ++++++++++++------
 indra/newview/llinventorymodel.h      |  5 ++++-
 indra/newview/llinventoryobserver.cpp | 33 +++------------------------------
 indra/newview/llinventoryobserver.h   |  4 +---
 indra/newview/lllocationinputctrl.cpp |  6 ++----
 indra/newview/llpanelplaces.cpp       |  7 +++----
 indra/newview/llpanelplaces.h         |  2 +-
 indra/newview/llviewermessage.cpp     | 20 ++++++++++++++------
 9 files changed, 48 insertions(+), 60 deletions(-)

diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 7889828c85..82afc7225f 100755
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -131,10 +131,14 @@ public:
 };
 
 typedef std::vector<LLUUID> uuid_vec_t;
-
-
-// Helper structure for ordering lluuids in stl containers.
-// eg: 	std::map<LLUUID, LLWidget*, lluuid_less> widget_map;
+typedef std::set<LLUUID> uuid_set_t;
+
+// Helper structure for ordering lluuids in stl containers.  eg:
+// std::map<LLUUID, LLWidget*, lluuid_less> widget_map;
+//
+// (isn't this the default behavior anyway? I think we could
+// everywhere replace these with uuid_set_t, but someone should
+// verify.)
 struct lluuid_less
 {
 	bool operator()(const LLUUID& lhs, const LLUUID& rhs) const
@@ -144,7 +148,6 @@ struct lluuid_less
 };
 
 typedef std::set<LLUUID, lluuid_less> uuid_list_t;
-
 /*
  * Sub-classes for keeping transaction IDs and asset IDs
  * straight.
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index be1a396fff..e9bbf3a7cd 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1454,6 +1454,7 @@ void LLInventoryModel::notifyObservers()
 
 	mModifyMask = LLInventoryObserver::NONE;
 	mChangedItemIDs.clear();
+	mAddedItemIDs.clear();
 	mIsNotifyObservers = FALSE;
 }
 
@@ -1473,13 +1474,18 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
 	if (referent.notNull())
 	{
 		mChangedItemIDs.insert(referent);
-	}
+
+		if (mask & LLInventoryObserver::ADD)
+		{
+			mAddedItemIDs.insert(referent);
+		}
 	
-	// Update all linked items.  Starting with just LABEL because I'm
-	// not sure what else might need to be accounted for this.
-	if (mModifyMask & LLInventoryObserver::LABEL)
-	{
-		addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
+		// Update all linked items.  Starting with just LABEL because I'm
+		// not sure what else might need to be accounted for this.
+		if (mask & LLInventoryObserver::LABEL)
+		{
+			addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
+		}
 	}
 }
 
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 7afe1dea35..339740870d 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -73,7 +73,6 @@ public:
 
 	typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
 	typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
-	typedef std::set<LLUUID> changed_items_t;
 
 	class fetchInventoryResponder : public LLHTTPClient::Responder
 	{
@@ -472,7 +471,9 @@ public:
 	// been changed 'under the hood', but outside the control of the
 	// inventory. The next notify will include that notification.
 	void addChangedMask(U32 mask, const LLUUID& referent);
+	typedef uuid_set_t changed_items_t;
 	const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
+	const changed_items_t& getAddedIDs() const { return mAddedItemIDs; }
 protected:
 	// Updates all linked items pointing to this id.
 	void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
@@ -483,6 +484,8 @@ private:
 	// Variables used to track what has changed since the last notify.
 	U32 mModifyMask;
 	changed_items_t mChangedItemIDs;
+	changed_items_t mAddedItemIDs;
+	
 	
 	//--------------------------------------------------------------------
 	// Observers
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 6042ab996d..6181474e5b 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -541,34 +541,7 @@ void LLInventoryAddedObserver::changed(U32 mask)
 		return;
 	}
 
-	// *HACK: If this was in response to a packet off
-	// the network, figure out which item was updated.
-	LLMessageSystem* msg = gMessageSystem;
-
-	std::string msg_name = msg->getMessageName();
-	if (msg_name.empty())
-	{
-		return;
-	}
-	
-	// We only want newly created inventory items. JC
-	if ( msg_name != "UpdateCreateInventoryItem")
-	{
-		return;
-	}
-
-	LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
-	S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
-	for (S32 i = 0; i < num_blocks; ++i)
-	{
-		titem->unpackMessage(msg, _PREHASH_InventoryData, i);
-		if (!(titem->getUUID().isNull()))
-		{
-			//we don't do anything with null keys
-			mAdded.push_back(titem->getUUID());
-		}
-	}
-	if (!mAdded.empty())
+	if (!gInventory.getAddedIDs().empty())
 	{
 		done();
 	}
@@ -581,9 +554,9 @@ void LLInventoryCategoryAddedObserver::changed(U32 mask)
 		return;
 	}
 	
-	const LLInventoryModel::changed_items_t& changed_ids = gInventory.getChangedIDs();
+	const LLInventoryModel::changed_items_t& added_ids = gInventory.getAddedIDs();
 	
-	for (LLInventoryModel::changed_items_t::const_iterator cit = changed_ids.begin(); cit != changed_ids.end(); ++cit)
+	for (LLInventoryModel::changed_items_t::const_iterator cit = added_ids.begin(); cit != added_ids.end(); ++cit)
 	{
 		LLViewerInventoryCategory* cat = gInventory.getCategory(*cit);
 		
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index 73288242eb..c3cd0d761e 100755
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -190,13 +190,11 @@ private:
 class LLInventoryAddedObserver : public LLInventoryObserver
 {
 public:
-	LLInventoryAddedObserver() : mAdded() {}
+	LLInventoryAddedObserver() {}
 	/*virtual*/ void changed(U32 mask);
 
 protected:
 	virtual void done() = 0;
-
-	uuid_vec_t mAdded;
 };
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 5022dba934..0d5ecc4059 100755
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -107,8 +107,8 @@ public:
 private:
 	/*virtual*/ void done()
 	{
-		uuid_vec_t::const_iterator it = mAdded.begin(), end = mAdded.end();
-		for(; it != end; ++it)
+		const uuid_set_t& added = gInventory.getAddedIDs();
+		for (uuid_set_t::const_iterator it = added.begin(); it != added.end(); ++it)
 		{
 			LLInventoryItem* item = gInventory.getItem(*it);
 			if (!item || item->getType() != LLAssetType::AT_LANDMARK)
@@ -124,8 +124,6 @@ private:
 				mInput->onLandmarkLoaded(lm);
 			}
 		}
-
-		mAdded.clear();
 	}
 
 	LLLocationInputCtrl* mInput;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 730df2ea23..8cd54204e8 100755
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -168,8 +168,7 @@ public:
 protected:
 	/*virtual*/ void done()
 	{
-		mPlaces->showAddedLandmarkInfo(mAdded);
-		mAdded.clear();
+		mPlaces->showAddedLandmarkInfo(gInventory.getAddedIDs());
 	}
 
 private:
@@ -1100,9 +1099,9 @@ void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos)
 	updateVerbs();
 }
 
-void LLPanelPlaces::showAddedLandmarkInfo(const uuid_vec_t& items)
+void LLPanelPlaces::showAddedLandmarkInfo(const uuid_set_t& items)
 {
-	for (uuid_vec_t::const_iterator item_iter = items.begin();
+	for (uuid_set_t::const_iterator item_iter = items.begin();
 		 item_iter != items.end();
 		 ++item_iter)
 	{
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 85bdc2c4e1..b3bc248bd9 100755
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -69,7 +69,7 @@ public:
 	void changedGlobalPos(const LLVector3d &global_pos);
 
 	// Opens landmark info panel when agent creates or receives landmark.
-	void showAddedLandmarkInfo(const uuid_vec_t& items);
+	void showAddedLandmarkInfo(const uuid_set_t& items);
 
 	void setItem(LLInventoryItem* item);
 
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 167c33f3ff..64cbc82578 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1001,7 +1001,12 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
 protected:
 	/*virtual*/ void done()
 	{
-		for (uuid_vec_t::iterator it = mAdded.begin(); it != mAdded.end();)
+		uuid_vec_t added;
+		for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it)
+		{
+			added.push_back(*it);
+		}
+		for (uuid_vec_t::iterator it = added.begin(); it != added.end();)
 		{
 			const LLUUID& item_uuid = *it;
 			bool was_moved = false;
@@ -1023,13 +1028,12 @@ protected:
 
 			if (was_moved)
 			{
-				it = mAdded.erase(it);
+				it = added.erase(it);
 			}
 			else ++it;
 		}
 
-		open_inventory_offer(mAdded, "");
-		mAdded.clear();
+		open_inventory_offer(added, "");
 	}
  };
 
@@ -1038,8 +1042,12 @@ class LLOpenTaskGroupOffer : public LLInventoryAddedObserver
 protected:
 	/*virtual*/ void done()
 	{
-		open_inventory_offer(mAdded, "group_offer");
-		mAdded.clear();
+		uuid_vec_t added;
+		for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it)
+		{
+			added.push_back(*it);
+		}
+		open_inventory_offer(added, "group_offer");
 		gInventory.removeObserver(this);
 		delete this;
 	}
-- 
cgit v1.2.3


From 49956093db3ada36c04d01b905883067301a449a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 1 Nov 2013 14:37:38 -0400
Subject: SH-4595 WIP - removed UDP hooks from
 LLInventoryAddItemByAssetObserver

---
 indra/newview/llinventoryobserver.cpp | 20 ++++++--------------
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 6181474e5b..b025c0786e 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -478,20 +478,12 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 		return;
 	}
 
-	LLMessageSystem* msg = gMessageSystem;
-	if (!(msg->getMessageName() && (0 == strcmp(msg->getMessageName(), "UpdateCreateInventoryItem"))))
+	const uuid_set_t& added = gInventory.getAddedIDs();
+	for (uuid_set_t::iterator it = added.begin(); it != added.end(); ++it)
 	{
-		// this is not our message
-		return; // to prevent a crash. EXT-7921;
-	}
-
-	LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem;
-	S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
-	for(S32 i = 0; i < num_blocks; ++i)
-	{
-		item->unpackMessage(msg, _PREHASH_InventoryData, i);
+		LLInventoryItem *item = gInventory.getItem(*it);
 		const LLUUID& asset_uuid = item->getAssetUUID();
-		if (item->getUUID().notNull() && asset_uuid.notNull())
+		if (item && item->getUUID().notNull() && asset_uuid.notNull())
 		{
 			if (isAssetWatched(asset_uuid))
 			{
@@ -500,11 +492,11 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 			}
 		}
 	}
-
+	
 	if (mAddedItems.size() == mWatchedAssets.size())
 	{
-		done();
 		LL_DEBUGS("Inventory_Move") << "All watched items are added & processed." << LL_ENDL;
+		done();
 		mAddedItems.clear();
 
 		// Unable to clean watched items here due to somebody can require to check them in current frame.
-- 
cgit v1.2.3


From 6ea320198afcd3080fd7fcdfcb5829b5e8ef2c31 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 4 Nov 2013 15:55:04 -0500
Subject: SH-4595 WIP - use new LLInventoryObserver::CREATE flag to distinguish
 newly created items from existing ones being added to inventory.

---
 indra/newview/llinventorymodel.cpp    | 6 +++---
 indra/newview/llinventorymodel.h      | 2 +-
 indra/newview/llinventoryobserver.cpp | 4 ++--
 indra/newview/llinventoryobserver.h   | 1 +
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index e9bbf3a7cd..1ad70492ca 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -774,9 +774,8 @@ bool LLInventoryModel::isInventoryUsable() const
 // Calling this method with an inventory item will either change an
 // existing item with a matching item_id, or will add the item to the
 // current inventory.
-U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
+U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
 {
-	U32 mask = LLInventoryObserver::NONE;
 	if(item->getUUID().isNull())
 	{
 		return mask;
@@ -2652,10 +2651,11 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account)
 	}
 
 	U32 changes = 0x0;
+	U32 mask = account ? LLInventoryObserver::CREATE : 0x0;
 	//as above, this loop never seems to loop more than once per call
 	for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
 	{
-		changes |= gInventory.updateItem(*it);
+		changes |= gInventory.updateItem(*it, mask);
 	}
 	gInventory.notifyObservers();
 	gViewerWindow->getWindow()->decBusyCount();
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 339740870d..779319fa67 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -298,7 +298,7 @@ public:
 	//    NOTE: In usage, you will want to perform cache accounting
 	//    operations in LLInventoryModel::accountForUpdate() or
 	//    LLViewerInventoryItem::updateServer() before calling this method.
-	U32 updateItem(const LLViewerInventoryItem* item);
+	U32 updateItem(const LLViewerInventoryItem* item, U32 mask = 0);
 
 	// Change an existing item with the matching id or add
 	// the category. No notifcation will be sent to observers. This
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index b025c0786e..011686bfdd 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -467,7 +467,7 @@ void LLInventoryFetchComboObserver::startFetch()
 
 void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 {
-	if(!(mask & LLInventoryObserver::ADD))
+	if(!(mask & LLInventoryObserver::ADD) || !(mask & LLInventoryObserver::CREATE))
 	{
 		return;
 	}
@@ -528,7 +528,7 @@ bool LLInventoryAddItemByAssetObserver::isAssetWatched( const LLUUID& asset_id )
 
 void LLInventoryAddedObserver::changed(U32 mask)
 {
-	if (!(mask & LLInventoryObserver::ADD))
+	if (!(mask & LLInventoryObserver::ADD) || !(mask & LLInventoryObserver::CREATE))
 	{
 		return;
 	}
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index c3cd0d761e..dd30513844 100755
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -58,6 +58,7 @@ public:
 		GESTURE 		= 64,
 		REBUILD 		= 128, 	// Item UI changed (e.g. item type different)
 		SORT 			= 256, 	// Folder needs to be resorted.
+		CREATE			= 512,  // With ADD, item has just been created.
 		ALL 			= 0xffffffff
 	};
 	LLInventoryObserver();
-- 
cgit v1.2.3


From 19cebb8a2998026766171c08849f0018b846742f Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 6 Nov 2013 17:21:11 -0500
Subject: SH-4595 WIP

---
 indra/newview/lllocationinputctrl.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 0d5ecc4059..7b97b26a37 100755
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -140,7 +140,7 @@ public:
 private:
 	/*virtual*/ void changed(U32 mask)
 	{
-		if (mask & (~(LLInventoryObserver::LABEL|LLInventoryObserver::INTERNAL|LLInventoryObserver::ADD)))
+		if (mask & (~(LLInventoryObserver::LABEL|LLInventoryObserver::INTERNAL|LLInventoryObserver::ADD|LLInventoryObserver::CREATE)))
 		{
 			mInput->updateAddLandmarkButton();
 		}
-- 
cgit v1.2.3


From 2b8dc4d80c973770256d0d765f5d8f4f51cf9d57 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 7 Nov 2013 10:18:50 -0700
Subject: fix for SH-3959: Make sure baked textures cache and load from cache
 correctly.

---
 indra/newview/lltexturefetch.cpp | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 70e2c0f2dc..7d17aacfe7 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1205,9 +1205,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 																		  offset, size, responder);
 				mCacheReadTimer.reset();
 			}
-/* SH-3980 - disabling caching of server bakes until we can fix the blurring problems */
-/*			else if ((mUrl.empty()||mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache()) */
-			else if (mUrl.empty() && mFetcher->canLoadFromCache())
+			else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache())
 			{
 				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
 
@@ -1343,12 +1341,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				mCanUseHTTP = false;
 			}
 		}
-#if 0 /* SH-3980 - disabling caching of server bakes until we can fix the blurring problems */
-		if (mFTType == FTT_SERVER_BAKE)
+		else if (mFTType == FTT_SERVER_BAKE)
 		{
 			mWriteToCacheState = CAN_WRITE;
 		}
-#endif
+
 		if (mCanUseHTTP && !mUrl.empty())
 		{
 			setState(WAIT_HTTP_RESOURCE);
-- 
cgit v1.2.3


From 5fc3066bdb3921203dfdb085b2690fd2d79cf350 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 7 Nov 2013 15:36:45 -0700
Subject: add some debug code for possible gray baked avatar textures

---
 indra/newview/llviewertexture.cpp | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index f22074a8d6..fdbf2b015d 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2345,6 +2345,15 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 	}	
 	if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching)
 	{
+		if (mFTType == FTT_SERVER_BAKE)
+		{
+			//output some debug info
+			llinfos << "baked texture: " << mID << "clears all call backs due to inactivity." << llendl;
+			llinfos << mUrl << llendl;
+			llinfos << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() <<
+				" Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << llendl;
+		}
+
 		clearCallbackEntryList() ; //remove all callbacks.
 		return false ;
 	}
@@ -2353,6 +2362,13 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 	
 	if (isMissingAsset())
 	{
+		if (mFTType == FTT_SERVER_BAKE)
+		{
+			//output some debug info
+			llinfos << "baked texture: " << mID << "is missing." << llendl;
+			llinfos << mUrl << llendl;
+		}
+
 		for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
 			iter != mLoadedCallbackList.end(); )
 		{
-- 
cgit v1.2.3


From 9fe7ec50e0cf4d743b05e335ee27d6fb7fbe37b7 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 12 Nov 2013 12:49:51 -0500
Subject: SH-4030 FIX

---
 indra/newview/lltexturefetch.cpp | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
 mode change 100644 => 100755 indra/newview/lltexturefetch.cpp

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
old mode 100644
new mode 100755
index 7d17aacfe7..4b9db53bc8
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2582,7 +2582,18 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 
 	S32 desired_size;
 	std::string exten = gDirUtilp->getExtension(url);
-	if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
+	if (f_type == FTT_SERVER_BAKE)
+	{
+		// SH-4030: This case should be redundant with the following one, just
+		// breaking it out here to clarify that it's intended behavior.
+		llassert(!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C));
+
+		// Do full requests for baked textures to reduce interim blurring.
+		LL_DEBUGS("Texture") << "full request for " << id << " texture is FTT_SERVER_BAKE" << llendl;
+		desired_size = MAX_IMAGE_DATA_SIZE;
+		desired_discard = 0;
+	}
+	else if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
 	{
 		LL_DEBUGS("Texture") << "full request for " << id << " exten is not J2C: " << exten << llendl;
 		// Only do partial requests for J2C at the moment
-- 
cgit v1.2.3


From c1f60e7f2fe1775d8ca5f79af23579ac8a1fd851 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 15 Nov 2013 13:33:31 -0500
Subject: SH-4621 WIP

---
 indra/newview/llfriendcard.cpp     |  3 ++-
 indra/newview/llinventorymodel.cpp | 28 +++++++++++++++++++++++++---
 indra/newview/llinventorymodel.h   |  2 ++
 indra/newview/llstartup.cpp        |  9 +++++++++
 4 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index a6be604222..01f70d4b57 100755
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -38,6 +38,7 @@
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llviewerinventory.h"
 #include "llinventorymodel.h"
+#include "llcallbacklist.h"
 
 // Constants;
 
@@ -154,7 +155,7 @@ void LLInitialFriendCardsFetch::done()
 	// This observer is no longer needed.
 	gInventory.removeObserver(this);
 
-	mCheckFolderCallback();
+	doOnIdleOneTime(mCheckFolderCallback);
 
 	delete this;
 }
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 1ad70492ca..3dbc1ae288 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1467,6 +1467,19 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
 		// (which is in the process of processing the list of items marked for change).
 		// This means the change may fail to be processed.
 		llwarns << "Adding changed mask within notify observers!  Change will likely be lost." << llendl;
+		LLViewerInventoryItem *item = getItem(referent);
+		if (item)
+		{
+			llwarns << "Item " << item->getName() << llendl;
+		}
+		else
+		{
+			LLViewerInventoryCategory *cat = getCategory(referent);
+			if (cat)
+			{
+				llwarns << "Category " << cat->getName() << llendl;
+			}
+		}
 	}
 	
 	mModifyMask |= mask; 
@@ -2344,9 +2357,10 @@ void LLInventoryModel::buildParentChildMap()
 			// The inv tree is built.
 			mIsAgentInvUsable = true;
 
-			llinfos << "Inventory initialized, notifying observers" << llendl;
-			addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
-			notifyObservers();
+			// notifyObservers() has been moved to
+			// llstartup/idle_startup() after this func completes.
+			// Allows some system categories to be created before
+			// observers start firing.
 		}
 	}
 
@@ -2356,6 +2370,14 @@ void LLInventoryModel::buildParentChildMap()
 	}
 }
 
+void LLInventoryModel::createCommonSystemCategories()
+{
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH,true);
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true);
+	gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true);
+}
+
 struct LLUUIDAndName
 {
 	LLUUIDAndName() {}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 779319fa67..ab8bbac6d8 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -134,6 +134,8 @@ public:
 	// during authentication. Returns true if everything parsed.
 	bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
 	void buildParentChildMap(); // brute force method to rebuild the entire parent-child relations
+	void createCommonSystemCategories();
+	
 	// Call on logout to save a terse representation.
 	void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
 private:
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d440ba246a..9f0abd858e 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1779,6 +1779,15 @@ bool idle_startup()
 		// This method MUST be called before gInventory.findCategoryUUIDForType because of 
 		// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
 		gInventory.buildParentChildMap();
+		gInventory.createCommonSystemCategories();
+
+		// It's debatable whether this flag is a good idea - sets all
+		// bits, and in general it isn't true that inventory
+		// initialization generates all types of changes. Maybe add an
+		// INITIALIZE mask bit instead?
+		gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
+		gInventory.notifyObservers();
+		
 		display_startup();
 
 		//all categories loaded. lets create "My Favorites" category
-- 
cgit v1.2.3


From 8179175e6e6078fab9dc16cf02b5ee744955cd7d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 18 Nov 2013 13:19:43 -0500
Subject: SH-4578 WIP - cleaner folder version accounting

---
 indra/newview/llappearancemgr.cpp   |  7 +++++++
 indra/newview/llinventorymodel.cpp  | 30 +++---------------------------
 indra/newview/llviewerinventory.cpp | 13 +++++++++++++
 indra/newview/llviewerinventory.h   |  2 ++
 4 files changed, 25 insertions(+), 27 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 43ba66f8c5..f6c9bf6953 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2124,6 +2124,13 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 	dumpItemArray(wear_items,"asset_dump: wear_item");
 	dumpItemArray(obj_items,"asset_dump: obj_item");
 
+	LLViewerInventoryCategory *cof = gInventory.getCategory(current_outfit_id);
+	if (!gInventory.isCategoryComplete(current_outfit_id))
+	{
+		llwarns << "COF info is not complete. Version " << cof->getVersion()
+				<< " descendent_count " << cof->getDescendentCount()
+				<< " viewer desc count " << cof->getViewerDescendentCount() << llendl;
+	}
 	if(!wear_items.count())
 	{
 		LLNotificationsUtil::add("CouldNotPutOnOutfit");
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 3dbc1ae288..52b6e4bf3b 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -105,17 +105,7 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 		if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
 		{
 			S32 descendents_server = c->getDescendentCount();
-			LLInventoryModel::cat_array_t* cats;
-			LLInventoryModel::item_array_t* items;
-			mModel->getDirectDescendentsOf(
-				c->getUUID(),
-				cats,
-				items);
-			S32 descendents_actual = 0;
-			if(cats && items)
-			{
-				descendents_actual = cats->count() + items->count();
-			}
+			S32 descendents_actual = c->getViewerDescendentCount();
 			if(descendents_server == descendents_actual)
 			{
 				mCachedCatIDs.insert(c->getUUID());
@@ -1717,14 +1707,7 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
 		if(version != LLViewerInventoryCategory::VERSION_UNKNOWN)
 		{
 			S32 descendents_server = cat->getDescendentCount();
-			LLInventoryModel::cat_array_t* cats;
-			LLInventoryModel::item_array_t* items;
-			getDirectDescendentsOf(update.mCategoryID, cats, items);
-			S32 descendents_actual = 0;
-			if(cats && items)
-			{
-				descendents_actual = cats->count() + items->count();
-			}
+			S32 descendents_actual = cat->getViewerDescendentCount();
 			if(descendents_server == descendents_actual)
 			{
 				descendents_actual += update.mDescendentDelta;
@@ -1821,14 +1804,7 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
 	if(cat && (cat->getVersion()!=LLViewerInventoryCategory::VERSION_UNKNOWN))
 	{
 		S32 descendents_server = cat->getDescendentCount();
-		LLInventoryModel::cat_array_t* cats;
-		LLInventoryModel::item_array_t* items;
-		getDirectDescendentsOf(cat_id, cats, items);
-		S32 descendents_actual = 0;
-		if(cats && items)
-		{
-			descendents_actual = cats->count() + items->count();
-		}
+		S32 descendents_actual = cat->getViewerDescendentCount();
 		if(descendents_server == descendents_actual)
 		{
 			return true;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index b6a5534815..2d9fb7d773 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -701,6 +701,19 @@ bool LLViewerInventoryCategory::fetch()
 	return false;
 }
 
+S32 LLViewerInventoryCategory::getViewerDescendentCount() const
+{
+	LLInventoryModel::cat_array_t* cats;
+	LLInventoryModel::item_array_t* items;
+	gInventory.getDirectDescendentsOf(getUUID(), cats, items);
+	S32 descendents_actual = 0;
+	if(cats && items)
+	{
+		descendents_actual = cats->count() + items->count();
+	}
+	return descendents_actual;
+}
+
 bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp)
 {
 	// *NOTE: This buffer size is hard coded into scanf() below.
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index c82c2b6fbe..2e662d1730 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -217,6 +217,8 @@ public:
 	enum { DESCENDENT_COUNT_UNKNOWN = -1 };
 	S32 getDescendentCount() const { return mDescendentCount; }
 	void setDescendentCount(S32 descendents) { mDescendentCount = descendents; }
+	// How many descendents do we currently have information for in the InventoryModel?
+	S32 getViewerDescendentCount() const;
 
 	// file handling on the viewer. These are not meant for anything
 	// other than caching.
-- 
cgit v1.2.3


From d26ea73ce8e6c76517e836316150ca76f5f925d9 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 18 Nov 2013 16:03:30 -0500
Subject: SH-4625 FIX - changed a warning that didn't really indicate a problem
 to an info statement

---
 indra/newview/llinventorymodel.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 52b6e4bf3b..6b1bf69b5e 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -3704,7 +3704,7 @@ bool LLInventoryModel::validate() const
 	
 	if (cat_lock > 0 || item_lock > 0)
 	{
-		llwarns << "Found locks on some categories: sub-cat arrays "
+		llinfos << "Found locks on some categories: sub-cat arrays "
 				<< cat_lock << ", item arrays " << item_lock << llendl;
 	}
 	if (desc_unknown_count != 0)
-- 
cgit v1.2.3


From 0384d579726e61b4239880df9fddb502afe65f5a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 20 Nov 2013 16:21:34 -0500
Subject: SH-4611 WIP

---
 indra/newview/lltexturefetch.cpp | 78 +++++++++++++++++++++-------------------
 indra/newview/lltexturefetch.h   |  7 ++--
 2 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 4b9db53bc8..a86cf1fd4b 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1326,6 +1326,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				std::string http_url = region->getHttpUrl() ;
 				if (!http_url.empty())
 				{
+					if (mFTType != FTT_DEFAULT)
+					{
+						llwarns << "trying to seek a non-default texture on the sim. Bad!" << llendl;
+					}
 					setUrl(http_url + "/?texture_id=" + mID.asString().c_str());
 					mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.
 				}
@@ -1814,7 +1818,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0)
 				{
 					// Cache file should be deleted, try again
-// 					llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl;
+ 					llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl;
 					llassert_always(mDecodeHandle == 0);
 					mFormattedImage = NULL;
 					++mRetryAttempt;
@@ -2565,7 +2569,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 
 	if (f_type == FTT_SERVER_BAKE)
 	{
-		LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl;
+		LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << " type " << f_type << llendl;
 	}
 	LLTextureFetchWorker* worker = getWorker(id) ;
 	if (worker)
@@ -4105,7 +4109,7 @@ LLTextureFetchDebugger::~LLTextureFetchDebugger()
 
 void LLTextureFetchDebugger::init()
 {
-	mState = IDLE;
+	setDebuggerState(IDLE);
 	
 	mCacheReadTime = -1.f;
 	mCacheWriteTime = -1.f;
@@ -4203,7 +4207,7 @@ void LLTextureFetchDebugger::startDebug()
 	//clear the current fetching queue
 	gTextureList.clearFetchingRequests();
 
-	mState = START_DEBUG;
+	setDebuggerState(START_DEBUG);
 }
 
 bool LLTextureFetchDebugger::processStartDebug(F32 max_time)
@@ -4278,7 +4282,7 @@ void LLTextureFetchDebugger::tryToStopDebug()
 
 	//clear the current debug work
 	S32 size = mFetchingHistory.size();
-	switch(mState)
+	switch(mDebuggerState)
 	{
 	case READ_CACHE:		
 		for(S32 i = 0 ; i < size; i++)
@@ -4351,7 +4355,7 @@ void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
 
 	if(mFreezeHistory)
 	{
-		if(mState == REFETCH_VIS_CACHE || mState == REFETCH_VIS_HTTP)
+		if(mDebuggerState == REFETCH_VIS_CACHE || mDebuggerState == REFETCH_VIS_HTTP)
 		{
 			mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
 			mRefetchedVisData += worker->mFormattedImage->getDataSize();
@@ -4396,9 +4400,9 @@ void LLTextureFetchDebugger::unlockCache()
 void LLTextureFetchDebugger::debugCacheRead()
 {
 	lockCache();
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 	mTimer.reset();
-	mState = READ_CACHE;
+	setDebuggerState(READ_CACHE);
 	mCacheReadTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
@@ -4432,9 +4436,9 @@ void LLTextureFetchDebugger::debugCacheWrite()
 	clearCache();
 
 	lockCache();
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 	mTimer.reset();
-	mState = WRITE_CACHE;
+	setDebuggerState(WRITE_CACHE);
 	mCacheWriteTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
@@ -4461,9 +4465,9 @@ void LLTextureFetchDebugger::unlockDecoder()
 void LLTextureFetchDebugger::debugDecoder()
 {
 	lockDecoder();
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 	mTimer.reset();
-	mState = DECODING;
+	setDebuggerState(DECODING);
 	mDecodingTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
@@ -4482,7 +4486,7 @@ void LLTextureFetchDebugger::debugDecoder()
 
 void LLTextureFetchDebugger::debugHTTP()
 {
-	llassert_always(mState == IDLE);
+	llassert_always(mDebuggerState == IDLE);
 
 	LLViewerRegion* region = gAgent.getRegion();
 	if (!region)
@@ -4499,7 +4503,7 @@ void LLTextureFetchDebugger::debugHTTP()
 	}
 	
 	mTimer.reset();
-	mState = HTTP_FETCHING;
+	setDebuggerState(HTTP_FETCHING);
 	mHTTPTime = -1.f;
 	
 	S32 size = mFetchingHistory.size();
@@ -4579,8 +4583,8 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
 
 void LLTextureFetchDebugger::debugGLTextureCreation()
 {
-	llassert_always(mState == IDLE);
-	mState = GL_TEX;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(GL_TEX);
 	mTempTexList.clear();
 
 	S32 size = mFetchingHistory.size();
@@ -4701,8 +4705,8 @@ void LLTextureFetchDebugger::scanRefetchList()
 
 void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_VIS_CACHE;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_VIS_CACHE);
 
 	clearTextures();
 	mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
@@ -4716,8 +4720,8 @@ void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
 
 void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_VIS_HTTP;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_VIS_HTTP);
 
 	clearTextures();
 	mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
@@ -4731,8 +4735,8 @@ void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
 
 void LLTextureFetchDebugger::debugRefetchAllFromCache()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_ALL_CACHE;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_ALL_CACHE);
 
 	clearTextures();
 	makeRefetchList();
@@ -4748,8 +4752,8 @@ void LLTextureFetchDebugger::debugRefetchAllFromCache()
 
 void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
 {
-	llassert_always(mState == IDLE);
-	mState = REFETCH_ALL_HTTP;
+	llassert_always(mDebuggerState == IDLE);
+	setDebuggerState(REFETCH_ALL_HTTP);
 
 	clearTextures();
 	makeRefetchList();
@@ -4765,19 +4769,19 @@ void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
 
 bool LLTextureFetchDebugger::update(F32 max_time)
 {
-	switch(mState)
+	switch(mDebuggerState)
 	{
 	case START_DEBUG:
 		if(processStartDebug(max_time))
 		{
-			mState = IDLE;
+			setDebuggerState(IDLE);
 		}
 		break;
 	case READ_CACHE:
 		if(!mTextureCache->update(1))
 		{
 			mCacheReadTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			unlockCache();
 		}
 		break;
@@ -4785,7 +4789,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if(!mTextureCache->update(1))
 		{
 			mCacheWriteTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			unlockCache();
 		}
 		break;
@@ -4793,7 +4797,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if(!mImageDecodeThread->update(1))
 		{
 			mDecodingTime =  mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			unlockDecoder();
 		}
 		break;
@@ -4803,13 +4807,13 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
 		{
 			mHTTPTime =  mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 		}
 		break;
 	case GL_TEX:
 		if(processGLCreation(max_time))
 		{
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mTempTexList.clear();
 		}
 		break;
@@ -4817,7 +4821,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
 			mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 		}
@@ -4826,7 +4830,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
 			mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 		}
@@ -4843,7 +4847,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 			}
 
 			mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE; 
+			setDebuggerState(IDLE); 
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 			mRefetchList.clear();
@@ -4855,7 +4859,7 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
 			mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ;
-			mState = IDLE;
+			setDebuggerState(IDLE);
 			mFetcher->lockFetcher(true);
 			mFetcher->resetLoadSource();
 			mRefetchList.clear();
@@ -4863,11 +4867,11 @@ bool LLTextureFetchDebugger::update(F32 max_time)
 		}
 		break;
 	default:
-		mState = IDLE;
+		setDebuggerState(IDLE);
 		break;
 	}
 
-	return mState == IDLE;
+	return mDebuggerState == IDLE;
 }
 
 void LLTextureFetchDebugger::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 237912cde7..5c23f3bbc0 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -479,8 +479,9 @@ private:
 
 	typedef std::map<LLCore::HttpHandle, S32> handle_fetch_map_t;
 	handle_fetch_map_t mHandleToFetchIndex;
-	
-	e_debug_state mState;
+
+	void setDebuggerState(e_debug_state new_state) { mDebuggerState = new_state; }
+	e_debug_state mDebuggerState;
 	
 	F32 mCacheReadTime;
 	F32 mCacheWriteTime;
@@ -553,7 +554,7 @@ public:
 	void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux);
 	void callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response);
 
-	e_debug_state getState()             {return mState;}
+	e_debug_state getState()             {return mDebuggerState;}
 	S32  getNumFetchedTextures()         {return mNumFetchedTextures;}
 	S32  getNumFetchingRequests()        {return mFetchingHistory.size();}
 	S32  getNumCacheHits()               {return mNumCacheHits;}
-- 
cgit v1.2.3


From 8f4c4db90fdafc86efb64318e611d00aae662ab1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Sat, 23 Nov 2013 09:37:09 -0500
Subject: SH-4611 FIX - use an observer to scroll after category rename
 completes

---
 indra/llui/llfolderview.cpp           |  3 ++-
 indra/newview/llinventorybridge.cpp   | 37 +++++++++++++++++++++++++++++++++++
 indra/newview/llinventoryobserver.cpp | 21 ++++++++++++++++++++
 indra/newview/llinventoryobserver.h   | 18 +++++++++++++++++
 4 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index f32a52e6c6..ff5c2d0849 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -701,8 +701,9 @@ void LLFolderView::finishRenamingItem( void )
 
 	closeRenamer();
 
+	// This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611).
 	// List is re-sorted alphabetically, so scroll to make sure the selected item is visible.
-	scrollToShowSelection();
+	//scrollToShowSelection();
 }
 
 void LLFolderView::closeRenamer( void )
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3877f9f040..74837bac37 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2984,8 +2984,45 @@ std::string LLFolderBridge::getLabelSuffix() const
 		: LLStringUtil::null;
 }
 
+class ScrollOnRenameObserver: public LLInventoryObserver
+{
+public:
+	LLFolderView *mView;
+	LLUUID mUUID;
+	
+	ScrollOnRenameObserver(const LLUUID& uuid, LLFolderView *view):
+		mUUID(uuid),
+		mView(view)
+	{
+	}
+	void changed(U32 mask)
+	{
+		if (mask & LLInventoryObserver::LABEL)
+		{
+			// TODO - check for whether this is the item we're waiting for a rename of
+			const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
+			for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
+			{
+				const LLUUID& id = *it;
+				if (id == mUUID)
+				{
+					mView->scrollToShowSelection();
+					
+					gInventory.removeObserver(this);
+					delete this;
+					return;
+				}
+			}
+		}
+	}
+};
+
 BOOL LLFolderBridge::renameItem(const std::string& new_name)
 {
+
+	LLScrollOnRenameObserver *observer = new LLScrollOnRenameObserver(mUUID, mRoot);
+	gInventory.addObserver(observer);
+
 	rename_category(getInventoryModel(), mUUID, new_name);
 
 	// return FALSE because we either notified observers (& therefore
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 011686bfdd..ae59b44184 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -701,3 +701,24 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
 {
 	mItemNameHash.finalize();
 }
+
+void LLScrollOnRenameObserver::changed(U32 mask)
+{
+	if (mask & LLInventoryObserver::LABEL)
+	{
+		// TODO - check for whether this is the item we're waiting for a rename of
+		const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
+		for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
+		{
+			const LLUUID& id = *it;
+			if (id == mUUID)
+			{
+				mView->scrollToShowSelection();
+					
+				gInventory.removeObserver(this);
+				delete this;
+				return;
+			}
+		}
+	}
+}
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index dd30513844..2436930ef6 100755
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -287,4 +287,22 @@ protected:
 	category_map_t				mCategoryMap;
 };
 
+class LLFolderView;
+
+// Force a FolderView to scroll after an item in the corresponding view has been renamed.
+class LLScrollOnRenameObserver: public LLInventoryObserver
+{
+public:
+	LLFolderView *mView;
+	LLUUID mUUID;
+	
+	LLScrollOnRenameObserver(const LLUUID& uuid, LLFolderView *view):
+		mUUID(uuid),
+		mView(view)
+	{
+	}
+	/* virtual */ void changed(U32 mask);
+};
+
+
 #endif // LL_LLINVENTORYOBSERVERS_H
-- 
cgit v1.2.3


From fd2d81223697bad850b979f308c271ca370eccd3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 25 Nov 2013 16:03:52 -0500
Subject: SH-4549 FIX - code cleanup

---
 indra/newview/llinventorybridge.cpp   | 33 ---------------------------------
 indra/newview/llinventoryobserver.cpp |  1 -
 2 files changed, 34 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 74837bac37..1f942f5f4b 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2984,39 +2984,6 @@ std::string LLFolderBridge::getLabelSuffix() const
 		: LLStringUtil::null;
 }
 
-class ScrollOnRenameObserver: public LLInventoryObserver
-{
-public:
-	LLFolderView *mView;
-	LLUUID mUUID;
-	
-	ScrollOnRenameObserver(const LLUUID& uuid, LLFolderView *view):
-		mUUID(uuid),
-		mView(view)
-	{
-	}
-	void changed(U32 mask)
-	{
-		if (mask & LLInventoryObserver::LABEL)
-		{
-			// TODO - check for whether this is the item we're waiting for a rename of
-			const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
-			for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
-			{
-				const LLUUID& id = *it;
-				if (id == mUUID)
-				{
-					mView->scrollToShowSelection();
-					
-					gInventory.removeObserver(this);
-					delete this;
-					return;
-				}
-			}
-		}
-	}
-};
-
 BOOL LLFolderBridge::renameItem(const std::string& new_name)
 {
 
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index ae59b44184..f71cf26b30 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -706,7 +706,6 @@ void LLScrollOnRenameObserver::changed(U32 mask)
 {
 	if (mask & LLInventoryObserver::LABEL)
 	{
-		// TODO - check for whether this is the item we're waiting for a rename of
 		const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
 		for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
 		{
-- 
cgit v1.2.3


From c0d780cb4473c02e885c67fbc1bc30e87536d1b8 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 25 Nov 2013 16:52:58 -0500
Subject: SH-4613 WIP - add CREATE mask bit for newly created items in
 AISUpdate::doUpdate() - needed for some inventory observers.

---
 indra/newview/llaisapi.cpp         | 5 +++--
 indra/newview/llinventorymodel.cpp | 5 +++--
 indra/newview/llinventorymodel.h   | 2 +-
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 14978662f6..38eb34676e 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -33,6 +33,7 @@
 #include "llinventorymodel.h"
 #include "llsdutil.h"
 #include "llviewerregion.h"
+#include "llinventoryobserver.h"
 
 ///----------------------------------------------------------------------------
 /// Classes for AISv3 support.
@@ -781,7 +782,7 @@ void AISUpdate::doUpdate()
 		LLUUID category_id(create_it->first);
 		LLPointer<LLViewerInventoryCategory> new_category = create_it->second;
 
-		gInventory.updateCategory(new_category);
+		gInventory.updateCategory(new_category, LLInventoryObserver::CREATE);
 		LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL;
 	}
 
@@ -818,7 +819,7 @@ void AISUpdate::doUpdate()
 		// cases.  Maybe break out the update/create cases, in which
 		// case this is create.
 		LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL;
-		gInventory.updateItem(new_item);
+		gInventory.updateItem(new_item, LLInventoryObserver::CREATE);
 	}
 	
 	// UPDATE ITEMS
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 6b1bf69b5e..891d7c821c 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -944,7 +944,7 @@ LLInventoryModel::item_array_t* LLInventoryModel::getUnlockedItemArray(const LLU
 
 // Calling this method with an inventory category will either change
 // an existing item with the matching id, or it will add the category.
-void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat)
+void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask)
 {
 	if(cat->getUUID().isNull())
 	{
@@ -961,7 +961,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat)
 	if(old_cat)
 	{
 		// We already have an old category, modify it's values
-		U32 mask = LLInventoryObserver::NONE;
 		LLUUID old_parent_id = old_cat->getParentUUID();
 		LLUUID new_parent_id = cat->getParentUUID();
 		if(old_parent_id != new_parent_id)
@@ -1128,6 +1127,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	llinfos << "elapsed: " << timer.getElapsedTimeF32() << llendl;
 }
 
+// Does not appear to be used currently.
 void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
 {
 	U32 mask = LLInventoryObserver::NONE;
@@ -1168,6 +1168,7 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates,
 	}
 }
 
+// Not used?
 void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates)
 {
 	U32 mask = LLInventoryObserver::NONE;
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index ab8bbac6d8..6b6d077a4b 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -309,7 +309,7 @@ public:
 	//    NOTE: In usage, you will want to perform cache accounting
 	//    operations in accountForUpdate() or LLViewerInventoryCategory::
 	//    updateServer() before calling this method.
-	void updateCategory(const LLViewerInventoryCategory* cat);
+	void updateCategory(const LLViewerInventoryCategory* cat, U32 mask = 0);
 
 	// Move the specified object id to the specified category and
 	// update the internal structures. No cache accounting,
-- 
cgit v1.2.3


From 940cde3938217daf348bd62f719cae262bad86b0 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 3 Dec 2013 11:49:29 -0500
Subject: SH-4640 WIP

---
 indra/newview/llinventorybridge.cpp |  13 +--
 indra/newview/llinventorymodel.cpp  | 174 ++++++++++++++++++++++++++++++------
 indra/newview/llinventorymodel.h    |  13 ++-
 3 files changed, 162 insertions(+), 38 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 1f942f5f4b..4bce25c8b5 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1730,16 +1730,9 @@ BOOL LLItemBridge::removeItem()
 	{
 		if (!item->getIsLinkType())
 		{
-			LLInventoryModel::cat_array_t cat_array;
-			LLInventoryModel::item_array_t item_array;
-			LLLinkedItemIDMatches is_linked_item_match(mUUID);
-			gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
-											cat_array,
-											item_array,
-											LLInventoryModel::INCLUDE_TRASH,
-											is_linked_item_match);
-
-			const U32 num_links = cat_array.size() + item_array.size();
+			LLInventoryModel::item_array_t item_array = 
+				gInventory.collectLinksTo(mUUID, gInventory.getRootFolderID());
+			const U32 num_links = item_array.size();
 			if (num_links > 0)
 			{
 				// Warn if the user is will break any links when deleting this item.
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 891d7c821c..2c63203773 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -127,6 +127,7 @@ LLInventoryModel gInventory;
 LLInventoryModel::LLInventoryModel()
 :	mModifyMask(LLInventoryObserver::ALL),
 	mChangedItemIDs(),
+	mBacklinkMMap(),
 	mCategoryMap(),
 	mItemMap(),
 	mCategoryLock(),
@@ -686,26 +687,8 @@ void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
 	if (!obj || obj->getIsLinkType())
 		return;
 
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t item_array;
-	LLLinkedItemIDMatches is_linked_item_match(object_id);
-	collectDescendentsIf(gInventory.getRootFolderID(),
-						 cat_array,
-						 item_array,
-						 LLInventoryModel::INCLUDE_TRASH,
-						 is_linked_item_match);
-	if (cat_array.empty() && item_array.empty())
-	{
-		return;
-	}
-	for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
-		 cat_iter != cat_array.end();
-		 cat_iter++)
-	{
-		LLViewerInventoryCategory *linked_cat = (*cat_iter);
-		addChangedMask(mask, linked_cat->getUUID());
-	};
-
+	LLInventoryModel::item_array_t item_array = 
+		collectLinksTo(object_id,gInventory.getRootFolderID());
 	for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
 		 iter != item_array.end();
 		 iter++)
@@ -733,11 +716,14 @@ LLViewerInventoryItem* LLInventoryModel::getLinkedItem(const LLUUID& object_id)
 	return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL;
 }
 
-LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID& id,
-																	const LLUUID& start_folder_id)
+LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id,
+																const LLUUID& start_folder_id)
 {
+	// Get item list via collectDescendents (slow!)
 	item_array_t items;
 	const LLInventoryObject *obj = getObject(id);
+	// FIXME - should be as below, but this is causing a stack-smashing crash of cause TBD... check in the REBUILD code.
+	//if (obj && obj->getIsLinkType())
 	if (!obj || obj->getIsLinkType())
 		return items;
 	
@@ -748,6 +734,38 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID
 						 items,
 						 LLInventoryModel::INCLUDE_TRASH,
 						 is_linked_item_match);
+
+	// Get via backlinks - fast.
+	item_array_t fast_items;
+	std::pair<backlink_mmap_t::iterator, backlink_mmap_t::iterator> range = mBacklinkMMap.equal_range(id);
+	for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it)
+	{
+		LLViewerInventoryItem *item = getItem(it->second);
+		if (item)
+		{
+			fast_items.put(item);
+		}
+	}
+
+	// Validate equivalence.
+	if (items.size() != fast_items.size())
+	{
+		llwarns << "size mismatch, " << items.size() << " != " << fast_items.size() << llendl;
+	}
+	for (item_array_t::iterator ita = items.begin(); ita != items.end(); ++ita)
+	{
+		if (fast_items.find(*ita) == item_array_t::FAIL)
+		{
+			llwarns << "in descendents search but not fast search " << (*ita)->getUUID() << llendl;
+		}
+	}
+	for (item_array_t::iterator itb = fast_items.begin(); itb != fast_items.end(); ++itb)
+	{
+		if (items.find(*itb) == item_array_t::FAIL)
+		{
+			llwarns << "in fast search but not descendents search " << (*itb)->getUUID() << llendl;
+		}
+	}
 	return items;
 }
 
@@ -1355,11 +1373,16 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
 		mParentChildCategoryTree.erase(id);
 	}
 	addChangedMask(LLInventoryObserver::REMOVE, id);
-	
+
+	bool is_link_type = obj->getIsLinkType();
+	if (is_link_type)
+	{
+		removeBacklinkInfo(obj->getUUID(), obj->getLinkedUUID());
+	}
+
 	// Can't have links to links, so there's no need for this update
 	// if the item removed is a link. Can also skip if source of the
 	// update is getting broken link info separately.
-	bool is_link_type = obj->getIsLinkType();
 	obj = NULL; // delete obj
 	if (fix_broken_links && !is_link_type)
 	{
@@ -1373,7 +1396,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
 
 void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
 {
-	LLInventoryModel::item_array_t item_array = collectLinkedItems(baseobj_id);
+	LLInventoryModel::item_array_t item_array = collectLinksTo(baseobj_id);
 
 	// REBUILD is expensive, so clear the current change list first else
 	// everything else on the changelist will also get rebuilt.
@@ -1653,6 +1676,47 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
 	}
 }
 
+bool LLInventoryModel::hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const
+{
+	std::pair <backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range;
+	range = mBacklinkMMap.equal_range(target_id);
+	for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+	{
+		if (it->second == link_id)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+void LLInventoryModel::addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id)
+{
+	if (!hasBacklinkInfo(link_id, target_id))
+	{
+		mBacklinkMMap.insert(std::make_pair(target_id, link_id));
+	}
+}
+
+void LLInventoryModel::removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id)
+{
+	std::pair <backlink_mmap_t::iterator, backlink_mmap_t::iterator> range;
+	range = mBacklinkMMap.equal_range(target_id);
+	for (backlink_mmap_t::iterator it = range.first; it != range.second; )
+	{
+		if (it->second == link_id)
+		{
+			backlink_mmap_t::iterator delete_it = it; // iterator will be invalidated by erase.
+			++it;
+			mBacklinkMMap.erase(delete_it);
+		}
+		else
+		{
+			++it;
+		}
+	}
+}
+
 void LLInventoryModel::addItem(LLViewerInventoryItem* item)
 {
 	llassert(item);
@@ -1674,7 +1738,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
 		{
 			llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " )  parent: " << item->getParentUUID() << llendl;
 		}
-
+		if (item->getIsLinkType())
+		{
+			// Add back-link from linked-to UUID.
+			const LLUUID& link_id = item->getUUID();
+			const LLUUID& target_id = item->getLinkedUUID();
+			addBacklinkInfo(link_id, target_id);
+		}
 		mItemMap[item->getUUID()] = item;
 	}
 }
@@ -1693,6 +1763,7 @@ void LLInventoryModel::empty()
 		mParentChildItemTree.end(),
 		DeletePairedPointer());
 	mParentChildItemTree.clear();
+	mBacklinkMMap.clear(); // forget all backlink information.
 	mCategoryMap.clear(); // remove all references (should delete entries)
 	mItemMap.clear(); // remove all references (should delete entries)
 	mLastItem = NULL;
@@ -3701,6 +3772,57 @@ bool LLInventoryModel::validate() const
 			}
 				
 		}
+		// Link checking
+		if (item->getIsLinkType())
+		{
+			const LLUUID& link_id = item->getUUID();
+			const LLUUID& target_id = item->getLinkedUUID();
+			LLViewerInventoryItem *target_item = getItem(target_id);
+			LLViewerInventoryCategory *target_cat = getCategory(target_id);
+			// Linked-to UUID should have back reference to this link.
+			if (!hasBacklinkInfo(link_id, target_id))
+			{
+				llwarns << "link " << item->getUUID() << " type " << item->getActualType()
+						<< " missing backlink info at target_id " << target_id
+						<< llendl;
+			}
+			// Links should have referents.
+			if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
+			{
+				llwarns << "broken item link " << item->getName() << " id " << item->getUUID() << llendl;
+			}
+			else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
+			{
+				llwarns << "broken folder link " << item->getName() << " id " << item->getUUID() << llendl;
+			}
+			if (target_item && target_item->getIsLinkType())
+			{
+				llwarns << "link " << item->getName() << " references a link item "
+						<< target_item->getName() << " " << target_item->getUUID() << llendl;
+			}
+
+			// Links should not have backlinks.
+			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
+			if (range.first != range.second)
+			{
+				llwarns << "Link item " << item->getName() << " has backlinks!" << llendl;
+			}
+		}
+		else
+		{
+			// Check the backlinks of a non-link item.
+			const LLUUID& target_id = item->getUUID();
+			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id);
+			for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+			{
+				const LLUUID& link_id = it->second;
+				LLViewerInventoryItem *link_item = getItem(link_id);
+				if (!link_item || !link_item->getIsLinkType())
+				{
+					llwarns << "invalid backlink from target " << item->getName() << " to " << link_id << llendl;
+				}
+			}
+		}
 	}
 	
 	if (cat_lock > 0 || item_lock > 0)
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 6b6d077a4b..0bb89bc5d4 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -154,6 +154,15 @@ private:
 	parent_cat_map_t mParentChildCategoryTree;
 	parent_item_map_t mParentChildItemTree;
 
+	// Track links to items and categories. We do not store item or
+	// category pointers here, because broken links are also supported.
+	typedef std::multimap<LLUUID, LLUUID> backlink_mmap_t;
+	backlink_mmap_t mBacklinkMMap; // key = target_id: ID of item, values = link_ids: IDs of item or folder links referencing it.
+	// For internal use only
+	bool hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const;
+	void addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id);
+	void removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id);
+	
 	//--------------------------------------------------------------------
 	// Login
 	//--------------------------------------------------------------------
@@ -217,8 +226,8 @@ public:
 
 	// Collect all items in inventory that are linked to item_id.
 	// Assumes item_id is itself not a linked item.
-	item_array_t collectLinkedItems(const LLUUID& item_id,
-									const LLUUID& start_folder_id = LLUUID::null);
+	item_array_t collectLinksTo(const LLUUID& item_id,
+								const LLUUID& start_folder_id = LLUUID::null);
 	
 
 	// Check if one object has a parent chain up to the category specified by UUID.
-- 
cgit v1.2.3


From 1320e5ddcd9fc3be526dcacbf4710f8bcf878665 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 3 Dec 2013 16:35:07 -0500
Subject: SH-4640 WIP - use backlinks in inventory

---
 indra/newview/llinventorybridge.cpp |  3 +--
 indra/newview/llinventorymodel.cpp  | 40 +++++--------------------------------
 indra/newview/llinventorymodel.h    |  4 +---
 3 files changed, 7 insertions(+), 40 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 4bce25c8b5..fbb276efd6 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1730,8 +1730,7 @@ BOOL LLItemBridge::removeItem()
 	{
 		if (!item->getIsLinkType())
 		{
-			LLInventoryModel::item_array_t item_array = 
-				gInventory.collectLinksTo(mUUID, gInventory.getRootFolderID());
+			LLInventoryModel::item_array_t item_array = gInventory.collectLinksTo(mUUID);
 			const U32 num_links = item_array.size();
 			if (num_links > 0)
 			{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 2c63203773..268cb7d8b2 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -687,8 +687,7 @@ void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
 	if (!obj || obj->getIsLinkType())
 		return;
 
-	LLInventoryModel::item_array_t item_array = 
-		collectLinksTo(object_id,gInventory.getRootFolderID());
+	LLInventoryModel::item_array_t item_array = collectLinksTo(object_id);
 	for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
 		 iter != item_array.end();
 		 iter++)
@@ -716,56 +715,27 @@ LLViewerInventoryItem* LLInventoryModel::getLinkedItem(const LLUUID& object_id)
 	return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL;
 }
 
-LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id,
-																const LLUUID& start_folder_id)
+LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id)
 {
 	// Get item list via collectDescendents (slow!)
 	item_array_t items;
 	const LLInventoryObject *obj = getObject(id);
-	// FIXME - should be as below, but this is causing a stack-smashing crash of cause TBD... check in the REBUILD code.
+	// FIXME - should be as in next line, but this is causing a
+	// stack-smashing crash of cause TBD... check in the REBUILD code.
 	//if (obj && obj->getIsLinkType())
 	if (!obj || obj->getIsLinkType())
 		return items;
 	
-	LLInventoryModel::cat_array_t cat_array;
-	LLLinkedItemIDMatches is_linked_item_match(id);
-	collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id),
-						 cat_array,
-						 items,
-						 LLInventoryModel::INCLUDE_TRASH,
-						 is_linked_item_match);
-
-	// Get via backlinks - fast.
-	item_array_t fast_items;
 	std::pair<backlink_mmap_t::iterator, backlink_mmap_t::iterator> range = mBacklinkMMap.equal_range(id);
 	for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it)
 	{
 		LLViewerInventoryItem *item = getItem(it->second);
 		if (item)
 		{
-			fast_items.put(item);
+			items.put(item);
 		}
 	}
 
-	// Validate equivalence.
-	if (items.size() != fast_items.size())
-	{
-		llwarns << "size mismatch, " << items.size() << " != " << fast_items.size() << llendl;
-	}
-	for (item_array_t::iterator ita = items.begin(); ita != items.end(); ++ita)
-	{
-		if (fast_items.find(*ita) == item_array_t::FAIL)
-		{
-			llwarns << "in descendents search but not fast search " << (*ita)->getUUID() << llendl;
-		}
-	}
-	for (item_array_t::iterator itb = fast_items.begin(); itb != fast_items.end(); ++itb)
-	{
-		if (items.find(*itb) == item_array_t::FAIL)
-		{
-			llwarns << "in fast search but not descendents search " << (*itb)->getUUID() << llendl;
-		}
-	}
 	return items;
 }
 
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 0bb89bc5d4..1e18adf8d6 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -226,9 +226,7 @@ public:
 
 	// Collect all items in inventory that are linked to item_id.
 	// Assumes item_id is itself not a linked item.
-	item_array_t collectLinksTo(const LLUUID& item_id,
-								const LLUUID& start_folder_id = LLUUID::null);
-	
+	item_array_t collectLinksTo(const LLUUID& item_id);
 
 	// Check if one object has a parent chain up to the category specified by UUID.
 	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
-- 
cgit v1.2.3


From 4724232abd2aa88cdd592be6f5aa287ed70af1aa Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 5 Dec 2013 13:24:38 -0500
Subject: SH-4611 WIP - this should prevent the case logged, which I believe is
 caused when cache loading fails. Can not repro so somewhat speculative.

---
 indra/newview/lltexturefetch.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index d9c2c7d279..12c83ce28f 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1612,7 +1612,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
 							<< llendl;
 				}
 
-				mUrl.clear();
+				if (mFTType != FTT_SERVER_BAKE)
+				{
+					mUrl.clear();
+				}
 				if (cur_size > 0)
 				{
 					// Use available data
@@ -1639,7 +1642,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			// Clear the url since we're done with the fetch
 			// Note: mUrl is used to check is fetching is required so failure to clear it will force an http fetch
 			// next time the texture is requested, even if the data have already been fetched.
-			if(mWriteToCacheState != NOT_WRITE)
+			if(mWriteToCacheState != NOT_WRITE && mFTType != FTT_SERVER_BAKE)
 			{
 				// Why do we want to keep url if NOT_WRITE - is this a proxy for map tiles?
 				mUrl.clear();
-- 
cgit v1.2.3


From 9acc63001023c31d67e20d61d5ef2c67905a5c7c Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 10 Dec 2013 16:25:37 -0500
Subject: fix for license wording

---
 indra/llmessage/tests/llhttpnode_stub.cpp | 33 +++++++++++++------------------
 1 file changed, 14 insertions(+), 19 deletions(-)
 mode change 100644 => 100755 indra/llmessage/tests/llhttpnode_stub.cpp

diff --git a/indra/llmessage/tests/llhttpnode_stub.cpp b/indra/llmessage/tests/llhttpnode_stub.cpp
old mode 100644
new mode 100755
index cc2108fed5..479a256bdd
--- a/indra/llmessage/tests/llhttpnode_stub.cpp
+++ b/indra/llmessage/tests/llhttpnode_stub.cpp
@@ -2,31 +2,26 @@
  * @file llhttpnode_stub.cpp
  * @brief STUB Implementation of classes for generic HTTP/LSL/REST handling.
  *
- * $LicenseInfo:firstyear=2006&license=viewergpl$
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  * 
+ * Second Life Viewer Source Code
  * Copyright (c) 2006-2009, Linden Research, Inc.
  * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab.  Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
  * 
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
  * 
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
  * 
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
-- 
cgit v1.2.3


From cc9a7a70b1971def1c53c70c96e8ce88fc5a7b86 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 17 Dec 2013 14:14:03 -0500
Subject: merge fix

---
 indra/newview/llinventorybridge.cpp | 2 +-
 indra/newview/lltexturefetch.cpp    | 2 +-
 indra/newview/llviewerregion.cpp    | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 32164f3a72..1a98f293d1 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2970,7 +2970,7 @@ LLUIImagePtr LLFolderBridge::getIconOverlay() const
 
 std::string LLFolderBridge::getLabelSuffix() const
 {
-	static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5);
+	static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f);
 	return mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay() 
 		? llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str())
 		: LLStringUtil::null;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 12c83ce28f..d0ab9f55ff 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1949,7 +1949,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
 	}
 
-	static LLCachedControl<F32> fake_failure_rate(gSavedSettings, "TextureFetchFakeFailureRate", 0.0);
+	static LLCachedControl<F32> fake_failure_rate(gSavedSettings, "TextureFetchFakeFailureRate", 0.0f);
 	F32 rand_val = ll_frand();
 	F32 rate = fake_failure_rate;
 	if (mFTType == FTT_SERVER_BAKE && (fake_failure_rate > 0.0) && (rand_val < fake_failure_rate))
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index fa7af4f48e..e6cc75f1ce 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1673,6 +1673,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("ProductInfoRequest");
 	capabilityNames.append("ProvisionVoiceAccountRequest");
 	capabilityNames.append("RemoteParcelRequest");
+	capabilityNames.append("RenderMaterials");
 	capabilityNames.append("RequestTextureDownload");
 	capabilityNames.append("ResourceCostSelected");
 	capabilityNames.append("RetrieveNavMeshSrc");
-- 
cgit v1.2.3


From f6947e9ce5a5225c30dd347ee2e16392411c6d2f Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 19 Dec 2013 15:39:21 -0500
Subject: SH-4664 WIP - updated from from UpdateCreateInventoryItem to
 inventory observers.

---
 indra/newview/llinventorymodel.cpp    | 11 +++++++----
 indra/newview/llinventorymodel.h      |  2 +-
 indra/newview/llinventoryobserver.cpp | 22 ++++++++++++++++++++--
 indra/newview/llinventoryobserver.h   |  2 ++
 indra/newview/lllocationinputctrl.cpp |  6 +++++-
 5 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 268cb7d8b2..1699088b99 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1514,7 +1514,7 @@ void LLInventoryModel::fetchInventoryResponder::httpSuccess()
 		LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
 		titem->unpackMessage(content["items"][i]);
 		
-		lldebugs << "LLInventoryModel::messageUpdateCore() item id:"
+		lldebugs << "LLInventoryModel::fetchInventoryResponder item id: "
 				 << titem->getUUID() << llendl;
 		items.push_back(titem);
 		// examine update for changes.
@@ -2617,7 +2617,7 @@ void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
 void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**)
 {
 	// do accounting and highlight new items if they arrive
-	if (gInventory.messageUpdateCore(msg, true))
+	if (gInventory.messageUpdateCore(msg, true, LLInventoryObserver::UPDATE_CREATE))
 	{
 		U32 callback_id;
 		LLUUID item_id;
@@ -2637,7 +2637,7 @@ void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**)
 }
 
 
-bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account)
+bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask)
 {
 	//make sure our added inventory observer is active
 	start_new_inventory_observer();
@@ -2691,7 +2691,10 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account)
 	}
 
 	U32 changes = 0x0;
-	U32 mask = account ? LLInventoryObserver::CREATE : 0x0;
+	if (account)
+	{
+		mask |= LLInventoryObserver::CREATE;
+	}
 	//as above, this loop never seems to loop more than once per call
 	for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
 	{
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 1e18adf8d6..41ab895e84 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -556,7 +556,7 @@ public:
 	static void processMoveInventoryItem(LLMessageSystem* msg, void**);
 	static void processFetchInventoryReply(LLMessageSystem* msg, void**);
 protected:
-	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
+	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, U32 mask = 0x0);
 
 	//--------------------------------------------------------------------
 	// Locks
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index f71cf26b30..996decde8c 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -465,9 +465,13 @@ void LLInventoryFetchComboObserver::startFetch()
 	mFetchDescendents->startFetch();
 }
 
+// See comment preceding LLInventoryAddedObserver::changed() for some
+// concerns that also apply to this observer.
 void LLInventoryAddItemByAssetObserver::changed(U32 mask)
 {
-	if(!(mask & LLInventoryObserver::ADD) || !(mask & LLInventoryObserver::CREATE))
+	if(!(mask & LLInventoryObserver::ADD) ||
+	   !(mask & LLInventoryObserver::CREATE) ||
+	   !(mask & LLInventoryObserver::UPDATE_CREATE))
 	{
 		return;
 	}
@@ -526,9 +530,23 @@ bool LLInventoryAddItemByAssetObserver::isAssetWatched( const LLUUID& asset_id )
 	return std::find(mWatchedAssets.begin(), mWatchedAssets.end(), asset_id) != mWatchedAssets.end();
 }
 
+// This observer used to explicitly check for whether it was being
+// called as a result of an UpdateCreateInventoryItem message. It has
+// now been decoupled enough that it's not actually checking the
+// message system, but now we have the special UPDATE_CREATE flag
+// being used for the same purpose. Fixing this, as we would need to
+// do to get rid of the message, is somewhat subtle because there's no
+// particular obvious criterion for when creating a new item should
+// trigger this observer and when it shouldn't. For example, creating
+// a new notecard with new->notecard causes a preview window to pop up
+// via the derived class LLOpenTaskOffer, but creating a new notecard
+// by copy and paste does not, solely because one goes through
+// UpdateCreateInventoryItem and the other doesn't.
 void LLInventoryAddedObserver::changed(U32 mask)
 {
-	if (!(mask & LLInventoryObserver::ADD) || !(mask & LLInventoryObserver::CREATE))
+	if (!(mask & LLInventoryObserver::ADD) ||
+		!(mask & LLInventoryObserver::CREATE) ||
+		!(mask & LLInventoryObserver::UPDATE_CREATE))
 	{
 		return;
 	}
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index 2436930ef6..8cf6a6bdab 100755
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -59,6 +59,8 @@ public:
 		REBUILD 		= 128, 	// Item UI changed (e.g. item type different)
 		SORT 			= 256, 	// Folder needs to be resorted.
 		CREATE			= 512,  // With ADD, item has just been created.
+		// unfortunately a particular message is still associated with some unique semantics.
+		UPDATE_CREATE	= 1024,  // With ADD, item added via UpdateCreateInventoryItem
 		ALL 			= 0xffffffff
 	};
 	LLInventoryObserver();
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 7b97b26a37..dcfe3cc9a7 100755
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -140,7 +140,11 @@ public:
 private:
 	/*virtual*/ void changed(U32 mask)
 	{
-		if (mask & (~(LLInventoryObserver::LABEL|LLInventoryObserver::INTERNAL|LLInventoryObserver::ADD|LLInventoryObserver::CREATE)))
+		if (mask & (~(LLInventoryObserver::LABEL|
+					  LLInventoryObserver::INTERNAL|
+					  LLInventoryObserver::ADD|
+					  LLInventoryObserver::CREATE|
+					  LLInventoryObserver::UPDATE_CREATE)))
 		{
 			mInput->updateAddLandmarkButton();
 		}
-- 
cgit v1.2.3


From 87fc26e0c6d8b09bc3747922fb1c1b9a2d757e98 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 6 Jan 2014 17:29:39 -0500
Subject: SH-4666 WIP - modified LLMaterialsResponder to use
 httpSuccess()/httpFailure()

---
 indra/newview/llmaterialmgr.cpp | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
 mode change 100644 => 100755 indra/newview/llmaterialmgr.cpp

diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
old mode 100644
new mode 100755
index 14d3d4e7a8..2e569543bd
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -71,8 +71,8 @@ public:
 	LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
 	virtual ~LLMaterialsResponder();
 
-	virtual void result(const LLSD& pContent);
-	virtual void error(U32 pStatus, const std::string& pReason);
+	virtual void httpSuccess();
+	virtual void httpFailure();
 
 private:
 	std::string      mMethod;
@@ -92,14 +92,19 @@ LLMaterialsResponder::~LLMaterialsResponder()
 {
 }
 
-void LLMaterialsResponder::result(const LLSD& pContent)
+void LLMaterialsResponder::httpSuccess()
 {
+	const LLSD& pContent = getContent();
+
 	LL_DEBUGS("Materials") << LL_ENDL;
 	mCallback(true, pContent);
 }
 
-void LLMaterialsResponder::error(U32 pStatus, const std::string& pReason)
+void LLMaterialsResponder::httpFailure()
 {
+	U32 pStatus = (U32) getStatus();
+	const std::string& pReason = getReason();
+	
 	LL_WARNS("Materials")
 		<< "\n--------------------------------------------------------------------------\n"
 		<< mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
-- 
cgit v1.2.3


From 041f267d6a5a4c6251a113accdf0003301beb6a9 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 23 Apr 2014 01:57:24 +0100
Subject: MAINT-4009: Adding LLWinDebug::cleanup() to ensure memory is freed at
 app end.

---
 indra/newview/llappviewerwin32.cpp |  4 ++++
 indra/newview/llwindebug.cpp       | 20 +++++++++++++++-----
 indra/newview/llwindebug.h         |  1 +
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 06f081e920..a1b4fd1035 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -542,6 +542,10 @@ bool LLAppViewerWin32::cleanup()
 
 	gDXHardware.cleanup();
 
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	LLWinDebug::instance().cleanup();
+#endif
+
 	return result;
 }
 
diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp
index 551d0be8d7..eff70ca0b2 100755
--- a/indra/newview/llwindebug.cpp
+++ b/indra/newview/llwindebug.cpp
@@ -45,7 +45,7 @@ public:
 	~LLMemoryReserve();
 	void reserve();
 	void release();
-protected:
+private:
 	unsigned char *mReserve;
 	static const size_t MEMORY_RESERVATION_SIZE;
 };
@@ -53,7 +53,7 @@ protected:
 LLMemoryReserve::LLMemoryReserve() :
 	mReserve(NULL)
 {
-};
+}
 
 LLMemoryReserve::~LLMemoryReserve()
 {
@@ -66,14 +66,19 @@ const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024;
 void LLMemoryReserve::reserve()
 {
 	if(NULL == mReserve)
+	{
 		mReserve = new unsigned char[MEMORY_RESERVATION_SIZE];
-};
+	}
+}
 
 void LLMemoryReserve::release()
 {
-	delete [] mReserve;
+	if (NULL != mReserve)
+	{
+		delete [] mReserve;
+	}
 	mReserve = NULL;
-};
+}
 
 static LLMemoryReserve gEmergencyMemoryReserve;
 
@@ -130,6 +135,11 @@ void  LLWinDebug::init()
 	}
 }
 
+void LLWinDebug::cleanup ()
+{
+	gEmergencyMemoryReserve.release();
+}
+
 void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename)
 {
 	// Temporary fix to switch out the code that writes the DMP file.
diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h
index 6f274c6f16..a3cbf6dc03 100755
--- a/indra/newview/llwindebug.h
+++ b/indra/newview/llwindebug.h
@@ -37,6 +37,7 @@ class LLWinDebug:
 public:
 	static void init();
 	static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL);
+	static void cleanup();
 private:
 	static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename);
 };
-- 
cgit v1.2.3


From 5e225213f6bdb7b4ca97abfef99b2249a1f88638 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 23 Apr 2014 17:57:23 +0100
Subject: MAINT-4009: Adding an ares cleanup call to free the allocated memory.

---
 indra/llmessage/llares.cpp    | 9 +++++++++
 indra/llmessage/llares.h      | 1 +
 indra/newview/llappviewer.cpp | 3 +++
 3 files changed, 13 insertions(+)

diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index 81e28121fd..9f90ae1544 100755
--- a/indra/llmessage/llares.cpp
+++ b/indra/llmessage/llares.cpp
@@ -610,6 +610,15 @@ LLAres *ll_init_ares()
 	return gAres;
 }
 
+void ll_cleanup_ares()
+{
+	if (gAres != NULL)
+	{
+		delete gAres;
+		gAres = NULL;
+	}
+}
+
 LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name,
 						 unsigned ttl)
 	: LLRefCount(),
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
index 800781ee88..0b5d49e322 100755
--- a/indra/llmessage/llares.h
+++ b/indra/llmessage/llares.h
@@ -578,5 +578,6 @@ extern LLAres *gAres;
  * thread safe.
  */
 extern LLAres *ll_init_ares();
+extern void ll_cleanup_ares();
 
 #endif // LL_LLARES_H
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 3b9259a966..2b634074d5 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2019,6 +2019,9 @@ bool LLAppViewer::cleanup()
 	// Non-LLCurl libcurl library
 	mAppCoreHttp.cleanup();
 
+	// NOTE The following call is not thread safe. 
+	ll_cleanup_ares();
+
 	LLFilePickerThread::cleanupClass();
 
 	//MUST happen AFTER LLCurl::cleanupClass
-- 
cgit v1.2.3


From 5969c3d04f501d1c330674153702d32051daaf67 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 23 Apr 2014 18:13:12 +0100
Subject: MAINT-4009: Freeing the allocated console during shutdown.

---
 indra/newview/llappviewerwin32.cpp | 17 +++++++++++++----
 indra/newview/llappviewerwin32.h   |  3 ++-
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index a1b4fd1035..57fb84bbf1 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -438,7 +438,7 @@ void LLAppViewerWin32::disableWinErrorReporting()
 
 const S32 MAX_CONSOLE_LINES = 500;
 
-void create_console()
+static bool create_console()
 {
 	int h_con_handle;
 	long l_std_handle;
@@ -447,7 +447,7 @@ void create_console()
 	FILE *fp;
 
 	// allocate a console for this app
-	AllocConsole();
+	const bool isConsoleAllocated = AllocConsole();
 
 	// set the screen buffer to be big enough to let us scroll text
 	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
@@ -495,10 +495,13 @@ void create_console()
 		*stderr = *fp;
 		setvbuf( stderr, NULL, _IONBF, 0 );
 	}
+
+    return isConsoleAllocated;
 }
 
 LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) :
-    mCmdLine(cmd_line)
+	mCmdLine(cmd_line),
+	mIsConsoleAllocated(false)
 {
 }
 
@@ -546,6 +549,12 @@ bool LLAppViewerWin32::cleanup()
 	LLWinDebug::instance().cleanup();
 #endif
 
+	if (mIsConsoleAllocated)
+	{
+		FreeConsole();
+		mIsConsoleAllocated = false;
+	}
+
 	return result;
 }
 
@@ -557,7 +566,7 @@ void LLAppViewerWin32::initLoggingAndGetLastDuration()
 void LLAppViewerWin32::initConsole()
 {
 	// pop up debug console
-	create_console();
+	mIsConsoleAllocated = create_console();
 	return LLAppViewer::initConsole();
 }
 
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index fb37df1a2f..59d1ddaa3d 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -61,7 +61,8 @@ protected:
 private:
 	void disableWinErrorReporting();
 
-    std::string mCmdLine;
+	std::string mCmdLine;
+	bool mIsConsoleAllocated;
 };
 
 #endif // LL_LLAPPVIEWERWIN32_H
-- 
cgit v1.2.3


From fd0e84296e1f20b90bc6e7c0ad4fbfcecf0aa6d9 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 23 Apr 2014 19:36:08 +0100
Subject: MAINT-4009: Cleaning up the curl easy handle during shutdown.

---
 indra/llmessage/llcurl.cpp | 45 ++++++++++++++++++++++++++++++++++++---------
 indra/llmessage/llcurl.h   |  3 +++
 2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 147940c983..161b7c1615 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -274,6 +274,36 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
 	}
 }
 
+//static
+void LLCurl::Easy::deleteAllActiveHandles()
+{
+	LLMutexLock lock(sHandleMutexp) ;
+	LL_CHECK_MEMORY
+	for (std::set<CURL*>::iterator activeHandle = sActiveHandles.begin(); activeHandle != sActiveHandles.end(); ++activeHandle)
+	{
+		CURL* curlHandle = *activeHandle;
+		LLCurl::deleteEasyHandle(curlHandle);
+		LL_CHECK_MEMORY
+	}
+
+	sFreeHandles.clear();
+}
+
+//static
+void LLCurl::Easy::deleteAllFreeHandles()
+{
+	LLMutexLock lock(sHandleMutexp) ;
+	LL_CHECK_MEMORY
+	for (std::set<CURL*>::iterator freeHandle = sFreeHandles.begin(); freeHandle != sFreeHandles.end(); ++freeHandle)
+	{
+		CURL* curlHandle = *freeHandle;
+		LLCurl::deleteEasyHandle(curlHandle);
+		LL_CHECK_MEMORY
+	}
+
+	sFreeHandles.clear();
+}
+
 LLCurl::Easy::Easy()
 	: mHeaders(NULL),
 	  mCurlEasyHandle(NULL)
@@ -1745,17 +1775,14 @@ void LLCurl::cleanupClass()
 #endif
 	
 	LL_CHECK_MEMORY
-
-	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
-	{
-		CURL* curl = *iter;
-		LLCurl::deleteEasyHandle(curl);
-	}
-	
+	Easy::deleteAllFreeHandles();
+	LL_CHECK_MEMORY
+	Easy::deleteAllActiveHandles();
 	LL_CHECK_MEMORY
 
-	Easy::sFreeHandles.clear();
-
+	// Free the template easy handle
+	curl_easy_cleanup(sCurlTemplateStandardHandle);
+	sCurlTemplateStandardHandle = NULL;
 	LL_CHECK_MEMORY
 
 	delete Easy::sHandleMutexp ;
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fc9761ff9f..b033a3d4ab 100755
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -269,6 +269,9 @@ private:
 	static std::set<CURL*> sFreeHandles;
 	static std::set<CURL*> sActiveHandles;
 	static LLMutex*        sHandleMutexp ;
+
+	static void deleteAllActiveHandles();
+	static void deleteAllFreeHandles();
 };
 
 class LLCurl::Multi
-- 
cgit v1.2.3


From 592b7e2fdff3f5a405632cec5870e385a2b3f367 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Thu, 24 Apr 2014 00:35:14 +0100
Subject: MAINT-4009: Correcting a pointer deletion that should have correctly
 been an array deletion.

---
 indra/llwindow/llwindowwin32.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 0637572f67..19961d5759 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -657,7 +657,7 @@ LLWindowWin32::~LLWindowWin32()
 	delete [] mSupportedResolutions;
 	mSupportedResolutions = NULL;
 
-	delete mWindowClassName;
+	delete [] mWindowClassName;
 	mWindowClassName = NULL;
 }
 
-- 
cgit v1.2.3


From b24552e313dc971d7750025c4b6f953ee3155ea9 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Thu, 24 Apr 2014 01:50:17 +0100
Subject: MAINT-4009: Ensuring that the shader manager instance is released
 during cleanup.

---
 indra/newview/llviewershadermgr.cpp | 10 ++++++++++
 indra/newview/llviewershadermgr.h   |  1 +
 indra/newview/llviewerwindow.cpp    |  6 ++++++
 3 files changed, 17 insertions(+)

diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 9d2a4a50e1..dafe2cafec 100755
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -355,6 +355,16 @@ LLViewerShaderMgr * LLViewerShaderMgr::instance()
 	return static_cast<LLViewerShaderMgr*>(sInstance);
 }
 
+// static
+void LLViewerShaderMgr::releaseInstance()
+{
+	if (sInstance != NULL)
+	{
+		delete sInstance;
+		sInstance = NULL;
+	}
+}
+
 void LLViewerShaderMgr::initAttribsAndUniforms(void)
 {
 	if (mReservedAttribs.empty())
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 42147fdd29..923aa522ad 100755
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -43,6 +43,7 @@ public:
 
 	// singleton pattern implementation
 	static LLViewerShaderMgr * instance();
+	static void releaseInstance();
 
 	void initAttribsAndUniforms(void);
 	void setShaders();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index aa75bae712..3dad782715 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2153,6 +2153,12 @@ LLViewerWindow::~LLViewerWindow()
 
 	delete mDebugText;
 	mDebugText = NULL;
+
+	if (LLViewerShaderMgr::sInitialized)
+	{
+		LLViewerShaderMgr::releaseInstance();
+		LLViewerShaderMgr::sInitialized = FALSE;
+	}
 }
 
 
-- 
cgit v1.2.3


From 721ccc41bb6fca559146098a8cfdf02c785e6618 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Thu, 24 Apr 2014 21:55:35 +0100
Subject: MAINT-4009: Cleaning up some statically allocated memory in a
 LLVolumeGeometryManager method that was never freed.

---
 indra/newview/llspatialpartition.h |  16 ++++-
 indra/newview/llvovolume.cpp       | 118 +++++++++++++++++++++++++++----------
 2 files changed, 102 insertions(+), 32 deletions(-)

diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index a7b99a0f6b..08a4d00d0f 100755
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -640,12 +640,26 @@ class LLVolumeGeometryManager: public LLGeometryManager
 		DISTANCE_SORT
 	} eSortType;
 
-	virtual ~LLVolumeGeometryManager() { }
+	LLVolumeGeometryManager();
+	virtual ~LLVolumeGeometryManager();
 	virtual void rebuildGeom(LLSpatialGroup* group);
 	virtual void rebuildMesh(LLSpatialGroup* group);
 	virtual void getGeometry(LLSpatialGroup* group);
 	void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
 	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
+
+private:
+	void allocateFaces(U32 pMaxFaceCount);
+	void freeFaces();
+
+	static int32_t sInstanceCount;
+	static LLFace** sFullbrightFaces;
+	static LLFace** sBumpFaces;
+	static LLFace** sSimpleFaces;
+	static LLFace** sNormFaces;
+	static LLFace** sSpecFaces;
+	static LLFace** sNormSpecFaces;
+	static LLFace** sAlphaFaces;
 };
 
 //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp)
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index d1108020ff..1fa14cf003 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4059,7 +4059,8 @@ U32 LLVOVolume::getPartitionType() const
 }
 
 LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
-: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp)
+: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp),
+LLVolumeGeometryManager()
 {
 	mLODPeriod = 32;
 	mDepthMask = FALSE;
@@ -4070,7 +4071,8 @@ LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
 }
 
 LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
-: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp)
+: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp),
+LLVolumeGeometryManager()
 {
 	mDepthMask = FALSE;
 	mLODPeriod = 32;
@@ -4107,6 +4109,70 @@ bool can_batch_texture(LLFace* facep)
 	return true;
 }
 
+const static U32 MAX_FACE_COUNT = 4096U;
+int32_t LLVolumeGeometryManager::sInstanceCount = 0;
+LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL;
+LLFace** LLVolumeGeometryManager::sBumpFaces = NULL;
+LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL;
+LLFace** LLVolumeGeometryManager::sNormFaces = NULL;
+LLFace** LLVolumeGeometryManager::sSpecFaces = NULL;
+LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL;
+LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL;
+
+LLVolumeGeometryManager::LLVolumeGeometryManager()
+	: LLGeometryManager()
+{
+	llassert(sInstanceCount >= 0);
+	if (sInstanceCount == 0)
+	{
+		allocateFaces(MAX_FACE_COUNT);
+	}
+
+	++sInstanceCount;
+}
+
+LLVolumeGeometryManager::~LLVolumeGeometryManager()
+{
+	llassert(sInstanceCount > 0);
+	--sInstanceCount;
+
+	if (sInstanceCount <= 0)
+	{
+		freeFaces();
+		sInstanceCount = 0;
+	}
+}
+
+void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount)
+{
+	sFullbrightFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sBumpFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sSimpleFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sNormFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sNormSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+	sAlphaFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+}
+
+void LLVolumeGeometryManager::freeFaces()
+{
+	ll_aligned_free<64>(sFullbrightFaces);
+	ll_aligned_free<64>(sBumpFaces);
+	ll_aligned_free<64>(sSimpleFaces);
+	ll_aligned_free<64>(sNormFaces);
+	ll_aligned_free<64>(sSpecFaces);
+	ll_aligned_free<64>(sNormSpecFaces);
+	ll_aligned_free<64>(sAlphaFaces);
+
+	sFullbrightFaces = NULL;
+	sBumpFaces = NULL;
+	sSimpleFaces = NULL;
+	sNormFaces = NULL;
+	sSpecFaces = NULL;
+	sNormSpecFaces = NULL;
+	sAlphaFaces = NULL;
+}
+
 static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face");
 
 void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
@@ -4429,16 +4495,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	mFaceList.clear();
 
-	const U32 MAX_FACE_COUNT = 4096;
-	
-	static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** bump_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** simple_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** norm_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** spec_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** normspec_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc<64>(MAX_FACE_COUNT*sizeof(LLFace*));
-	
 	U32 fullbright_count = 0;
 	U32 bump_count = 0;
 	U32 simple_count = 0;
@@ -4820,7 +4876,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						{ //can be treated as alpha mask
 							if (simple_count < MAX_FACE_COUNT)
 							{
-								simple_faces[simple_count++] = facep;
+								sSimpleFaces[simple_count++] = facep;
 							}
 						}
 						else
@@ -4831,7 +4887,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							}
 							if (alpha_count < MAX_FACE_COUNT)
 							{
-								alpha_faces[alpha_count++] = facep;
+								sAlphaFaces[alpha_count++] = facep;
 							}
 						}
 					}
@@ -4854,14 +4910,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 									{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
 										if (normspec_count < MAX_FACE_COUNT)
 										{
-											normspec_faces[normspec_count++] = facep;
+											sNormSpecFaces[normspec_count++] = facep;
 										}
 									}
 									else
 									{ //has normal map (needs texcoord1 and tangent)
 										if (norm_count < MAX_FACE_COUNT)
 										{
-											norm_faces[norm_count++] = facep;
+											sNormFaces[norm_count++] = facep;
 										}
 									}
 								}
@@ -4869,14 +4925,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								{ //has specular map but no normal map, needs texcoord2
 									if (spec_count < MAX_FACE_COUNT)
 									{
-										spec_faces[spec_count++] = facep;
+										sSpecFaces[spec_count++] = facep;
 									}
 								}
 								else
 								{ //has neither specular map nor normal map, only needs texcoord0
 									if (simple_count < MAX_FACE_COUNT)
 									{
-										simple_faces[simple_count++] = facep;
+										sSimpleFaces[simple_count++] = facep;
 									}
 								}									
 							}
@@ -4884,14 +4940,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{ //needs normal + tangent
 								if (bump_count < MAX_FACE_COUNT)
 								{
-									bump_faces[bump_count++] = facep;
+									sBumpFaces[bump_count++] = facep;
 								}
 							}
 							else if (te->getShiny() || !te->getFullbright())
 							{ //needs normal
 								if (simple_count < MAX_FACE_COUNT)
 								{
-									simple_faces[simple_count++] = facep;
+									sSimpleFaces[simple_count++] = facep;
 								}
 							}
 							else 
@@ -4899,7 +4955,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								facep->setState(LLFace::FULLBRIGHT);
 								if (fullbright_count < MAX_FACE_COUNT)
 								{
-									fullbright_faces[fullbright_count++] = facep;
+									sFullbrightFaces[fullbright_count++] = facep;
 								}
 							}
 						}
@@ -4909,7 +4965,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{ //needs normal + tangent
 								if (bump_count < MAX_FACE_COUNT)
 								{
-									bump_faces[bump_count++] = facep;
+									sBumpFaces[bump_count++] = facep;
 								}
 							}
 							else if ((te->getShiny() && LLPipeline::sRenderBump) ||
@@ -4917,7 +4973,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							{ //needs normal
 								if (simple_count < MAX_FACE_COUNT)
 								{
-									simple_faces[simple_count++] = facep;
+									sSimpleFaces[simple_count++] = facep;
 								}
 							}
 							else 
@@ -4925,7 +4981,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 								facep->setState(LLFace::FULLBRIGHT);
 								if (fullbright_count < MAX_FACE_COUNT)
 								{
-									fullbright_faces[fullbright_count++] = facep;
+									sFullbrightFaces[fullbright_count++] = facep;
 								}
 							}
 						}
@@ -4988,13 +5044,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 		fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
 	}
 
-	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, simple_count, FALSE, batch_textures, FALSE);
-	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, fullbright_count, FALSE, batch_textures);
-	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, alpha_count, TRUE, batch_textures);
-	genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, bump_count, FALSE, FALSE);
-	genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, norm_faces, norm_count, FALSE, FALSE);
-	genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, spec_faces, spec_count, FALSE, FALSE);
-	genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, normspec_faces, normspec_count, FALSE, FALSE);
+	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
+	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
+	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
+	genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
+	genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
+	genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
+	genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
 
 	if (!LLPipeline::sDelayVBUpdate)
 	{
-- 
cgit v1.2.3


From 582c10cc47f7a07b4de961e8ef954b5cc935cd16 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 25 Apr 2014 23:30:53 +0100
Subject: MAINT-4009: Ensuring to delete array data with the array delete in
 the RawInjector destructor.

---
 indra/llmessage/llhttpclient.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 31a499b370..21d459b832 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -124,7 +124,7 @@ namespace
 	{
 	public:
 		RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {}
-		virtual ~RawInjector() {delete mData;}
+		virtual ~RawInjector() {delete [] mData;}
 
 		const char* contentType() { return "application/octet-stream"; }
 
-- 
cgit v1.2.3


From b31bfdba37398e3100e8e209d407cea6065ce52a Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Sat, 26 Apr 2014 01:47:41 +0100
Subject: MAINT-4009: Converting the Globals class within llerror to be derived
 from LLSingleton so that it may be cleaned up properly on app exit.

---
 indra/llcommon/llerror.cpp | 88 ++++++++++++++++++----------------------------
 1 file changed, 35 insertions(+), 53 deletions(-)

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index a7963174ad..a3053617d3 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -47,6 +47,7 @@
 #include "lllivefile.h"
 #include "llsd.h"
 #include "llsdserialize.h"
+#include "llsingleton.h"
 #include "llstl.h"
 #include "lltimer.h"
 
@@ -359,27 +360,28 @@ namespace
 	typedef std::vector<LLError::Recorder*> Recorders;
 	typedef std::vector<LLError::CallSite*> CallSiteVector;
 
-	class Globals
+	class Globals : public LLSingleton<Globals>
 	{
 	public:
+		Globals();
+
 		std::ostringstream messageStream;
 		bool messageStreamInUse;
 
 		void addCallSite(LLError::CallSite&);
 		void invalidateCallSites();
-		
-		static Globals& get();
-			// return the one instance of the globals
 
 	private:
 		CallSiteVector callSites;
-
-		Globals()
-			:	messageStreamInUse(false)
-			{ }
-		
 	};
 
+	Globals::Globals()
+		: messageStream(),
+		messageStreamInUse(false),
+		callSites()
+	{
+	}
+
 	void Globals::addCallSite(LLError::CallSite& site)
 	{
 		callSites.push_back(&site);
@@ -396,18 +398,6 @@ namespace
 		
 		callSites.clear();
 	}
-
-	Globals& Globals::get()
-	{
-		/* This pattern, of returning a reference to a static function
-		   variable, is to ensure that this global is constructed before
-		   it is used, no matter what the global initialization sequence
-		   is.
-		   See C++ FAQ Lite, sections 10.12 through 10.14
-		*/
-		static Globals* globals = new Globals;		
-		return *globals;
-	}
 }
 
 namespace LLError
@@ -474,7 +464,7 @@ namespace LLError
 	
 	void Settings::reset()
 	{
-		Globals::get().invalidateCallSites();
+		Globals::getInstance()->invalidateCallSites();
 		
 		Settings*& p = getPtr();
 		delete p;
@@ -483,7 +473,7 @@ namespace LLError
 	
 	Settings* Settings::saveAndReset()
 	{
-		Globals::get().invalidateCallSites();
+		Globals::getInstance()->invalidateCallSites();
 		
 		Settings*& p = getPtr();
 		Settings* originalSettings = p;
@@ -493,7 +483,7 @@ namespace LLError
 	
 	void Settings::restore(Settings* originalSettings)
 	{
-		Globals::get().invalidateCallSites();
+		Globals::getInstance()->invalidateCallSites();
 		
 		Settings*& p = getPtr();
 		delete p;
@@ -680,9 +670,8 @@ namespace LLError
 
 	void setDefaultLevel(ELevel level)
 	{
-		Globals& g = Globals::get();
+		Globals::getInstance()->invalidateCallSites();
 		Settings& s = Settings::get();
-		g.invalidateCallSites();
 		s.mDefaultLevel = level;
 	}
 
@@ -694,33 +683,29 @@ namespace LLError
 
 	void setFunctionLevel(const std::string& function_name, ELevel level)
 	{
-		Globals& g = Globals::get();
+		Globals::getInstance()->invalidateCallSites();
 		Settings& s = Settings::get();
-		g.invalidateCallSites();
 		s.mFunctionLevelMap[function_name] = level;
 	}
 
 	void setClassLevel(const std::string& class_name, ELevel level)
 	{
-		Globals& g = Globals::get();
+		Globals::getInstance()->invalidateCallSites();
 		Settings& s = Settings::get();
-		g.invalidateCallSites();
 		s.mClassLevelMap[class_name] = level;
 	}
 
 	void setFileLevel(const std::string& file_name, ELevel level)
 	{
-		Globals& g = Globals::get();
+		Globals::getInstance()->invalidateCallSites();
 		Settings& s = Settings::get();
-		g.invalidateCallSites();
 		s.mFileLevelMap[file_name] = level;
 	}
 
 	void setTagLevel(const std::string& tag_name, ELevel level)
 	{
-		Globals& g = Globals::get();
+		Globals::getInstance()->invalidateCallSites();
 		Settings& s = Settings::get();
-		g.invalidateCallSites();
 		s.mTagLevelMap[tag_name] = level;
 	}
 
@@ -765,10 +750,9 @@ namespace LLError
 {
 	void configure(const LLSD& config)
 	{
-		Globals& g = Globals::get();
+		Globals::getInstance()->invalidateCallSites();
 		Settings& s = Settings::get();
 		
-		g.invalidateCallSites();
 		s.mFunctionLevelMap.clear();
 		s.mClassLevelMap.clear();
 		s.mFileLevelMap.clear();
@@ -1060,7 +1044,6 @@ namespace LLError
 			return false;
 		}
 		
-		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		
 		s.mShouldLogCallCounter++;
@@ -1091,7 +1074,7 @@ namespace LLError
 			: false);
 
 		site.mCached = true;
-		g.addCallSite(site);
+		Globals::getInstance()->addCallSite(site);
 		return site.mShouldLog = site.mLevel >= compareLevel;
 	}
 
@@ -1101,12 +1084,12 @@ namespace LLError
 		LogLock lock;
 		if (lock.ok())
 		{
-			Globals& g = Globals::get();
+			Globals* g = Globals::getInstance();
 
-			if (!g.messageStreamInUse)
+			if (!g->messageStreamInUse)
 			{
-				g.messageStreamInUse = true;
-				return &g.messageStream;
+				g->messageStreamInUse = true;
+				return &g->messageStream;
 			}
 		}
 		
@@ -1131,13 +1114,12 @@ namespace LLError
 		   message[127] = '\0' ;
 	   }
 	   
-	   Globals& g = Globals::get();
-
-       if (out == &g.messageStream)
+	   Globals* g = Globals::getInstance();
+       if (out == &g->messageStream)
        {
-           g.messageStream.clear();
-           g.messageStream.str("");
-           g.messageStreamInUse = false;
+           g->messageStream.clear();
+           g->messageStream.str("");
+           g->messageStreamInUse = false;
        }
        else
        {
@@ -1154,15 +1136,15 @@ namespace LLError
 			return;
 		}
 		
-		Globals& g = Globals::get();
+		Globals* g = Globals::getInstance();
 		Settings& s = Settings::get();
 
 		std::string message = out->str();
-		if (out == &g.messageStream)
+		if (out == &g->messageStream)
 		{
-			g.messageStream.clear();
-			g.messageStream.str("");
-			g.messageStreamInUse = false;
+			g->messageStream.clear();
+			g->messageStream.str("");
+			g->messageStreamInUse = false;
 		}
 		else
 		{
-- 
cgit v1.2.3


From 37d620463b6f6d0ec932f1660f314268bafa229a Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Mon, 28 Apr 2014 19:18:47 +0100
Subject: MAINT-4009: Cleaning up the error callstacks memory before app quit.

---
 indra/llcommon/llerror.cpp    | 56 +++++++++++++++++++++++++++----------------
 indra/llcommon/llerror.h      |  4 ++++
 indra/newview/llappviewer.cpp |  2 ++
 3 files changed, 42 insertions(+), 20 deletions(-)

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index a3053617d3..4f721fabdf 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1357,15 +1357,9 @@ namespace LLError
 #endif
 
 	//static
-   void LLCallStacks::push(const char* function, const int line)
+   void LLCallStacks::allocateStackBuffer()
    {
-	   CallStacksLogLock lock;
-       if (!lock.ok())
-       {
-           return;
-       }
-
-	   if(!sBuffer)
+	   if(sBuffer == NULL)
 	   {
 		   sBuffer = new char*[512] ;
 		   sBuffer[0] = new char[512 * 128] ;
@@ -1375,6 +1369,31 @@ namespace LLError
 		   }
 		   sIndex = 0 ;
 	   }
+   }
+
+   void LLCallStacks::freeStackBuffer()
+   {
+	   if(sBuffer != NULL)
+	   {
+		   delete [] sBuffer[0] ;
+		   delete [] sBuffer ;
+		   sBuffer = NULL ;
+	   }
+   }
+
+   //static
+   void LLCallStacks::push(const char* function, const int line)
+   {
+	   CallStacksLogLock lock;
+       if (!lock.ok())
+       {
+           return;
+       }
+
+	   if(sBuffer == NULL)
+	   {
+		   allocateStackBuffer();
+	   }
 
 	   if(sIndex > 511)
 	   {
@@ -1406,15 +1425,9 @@ namespace LLError
            return;
        }
 
-	   if(!sBuffer)
+	   if(sBuffer == NULL)
 	   {
-		   sBuffer = new char*[512] ;
-		   sBuffer[0] = new char[512 * 128] ;
-		   for(S32 i = 1 ; i < 512 ; i++)
-		   {
-			   sBuffer[i] = sBuffer[i-1] + 128 ;
-		   }
-		   sIndex = 0 ;
+		   allocateStackBuffer();
 	   }
 
 	   if(sIndex > 511)
@@ -1445,11 +1458,9 @@ namespace LLError
            LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
        }
 
-	   if(sBuffer)
+	   if(sBuffer != NULL)
 	   {
-		   delete[] sBuffer[0] ;
-		   delete[] sBuffer ;
-		   sBuffer = NULL ;
+		   freeStackBuffer();
 	   }
    }
 
@@ -1459,5 +1470,10 @@ namespace LLError
        sIndex = 0 ;
    }
 
+   //static
+   void LLCallStacks::cleanup()
+   {
+	   freeStackBuffer();
+   }
 }
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index bc80e64423..63040e1772 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -261,6 +261,9 @@ namespace LLError
    private:
        static char**  sBuffer ;
 	   static S32     sIndex ;
+
+	   static void allocateStackBuffer();
+	   static void freeStackBuffer();
           
    public:   
 	   static void push(const char* function, const int line) ;
@@ -268,6 +271,7 @@ namespace LLError
        static void print() ;
        static void clear() ;
 	   static void end(std::ostringstream* _out) ;
+	   static void cleanup();
    }; 
 }
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 2b634074d5..f92467a562 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2117,6 +2117,8 @@ bool LLAppViewer::cleanup()
 
 	ll_close_fail_log();
 
+	LLError::LLCallStacks::cleanup();
+
 	removeMarkerFiles();
 	
     LL_INFOS() << "Goodbye!" << LL_ENDL;
-- 
cgit v1.2.3


From f43e46bc9c0007d30cef6f0a2b2b07b9bbadd996 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Mon, 28 Apr 2014 19:44:02 +0100
Subject: MAINT-4009: Ensuring that the pick mask for the LLImageGL is always
 properly freed during its cleanup method.

---
 indra/llrender/llimagegl.cpp | 61 +++++++++++++++++++++++++++-----------------
 indra/llrender/llimagegl.h   |  3 +++
 2 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ddf38c6745..5b989da911 100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -390,9 +390,7 @@ LLImageGL::~LLImageGL()
 {
 	LLImageGL::cleanup();
 	sImageList.erase(this);
-	disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-	delete [] mPickMask;
-	mPickMask = NULL;
+	freePickMask();
 	sCount--;
 }
 
@@ -461,6 +459,8 @@ void LLImageGL::cleanup()
 	{
 		destroyGLTexture();
 	}
+	freePickMask();
+
 	mSaveData = NULL; // deletes data
 }
 
@@ -504,10 +504,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
 		}
 
 		// pickmask validity depends on old image size, delete it
-		disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-		delete [] mPickMask;
-		mPickMask = NULL;
-		mPickMaskWidth = mPickMaskHeight = 0;
+		freePickMask();
 
 		mWidth = width;
 		mHeight = height;
@@ -1885,6 +1882,37 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
 	}
 }
 
+//----------------------------------------------------------------------------
+U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
+{
+	U32 pick_width = pWidth/2 + 1;
+	U32 pick_height = pHeight/2 + 1;
+
+	U32 size = pick_width * pick_height;
+	size = (size + 7) / 8; // pixelcount-to-bits
+	mPickMask = new U8[size];
+	claimMem(size);
+	mPickMaskWidth = pick_width - 1;
+	mPickMaskHeight = pick_height - 1;
+
+	memset(mPickMask, 0, sizeof(U8) * size);
+
+	return size;
+}
+
+//----------------------------------------------------------------------------
+void LLImageGL::freePickMask()
+{
+	// pickmask validity depends on old image size, delete it
+	if (mPickMask != NULL)
+	{
+		disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
+		delete [] mPickMask;
+	}
+	mPickMask = NULL;
+	mPickMaskWidth = mPickMaskHeight = 0;
+}
+
 //----------------------------------------------------------------------------
 void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 {
@@ -1893,10 +1921,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return ;
 	}
 
-	disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-	delete [] mPickMask;
-	mPickMask = NULL;
-	mPickMaskWidth = mPickMaskHeight = 0;
+	freePickMask();
 
 	if (mFormatType != GL_UNSIGNED_BYTE ||
 	    mFormatPrimary != GL_RGBA)
@@ -1905,17 +1930,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return;
 	}
 
-	U32 pick_width = width/2 + 1;
-	U32 pick_height = height/2 + 1;
-
-	U32 size = pick_width * pick_height;
-	size = (size + 7) / 8; // pixelcount-to-bits
-	mPickMask = new U8[size];
-	claimMem(size);
-	mPickMaskWidth = pick_width - 1;
-	mPickMaskHeight = pick_height - 1;
-
-	memset(mPickMask, 0, sizeof(U8) * size);
+	U32 pickSize = createPickMask(width, height);
 
 	U32 pick_bit = 0;
 	
@@ -1929,7 +1944,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 			{
 				U32 pick_idx = pick_bit/8;
 				U32 pick_offset = pick_bit%8;
-				llassert(pick_idx < size);
+				llassert(pick_idx < pickSize);
 
 				mPickMask[pick_idx] |= 1 << pick_offset;
 			}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 6ca814af6f..21982eab1d 100755
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -186,6 +186,9 @@ public:
 	mutable F32  mLastBindTime;	// last time this was bound, by discard level
 	
 private:
+	U32 createPickMask(S32 pWidth, S32 pHeight);
+	void freePickMask();
+
 	LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
 	U8* mPickMask;  //downsampled bitmap approximation of alpha channel.  NULL if no alpha channel
 	U16 mPickMaskWidth;
-- 
cgit v1.2.3


From 72c11c0e578b466eccc64e15fcaeb8d977c15e70 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 30 Apr 2014 01:45:09 +0100
Subject: MAINT-4009: Patching another memory leak in LLBadgeOwner that
 indirectly was also causing leaks in llimage.

---
 indra/llui/llbadgeowner.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
index 1860a05edd..9b2a9569f7 100755
--- a/indra/llui/llbadgeowner.cpp
+++ b/indra/llui/llbadgeowner.cpp
@@ -45,6 +45,7 @@ void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
 	if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
 	{
 		mBadge = createBadge(p);
+		addBadgeToParentPanel();
 	}
 }
 
@@ -53,7 +54,6 @@ void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
 	if (mBadge == NULL)
 	{
 		mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
-
 		addBadgeToParentPanel();
 	}
 
-- 
cgit v1.2.3


From e5375795e1ac519eb62b79807d5f5d4c5841990d Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 30 Apr 2014 23:10:35 +0100
Subject: MAINT-4009: Patching the LLTabContainer that was leaking some child
 views and their associated llimage allocations.

---
 indra/llui/lltabcontainer.cpp | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index ebc6183b8b..273e9c1ef6 100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1140,6 +1140,17 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 			addChild( btn, 0 );
 		}
 	}
+	else
+	{
+		if (textbox)
+		{
+			LLUICtrl::addChild(textbox, 0);
+		}
+		if (btn)
+		{
+			LLUICtrl::addChild(btn, 0);
+		}
+	}
 
 	if (child)
 	{
-- 
cgit v1.2.3


From 827a9f7c2d98a10d09ab87b16c92a22295f21cde Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 2 May 2014 00:28:22 +0100
Subject: MAINT-4009: Patching the memory leak occurring in the scenario where
 toast panels were being created, but the screen channel were deciding not to
 display the given toasts.

---
 indra/newview/llscreenchannel.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 6a840f3f40..8708fb87ee 100755
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -273,6 +273,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
 			// only cancel notification if it isn't being used in IM session
 			LLNotifications::instance().cancel(notification);
 		}
+
+		// It was assumed that the toast would take ownership of the panel pointer.
+		// But since we have decided not to display the toast, kill the panel to
+		// prevent the memory leak.
+		if (p.panel != NULL)
+		{
+			p.panel()->die();
+		}
 		return;
 	}
 
-- 
cgit v1.2.3


From 8247f51684ecc73cc60fa64b2fb0de3dce2a0c26 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 2 May 2014 00:32:31 +0100
Subject: MAINT-4009: Patching the memory leak occurring in the scenario where
 avatar icon was being created, but the tab container did not have a button to
 accept the gieven icon.

---
 indra/llui/lltabcontainer.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 273e9c1ef6..6f858cdeb3 100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1647,16 +1647,26 @@ void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
 {
 	LLTabTuple* tuple = getTabByPanel(child);
 	LLCustomButtonIconCtrl* button;
+	bool hasButton = false;
 
 	if(tuple)
 	{
 		button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
 		if(button)
 		{
+			hasButton = true;
 			button->setIcon(icon);
 			reshapeTuple(tuple);
 		}
 	}
+
+	if (!hasButton && (icon != NULL))
+	{
+		// It was assumed that the tab's button would take ownership of the icon pointer.
+		// But since the tab did not have a button, kill the icon to prevent the memory
+		// leak.
+		icon->die();
+	}
 }
 
 void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
-- 
cgit v1.2.3


From 205503dd84479be4989e5f5567a1d187cc0e71eb Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 2 May 2014 23:04:06 +0100
Subject: MAINT-4009: Patching the memory leak occurring from the info icons
 that appear when hovering over a chat history item.

---
 indra/newview/llchathistory.cpp | 47 ++++++++++++-----------------------------
 indra/newview/llchathistory.h   |  7 +++---
 2 files changed, 18 insertions(+), 36 deletions(-)

diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 05c4181714..84b9ac756a 100755
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -107,6 +107,7 @@ class LLChatHistoryHeader: public LLPanel
 public:
 	LLChatHistoryHeader()
 	:	LLPanel(),
+		mInfoCtrl(NULL),
 		mPopupMenuHandleAvatar(),
 		mPopupMenuHandleObject(),
 		mAvatarID(),
@@ -129,9 +130,6 @@ public:
 
 	~LLChatHistoryHeader()
 	{
-		// Detach the info button so that it doesn't get destroyed (EXT-8463).
-		hideInfoCtrl();
-
 		if (mAvatarNameCacheConnection.connected())
 		{
 			mAvatarNameCacheConnection.disconnect();
@@ -292,6 +290,11 @@ public:
 		mUserNameTextBox = getChild<LLTextBox>("user_name");
 		mTimeBoxTextBox = getChild<LLTextBox>("time_box");
 
+		mInfoCtrl = LLUICtrlFactory::getInstance()->createFromFile<LLUICtrl>("inspector_info_ctrl.xml", this, LLPanel::child_registry_t::instance());
+		llassert(mInfoCtrl != NULL);
+		mInfoCtrl->setCommitCallback(boost::bind(&LLChatHistoryHeader::onClickInfoCtrl, mInfoCtrl));
+		mInfoCtrl->setVisible(FALSE);
+
 		return LLPanel::postBuild();
 	}
 
@@ -589,39 +592,19 @@ protected:
 
 	void showInfoCtrl()
 	{
-		if (mAvatarID.isNull() || mFrom.empty() || CHAT_SOURCE_SYSTEM == mSourceType) return;
-				
-		if (!sInfoCtrl)
-		{
-			// *TODO: Delete the button at exit.
-			sInfoCtrl = LLUICtrlFactory::createFromFile<LLUICtrl>("inspector_info_ctrl.xml", NULL, LLPanel::child_registry_t::instance());
-			if (sInfoCtrl)
-			{
-				sInfoCtrl->setCommitCallback(boost::bind(&LLChatHistoryHeader::onClickInfoCtrl, sInfoCtrl));
-			}
-		}
-
-		if (!sInfoCtrl)
+		const bool isVisible = !mAvatarID.isNull() && !mFrom.empty() && CHAT_SOURCE_SYSTEM != mSourceType;
+		if (isVisible)
 		{
-			llassert(sInfoCtrl != NULL);
-			return;
+			const LLRect sticky_rect = mUserNameTextBox->getRect();
+			S32 icon_x = llmin(sticky_rect.mLeft + mUserNameTextBox->getTextBoundingRect().getWidth() + 7, sticky_rect.mRight - 3);
+			mInfoCtrl->setOrigin(icon_x, sticky_rect.getCenterY() - mInfoCtrl->getRect().getHeight() / 2 ) ;
 		}
-
-		LLTextBox* name = getChild<LLTextBox>("user_name");
-		LLRect sticky_rect = name->getRect();
-		S32 icon_x = llmin(sticky_rect.mLeft + name->getTextBoundingRect().getWidth() + 7, sticky_rect.mRight - 3);
-		sInfoCtrl->setOrigin(icon_x, sticky_rect.getCenterY() - sInfoCtrl->getRect().getHeight() / 2 ) ;
-		addChild(sInfoCtrl);
+		mInfoCtrl->setVisible(isVisible);
 	}
 
 	void hideInfoCtrl()
 	{
-		if (!sInfoCtrl) return;
-
-		if (sInfoCtrl->getParent() == this)
-		{
-			removeChild(sInfoCtrl);
-		}
+		mInfoCtrl->setVisible(FALSE);
 	}
 
 private:
@@ -692,7 +675,7 @@ protected:
 	LLHandle<LLView>	mPopupMenuHandleAvatar;
 	LLHandle<LLView>	mPopupMenuHandleObject;
 
-	static LLUICtrl*	sInfoCtrl;
+	LLUICtrl*			mInfoCtrl;
 
 	LLUUID			    mAvatarID;
 	LLSD				mObjectData;
@@ -709,8 +692,6 @@ private:
 	boost::signals2::connection mAvatarNameCacheConnection;
 };
 
-LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;
-
 LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
 :	LLUICtrl(p),
 	mMessageHeaderFilename(p.message_header),
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index bb6d4fb59c..44736a0489 100755
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -93,14 +93,15 @@ class LLChatHistory : public LLUICtrl
 		 * @return pointer to LLView separator object.
 		 */
 		LLView* getSeparator();
+
+		void onClickMoreText();
+
+	private:
 		/**
 		 * Builds a message header.
 		 * @return pointer to LLView header object.
 		 */
 		LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params, const LLSD& args);
-
-		void onClickMoreText();
-
 	public:
 		~LLChatHistory();
 		LLSD getValue() const;   
-- 
cgit v1.2.3


From 001621dfc21942a6ae0075ca3eef31720f42477b Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Mon, 5 May 2014 23:24:34 +0100
Subject: MAINT-4009: Patching a small memory leak for when menu items were
 being created before the viewer window initialization had created the menu
 holder.  Also, added llasserts in other cases when referencing the menu
 holder to ensure the holder is non-null.

---
 indra/llui/llfolderview.cpp              | 1 +
 indra/llui/lllineeditor.cpp              | 1 +
 indra/llui/llmenubutton.cpp              | 1 +
 indra/llui/llscrolllistctrl.cpp          | 1 +
 indra/llui/lltextbase.cpp                | 1 +
 indra/llui/lltexteditor.cpp              | 1 +
 indra/llui/lltoolbar.cpp                 | 1 +
 indra/newview/llchiclet.cpp              | 1 +
 indra/newview/lllistcontextmenu.cpp      | 1 +
 indra/newview/llmediactrl.cpp            | 7 +++++++
 indra/newview/llmediactrl.h              | 2 ++
 indra/newview/llpaneloutfitedit.cpp      | 2 ++
 indra/newview/llpanelteleporthistory.cpp | 2 ++
 indra/newview/llviewerwindow.cpp         | 6 +++++-
 14 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 53f2e15ed0..2ec7ed861f 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -231,6 +231,7 @@ LLFolderView::LLFolderView(const Params& p)
 
 
 	// make the popup menu available
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 	if (!menu)
 	{
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index d410a2de33..b09c927782 100755
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -192,6 +192,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
 	setPrevalidateInput(p.prevalidate_input_callback());
 	setPrevalidate(p.prevalidate_callback());
 
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
 		("menu_text_editor.xml",
 		 LLMenuGL::sMenuContainer,
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 0609cd8b42..303afcda15 100755
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -93,6 +93,7 @@ void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition posit
 		return;
 	}
 
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 	if (!menu)
 	{
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 3708071e11..5f72ee3ac6 100755
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1815,6 +1815,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
 			// create the context menu from the XUI file and display it
 			std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
 			delete mPopupMenu;
+			llassert(LLMenuGL::sMenuContainer != NULL);
 			mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 				menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 			if (mPopupMenu)
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 62edbadb07..30e6c6248e 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1955,6 +1955,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
 
 	// create and return the context menu from the XUI file
 	delete mPopupMenu;
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
 																		 LLMenuHolderGL::child_registry_t::instance());	
 	if (mIsFriendSignal)
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 494666df8a..517142bf17 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2031,6 +2031,7 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)
 {
 	if (!mContextMenu)
 	{
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml", 
 																				LLMenuGL::sMenuContainer, 
 																				LLMenuHolderGL::child_registry_t::instance());
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index f9bdd87087..abc2b6e9ca 100755
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -148,6 +148,7 @@ void LLToolBar::createContextMenu()
 		enable_reg.add("Toolbars.CheckSetting", boost::bind(&LLToolBar::isSettingChecked, this, _2));
 
 		// Create the context menu
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_toolbars.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 
 		if (menu)
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index b1dce42dfd..c0823182c0 100755
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -204,6 +204,7 @@ void LLNotificationChiclet::createMenu()
 	enable_registrar.add("NotificationWellChicletMenu.EnableItem",
 		boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
 
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
 		("menu_notification_well_button.xml",
 		 LLMenuGL::sMenuContainer,
diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp
index a624c9fb87..6bda8b1d0d 100755
--- a/indra/newview/lllistcontextmenu.cpp
+++ b/indra/newview/lllistcontextmenu.cpp
@@ -110,6 +110,7 @@ void LLListContextMenu::handleMultiple(functor_t functor, const uuid_vec_t& ids)
 // static
 LLContextMenu* LLListContextMenu::createFromFile(const std::string& filename)
 {
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		filename, LLContextMenu::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 }
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 323445afa6..90d4dd093b 100755
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -390,6 +390,8 @@ BOOL LLMediaCtrl::postBuild ()
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
 	registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
 
+	// stinson 05/05/2014 : cannot assert on the menu container being NULL because it will be during the processing of main_view.xml
+	// llassert(LLMenuGL::sMenuContainer != NULL);
 	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		"menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 	setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));
@@ -1117,3 +1119,8 @@ void LLMediaCtrl::setTrustedContent(bool trusted)
 		mMediaSource->setTrustedBrowser(trusted);
 	}
 }
+
+void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent)
+{
+	mContextMenu->updateParent(pNewParent);
+}
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 5978a7a344..b07eb356ae 100755
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -168,6 +168,8 @@ public:
 
 		LLUUID getTextureID() {return mMediaTextureID;}
 
+		void updateContextMenuParent(LLView* pNewParent);
+
 	protected:
 		void convertInputCoords(S32& x, S32& y);
 
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index e48aa88937..158038c4f7 100755
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -159,6 +159,7 @@ public:
 
 		registrar.add("Wearable.Create", boost::bind(onCreate, _2));
 
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
 			"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 		llassert(menu);
@@ -228,6 +229,7 @@ public:
 		enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2));
 		enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2));
 
+		llassert(LLMenuGL::sMenuContainer != NULL);
 		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
 			"menu_add_wearable_gear.xml",
 			LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 8fddd9523f..652d2be6f6 100755
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -341,6 +341,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
 	registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
 
 	// create the context menu from the XUI
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		"menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 }
@@ -935,6 +936,7 @@ void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y
 	registrar.add("TeleportHistory.TabClose",	boost::bind(&LLTeleportHistoryPanel::onAccordionTabClose, this, tab));
 
 	// create the context menu from the XUI
+	llassert(LLMenuGL::sMenuContainer != NULL);
 	mAccordionTabMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		"menu_teleport_history_tab.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 3dad782715..621baee0e6 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1910,9 +1910,13 @@ void LLViewerWindow::initBase()
 	setProgressCancelButtonVisible(FALSE);
 
 	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
-
 	LLMenuGL::sMenuContainer = gMenuHolder;
 
+	// stinson 05/05/2014 : the panel_progress.xml references a LLMediaCtrl(<web_browser></web_browser>) class
+	// which creates some menu items.  However, because the Menu Holder is not initialized then, we need to
+	// update the parent for the menu items so they will be properly cleaned up.
+	LLMediaCtrl* mediaCtrl = getRootView()->findChild<LLMediaCtrl>("login_media_panel");
+	mediaCtrl->updateContextMenuParent(LLMenuGL::sMenuContainer);
 }
 
 void LLViewerWindow::initWorldUI()
-- 
cgit v1.2.3


From 12d44073c8399bb29588f252b95d19f0d379998d Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Tue, 6 May 2014 01:11:46 +0100
Subject: MAINT-4009: Ensuring that the spare browser media source is cleaned
 up with the LLViewerMedia class.

---
 indra/newview/llviewermedia.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 7958537856..0967ca23c0 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1603,6 +1603,11 @@ void LLViewerMedia::cleanupClass()
 {
 	gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
 	sTeleportFinishConnection.disconnect();
+	if (sSpareBrowserMediaSource != NULL)
+	{
+		delete sSpareBrowserMediaSource;
+		sSpareBrowserMediaSource = NULL;
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From c307bda68a3e473a45491ca3ecfeb63e4e3f72bc Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Thu, 8 May 2014 21:58:51 +0100
Subject: Correcting a build error with the release viewer.

---
 indra/llrender/llimagegl.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 5b989da911..ebed454271 100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1930,7 +1930,11 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return;
 	}
 
-	U32 pickSize = createPickMask(width, height);
+#ifdef SHOW_ASSERT
+	const U32 pickSize = createPickMask(width, height);
+#else // SHOW_ASSERT
+	createPickMask(width, height);
+#endif // SHOW_ASSERT
 
 	U32 pick_bit = 0;
 	
-- 
cgit v1.2.3


From 8e7912f3821b3e20b528239b7ebfe0c6a9bffc71 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 9 May 2014 23:06:53 +0100
Subject: MAINT-4009: Improved patching of a memory leak for when menu items
 are created before the viewer window initialization has created the menu
 holder.  See also changeset bc0743639926a84b38b4907d252eff1cc0498c7d.

---
 indra/newview/llmediactrl.cpp    | 8 +++++---
 indra/newview/llviewerwindow.cpp | 6 ------
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 90d4dd093b..c4b68bb7e1 100755
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -390,10 +390,12 @@ BOOL LLMediaCtrl::postBuild ()
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
 	registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
 
-	// stinson 05/05/2014 : cannot assert on the menu container being NULL because it will be during the processing of main_view.xml
-	// llassert(LLMenuGL::sMenuContainer != NULL);
+	// stinson 05/05/2014 : use this as the parent of the context menu if the static menu
+	// container has yet to be created
+	LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this);
+	llassert(menuParent != NULL);
 	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
-		"menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+		"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
 	setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));
 
 	return TRUE;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 621baee0e6..2cb8e6a3ab 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1911,12 +1911,6 @@ void LLViewerWindow::initBase()
 
 	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
 	LLMenuGL::sMenuContainer = gMenuHolder;
-
-	// stinson 05/05/2014 : the panel_progress.xml references a LLMediaCtrl(<web_browser></web_browser>) class
-	// which creates some menu items.  However, because the Menu Holder is not initialized then, we need to
-	// update the parent for the menu items so they will be properly cleaned up.
-	LLMediaCtrl* mediaCtrl = getRootView()->findChild<LLMediaCtrl>("login_media_panel");
-	mediaCtrl->updateContextMenuParent(LLMenuGL::sMenuContainer);
 }
 
 void LLViewerWindow::initWorldUI()
-- 
cgit v1.2.3


From 35fe7aaedd5657898e152676f7744c14f7afa937 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Mon, 12 May 2014 21:34:30 +0100
Subject: MAINT-4009: Patching a leak of keyframed motions that had been
 deprecated but were never properly destroyed.

---
 indra/llcharacter/llmotioncontroller.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp
index 50ccfd75fb..e02b139608 100755
--- a/indra/llcharacter/llmotioncontroller.cpp
+++ b/indra/llcharacter/llmotioncontroller.cpp
@@ -172,6 +172,13 @@ void LLMotionController::deleteAllMotions()
 
 	for_each(mAllMotions.begin(), mAllMotions.end(), DeletePairedPointer());
 	mAllMotions.clear();
+
+	// stinson 05/12/20014 : Ownership of the LLMotion pointers is transferred from
+	// mAllMotions to mDeprecatedMotions in method
+	// LLMotionController::deprecateMotionInstance().  Thus, we should also clean
+	// up the mDeprecatedMotions list as well.
+	for_each(mDeprecatedMotions.begin(), mDeprecatedMotions.end(), DeletePointer());
+	mDeprecatedMotions.clear();
 }
 
 //-----------------------------------------------------------------------------
-- 
cgit v1.2.3


From b34cdbaa697f99673588d6b2f49fd917fed3ee09 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Mon, 12 May 2014 23:43:36 +0100
Subject: MAINT-4009: Patching a minor leak for when the status text box for
 the folder view has not been reparented.

---
 indra/llui/llfolderview.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 2ec7ed861f..602bd1a23a 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -227,7 +227,7 @@ LLFolderView::LLFolderView(const Params& p)
 	mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p);
 	mStatusTextBox->setFollowsLeft();
 	mStatusTextBox->setFollowsTop();
-	//addChild(mStatusTextBox);
+	addChild(mStatusTextBox);
 
 
 	// make the popup menu available
-- 
cgit v1.2.3


From 75538968dbc224a956115762a67e5da20c1d369f Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 14 May 2014 19:49:13 +0100
Subject: MAINT-4009: Patching the final leak of LLViewerFetchedTexture objects
 occurring because the LLWearable class was not properly destroying itself.

---
 indra/llappearance/llwearable.cpp | 28 ++++++++++++++++++----------
 indra/llappearance/llwearable.h   |  1 +
 2 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 389505fa34..6749a85f3c 100644
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -43,9 +43,24 @@ S32 LLWearable::sCurrentDefinitionVersion = 1;
 // Private local functions
 static std::string terse_F32_to_string(F32 f);
 
+LLWearable::LLWearable()
+	: mDefinitionVersion(-1),
+	mName(),
+	mDescription(),
+	mPermissions(),
+	mSaleInfo(),
+	mType(LLWearableType::WT_NONE),
+	mSavedVisualParamMap(),
+	mVisualParamIndexMap(),
+	mTEMap(),
+	mSavedTEMap()
+{
+}
+
 // virtual
 LLWearable::~LLWearable()
 {
+	destroyTextures();
 }
 
 const std::string& LLWearable::getTypeLabel() const
@@ -620,17 +635,10 @@ void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
 
 void LLWearable::destroyTextures()
 {
-	for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
-	{
-		LLLocalTextureObject *lto = iter->second;
-		delete lto;
-	}
+	std::for_each(mTEMap.begin(), mTEMap.end(), DeletePairedPointer());
 	mTEMap.clear();
-	for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
-	{
-		LLLocalTextureObject *lto = iter->second;
-		delete lto;
-	}
+
+	std::for_each(mSavedTEMap.begin(), mSavedTEMap.end(), DeletePairedPointer());
 	mSavedTEMap.clear();
 }
 
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
index 132c153bcd..96809aab58 100644
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -46,6 +46,7 @@ class LLWearable
 	// Constructors and destructors
 	//--------------------------------------------------------------------
 public:
+	LLWearable();
 	virtual ~LLWearable();
 
 	//--------------------------------------------------------------------
-- 
cgit v1.2.3


From 487ca1bad37883be0325b564ab557a8f77575388 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 14 May 2014 17:50:59 -0400
Subject: v-r -> s-e merge WIP

---
 indra/llappearance/lltexlayer.cpp                 |   2 +-
 indra/llcommon/llpointer.h                        | 126 +++++++++++++++++++
 indra/llcommon/tests/stringize_test.cpp           |   2 +-
 indra/llinventory/llinventory.h                   |   1 +
 indra/llmessage/llcurl.cpp                        |   8 +-
 indra/llmessage/lliohttpserver.cpp                |   2 +-
 indra/llmessage/llsdappservices.cpp               |   2 +-
 indra/newview/llagentwearables.cpp                |  21 ++--
 indra/newview/llagentwearables.h                  |   2 +-
 indra/newview/llaisapi.cpp                        |  34 ++---
 indra/newview/llappearancemgr.cpp                 | 115 +++++++++--------
 indra/newview/llassetuploadqueue.cpp              |   2 +-
 indra/newview/llassetuploadresponders.cpp         |   2 +-
 indra/newview/lleventpoll.cpp                     |   2 +-
 indra/newview/llfacebookconnect.cpp               |   4 +-
 indra/newview/llfeaturemanager.cpp                |   2 +-
 indra/newview/llhomelocationresponder.cpp         |   6 +-
 indra/newview/llhttpretrypolicy.cpp               |   8 +-
 indra/newview/llinventorymodel.cpp                | 144 +++++++++++-----------
 indra/newview/llinventorymodelbackgroundfetch.cpp |   4 +-
 indra/newview/llinventoryobserver.cpp             |   2 +-
 indra/newview/llmeshrepository.cpp                |   1 -
 indra/newview/llpaneleditwearable.cpp             |   2 +-
 indra/newview/llpathfindingmanager.cpp            |  14 +--
 indra/newview/llpathfindingnavmesh.cpp            |   2 -
 indra/newview/llstartup.cpp                       |   8 +-
 indra/newview/lltexturefetch.cpp                  |  36 +++---
 indra/newview/llviewerinventory.cpp               |  42 +++----
 indra/newview/llviewermedia.cpp                   |   8 +-
 indra/newview/llviewerregion.cpp                  |  23 ++--
 indra/newview/llviewerstats.cpp                   |   6 +-
 indra/newview/llviewertexture.cpp                 |  28 ++---
 indra/newview/llvoavatar.cpp                      |  24 ++--
 indra/newview/llvoavatarself.cpp                  |   9 +-
 indra/newview/llwearablelist.cpp                  |   2 +-
 indra/newview/llwebprofile.cpp                    |   4 +-
 indra/newview/llwebsharing.cpp                    |   4 +-
 37 files changed, 409 insertions(+), 295 deletions(-)

diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index b78d9da958..2cf86bb4fe 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1565,7 +1565,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
                 // We can get bad morph masks during login, on minimize, and occasional gl errors.
                 // We should only be doing this when we believe something has changed with respect to the user's appearance.
 		{
-                       LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << llendl;
+                       LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
                         // clear out a slot if we have filled our cache
 			S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
 			while ((S32)mAlphaCache.size() >= max_cache_entries)
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index c9ebc70d19..9a6453ea48 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -166,6 +166,132 @@ protected:
 	Type*	mPointer;
 };
 
+template <class Type> class LLConstPointer
+{
+public:
+	LLConstPointer() : 
+		mPointer(NULL)
+	{
+	}
+
+	LLConstPointer(const Type* ptr) : 
+		mPointer(ptr)
+	{
+		ref();
+	}
+
+	LLConstPointer(const LLConstPointer<Type>& ptr) : 
+		mPointer(ptr.mPointer)
+	{
+		ref();
+	}
+
+	// support conversion up the type hierarchy.  See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLConstPointer(const LLConstPointer<Subclass>& ptr) : 
+		mPointer(ptr.get())
+	{
+		ref();
+	}
+
+	~LLConstPointer()
+	{
+		unref();
+	}
+
+	const Type*	get() const						{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }
+	const Type&	operator*() const				{ return *mPointer; }
+
+	operator BOOL()  const						{ return (mPointer != NULL); }
+	operator bool()  const						{ return (mPointer != NULL); }
+	bool operator!() const						{ return (mPointer == NULL); }
+	bool isNull() const							{ return (mPointer == NULL); }
+	bool notNull() const						{ return (mPointer != NULL); }
+
+	operator const Type*()       const			{ return mPointer; }
+	bool operator !=(const Type* ptr) const     { return (mPointer != ptr); 	}
+	bool operator ==(const Type* ptr) const     { return (mPointer == ptr); 	}
+	bool operator ==(const LLConstPointer<Type>& ptr) const           { return (mPointer == ptr.mPointer); 	}
+	bool operator < (const LLConstPointer<Type>& ptr) const           { return (mPointer < ptr.mPointer); 	}
+	bool operator > (const LLConstPointer<Type>& ptr) const           { return (mPointer > ptr.mPointer); 	}
+
+	LLConstPointer<Type>& operator =(const Type* ptr)                   
+	{
+		if( mPointer != ptr )
+		{
+			unref(); 
+			mPointer = ptr; 
+			ref();
+		}
+
+		return *this; 
+	}
+
+	LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)  
+	{ 
+		if( mPointer != ptr.mPointer )
+		{
+			unref(); 
+			mPointer = ptr.mPointer;
+			ref();
+		}
+		return *this; 
+	}
+
+	// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)  
+	{ 
+		if( mPointer != ptr.get() )
+		{
+			unref(); 
+			mPointer = ptr.get();
+			ref();
+		}
+		return *this; 
+	}
+	
+	// Just exchange the pointers, which will not change the reference counts.
+	static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
+	{
+		const Type* temp = a.mPointer;
+		a.mPointer = b.mPointer;
+		b.mPointer = temp;
+	}
+
+protected:
+#ifdef LL_LIBRARY_INCLUDE
+	void ref();                             
+	void unref();
+#else
+	void ref()                             
+	{ 
+		if (mPointer)
+		{
+			mPointer->ref();
+		}
+	}
+
+	void unref()
+	{
+		if (mPointer)
+		{
+			const Type *tempp = mPointer;
+			mPointer = NULL;
+			tempp->unref();
+			if (mPointer != NULL)
+			{
+				LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+				unref();
+			}
+		}
+	}
+#endif
+protected:
+	const Type*	mPointer;
+};
+
 template<typename Type>
 class LLCopyOnWritePointer : public LLPointer<Type>
 {
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index 3e4ca548e5..2a4ed44a67 100755
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -95,7 +95,7 @@ namespace tut
         ensure_equals(stringize(f),    "3.14159");
         ensure_equals(stringize(d),    "3.14159");
         ensure_equals(stringize(abc),  "abc def");
-        ensure_equals(stringize(def),  "def ghi"); //Will generate llwarns due to narrowing.
+        ensure_equals(stringize(def),  "def ghi"); //Will generate LL_WARNS() due to narrowing.
         ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}");
     }
 
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 443d34e145..70b200e139 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -48,6 +48,7 @@ class LLInventoryObject : public LLRefCount, public LLTrace::MemTrackable<LLInve
 {
 public:
 	typedef std::list<LLPointer<LLInventoryObject> > object_list_t;
+	typedef std::list<LLConstPointer<LLInventoryObject> > const_object_list_t;
 
 	//--------------------------------------------------------------------
 	// Initialization
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 5f8581b4fd..a80d5a570e 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -261,8 +261,8 @@ void LLCurl::Responder::completedRaw(
 	// Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
 	if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
 	{
-		llwarns << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " 
-			<< "(" << mReason << ") body: " << debug_body << llendl;
+		LL_WARNS() << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " 
+			<< "(" << mReason << ") body: " << debug_body << LL_ENDL;
 	}
 
 	httpCompleted();
@@ -543,7 +543,7 @@ void LLCurl::Easy::slist_append(const char* str)
 		mHeaders = curl_slist_append(mHeaders, str);
 		if (!mHeaders)
 		{
-			llwarns << "curl_slist_append() call returned NULL appending " << str << llendl;
+			LL_WARNS() << "curl_slist_append() call returned NULL appending " << str << LL_ENDL;
 		}
 	}
 }
@@ -934,7 +934,7 @@ S32 LLCurl::Multi::process()
 			else
 			{
 				response = HTTP_INTERNAL_ERROR;
-				//*TODO: change to llwarns
+				//*TODO: change to LL_WARNS()
 				LL_ERRS() << "cleaned up curl request completed!" << LL_ENDL;
 			}
 			if (response >= 400)
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index cdd8d25f16..d9042fa8b0 100755
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -352,7 +352,7 @@ void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& h
 {
 	if(! mPipe)
 	{
-		llwarns << "LLHTTPPipe::Response::extendedResult: NULL pipe" << llendl;
+		LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
 		return;
 	}
 
diff --git a/indra/llmessage/llsdappservices.cpp b/indra/llmessage/llsdappservices.cpp
index 577429a941..4ca45267bd 100755
--- a/indra/llmessage/llsdappservices.cpp
+++ b/indra/llmessage/llsdappservices.cpp
@@ -120,7 +120,7 @@ public:
 	virtual bool validate(const std::string& name, LLSD& context) const
 	{
 		//LL_INFOS() << "validate: " << name << ", "
-		//	<< LLSDOStreamer<LLSDNotationFormatter>(context) << llendl;
+		//	<< LLSDOStreamer<LLSDNotationFormatter>(context) << LL_ENDL;
 		if((std::string("PUT") == context[CONTEXT_REQUEST][CONTEXT_VERB].asString()) && !name.empty())
 		{
 			return true;
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 6ce6b33790..11666f6c8f 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -770,7 +770,7 @@ void LLAgentWearables::createStandardWearables()
 // remove this function once the SH-3455 changesets are universally deployed.
 void LLAgentWearables::sendDummyAgentWearablesUpdate()
 {
-	LL_DEBUGS("Avatar") << "sendAgentWearablesUpdate()" << llendl;
+	LL_DEBUGS("Avatar") << "sendAgentWearablesUpdate()" << LL_ENDL;
 
 	// Send the AgentIsNowWearing 
 	gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
@@ -936,13 +936,12 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 
 // Assumes existing wearables are not dirty.
 void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items,
-										 const std::vector< LLViewerWearable* >& wearables,
-										 BOOL remove)
+										 const std::vector< LLViewerWearable* >& wearables)
 {
 	LL_INFOS() << "setWearableOutfit() start" << LL_ENDL;
 
-	S32 count = wearables.count();
-	llassert(items.count() == count);
+	S32 count = wearables.size();
+	llassert(items.size() == count);
 
 	// Check for whether outfit already matches the one requested
 	S32 matched = 0, mismatched = 0;
@@ -957,7 +956,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 		const LLWearableType::EType type = new_wearable->getType();
 		if (type < 0 || type>=LLWearableType::WT_COUNT)
 		{
-			llwarns << "invalid type " << type << llendl;
+			LL_WARNS() << "invalid type " << type << LL_ENDL;
 			mismatched++;
 			continue;
 		}
@@ -970,7 +969,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 		{
 			LL_DEBUGS("Avatar") << "mismatch, type " << type << " index " << index
 								<< " names " << (curr_wearable ? curr_wearable->getName() : "NONE")  << ","
-								<< " names " << (new_wearable ? new_wearable->getName() : "NONE")  << llendl;
+								<< " names " << (new_wearable ? new_wearable->getName() : "NONE")  << LL_ENDL;
 			mismatched++;
 			continue;
 		}
@@ -981,26 +980,26 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 			LL_DEBUGS("Avatar") << "mismatch on name or inventory id, names "
 								<< curr_wearable->getName() << " vs " << new_item->getName()
 								<< " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID()
-								<< llendl;
+								<< LL_ENDL;
 			mismatched++;
 			continue;
 		}
 		// If we got here, everything matches.
 		matched++;
 	}
-	LL_DEBUGS("Avatar") << "matched " << matched << " mismatched " << mismatched << llendl;
+	LL_DEBUGS("Avatar") << "matched " << matched << " mismatched " << mismatched << LL_ENDL;
 	for (S32 j=0; j<LLWearableType::WT_COUNT; j++)
 	{
 		LLWearableType::EType type = (LLWearableType::EType) j;
 		if (getWearableCount(type) != type_counts[j])
 		{
-			LL_DEBUGS("Avatar") << "count mismatch for type " << j << " current " << getWearableCount(j) << " requested " << type_counts[j] << llendl; 
+			LL_DEBUGS("Avatar") << "count mismatch for type " << j << " current " << getWearableCount(j) << " requested " << type_counts[j] << LL_ENDL; 
 			mismatched++;
 		}
 	}
 	if (mismatched == 0)
 	{
-		LL_DEBUGS("Avatar") << "no changes, bailing out" << llendl;
+		LL_DEBUGS("Avatar") << "no changes, bailing out" << LL_ENDL;
 		return;
 	}
 	
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 08d7de8a4c..cdb1bdbe05 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -103,7 +103,7 @@ private:
 	/*virtual*/void	wearableUpdated(LLWearable *wearable, BOOL removed);
 public:
 	void			setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false);
-	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const std::vector< LLViewerWearable* >& wearables, BOOL remove);
+	void			setWearableOutfit(const LLInventoryItem::item_array_t& items, const std::vector< LLViewerWearable* >& wearables);
 	void			setWearableName(const LLUUID& item_id, const std::string& new_name);
 	// *TODO: Move this into llappearance/LLWearableData ?
 	void			addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index);
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 38eb34676e..da66ea357a 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -171,7 +171,7 @@ RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	std::string url = cap + std::string("/item/") + item_id.asString();
@@ -190,7 +190,7 @@ RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	std::string url = cap + std::string("/category/") + item_id.asString();
@@ -209,7 +209,7 @@ PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
@@ -230,7 +230,7 @@ UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	std::string url = cap + std::string("/item/") + item_id.asString();
@@ -253,7 +253,7 @@ UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id,
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	std::string url = cap + std::string("/category/") + cat_id.asString();
@@ -275,7 +275,7 @@ CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id,
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	LLUUID tid;
@@ -297,13 +297,13 @@ SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& conten
 	std::string cap;
 	if (!getInvCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	LLUUID tid;
 	tid.generate();
 	std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
-	llinfos << url << llendl;
+	LL_INFOS() << url << LL_ENDL;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
 	headers["Content-Type"] = "application/llsd+xml";
@@ -320,14 +320,14 @@ CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id,
 	std::string cap;
 	if (!getLibCap(cap))
 	{
-		llwarns << "No cap found" << llendl;
+		LL_WARNS() << "No cap found" << LL_ENDL;
 		return;
 	}
 	LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL;
 	LLUUID tid;
 	tid.generate();
 	std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString();
-	llinfos << url << llendl;
+	LL_INFOS() << url << LL_ENDL;
 	LLCurl::ResponderPtr responder = this;
 	LLSD headers;
 	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
@@ -482,7 +482,7 @@ void AISUpdate::parseItem(const LLSD& item_map)
 	else
 	{
 		// *TODO: Wow, harsh.  Should we just complain and get out?
-		llerrs << "unpack failed" << llendl;
+		LL_ERRS() << "unpack failed" << LL_ENDL;
 	}
 }
 
@@ -524,7 +524,7 @@ void AISUpdate::parseLink(const LLSD& link_map)
 	else
 	{
 		// *TODO: Wow, harsh.  Should we just complain and get out?
-		llerrs << "unpack failed" << llendl;
+		LL_ERRS() << "unpack failed" << LL_ENDL;
 	}
 }
 
@@ -590,7 +590,7 @@ void AISUpdate::parseCategory(const LLSD& category_map)
 	else
 	{
 		// *TODO: Wow, harsh.  Should we just complain and get out?
-		llerrs << "unpack failed" << llendl;
+		LL_ERRS() << "unpack failed" << LL_ENDL;
 	}
 
 	// Check for more embedded content.
@@ -739,7 +739,7 @@ void AISUpdate::doUpdate()
 	for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
 		 catit != mCatDescendentDeltas.end(); ++catit)
 	{
-		LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << llendl;
+		LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL;
 
 		const LLUUID cat_id(catit->first);
 		// Don't account for update if we just created this category.
@@ -853,12 +853,12 @@ void AISUpdate::doUpdate()
 		const LLUUID id = ucv_it->first;
 		S32 version = ucv_it->second;
 		LLViewerInventoryCategory *cat = gInventory.getCategory(id);
-		LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << llendl;
+		LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << LL_ENDL;
 		if (cat->getVersion() != version)
 		{
-			llwarns << "Possible version mismatch for category " << cat->getName()
+			LL_WARNS() << "Possible version mismatch for category " << cat->getName()
 					<< ", viewer version " << cat->getVersion()
-					<< " server version " << version << llendl;
+					<< " server version " << version << LL_ENDL;
 		}
 	}
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 5e3753a476..dc503dc50e 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -665,7 +665,7 @@ LLWearableHoldingPattern::LLWearableHoldingPattern():
 	}
 	mIndex = sNextIndex++;
 	sActiveHoldingPatterns.insert(this);
-	LL_DEBUGS("Avatar") << "HP " << index() << " created" << llendl;
+	LL_DEBUGS("Avatar") << "HP " << index() << " created" << LL_ENDL;
 	selfStartPhase("holding_pattern");
 }
 
@@ -676,7 +676,7 @@ LLWearableHoldingPattern::~LLWearableHoldingPattern()
 	{
 		selfStopPhase("holding_pattern");
 	}
-	LL_DEBUGS("Avatar") << "HP " << index() << " deleted" << llendl;
+	LL_DEBUGS("Avatar") << "HP " << index() << " deleted" << LL_ENDL;
 }
 
 bool LLWearableHoldingPattern::isMostRecent()
@@ -880,11 +880,11 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L
 {
 	if (!holder->isMostRecent())
 	{
-		llwarns << "HP " << holder->index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
+		LL_WARNS() << "HP " << holder->index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
 		// runway skip here?
 	}
 
-	llinfos << "HP " << holder->index() << " recovered item link for type " << type << llendl;
+	LL_INFOS() << "HP " << holder->index() << " recovered item link for type " << type << LL_ENDL;
 	holder->eraseTypeToLink(type);
 	// Add wearable to FoundData for actual wearing
 	LLViewerInventoryItem *item = gInventory.getItem(item_id);
@@ -913,7 +913,7 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L
 	}
 	else
 	{
-		llwarns << self_av_string() << "HP " << holder->index() << " inventory link not found for recovered wearable" << llendl;
+		LL_WARNS() << self_av_string() << "HP " << holder->index() << " inventory link not found for recovered wearable" << LL_ENDL;
 	}
 }
 
@@ -1523,7 +1523,7 @@ void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_
 		{
 			case LLAssetType::AT_LINK:
 			{
-				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << llendl;
+				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << LL_ENDL;
 				//getActualDescription() is used for a new description 
 				//to propagate ordering information saved in descriptions of links
 				LLSD item_contents;
@@ -1539,7 +1539,7 @@ void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_
 				LLViewerInventoryCategory *catp = item->getLinkedCategory();
 				if (catp && include_folder_links)
 				{
-					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << llendl;
+					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << LL_ENDL;
 					LLSD base_contents;
 					base_contents["name"] = catp->getName();
 					base_contents["desc"] = ""; // categories don't have descriptions.
@@ -1565,7 +1565,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 	LLInventoryModel::cat_array_t* cats;
 	LLInventoryModel::item_array_t* items;
 	gInventory.getDirectDescendentsOf(src_id, cats, items);
-	llinfos << "copying " << items->count() << " items" << llendl;
+	LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL;
 	LLInventoryObject::const_object_list_t link_array;
 	for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
 		 iter != items->end();
@@ -1576,7 +1576,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 		{
 			case LLAssetType::AT_LINK:
 			{
-				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << llendl;
+				LL_DEBUGS("Avatar") << "linking inventory item " << item->getName() << LL_ENDL;
 				link_array.push_back(LLConstPointer<LLInventoryObject>(item));
 				break;
 			}
@@ -1586,7 +1586,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL
 				// Skip copying outfit links.
 				if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
 				{
-					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << llendl;
+					LL_DEBUGS("Avatar") << "linking inventory folder " << item->getName() << LL_ENDL;
 					link_array.push_back(LLConstPointer<LLInventoryObject>(item));
 				}
 				break;
@@ -1766,7 +1766,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
 	if (!pcat)
 	{
-		llwarns << "no category found for id " << category << llendl;
+		LL_WARNS() << "no category found for id " << category << LL_ENDL;
 		return;
 	}
 	LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL;
@@ -1778,7 +1778,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	{
 		LLInventoryModel::item_array_t gest_items;
 		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE);
-		for(S32 i = 0; i  < gest_items.count(); ++i)
+		for(S32 i = 0; i  < gest_items.size(); ++i)
 		{
 			LLViewerInventoryItem *gest_item = gest_items.at(i);
 			if ( LLGestureMgr::instance().isGestureActive( gest_item->getLinkedUUID()) )
@@ -1853,7 +1853,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 		{
 			desc = desc_iter->second;
 			LL_DEBUGS("Avatar") << item->getName() << " overriding desc to: " << desc
-								<< " (was: " << item->getActualDescription() << ")" << llendl;
+								<< " (was: " << item->getActualDescription() << ")" << LL_ENDL;
 		}
 		else
 		{
@@ -1944,7 +1944,6 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder)
 	{
 		gAgentWearables.setWearableOutfit(items, wearables);
 	}
-	LL_DEBUGS("Avatar") << "ends, elapsed " << timer.getElapsedTimeF32() << llendl;
 }
 
 S32 LLAppearanceMgr::countActiveHoldingPatterns()
@@ -2089,7 +2088,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 
 	if (!validateClothingOrderingInfo())
 	{
-		llwarns << "Clothing ordering error" << llendl;
+		LL_WARNS() << "Clothing ordering error" << LL_ENDL;
 	}
 
 	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
@@ -2124,9 +2123,9 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 	LLViewerInventoryCategory *cof = gInventory.getCategory(current_outfit_id);
 	if (!gInventory.isCategoryComplete(current_outfit_id))
 	{
-		llwarns << "COF info is not complete. Version " << cof->getVersion()
+		LL_WARNS() << "COF info is not complete. Version " << cof->getVersion()
 				<< " descendent_count " << cof->getDescendentCount()
-				<< " viewer desc count " << cof->getViewerDescendentCount() << llendl;
+				<< " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL;
 	}
 	if(!wear_items.size())
 	{
@@ -2138,7 +2137,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 	sortItemsByActualDescription(wear_items);
 
 
-	LL_DEBUGS("Avatar") << "HP block starts" << llendl;
+	LL_DEBUGS("Avatar") << "HP block starts" << LL_ENDL;
 	LLTimer hp_block_timer;
 	LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
 
@@ -2215,7 +2214,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
 	}
 	post_update_func();
 
-	LL_DEBUGS("Avatar") << "HP block ends, elapsed " << hp_block_timer.getElapsedTimeF32() << llendl;
+	LL_DEBUGS("Avatar") << "HP block ends, elapsed " << hp_block_timer.getElapsedTimeF32() << LL_ENDL;
 }
 
 void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
@@ -2740,7 +2739,7 @@ void LLAppearanceMgr::updateIsDirty()
 
 		if(outfit_items.size() != cof_items.size())
 		{
-			LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.count() << " cof " << cof_items.count() << llendl;
+			LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.size() << " cof " << cof_items.size() << LL_ENDL;
 			// Current outfit folder should have one more item than the outfit folder.
 			// this one item is the link back to the outfit folder itself.
 			mOutfitIsDirty = true;
@@ -2762,19 +2761,19 @@ void LLAppearanceMgr::updateIsDirty()
 			{
 				if (item1->getLinkedUUID() != item2->getLinkedUUID())
 				{
-					LL_DEBUGS("Avatar") << "link id different " << llendl;
+					LL_DEBUGS("Avatar") << "link id different " << LL_ENDL;
 				}
 				else
 				{
 					if (item1->getName() != item2->getName())
 					{
-						LL_DEBUGS("Avatar") << "name different " << item1->getName() << " " << item2->getName() << llendl;
+						LL_DEBUGS("Avatar") << "name different " << item1->getName() << " " << item2->getName() << LL_ENDL;
 					}
 					if (item1->getActualDescription() != item2->getActualDescription())
 					{
 						LL_DEBUGS("Avatar") << "desc different " << item1->getActualDescription()
 											<< " " << item2->getActualDescription() 
-											<< " names " << item1->getName() << " " << item2->getName() << llendl;
+											<< " names " << item1->getName() << " " << item2->getName() << LL_ENDL;
 					}
 				}
 				mOutfitIsDirty = true;
@@ -2783,7 +2782,7 @@ void LLAppearanceMgr::updateIsDirty()
 		}
 	}
 	llassert(!mOutfitIsDirty);
-	LL_DEBUGS("Avatar") << "clean" << llendl;
+	LL_DEBUGS("Avatar") << "clean" << LL_ENDL;
 }
 
 // *HACK: Must match name in Library or agent inventory
@@ -2922,7 +2921,7 @@ bool LLAppearanceMgr::updateBaseOutfit()
 
 	const LLUUID base_outfit_id = getBaseOutfitUUID();
 	if (base_outfit_id.isNull()) return false;
-	LL_DEBUGS("Avatar") << "saving cof to base outfit " << base_outfit_id << llendl;
+	LL_DEBUGS("Avatar") << "saving cof to base outfit " << base_outfit_id << LL_ENDL;
 
 	LLPointer<LLInventoryCallback> cb =
 		new LLBoostFuncInventoryCallback(no_op_inventory_func, update_base_outfit_after_ordering);
@@ -3053,9 +3052,9 @@ bool LLAppearanceMgr::validateClothingOrderingInfo(LLUUID cat_id)
 		const LLUUID& item_id = it->first;
 		const std::string& new_order_str = it->second;
 		LLViewerInventoryItem *item = gInventory.getItem(item_id);
-		llwarns << "Order validation fails: " << item->getName()
+		LL_WARNS() << "Order validation fails: " << item->getName()
 				<< " needs to update desc to: " << new_order_str
-				<< " (from: " << item->getActualDescription() << ")" << llendl;
+				<< " (from: " << item->getActualDescription() << ")" << LL_ENDL;
 	}
 	
 	return desc_map.size() == 0;
@@ -3085,7 +3084,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
 		const std::string& new_order_str = it->second;
 		LLViewerInventoryItem *item = gInventory.getItem(item_id);
 		LL_DEBUGS("Avatar") << item->getName() << " updating desc to: " << new_order_str
-			<< " (was: " << item->getActualDescription() << ")" << llendl;
+			<< " (was: " << item->getActualDescription() << ")" << LL_ENDL;
 		updates["desc"] = new_order_str;
 		update_inventory_item(item_id,updates,cb);
 	}
@@ -3148,27 +3147,27 @@ void RequestAgentUpdateAppearanceResponder::onRequestRequested()
 	LL_DEBUGS("Avatar") << "cof_version " << cof_version
 						<< " last_rcv " << last_rcv
 						<< " last_req " << last_req
-						<< " in flight " << mInFlightCounter << llendl;
+						<< " in flight " << mInFlightCounter << LL_ENDL;
 	if ((mInFlightCounter>0) && (mInFlightTimer.hasExpired()))
 	{
-		LL_WARNS("Avatar") << "in flight timer expired, resetting " << llendl;
+		LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
 		mInFlightCounter = 0;
 	}
 	if (cof_version < last_rcv)
 	{
 		LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
-							<< " will not request for " << cof_version << llendl;
+							<< " will not request for " << cof_version << LL_ENDL;
 		return;
 	}
 	if (mInFlightCounter>0 && last_req >= cof_version)
 	{
 		LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req 
-							<< " will not request for " << cof_version << llendl;
+							<< " will not request for " << cof_version << LL_ENDL;
 		return;
 	}
 
 	// Actually send the request.
-	LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << llendl;
+	LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL;
 	mRetryPolicy->reset();
 	sendRequest();
 }
@@ -3183,17 +3182,17 @@ void RequestAgentUpdateAppearanceResponder::sendRequest()
 
 	if (!gAgent.getRegion())
 	{
-		llwarns << "Region not set, cannot request server appearance update" << llendl;
+		LL_WARNS() << "Region not set, cannot request server appearance update" << LL_ENDL;
 		return;
 	}
 	if (gAgent.getRegion()->getCentralBakeVersion()==0)
 	{
-		llwarns << "Region does not support baking" << llendl;
+		LL_WARNS() << "Region does not support baking" << LL_ENDL;
 	}
 	std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");	
 	if (url.empty())
 	{
-		llwarns << "No cap for UpdateAvatarAppearance." << llendl;
+		LL_WARNS() << "No cap for UpdateAvatarAppearance." << LL_ENDL;
 		return;
 	}
 	
@@ -3211,7 +3210,7 @@ void RequestAgentUpdateAppearanceResponder::sendRequest()
 			body["cof_version"] = cof_version+999;
 		}
 	}
-	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl;
+	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
 
 	mInFlightCounter++;
 	mInFlightTimer.setTimerExpirySec(60.0);
@@ -3223,7 +3222,7 @@ void RequestAgentUpdateAppearanceResponder::sendRequest()
 void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 {
 	LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
-					   << " ================================= " << llendl;
+					   << " ================================= " << LL_ENDL;
 	std::set<LLUUID> ais_items, local_items;
 	const LLSD& cof_raw = content["cof_raw"];
 	for (LLSD::array_const_iterator it = cof_raw.beginArray();
@@ -3238,14 +3237,14 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 				LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
 								   << " linked_item_id: " << item["asset_id"].asUUID()
 								   << " name: " << item["name"].asString()
-								   << llendl; 
+								   << LL_ENDL; 
 			}
 			else if (item["type"].asInteger() == 25) // folder link
 			{
 				LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
 								   << " linked_item_id: " << item["asset_id"].asUUID()
 								   << " name: " << item["name"].asString()
-								   << llendl; 
+								   << LL_ENDL; 
 			}
 			else
 			{
@@ -3253,34 +3252,34 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 								   << " linked_item_id: " << item["asset_id"].asUUID()
 								   << " name: " << item["name"].asString()
 								   << " type: " << item["type"].asInteger()
-								   << llendl; 
+								   << LL_ENDL; 
 			}
 		}
 	}
-	LL_INFOS("Avatar") << llendl;
+	LL_INFOS("Avatar") << LL_ENDL;
 	LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() 
-					   << " ================================= " << llendl;
+					   << " ================================= " << LL_ENDL;
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t item_array;
 	gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
 								  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
-	for (S32 i=0; i<item_array.count(); i++)
+	for (S32 i=0; i<item_array.size(); i++)
 	{
-		const LLViewerInventoryItem* inv_item = item_array.get(i).get();
+		const LLViewerInventoryItem* inv_item = item_array.at(i).get();
 		local_items.insert(inv_item->getUUID());
 		LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
 						   << " linked_item_id: " << inv_item->getLinkedUUID()
 						   << " name: " << inv_item->getName()
 						   << " parent: " << inv_item->getParentUUID()
-						   << llendl;
+						   << LL_ENDL;
 	}
-	LL_INFOS("Avatar") << " ================================= " << llendl;
+	LL_INFOS("Avatar") << " ================================= " << LL_ENDL;
 	S32 local_only = 0, ais_only = 0;
 	for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
 	{
 		if (ais_items.find(*it) == ais_items.end())
 		{
-			LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl;
+			LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL;
 			local_only++;
 		}
 	}
@@ -3288,7 +3287,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 	{
 		if (local_items.find(*it) == local_items.end())
 		{
-			LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl;
+			LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL;
 			ais_only++;
 		}
 	}
@@ -3297,7 +3296,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 		LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
 						   << content["observed"].asInteger()
 						   << " rcv " << content["expected"].asInteger()
-						   << ")" << llendl;
+						   << ")" << LL_ENDL;
 	}
 }
 
@@ -3311,7 +3310,7 @@ void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
 	}
 	if (content["success"].asBoolean())
 	{
-		LL_DEBUGS("Avatar") << "succeeded" << llendl;
+		LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
 		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
 		{
 			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
@@ -3352,13 +3351,13 @@ void RequestAgentUpdateAppearanceResponder::onFailure()
 	mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
 	if (mRetryPolicy->shouldRetry(seconds_to_wait))
 	{
-		llinfos << "retrying" << llendl;
+		LL_INFOS() << "retrying" << LL_ENDL;
 		doAfterInterval(boost::bind(&RequestAgentUpdateAppearanceResponder::sendRequest,this),
 						seconds_to_wait);
 	}
 	else
 	{
-		llwarns << "giving up after too many retries" << llendl;
+		LL_WARNS() << "giving up after too many retries" << LL_ENDL;
 	}
 }	
 
@@ -3541,14 +3540,14 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
 		return;
 	}
 	
-	LL_DEBUGS("Avatar") << "called" << llendl;
+	LL_DEBUGS("Avatar") << "called" << LL_ENDL;
 	LLSD key;
 	
 	//EXT-7727. For new accounts inventory callback is created during login process
 	// and may be processed after login process is finished
 	if (show_panel)
 	{
-		LL_DEBUGS("Avatar") << "showing panel" << llendl;
+		LL_DEBUGS("Avatar") << "showing panel" << LL_ENDL;
 		LLFloaterSidePanelContainer::showPanel("appearance", "panel_outfits_inventory", key);
 		
 	}
@@ -3567,7 +3566,7 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true)
 	// link, since, the COF version has changed. There is a race
 	// condition in initial outfit setup which can lead to rez
 	// failures - SH-3860.
-	LL_DEBUGS("Avatar") << "requesting appearance update after createBaseOutfitLink" << llendl;
+	LL_DEBUGS("Avatar") << "requesting appearance update after createBaseOutfitLink" << LL_ENDL;
 	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
 	LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb);
 }
@@ -3593,7 +3592,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
 {
 	if (!isAgentAvatarValid()) return;
 
-	LL_DEBUGS("Avatar") << "creating new outfit" << llendl;
+	LL_DEBUGS("Avatar") << "creating new outfit" << LL_ENDL;
 
 	gAgentWearables.notifyLoadingStarted();
 
@@ -3714,7 +3713,7 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b
 	// LL_DEBUGS("Inventory") << "swap, item "
 	// 					   << ll_pretty_print_sd(item->asLLSD())
 	// 					   << " swap_item "
-	// 					   << ll_pretty_print_sd(swap_item->asLLSD()) << llendl;
+	// 					   << ll_pretty_print_sd(swap_item->asLLSD()) << LL_ENDL;
 
 	// FIXME switch to use AISv3 where supported.
 	//items need to be updated on a dataserver
diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp
index 6f97ca6bc7..8833c57948 100755
--- a/indra/newview/llassetuploadqueue.cpp
+++ b/indra/newview/llassetuploadqueue.cpp
@@ -74,7 +74,7 @@ protected:
 	virtual void httpFailure()
 	{
 		// Parent class will spam the failure.
-		//llwarns << dumpResponse() << llendl;
+		//LL_WARNS() << dumpResponse() << LL_ENDL;
 		LLUpdateTaskInventoryResponder::httpFailure();
 		LLAssetUploadQueue *queue = mSupplier->get();
 		if (queue)
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index e92c897ad8..a98ff64d0a 100755
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -297,7 +297,7 @@ void LLAssetUploadResponder::uploadUpload(const LLSD& content)
 
 void LLAssetUploadResponder::uploadFailure(const LLSD& content)
 {
-	llwarns << dumpResponse() << llendl;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	// remove the "Uploading..." message
 	LLUploadDialog::modalUploadFinished();
 	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index e603cd0483..4de6ad4d2f 100755
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -260,7 +260,7 @@ namespace
 			LL_WARNS() << "LLEventPollResponder: id undefined" << LL_ENDL;
 		}
 		
-		// was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
+		// was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
 		LL_DEBUGS()  << "LLEventPollResponder::httpSuccess <" <<	mCount << "> " << events.size() << "events (id "
 					 <<	LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL;
 		
diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 1a3ddf2b91..e2fa117453 100755
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -303,8 +303,8 @@ public:
 		if ( HTTP_FOUND == getStatus() )
 		{
 			LL_INFOS() << "Facebook: Info received" << LL_ENDL;
-			LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << info << LL_ENDL;
-			LLFacebookConnect::instance().storeInfo(info);
+			LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << getContent() << LL_ENDL;
+			LLFacebookConnect::instance().storeInfo(getContent());
 		}
 		else
 		{
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 9227d2102e..d0555477ea 100755
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -651,7 +651,7 @@ public:
 			{
 				mContent["body"] = body;
 			}
-			llwarns << dumpResponse() << llendl;
+			LL_WARNS() << dumpResponse() << LL_ENDL;
 		}
 	}
 	
diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp
index 7496b0a922..d0492bcdb4 100755
--- a/indra/newview/llhomelocationresponder.cpp
+++ b/indra/newview/llhomelocationresponder.cpp
@@ -104,9 +104,5 @@ void LLHomeLocationResponder::httpSuccess()
 
 void LLHomeLocationResponder::httpFailure()
 {
-<<<<<<< local
-  llwarns << dumpResponse() << llendl;
-=======
-	LL_WARNS() << "LLHomeLocationResponder error [status:" << status << "]: " << content << LL_ENDL;
->>>>>>> other
+  LL_WARNS() << dumpResponse() << LL_ENDL;
 }
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index ae429f11f8..7001a9a88b 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -94,7 +94,7 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti
 {
 	if (!mShouldRetry)
 	{
-		llinfos << "keep on failing" << llendl;
+		LL_INFOS() << "keep on failing" << LL_ENDL;
 		return;
 	}
 	if (mRetryCount > 0)
@@ -111,17 +111,17 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti
 
 	if (mRetryCount>=mMaxRetries)
 	{
-		llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl;
+		LL_INFOS() << "Too many retries " << mRetryCount << ", will not retry" << LL_ENDL;
 		mShouldRetry = false;
 	}
 	if (!mRetryOn4xx && !isHttpServerErrorStatus(status))
 	{
-		llinfos << "Non-server error " << status << ", will not retry" << llendl;
+		LL_INFOS() << "Non-server error " << status << ", will not retry" << LL_ENDL;
 		mShouldRetry = false;
 	}
 	if (mShouldRetry)
 	{
-		llinfos << "Retry count " << mRetryCount << " should retry after " << wait_time << llendl;
+		LL_INFOS() << "Retry count " << mRetryCount << " should retry after " << wait_time << LL_ENDL;
 		mRetryTimer.reset();
 		mRetryTimer.setTimerExpirySec(wait_time);
 	}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 7b3aacd5e9..29b9c2b998 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -253,7 +253,7 @@ bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID&
 		LLInventoryObject *parent_object = getObject(object->getParentUUID());
 		if (!parent_object)
 		{
-			llwarns << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << llendl;
+			LL_WARNS() << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL;
 			return false;
 		}
 		object = parent_object;
@@ -522,7 +522,7 @@ protected:
 		}
 		LLUUID category_id = content["folder_id"].asUUID();
 		
-		LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << llendl;
+		LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << LL_ENDL;
 		// Add the category to the internal representation
 		LLPointer<LLViewerInventoryCategory> cat =
 		new LLViewerInventoryCategory( category_id, 
@@ -599,7 +599,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 		request["message"] = "CreateInventoryCategory";
 		request["payload"] = body;
 
-		LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << llendl;
+		LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL;
 		//		viewer_region->getCapAPI().post(request);
 		LLHTTPClient::post(
 			url,
@@ -791,7 +791,7 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id
 		LLViewerInventoryItem *item = getItem(it->second);
 		if (item)
 		{
-			items.put(item);
+			items.push_back(item);
 		}
 	}
 
@@ -1171,7 +1171,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 
 	AISUpdate ais_update(update); // parse update llsd into stuff to do.
 	ais_update.doUpdate(); // execute the updates in the appropriate order.
-	llinfos << "elapsed: " << timer.getElapsedTimeF32() << llendl;
+	LL_INFOS() << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL;
 }
 
 // Does not appear to be used currently.
@@ -1180,7 +1180,7 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates,
 	U32 mask = LLInventoryObserver::NONE;
 
 	LLPointer<LLViewerInventoryItem> item = gInventory.getItem(item_id);
-	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << llendl;
+	LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL;
 	if(item)
 	{
 		for (LLSD::map_const_iterator it = updates.beginMap();
@@ -1188,19 +1188,19 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates,
 		{
 			if (it->first == "name")
 			{
-				llinfos << "Updating name from " << item->getName() << " to " << it->second.asString() << llendl;
+				LL_INFOS() << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL;
 				item->rename(it->second.asString());
 				mask |= LLInventoryObserver::LABEL;
 			}
 			else if (it->first == "desc")
 			{
-				llinfos << "Updating description from " << item->getActualDescription()
-						<< " to " << it->second.asString() << llendl;
+				LL_INFOS() << "Updating description from " << item->getActualDescription()
+						<< " to " << it->second.asString() << LL_ENDL;
 				item->setDescription(it->second.asString());
 			}
 			else
 			{
-				llerrs << "unhandled updates for field: " << it->first << llendl;
+				LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL;
 			}
 		}
 		mask |= LLInventoryObserver::INTERNAL;
@@ -1221,7 +1221,7 @@ void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updat
 	U32 mask = LLInventoryObserver::NONE;
 
 	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(cat_id);
-	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << llendl;
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL;
 	if(cat)
 	{
 		for (LLSD::map_const_iterator it = updates.beginMap();
@@ -1229,13 +1229,13 @@ void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updat
 		{
 			if (it->first == "name")
 			{
-				llinfos << "Updating name from " << cat->getName() << " to " << it->second.asString() << llendl;
+				LL_INFOS() << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL;
 				cat->rename(it->second.asString());
 				mask |= LLInventoryObserver::LABEL;
 			}
 			else
 			{
-				llerrs << "unhandled updates for field: " << it->first << llendl;
+				LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL;
 			}
 		}
 		mask |= LLInventoryObserver::INTERNAL;
@@ -1270,12 +1270,12 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 						   categories,
 						   items,
 						   LLInventoryModel::INCLUDE_TRASH);
-		S32 count = items.count();
+		S32 count = items.size();
 
 		LLUUID uu_id;
 		for(S32 i = 0; i < count; ++i)
 		{
-			uu_id = items.get(i)->getUUID();
+			uu_id = items.at(i)->getUUID();
 
 			// This check prevents the deletion of a previously deleted item.
 			// This is necessary because deletion is not done in a hierarchical
@@ -1287,7 +1287,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 			}
 		}
 
-		count = categories.count();
+		count = categories.size();
 		// Slightly kludgy way to make sure categories are removed
 		// only after their child categories have gone away.
 
@@ -1301,7 +1301,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 			deleted_count = 0;
 			for(S32 i = 0; i < count; ++i)
 			{
-				uu_id = categories.get(i)->getUUID();
+				uu_id = categories.at(i)->getUUID();
 				if (getCategory(uu_id))
 				{
 					cat_array_t* cat_list = getUnlockedCatArray(uu_id);
@@ -1317,8 +1317,8 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
 		while (deleted_count > 0);
 		if (total_deleted_count != count)
 		{
-			llwarns << "Unexpected count of categories deleted, got "
-					<< total_deleted_count << " expected " << count << llendl;
+			LL_WARNS() << "Unexpected count of categories deleted, got "
+					<< total_deleted_count << " expected " << count << LL_ENDL;
 		}
 		//gInventory.validate();
 	}
@@ -1386,7 +1386,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
 	{
 		if (item_list->size())
 		{
-			llwarns << "Deleting cat " << id << " while it still has child items" << llendl;
+			LL_WARNS() << "Deleting cat " << id << " while it still has child items" << LL_ENDL;
 		}
 		delete item_list;
 		mParentChildItemTree.erase(id);
@@ -1396,7 +1396,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
 	{
 		if (cat_list->size())
 		{
-			llwarns << "Deleting cat " << id << " while it still has child cats" << llendl;
+			LL_WARNS() << "Deleting cat " << id << " while it still has child cats" << LL_ENDL;
 		}
 		delete cat_list;
 		mParentChildCategoryTree.erase(id);
@@ -1513,14 +1513,14 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
 		LLViewerInventoryItem *item = getItem(referent);
 		if (item)
 		{
-			llwarns << "Item " << item->getName() << llendl;
+			LL_WARNS() << "Item " << item->getName() << LL_ENDL;
 		}
 		else
 		{
 			LLViewerInventoryCategory *cat = getCategory(referent);
 			if (cat)
 			{
-				llwarns << "Category " << cat->getName() << llendl;
+				LL_WARNS() << "Category " << cat->getName() << LL_ENDL;
 			}
 		}
 	}
@@ -2267,7 +2267,7 @@ void LLInventoryModel::buildParentChildMap()
 			LL_INFOS() << "Lost category: " << cat->getUUID() << " - "
 					   << cat->getName() << LL_ENDL;
 			++lost;
-			lost_cats.put(cat);
+			lost_cats.push_back(cat);
 			// notifyObservers() has been moved to
 			// llstartup/idle_startup() after this func completes.
 			// Allows some system categories to be created before
@@ -2277,7 +2277,7 @@ void LLInventoryModel::buildParentChildMap()
 
 	if (!gInventory.validate())
 	{
-	 	llwarns << "model failed validity check!" << llendl;
+	 	LL_WARNS() << "model failed validity check!" << LL_ENDL;
 	}
 }
 
@@ -3419,20 +3419,20 @@ bool LLInventoryModel::validate() const
 
 	if (getRootFolderID().isNull())
 	{
-		llwarns << "no root folder id" << llendl;
+		LL_WARNS() << "no root folder id" << LL_ENDL;
 		valid = false;
 	}
 	if (getLibraryRootFolderID().isNull())
 	{
-		llwarns << "no root folder id" << llendl;
+		LL_WARNS() << "no root folder id" << LL_ENDL;
 		valid = false;
 	}
 
 	if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
 	{
 		// ParentChild should be one larger because of the special entry for null uuid.
-		llinfos << "unexpected sizes: cat map size " << mCategoryMap.size()
-				<< " parent/child " << mParentChildCategoryTree.size() << llendl;
+		LL_INFOS() << "unexpected sizes: cat map size " << mCategoryMap.size()
+				<< " parent/child " << mParentChildCategoryTree.size() << LL_ENDL;
 		valid = false;
 	}
 	S32 cat_lock = 0;
@@ -3445,13 +3445,13 @@ bool LLInventoryModel::validate() const
 		const LLViewerInventoryCategory *cat = cit->second;
 		if (!cat)
 		{
-			llwarns << "invalid cat" << llendl;
+			LL_WARNS() << "invalid cat" << LL_ENDL;
 			valid = false;
 			continue;
 		}
 		if (cat_id != cat->getUUID())
 		{
-			llwarns << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << llendl;
+			LL_WARNS() << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
 			valid = false;
 		}
 
@@ -3459,9 +3459,9 @@ bool LLInventoryModel::validate() const
 		{
 			if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())
 			{
-				llwarns << "cat " << cat_id << " has no parent, but is not root ("
+				LL_WARNS() << "cat " << cat_id << " has no parent, but is not root ("
 						<< getRootFolderID() << ") or library root ("
-						<< getLibraryRootFolderID() << ")" << llendl;
+						<< getLibraryRootFolderID() << ")" << LL_ENDL;
 			}
 		}
 		cat_array_t* cats;
@@ -3469,7 +3469,7 @@ bool LLInventoryModel::validate() const
 		getDirectDescendentsOf(cat_id,cats,items);
 		if (!cats || !items)
 		{
-			llwarns << "invalid direct descendents for " << cat_id << llendl;
+			LL_WARNS() << "invalid direct descendents for " << cat_id << LL_ENDL;
 			valid = false;
 			continue;
 		}
@@ -3479,11 +3479,11 @@ bool LLInventoryModel::validate() const
 		}
 		else if (cats->size() + items->size() != cat->getDescendentCount())
 		{
-			llwarns << "invalid desc count for " << cat_id << " name [" << cat->getName()
+			LL_WARNS() << "invalid desc count for " << cat_id << " name [" << cat->getName()
 					<< "] parent " << cat->getParentUUID()
 					<< " cached " << cat->getDescendentCount()
 					<< " expected " << cats->size() << "+" << items->size()
-					<< "=" << cats->size() +items->size() << llendl;
+					<< "=" << cats->size() +items->size() << LL_ENDL;
 			valid = false;
 		}
 		if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
@@ -3500,11 +3500,11 @@ bool LLInventoryModel::validate() const
 		}
 		for (S32 i = 0; i<items->size(); i++)
 		{
-			LLViewerInventoryItem *item = items->get(i);
+			LLViewerInventoryItem *item = items->at(i);
 
 			if (!item)
 			{
-				llwarns << "null item at index " << i << " for cat " << cat_id << llendl;
+				LL_WARNS() << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
 				valid = false;
 				continue;
 			}
@@ -3513,9 +3513,9 @@ bool LLInventoryModel::validate() const
 			
 			if (item->getParentUUID() != cat_id)
 			{
-				llwarns << "wrong parent for " << item_id << " found "
+				LL_WARNS() << "wrong parent for " << item_id << " found "
 						<< item->getParentUUID() << " expected " << cat_id
-						<< llendl;
+						<< LL_ENDL;
 				valid = false;
 			}
 
@@ -3524,8 +3524,8 @@ bool LLInventoryModel::validate() const
 			item_map_t::const_iterator it = mItemMap.find(item_id);
 			if (it == mItemMap.end())
 			{
-				llwarns << "item " << item_id << " found as child of "
-						<< cat_id << " but not in top level mItemMap" << llendl;
+				LL_WARNS() << "item " << item_id << " found as child of "
+						<< cat_id << " but not in top level mItemMap" << LL_ENDL;
 				valid = false;
 			}
 			else
@@ -3533,8 +3533,8 @@ bool LLInventoryModel::validate() const
 				LLViewerInventoryItem *top_item = it->second;
 				if (top_item != item)
 				{
-					llwarns << "item mismatch, item_id " << item_id
-							<< " top level entry is different, uuid " << top_item->getUUID() << llendl;
+					LL_WARNS() << "item mismatch, item_id " << item_id
+							<< " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;
 				}
 			}
 
@@ -3543,7 +3543,7 @@ bool LLInventoryModel::validate() const
 			bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
 			if (!found)
 			{
-				llwarns << "unable to find topmost ancestor for " << item_id << llendl;
+				LL_WARNS() << "unable to find topmost ancestor for " << item_id << LL_ENDL;
 				valid = false;
 			}
 			else
@@ -3551,10 +3551,10 @@ bool LLInventoryModel::validate() const
 				if (topmost_ancestor_id != getRootFolderID() &&
 					topmost_ancestor_id != getLibraryRootFolderID())
 				{
-					llwarns << "unrecognized top level ancestor for " << item_id
+					LL_WARNS() << "unrecognized top level ancestor for " << item_id
 							<< " got " << topmost_ancestor_id
 							<< " expected " << getRootFolderID()
-							<< " or " << getLibraryRootFolderID() << llendl;
+							<< " or " << getLibraryRootFolderID() << LL_ENDL;
 					valid = false;
 				}
 			}
@@ -3569,8 +3569,8 @@ bool LLInventoryModel::validate() const
 			getDirectDescendentsOf(parent_id,cats,items);
 			if (!cats)
 			{
-				llwarns << "cat " << cat_id << " name [" << cat->getName()
-						<< "] orphaned - no child cat array for alleged parent " << parent_id << llendl;
+				LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
+						<< "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
 				valid = false;
 			}
 			else
@@ -3578,7 +3578,7 @@ bool LLInventoryModel::validate() const
 				bool found = false;
 				for (S32 i = 0; i<cats->size(); i++)
 				{
-					LLViewerInventoryCategory *kid_cat = cats->get(i);
+					LLViewerInventoryCategory *kid_cat = cats->at(i);
 					if (kid_cat == cat)
 					{
 						found = true;
@@ -3587,8 +3587,8 @@ bool LLInventoryModel::validate() const
 				}
 				if (!found)
 				{
-					llwarns << "cat " << cat_id << " name [" << cat->getName()
-							<< "] orphaned - not found in child cat array of alleged parent " << parent_id << llendl;
+					LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
+							<< "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
 				}
 			}
 		}
@@ -3600,14 +3600,14 @@ bool LLInventoryModel::validate() const
 		LLViewerInventoryItem *item = iit->second;
 		if (item->getUUID() != item_id)
 		{
-			llwarns << "item_id " << item_id << " does not match " << item->getUUID() << llendl;
+			LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
 			valid = false;
 		}
 
 		const LLUUID& parent_id = item->getParentUUID();
 		if (parent_id.isNull())
 		{
-			llwarns << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << llendl;
+			LL_WARNS() << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
 		}
 		else
 		{
@@ -3616,15 +3616,15 @@ bool LLInventoryModel::validate() const
 			getDirectDescendentsOf(parent_id,cats,items);
 			if (!items)
 			{
-				llwarns << "item " << item_id << " name [" << item->getName()
-						<< "] orphaned - alleged parent has no child items list " << parent_id << llendl;
+				LL_WARNS() << "item " << item_id << " name [" << item->getName()
+						<< "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
 			}
 			else
 			{
 				bool found = false;
 				for (S32 i=0; i<items->size(); ++i)
 				{
-					if (items->get(i) == item) 
+					if (items->at(i) == item) 
 					{
 						found = true;
 						break;
@@ -3632,8 +3632,8 @@ bool LLInventoryModel::validate() const
 				}
 				if (!found)
 				{
-					llwarns << "item " << item_id << " name [" << item->getName()
-							<< "] orphaned - not found as child of alleged parent " << parent_id << llendl;
+					LL_WARNS() << "item " << item_id << " name [" << item->getName()
+							<< "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
 				}
 			}
 				
@@ -3648,30 +3648,30 @@ bool LLInventoryModel::validate() const
 			// Linked-to UUID should have back reference to this link.
 			if (!hasBacklinkInfo(link_id, target_id))
 			{
-				llwarns << "link " << item->getUUID() << " type " << item->getActualType()
+				LL_WARNS() << "link " << item->getUUID() << " type " << item->getActualType()
 						<< " missing backlink info at target_id " << target_id
-						<< llendl;
+						<< LL_ENDL;
 			}
 			// Links should have referents.
 			if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
 			{
-				llwarns << "broken item link " << item->getName() << " id " << item->getUUID() << llendl;
+				LL_WARNS() << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
 			}
 			else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
 			{
-				llwarns << "broken folder link " << item->getName() << " id " << item->getUUID() << llendl;
+				LL_WARNS() << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
 			}
 			if (target_item && target_item->getIsLinkType())
 			{
-				llwarns << "link " << item->getName() << " references a link item "
-						<< target_item->getName() << " " << target_item->getUUID() << llendl;
+				LL_WARNS() << "link " << item->getName() << " references a link item "
+						<< target_item->getName() << " " << target_item->getUUID() << LL_ENDL;
 			}
 
 			// Links should not have backlinks.
 			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
 			if (range.first != range.second)
 			{
-				llwarns << "Link item " << item->getName() << " has backlinks!" << llendl;
+				LL_WARNS() << "Link item " << item->getName() << " has backlinks!" << LL_ENDL;
 			}
 		}
 		else
@@ -3685,7 +3685,7 @@ bool LLInventoryModel::validate() const
 				LLViewerInventoryItem *link_item = getItem(link_id);
 				if (!link_item || !link_item->getIsLinkType())
 				{
-					llwarns << "invalid backlink from target " << item->getName() << " to " << link_id << llendl;
+					LL_WARNS() << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL;
 				}
 			}
 		}
@@ -3693,19 +3693,19 @@ bool LLInventoryModel::validate() const
 	
 	if (cat_lock > 0 || item_lock > 0)
 	{
-		llinfos << "Found locks on some categories: sub-cat arrays "
-				<< cat_lock << ", item arrays " << item_lock << llendl;
+		LL_INFOS() << "Found locks on some categories: sub-cat arrays "
+				<< cat_lock << ", item arrays " << item_lock << LL_ENDL;
 	}
 	if (desc_unknown_count != 0)
 	{
-		llinfos << "Found " << desc_unknown_count << " cats with unknown descendent count" << llendl; 
+		LL_INFOS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL; 
 	}
 	if (version_unknown_count != 0)
 	{
-		llinfos << "Found " << version_unknown_count << " cats with unknown version" << llendl;
+		LL_INFOS() << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL;
 	}
 
-	llinfos << "Validate done, valid = " << (U32) valid << llendl;
+	LL_INFOS() << "Validate done, valid = " << (U32) valid << LL_ENDL;
 
 	return valid;
 }
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 5f8dc95d8a..2de37b0790 100755
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -172,7 +172,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
 		mRecursiveLibraryFetchStarted)
 	{
 		mAllFoldersFetched = TRUE;
-		//llinfos << "All folders fetched, validating" << llendl;
+		//LL_INFOS() << "All folders fetched, validating" << LL_ENDL;
 		//gInventory.validate();
 	}
 	mFolderFetchActive = false;
@@ -544,7 +544,7 @@ void LLInventoryModelFetchDescendentsResponder::httpSuccess()
 // If we get back an error (not found, etc...), handle it here.
 void LLInventoryModelFetchDescendentsResponder::httpFailure()
 {
-	llwarns << dumpResponse() << llendl;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
 
 	LL_INFOS() << dumpResponse() << LL_ENDL;
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 2df01bb494..2dd8dce42f 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -601,7 +601,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
 		LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);
 		if (!category)
         {
-            llwarns << "Category : Category id = " << cat_id << " disappeared" << llendl;
+            LL_WARNS() << "Category : Category id = " << cat_id << " disappeared" << LL_ENDL;
 			cat_data.mCallback();
             // Keep track of those deleted categories so we can remove them
             deleted_categories_ids.push_back(cat_id);
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 86b471a284..80a427c0b8 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -31,7 +31,6 @@
 #include "apr_dso.h"
 #include "llhttpconstants.h"
 #include "llapr.h"
-#include "llhttpstatuscodes.h"
 #include "llmeshrepository.h"
 
 #include "llagent.h"
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 0447e66e4a..ac00c5d986 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1095,7 +1095,7 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
 				// Create new link
 				LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
 									<< " removing old link at " << link_item->getUUID()
-									<< " wearable item id " << mWearablePtr->getItemID() << llendl;
+									<< " wearable item id " << mWearablePtr->getItemID() << LL_ENDL;
 
 				LLInventoryObject::const_object_list_t obj_array;
 				obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index 9534b54dcf..4977a72dc6 100755
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -819,7 +819,7 @@ void NavMeshResponder::httpSuccess()
 
 void NavMeshResponder::httpFailure()
 {
-	llwarns << dumpResponse() << llendl;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	mNavMeshPtr->handleNavMeshError(mNavMeshVersion);
 }
 
@@ -872,7 +872,7 @@ void NavMeshRebakeResponder::httpSuccess()
 
 void NavMeshRebakeResponder::httpFailure()
 {
-	LL_WARNS() << dumpResponse() < LL_ENDL;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	mRebakeNavMeshCallback(false);
 }
 
@@ -907,8 +907,7 @@ void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent)
 
 void LinksetsResponder::handleObjectLinksetsError()
 {
-	LL_WARNS() << "LinksetsResponder object linksets error with request to URL '" << pURL << "' [status:"
-			   << pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << "LinksetsResponder object linksets error" << LL_ENDL;
 	mObjectMessagingState = kReceivedError;
 	if (mTerrainMessagingState != kWaiting)
 	{
@@ -929,8 +928,7 @@ void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent)
 
 void LinksetsResponder::handleTerrainLinksetsError()
 {
-	LL_WARNS() << "LinksetsResponder terrain linksets error with request to URL '" << pURL << "' [status:"
-			   << pStatus << "]: " << pContent << LL_ENDL;
+	LL_WARNS() << "LinksetsResponder terrain linksets error" << LL_ENDL;
 	mTerrainMessagingState = kReceivedError;
 	if (mObjectMessagingState != kWaiting)
 	{
@@ -981,7 +979,7 @@ void ObjectLinksetsResponder::httpSuccess()
 
 void ObjectLinksetsResponder::httpFailure()
 {
-	llwarns << dumpResponse() << llendl;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	mLinksetsResponsderPtr->handleObjectLinksetsError();
 }
 
@@ -1006,7 +1004,7 @@ void TerrainLinksetsResponder::httpSuccess()
 
 void TerrainLinksetsResponder::httpFailure()
 {
-	llwarns << dumpResponse() << llendl;
+	LL_WARNS() << dumpResponse() << LL_ENDL;
 	mLinksetsResponsderPtr->handleTerrainLinksetsError();
 }
 
diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp
index e4a696ac7e..0287c07f96 100755
--- a/indra/newview/llpathfindingnavmesh.cpp
+++ b/indra/newview/llpathfindingnavmesh.cpp
@@ -186,8 +186,6 @@ void LLPathfindingNavMesh::handleNavMeshError()
 
 void LLPathfindingNavMesh::handleNavMeshError(U32 pNavMeshVersion)
 {
-	LL_WARNS() << "LLPathfindingNavMesh error with request to URL '" << pURL << "' [status:"
-			   << pStatus << "]: " << pContent << LL_ENDL;
 	if (mNavMeshStatus.getVersion() == pNavMeshVersion)
 	{
 		handleNavMeshError();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 5bb67490ac..7b7168d438 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2077,8 +2077,8 @@ bool idle_startup()
 			// the gender chooser. This should occur only in very
 			// unusual circumstances, so set the timeout fairly high
 			// to minimize mistaken hits here.
-			llwarns << "Wait for valid avatar state exceeded " 
-					<< timeout.getElapsedTimeF32() << " will invoke gender chooser" << llendl; 
+			LL_WARNS() << "Wait for valid avatar state exceeded " 
+					<< timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL; 
 			LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
 		}
 		else
@@ -2131,7 +2131,7 @@ bool idle_startup()
 			if (isAgentAvatarValid()
 				&& gAgentAvatarp->isFullyLoaded())
 			{
-				LL_DEBUGS("Avatar") << "avatar fully loaded" << llendl;
+				LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL;
 				LLStartUp::setStartupState( STATE_CLEANUP );
 				return TRUE;
 			}
@@ -2142,7 +2142,7 @@ bool idle_startup()
 			if ( gAgentWearables.areWearablesLoaded() )
 			{
 				// We have our clothing, proceed.
-				LL_DEBUGS("Avatar") << "wearables loaded" << llendl;
+				LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL;
 				LLStartUp::setStartupState( STATE_CLEANUP );
 				return TRUE;
 			}
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index fb4be553c1..14a42dd8dc 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1306,11 +1306,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		{
 			if (wait_seconds <= 0.0)
 			{
-				llinfos << mID << " retrying now" << llendl;
+				LL_INFOS() << mID << " retrying now" << LL_ENDL;
 			}
 			else
 			{
-				//llinfos << mID << " waiting to retry for " << wait_seconds << " seconds" << llendl;
+				//LL_INFOS() << mID << " waiting to retry for " << wait_seconds << " seconds" << LL_ENDL;
 				return false;
 			}
 		}
@@ -1333,7 +1333,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				{
 					if (mFTType != FTT_DEFAULT)
 					{
-						llwarns << "trying to seek a non-default texture on the sim. Bad!" << llendl;
+						LL_WARNS() << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL;
 					}
 					setUrl(http_url + "/?texture_id=" + mID.asString().c_str());
 					mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.
@@ -1570,7 +1570,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				{
 					if (mFTType != FTT_MAP_TILE)
 					{
-						llwarns << "Texture missing from server (404): " << mUrl << llendl;
+						LL_WARNS() << "Texture missing from server (404): " << mUrl << LL_ENDL;
 					}
 
 					if(mWriteToCacheState == NOT_WRITE) //map tiles or server bakes
@@ -1579,7 +1579,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 						releaseHttpSemaphore();
 						if (mFTType != FTT_MAP_TILE)
 						{
-							LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl;
+							LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL;
 						}
 						return true; 
 					}
@@ -1598,10 +1598,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				else if (http_service_unavail == mGetStatus)
 				{
 					LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
-					llinfos << "503: HTTP GET failed for: " << mUrl
+					LL_INFOS() << "503: HTTP GET failed for: " << mUrl
 							<< " Status: " << mGetStatus.toHex()
 							<< " Reason: '" << mGetReason << "'"
-							<< llendl;
+							<< LL_ENDL;
 				}
 				else if (http_not_sat == mGetStatus)
 				{
@@ -1957,8 +1957,8 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 	F32 rate = fake_failure_rate;
 	if (mFTType == FTT_SERVER_BAKE && (fake_failure_rate > 0.0) && (rand_val < fake_failure_rate))
 	{
-		llwarns << mID << " for debugging, setting fake failure status for texture " << mID
-				<< " (rand was " << rand_val << "/" << rate << ")" << llendl;
+		LL_WARNS() << mID << " for debugging, setting fake failure status for texture " << mID
+				<< " (rand was " << rand_val << "/" << rate << ")" << LL_ENDL;
 		response->setStatus(LLCore::HttpStatus(503));
 	}
 	bool success = true;
@@ -1966,13 +1966,13 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 	LLCore::HttpStatus status(response->getStatus());
 	if (!status && (mFTType == FTT_SERVER_BAKE))
 	{
-		llinfos << mID << " state " << e_state_name[mState] << llendl;
+		LL_INFOS() << mID << " state " << e_state_name[mState] << LL_ENDL;
 		mFetchRetryPolicy.onFailure(response);
 		F32 retry_after;
 		if (mFetchRetryPolicy.shouldRetry(retry_after))
 		{
-			llinfos << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << llendl;
-			mFetcher->removeFromHTTPQueue(mID, 0);
+			LL_INFOS() << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << LL_ENDL;
+			mFetcher->removeFromHTTPQueue(mID, S32Bytes(0));
 			std::string reason(status.toString());
 			setGetStatus(status, reason);
 			releaseHttpSemaphore();
@@ -1981,7 +1981,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		}
 		else
 		{
-			llinfos << mID << " will not retry" << llendl;
+			LL_INFOS() << mID << " will not retry" << LL_ENDL;
 		}
 	}
 	else
@@ -2011,8 +2011,8 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 		{
 			std::string reason(status.toString());
 			setGetStatus(status, reason);
-			llwarns << "CURL GET FAILED, status: " << status.toTerseString()
-					<< " reason: " << reason << llendl;
+			LL_WARNS() << "CURL GET FAILED, status: " << status.toTerseString()
+					<< " reason: " << reason << LL_ENDL;
 		}
 	}
 	else
@@ -2576,7 +2576,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 
 	if (f_type == FTT_SERVER_BAKE)
 	{
-		LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << " type " << f_type << llendl;
+		LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << " type " << f_type << LL_ENDL;
 	}
 	LLTextureFetchWorker* worker = getWorker(id) ;
 	if (worker)
@@ -2600,7 +2600,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 		llassert(!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C));
 
 		// Do full requests for baked textures to reduce interim blurring.
-		LL_DEBUGS("Texture") << "full request for " << id << " texture is FTT_SERVER_BAKE" << llendl;
+		LL_DEBUGS("Texture") << "full request for " << id << " texture is FTT_SERVER_BAKE" << LL_ENDL;
 		desired_size = MAX_IMAGE_DATA_SIZE;
 		desired_discard = 0;
 	}
@@ -3354,7 +3354,7 @@ void LLTextureFetchWorker::setState(e_state new_state)
 	// blurry images fairly frequently. Presumably this is an
 	// indication of some subtle timing or locking issue.
 
-//		LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl;
+//		LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << LL_ENDL;
 	}
 	mState = new_state;
 }
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 3e3e385905..b236bba3b7 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -709,7 +709,7 @@ S32 LLViewerInventoryCategory::getViewerDescendentCount() const
 	S32 descendents_actual = 0;
 	if(cats && items)
 	{
-		descendents_actual = cats->count() + items->count();
+		descendents_actual = cats->size() + items->size();
 	}
 	return descendents_actual;
 }
@@ -1128,7 +1128,7 @@ void link_inventory_array(const LLUUID& category,
 		const LLInventoryObject* baseobj = *it;
 		if (!baseobj)
 		{
-			llwarns << "attempt to link to unknown object" << llendl;
+			LL_WARNS() << "attempt to link to unknown object" << LL_ENDL;
 			continue;
 		}
 
@@ -1137,7 +1137,7 @@ void link_inventory_array(const LLUUID& category,
 			// Fail if item can be found but is of a type that can't be linked.
 			// Arguably should fail if the item can't be found too, but that could
 			// be a larger behavioral change.
-			llwarns << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << llendl;
+			LL_WARNS() << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << LL_ENDL;
 			continue;
 		}
 		
@@ -1173,7 +1173,7 @@ void link_inventory_array(const LLUUID& category,
 			}
 			else
 			{
-				llwarns << "could not convert object into an item or category: " << baseobj->getUUID() << llendl;
+				LL_WARNS() << "could not convert object into an item or category: " << baseobj->getUUID() << LL_ENDL;
 				continue;
 			}
 		}
@@ -1281,7 +1281,7 @@ void update_inventory_item(
 	if (!ais_ran)
 	{
 		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
-		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << llendl;
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL;
 		if(obj)
 		{
 			LLMessageSystem* msg = gMessageSystem;
@@ -1323,7 +1323,7 @@ void update_inventory_item(
 	if (!ais_ran)
 	{
 		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
-		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
 		if(obj)
 		{
 			LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
@@ -1358,7 +1358,7 @@ void update_inventory_category(
 	LLPointer<LLInventoryCallback> cb)
 {
 	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
-	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl;
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
 	if(obj)
 	{
 		if (LLFolderType::lookupIsProtectedType(obj->getPreferredType()))
@@ -1421,7 +1421,7 @@ void remove_inventory_item(
 	}
 	else
 	{
-		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << llendl;
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << LL_ENDL;
 	}
 }
 
@@ -1432,7 +1432,7 @@ void remove_inventory_item(
 	if(obj)
 	{
 		const LLUUID item_id(obj->getUUID());
-		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << obj->getName() << llendl;
+		LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL;
 		if (AISCommand::isAPIAvailable())
 		{
 			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
@@ -1461,7 +1461,7 @@ void remove_inventory_item(
 	else
 	{
 		// *TODO: Clean up callback?
-		llwarns << "remove_inventory_item called for invalid or nonexistent item." << llendl;
+		LL_WARNS() << "remove_inventory_item called for invalid or nonexistent item." << LL_ENDL;
 	}
 }
 
@@ -1479,7 +1479,7 @@ public:
 		LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID);
 		if(children != LLInventoryModel::CHILDREN_NO)
 		{
-			llwarns << "remove descendents failed, cannot remove category " << llendl;
+			LL_WARNS() << "remove descendents failed, cannot remove category " << LL_ENDL;
 		}
 		else
 		{
@@ -1495,7 +1495,7 @@ void remove_inventory_category(
 	const LLUUID& cat_id,
 	LLPointer<LLInventoryCallback> cb)
 {
-	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] " << llendl;
+	LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] " << LL_ENDL;
 	LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id);
 	if(obj)
 	{
@@ -1516,7 +1516,7 @@ void remove_inventory_category(
 			LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id);
 			if(children != LLInventoryModel::CHILDREN_NO)
 			{
-				LL_DEBUGS("Inventory") << "Will purge descendents first before deleting category " << cat_id << llendl;
+				LL_DEBUGS("Inventory") << "Will purge descendents first before deleting category " << cat_id << LL_ENDL;
 				LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); 
 				purge_descendents_of(cat_id, wrap_cb);
 				return;
@@ -1542,7 +1542,7 @@ void remove_inventory_category(
 	}
 	else
 	{
-		llwarns << "remove_inventory_category called for invalid or nonexistent item " << cat_id << llendl;
+		LL_WARNS() << "remove_inventory_category called for invalid or nonexistent item " << cat_id << LL_ENDL;
 	}
 }
 
@@ -1570,7 +1570,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 	LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id);
 	if(children == LLInventoryModel::CHILDREN_NO)
 	{
-		LL_DEBUGS("Inventory") << "No descendents to purge for " << id << llendl;
+		LL_DEBUGS("Inventory") << "No descendents to purge for " << id << LL_ENDL;
 		return;
 	}
 	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id);
@@ -1580,7 +1580,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		{
 			// Something on the clipboard is in "cut mode" and needs to be preserved
 			LL_DEBUGS("Inventory") << "purge_descendents_of clipboard case " << cat->getName()
-								   << " iterate and purge non hidden items" << llendl;
+								   << " iterate and purge non hidden items" << LL_ENDL;
 			LLInventoryModel::cat_array_t* categories;
 			LLInventoryModel::item_array_t* items;
 			// Get the list of direct descendants in tha categoy passed as argument
@@ -1615,7 +1615,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 			else // no cap
 			{
 				// Fast purge
-				LL_DEBUGS("Inventory") << "purge_descendents_of fast case " << cat->getName() << llendl;
+				LL_DEBUGS("Inventory") << "purge_descendents_of fast case " << cat->getName() << LL_ENDL;
 
 				// send it upstream
 				LLMessageSystem* msg = gMessageSystem;
@@ -1744,14 +1744,14 @@ void slam_inventory_folder(const LLUUID& folder_id,
 	if (AISCommand::isAPIAvailable())
 	{
 		LL_DEBUGS("Avatar") << "using AISv3 to slam folder, id " << folder_id
-							<< " new contents: " << ll_pretty_print_sd(contents) << llendl;
+							<< " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
 		LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
 		cmd_ptr->run_command();
 	}
 	else // no cap
 	{
 		LL_DEBUGS("Avatar") << "using item-by-item calls to slam folder, id " << folder_id
-							<< " new contents: " << ll_pretty_print_sd(contents) << llendl;
+							<< " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
 		for (LLSD::array_const_iterator it = contents.beginArray();
 			 it != contents.endArray();
 			 ++it)
@@ -1772,9 +1772,9 @@ void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
 	LLInventoryModel::item_array_t items;
 	gInventory.collectDescendents(category, cats, items,
 								  LLInventoryModel::EXCLUDE_TRASH);
-	for (S32 i = 0; i < items.count(); ++i)
+	for (S32 i = 0; i < items.size(); ++i)
 	{
-		LLViewerInventoryItem *item = items.get(i);
+		LLViewerInventoryItem *item = items.at(i);
 		if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
 			continue;
 		if (item->getIsLinkType())
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index a5cfff177e..44ac93d3de 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -182,14 +182,14 @@ private:
 	{
 		if (!isGoodStatus())
 		{
-			llwarns << dumpResponse()
-					<< " [headers:" << getResponseHeaders() << "]" << llendl;
+			LL_WARNS() << dumpResponse()
+					<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
 		}
 		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
 		std::string::size_type idx1 = media_type.find_first_of(";");
 		std::string mime_type = media_type.substr(0, idx1);
 
-		LL_DEBUGS << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL;
+		LL_DEBUGS() << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL;
 		
 		// 2xx status codes indicate success.
 		// Most 4xx status codes are successful enough for our purposes.
@@ -218,7 +218,7 @@ private:
 		}
 		//else
 		//{
-		//	llwarns << "responder failed with status " << dumpResponse() << llendl;
+		//	LL_WARNS() << "responder failed with status " << dumpResponse() << LL_ENDL;
 		//
 		//	if(mMediaImpl)
 		//	{
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7e22b65d4c..fd5df9b774 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -250,7 +250,7 @@ public:
 private:
 	/* virtual */void httpFailure()
 	{
-		LL_WARNS2("AppInit", "Capabilities") << dumpResponse() << LL_ENDL;
+		LL_WARNS("AppInit", "Capabilities") << dumpResponse() << LL_ENDL;
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if (regionp)
 		{
@@ -326,7 +326,7 @@ public:
 private:
 	/* virtual */ void httpFailure()
 	{
-		llwarns << dumpResponse() << llendl;
+		LL_WARNS() << dumpResponse() << LL_ENDL;
 	}
 
 	/* virtual */ void httpSuccess()
@@ -334,7 +334,7 @@ private:
 		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 		if( !regionp ) 
 		{
-			LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
+			LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
 			return ;
 		}
 
@@ -353,18 +353,18 @@ private:
 		
 		if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )
 		{
-			LL_WARNS2("AppInit", "Capabilities") 
+			LL_WARNS("AppInit", "Capabilities") 
 				<< "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. "
 				<< "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size()
 				<< " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
 				<< LL_ENDL;
 #ifdef DEBUG_CAPS_GRANTS
-			LL_WARNS2("AppInit", "Capabilities")
+			LL_WARNS("AppInit", "Capabilities")
 				<< "Initial Base capabilities: " << LL_ENDL;
 
 			log_capabilities(regionp->getRegionImpl()->mCapabilities);
 
-			LL_WARNS2("AppInit", "Capabilities")
+			LL_WARNS("AppInit", "Capabilities")
 							<< "Latest base capabilities: " << LL_ENDL;
 
 			log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
@@ -2809,14 +2809,13 @@ class SimulatorFeaturesReceived : public LLHTTPClient::Responder
 	LOG_CLASS(SimulatorFeaturesReceived);
 public:
 	SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
-			S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
-<<<<<<< local
+							  S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
 		: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
 	{ }
 
 	/* virtual */ void httpFailure()
 	{
-		LL_WARNS2("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL;
+		LL_WARNS("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL;
 		retry();
 	}
 
@@ -2922,7 +2921,7 @@ bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const
 {
 	if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
 	{
-		llwarns << "isCapabilityAvailable called before caps received for " << name << llendl;
+		LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL;
 	}
 	
 	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
@@ -3063,10 +3062,10 @@ void log_capabilities(const CapabilityMap &capmap)
 	{
 		if (!iter->second.empty())
 		{
-			llinfos << "log_capabilities: " << iter->first << " URL is " << iter->second << llendl;
+			LL_INFOS() << "log_capabilities: " << iter->first << " URL is " << iter->second << LL_ENDL;
 		}
 	}
-	llinfos << "log_capabilities: Dumped " << count << " entries." << llendl;
+	LL_INFOS() << "log_capabilities: Dumped " << count << " entries." << LL_ENDL;
 }
 void LLViewerRegion::resetMaterialsCapThrottle()
 {
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index fd2fb3695f..f60829e9e8 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -639,7 +639,7 @@ void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
 {
 	LLTimer& timer = getPhaseTimer(phase_name);
 	timer.start();
-	//LL_DEBUGS("Avatar") << "startPhase " << phase_name << llendl;
+	//LL_DEBUGS("Avatar") << "startPhase " << phase_name << LL_ENDL;
 }
 
 void LLViewerStats::PhaseMap::clearPhases()
@@ -711,11 +711,11 @@ bool LLViewerStats::PhaseMap::getPhaseValues(const std::string& phase_name, F32&
 		found = true;
 		elapsed =  iter->second.getElapsedTimeF32();
 		completed = !iter->second.getStarted();
-		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << llendl;
+		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << LL_ENDL;
 	}
 	else
 	{
-		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND"  << llendl;
+		//LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND"  << LL_ENDL;
 	}
 
 	return found;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 28b07feef7..ba89aafc84 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -994,7 +994,7 @@ LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type,
 	mFTType = f_type;
 	if (mFTType == FTT_HOST_BAKE)
 	{
-		llwarns << "Unsupported fetch type " << mFTType << llendl;
+		LL_WARNS() << "Unsupported fetch type " << mFTType << LL_ENDL;
 	}
 	generateGLTexture();
 }
@@ -1930,19 +1930,19 @@ bool LLViewerFetchedTexture::updateFetch()
 				{
 					if (getFTType() != FTT_MAP_TILE)
 					{
-						llwarns << mID
+						LL_WARNS() << mID
 								<< " Fetch failure, setting as missing, decode_priority " << decode_priority
 								<< " mRawDiscardLevel " << mRawDiscardLevel
 								<< " current_discard " << current_discard
 								<< " stats " << mLastHttpGetStatus.toHex()
-								<< llendl;
+								<< LL_ENDL;
 					}
 					setIsMissingAsset();
 					desired_discard = -1;
 				}
 				else
 				{
-					//llwarns << mID << ": Setting min discard to " << current_discard << llendl;
+					//LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
 					if(current_discard >= 0)
 					{
 						mMinDiscardLevel = current_discard;
@@ -2134,7 +2134,7 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 	{
 		if (mUrl.empty())
 		{
-			llwarns << mID << ": Marking image as missing" << llendl;
+			LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
 		}
 		else
 		{
@@ -2143,7 +2143,7 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 			// server bake texture.
 			if (getFTType() != FTT_MAP_TILE)
 			{
-				llwarns << mUrl << ": Marking image as missing" << llendl;
+				LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
 			}
 		}
 		if (mHasFetcher)
@@ -2158,7 +2158,7 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
 	}
 	else
 	{
-		llinfos << mID << ": un-flagging missing asset" << llendl;
+		LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL;
 	}
 	mIsMissingAsset = is_missing;
 }
@@ -2211,7 +2211,7 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
 		else
 		{
 			// We need aux data, but we've already loaded the image, and it didn't have any
-			llwarns << "No aux data available for callback for image:" << getID() << llendl;
+			LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
 		}
 	}
 	mLastCallBackActiveTime = sCurrentTime ;
@@ -2385,10 +2385,10 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 		if (mFTType == FTT_SERVER_BAKE)
 		{
 			//output some debug info
-			llinfos << "baked texture: " << mID << "clears all call backs due to inactivity." << llendl;
-			llinfos << mUrl << llendl;
-			llinfos << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() <<
-				" Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << llendl;
+			LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL;
+			LL_INFOS() << mUrl << LL_ENDL;
+			LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() <<
+				" Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL;
 		}
 
 		clearCallbackEntryList() ; //remove all callbacks.
@@ -2402,8 +2402,8 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 		if (mFTType == FTT_SERVER_BAKE)
 		{
 			//output some debug info
-			llinfos << "baked texture: " << mID << "is missing." << llendl;
-			llinfos << mUrl << llendl;
+			LL_INFOS() << "baked texture: " << mID << "is missing." << LL_ENDL;
+			LL_INFOS() << mUrl << LL_ENDL;
 		}
 
 		for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f5538efc24..9f42776d78 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1996,10 +1996,10 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 
 		if (url.empty())
 		{
-			llwarns << "unable to determine URL for te " << te << " uuid " << uuid << llendl;
+			LL_WARNS() << "unable to determine URL for te " << te << " uuid " << uuid << LL_ENDL;
 			return NULL;
 		}
-		LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << llendl;
+		LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << LL_ENDL;
 		result = LLViewerTextureManager::getFetchedTextureFromUrl(
 			url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
 		if (result->isMissingAsset())
@@ -4665,7 +4665,7 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid)
 	if (appearance_service_url.empty())
 	{
 		// Probably a server-side issue if we get here:
-		llwarns << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << llendl;
+		LL_WARNS() << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << LL_ENDL;
 		return url;
 	}
 	
@@ -4673,7 +4673,7 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid)
 	if (texture_entry != NULL)
 	{
 		url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString();
-		//llinfos << "baked texture url: " << url << llendl;
+		//LL_INFOS() << "baked texture url: " << url << LL_ENDL;
 	}
 	return url;
 }
@@ -6055,7 +6055,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
 	} 
 	else if (global_color == mTexEyeColor)
 	{
-//		llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; 
+//		LL_INFOS() << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << LL_ENDL; 
 		invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet);
 	}
 	updateMeshTextures();
@@ -6151,7 +6151,7 @@ void LLVOAvatar::startPhase(const std::string& phase_name)
 	bool completed = false;
 	bool found = getPhases().getPhaseValues(phase_name, elapsed, completed);
 	//LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name
-	//					<< " found " << found << " elapsed " << elapsed << " completed " << completed << llendl;
+	//					<< " found " << found << " elapsed " << elapsed << " completed " << completed << LL_ENDL;
 	if (found)
 	{
 		if (!completed)
@@ -7146,7 +7146,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	llassert(appearance_version > 0);
 	if (appearance_version > 1)
 	{
-		llwarns << "unsupported appearance version " << appearance_version << ", discarding appearance message" << llendl;
+		LL_WARNS() << "unsupported appearance version " << appearance_version << ", discarding appearance message" << LL_ENDL;
 		return;
 	}
 
@@ -7157,7 +7157,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	{
 		LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version
 				<< " last_update_request_cof_version " << last_update_request_cof_version
-				<<  " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << llendl;
+				<<  " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL;
 	}
 	else
 	{
@@ -7208,14 +7208,14 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			&& mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT
 			&& baked_index != BAKED_SKIRT)
 		{
-			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << llendl;
+			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << LL_ENDL;
 			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, 
 				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
 		}
 		else
 		{
 			LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using texture id "
-								<< getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << llendl;
+								<< getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << LL_ENDL;
 		}
 	}
 
@@ -7256,7 +7256,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 
 				if(is_first_appearance_message)
 				{
-					//LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << llendl;
+					//LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << LL_ENDL;
 					param->setWeight(newWeight);
 				}
 				else
@@ -7273,7 +7273,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 			LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << ").  Processing what we can.  object: " << getID() << LL_ENDL;
 		}
 
-		LL_DEBUGS("Avatar") << "Changed " << params_changed_count << " params" << llendl;
+		LL_DEBUGS("Avatar") << "Changed " << params_changed_count << " params" << LL_ENDL;
 		if (params_changed)
 		{
 			if (interp_params)
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 20ef72708c..84e5567d37 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -232,13 +232,13 @@ bool LLVOAvatarSelf::checkStuckAppearance()
 	
 	if (gAgentWearables.isCOFChangeInProgress())
 	{
-		LL_DEBUGS("Avatar") << "checking for stuck appearance" << llendl;
+		LL_DEBUGS("Avatar") << "checking for stuck appearance" << LL_ENDL;
 		F32 change_time = gAgentWearables.getCOFChangeTime();
-		LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << llendl;
+		LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << LL_ENDL;
 		S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns();
-		LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << llendl;
+		LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << LL_ENDL;
 		S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations();
-		LL_DEBUGS("Avatar") << "active copy operations " << active_copies << llendl;
+		LL_DEBUGS("Avatar") << "active copy operations " << active_copies << LL_ENDL;
 
 		if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) ||
 			(change_time > UNCONDITIONAL_UNSTICK_INTERVAL))
@@ -2526,7 +2526,6 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 			}
 
 			invalidateComposite(layer_set);
-			LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
 		}
 		else
 		{
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 7f08d42e8b..b61fbbd073 100755
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -81,7 +81,7 @@ void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& weara
 	LLViewerWearable* instance = get_if_there(mList, assetID, (LLViewerWearable*)NULL );
 	if( instance )
 	{
-		LL_DEBUGS("Avatar") << "wearable " << assetID << " found in LLWearableList" << llendl;
+		LL_DEBUGS("Avatar") << "wearable " << assetID << " found in LLWearableList" << LL_ENDL;
 		asset_arrived_callback( instance, userdata );
 	}
 	else
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index 6ee42d2274..ddb7f7bfce 100755
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -168,13 +168,13 @@ public:
 			const std::string& redir_url = getResponseHeader(HTTP_IN_HEADER_LOCATION);
 			if (redir_url.empty())
 			{
-				llwarns << "Received empty redirection URL " << dumpResponse() << llendl;
+				LL_WARNS() << "Received empty redirection URL " << dumpResponse() << LL_ENDL;
 				LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
 				LLWebProfile::reportImageUploadStatus(false);
 			}
 			else
 			{
-				LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
+				LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
 				LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
 			}
 		}
diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp
index 7036162014..82615e55fc 100755
--- a/indra/newview/llwebsharing.cpp
+++ b/indra/newview/llwebsharing.cpp
@@ -82,9 +82,9 @@ public:
 		// Only emit a warning if we failed to parse when 'content-type' == 'application/json'
 		if (!parsed && (HTTP_CONTENT_JSON == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
 		{
-			llwarns << "Failed to deserialize LLSD from JSON response. " << getURL()
+			LL_WARNS() << "Failed to deserialize LLSD from JSON response. " << getURL()
 				<< " [status:" << mStatus << "] " 
-				<< "(" << mReason << ") body: " << debug_body << llendl;
+				<< "(" << mReason << ") body: " << debug_body << LL_ENDL;
 		}
 
 		if (!parsed)
-- 
cgit v1.2.3


From 76023f172c2a8eeb5c8d6b55119ef3e8faf8cc6f Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Wed, 14 May 2014 22:55:19 +0100
Subject: MAINT-4009: Patching a leak of LLVisualParam derived objects that
 were being leaked because the LLWearable class was not destroying itself
 properly.

---
 indra/llappearance/llwearable.cpp   |  8 ++++++++
 indra/llcharacter/llvisualparam.cpp | 13 ++++++++++++-
 indra/llcharacter/llvisualparam.h   |  1 +
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 6749a85f3c..d064b2982c 100644
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -60,6 +60,14 @@ LLWearable::LLWearable()
 // virtual
 LLWearable::~LLWearable()
 {
+	for (visual_param_index_map_t::iterator vpIter = mVisualParamIndexMap.begin(); vpIter != mVisualParamIndexMap.end(); ++vpIter)
+	{
+		LLVisualParam* vp = vpIter->second;
+		vp->clearNextParam();
+		delete vp;
+		vpIter->second = NULL;
+	}
+
 	destroyTextures();
 }
 
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index 0df7fb2bc3..dd87847c18 100755
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -178,7 +178,10 @@ LLVisualParam::LLVisualParam()
 //-----------------------------------------------------------------------------
 LLVisualParam::~LLVisualParam()
 {
-	delete mNext;
+	if (mNext != NULL)
+	{
+		delete mNext;
+	}
 }
 
 /*
@@ -284,6 +287,14 @@ void LLVisualParam::setNextParam( LLVisualParam *next )
 	mNext = next;
 }
 
+//-----------------------------------------------------------------------------
+// clearNextParam()
+//-----------------------------------------------------------------------------
+void LLVisualParam::clearNextParam()
+{
+	mNext = NULL;
+}
+
 //-----------------------------------------------------------------------------
 // animate()
 //-----------------------------------------------------------------------------
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index a4d9f93e56..78c776705f 100755
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -155,6 +155,7 @@ public:
 
 	LLVisualParam*			getNextParam()		{ return mNext; }
 	void					setNextParam( LLVisualParam *next );
+	void					clearNextParam();
 	
 	virtual void			setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; }
 	BOOL					getAnimating() const { return mIsAnimating; }
-- 
cgit v1.2.3


From 01ad22ce197ba3bbf97ee396e163e5de529ad2e8 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 15 May 2014 12:53:09 -0400
Subject: fix for bad merge

---
 indra/newview/llinventorymodel.cpp | 166 +++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 29b9c2b998..14ca0095ae 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2268,6 +2268,172 @@ void LLInventoryModel::buildParentChildMap()
 					   << cat->getName() << LL_ENDL;
 			++lost;
 			lost_cats.push_back(cat);
+		}
+	}
+	if(lost)
+	{
+		LL_WARNS() << "Found  " << lost << " lost categories." << LL_ENDL;
+	}
+
+	// Do moves in a separate pass to make sure we've properly filed
+	// the FT_LOST_AND_FOUND category before we try to find its UUID.
+	for(i = 0; i<lost_cats.size(); ++i)
+	{
+		LLViewerInventoryCategory *cat = lost_cats.at(i);
+
+		// plop it into the lost & found.
+		LLFolderType::EType pref = cat->getPreferredType();
+		if(LLFolderType::FT_NONE == pref)
+		{
+			cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
+		}
+		else if(LLFolderType::FT_ROOT_INVENTORY == pref)
+		{
+			// it's the root
+			cat->setParent(LLUUID::null);
+		}
+		else
+		{
+			// it's a protected folder.
+			cat->setParent(gInventory.getRootFolderID());
+		}
+		// FIXME note that updateServer() fails with protected
+		// types, so this will not work as intended in that case.
+		cat->updateServer(TRUE);
+		catsp = getUnlockedCatArray(cat->getParentUUID());
+		if(catsp)
+		{
+			catsp->push_back(cat);
+		}
+		else
+		{		
+			LL_WARNS() << "Lost and found Not there!!" << LL_ENDL;
+		}
+	}
+
+	const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null);
+	sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
+
+
+	// Now the items. We allocated in the last step, so now all we
+	// have to do is iterate over the items and put them in the right
+	// place.
+	item_array_t items;
+	if(!mItemMap.empty())
+	{
+		LLPointer<LLViewerInventoryItem> item;
+		for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+		{
+			item = (*iit).second;
+			items.push_back(item);
+		}
+	}
+	count = items.size();
+	lost = 0;
+	uuid_vec_t lost_item_ids;
+	for(i = 0; i < count; ++i)
+	{
+		LLPointer<LLViewerInventoryItem> item;
+		item = items.at(i);
+		itemsp = getUnlockedItemArray(item->getParentUUID());
+		if(itemsp)
+		{
+			itemsp->push_back(item);
+		}
+		else
+		{
+			LL_INFOS() << "Lost item: " << item->getUUID() << " - "
+					   << item->getName() << LL_ENDL;
+			++lost;
+			// plop it into the lost & found.
+			//
+			item->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
+			// move it later using a special message to move items. If
+			// we update server here, the client might crash.
+			//item->updateServer();
+			lost_item_ids.push_back(item->getUUID());
+			itemsp = getUnlockedItemArray(item->getParentUUID());
+			if(itemsp)
+			{
+				itemsp->push_back(item);
+			}
+			else
+			{
+				LL_WARNS() << "Lost and found Not there!!" << LL_ENDL;
+			}
+		}
+	}
+	if(lost)
+	{
+		LL_WARNS() << "Found " << lost << " lost items." << LL_ENDL;
+		LLMessageSystem* msg = gMessageSystem;
+		BOOL start_new_message = TRUE;
+		const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+		for(uuid_vec_t::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it)
+		{
+			if(start_new_message)
+			{
+				start_new_message = FALSE;
+				msg->newMessageFast(_PREHASH_MoveInventoryItem);
+				msg->nextBlockFast(_PREHASH_AgentData);
+				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+				msg->addBOOLFast(_PREHASH_Stamp, FALSE);
+			}
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addUUIDFast(_PREHASH_ItemID, (*it));
+			msg->addUUIDFast(_PREHASH_FolderID, lnf);
+			msg->addString("NewName", NULL);
+			if(msg->isSendFull(NULL))
+			{
+				start_new_message = TRUE;
+				gAgent.sendReliableMessage();
+			}
+		}
+		if(!start_new_message)
+		{
+			gAgent.sendReliableMessage();
+		}
+	}
+
+	const LLUUID &agent_inv_root_id = gInventory.getRootFolderID();
+	if (agent_inv_root_id.notNull())
+	{
+		cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
+		if(catsp)
+		{
+			// *HACK - fix root inventory folder
+			// some accounts has pbroken inventory root folders
+			
+			std::string name = "My Inventory";
+			LLUUID prev_root_id = mRootFolderID;
+			for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
+					 it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
+			{
+				cat_array_t* cat_array = it->second;
+				for (cat_array_t::const_iterator cat_it = cat_array->begin(),
+						 cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it)
+					{
+					LLPointer<LLViewerInventoryCategory> category = *cat_it;
+
+					if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY)
+						continue;
+					if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) )
+					{
+						if(category->getUUID()!=mRootFolderID)
+						{
+							LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID);
+							new_inv_root_folder_id = category->getUUID();
+						}
+					}
+				}
+			}
+
+			// 'My Inventory',
+			// root of the agent's inv found.
+			// The inv tree is built.
+			mIsAgentInvUsable = true;
+
 			// notifyObservers() has been moved to
 			// llstartup/idle_startup() after this func completes.
 			// Allows some system categories to be created before
-- 
cgit v1.2.3


From f2d7dfb1e6689968459ef680e608546d474da008 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 16 May 2014 10:18:53 -0400
Subject: merge fixes

---
 indra/newview/llagentwearables.cpp | 2 +-
 indra/newview/llappearancemgr.cpp  | 8 +-------
 indra/newview/llvoavatarself.cpp   | 1 +
 3 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 11666f6c8f..26626ad894 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -654,7 +654,7 @@ public:
 	/* virtual */ void fire(const LLUUID& inv_item)
 	{
 		LL_INFOS() << "One item created " << inv_item.asString() << LL_ENDL;
-		LLViewerInventoryItem *item = gInventory.getItem(inv_item);
+		LLConstPointer<LLInventoryObject> item = gInventory.getItem(inv_item);
 		mItemsToLink.push_back(item);
 		updatePendingWearable(inv_item);
 	}
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index dc503dc50e..a4c430bada 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -926,7 +926,7 @@ void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLView
 	}
 
 	LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL;
-	LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
+	LLConstPointer<LLInventoryObject> itemp = gInventory.getItem(item_id);
 	wearable->setItemID(item_id);
 	holder->eraseTypeToRecover(type);
 	llassert(itemp);
@@ -2975,12 +2975,6 @@ struct WearablesOrderComparator
 
 	bool operator()(const LLInventoryItem* item1, const LLInventoryItem* item2)
 	{
-		if (!item1 || !item2)
-		{
-			LL_WARNS() << "either item1 or item2 is NULL" << LL_ENDL;
-			return true;
-		}
-		
 		const std::string& desc1 = item1->getActualDescription();
 		const std::string& desc2 = item2->getActualDescription();
 		
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 84e5567d37..1f497bc107 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2526,6 +2526,7 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
 			}
 
 			invalidateComposite(layer_set);
+			add(LLStatViewer::TEX_REBAKES, 1);
 		}
 		else
 		{
-- 
cgit v1.2.3


From 7f3e1b73137d51e27075c6a71c25c4eafd6cb21c Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 16 May 2014 13:28:22 -0400
Subject: merge fix

---
 indra/llmessage/llsdrpcclient.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index 84cd7fb851..c4e0333ca3 100755
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -240,7 +240,7 @@ public:
 	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
 	{
 		LL_DEBUGS() << "LLSDRPCClientFactory::build" << LL_ENDL;
-		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
+		LLURLRequest* http(new LLURLRequest(HTTP_POST));
 		if(!http->isValid())
 		{
 			LL_WARNS() << "Creating LLURLRequest failed." << LL_ENDL ;
-- 
cgit v1.2.3


From a5bb8839fa24fa0b7da331f14eedccea1b44bc84 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 16 May 2014 15:47:34 -0400
Subject: merge fix

---
 indra/newview/llhttpretrypolicy.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 7001a9a88b..2d4ce6c883 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -137,6 +137,6 @@ bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
 		seconds_to_wait = F32_MAX;
 		return false;
 	}
-	seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX;
+	seconds_to_wait = mShouldRetry ? (F32) mRetryTimer.getRemainingTimeF32() : F32_MAX;
 	return mShouldRetry;
 }
-- 
cgit v1.2.3


From 34b2f2d1f841f7b7f93386d66be6943910cd055b Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 16 May 2014 22:44:25 +0100
Subject: MAINT-4009: First pass refactoring to eliminate memory related to
 error reporting that is not properly cleaned up.

---
 indra/llcommon/llerror.cpp            |  54 ++++++++--------
 indra/llcommon/llerrorcontrol.h       |  15 +++--
 indra/llcommon/tests/llerror_test.cpp |  76 ++++++++++++++---------
 indra/llcommon/tests/wrapllerrs.h     | 113 ++++++++++++++++++----------------
 indra/newview/llviewerwindow.cpp      |  25 ++++++--
 indra/test/test.cpp                   |  62 ++++++++++++++-----
 6 files changed, 205 insertions(+), 140 deletions(-)

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 4f721fabdf..09a2d38e1a 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -357,7 +357,7 @@ namespace
 
 
 	typedef std::map<std::string, LLError::ELevel> LevelMap;
-	typedef std::vector<LLError::Recorder*> Recorders;
+	typedef std::vector<LLError::RecorderPtr> Recorders;
 	typedef std::vector<LLError::CallSite*> CallSiteVector;
 
 	class Globals : public LLSingleton<Globals>
@@ -419,8 +419,8 @@ namespace LLError
 		LLError::TimeFunction               mTimeFunction;
 		
 		Recorders                           mRecorders;
-		Recorder*                           mFileRecorder;
-		Recorder*                           mFixedBufferRecorder;
+		RecorderPtr                           mFileRecorder;
+		RecorderPtr                           mFixedBufferRecorder;
 		std::string                         mFileRecorderFileName;
 		
 		int									mShouldLogCallCounter;
@@ -437,14 +437,13 @@ namespace LLError
 			mDefaultLevel(LLError::LEVEL_DEBUG),
 			mCrashFunction(),
 			mTimeFunction(NULL),
-			mFileRecorder(NULL),
-			mFixedBufferRecorder(NULL),
+			mFileRecorder(),
+			mFixedBufferRecorder(),
 			mShouldLogCallCounter(0)
 			{ }
 		
 		~Settings()
 		{
-			for_each(mRecorders.begin(), mRecorders.end(), DeletePointer());
 			mRecorders.clear();
 		}
 		
@@ -603,11 +602,13 @@ namespace
 		// log_to_stderr is only false in the unit and integration tests to keep builds quieter
 		if (log_to_stderr && shouldLogToStderr())
 		{
-			LLError::addRecorder(new RecordToStderr(stderrLogWantsTime()));
+			LLError::RecorderPtr recordToStdErr(new RecordToStderr(stderrLogWantsTime()));
+			LLError::addRecorder(recordToStdErr);
 		}
 		
 #if LL_WINDOWS
-		LLError::addRecorder(new RecordToWinDebug);
+		LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug());
+		LLError::addRecorder(recordToWinDebug);
 #endif
 
 		LogControlFile& e = LogControlFile::fromDirectory(dir);
@@ -635,7 +636,8 @@ namespace LLError
 		}
 		commonInit(dir);
 #if !LL_WINDOWS
-		addRecorder(new RecordToSyslog(identity));
+		LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity));
+		addRecorder(recordToSyslog);
 #endif
 	}
 
@@ -821,9 +823,9 @@ namespace LLError
 		return mWantsFunctionName;
 	}
 
-	void addRecorder(Recorder* recorder)
+	void addRecorder(RecorderPtr recorder)
 	{
-		if (recorder == NULL)
+		if (!recorder)
 		{
 			return;
 		}
@@ -831,9 +833,9 @@ namespace LLError
 		s.mRecorders.push_back(recorder);
 	}
 
-	void removeRecorder(Recorder* recorder)
+	void removeRecorder(RecorderPtr recorder)
 	{
-		if (recorder == NULL)
+		if (!recorder)
 		{
 			return;
 		}
@@ -850,8 +852,7 @@ namespace LLError
 		LLError::Settings& s = LLError::Settings::get();
 
 		removeRecorder(s.mFileRecorder);
-		delete s.mFileRecorder;
-		s.mFileRecorder = NULL;
+		s.mFileRecorder.reset();
 		s.mFileRecorderFileName.clear();
 		
 		if (file_name.empty())
@@ -859,16 +860,13 @@ namespace LLError
 			return;
 		}
 		
-		RecordToFile* f = new RecordToFile(file_name);
-		if (!f->okay())
+		RecorderPtr recordToFile(new RecordToFile(file_name));
+		if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay())
 		{
-			delete f;
-			return;
+			s.mFileRecorderFileName = file_name;
+			s.mFileRecorder = recordToFile;
+			addRecorder(recordToFile);
 		}
-
-		s.mFileRecorderFileName = file_name;
-		s.mFileRecorder = f;
-		addRecorder(f);
 	}
 	
 	void logToFixedBuffer(LLLineBuffer* fixedBuffer)
@@ -876,16 +874,16 @@ namespace LLError
 		LLError::Settings& s = LLError::Settings::get();
 
 		removeRecorder(s.mFixedBufferRecorder);
-		delete s.mFixedBufferRecorder;
-		s.mFixedBufferRecorder = NULL;
+		s.mFixedBufferRecorder.reset();
 		
 		if (!fixedBuffer)
 		{
 			return;
 		}
 		
-		s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
-		addRecorder(s.mFixedBufferRecorder);
+		RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
+		s.mFixedBufferRecorder = recordToFixedBuffer;
+		addRecorder(recordToFixedBuffer);
 	}
 
 	std::string logFileName()
@@ -906,7 +904,7 @@ namespace
 			i != s.mRecorders.end();
 			++i)
 		{
-			LLError::Recorder* r = *i;
+			LLError::RecorderPtr r = *i;
 			
 			std::ostringstream message_stream;
 
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index aab695094c..681f444234 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -30,6 +30,7 @@
 
 #include "llerror.h"
 #include "boost/function.hpp"
+#include "boost/shared_ptr.hpp"
 #include <string>
 
 class LLSD;
@@ -156,16 +157,14 @@ namespace LLError
 				mWantsFunctionName;
 	};
 
+	typedef boost::shared_ptr<Recorder> RecorderPtr;
+
 	/**
-	 * @NOTE: addRecorder() conveys ownership to the underlying Settings
-	 * object -- when destroyed, it will @em delete the passed Recorder*!
-	 */
-	LL_COMMON_API void addRecorder(Recorder*);
-	/**
-	 * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its
-	 * lifespan becomes the caller's problem.
+	 * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership
+	 * while still ensuring that the allocated memory is eventually freed
 	 */
-	LL_COMMON_API void removeRecorder(Recorder*);
+	LL_COMMON_API void addRecorder(RecorderPtr);
+	LL_COMMON_API void removeRecorder(RecorderPtr);
 		// each error message is passed to each recorder via recordMessage()
 
 	LL_COMMON_API void logToFile(const std::string& filename);
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index b28c5ba4b3..6cecd6bbc8 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -56,9 +56,9 @@ namespace tut
 	{
 	public:
 		TestRecorder() { mWantsTime = false; }
-		~TestRecorder() { LLError::removeRecorder(this); }
+		virtual ~TestRecorder() {  }
 
-		void recordMessage(LLError::ELevel level,
+		virtual void recordMessage(LLError::ELevel level,
 						   const std::string& message)
 		{
 			mMessages.push_back(message);
@@ -85,15 +85,11 @@ namespace tut
 
 	struct ErrorTestData
 	{
-		// addRecorder() expects to be able to later delete the passed
-		// Recorder*. Even though removeRecorder() reclaims ownership, passing
-		// a pointer to a data member rather than a heap Recorder subclass
-		// instance would just be Wrong.
-		TestRecorder* mRecorder;
+		LLError::RecorderPtr mRecorder;
 		LLError::Settings* mPriorErrorSettings;
 
 		ErrorTestData():
-			mRecorder(new TestRecorder)
+			mRecorder(new TestRecorder())
 		{
 			fatalWasCalled = false;
 
@@ -106,13 +102,32 @@ namespace tut
 		~ErrorTestData()
 		{
 			LLError::removeRecorder(mRecorder);
-			delete mRecorder;
 			LLError::restoreSettings(mPriorErrorSettings);
 		}
 
+		int countMessages()
+		{
+			return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages();
+		}
+
+		void clearMessages()
+		{
+			boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages();
+		}
+
+		void setWantsTime(bool t)
+		{
+			boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->setWantsTime(t);
+		}
+
+		std::string message(int n)
+		{
+			return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n);
+		}
+
 		void ensure_message_count(int expectedCount)
 		{
-			ensure_equals("message count", mRecorder->countMessages(), expectedCount);
+			ensure_equals("message count", countMessages(), expectedCount);
 		}
 
 		void ensure_message_contains(int n, const std::string& expectedText)
@@ -120,7 +135,7 @@ namespace tut
 			std::ostringstream test_name;
 			test_name << "testing message " << n;
 
-			ensure_contains(test_name.str(), mRecorder->message(n), expectedText);
+			ensure_contains(test_name.str(), message(n), expectedText);
 		}
 
 		void ensure_message_does_not_contain(int n, const std::string& expectedText)
@@ -128,7 +143,7 @@ namespace tut
 			std::ostringstream test_name;
 			test_name << "testing message " << n;
 
-			ensure_does_not_contain(test_name.str(), mRecorder->message(n), expectedText);
+			ensure_does_not_contain(test_name.str(), message(n), expectedText);
 		}
 	};
 
@@ -385,15 +400,15 @@ namespace
 	}
 
 	typedef std::string (*LogFromFunction)(bool);
-	void testLogName(tut::TestRecorder* recorder, LogFromFunction f,
+	void testLogName(LLError::RecorderPtr recorder, LogFromFunction f,
 		const std::string& class_name = "")
 	{
-		recorder->clearMessages();
+		boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages();
 		std::string name = f(false);
 		f(true);
 
-		std::string messageWithoutName = recorder->message(0);
-		std::string messageWithName = recorder->message(1);
+		std::string messageWithoutName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0);
+		std::string messageWithName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1);
 
 		ensure_has(name + " logged without name",
 			messageWithoutName, name);
@@ -528,12 +543,12 @@ namespace tut
 	{
 		LLError::setTimeFunction(roswell);
 
-		mRecorder->setWantsTime(false);
+		setWantsTime(false);
 		ufoSighting();
 		ensure_message_contains(0, "ufo");
 		ensure_message_does_not_contain(0, roswell());
 
-		mRecorder->setWantsTime(true);
+		setWantsTime(true);
 		ufoSighting();
 		ensure_message_contains(1, "ufo");
 		ensure_message_contains(1, roswell());
@@ -545,13 +560,13 @@ namespace tut
 	{
 		LLError::setPrintLocation(true);
 		LLError::setTimeFunction(roswell);
-		mRecorder->setWantsTime(true);
+		setWantsTime(true);
 		std::string location,
 					function;
 		writeReturningLocationAndFunction(location, function);
 
 		ensure_equals("order is location time type function message",
-			mRecorder->message(0),
+			message(0),
 			location + roswell() + " INFO: " + function + ": apple");
 	}
 
@@ -559,19 +574,19 @@ namespace tut
 		// multiple recorders
 	void ErrorTestObject::test<11>()
 	{
-		TestRecorder* altRecorder(new TestRecorder);
+		LLError::RecorderPtr altRecorder(new TestRecorder());
 		LLError::addRecorder(altRecorder);
 
 		LL_INFOS() << "boo" << LL_ENDL;
 
 		ensure_message_contains(0, "boo");
-		ensure_equals("alt recorder count", altRecorder->countMessages(), 1);
-		ensure_contains("alt recorder message 0", altRecorder->message(0), "boo");
+		ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1);
+		ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");
 
 		LLError::setTimeFunction(roswell);
 
-		TestRecorder* anotherRecorder(new TestRecorder);
-		anotherRecorder->setWantsTime(true);
+		LLError::RecorderPtr anotherRecorder(new TestRecorder());
+		boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->setWantsTime(true);
 		LLError::addRecorder(anotherRecorder);
 
 		LL_INFOS() << "baz" << LL_ENDL;
@@ -579,10 +594,13 @@ namespace tut
 		std::string when = roswell();
 
 		ensure_message_does_not_contain(1, when);
-		ensure_equals("alt recorder count", altRecorder->countMessages(), 2);
-		ensure_does_not_contain("alt recorder message 1", altRecorder->message(1), when);
-		ensure_equals("another recorder count", anotherRecorder->countMessages(), 1);
-		ensure_contains("another recorder message 0", anotherRecorder->message(0), when);
+		ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2);
+		ensure_does_not_contain("alt recorder message 1", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when);
+		ensure_equals("another recorder count", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1);
+		ensure_contains("another recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when);
+
+		LLError::removeRecorder(altRecorder);
+		LLError::removeRecorder(anotherRecorder);
 	}
 }
 
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 3137bd8fea..0a52844671 100755
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -38,6 +38,7 @@
 #include "stringize.h"
 #include <boost/bind.hpp>
 #include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
 #include <list>
 #include <string>
 #include <stdexcept>
@@ -85,68 +86,25 @@ struct WrapLLErrs
     LLError::FatalFunction mPriorFatal;
 };
 
-/**
- * LLError::addRecorder() accepts ownership of the passed Recorder* -- it
- * expects to be able to delete it later. CaptureLog isa Recorder whose
- * pointer we want to be able to pass without any ownership implications.
- * For such cases, instantiate a new RecorderProxy(yourRecorder) and pass
- * that. Your heap RecorderProxy might later be deleted, but not yourRecorder.
- */
-class RecorderProxy: public LLError::Recorder
-{
-public:
-    RecorderProxy(LLError::Recorder* recorder):
-        mRecorder(recorder)
-    {}
-
-    virtual void recordMessage(LLError::ELevel level, const std::string& message)
-    {
-        mRecorder->recordMessage(level, message);
-    }
-
-    virtual bool wantsTime()
-    {
-        return mRecorder->wantsTime();
-    }
-
-private:
-    LLError::Recorder* mRecorder;
-};
-
 /**
  * Capture log messages. This is adapted (simplified) from the one in
  * llerror_test.cpp.
  */
-class CaptureLog : public LLError::Recorder, public boost::noncopyable
+class CaptureLogRecorder : public LLError::Recorder, public boost::noncopyable
 {
 public:
-    CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG):
-        // Mostly what we're trying to accomplish by saving and resetting
-        // LLError::Settings is to bypass the default RecordToStderr and
-        // RecordToWinDebug Recorders. As these are visible only inside
-        // llerror.cpp, we can't just call LLError::removeRecorder() with
-        // each. For certain tests we need to produce, capture and examine
-        // DEBUG log messages -- but we don't want to spam the user's console
-        // with that output. If it turns out that saveAndResetSettings() has
-        // some bad effect, give up and just let the DEBUG level log messages
-        // display.
-        mOldSettings(LLError::saveAndResetSettings()),
-        mProxy(new RecorderProxy(this))
+    CaptureLogRecorder()
+		: LLError::Recorder(),
+		boost::noncopyable(),
+		mMessages()
     {
-        LLError::setFatalFunction(wouldHaveCrashed);
-        LLError::setDefaultLevel(level);
-        LLError::addRecorder(mProxy);
     }
 
-    ~CaptureLog()
+    virtual ~CaptureLogRecorder()
     {
-        LLError::removeRecorder(mProxy);
-        delete mProxy;
-        LLError::restoreSettings(mOldSettings);
     }
 
-    void recordMessage(LLError::ELevel level,
-                       const std::string& message)
+    virtual void recordMessage(LLError::ELevel level, const std::string& message)
     {
         mMessages.push_back(message);
     }
@@ -154,7 +112,7 @@ public:
     /// Don't assume the message we want is necessarily the LAST log message
     /// emitted by the underlying code; search backwards through all messages
     /// for the sought string.
-    std::string messageWith(const std::string& search, bool required=true)
+    std::string messageWith(const std::string& search, bool required)
     {
         for (MessageList::const_reverse_iterator rmi(mMessages.rbegin()), rmend(mMessages.rend());
              rmi != rmend; ++rmi)
@@ -187,14 +145,63 @@ public:
         return out;
     }
 
+private:
     typedef std::list<std::string> MessageList;
     MessageList mMessages;
+};
+
+/**
+ * Capture log messages. This is adapted (simplified) from the one in
+ * llerror_test.cpp.
+ */
+class CaptureLog : public boost::noncopyable
+{
+public:
+    CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG)
+        // Mostly what we're trying to accomplish by saving and resetting
+        // LLError::Settings is to bypass the default RecordToStderr and
+        // RecordToWinDebug Recorders. As these are visible only inside
+        // llerror.cpp, we can't just call LLError::removeRecorder() with
+        // each. For certain tests we need to produce, capture and examine
+        // DEBUG log messages -- but we don't want to spam the user's console
+        // with that output. If it turns out that saveAndResetSettings() has
+        // some bad effect, give up and just let the DEBUG level log messages
+        // display.
+		: boost::noncopyable(),
+        mOldSettings(LLError::saveAndResetSettings()),
+		mRecorder(new CaptureLogRecorder())
+    {
+        LLError::setFatalFunction(wouldHaveCrashed);
+        LLError::setDefaultLevel(level);
+        LLError::addRecorder(mRecorder);
+    }
+
+    ~CaptureLog()
+    {
+        LLError::removeRecorder(mRecorder);
+        LLError::restoreSettings(mOldSettings);
+    }
+
+    /// Don't assume the message we want is necessarily the LAST log message
+    /// emitted by the underlying code; search backwards through all messages
+    /// for the sought string.
+    std::string messageWith(const std::string& search, bool required=true)
+    {
+		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required);
+    }
+
+    std::ostream& streamto(std::ostream& out) const
+    {
+		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out);
+    }
+
+private:
     LLError::Settings* mOldSettings;
-    LLError::Recorder* mProxy;
+	LLError::RecorderPtr mRecorder;
 };
 
 inline
-std::ostream& operator<<(std::ostream& out, const CaptureLog& log)
+std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log)
 {
     return log.streamto(out);
 }
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2cb8e6a3ab..8e5d577968 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -261,7 +261,7 @@ std::string	LLViewerWindow::sMovieBaseName;
 LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity");
 
 
-class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
+class RecordToChatConsoleRecorder : public LLError::Recorder
 {
 public:
 	virtual void recordMessage(LLError::ELevel level,
@@ -285,6 +285,22 @@ public:
 	}
 };
 
+class RecordToChatConsole : public LLSingleton<RecordToChatConsole>
+{
+public:
+	RecordToChatConsole()
+		: LLSingleton<RecordToChatConsole>(),
+		mRecorder(new RecordToChatConsoleRecorder())
+	{
+	}
+
+	void startRecorder() { LLError::addRecorder(mRecorder); }
+	void stopRecorder() { LLError::removeRecorder(mRecorder); }
+
+private:
+	LLError::RecorderPtr mRecorder;
+};
+
 ////////////////////////////////////////////////////////////////////////////
 //
 // LLDebugText
@@ -1889,11 +1905,11 @@ void LLViewerWindow::initBase()
 	// optionally forward warnings to chat console/chat floater
 	// for qa runs and dev builds
 #if  !LL_RELEASE_FOR_DOWNLOAD
-	LLError::addRecorder(RecordToChatConsole::getInstance());
+	RecordToChatConsole::getInstance()->startRecorder();
 #else
 	if(gSavedSettings.getBOOL("QAMode"))
 	{
-		LLError::addRecorder(RecordToChatConsole::getInstance());
+		RecordToChatConsole::getInstance()->startRecorder();
 	}
 #endif
 
@@ -2040,8 +2056,7 @@ void LLViewerWindow::initWorldUI()
 void LLViewerWindow::shutdownViews()
 {
 	// clean up warning logger
-	LLError::removeRecorder(RecordToChatConsole::getInstance());
-
+	RecordToChatConsole::getInstance()->stopRecorder();
 	LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ;
 
 	delete mDebugText;
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 10f71a2843..0dd21b6a05 100755
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -95,25 +95,20 @@ public:
 	virtual void replay(std::ostream&) {}
 };
 
-class LLReplayLogReal: public LLReplayLog, public LLError::Recorder, public boost::noncopyable
+class RecordToTempFile : public LLError::Recorder, public boost::noncopyable
 {
 public:
-	LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool):
-		mOldSettings(LLError::saveAndResetSettings()),
-		mProxy(new RecorderProxy(this)),
-		mTempFile("log", "", pool),		// create file
-		mFile(mTempFile.getName().c_str()) // open it
+	RecordToTempFile(apr_pool_t* pPool)
+		: LLError::Recorder(),
+		boost::noncopyable(),
+		mTempFile("log", "", pPool),
+		mFile(mTempFile.getName().c_str())
 	{
-		LLError::setFatalFunction(wouldHaveCrashed);
-		LLError::setDefaultLevel(level);
-		LLError::addRecorder(mProxy);
 	}
 
-	virtual ~LLReplayLogReal()
+	virtual ~RecordToTempFile()
 	{
-		LLError::removeRecorder(mProxy);
-		delete mProxy;
-		LLError::restoreSettings(mOldSettings);
+		mFile.close();
 	}
 
 	virtual void recordMessage(LLError::ELevel level, const std::string& message)
@@ -121,13 +116,13 @@ public:
 		mFile << message << std::endl;
 	}
 
-	virtual void reset()
+	void reset()
 	{
 		mFile.close();
 		mFile.open(mTempFile.getName().c_str());
 	}
 
-	virtual void replay(std::ostream& out)
+	void replay(std::ostream& out)
 	{
 		mFile.close();
 		std::ifstream inf(mTempFile.getName().c_str());
@@ -139,12 +134,45 @@ public:
 	}
 
 private:
-	LLError::Settings* mOldSettings;
-	LLError::Recorder* mProxy;
 	NamedTempFile mTempFile;
 	std::ofstream mFile;
 };
 
+class LLReplayLogReal: public LLReplayLog, public boost::noncopyable
+{
+public:
+	LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool)
+		: LLReplayLog(),
+		boost::noncopyable(),
+		mOldSettings(LLError::saveAndResetSettings()),
+		mRecorder(new RecordToTempFile(pool))
+	{
+		LLError::setFatalFunction(wouldHaveCrashed);
+		LLError::setDefaultLevel(level);
+		LLError::addRecorder(mRecorder);
+	}
+
+	virtual ~LLReplayLogReal()
+	{
+		LLError::removeRecorder(mRecorder);
+		LLError::restoreSettings(mOldSettings);
+	}
+
+	virtual void reset()
+	{
+		boost::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->reset();
+	}
+
+	virtual void replay(std::ostream& out)
+	{
+		boost::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->replay(out);
+	}
+
+private:
+	LLError::Settings* mOldSettings;
+	LLError::RecorderPtr mRecorder;
+};
+
 class LLTestCallback : public tut::callback
 {
 public:
-- 
cgit v1.2.3


From 08e83a341e76de8fa4d8c4a974edbe3e0bd1c128 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Sat, 17 May 2014 00:41:36 +0100
Subject: MAINT-4009: Final pass refactoring to eliminate memory allocation
 related to error reporting that is not properly cleaned up.

---
 indra/llcommon/llerror.cpp            | 268 ++++++++++++++++++----------------
 indra/llcommon/llerrorcontrol.h       |   8 +-
 indra/llcommon/tests/llerror_test.cpp |   2 +-
 indra/llcommon/tests/wrapllerrs.h     |   4 +-
 indra/test/test.cpp                   |   2 +-
 5 files changed, 149 insertions(+), 135 deletions(-)

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 09a2d38e1a..22cd861c72 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -402,9 +402,13 @@ namespace
 
 namespace LLError
 {
-	class Settings
+	class SettingsConfig : public LLRefCount
 	{
+		friend class Settings;
+
 	public:
+		virtual ~SettingsConfig();
+
 		bool                                mPrintLocation;
 
 		LLError::ELevel                     mDefaultLevel;
@@ -419,80 +423,86 @@ namespace LLError
 		LLError::TimeFunction               mTimeFunction;
 		
 		Recorders                           mRecorders;
-		RecorderPtr                           mFileRecorder;
-		RecorderPtr                           mFixedBufferRecorder;
+		RecorderPtr                         mFileRecorder;
+		RecorderPtr                         mFixedBufferRecorder;
 		std::string                         mFileRecorderFileName;
 		
 		int									mShouldLogCallCounter;
 		
-		static Settings& get();
+	private:
+		SettingsConfig();
+	};
+
+	typedef LLPointer<SettingsConfig> SettingsConfigPtr;
+
+	class Settings : public LLSingleton<Settings>
+	{
+	public:
+		Settings();
+
+		SettingsConfigPtr getSettingsConfig();
 	
-		static void reset();
-		static Settings* saveAndReset();
-		static void restore(Settings*);
+		void reset();
+		SettingsStoragePtr saveAndReset();
+		void restore(SettingsStoragePtr pSettingsStorage);
 		
 	private:
-		Settings()
-		:	mPrintLocation(false),
-			mDefaultLevel(LLError::LEVEL_DEBUG),
-			mCrashFunction(),
-			mTimeFunction(NULL),
-			mFileRecorder(),
-			mFixedBufferRecorder(),
-			mShouldLogCallCounter(0)
-			{ }
-		
-		~Settings()
-		{
-			mRecorders.clear();
-		}
-		
-		static Settings*& getPtr();
+		SettingsConfigPtr mSettingsConfig;
 	};
 	
-	Settings& Settings::get()
+	SettingsConfig::SettingsConfig()
+		: LLRefCount(),
+		mPrintLocation(false),
+		mDefaultLevel(LLError::LEVEL_DEBUG),
+		mFunctionLevelMap(),
+		mClassLevelMap(),
+		mFileLevelMap(),
+		mTagLevelMap(),
+		mUniqueLogMessages(),
+		mCrashFunction(NULL),
+		mTimeFunction(NULL),
+		mRecorders(),
+		mFileRecorder(),
+		mFixedBufferRecorder(),
+		mFileRecorderFileName(),
+		mShouldLogCallCounter(0)
 	{
-		Settings* p = getPtr();
-		if (!p)
-		{
-			reset();
-			p = getPtr();
-		}
-		return *p;
 	}
-	
-	void Settings::reset()
+
+	SettingsConfig::~SettingsConfig()
 	{
-		Globals::getInstance()->invalidateCallSites();
-		
-		Settings*& p = getPtr();
-		delete p;
-		p = new Settings();
+		mRecorders.clear();
+	}
+
+	Settings::Settings()
+		: LLSingleton<Settings>(),
+		mSettingsConfig(new SettingsConfig())
+	{
+	}
+
+	SettingsConfigPtr Settings::getSettingsConfig()
+	{
+		return mSettingsConfig;
 	}
 	
-	Settings* Settings::saveAndReset()
+	void Settings::reset()
 	{
 		Globals::getInstance()->invalidateCallSites();
-		
-		Settings*& p = getPtr();
-		Settings* originalSettings = p;
-		p = new Settings();
-		return originalSettings;
+		mSettingsConfig = new SettingsConfig();
 	}
 	
-	void Settings::restore(Settings* originalSettings)
+	SettingsStoragePtr Settings::saveAndReset()
 	{
-		Globals::getInstance()->invalidateCallSites();
-		
-		Settings*& p = getPtr();
-		delete p;
-		p = originalSettings;
+		SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
+		reset();
+		return oldSettingsConfig;
 	}
 	
-	Settings*& Settings::getPtr()
+	void Settings::restore(SettingsStoragePtr pSettingsStorage)
 	{
-		static Settings* currentSettings = NULL;
-		return currentSettings;
+		Globals::getInstance()->invalidateCallSites();
+		SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
+		mSettingsConfig = newSettingsConfig;
 	}
 }
 
@@ -593,7 +603,7 @@ namespace
 	
 	void commonInit(const std::string& dir, bool log_to_stderr = true)
 	{
-		LLError::Settings::reset();
+		LLError::Settings::getInstance()->reset();
 		
 		LLError::setDefaultLevel(LLError::LEVEL_INFO);
 		LLError::setFatalFunction(LLError::crashAndLoop);
@@ -648,67 +658,67 @@ namespace LLError
 
 	void setPrintLocation(bool print)
 	{
-		Settings& s = Settings::get();
-		s.mPrintLocation = print;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mPrintLocation = print;
 	}
 
 	void setFatalFunction(const FatalFunction& f)
 	{
-		Settings& s = Settings::get();
-		s.mCrashFunction = f;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mCrashFunction = f;
 	}
 
     FatalFunction getFatalFunction()
     {
-        Settings& s = Settings::get();
-        return s.mCrashFunction;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+        return s->mCrashFunction;
     }
 
 	void setTimeFunction(TimeFunction f)
 	{
-		Settings& s = Settings::get();
-		s.mTimeFunction = f;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mTimeFunction = f;
 	}
 
 	void setDefaultLevel(ELevel level)
 	{
 		Globals::getInstance()->invalidateCallSites();
-		Settings& s = Settings::get();
-		s.mDefaultLevel = level;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mDefaultLevel = level;
 	}
 
 	ELevel getDefaultLevel()
 	{
-		Settings& s = Settings::get();
-		return s.mDefaultLevel;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		return s->mDefaultLevel;
 	}
 
 	void setFunctionLevel(const std::string& function_name, ELevel level)
 	{
 		Globals::getInstance()->invalidateCallSites();
-		Settings& s = Settings::get();
-		s.mFunctionLevelMap[function_name] = level;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mFunctionLevelMap[function_name] = level;
 	}
 
 	void setClassLevel(const std::string& class_name, ELevel level)
 	{
 		Globals::getInstance()->invalidateCallSites();
-		Settings& s = Settings::get();
-		s.mClassLevelMap[class_name] = level;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mClassLevelMap[class_name] = level;
 	}
 
 	void setFileLevel(const std::string& file_name, ELevel level)
 	{
 		Globals::getInstance()->invalidateCallSites();
-		Settings& s = Settings::get();
-		s.mFileLevelMap[file_name] = level;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mFileLevelMap[file_name] = level;
 	}
 
 	void setTagLevel(const std::string& tag_name, ELevel level)
 	{
 		Globals::getInstance()->invalidateCallSites();
-		Settings& s = Settings::get();
-		s.mTagLevelMap[tag_name] = level;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mTagLevelMap[tag_name] = level;
 	}
 
 	LLError::ELevel decodeLevel(std::string name)
@@ -753,13 +763,13 @@ namespace LLError
 	void configure(const LLSD& config)
 	{
 		Globals::getInstance()->invalidateCallSites();
-		Settings& s = Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		
-		s.mFunctionLevelMap.clear();
-		s.mClassLevelMap.clear();
-		s.mFileLevelMap.clear();
-		s.mTagLevelMap.clear();
-		s.mUniqueLogMessages.clear();
+		s->mFunctionLevelMap.clear();
+		s->mClassLevelMap.clear();
+		s->mFileLevelMap.clear();
+		s->mTagLevelMap.clear();
+		s->mUniqueLogMessages.clear();
 		
 		setPrintLocation(config["print-location"]);
 		setDefaultLevel(decodeLevel(config["default-level"]));
@@ -772,10 +782,10 @@ namespace LLError
 			
 			ELevel level = decodeLevel(entry["level"]);
 			
-			setLevels(s.mFunctionLevelMap,	entry["functions"],	level);
-			setLevels(s.mClassLevelMap,		entry["classes"],	level);
-			setLevels(s.mFileLevelMap,		entry["files"],		level);
-			setLevels(s.mTagLevelMap,		entry["tags"],		level);
+			setLevels(s->mFunctionLevelMap,	entry["functions"],	level);
+			setLevels(s->mClassLevelMap,	entry["classes"],	level);
+			setLevels(s->mFileLevelMap,		entry["files"],		level);
+			setLevels(s->mTagLevelMap,		entry["tags"],		level);
 		}
 	}
 }
@@ -789,10 +799,12 @@ namespace LLError
 		mWantsLevel(true),
 		mWantsLocation(false),
 		mWantsFunctionName(true)
-	{}
+	{
+	}
 
 	Recorder::~Recorder()
-		{ }
+	{
+	}
 
 	bool Recorder::wantsTime()
 	{ 
@@ -829,8 +841,8 @@ namespace LLError
 		{
 			return;
 		}
-		Settings& s = Settings::get();
-		s.mRecorders.push_back(recorder);
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mRecorders.push_back(recorder);
 	}
 
 	void removeRecorder(RecorderPtr recorder)
@@ -839,9 +851,9 @@ namespace LLError
 		{
 			return;
 		}
-		Settings& s = Settings::get();
-		s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder),
-							s.mRecorders.end());
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
+							s->mRecorders.end());
 	}
 }
 
@@ -849,11 +861,11 @@ namespace LLError
 {
 	void logToFile(const std::string& file_name)
 	{
-		LLError::Settings& s = LLError::Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
-		removeRecorder(s.mFileRecorder);
-		s.mFileRecorder.reset();
-		s.mFileRecorderFileName.clear();
+		removeRecorder(s->mFileRecorder);
+		s->mFileRecorder.reset();
+		s->mFileRecorderFileName.clear();
 		
 		if (file_name.empty())
 		{
@@ -863,18 +875,18 @@ namespace LLError
 		RecorderPtr recordToFile(new RecordToFile(file_name));
 		if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay())
 		{
-			s.mFileRecorderFileName = file_name;
-			s.mFileRecorder = recordToFile;
+			s->mFileRecorderFileName = file_name;
+			s->mFileRecorder = recordToFile;
 			addRecorder(recordToFile);
 		}
 	}
 	
 	void logToFixedBuffer(LLLineBuffer* fixedBuffer)
 	{
-		LLError::Settings& s = LLError::Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
-		removeRecorder(s.mFixedBufferRecorder);
-		s.mFixedBufferRecorder.reset();
+		removeRecorder(s->mFixedBufferRecorder);
+		s->mFixedBufferRecorder.reset();
 		
 		if (!fixedBuffer)
 		{
@@ -882,14 +894,14 @@ namespace LLError
 		}
 		
 		RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
-		s.mFixedBufferRecorder = recordToFixedBuffer;
+		s->mFixedBufferRecorder = recordToFixedBuffer;
 		addRecorder(recordToFixedBuffer);
 	}
 
 	std::string logFileName()
 	{
-		LLError::Settings& s = LLError::Settings::get();
-		return s.mFileRecorderFileName;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		return s->mFileRecorderFileName;
 	}
 }
 
@@ -898,24 +910,24 @@ namespace
 	void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
 	{
 		LLError::ELevel level = site.mLevel;
-		LLError::Settings& s = LLError::Settings::get();
+		LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
 	
-		for (Recorders::const_iterator i = s.mRecorders.begin();
-			i != s.mRecorders.end();
+		for (Recorders::const_iterator i = s->mRecorders.begin();
+			i != s->mRecorders.end();
 			++i)
 		{
 			LLError::RecorderPtr r = *i;
 			
 			std::ostringstream message_stream;
 
-			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
+			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
 			{
 				message_stream << site.mLocationString << " ";
 			}
 
-			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
+			if (show_time && r->wantsTime() && s->mTimeFunction != NULL)
 			{
-				message_stream << s.mTimeFunction() << " ";
+				message_stream << s->mTimeFunction() << " ";
 			}
 
 			if (show_level && r->wantsLevel())
@@ -1042,9 +1054,9 @@ namespace LLError
 			return false;
 		}
 		
-		Settings& s = Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		
-		s.mShouldLogCallCounter++;
+		s->mShouldLogCallCounter++;
 		
 		const std::string& class_name = className(site.mClassInfo);
 		std::string function_name = functionName(site.mFunction);
@@ -1058,17 +1070,17 @@ namespace LLError
 			function_name = class_name + "::" + function_name;
 		}
 
-		ELevel compareLevel = s.mDefaultLevel;
+		ELevel compareLevel = s->mDefaultLevel;
 
 		// The most specific match found will be used as the log level,
 		// since the computation short circuits.
 		// So, in increasing order of importance:
 		// Default < Tags < File < Class < Function
-		checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel)
-		|| checkLevelMap(s.mClassLevelMap, class_name, compareLevel)
-		|| checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+		checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel)
+		|| checkLevelMap(s->mClassLevelMap, class_name, compareLevel)
+		|| checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
 		|| (site.mTagCount > 0
-			? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel) 
+			? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel) 
 			: false);
 
 		site.mCached = true;
@@ -1135,7 +1147,7 @@ namespace LLError
 		}
 		
 		Globals* g = Globals::getInstance();
-		Settings& s = Settings::get();
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
 		std::string message = out->str();
 		if (out == &g->messageStream)
@@ -1158,8 +1170,8 @@ namespace LLError
 
 		if (site.mPrintOnce)
 		{
-			std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message);
-			if (messageIter != s.mUniqueLogMessages.end())
+			std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
+			if (messageIter != s->mUniqueLogMessages.end())
 			{
 				messageIter->second++;
 				unsigned int num_messages = messageIter->second;
@@ -1175,7 +1187,7 @@ namespace LLError
 			else 
 			{
 				message_stream << "ONCE: ";
-				s.mUniqueLogMessages[message] = 1;
+				s->mUniqueLogMessages[message] = 1;
 			}
 		}
 		
@@ -1183,23 +1195,23 @@ namespace LLError
 		
 		writeToRecorders(site, message_stream.str());
 		
-		if (site.mLevel == LEVEL_ERROR  &&  s.mCrashFunction)
+		if (site.mLevel == LEVEL_ERROR  &&  s->mCrashFunction)
 		{
-			s.mCrashFunction(message_stream.str());
+			s->mCrashFunction(message_stream.str());
 		}
 	}
 }
 
 namespace LLError
 {
-	Settings* saveAndResetSettings()
+	SettingsStoragePtr saveAndResetSettings()
 	{
-		return Settings::saveAndReset();
+		return Settings::getInstance()->saveAndReset();
 	}
 	
-	void restoreSettings(Settings* s)
+	void restoreSettings(SettingsStoragePtr pSettingsStorage)
 	{
-		return Settings::restore(s);
+		return Settings::getInstance()->restore(pSettingsStorage);
 	}
 
 	std::string removePrefix(std::string& s, const std::string& p)
@@ -1245,8 +1257,8 @@ namespace LLError
 
 	int shouldLogCallCount()
 	{
-		Settings& s = Settings::get();
-		return s.mShouldLogCallCounter;
+		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+		return s->mShouldLogCallCounter;
 	}
 
 #if LL_WINDOWS
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 681f444234..56ac52e5de 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -29,6 +29,8 @@
 #define LL_LLERRORCONTROL_H
 
 #include "llerror.h"
+#include "llpointer.h"
+#include "llrefcount.h"
 #include "boost/function.hpp"
 #include "boost/shared_ptr.hpp"
 #include <string>
@@ -181,9 +183,9 @@ namespace LLError
 		Utilities for use by the unit tests of LLError itself.
 	*/
 
-	class Settings;
-	LL_COMMON_API Settings* saveAndResetSettings();
-	LL_COMMON_API void restoreSettings(Settings *);
+	typedef LLPointer<LLRefCount> SettingsStoragePtr;
+	LL_COMMON_API SettingsStoragePtr saveAndResetSettings();
+	LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage);
 
 	LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
 	LL_COMMON_API int shouldLogCallCount();
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 6cecd6bbc8..a5aaff10c5 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -86,7 +86,7 @@ namespace tut
 	struct ErrorTestData
 	{
 		LLError::RecorderPtr mRecorder;
-		LLError::Settings* mPriorErrorSettings;
+		LLError::SettingsStoragePtr mPriorErrorSettings;
 
 		ErrorTestData():
 			mRecorder(new TestRecorder())
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 0a52844671..785197ba11 100755
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -82,7 +82,7 @@ struct WrapLLErrs
     }
 
     std::string error;
-    LLError::Settings* mPriorErrorSettings;
+    LLError::SettingsStoragePtr mPriorErrorSettings;
     LLError::FatalFunction mPriorFatal;
 };
 
@@ -196,7 +196,7 @@ public:
     }
 
 private:
-    LLError::Settings* mOldSettings;
+    LLError::SettingsStoragePtr mOldSettings;
 	LLError::RecorderPtr mRecorder;
 };
 
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 0dd21b6a05..e42374d56b 100755
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -169,7 +169,7 @@ public:
 	}
 
 private:
-	LLError::Settings* mOldSettings;
+	LLError::SettingsStoragePtr mOldSettings;
 	LLError::RecorderPtr mRecorder;
 };
 
-- 
cgit v1.2.3


From d0d32626a5bf25f76b4a3296f681eb13e071d55e Mon Sep 17 00:00:00 2001
From: Nyx Linden <nyx@lindenlab.com>
Date: Mon, 19 May 2014 14:44:01 -0400
Subject: merge fix for merge with project interesting. New appearance utility
 source and one quick doubly-declared typedef.

---
 autobuild.xml                    | 8 ++++----
 indra/newview/llinventorymodel.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index 065c8351d0..dd4c63f474 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -764,7 +764,7 @@
               <key>hash</key>
               <string>aff5566e04003de0383941981198e04e</string>
               <key>url</key>
-          <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130329.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273073/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -776,7 +776,7 @@
               <key>hash</key>
               <string>52257e5eb166a0b69c9c0c38f6e1920e</string>
               <key>url</key>
-	         <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1290,9 +1290,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b6d29de20de5c8f31925697b30e8f727</string>
+              <string>54e46715e72b7805d9d3f84d45b6b1b7</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/283723/arch/Linux/installer/llappearanceutility_source-0.1-linux-20131109.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/290120/arch/Linux/installer/llappearanceutility_source-0.1-linux-20140519.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index b72c8fed50..2e957809be 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -485,7 +485,7 @@ public:
 	// been changed 'under the hood', but outside the control of the
 	// inventory. The next notify will include that notification.
 	void addChangedMask(U32 mask, const LLUUID& referent);
-	typedef uuid_set_t changed_items_t;
+	
 	const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
 	const changed_items_t& getAddedIDs() const { return mAddedItemIDs; }
 protected:
-- 
cgit v1.2.3


From 5537417ac35ed36322acdba843bd72bf7a7d1992 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Tue, 20 May 2014 01:03:50 +0100
Subject: MAINT-4009: Ensuring that the cookie store is properly cleaned on app
 exit.

---
 indra/llplugin/llplugincookiestore.cpp | 9 +++------
 indra/newview/llviewermedia.cpp        | 6 ++++++
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/indra/llplugin/llplugincookiestore.cpp b/indra/llplugin/llplugincookiestore.cpp
index f64b264222..a5d717389d 100755
--- a/indra/llplugin/llplugincookiestore.cpp
+++ b/indra/llplugin/llplugincookiestore.cpp
@@ -27,6 +27,7 @@
  */
 
 #include "linden_common.h"
+#include "llstl.h"
 #include "indra_constants.h"
 
 #include "llplugincookiestore.h"
@@ -654,12 +655,8 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
 
 void LLPluginCookieStore::clearCookies()
 {
-	while(!mCookies.empty())
-	{
-		cookie_map_t::iterator iter = mCookies.begin();
-		delete iter->second;
-		mCookies.erase(iter);
-	}
+	std::for_each(mCookies.begin(), mCookies.end(), DeletePairedPointer());
+	mCookies.clear();
 }
 
 void LLPluginCookieStore::removeCookie(const std::string &key)
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index afa2bb6728..a2a3caee00 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1604,6 +1604,12 @@ void LLViewerMedia::cleanupClass()
 		delete sSpareBrowserMediaSource;
 		sSpareBrowserMediaSource = NULL;
 	}
+
+	if (sCookieStore != NULL)
+	{
+		delete sCookieStore;
+		sCookieStore = NULL;
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From a13d2f7f706bc8d5a4ea103cde56bacea1dd82cc Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Tue, 20 May 2014 21:03:13 +0100
Subject: MAINT-4009: Patching a leak of LLPluginSharedMemory objects from the
 LLPluginProcessParent class.

---
 indra/llplugin/llpluginprocessparent.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index ea0d2b81f1..b5a2588e1e 100755
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -131,6 +131,8 @@ LLPluginProcessParent::~LLPluginProcessParent()
 	{
 		// destroy the shared memory region
 		iter->second->destroy();
+		delete iter->second;
+		iter->second = NULL;
 		
 		// and remove it from our map
 		mSharedMemoryRegions.erase(iter);
@@ -960,6 +962,8 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 			{
 				// destroy the shared memory region
 				iter->second->destroy();
+				delete iter->second;
+				iter->second = NULL;
 				
 				// and remove it from our map
 				mSharedMemoryRegions.erase(iter);
-- 
cgit v1.2.3


From 0160c514c5e0bc3e575b33ef27924a9c8c7c30cf Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 23 May 2014 21:56:44 +0100
Subject: MAINT-4077: Refactoring to add copy constructors to the LLVisualParam
 class and all of its derived descendants in order to clarify ownership of
 memory pointers.

---
 indra/llappearance/lldriverparam.cpp            | 30 ++++++++-----
 indra/llappearance/lldriverparam.h              |  1 +
 indra/llappearance/llpolymorph.cpp              | 59 ++++++++++++++++++-------
 indra/llappearance/llpolymorph.h                |  3 ++
 indra/llappearance/llpolyskeletaldistortion.cpp | 24 +++++++---
 indra/llappearance/llpolyskeletaldistortion.h   |  2 +
 indra/llappearance/lltexglobalcolor.cpp         | 24 +++++++---
 indra/llappearance/lltexglobalcolor.h           |  2 +
 indra/llappearance/lltexlayerparams.cpp         | 58 +++++++++++++++++-------
 indra/llappearance/lltexlayerparams.h           |  6 +++
 indra/llappearance/llviewervisualparam.cpp      | 16 +++++++
 indra/llappearance/llviewervisualparam.h        |  4 +-
 indra/llcharacter/llvisualparam.cpp             | 29 ++++++++----
 indra/llcharacter/llvisualparam.h               |  2 +
 14 files changed, 198 insertions(+), 62 deletions(-)

diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
index c66a428374..d2203ecc81 100644
--- a/indra/llappearance/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -152,19 +152,31 @@ void LLDriverParamInfo::toStream(std::ostream &out)
 // LLDriverParam
 //-----------------------------------------------------------------------------
 
-LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) :
+LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */)
+	: LLViewerVisualParam(),
+	mDefaultVec(),
+	mDriven(),
 	mCurrentDistortionParam( NULL ), 
 	mAvatarAppearance(appearance), 
 	mWearablep(wearable)
 {
 	llassert(mAvatarAppearance);
-	if (mWearablep)
-	{
-		llassert(mAvatarAppearance->isSelf());
-	}
+	llassert((mWearablep == NULL) || mAvatarAppearance->isSelf());
 	mDefaultVec.clear();
 }
 
+LLDriverParam::LLDriverParam(const LLDriverParam& pOther)
+	: LLViewerVisualParam(pOther),
+	mDefaultVec(pOther.mDefaultVec),
+	mDriven(pOther.mDriven),
+	mCurrentDistortionParam(pOther.mCurrentDistortionParam),
+	mAvatarAppearance(pOther.mAvatarAppearance),
+	mWearablep(pOther.mWearablep)
+{
+	llassert(mAvatarAppearance);
+	llassert((mWearablep == NULL) || mAvatarAppearance->isSelf());
+}
+
 LLDriverParam::~LLDriverParam()
 {
 }
@@ -186,13 +198,7 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
 /*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const
 {
 	llassert(wearable);
-	LLDriverParam *new_param = new LLDriverParam(mAvatarAppearance, wearable);
-	// FIXME DRANO this clobbers mWearablep, which means any code
-	// currently using mWearablep is wrong, or at least untested.
-	*new_param = *this;
-	//new_param->mWearablep = wearable;
-//	new_param->mDriven.clear(); // clear driven list to avoid overwriting avatar driven params from wearables. 
-	return new_param;
+	return new LLDriverParam(*this);
 }
 
 void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h
index 2420db76e7..cd151bcf30 100644
--- a/indra/llappearance/lldriverparam.h
+++ b/indra/llappearance/lldriverparam.h
@@ -129,6 +129,7 @@ public:
 	const LLViewerVisualParam*		getDrivenParam(S32 index) const;
 
 protected:
+	LLDriverParam(const LLDriverParam& pOther);
 	F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
 	void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
 
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index ce8a0b0b76..d69b59ab1b 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -315,10 +315,27 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node)
 // LLPolyMorphTarget()
 //-----------------------------------------------------------------------------
 LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
-	: mMorphData(NULL), mMesh(poly_mesh),
-	  mVertMask(NULL),
-	  mLastSex(SEX_FEMALE),
-	  mNumMorphMasksPending(0)
+	: LLViewerVisualParam(),
+	mMorphData(NULL),
+	mMesh(poly_mesh),
+	mVertMask(NULL),
+	mLastSex(SEX_FEMALE),
+	mNumMorphMasksPending(0),
+	mVolumeMorphs()
+{
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTarget()
+//-----------------------------------------------------------------------------
+LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther)
+	: LLViewerVisualParam(pOther),
+	mMorphData(pOther.mMorphData),
+	mMesh(pOther.mMesh),
+	mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)),
+	mLastSex(pOther.mLastSex),
+	mNumMorphMasksPending(pOther.mNumMorphMasksPending),
+	mVolumeMorphs(pOther.mVolumeMorphs)
 {
 }
 
@@ -327,10 +344,8 @@ LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
 //-----------------------------------------------------------------------------
 LLPolyMorphTarget::~LLPolyMorphTarget()
 {
-	if (mVertMask)
-	{
-		delete mVertMask;
-	}
+	delete mVertMask;
+	mVertMask = NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -385,9 +400,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
 
 /*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
 {
-	LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
-	*new_param = *this;
-	return new_param;
+	return new LLPolyMorphTarget(*this);
 }
 
 #if 0 // obsolete
@@ -722,10 +735,25 @@ void	LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3
 // LLPolyVertexMask()
 //-----------------------------------------------------------------------------
 LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
+	: mWeights(new F32[morph_data->mNumIndices]),
+	mMorphData(morph_data),
+	mWeightsGenerated(FALSE)
+{
+	llassert(mMorphData != NULL);
+	llassert(mMorphData->mNumIndices > 0);
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyVertexMask()
+//-----------------------------------------------------------------------------
+LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther)
+	: mWeights(new F32[pOther.mMorphData->mNumIndices]),
+	mMorphData(pOther.mMorphData),
+	mWeightsGenerated(pOther.mWeightsGenerated)
 {
-	mWeights = new F32[morph_data->mNumIndices];
-	mMorphData = morph_data;
-	mWeightsGenerated = FALSE;
+	llassert(mMorphData != NULL);
+	llassert(mMorphData->mNumIndices > 0);
+	memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices);
 }
 
 //-----------------------------------------------------------------------------
@@ -733,7 +761,8 @@ LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
 //-----------------------------------------------------------------------------
 LLPolyVertexMask::~LLPolyVertexMask()
 {
-	delete[] mWeights;
+	delete [] mWeights;
+	mWeights = NULL;
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h
index ee380ae7c3..7e712f9e94 100644
--- a/indra/llappearance/llpolymorph.h
+++ b/indra/llappearance/llpolymorph.h
@@ -91,6 +91,7 @@ class LLPolyVertexMask
 {
 public:
 	LLPolyVertexMask(LLPolyMorphData* morph_data);
+	LLPolyVertexMask(const LLPolyVertexMask& pOther);
 	~LLPolyVertexMask();
 
 	void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
@@ -182,6 +183,8 @@ public:
 	void	addPendingMorphMask() { mNumMorphMasksPending++; }
 
 protected:
+	LLPolyMorphTarget(const LLPolyMorphTarget& pOther);
+
 	LLPolyMorphData*				mMorphData;
 	LLPolyMesh*						mMesh;
 	LLPolyVertexMask *				mVertMask;
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index a72b446ace..b9c1ee340c 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -104,9 +104,25 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
 // LLPolySkeletalDistortion()
 //-----------------------------------------------------------------------------
 LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp)
+	: LLViewerVisualParam(),
+	mDefaultVec(),
+	mJointScales(),
+	mJointOffsets(),
+	mAvatar(avatarp)
+{
+	mDefaultVec.splat(0.001f);
+}
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::LLPolySkeletalDistortion(const LLPolySkeletalDistortion &pOther)
+	: LLViewerVisualParam(pOther),
+	mDefaultVec(pOther.mDefaultVec),
+	mJointScales(pOther.mJointScales),
+	mJointOffsets(pOther.mJointOffsets),
+	mAvatar(pOther.mAvatar)
 {
-        mAvatar = avatarp;
-        mDefaultVec.splat(0.001f);
 }
 
 //-----------------------------------------------------------------------------
@@ -171,9 +187,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
 
 /*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
 {
-        LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
-        *new_param = *this;
-        return new_param;
+	return new LLPolySkeletalDistortion(*this);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h
index 24c9e9ae48..ea2adb8a87 100644
--- a/indra/llappearance/llpolyskeletaldistortion.h
+++ b/indra/llappearance/llpolyskeletaldistortion.h
@@ -118,6 +118,8 @@ public:
 	/*virtual*/ const LLVector4a*	getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
 
 protected:
+	LLPolySkeletalDistortion(const LLPolySkeletalDistortion& pOther);
+
 	LL_ALIGN_16(LLVector4a mDefaultVec);
 	typedef std::map<LLJoint*, LLVector3> joint_vec_map_t;
 	joint_vec_map_t mJointScales;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
index 186c537659..a8283ea2e6 100644
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -90,17 +90,31 @@ const std::string& LLTexGlobalColor::getName() const
 //-----------------------------------------------------------------------------
 // LLTexParamGlobalColor
 //-----------------------------------------------------------------------------
-LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
-	LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
+LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
+	: LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
 	mTexGlobalColor(tex_global_color)
 {
 }
 
+//-----------------------------------------------------------------------------
+// LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther)
+	: LLTexLayerParamColor(pOther),
+	mTexGlobalColor(pOther.mTexGlobalColor)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::~LLTexParamGlobalColor()
+{
+}
+
 /*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const
 {
-	LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor);
-	*new_param = *this;
-	return new_param;
+	return new LLTexParamGlobalColor(*this);
 }
 
 void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
index 2867479876..4b7d23d20f 100644
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -73,8 +73,10 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
 {
 public:
 	LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
+	virtual ~LLTexParamGlobalColor();
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
 protected:
+	LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther);
 	/*virtual*/ void onGlobalColorChanged(bool upload_bake);
 private:
 	LLTexGlobalColor*		mTexGlobalColor;
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index f1f7d07fa9..e04851aa71 100644
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -40,7 +40,8 @@
 //-----------------------------------------------------------------------------
 // LLTexLayerParam
 //-----------------------------------------------------------------------------
-LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
+LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer)
+	: LLViewerVisualParam(),
 	mTexLayer(layer),
 	mAvatarAppearance(NULL)
 {
@@ -54,12 +55,19 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
 	}
 }
 
-LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) :
+LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance)
+	: LLViewerVisualParam(),
 	mTexLayer(NULL),
 	mAvatarAppearance(appearance)
 {
 }
 
+LLTexLayerParam::LLTexLayerParam(const LLTexLayerParam& pOther)
+	: LLViewerVisualParam(pOther),
+	mTexLayer(pOther.mTexLayer),
+	mAvatarAppearance(pOther.mAvatarAppearance)
+{
+}
 
 BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance)
 {
@@ -112,9 +120,11 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
 	}
 }
 
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
-	LLTexLayerParam(layer),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer)
+	: LLTexLayerParam(layer),
 	mCachedProcessedTexture(NULL),
+	mStaticImageTGA(),
+	mStaticImageRaw(),
 	mNeedsCreateTexture(FALSE),
 	mStaticImageInvalid(FALSE),
 	mAvgDistortionVec(1.f, 1.f, 1.f),
@@ -123,9 +133,11 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
 	sInstances.push_front(this);
 }
 
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
-	LLTexLayerParam(appearance),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance)
+	: LLTexLayerParam(appearance),
 	mCachedProcessedTexture(NULL),
+	mStaticImageTGA(),
+	mStaticImageRaw(),
 	mNeedsCreateTexture(FALSE),
 	mStaticImageInvalid(FALSE),
 	mAvgDistortionVec(1.f, 1.f, 1.f),
@@ -134,6 +146,18 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
 	sInstances.push_front(this);
 }
 
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther)
+	: LLTexLayerParam(pOther),
+	mCachedProcessedTexture(pOther.mCachedProcessedTexture),
+	mStaticImageTGA(pOther.mStaticImageTGA),
+	mStaticImageRaw(pOther.mStaticImageRaw),
+	mNeedsCreateTexture(pOther.mNeedsCreateTexture),
+	mStaticImageInvalid(pOther.mStaticImageInvalid),
+	mAvgDistortionVec(pOther.mAvgDistortionVec),
+	mCachedEffectiveWeight(pOther.mCachedEffectiveWeight)
+{
+	sInstances.push_front(this);
+}
 
 LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
 {
@@ -143,9 +167,7 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
 
 /*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const
 {
-	LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer);
-	*new_param = *this;
-	return new_param;
+	return new LLTexLayerParamAlpha(*this);
 }
 
 void LLTexLayerParamAlpha::deleteCaches()
@@ -399,27 +421,31 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
 
 
 
-LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
-	LLTexLayerParam(layer),
+LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer)
+	: LLTexLayerParam(layer),
 	mAvgDistortionVec(1.f, 1.f, 1.f)
 {
 }
 
-LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) :
-	LLTexLayerParam(appearance),
+LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance)
+	: LLTexLayerParam(appearance),
 	mAvgDistortionVec(1.f, 1.f, 1.f)
 {
 }
 
+LLTexLayerParamColor::LLTexLayerParamColor(const LLTexLayerParamColor& pOther)
+	: LLTexLayerParam(pOther),
+	mAvgDistortionVec(pOther.mAvgDistortionVec)
+{
+}
+
 LLTexLayerParamColor::~LLTexLayerParamColor()
 {
 }
 
 /*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const
 {
-	LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer);
-	*new_param = *this;
-	return new_param;
+	return new LLTexLayerParamColor(*this);
 }
 
 LLColor4 LLTexLayerParamColor::getNetColor() const
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index b38d28d3eb..68c67784e3 100644
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -52,6 +52,8 @@ public:
 	/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
 
 protected:
+	LLTexLayerParam(const LLTexLayerParam& pOther);
+
 	LLTexLayerInterface*	mTexLayer;
 	LLAvatarAppearance*		mAvatarAppearance;
 };
@@ -102,6 +104,8 @@ public:
 	BOOL					getMultiplyBlend() const;
 
 private:
+	LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther);
+
 	LLPointer<LLGLTexture>	mCachedProcessedTexture;
 	LLPointer<LLImageTGA>	mStaticImageTGA;
 	LLPointer<LLImageRaw>	mStaticImageRaw;
@@ -190,6 +194,8 @@ public:
 	// New functions
 	LLColor4				getNetColor() const;
 protected:
+	LLTexLayerParamColor(const LLTexLayerParamColor& pOther);
+
 	virtual void onGlobalColorChanged(bool upload_bake) {}
 private:
 	LL_ALIGN_16(LLVector4a				mAvgDistortionVec);
diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp
index cc81bcf118..f58f7c24bc 100644
--- a/indra/llappearance/llviewervisualparam.cpp
+++ b/indra/llappearance/llviewervisualparam.cpp
@@ -123,6 +123,22 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
 // LLViewerVisualParam()
 //-----------------------------------------------------------------------------
 LLViewerVisualParam::LLViewerVisualParam()
+	: LLVisualParam()
+{
+}
+
+//-----------------------------------------------------------------------------
+// LLViewerVisualParam()
+//-----------------------------------------------------------------------------
+LLViewerVisualParam::LLViewerVisualParam(const LLViewerVisualParam& pOther)
+	: LLVisualParam(pOther)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLViewerVisualParam()
+//-----------------------------------------------------------------------------
+LLViewerVisualParam::~LLViewerVisualParam()
 {
 }
 
diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h
index 2826e6c316..1a710c0ca6 100644
--- a/indra/llappearance/llviewervisualparam.h
+++ b/indra/llappearance/llviewervisualparam.h
@@ -70,7 +70,7 @@ class LLViewerVisualParam : public LLVisualParam
 {
 public:
 	LLViewerVisualParam();
-	/*virtual*/ ~LLViewerVisualParam(){};
+	virtual ~LLViewerVisualParam();
 
 	// Special: These functions are overridden by child classes
 	LLViewerVisualParamInfo 	*getInfo() const { return (LLViewerVisualParamInfo*)mInfo; };
@@ -105,6 +105,8 @@ public:
 
 	BOOL				getCrossWearable() const 	{ return getInfo()->mCrossWearable; }
 
+protected:
+	LLViewerVisualParam(const LLViewerVisualParam& pOther);
 } LL_ALIGN_POSTFIX(16);
 
 #endif // LL_LLViewerVisualParam_H
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index dd87847c18..4f7898ef49 100755
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -159,29 +159,42 @@ void LLVisualParamInfo::toStream(std::ostream &out)
 //-----------------------------------------------------------------------------
 // LLVisualParam()
 //-----------------------------------------------------------------------------
-LLVisualParam::LLVisualParam()	
-	:
-	mCurWeight( 0.f ),
+LLVisualParam::LLVisualParam()
+	: mCurWeight( 0.f ),
 	mLastWeight( 0.f ),
 	mNext( NULL ),
 	mTargetWeight( 0.f ),
 	mIsAnimating( FALSE ),
+	mIsDummy(FALSE),
 	mID( -1 ),
 	mInfo( 0 ),
-	mIsDummy(FALSE),
 	mParamLocation(LOC_UNKNOWN)
 {
 }
 
+//-----------------------------------------------------------------------------
+// LLVisualParam()
+//-----------------------------------------------------------------------------
+LLVisualParam::LLVisualParam(const LLVisualParam& pOther)
+	: mCurWeight(pOther.mCurWeight),
+	mLastWeight(pOther.mLastWeight),
+	mNext(pOther.mNext),
+	mTargetWeight(pOther.mTargetWeight),
+	mIsAnimating(pOther.mIsAnimating),
+	mIsDummy(pOther.mIsDummy),
+	mID(pOther.mID),
+	mInfo(pOther.mInfo),
+	mParamLocation(pOther.mParamLocation)
+{
+}
+
 //-----------------------------------------------------------------------------
 // ~LLVisualParam()
 //-----------------------------------------------------------------------------
 LLVisualParam::~LLVisualParam()
 {
-	if (mNext != NULL)
-	{
-		delete mNext;
-	}
+	delete mNext;
+	mNext = NULL;
 }
 
 /*
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index 78c776705f..e49b1225c3 100755
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -166,6 +166,8 @@ public:
 	EParamLocation			getParamLocation() const { return mParamLocation; }
 
 protected:
+	LLVisualParam(const LLVisualParam& pOther);
+
 	F32					mCurWeight;			// current weight
 	F32					mLastWeight;		// last weight
 	LLVisualParam*		mNext;				// next param in a shared chain
-- 
cgit v1.2.3


From fdc787cc06cd09a70e13cfb9da6f0aecd5d5d50f Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Sat, 24 May 2014 00:05:02 +0100
Subject: MAINT-4009: Patching a memory leak of ParamDescriptor objects.

---
 indra/llcommon/llinitparam.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 2532566319..7aa87fcd0e 100755
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -31,6 +31,7 @@
 #include <vector>
 #include <list>
 #include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/is_enum.hpp>
 #include <boost/unordered_map.hpp>
@@ -629,7 +630,7 @@ namespace LLInitParam
 		UserData*			mUserData;
 	};
 
-	typedef ParamDescriptor* ParamDescriptorPtr;
+	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
 
 	// each derived Block class keeps a static data structure maintaining offsets to various params
 	class LL_COMMON_API BlockDescriptor
-- 
cgit v1.2.3


From c84217cc5bf49354b39ea3521e4805c791a15c8c Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Tue, 27 May 2014 22:45:02 +0100
Subject: MAINT-4009: Ensuring that the view listeners are properly cleaned up
 at app close.

---
 indra/llui/llmenugl.cpp          |  1 +
 indra/llui/llmenugl.h            | 17 ++++++++++++++++-
 indra/newview/llviewerwindow.cpp |  3 +++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 7383a8c307..604dc92789 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -63,6 +63,7 @@
 
 // static
 LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL;
+view_listener_t::listener_map_t view_listener_t::sListeners;
 
 S32 MENU_BAR_HEIGHT = 0;
 S32 MENU_BAR_WIDTH = 0;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index feafaab199..ae9b169691 100755
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -895,7 +895,8 @@ class view_listener_t : public boost::signals2::trackable
 {
 public:
 	virtual bool handleEvent(const LLSD& userdata) = 0;
-	virtual ~view_listener_t() {}
+	view_listener_t() { sListeners.insert(this); }
+	virtual ~view_listener_t() { sListeners.erase(this); }
 	
 	static void addEnable(view_listener_t* listener, const std::string& name)
 	{
@@ -913,6 +914,20 @@ public:
 		addEnable(listener, name);
 		addCommit(listener, name);
 	}
+
+	static void cleanup()
+	{
+		listener_vector_t listeners(sListeners.begin(), sListeners.end());
+		sListeners.clear();
+
+		std::for_each(listeners.begin(), listeners.end(), DeletePointer());
+		listeners.clear();
+	}
+
+private:
+	typedef std::set<view_listener_t*> listener_map_t;
+	typedef std::vector<view_listener_t*> listener_vector_t;
+	static listener_map_t sListeners;
 };
 
 #endif // LL_LLMENUGL_H
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index fc5fb39f4e..7d2771802e 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2088,6 +2088,9 @@ void LLViewerWindow::shutdownViews()
 	// access to gMenuHolder
 	cleanup_menus();
 	LL_INFOS() << "menus destroyed." << LL_ENDL ;
+
+	view_listener_t::cleanup();
+	LL_INFOS() << "view listeners destroyed." << LL_ENDL ;
 	
 	// Delete all child views.
 	delete mRootView;
-- 
cgit v1.2.3


From 72dba8742c3120fcb76b42aa6ede796bdad8554d Mon Sep 17 00:00:00 2001
From: "maxim@mnikolenko" <maxim@mnikolenko>
Date: Wed, 28 May 2014 13:20:12 +0300
Subject: MAINT-4070 FIXED Use icon in urls when content is trusted.

---
 indra/llui/lltextbase.cpp                  |  4 ++--
 indra/llui/lltextbase.h                    |  2 ++
 indra/llui/lltextutil.cpp                  |  4 ++--
 indra/llui/lltextutil.h                    |  2 +-
 indra/llui/llurlregistry.cpp               | 11 +++++++++--
 indra/llui/llurlregistry.h                 |  4 +++-
 indra/newview/llchatitemscontainerctrl.cpp | 27 ++++++++++++---------------
 indra/newview/llchatitemscontainerctrl.h   |  2 ++
 indra/newview/lltoastimpanel.cpp           |  1 +
 indra/newview/lltoastnotifypanel.cpp       |  7 ++++++-
 10 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 30e6c6248e..8906a6e736 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -2038,7 +2038,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 		LLUrlMatch match;
 		std::string text = new_text;
 		while ( LLUrlRegistry::instance().findUrl(text, match,
-				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
+				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted()))
 		{
 			start = match.getStart();
 			end = match.getEnd()+1;
@@ -2075,7 +2075,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
 					}
 			}
 
-			LLTextUtil::processUrlMatch(&match,this);
+			LLTextUtil::processUrlMatch(&match,this,isContentTrusted());
 
 			// move on to the rest of the text after the Url
 			if (end < (S32)text.length()) 
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index d1f66b6cfe..ecbfdaf84c 100755
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -367,7 +367,9 @@ public:
 	bool					getWordWrap() { return mWordWrap; }
 	bool					getUseEllipses() { return mUseEllipses; }
 	bool					truncate(); // returns true of truncation occurred
+
 	bool					isContentTrusted() {return mTrustedContent;}
+	void					setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; }
 
 	// TODO: move into LLTextSegment?
 	void					createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url
diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp
index 4df2c3363f..fff04b34f2 100755
--- a/indra/llui/lltextutil.cpp
+++ b/indra/llui/lltextutil.cpp
@@ -72,7 +72,7 @@ const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str)
 	return formatted_phone_str;
 }
 
-bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base)
+bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted)
 {
 	if (match == 0 || text_base == 0)
 		return false;
@@ -85,7 +85,7 @@ bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base)
 	}
 
 	// output an optional icon before the Url
-	if (!match->getIcon().empty() )
+	if (is_content_trusted && !match->getIcon().empty() )
 	{
 		LLUIImagePtr image = LLUI::getUIImage(match->getIcon());
 		if (image)
diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h
index bf7dbb58ce..798f14d086 100755
--- a/indra/llui/lltextutil.h
+++ b/indra/llui/lltextutil.h
@@ -64,7 +64,7 @@ namespace LLTextUtil
 	 */
 	const std::string& formatPhoneNumber(const std::string& phone_str);
 
-	bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base);
+	bool processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted);
 
 	class TextHelpers
 	{
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 523ee5d78c..bccc646821 100755
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -41,7 +41,8 @@ LLUrlRegistry::LLUrlRegistry()
 
 	// Urls are matched in the order that they were registered
 	registerUrl(new LLUrlEntryNoLink());
-	registerUrl(new LLUrlEntryIcon());
+	mUrlEntryIcon = new LLUrlEntryIcon();
+	registerUrl(mUrlEntryIcon);
 	registerUrl(new LLUrlEntrySLURL());
 	registerUrl(new LLUrlEntryHTTP());
 	registerUrl(new LLUrlEntryHTTPLabel());
@@ -145,7 +146,7 @@ static bool stringHasUrl(const std::string &text)
 			text.find("<icon") != std::string::npos);
 }
 
-bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted)
 {
 	// avoid costly regexes if there is clearly no URL in the text
 	if (! stringHasUrl(text))
@@ -160,6 +161,12 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
 	std::vector<LLUrlEntryBase *>::iterator it;
 	for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
 	{
+		//Skip for url entry icon if content is not trusted
+		if(!is_content_trusted && (mUrlEntryIcon == *it))
+		{
+			continue;
+		}
+
 		LLUrlEntryBase *url_entry = *it;
 
 		U32 start = 0, end = 0;
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index da16171a97..6270df1bbb 100755
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -73,7 +73,8 @@ public:
 	/// get the next Url in an input string, starting at a given character offset
 	/// your callback is invoked if the matched Url's label changes in the future
 	bool findUrl(const std::string &text, LLUrlMatch &match,
-				 const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+				 const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback,
+				 bool is_content_trusted = false);
 
 	/// a slightly less efficient version of findUrl for wide strings
 	bool findUrl(const LLWString &text, LLUrlMatch &match,
@@ -92,6 +93,7 @@ private:
 	friend class LLSingleton<LLUrlRegistry>;
 
 	std::vector<LLUrlEntryBase *> mUrlEntry;
+	LLUrlEntryBase*	mUrlEntryIcon;
 };
 
 #endif
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index fd4f17b694..cfc62c07b6 100755
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -29,7 +29,6 @@
 #include "llchatitemscontainerctrl.h"
 #include "lltextbox.h"
 
-#include "llchatmsgbox.h"
 #include "llavatariconctrl.h"
 #include "llcommandhandler.h"
 #include "llfloaterreg.h"
@@ -130,7 +129,6 @@ void LLFloaterIMNearbyChatToastPanel::addMessage(LLSD& notification)
 {
 	std::string		messageText = notification["message"].asString();		// UTF-8 line of text
 
-	LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
 
 	std::string color_name = notification["text_color"].asString();
 	
@@ -171,7 +169,7 @@ void LLFloaterIMNearbyChatToastPanel::addMessage(LLSD& notification)
 		{
 			style_params.font.style = "ITALIC";
 		}
-		msg_text->appendText(messageText, TRUE, style_params);
+		mMsgText->appendText(messageText, TRUE, style_params);
 	}
 
 	snapToMessageHeight();
@@ -204,9 +202,10 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 		case 2:	messageFont = LLFontGL::getFontSansSerifBig();	break;
 	}
 	
-	LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
+	mMsgText = getChild<LLChatMsgBox>("msg_text", false);
+	mMsgText->setContentTrusted(false);
 
-	msg_text->setText(std::string(""));
+	mMsgText->setText(std::string(""));
 
 	if ( notification["chat_style"].asInteger() != CHAT_STYLE_IRC )
 	{
@@ -232,12 +231,12 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 			style_params_name.link_href = notification["sender_slurl"].asString();
 			style_params_name.is_link = true;
 
-			msg_text->appendText(str_sender, FALSE, style_params_name);
+			mMsgText->appendText(str_sender, FALSE, style_params_name);
 
 		}
 		else
 		{
-			msg_text->appendText(str_sender, false);
+			mMsgText->appendText(str_sender, false);
 		}
 	}
 
@@ -264,7 +263,7 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 		{
 			style_params.font.style = "ITALIC";
 		}
-		msg_text->appendText(messageText, FALSE, style_params);
+		mMsgText->appendText(messageText, FALSE, style_params);
 	}
 
 
@@ -275,8 +274,7 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
 
 void	LLFloaterIMNearbyChatToastPanel::snapToMessageHeight	()
 {
-	LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
-	S32 new_height = llmax (text_box->getTextPixelHeight() + 2*text_box->getVPad() + 2*msg_height_pad, 25);
+	S32 new_height = llmax (mMsgText->getTextPixelHeight() + 2*mMsgText->getVPad() + 2*msg_height_pad, 25);
 	
 	LLRect panel_rect = getRect();
 
@@ -312,14 +310,13 @@ BOOL	LLFloaterIMNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)
 		return LLPanel::handleMouseUp(x,y,mask);
     */
 
-	LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
-	S32 local_x = x - text_box->getRect().mLeft;
-	S32 local_y = y - text_box->getRect().mBottom;
+	S32 local_x = x - mMsgText->getRect().mLeft;
+	S32 local_y = y - mMsgText->getRect().mBottom;
 	
 	//if text_box process mouse up (ussually this is click on url) - we didn't show nearby_chat.
-	if (text_box->pointInView(local_x, local_y) )
+	if (mMsgText->pointInView(local_x, local_y) )
 	{
-		if (text_box->handleMouseUp(local_x,local_y,mask) == TRUE)
+		if (mMsgText->handleMouseUp(local_x,local_y,mask) == TRUE)
 			return TRUE;
 		else
 		{
diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h
index 54b6499d52..f66670ec8c 100755
--- a/indra/newview/llchatitemscontainerctrl.h
+++ b/indra/newview/llchatitemscontainerctrl.h
@@ -28,6 +28,7 @@
 #define LL_LLCHATITEMSCONTAINERCTRL_H_
 
 #include "llchat.h"
+#include "llchatmsgbox.h"
 #include "llpanel.h"
 #include "llscrollbar.h"
 #include "llviewerchat.h"
@@ -85,6 +86,7 @@ private:
 	LLUUID			mFromID;	// agent id or object id
 	std::string		mFromName;
 	EChatSourceType	mSourceType;
+	LLChatMsgBox* 	mMsgText;
 	
 
 
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index a27105e22d..39adfb3431 100755
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -54,6 +54,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif
 	mAvatarName = getChild<LLTextBox>("user_name");
 	mTime = getChild<LLTextBox>("time_box");
 	mMessage = getChild<LLTextBox>("message");
+	mMessage->setContentTrusted(false);
 
 	LLStyle::Params style_params;
 	LLFontGL* fontp = LLViewerChat::getChatFont();
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 51935dc03b..907baf0661 100755
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -270,8 +270,12 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
     // customize panel's attributes
     // is it intended for displaying a tip?
     mIsTip = mNotification->getType() == "notifytip";
+
+    std::string notif_name = mNotification->getName();
     // is it a script dialog?
-    mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup");
+    mIsScriptDialog = (notif_name == "ScriptDialog" || notif_name == "ScriptDialogGroup");
+
+    bool is_content_trusted = (notif_name != "LoadWebPage");
     // is it a caution?
     //
     // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
@@ -314,6 +318,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
     mTextBox->setMaxTextLength(MAX_LENGTH);
     mTextBox->setVisible(TRUE);
     mTextBox->setPlainText(!show_images);
+    mTextBox->setContentTrusted(is_content_trusted);
     mTextBox->setValue(mNotification->getMessage());
 	mTextBox->setIsFriendCallback(LLAvatarActions::isFriend);
 
-- 
cgit v1.2.3


From 90fc7a13d1ebf766f727f4709853d2a9bd4f2d4e Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Thu, 29 May 2014 21:08:21 +0100
Subject: MAINT-4106: Correcting crash on exit behavior during normal shutdown.
  With the more comprehensive texture cleanup going on, this code was causing
 an crash on exit when gAgentAvatarp was null.  Adding a check for null before
 proceeding.

---
 indra/newview/llvoavatarself.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 319da1abb5..83e08ff1e8 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2033,7 +2033,10 @@ BOOL LLVOAvatarSelf::getIsCloud() const
 /*static*/
 void LLVOAvatarSelf::debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
 {
-	gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata);
+	if (gAgentAvatarp.notNull())
+	{
+		gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata);
+	}
 }
 
 void LLVOAvatarSelf::debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
-- 
cgit v1.2.3


From 51e0cc8140a2cbe92363cb902144ccc9bf34b7c7 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Sat, 31 May 2014 02:30:12 +0100
Subject: MAINT-4114: Refactoring the LLBadge code to ensure a parent view
 always has the badge (to preserve memory cleanliness), but to also allow for
 badge reparenting so that the NEW badge works in the inventory window.  This
 change relates to 9e0d629da1487f850beb2767bd47734c4ccc393e.

---
 indra/llui/llbadgeowner.cpp                        | 45 +++++-----------------
 indra/llui/llbadgeowner.h                          |  8 ++--
 indra/llui/llbutton.cpp                            |  2 +-
 indra/newview/llpanelmarketplaceinboxinventory.cpp | 10 ++---
 4 files changed, 18 insertions(+), 47 deletions(-)

diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
index 9b2a9569f7..55e64bb940 100755
--- a/indra/llui/llbadgeowner.cpp
+++ b/indra/llui/llbadgeowner.cpp
@@ -35,8 +35,9 @@
 //
 
 LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle)
-	: mBadge(NULL)
-	, mBadgeOwnerView(viewHandle)
+	: mHasBadgeHolderParent(false),
+	mBadge(NULL),
+	mBadgeOwnerView(viewHandle)
 {
 }
 
@@ -45,31 +46,12 @@ void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
 	if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
 	{
 		mBadge = createBadge(p);
-		addBadgeToParentPanel();
-	}
-}
-
-void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
-{
-	if (mBadge == NULL)
-	{
-		mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
-		addBadgeToParentPanel();
-	}
+		mHasBadgeHolderParent = false;
 
-	if (mBadge)
-	{
-		mBadge->setLabel(label);
-
-		//
-		// Push the badge to the front so it renders on top
-		//
-
-		LLView * parent = mBadge->getParent();
-
-		if (parent)
+		LLView * owner_view = mBadgeOwnerView.get();
+		if (owner_view)
 		{
-			parent->sendChildToFront(mBadge);
+			mBadge->addToView(owner_view);
 		}
 	}
 }
@@ -82,10 +64,8 @@ void LLBadgeOwner::setBadgeVisibility(bool visible)
 	}
 }
 
-bool LLBadgeOwner::addBadgeToParentPanel()
+void LLBadgeOwner::addBadgeToParentHolder()
 {
-	bool badge_added = false;
-
 	LLView * owner_view = mBadgeOwnerView.get();
 	
 	if (mBadge && owner_view)
@@ -110,16 +90,9 @@ bool LLBadgeOwner::addBadgeToParentPanel()
 
 		if (badge_holder)
 		{
-			badge_added = badge_holder->addBadge(mBadge);
-		}
-		else
-		{
-			// Badge parent is fallback badge owner if no valid holder exists in the hierarchy
-			badge_added = mBadge->addToView(owner_view);
+			mHasBadgeHolderParent = badge_holder->addBadge(mBadge);
 		}
 	}
-
-	return badge_added;
 }
 
 LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p)
diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h
index 8d03e30645..53c2de95c8 100755
--- a/indra/llui/llbadgeowner.h
+++ b/indra/llui/llbadgeowner.h
@@ -41,11 +41,9 @@ public:
 	LLBadgeOwner(LLHandle< LLView > viewHandle);
 
 	void initBadgeParams(const LLBadge::Params& p);
-	bool addBadgeToParentPanel();
+	void addBadgeToParentHolder();
 	
-	bool badgeHasParent() const { return (mBadge && mBadge->getParent()); }
-
-	void setBadgeLabel(const LLStringExplicit& label);
+	bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; };
 	void setBadgeVisibility(bool visible);
 
 private:
@@ -53,7 +51,7 @@ private:
 	LLBadge* createBadge(const LLBadge::Params& p);
 
 private:
-
+	bool				mHasBadgeHolderParent;
 	LLBadge*			mBadge;
 	LLHandle< LLView >	mBadgeOwnerView;
 };
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 093d91d44d..ce8383857c 100755
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -384,7 +384,7 @@ BOOL LLButton::postBuild()
 {
 	autoResize();
 
-	addBadgeToParentPanel();
+	addBadgeToParentHolder();
 
 	return LLUICtrl::postBuild();
 }
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp
index 2f65bedc2b..f7c2f629ec 100755
--- a/indra/newview/llpanelmarketplaceinboxinventory.cpp
+++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp
@@ -129,11 +129,11 @@ void LLInboxFolderViewFolder::addItem(LLFolderViewItem* item)
 // virtual
 void LLInboxFolderViewFolder::draw()
 {
-	if (!badgeHasParent())
+	if (!hasBadgeHolderParent())
 	{
-		addBadgeToParentPanel();
+		addBadgeToParentHolder();
 	}
-	
+
 	setBadgeVisibility(mFresh);
 
 	LLFolderViewFolder::draw();
@@ -214,9 +214,9 @@ BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask)
 // virtual
 void LLInboxFolderViewItem::draw()
 {
-	if (!badgeHasParent())
+	if (!hasBadgeHolderParent())
 	{
-		addBadgeToParentPanel();
+		addBadgeToParentHolder();
 	}
 
 	setBadgeVisibility(mFresh);
-- 
cgit v1.2.3


From 6f056ef99dd08a4278ae3b1d3c4bac070a9dfc64 Mon Sep 17 00:00:00 2001
From: "maxim@mnikolenko" <maxim@mnikolenko>
Date: Wed, 4 Jun 2014 13:01:58 +0300
Subject: MAINT-4113 FIXED Get total contribution as sum of parcels' billable
 area.

---
 indra/newview/llpanelgrouplandmoney.cpp | 33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index 106f6c25f1..506c31c22a 100755
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -421,27 +421,14 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
 		msg->getUUID("QueryData", "OwnerID", owner_id, 0);
 		msg->getUUID("TransactionData", "TransactionID", trans_id);
 
+		S32 total_contribution;
 		if(owner_id.isNull())
 		{
 			// special block which has total contribution
 			++first_block;
-			
-			S32 total_contribution;
+
 			msg->getS32("QueryData", "ActualArea", total_contribution, 0);
 			mPanel.getChild<LLUICtrl>("total_contributed_land_value")->setTextArg("[AREA]", llformat("%d", total_contribution));
-
-			S32 committed;
-			msg->getS32("QueryData", "BillableArea", committed, 0);
-			mPanel.getChild<LLUICtrl>("total_land_in_use_value")->setTextArg("[AREA]", llformat("%d", committed));
-			
-			S32 available = total_contribution - committed;
-			mPanel.getChild<LLUICtrl>("land_available_value")->setTextArg("[AREA]", llformat("%d", available));
-
-			if ( mGroupOverLimitTextp && mGroupOverLimitIconp )
-			{
-				mGroupOverLimitIconp->setVisible(available < 0);
-				mGroupOverLimitTextp->setVisible(available < 0);
-			}
 		}
 
 		if ( trans_id != mTransID ) return;
@@ -460,7 +447,8 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
 		std::string sim_name;
 		std::string land_sku;
 		std::string land_type;
-		
+		S32 committed = 0;
+
 		for(S32 i = first_block; i < count; ++i)
 		{
 			msg->getUUID("QueryData", "OwnerID", owner_id, i);
@@ -489,6 +477,9 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
 			S32 region_y = llround(global_y) % REGION_WIDTH_UNITS;
 			std::string location = sim_name + llformat(" (%d, %d)", region_x, region_y);
 			std::string area;
+			committed+=billable_area;
+
+
 			if(billable_area == actual_area)
 			{
 				area = llformat("%d", billable_area);
@@ -525,6 +516,16 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
 			
 			mGroupParcelsp->addElement(row);
 		}
+
+		mPanel.getChild<LLUICtrl>("total_land_in_use_value")->setTextArg("[AREA]", llformat("%d", committed));
+
+		S32 available = total_contribution - committed;
+		mPanel.getChild<LLUICtrl>("land_available_value")->setTextArg("[AREA]", llformat("%d", available));
+		if ( mGroupOverLimitTextp && mGroupOverLimitIconp )
+		{
+			mGroupOverLimitIconp->setVisible(available < 0);
+			mGroupOverLimitTextp->setVisible(available < 0);
+		}
 	}
 }
 
-- 
cgit v1.2.3


From 739f4954b165bd993f8dfaf0636b7a29c228e091 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 6 Jun 2014 22:35:59 +0100
Subject: Correcting a build error.

---
 indra/newview/llpanelgrouplandmoney.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index 506c31c22a..375c54479d 100755
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -421,7 +421,7 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
 		msg->getUUID("QueryData", "OwnerID", owner_id, 0);
 		msg->getUUID("TransactionData", "TransactionID", trans_id);
 
-		S32 total_contribution;
+		S32 total_contribution = 0;
 		if(owner_id.isNull())
 		{
 			// special block which has total contribution
-- 
cgit v1.2.3


From 47a5e1c751bb8dfccef65ee841749d8209106c99 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Thu, 5 Jun 2014 23:15:43 +0100
Subject: MAINT-4009: Ensuring that the local bitmaps are cleaned up on app
 exit.

---
 indra/newview/llappviewer.cpp    | 5 ++++-
 indra/newview/lllocalbitmaps.cpp | 6 ++++++
 indra/newview/lllocalbitmaps.h   | 1 +
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 1c38adb879..42f56fff32 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -100,6 +100,7 @@
 #include "llspellcheck.h"
 #include "llscenemonitor.h"
 #include "llavatarrenderinfoaccountant.h"
+#include "lllocalbitmaps.h"
 
 // Linden library includes
 #include "llavatarnamecache.h"
@@ -1758,7 +1759,9 @@ bool LLAppViewer::cleanup()
 #if 0 // this seems to get us stuck in an infinite loop...
 	gTransferManager.cleanup();
 #endif
-	
+
+	LLLocalBitmapMgr::cleanupClass();
+
 	// Note: this is where gWorldMap used to be deleted.
 
 	// Note: this is where gHUDManager used to be deleted.
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 1948475530..e78e0233d7 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -824,6 +824,12 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr()
 {
 }
 
+void LLLocalBitmapMgr::cleanupClass()
+{
+	std::for_each(sBitmapList.begin(), sBitmapList.end(), DeletePointer());
+	sBitmapList.clear();
+}
+
 bool LLLocalBitmapMgr::addUnit()
 {
 	bool add_successful = false;
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index 47c077dcab..a15ea10801 100755
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -117,6 +117,7 @@ class LLLocalBitmapMgr
 		~LLLocalBitmapMgr();
 
 	public:
+		static void			cleanupClass();
 		static bool         addUnit();
 		static void         delUnit(LLUUID tracking_id);
 
-- 
cgit v1.2.3


From bde6023286c899c99104b16181203f7b58819333 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 6 Jun 2014 19:28:18 +0100
Subject: MAINT-4137: Correcting some poorly written CPP code that could
 potentially lead to problems in the future.

---
 indra/newview/lllocalbitmaps.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index e78e0233d7..92587a911a 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -190,7 +190,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
 				{
 					// decode is successful, we can safely proceed.
 					LLUUID old_id = LLUUID::null;
-					if (!(optional_firstupdate == UT_FIRSTUSE) && !mWorldID.isNull())
+					if ((optional_firstupdate != UT_FIRSTUSE) && !mWorldID.isNull())
 					{
 						old_id = mWorldID;
 					}
@@ -206,7 +206,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
 
 					gTextureList.addImage(texture);
 			
-					if (!optional_firstupdate == UT_FIRSTUSE)
+					if (optional_firstupdate != UT_FIRSTUSE)
 					{
 						// seek out everything old_id uses and replace it with mWorldID
 						replaceIDs(old_id, mWorldID);
-- 
cgit v1.2.3


From 61f3bf8a4799016f6a50007314816cddb1dff030 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Fri, 6 Jun 2014 19:30:41 +0100
Subject: MAINT-4137: Correcting a potential crash.  This change should fix the
 most probable location of a callstack being reported by the crash reporter. 
 However, there is no reproduction yet, so hard to test whether this actually
 patches the crash occcurrence.

---
 indra/newview/lllocalbitmaps.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 92587a911a..6d1a240ce5 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -213,8 +213,11 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
 
 						// remove old_id from gimagelist
 						LLViewerFetchedTexture* image = gTextureList.findImage(old_id);
-						gTextureList.deleteImage(image);
-						image->unref();
+						if (image != NULL)
+						{
+							gTextureList.deleteImage(image);
+							image->unref();
+						}
 					}
 
 					mUpdateRetries = LL_LOCAL_UPDATE_RETRIES;
-- 
cgit v1.2.3


From 086b2c0448584c3a3c5fc320f9f6ba20e613d974 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Sat, 7 Jun 2014 16:02:30 -0700
Subject: MAINT-4001 : Make Received Items not movable (protected), consolidate
 Received Items folders which may have been moved

---
 indra/llinventory/llfoldertype.cpp     |  2 +-
 indra/newview/llsidepanelinventory.cpp | 12 +++++++-----
 indra/newview/llviewerfoldertype.cpp   |  2 +-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 8b568ea560..5f8aaae20b 100755
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -92,7 +92,7 @@ LLFolderDictionary::LLFolderDictionary()
 
 	addEntry(LLFolderType::FT_MESH, 				new FolderEntry("mesh",	TRUE));
 
-	addEntry(LLFolderType::FT_INBOX, 				new FolderEntry("inbox",	FALSE));
+	addEntry(LLFolderType::FT_INBOX, 				new FolderEntry("inbox",	TRUE));
 	addEntry(LLFolderType::FT_OUTBOX, 				new FolderEntry("outbox",	FALSE));
 	
 	addEntry(LLFolderType::FT_BASIC_ROOT,			new FolderEntry("basic_rt", TRUE));
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 2556714792..4970eec636 100755
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -257,12 +257,9 @@ void LLSidepanelInventory::updateInbox()
 	//
 	// Track inbox folder changes
 	//
-
-	const bool do_not_create_folder = false;
-
-	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder);
+	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
 	
-	// Set up observer to listen for creation of inbox if at least one of them doesn't exist
+	// Set up observer to listen for creation of inbox if it doesn't exist
 	if (inbox_id.isNull())
 	{
 		observeInboxCreation();
@@ -270,6 +267,11 @@ void LLSidepanelInventory::updateInbox()
 	// Set up observer for inbox changes, if we have an inbox already
 	else 
 	{
+        // Consolidate Received items
+        // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention,
+        // things can get messy and conventions broken. This call puts everything back together in its right place.
+        gInventory.consolidateForType(inbox_id, LLFolderType::FT_INBOX);
+        
 		// Enable the display of the inbox if it exists
 		enableInbox(true);
 
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 4237ffd295..66e900c405 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -136,7 +136,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 	addEntry(LLFolderType::FT_MESH, 				new ViewerFolderEntry("Meshes",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
 	
 	bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible");
-	addEntry(LLFolderType::FT_INBOX, 				new ViewerFolderEntry("Inbox",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     boxes_invisible));
+	addEntry(LLFolderType::FT_INBOX, 				new ViewerFolderEntry("Received Items",			"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     boxes_invisible));
 	addEntry(LLFolderType::FT_OUTBOX, 				new ViewerFolderEntry("Merchant Outbox",		"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     boxes_invisible));
 
 	addEntry(LLFolderType::FT_BASIC_ROOT, 			new ViewerFolderEntry("Basic Root",				"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
-- 
cgit v1.2.3


From de8af18157e6defae07cd7c9f5d411fdb0c17245 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 16 Jun 2014 11:34:48 -0400
Subject: Added tag 3.7.9-release for changeset a9f2d0cb11f7

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 0f990fc3b9..b972d376f7 100755
--- a/.hgtags
+++ b/.hgtags
@@ -481,3 +481,4 @@ fc066b82343fca51f9c1b8eda0abc6bee9bb4503 3.7.5-release
 d029faf69f20a23007f32420a1ac6a3b89a6d441 3.7.6-release
 83959480cb986522d07b151a0c778ab7f920d41b 3.7.7-release
 bba9b3722eea08949e4ff69591f736bf0f808434 3.7.8-release
+a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
-- 
cgit v1.2.3


From 977476171ddcc057d7c28b6c14ae988b8189ed75 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 16 Jun 2014 11:35:23 -0400
Subject: increment viewer version to 3.7.10

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index c77a7de85c..f06fb9e915 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.9
+3.7.10
-- 
cgit v1.2.3