From 87776b19443030bece31c26290d1092bf6cbb3e6 Mon Sep 17 00:00:00 2001
From: Christian Goetze <cg@lindenlab.com>
Date: Wed, 29 Jul 2009 22:16:52 +0000
Subject: [PATCH] svn merge -r128774:128808
 svn+ssh://svn.lindenlab.com/svn/user/cg/qar-1737 effective merge: svn merge
 -r127126:128746
 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.27

---
 indra/llinventory/llinventory.cpp |  33 ++++++
 indra/llinventory/llinventory.h   |   4 +
 indra/llmessage/llmail.cpp        |  18 ++-
 indra/llprimitive/llprimitive.cpp | 187 +++++++++++++++++++++++++++++-
 4 files changed, 238 insertions(+), 4 deletions(-)

diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index e45bb598812..76de357e2b8 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -453,6 +453,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc)
 	mCreationDate = creation_date_utc;
 }
 
+void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
+{
+	// Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags 
+	// because we now detect when they should be set.
+	setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) );
+
+	// Enforce the PERM_OVERWRITE flags for any masks that are different
+	// but only for AT_OBJECT's since that is the only asset type that can 
+	// exist in-world (instead of only in-inventory or in-object-contents).
+	if (LLAssetType::AT_OBJECT == getType())
+	{
+		LLPermissions old_permissions = old_item.getPermissions();
+		U32 flags_to_be_set = 0;
+		if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+		}
+		if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+		}
+		if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+		}
+		LLSaleInfo old_sale_info = old_item.getSaleInfo();
+		if(old_sale_info != getSaleInfo())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+		}
+		setFlags(getFlags() | flags_to_be_set);
+	}
+}
 
 const LLSaleInfo& LLInventoryItem::getSaleInfo() const
 {
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 094aebe93b9..08e39585336 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -262,6 +262,10 @@ class LLInventoryItem : public LLInventoryObject
 	void setFlags(U32 flags);
 	void setCreationDate(time_t creation_date_utc);
 
+	// Check for changes in permissions masks and sale info
+	// and set the corresponding bits in mFlags
+	void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
+
 	// Put this inventory item onto the current outgoing mesage. It
 	// assumes you have already called nextBlock().
 	virtual void packMessage(LLMessageSystem* msg) const;
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index d52ff6c7e8b..ce206d8d7d1 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction(
 // static
 bool LLMail::send(
 	const std::string& header,
-	const std::string& message,
+	const std::string& raw_message,
 	const char* from_address,
 	const char* to_address)
 {
@@ -276,8 +276,20 @@ bool LLMail::send(
 		return false;
 	}
 
-	// *FIX: this translation doesn't deal with a single period on a
-	// line by itself.
+	// remove any "." SMTP commands to prevent injection (DEV-35777)
+	// we don't need to worry about "\r\n.\r\n" because of the 
+	// "\n" --> "\n\n" conversion going into rfc2822_msg below
+	std::string message = raw_message;
+	std::string bad_string = "\n.\n";
+	std::string good_string = "\n..\n";
+	while (1)
+	{
+		int index = message.find(bad_string);
+		if (index == std::string::npos) break;
+		message.replace(index, bad_string.size(), good_string);
+	}
+
+	// convert all "\n" into "\r\n"
 	std::ostringstream rfc2822_msg;
 	for(U32 i = 0; i < message.size(); ++i)
 	{
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 58aaf97a760..7b755a7d17d 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -746,16 +746,201 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
 
 	U32 old_face_mask = mVolumep->mFaceMask;
 
+	S32 face_bit = 0;
+	S32 cur_mask = 0;
+
+	// Grab copies of the old faces from the original shape, ordered by type.
+	// We will use these to figure out what old texture info gets mapped to new
+	// faces in the new shape.
+	std::vector<LLProfile::Face> old_faces; 
+	for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
+	{
+		old_faces.push_back(mVolumep->getProfile().mFaces[face]);
+	}
+
+	// Copy the old texture info off to the side, but not in the order in which
+	// they live in the mTextureList, rather in order of ther "face id" which
+	// is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
+	//
+	// Hence, some elements of old_tes::mEntryList will be invalid.  It is
+	// initialized to a size of 9 (max number of possible faces on a volume?)
+	// and only the ones with valid types are filled in.
+	LLPrimTextureList old_tes;
+	old_tes.setSize(9);
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		cur_mask = 0x1 << face_bit;
+		if (old_face_mask & cur_mask)
+		{
+			S32 te_index = face_index_from_id(cur_mask, old_faces);
+			old_tes.copyTexture(face_bit, *(getTE(te_index)));
+			//llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
+		}
+	}
+
+
 	// build the new object
 	sVolumeManager->unrefVolume(mVolumep);
 	mVolumep = volumep;
 	
 	U32 new_face_mask = mVolumep->mFaceMask;
-	if (old_face_mask != new_face_mask) 
+	S32 i;
+
+	if (old_face_mask == new_face_mask) 
 	{
+		// nothing to do
+		return TRUE;
+	}
+
+	if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
+	{
+		llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
 		setNumTEs(mVolumep->getNumFaces());
+		return TRUE;
+	}
+
+	// initialize face_mapping
+	S32 face_mapping[9];
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		face_mapping[face_bit] = face_bit;
+	}
+
+	// The new shape may have more faces than the original, but we can't just
+	// add them to the end -- the ordering matters and it may be that we must
+	// insert the new faces in the middle of the list.  When we add a face it
+	// will pick up the texture/color info of one of the old faces an so we
+	// now figure out which old face info gets mapped to each new face, and 
+	// store in the face_mapping lookup table.
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		cur_mask = 0x1 << face_bit;
+		if (!(new_face_mask & cur_mask))
+		{
+			// Face doesn't exist in new map.
+			face_mapping[face_bit] = -1;
+			continue;
+		}
+		else if (old_face_mask & cur_mask)
+		{
+			// Face exists in new and old map.
+			face_mapping[face_bit] = face_bit;
+			continue;
+		}
+
+		// OK, how we've got a mismatch, where we have to fill a new face with one from
+		// the old face.
+		if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
+		{
+			// It's a top/bottom/hollow interior face.
+			if (old_face_mask & LL_FACE_PATH_END)
+			{
+				face_mapping[face_bit] = 1;
+				continue;
+			}
+			else
+			{
+				S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+				for (i = 0; i < 4; i++)
+				{
+					if (old_face_mask & cur_outer_mask)
+					{
+						face_mapping[face_bit] = 5 + i;
+						break;
+					}
+					cur_outer_mask <<= 1;
+				}
+				if (i == 4)
+				{
+					llwarns << "No path end or outer face in volume!" << llendl;
+				}
+				continue;
+			}
+		}
+
+		if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
+		{
+			// A cut slice.  Use the hollow interior if we have it.
+			if (old_face_mask & LL_FACE_INNER_SIDE)
+			{
+				face_mapping[face_bit] = 2;
+				continue;
+			}
+
+			// No interior, use the bottom face.
+			// Could figure out which of the outer faces was nearest, but that would be harder.
+			if (old_face_mask & LL_FACE_PATH_END)
+			{
+				face_mapping[face_bit] = 1;
+				continue;
+			}
+			else
+			{
+				S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+				for (i = 0; i < 4; i++)
+				{
+					if (old_face_mask & cur_outer_mask)
+					{
+						face_mapping[face_bit] = 5 + i;
+						break;
+					}
+					cur_outer_mask <<= 1;
+				}
+				if (i == 4)
+				{
+					llwarns << "No path end or outer face in volume!" << llendl;
+				}
+				continue;
+			}
+		}
+
+		// OK, the face that's missing is an outer face...
+		// Pull from the nearest adjacent outer face (there's always guaranteed to be one...
+		S32 cur_outer = face_bit - 5;
+		S32 min_dist = 5;
+		S32 min_outer_bit = -1;
+		S32 i;
+		for (i = 0; i < 4; i++)
+		{
+			if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
+			{
+				S32 dist = abs(i - cur_outer);
+				if (dist < min_dist)
+				{
+					min_dist = dist;
+					min_outer_bit = i + 5;
+				}
+			}
+		}
+		if (-1 == min_outer_bit)
+		{
+			llinfos << (LLVolume *)mVolumep << llendl;
+			llwarns << "Bad!  No outer faces, impossible!" << llendl;
+		}
+		face_mapping[face_bit] = min_outer_bit;
 	}
+	
 
+	setNumTEs(mVolumep->getNumFaces());
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		// For each possible face type on the new shape we check to see if that
+		// face exists and if it does we create a texture entry that is a copy
+		// of one of the originals.  Since the originals might not have a
+		// matching face, we use the face_mapping lookup table to figure out
+		// which face information to copy.
+		cur_mask = 0x1 << face_bit;
+		if (new_face_mask & cur_mask)
+		{
+			if (-1 == face_mapping[face_bit])
+			{
+				llwarns << "No mapping from old face to new face!" << llendl;
+			}
+
+			S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
+			setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
+		}
+	}
 	return TRUE;
 }
 
-- 
GitLab