diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 929da0e9cb5799c72aa22285e37aa5dd43b11893..227b1c5461979f6dcd6de1fa4f384f8e8339f702 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -16034,6 +16034,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>UseHTTPInventory</key>
+    <map>
+      <key>Comment</key>
+      <string>Allow use of http inventory transfers instead of UDP</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>ClickToWalk</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 2ec20b827176a3683f8d109ebc7c01ff81917cbc..e6a77c8ccbb1e1336b64b7b0e4487ef4c6d7392e 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -3035,7 +3035,9 @@ void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
 	msg->setHandlerFuncFast(_PREHASH_BulkUpdateInventory,
 							processBulkUpdateInventory,
 							NULL);
+	msg->setHandlerFuncFast(_PREHASH_InventoryDescendents, processInventoryDescendents);
 	msg->setHandlerFuncFast(_PREHASH_MoveInventoryItem, processMoveInventoryItem);
+	msg->setHandlerFuncFast(_PREHASH_FetchInventoryReply, processFetchInventoryReply);
 }
 
 
@@ -3055,6 +3057,14 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo
 
 }
 
+// static
+void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**)
+{
+	// no accounting
+	gInventory.messageUpdateCore(msg, false);
+}
+
+
 bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask)
 {
 	//make sure our added inventory observer is active
@@ -3519,6 +3529,62 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 	}
 }
 
+// static
+void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
+{
+	LLUUID agent_id;
+	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+	if(agent_id != gAgent.getID())
+	{
+		LL_WARNS() << "Got a UpdateInventoryItem for the wrong agent." << LL_ENDL;
+		return;
+	}
+	LLUUID parent_id;
+	msg->getUUID("AgentData", "FolderID", parent_id);
+	LLUUID owner_id;
+	msg->getUUID("AgentData", "OwnerID", owner_id);
+	S32 version;
+	msg->getS32("AgentData", "Version", version);
+	S32 descendents;
+	msg->getS32("AgentData", "Descendents", descendents);
+
+	S32 i;
+	S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
+	LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
+	for(i = 0; i < count; ++i)
+	{
+		tcategory->unpackMessage(msg, _PREHASH_FolderData, i);
+		gInventory.updateCategory(tcategory);
+	}
+
+	count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
+	LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+	for(i = 0; i < count; ++i)
+	{
+		titem->unpackMessage(msg, _PREHASH_ItemData, i);
+		// 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()))
+		{
+			LL_DEBUGS("Inventory") << "Skipping prefetched item [ Name: " << titem->getName()
+								   << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << LL_ENDL;
+			continue;
+		}
+		gInventory.updateItem(titem);
+	}
+
+	// set version and descendentcount according to message.
+	LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
+	if(cat)
+	{
+		cat->setVersion(version);
+		cat->setDescendentCount(descendents);
+		// Get this UUID on the changed list so that whatever's listening for it
+		// will get triggered.
+		gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat->getUUID());
+	}
+	gInventory.notifyObservers();
+}
+
 // static
 void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**)
 {
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index d60884c3516c31c6f963936e1805b18331ea9bf7..cf8b1613306becb86c9b36b81a3b6ff58080ce69 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -664,7 +664,9 @@ class LLInventoryModel
 	static void processRemoveInventoryObjects(LLMessageSystem* msg, void**);
 	static void processSaveAssetIntoInventory(LLMessageSystem* msg, void**);
 	static void processBulkUpdateInventory(LLMessageSystem* msg, void**);
+	static void processInventoryDescendents(LLMessageSystem* msg, void**);
 	static void processMoveInventoryItem(LLMessageSystem* msg, void**);
+	static void processFetchInventoryReply(LLMessageSystem* msg, void**);
 protected:
 	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, U32 mask = 0x0);
 
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 362fed2aa009b7d13e8b6b3b1214f57a82ae69f7..dc9436dd6b94631adccc9c13d8484cb89c72745c 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -41,6 +41,8 @@
 #include "bufferarray.h"
 #include "bufferstream.h"
 #include "llcorehttputil.h"
+#include "llviewermenu.h"
+#include "llviewernetwork.h"
 
 // History (may be apocryphal)
 //
@@ -174,6 +176,8 @@ class BGFolderHttpHandler : public LLCore::HttpHandler
 };
 
 
+const S32 MAX_FETCH_RETRIES = 10;
+
 const char * const LOG_INV("Inventory");
 
 } // end of namespace anonymous
@@ -190,7 +194,11 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch():
 	mAllFoldersFetched(FALSE),
 	mRecursiveInventoryFetchStarted(FALSE),
 	mRecursiveLibraryFetchStarted(FALSE),
-	mMinTimeBetweenFetches(0.3f)
+	mTimelyFetchPending(FALSE),
+	mNumFetchRetries(0),
+	mMinTimeBetweenFetches(0.3f),
+	mMaxTimeBetweenFetches(10.f)
+
 {}
 
 LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
@@ -339,7 +347,164 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
 	if (mBackgroundFetchActive && gAgent.getRegion() && gAgent.getRegion()->capabilitiesReceived())
 	{
 		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
-		bulkFetch();
+		if (LLGridManager::instanceFast().isInSecondlife() || gSavedSettings.getBOOL("UseHTTPInventory"))
+		{
+			bulkFetch();
+			return;
+		}
+		
+#if 1
+		//--------------------------------------------------------------------------------
+		// DEPRECATED OLD CODE
+		//
+
+		// No more categories to fetch, stop fetch process.
+		if (mFetchQueue.empty())
+		{
+			setAllFoldersFetched();
+			return;
+		}
+
+		F32 fast_fetch_time = ll_lerp(mMinTimeBetweenFetches, mMaxTimeBetweenFetches, 0.1f);
+		F32 slow_fetch_time = ll_lerp(mMinTimeBetweenFetches, mMaxTimeBetweenFetches, 0.5f);
+		if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() > slow_fetch_time)
+		{
+			// Double timeouts on failure.
+			mMinTimeBetweenFetches = llmin(mMinTimeBetweenFetches * 2.f, 10.f);
+			mMaxTimeBetweenFetches = llmin(mMaxTimeBetweenFetches * 2.f, 120.f);
+			LL_DEBUGS(LOG_INV) << "Inventory fetch times grown to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << LL_ENDL;
+			// fetch is no longer considered "timely" although we will wait for full time-out.
+			mTimelyFetchPending = FALSE;
+		}
+
+		while(1)
+		{
+			if (mFetchQueue.empty())
+			{
+				break;
+			}
+
+			if (gDisconnected)
+			{
+				// Just bail if we are disconnected.
+				break;
+			}
+
+			const FetchQueueInfo info = mFetchQueue.front();
+
+			if (info.mIsCategory)
+			{
+
+				LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID);
+
+				// Category has been deleted, remove from queue.
+				if (!cat)
+				{
+					mFetchQueue.pop_front();
+					continue;
+				}
+			
+				if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches && 
+					LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
+				{
+					// Category exists but has no children yet, fetch the descendants
+					// for now, just request every time and rely on retry timer to throttle.
+					if (cat->fetch())
+					{
+						mFetchTimer.reset();
+						mTimelyFetchPending = TRUE;
+					}
+					else
+					{
+						//  The catagory also tracks if it has expired and here it says it hasn't
+						//  yet.  Get out of here because nothing is going to happen until we
+						//  update the timers.
+						break;
+					}
+				}
+				// Do I have all my children?
+				else if (gInventory.isCategoryComplete(info.mUUID))
+				{
+					// Finished with this category, remove from queue.
+					mFetchQueue.pop_front();
+
+					// Add all children to queue.
+					LLInventoryModel::cat_array_t* categories;
+					LLInventoryModel::item_array_t* items;
+					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
+					for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
+						 it != categories->end();
+						 ++it)
+					{
+						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));
+					}
+
+					// We received a response in less than the fast time.
+					if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)
+					{
+						// Shrink timeouts based on success.
+						mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);
+						mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);
+						LL_DEBUGS(LOG_INV) << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << LL_ENDL;
+					}
+
+					mTimelyFetchPending = FALSE;
+					continue;
+				}
+				else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
+				{
+					// Received first packet, but our num descendants does not match db's num descendants
+					// so try again later.
+					mFetchQueue.pop_front();
+
+					if (mNumFetchRetries++ < MAX_FETCH_RETRIES)
+					{
+						// push on back of queue
+						mFetchQueue.push_back(info);
+					}
+					mTimelyFetchPending = FALSE;
+					mFetchTimer.reset();
+					break;
+				}
+
+				// Not enough time has elapsed to do a new fetch
+				break;
+			}
+			else
+			{
+				LLViewerInventoryItem* itemp = gInventory.getItem(info.mUUID);
+
+				mFetchQueue.pop_front();
+				if (!itemp) 
+				{
+					continue;
+				}
+
+				if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches)
+				{
+					itemp->fetchFromServer();
+					mFetchTimer.reset();
+					mTimelyFetchPending = TRUE;
+				}
+				else if (itemp->mIsComplete)
+				{
+					mTimelyFetchPending = FALSE;
+				}
+				else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
+				{
+					mFetchQueue.push_back(info);
+					mFetchTimer.reset();
+					mTimelyFetchPending = FALSE;
+				}
+				// Not enough time has elapsed to do a new fetch
+				break;
+			}
+		}
+
+		//
+		// DEPRECATED OLD CODE
+		//--------------------------------------------------------------------------------
+#endif
 	}
 }
 
@@ -391,7 +556,10 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
 		// OnIdle it will be called anyway due to Add flag for processed item.
 		// It seems like in some cases we are updaiting on fail (no flag),
 		// but is there anything to update?
-		gInventory.notifyObservers();
+		if (LLGridManager::getInstance()->isInSecondlife())
+		{
+			gInventory.notifyObservers();
+		}
 	}
 	
 	if ((mFetchCount > max_concurrent_fetches) ||
@@ -700,6 +868,10 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res
                         titem->setParent(lost_uuid);
                         titem->updateParentOnServer(FALSE);
                         gInventory.updateItem(titem);
+                        if (!LLGridManager::getInstance()->isInSecondlife())
+                        {
+                            gInventory.notifyObservers();
+                        }
                     }
                 }
             }
@@ -761,6 +933,11 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res
 	{
 		fetcher->setAllFoldersFetched();
 	}
+
+	if (!LLGridManager::getInstance()->isInSecondlife())
+	{
+		gInventory.notifyObservers();
+	}
 }
 
 
@@ -800,6 +977,11 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http
 			fetcher->setAllFoldersFetched();
 		}
 	}
+
+	if (!LLGridManager::getInstance()->isInSecondlife())
+	{
+		gInventory.notifyObservers();
+	}
 }
 
 
@@ -834,6 +1016,11 @@ void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::Http
 			fetcher->setAllFoldersFetched();
 		}
 	}
+
+	if (!LLGridManager::getInstance()->isInSecondlife())
+	{
+		gInventory.notifyObservers();
+	}
 }
 
 
diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h
index b7839cf08075b033614cd793207906656967069f..67066bc0e2402cc2239398eb5e2faca87a594985 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.h
+++ b/indra/newview/llinventorymodelbackgroundfetch.h
@@ -89,7 +89,11 @@ class LLInventoryModelBackgroundFetch final : public LLSingleton<LLInventoryMode
 	S32 mFetchCount;
 
 	LLFrameTimer mFetchTimer;
+	BOOL mTimelyFetchPending;
+	S32 mNumFetchRetries;
 	F32 mMinTimeBetweenFetches;
+	F32 mMaxTimeBetweenFetches;
+
 
 	struct FetchQueueInfo
 	{
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 8ef8e0cc6a3ccd76a3b86096d8ffe6d05f32c9e7..be6de01a62aedc753d5c8584a81ef2282c55f610 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -56,6 +56,8 @@
 #include "llsdutil.h"
 #include <deque>
 
+#include "llviewernetwork.h"
+
 const F32 LLInventoryFetchItemsObserver::FETCH_TIMER_EXPIRY = 60.0f;
 
 
@@ -241,11 +243,39 @@ void fetch_items_from_llsd(const LLSD& items_llsd)
 			gInventory.requestPost(true, url, body[i], handler, (i ? "Library Item" : "Inventory Item"));
 			continue;
 		}
-        else
-        {
-            LL_WARNS("INVENTORY") << "Failed to get capability." << LL_ENDL;
-        }
-
+		else if (!LLGridManager::instance().isInSecondlife())
+		{
+			LLMessageSystem* msg = gMessageSystem;
+			BOOL start_new_message = TRUE;
+			for (S32 j = 0; j < body[i]["items"].size(); j++)
+			{
+				LLSD item_entry = body[i]["items"][j];
+				if (start_new_message)
+				{
+					start_new_message = FALSE;
+					msg->newMessageFast(_PREHASH_FetchInventory);
+					msg->nextBlockFast(_PREHASH_AgentData);
+					msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+					msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+				}
+				msg->nextBlockFast(_PREHASH_InventoryData);
+				msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
+				msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
+				if (msg->isSendFull(NULL))
+				{
+					start_new_message = TRUE;
+					gAgent.sendReliableMessage();
+				}
+			}
+			if (!start_new_message)
+			{
+				gAgent.sendReliableMessage();
+			}
+		}
+		else
+		{
+			LL_WARNS("INVENTORY") << "Failed to get capability or udp fallback." << LL_ENDL;
+		}
 	}
 }
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d7c6f692f686d019457d9748edd99b31861a552e..ff85fbfc039f6071990e1876b0d1098df9024c1d 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -429,26 +429,42 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const
 	LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
 	gInventory.accountForUpdate(up);
 
-    LLSD updates = asLLSD();
-    // Replace asset_id and/or shadow_id with transaction_id (hash_id)
-    if (updates.has("asset_id"))
-    {
-        updates.erase("asset_id");
-        if(getTransactionID().notNull())
+	if (AISAPI::isAvailable())
+	{
+        LLSD updates = asLLSD();
+        // Replace asset_id and/or shadow_id with transaction_id (hash_id)
+        if (updates.has("asset_id"))
         {
-            updates["hash_id"] = getTransactionID();
+            updates.erase("asset_id");
+            if(getTransactionID().notNull())
+            {
+                updates["hash_id"] = getTransactionID();
+            }
         }
-    }
-    if (updates.has("shadow_id"))
-    {
-        updates.erase("shadow_id");
-        if(getTransactionID().notNull())
+        if (updates.has("shadow_id"))
         {
-            updates["hash_id"] = getTransactionID();
+            updates.erase("shadow_id");
+            if(getTransactionID().notNull())
+            {
+                updates["hash_id"] = getTransactionID();
+            }
         }
-    }
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
-    AISAPI::UpdateItem(getUUID(), updates, cr);
+        AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
+        AISAPI::UpdateItem(getUUID(), updates, cr);
+	}
+	else
+	{
+		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, mTransactionID);
+		msg->nextBlockFast(_PREHASH_InventoryData);
+		msg->addU32Fast(_PREHASH_CallbackID, 0);
+		packMessage(msg);
+		gAgent.sendReliableMessage();
+	}
 }
 
 void LLViewerInventoryItem::fetchFromServer(void) const
@@ -657,9 +673,26 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
 		return;
 	}
 
-    LLSD new_llsd = asLLSD();
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
-    AISAPI::UpdateCategory(getUUID(), new_llsd, cr);
+	if (AISAPI::isAvailable())
+	{
+    	LLSD new_llsd = asLLSD();
+    	AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
+    	AISAPI::UpdateCategory(getUUID(), new_llsd, cr);
+	}
+	else
+	{
+		LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
+		gInventory.accountForUpdate(up);
+
+		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);
+		packMessage(msg);
+		gAgent.sendReliableMessage();
+	}
 }
 
 S32 LLViewerInventoryCategory::getVersion() const
@@ -696,6 +729,29 @@ bool LLViewerInventoryCategory::fetch()
 		{
 			LLInventoryModelBackgroundFetch::instance().start(mUUID, false);			
 		}
+		else
+		{
+			// bitfield
+			// 1 = by date
+			// 2 = folders by date
+			// Need to mask off anything but the first bit.
+			// This comes from LLInventoryFilter from llfolderview.h
+			U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1;
+			
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessage("FetchInventoryDescendents");
+			msg->nextBlock("AgentData");
+			msg->addUUID("AgentID", gAgent.getID());
+			msg->addUUID("SessionID", gAgent.getSessionID());
+			msg->nextBlock("InventoryData");
+			msg->addUUID("FolderID", mUUID);
+			msg->addUUID("OwnerID", mOwnerID);
+
+			msg->addS32("SortOrder", sort_order);
+			msg->addBOOL("FetchFolders", FALSE);
+			msg->addBOOL("FetchItems", TRUE);
+			gAgent.sendReliableMessage();
+		}
 		return true;
 	}
 	return false;
@@ -824,16 +880,33 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
 	const LLUUID &parent_id = getParentUUID();
 	const std::string &name = getName();
 		
-    LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(folder_id,
-                                                                                 parent_id,
-                                                                                 new_folder_type,
-                                                                                 name,
-                                                                                 gAgent.getID());
+	if (AISAPI::isAvailable())
+	{
+	    LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(folder_id,
+	                                                                                 parent_id,
+	                                                                                 new_folder_type,
+	                                                                                 name,
+	                                                                                 gAgent.getID());
         
         
-    LLSD new_llsd = new_cat->asLLSD();
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>) NULL, _1);
-    AISAPI::UpdateCategory(folder_id, new_llsd, cr);
+	    LLSD new_llsd = new_cat->asLLSD();
+	    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>) NULL, _1);
+	    AISAPI::UpdateCategory(folder_id, new_llsd, cr);
+	}
+	else
+	{
+		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);
+		msg->addUUIDFast(_PREHASH_FolderID, folder_id);
+		msg->addUUIDFast(_PREHASH_ParentID, parent_id);
+		msg->addS8Fast(_PREHASH_Type, new_folder_type);
+		msg->addStringFast(_PREHASH_Name, name);
+		gAgent.sendReliableMessage();
+	}
 
 	setPreferredType(new_folder_type);
 	gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
@@ -1238,10 +1311,40 @@ void link_inventory_array(const LLUUID& category,
 						   << " UUID:" << category << " ] " << LL_ENDL;
 #endif
 	}
-    LLSD new_inventory = LLSD::emptyMap();
-    new_inventory["links"] = links;
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
-    AISAPI::CreateInventory(category, new_inventory, cr);
+
+    if (AISAPI::isAvailable())
+	{
+        LLSD new_inventory = LLSD::emptyMap();
+        new_inventory["links"] = links;
+        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
+        AISAPI::CreateInventory(category, new_inventory, cr);
+	}
+    else
+	{
+		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();
+		}
+	}
 }
 
 void move_inventory_item(
@@ -1273,27 +1376,55 @@ void update_inventory_item(
 	LLPointer<LLInventoryCallback> cb)
 {
 	const LLUUID& item_id = update_item->getUUID();
-  
-    LLSD updates = update_item->asLLSD();
-    // Replace asset_id and/or shadow_id with transaction_id (hash_id)
-    if (updates.has("asset_id"))
-    {
-        updates.erase("asset_id");
-        if (update_item->getTransactionID().notNull())
-        {
-            updates["hash_id"] = update_item->getTransactionID();
-        }
-    }
-    if (updates.has("shadow_id"))
-    {
-        updates.erase("shadow_id");
-        if (update_item->getTransactionID().notNull())
-        {
-            updates["hash_id"] = update_item->getTransactionID();
-        }
-    }
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
-    AISAPI::UpdateItem(item_id, updates, cr);
+    if (AISAPI::isAvailable())
+	{
+		LLSD updates = update_item->asLLSD();
+		// Replace asset_id and/or shadow_id with transaction_id (hash_id)
+		if (updates.has("asset_id"))
+		{
+			updates.erase("asset_id");
+        		if (update_item->getTransactionID().notNull())
+        		{
+				updates["hash_id"] = update_item->getTransactionID();
+			}
+		}
+		if (updates.has("shadow_id"))
+		{
+			updates.erase("shadow_id");
+			if (update_item->getTransactionID().notNull())
+			{
+				updates["hash_id"] = update_item->getTransactionID();
+			}
+		}
+        	AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
+        	AISAPI::UpdateItem(item_id, updates, cr);
+	}
+    else
+	{
+		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL;
+		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
@@ -1304,8 +1435,41 @@ void update_inventory_item(
 	const LLSD& updates,
 	LLPointer<LLInventoryCallback> cb)
 {
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
-    AISAPI::UpdateItem(item_id, updates, cr);
+    if (AISAPI::isAvailable())
+	{
+        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
+        AISAPI::UpdateItem(item_id, updates, cr);
+	}
+    else
+	{
+		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
+		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
+		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);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->addUUIDFast(_PREHASH_TransactionID, new_item->getTransactionID());
+			msg->nextBlockFast(_PREHASH_InventoryData);
+			msg->addU32Fast(_PREHASH_CallbackID, 0);
+			new_item->packMessage(msg);
+			gAgent.sendReliableMessage();
+
+			LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateItem(new_item);
+			if (cb)
+			{
+				cb->fire(item_id);
+			}
+		}
+	}
 }
 
 void update_inventory_category(
@@ -1325,9 +1489,31 @@ void update_inventory_category(
 
 		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
 		new_cat->fromLLSD(updates);
-        LLSD new_llsd = new_cat->asLLSD();
-        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
-        AISAPI::UpdateCategory(cat_id, new_llsd, cr);
+        if (AISAPI::isAvailable())
+		{
+			LLSD new_llsd = new_cat->asLLSD();
+            AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
+            AISAPI::UpdateCategory(cat_id, new_llsd, cr);
+		}
+		else // no cap
+		{
+			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);
+			new_cat->packMessage(msg);
+			gAgent.sendReliableMessage();
+
+			LLInventoryModel::LLCategoryUpdate up(new_cat->getParentUUID(), 0);
+			gInventory.accountForUpdate(up);
+			gInventory.updateCategory(new_cat);
+			if (cb)
+			{
+				cb->fire(cat_id);
+			}
+		}
 	}
 }
 
@@ -1449,8 +1635,41 @@ void remove_inventory_category(
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
 			return;
 		}
-        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
-        AISAPI::RemoveCategory(cat_id, cr);
+        if (AISAPI::isAvailable())
+		{
+            AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
+            AISAPI::RemoveCategory(cat_id, cr);
+		}
+		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)
+			{
+				LL_DEBUGS(LOG_INV) << "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;
+			}
+
+			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
 	{
@@ -1729,11 +1948,47 @@ void slam_inventory_folder(const LLUUID& folder_id,
 						   const LLSD& contents,
 						   LLPointer<LLInventoryCallback> cb)
 {
-    LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id
-                       << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
+    if (AISAPI::isAvailable())
+	{
+		LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id
+						   << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
 
-    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
-    AISAPI::SlamFolder(folder_id, contents, cr);
+        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
+        AISAPI::SlamFolder(folder_id, contents, cr);
+	}
+	else // no cap
+	{
+// [RLVa:KB] - Checked: 2014-11-02 (RLVa-1.4.11)
+		LL_DEBUGS(LOG_INV) << "using item-by-item calls to slam folder, id " << folder_id
+						   << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
+
+		LLInventoryModel::item_array_t items;
+		for (LLSD::array_const_iterator itItem = contents.beginArray(); itItem != contents.endArray(); ++itItem)
+		{
+			LLViewerInventoryItem* pItem = new LLViewerInventoryItem;
+			pItem->fromLLSD(*itItem);
+			items.push_back(pItem);
+		}
+
+		LLInventoryModel::item_array_t items_to_add, items_to_remove;
+		sync_inventory_folder(folder_id, items, items_to_add, items_to_remove);
+
+		link_inventory_items(folder_id, items_to_add, cb);
+		remove_inventory_items(items_to_remove, cb);
+// [/RLVa:KB]
+//		LL_DEBUGS(LOG_INV) << "using item-by-item calls to slam folder, id " << folder_id
+//						   << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
+//		for (LLSD::array_const_iterator it = contents.beginArray();
+//			 it != contents.endArray();
+//			 ++it)
+//		{
+//			const LLSD& item_contents = *it;
+//			LLViewerInventoryItem *item = new LLViewerInventoryItem;
+//			item->fromLLSD(item_contents);
+//			link_inventory_object(folder_id, item, cb);
+//		}
+//		remove_folder_contents(folder_id,false,cb);
+	}
 }
 
 void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index fa1b12878883538b6816ce892d8d4cd01b9a002b..c1ddf5f3aad6e00c6aee9a1180611d815cb94680 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -83,6 +83,7 @@
 #include "llcallstack.h"
 #include "llsettingsdaycycle.h"
 #include "llviewerparcelmgr.h"
+#include "llviewernetwork.h"
 
 #include <boost/regex.hpp>
 
@@ -2997,12 +2998,15 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("EventQueueGet");
     capabilityNames.append("ExtEnvironment");
 
-	capabilityNames.append("FetchLib2");
-	capabilityNames.append("FetchLibDescendents2");
-	capabilityNames.append("FetchInventory2");
-	capabilityNames.append("FetchInventoryDescendents2");
-	capabilityNames.append("IncrementCOFVersion");
-	AISAPI::getCapNames(capabilityNames);
+	if (LLGridManager::instanceFast().isInSecondlife() || gSavedSettings.getBOOL("UseHTTPInventory"))
+	{
+		capabilityNames.append("FetchLib2");
+		capabilityNames.append("FetchLibDescendents2");
+		capabilityNames.append("FetchInventory2");
+		capabilityNames.append("FetchInventoryDescendents2");
+		capabilityNames.append("IncrementCOFVersion");
+		AISAPI::getCapNames(capabilityNames);
+	}
 
 	capabilityNames.append("InterestList");