diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index 0e8f3f0f732c4d1762f6ce0d29b5c2015d86e811..9d4f3a98f04668a41a7940353097322c9115191d 100644
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -231,8 +231,7 @@ static BOOL isDefault(const std::string& scheme, U16 port)
 void LLURI::parseAuthorityAndPathUsingOpaque()
 {
 	if (mScheme == "http" || mScheme == "https" ||
-		mScheme == "ftp" || mScheme == "secondlife" || 
-		mScheme == "x-grid-location-info")
+		mScheme == "ftp" || mScheme == "secondlife" )
 	{
 		if (mEscapedOpaque.substr(0,2) != "//")
 		{
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 583c1e589b473158536fe4e396b2729c590732b2..bcbae06ec564e968c68a40718d00b6fcbe9eca7b 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -33,12 +33,9 @@
 
 // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
 #if LL_WINDOWS
-#undef WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include <windows.h>
-// ugh, this is ugly.  We need to straighten out our linking for this library
-#pragma comment(lib, "IPHLPAPI.lib")
-#include <iphlpapi.h>
+#	undef WIN32_LEAN_AND_MEAN
+#	include <winsock2.h>
+#	include <windows.h>
 #endif
 
 #include "lldefs.h"
@@ -455,102 +452,67 @@ static void get_random_bytes(void *buf, int nbytes)
 	return;	
 }
 
-#if	LL_WINDOWS
-// Code	copied from	http://msdn.microsoft.com/en-us/library/aa365939(VS.85).aspx
-// This	code grabs the first hardware	address, rather	than the first interface.
-// Using a VPN can cause the first returned	interface	to be	changed.
-
-const	S32	MAC_ADDRESS_BYTES=6;
-
-
-// static
-S32	LLUUID::getNodeID(unsigned char	*node_id)
+#if LL_WINDOWS
+typedef struct _ASTAT_
 {
+	ADAPTER_STATUS adapt;
+	NAME_BUFFER    NameBuff [30];
+}ASTAT, * PASTAT;
 
-	// Declare and initialize variables.
-	DWORD	dwSize = 0;
-	DWORD	dwRetVal = 0;
-	int	i;
-
-/* variables used	for	GetIfTable and GetIfEntry	*/
-	MIB_IFTABLE	*pIfTable;
-	MIB_IFROW	*pIfRow;
-
-	// Allocate	memory for our pointers.
-	pIfTable = (MIB_IFTABLE	*) malloc(sizeof (MIB_IFTABLE));
-	if (pIfTable ==	NULL)	
-	{
-			printf("Error allocating memory needed to call GetIfTable\n");
-			return 0;
-	}
-
-	// Before	calling	GetIfEntry,	we call	GetIfTable to	make
-	// sure	there	are	entries	to get and retrieve	the	interface	index.
-
-	// Make	an initial call	to GetIfTable	to get the
-	// necessary size	into dwSize
-	if (GetIfTable(pIfTable, &dwSize,	0) ==	ERROR_INSUFFICIENT_BUFFER) {
-			free(pIfTable);
-			pIfTable = (MIB_IFTABLE	*) malloc(dwSize);
-			if (pIfTable ==	NULL)	
-			{
-					printf("Error	allocating memory\n");
-					return 0;
-			}
-	}
-	//	Make a second	call to	GetIfTable to	get	the	actual
-	// data	we want.
-	if ((dwRetVal = GetIfTable(pIfTable, &dwSize,	0))	== NO_ERROR) 
-	{
-		if (pIfTable->dwNumEntries > 0)	
-		{
-			pIfRow = (MIB_IFROW	*) malloc(sizeof (MIB_IFROW));
-			if (pIfRow ==	NULL)	
-			{
-					printf("Error allocating memory\n");
-					if (pIfTable != NULL)	
-					{
-						free(pIfTable);
-						pIfTable = NULL;
-					}
-					return 0;
-			}
-
-			int	limit	=	MAC_ADDRESS_BYTES;
-			memcpy(node_id,	"\0\0\0\0\0\0",	limit);	// zero	out	array	of bytes	 
-			for	(i = 0;	i < (int) pIfTable->dwNumEntries; i++) 
-			{
-				pIfRow->dwIndex	= pIfTable->table[i].dwIndex;
-				if ((dwRetVal = GetIfEntry(pIfRow)) == NO_ERROR) 
-				{
-					switch (pIfRow->dwType)	
-					{
-						case IF_TYPE_ETHERNET_CSMACD:
-						case IF_TYPE_IEEE80211:		 
-							 limit = min((int) pIfRow->dwPhysAddrLen, limit);
-							 if	(pIfRow->dwPhysAddrLen == 0)
-									 break;
-							 memcpy(node_id, (UCHAR *)&pIfRow->bPhysAddr[0], limit);		 //	just incase	the	PhysAddr is	not	the	expected MAC_Address size
-							 free(pIfTable);
-							 return 1;	//return first hardware	device found.	
-							break;
-
-						case IF_TYPE_OTHER:
-						case IF_TYPE_PPP:										 
-						case IF_TYPE_SOFTWARE_LOOPBACK:										 
-						case IF_TYPE_ISO88025_TOKENRING:										
-						case IF_TYPE_IEEE1394:																		
-						case IF_TYPE_ATM:										 
-						case IF_TYPE_TUNNEL:										
-								default:
-									break;
-					}
-				}
-			}
-		}
-	}
-	free(pIfTable);
-	return 0;
+// static
+S32 LLUUID::getNodeID(unsigned char * node_id)
+{
+	  ASTAT Adapter;
+      NCB Ncb;
+      UCHAR uRetCode;
+      LANA_ENUM   lenum;
+      int      i;
+	  int retval = 0;
+
+      memset( &Ncb, 0, sizeof(Ncb) );
+      Ncb.ncb_command = NCBENUM;
+      Ncb.ncb_buffer = (UCHAR *)&lenum;
+      Ncb.ncb_length = sizeof(lenum);
+      uRetCode = Netbios( &Ncb );
+ //     printf( "The NCBENUM return code is: 0x%x \n", uRetCode );
+
+      for(i=0; i < lenum.length ;i++)
+      {
+          memset( &Ncb, 0, sizeof(Ncb) );
+          Ncb.ncb_command = NCBRESET;
+          Ncb.ncb_lana_num = lenum.lana[i];
+
+          uRetCode = Netbios( &Ncb );
+ //         printf( "The NCBRESET on LANA %d return code is: 0x%x \n",
+ //                 lenum.lana[i], uRetCode );
+
+          memset( &Ncb, 0, sizeof (Ncb) );
+          Ncb.ncb_command = NCBASTAT;
+          Ncb.ncb_lana_num = lenum.lana[i];
+
+          strcpy( (char *)Ncb.ncb_callname,  "*              " );		/* Flawfinder: ignore */
+          Ncb.ncb_buffer = (unsigned char *)&Adapter;
+          Ncb.ncb_length = sizeof(Adapter);
+
+          uRetCode = Netbios( &Ncb );
+//          printf( "The NCBASTAT on LANA %d return code is: 0x%x \n",
+//                 lenum.lana[i], uRetCode );
+          if ( uRetCode == 0 )
+          {
+//            printf( "The Ethernet Number on LANA %d is: %02x%02x%02x%02x%02x%02x\n",
+//	 			  lenum.lana[i],
+//                  Adapter.adapt.adapter_address[0],
+//                  Adapter.adapt.adapter_address[1],
+//                  Adapter.adapt.adapter_address[2],
+//                  Adapter.adapt.adapter_address[3],
+//                  Adapter.adapt.adapter_address[4],
+//                  Adapter.adapt.adapter_address[5] );
+			memcpy(node_id,Adapter.adapt.adapter_address,6);		/* Flawfinder: ignore */
+			retval = 1;
+
+          }
+	  }
+	return retval;
 }
 
 #elif LL_DARWIN
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 91e11b8c0d9887cb2d819380430dc986fabe5402..024e17a7779a487ef8e9022e3ec5cda7104a4327 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -89,6 +89,10 @@ S32 gCurlMultiCount = 0;
 std::vector<LLMutex*> LLCurl::sSSLMutex;
 std::string LLCurl::sCAPath;
 std::string LLCurl::sCAFile;
+// Verify SSL certificates by default (matches libcurl default). The ability
+// to alter this flag is only to allow us to suppress verification if it's
+// broken for some reason.
+bool LLCurl::sSSLVerify = true;
 
 //static
 void LLCurl::setCAPath(const std::string& path)
@@ -102,6 +106,18 @@ void LLCurl::setCAFile(const std::string& file)
 	sCAFile = file;
 }
 
+//static
+void LLCurl::setSSLVerify(bool verify)
+{
+	sSSLVerify = verify;
+}
+
+//static
+bool LLCurl::getSSLVerify()
+{
+	return sSSLVerify;
+}
+
 //static
 std::string LLCurl::getVersionString()
 {
@@ -465,7 +481,8 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 	setErrorBuffer();
 	setCA();
 
-	setopt(CURLOPT_SSL_VERIFYPEER, true);
+	setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
+	setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
 	setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
 
 	setoptString(CURLOPT_URL, url);
@@ -895,15 +912,6 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd
 	}
 }
 
-void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata)
-{
-	if (mEasy)
-	{
-		mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback);
-		mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata);
-	}
-}
-
 void LLCurlEasyRequest::slist_append(const char* str)
 {
 	if (mEasy)
@@ -1053,4 +1061,3 @@ void LLCurl::cleanupClass()
 #endif
 	curl_global_cleanup();
 }
-
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index b6a637ae5b4966f6d9c6cf53592b64fc1409da1e..caf02cccd90bc6c70ab4f755485b6b355bb2986d 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -157,6 +157,16 @@ class LLCurl
 	 */
 	static const std::string& getCAPath() { return sCAPath; }
 
+	/**
+	 * @ brief Set flag controlling whether to verify HTTPS certs.
+	 */
+	static void setSSLVerify(bool verify);
+
+	/**
+	 * @ brief Get flag controlling whether to verify HTTPS certs.
+	 */
+	static bool getSSLVerify();
+
 	/**
 	 * @ brief Initialize LLCurl class
 	 */
@@ -182,6 +192,7 @@ class LLCurl
 private:
 	static std::string sCAPath;
 	static std::string sCAFile;
+	static bool sSSLVerify;
 };
 
 namespace boost
@@ -229,7 +240,6 @@ class LLCurlEasyRequest
 	void setHeaderCallback(curl_header_callback callback, void* userdata);
 	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 char* str);
 	void sendRequest(const std::string& url);
 	void requestComplete();
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 345b76d1a1940d95c97432707d16fd4b586ce55d..dd56e18caf8fbe26e60b61d0167cdcc3d20ee12b 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -31,7 +31,7 @@
  */
 
 #include "linden_common.h"
-#include <openssl/x509_vfy.h>
+
 #include "llhttpclient.h"
 
 #include "llassetstorage.h"
@@ -46,10 +46,7 @@
 #include "message.h"
 #include <curl/curl.h>
 
-
 const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
-LLURLRequest::SSLCertVerifyCallback LLHTTPClient::mCertVerifyCallback = NULL;
-
 ////////////////////////////////////////////////////////////////////////////
 
 // Responder class moved to LLCurl
@@ -209,19 +206,13 @@ namespace
 	LLPumpIO* theClientPump = NULL;
 }
 
-void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback)
-{
-	LLHTTPClient::mCertVerifyCallback = callback;
-}
-
 static void request(
 	const std::string& url,
 	LLURLRequest::ERequestAction method,
 	Injector* body_injector,
 	LLCurl::ResponderPtr responder,
 	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
-	const LLSD& headers = LLSD()
-    )
+	const LLSD& headers = LLSD())
 {
 	if (!LLHTTPClient::hasPump())
 	{
@@ -231,7 +222,7 @@ static void request(
 	LLPumpIO::chain_t chain;
 
 	LLURLRequest* req = new LLURLRequest(method, url);
-	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
+	req->checkRootCertificate(LLCurl::getSSLVerify());
 
 	
 	lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "
@@ -426,6 +417,7 @@ static LLSD blocking_request(
 	std::string body_str;
 	
 	// other request method checks root cert first, we skip?
+	//req->checkRootCertificate(true);
 	
 	// * Set curl handle options
 	curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1);	// don't use SIGALRM for timeouts
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index 8afbc9e0fc274f84dfbb5bd85c9b6694d4dfe3fc..3d0646e5fe9b53b436f5fc9c7166ca47845b767d 100644
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -40,8 +40,7 @@
 #include <string>
 
 #include <boost/intrusive_ptr.hpp>
-#include <openssl/x509_vfy.h>
-#include "llurlrequest.h"
+
 #include "llassettype.h"
 #include "llcurl.h"
 #include "lliopipe.h"
@@ -62,7 +61,6 @@ class LLHTTPClient
 	typedef LLCurl::Responder Responder;
 	typedef LLCurl::ResponderPtr ResponderPtr;
 
-	
 	/** @name non-blocking API */
 	//@{
 	static void head(
@@ -157,12 +155,7 @@ class LLHTTPClient
 	static void setPump(LLPumpIO& pump);
 		///< must be called before any of the above calls are made
 	static bool hasPump();
-
-	static void setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback);
-	static  LLURLRequest::SSLCertVerifyCallback getCertVerifyCallback() { return mCertVerifyCallback; }
-
-protected:
-	static LLURLRequest::SSLCertVerifyCallback mCertVerifyCallback;
+		///< for testing
 };
 
 #endif // LL_LLHTTPCLIENT_H
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 1e76d108289537e0564597ad1e11b2c63579d136..4e7ceff9843ffcc0d16b6c7795d0cbcb1bb09a5f 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -36,8 +36,7 @@
 #include "llurlrequest.h"
 
 #include <algorithm>
-#include <openssl/x509_vfy.h>
-#include <openssl/ssl.h>
+
 #include "llcurl.h"
 #include "llioutil.h"
 #include "llmemtype.h"
@@ -57,8 +56,6 @@ const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
 
 static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
 
-
-
 /**
  * class LLURLRequestDetail
  */
@@ -75,7 +72,6 @@ class LLURLRequestDetail
 	U32 mBodyLimit;
 	S32 mByteAccumulator;
 	bool mIsBodyLimitSet;
-	LLURLRequest::SSLCertVerifyCallback mSSLVerifyCallback;
 };
 
 LLURLRequestDetail::LLURLRequestDetail() :
@@ -84,8 +80,7 @@ LLURLRequestDetail::LLURLRequestDetail() :
 	mLastRead(NULL),
 	mBodyLimit(0),
 	mByteAccumulator(0),
-	mIsBodyLimitSet(false),
-    mSSLVerifyCallback(NULL)
+	mIsBodyLimitSet(false)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	mCurlRequest = new LLCurlEasyRequest();
@@ -99,36 +94,6 @@ LLURLRequestDetail::~LLURLRequestDetail()
 	mLastRead = NULL;
 }
 
-void LLURLRequest::setSSLVerifyCallback(SSLCertVerifyCallback callback, void *param)
-{
-	mDetail->mSSLVerifyCallback = callback;
-	mDetail->mCurlRequest->setSSLCtxCallback(LLURLRequest::_sslCtxCallback, (void *)this);
-	mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, true);
-	mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, 2);	
-}
-
-
-// _sslCtxFunction
-// Callback function called when an SSL Context is created via CURL
-// used to configure the context for custom cert validation
-
-CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param)
-{	
-	LLURLRequest *req = (LLURLRequest *)param;
-	if(req == NULL || req->mDetail->mSSLVerifyCallback == NULL)
-	{
-		SSL_CTX_set_cert_verify_callback((SSL_CTX *)sslctx, NULL, NULL);
-		return CURLE_OK;
-	}
-	SSL_CTX * ctx = (SSL_CTX *) sslctx;
-	// disable any default verification for server certs
-	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
-	// set the verification callback.
-	SSL_CTX_set_cert_verify_callback(ctx, req->mDetail->mSSLVerifyCallback, (void *)req);
-	// the calls are void
-	return CURLE_OK;
-	
-}
 
 /**
  * class LLURLRequest
@@ -183,11 +148,6 @@ void LLURLRequest::setURL(const std::string& url)
 	mDetail->mURL = url;
 }
 
-std::string LLURLRequest::getURL() const
-{
-	return mDetail->mURL;
-}
-
 void LLURLRequest::addHeader(const char* header)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
@@ -200,6 +160,13 @@ void LLURLRequest::setBodyLimit(U32 size)
 	mDetail->mIsBodyLimitSet = true;
 }
 
+void LLURLRequest::checkRootCertificate(bool check)
+{
+	mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, (check? TRUE : FALSE));
+	mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, (check? 2 : 0));
+	mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
+}
+
 void LLURLRequest::setCallback(LLURLRequestComplete* callback)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 69fd22e5928ebaba6980fad8e0547cf5de491c50..cb3c46644062cbb26530cc4fbc4e13c90a99309e 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -44,8 +44,6 @@
 #include "lliopipe.h"
 #include "llchainio.h"
 #include "llerror.h"
-#include <openssl/x509_vfy.h>
-#include "llcurl.h"
 
 
 extern const std::string CONTEXT_REQUEST;
@@ -74,8 +72,6 @@ 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.
 	 */
@@ -129,7 +125,7 @@ class LLURLRequest : public LLIOPipe
 	 * 
 	 */
 	void setURL(const std::string& url);
-	std::string getURL() const;
+
 	/** 
 	 * @brief Add a header to the http post.
 	 *
@@ -147,9 +143,8 @@ class LLURLRequest : public LLIOPipe
 	 * Set whether request will check that remote server
 	 * certificates are signed by a known root CA when using HTTPS.
 	 */
-	void setSSLVerifyCallback(SSLCertVerifyCallback callback, void * param);
+	void checkRootCertificate(bool check);
 
-	
 	/**
 	 * @brief Return at most size bytes of body.
 	 *
@@ -194,7 +189,6 @@ class LLURLRequest : public LLIOPipe
 	 * @brief Give this pipe a chance to handle a generated error
 	 */
 	virtual EStatus handleError(EStatus status, LLPumpIO* pump);
-
 	
 protected:
 	/** 
@@ -223,8 +217,6 @@ class LLURLRequest : public LLIOPipe
 	 S32 mRequestTransferedBytes;
 	 S32 mResponseTransferedBytes;
 
-	static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param);
-	
 private:
 	/** 
 	 * @brief Initialize the object. Called during construction.
@@ -372,6 +364,62 @@ class LLURLRequestComplete : public LLIOPipe
 };
 
 
+/** 
+ * @class LLURLRequestClientFactory
+ * @brief Template class to build url request based client chains 
+ *
+ * This class eases construction of a basic sd rpc client. Here is an
+ * example of it's use:
+ * <code>
+ *  class LLUsefulService : public LLService { ... }<br>
+ *  LLService::registerCreator(<br>
+ *    "useful",<br>
+ *    LLService::creator_t(new LLURLRequestClientFactory<LLUsefulService>))<br>
+ * </code>
+ *
+ * This class should work, but I never got around to using/testing it.
+ *
+ */
+#if 0
+template<class Client>
+class LLURLRequestClientFactory : public LLChainIOFactory
+{
+public:
+	LLURLRequestClientFactory(LLURLRequest::ERequestAction action) {}
+	LLURLRequestClientFactory(
+		LLURLRequest::ERequestAction action,
+		const std::string& fixed_url) :
+		mAction(action),
+		mURL(fixed_url)
+	{
+	}
+	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
+	{
+		lldebugs << "LLURLRequestClientFactory::build" << llendl;
+		LLIOPipe::ptr_t service(new Client);
+		chain.push_back(service);
+		LLURLRequest* http(new LLURLRequest(mAction));
+		LLIOPipe::ptr_t http_pipe(http);
+		// *FIX: how do we know the content type?
+		//http->addHeader("Content-Type: text/llsd");
+		if(mURL.empty())
+		{
+			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
+		}
+		else
+		{
+			http->setURL(mURL);
+		}
+		chain.push_back(http_pipe);
+		chain.push_back(service);
+		return true;
+	}
+
+protected:
+	LLURLRequest::ERequestAction mAction;
+	std::string mURL;
+};
+#endif
 
 /**
  * External constants
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index c38e38c90007614e4011cfeebf311276ac98631e..e8e345967309ac3f6ecceba36391a0899f70c846 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -41,9 +41,6 @@
 #include "lltrans.h"
 #include "lluicolortable.h"
 
-#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
-
-
 LLUrlEntryBase::LLUrlEntryBase() :
 	mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
 	mDisabledLink(false)
@@ -306,11 +303,10 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
 //
 // LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
 // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
-// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
 //
 LLUrlEntryAgent::LLUrlEntryAgent()
 {
-	mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/\\w+",
+	mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/\\w+",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_agent.xml";
 	mIcon = "Generic_Person";
@@ -422,11 +418,10 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
 // LLUrlEntryGroup Describes a Second Life group Url, e.g.,
 // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
 // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect
-// x-grid-location-info://lincoln.lindenlab.com/app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect
 //
 LLUrlEntryGroup::LLUrlEntryGroup()
 {
-	mPattern = boost::regex(APP_HEADER_REGEX "/group/[\\da-f-]+/\\w+",
+	mPattern = boost::regex("secondlife:///app/group/[\\da-f-]+/\\w+",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_group.xml";
 	mIcon = "Generic_Group";
@@ -487,8 +482,7 @@ LLUrlEntryInventory::LLUrlEntryInventory()
 	//*TODO: add supporting of inventory item names with whitespaces
 	//this pattern cann't parse for example 
 	//secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces&param2=value
-	//x-grid-location-info://lincoln.lindenlab.com/app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces&param2=value
-	mPattern = boost::regex(APP_HEADER_REGEX "/inventory/[\\da-f-]+/\\w+\\S*",
+	mPattern = boost::regex("secondlife:///app/inventory/[\\da-f-]+/\\w+\\S*",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_inventory.xml";
 }
@@ -502,11 +496,10 @@ std::string LLUrlEntryInventory::getLabel(const std::string &url, const LLUrlLab
 ///
 /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
 /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
-/// x-grid-location-info://lincoln.lindenlab.com/app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
 ///
 LLUrlEntryParcel::LLUrlEntryParcel()
 {
-	mPattern = boost::regex(APP_HEADER_REGEX "/parcel/[\\da-f-]+/about",
+	mPattern = boost::regex("secondlife:///app/parcel/[\\da-f-]+/about",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_parcel.xml";
 	mTooltip = LLTrans::getString("TooltipParcelUrl");
@@ -522,7 +515,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC
 //
 LLUrlEntryPlace::LLUrlEntryPlace()
 {
-	mPattern = boost::regex("((x-grid-location-info://[-\\w\\.]+/region/)|(secondlife://))\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?",
+	mPattern = boost::regex("secondlife://\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_slurl.xml";
 	mTooltip = LLTrans::getString("TooltipSLURL");
@@ -567,11 +560,10 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
 //
 // LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
 // secondlife:///app/teleport/Ahern/50/50/50/
-// x-grid-location-info://lincoln.lindenlab.com/app/teleport/Ahern/50/50/50/
 //
 LLUrlEntryTeleport::LLUrlEntryTeleport()
 {
-	mPattern = boost::regex(APP_HEADER_REGEX "/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*",
+	mPattern = boost::regex("secondlife:///app/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_teleport.xml";
 	mTooltip = LLTrans::getString("TooltipTeleportUrl");
@@ -589,12 +581,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
 	LLURI uri(url);
 	LLSD path_array = uri.pathArray();
 	S32 path_parts = path_array.size();
-	std::string host = uri.hostName();
-	std::string label = LLTrans::getString("SLurlLabelTeleport");
-	if (!host.empty())
-	{
-		label += " " + host;
-	}
+	const std::string label = LLTrans::getString("SLurlLabelTeleport");
 	if (path_parts == 6)
 	{
 		// handle teleport url with (X,Y,Z) coordinates
@@ -693,7 +680,7 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const
 //
 LLUrlEntryWorldMap::LLUrlEntryWorldMap()
 {
-	mPattern = boost::regex(APP_HEADER_REGEX "/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+	mPattern = boost::regex("secondlife:///app/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_map.xml";
 	mTooltip = LLTrans::getString("TooltipMapUrl");
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 4463b6cc6fa23dda15e44d48754c022419b88c84..cbb303a059254f864257b81fba4ab0f8e9d670c4 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -286,13 +286,6 @@ namespace tut
 				  "XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar",
 				  "secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar");
 
-		testRegex("Standalone Agent Url ", url,
-				  "x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about",
-				  "x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");		
-
-		testRegex("Standalone Agent Url Multicase with Text", url,
-				  "M x-grid-location-info://lincoln.lindenlab.com/app/AGENT/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about M",
-				  "x-grid-location-info://lincoln.lindenlab.com/app/AGENT/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");		
 	}
 
 	template<> template<>
@@ -322,15 +315,6 @@ namespace tut
 		testRegex("Group Url multicase", url,
 				  "XXX secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About XXX",
 				  "secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About");
-		
-		testRegex("Standalone Group Url ", url,
-				  "x-grid-location-info://lincoln.lindenlab.com/app/group/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about",
-				  "x-grid-location-info://lincoln.lindenlab.com/app/group/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");		
-		
-		testRegex("Standalone Group Url Multicase ith Text", url,
-				  "M x-grid-location-info://lincoln.lindenlab.com/app/GROUP/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about M",
-				  "x-grid-location-info://lincoln.lindenlab.com/app/GROUP/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");		
-		
 	}
 
 	template<> template<>
@@ -377,11 +361,7 @@ namespace tut
 		// DEV-35459: SLURLs and teleport Links not parsed properly
 		testRegex("SLURL with quote", url,
 				  "XXX secondlife://A'ksha%20Oasis/41/166/701 XXX",
-			          "secondlife://A%27ksha%20Oasis/41/166/701");
-		
-		testRegex("Standalone All Hands (50,50) [2] with text", url,
-				  "XXX x-grid-location-info://lincoln.lindenlab.com/region/All%20Hands/50/50/50 XXX",
-				  "x-grid-location-info://lincoln.lindenlab.com/region/All%20Hands/50/50/50");		
+				  "secondlife://A%27ksha%20Oasis/41/166/701");
 	}
 
 	template<> template<>
@@ -481,10 +461,6 @@ namespace tut
 		testRegex("Teleport url with quote", url,
 				  "XXX secondlife:///app/teleport/A'ksha%20Oasis/41/166/701 XXX",
 				  "secondlife:///app/teleport/A%27ksha%20Oasis/41/166/701");
-		
-		testRegex("Standalone All Hands", url,
-				  "XXX x-grid-location-info://lincoln.lindenlab.com/app/teleport/All%20Hands/50/50/50 XXX",
-				  "x-grid-location-info://lincoln.lindenlab.com/app/teleport/All%20Hands/50/50/50");		
 	}
 
 	template<> template<>
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index b4ee42ef3a6f0a862a4aaf44b294607ef56817ce..da4abde451f203a3204464323d119febdc4abbd3 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -459,6 +459,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
 	}
 
 	//llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl;
+
 	return expanded_filename;
 }
 
@@ -564,23 +565,27 @@ std::string LLDir::getForbiddenFileChars()
 	return "\\/:*?\"<>|";
 }
 
-void LLDir::setLindenUserDir(const std::string &username)
+void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
 {
-	// if the username isn't set, that's bad
-	if (!username.empty())
+	// if both first and last aren't set, that's bad.
+	if (!first.empty() && !last.empty())
 	{
 		// some platforms have case-sensitive filesystems, so be
 		// utterly consistent with our firstname/lastname case.
-		std::string userlower(username);
-		LLStringUtil::toLower(userlower);
-		LLStringUtil::replaceChar(userlower, ' ', '_');
+		std::string firstlower(first);
+		LLStringUtil::toLower(firstlower);
+		std::string lastlower(last);
+		LLStringUtil::toLower(lastlower);
 		mLindenUserDir = getOSUserAppDir();
 		mLindenUserDir += mDirDelimiter;
-		mLindenUserDir += userlower;
+		mLindenUserDir += firstlower;
+		mLindenUserDir += "_";
+		mLindenUserDir += lastlower;
+		llinfos << "Got name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
 	}
 	else
 	{
-		llerrs << "NULL name for LLDir::setLindenUserDir" << llendl;
+		llerrs << "Invalid name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
 	}
 
 	dumpCurrentDirectories();	
@@ -598,25 +603,27 @@ void LLDir::setChatLogsDir(const std::string &path)
 	}
 }
 
-void LLDir::setPerAccountChatLogsDir(const std::string &username)
+void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last)
 {
 	// if both first and last aren't set, assume we're grabbing the cached dir
-	if (!username.empty())
+	if (!first.empty() && !last.empty())
 	{
 		// some platforms have case-sensitive filesystems, so be
 		// utterly consistent with our firstname/lastname case.
-		std::string userlower(username);
-		LLStringUtil::toLower(userlower);
-		LLStringUtil::replaceChar(userlower, ' ', '_');
+		std::string firstlower(first);
+		LLStringUtil::toLower(firstlower);
+		std::string lastlower(last);
+		LLStringUtil::toLower(lastlower);
 		mPerAccountChatLogsDir = getChatLogsDir();
 		mPerAccountChatLogsDir += mDirDelimiter;
-		mPerAccountChatLogsDir += userlower;
+		mPerAccountChatLogsDir += firstlower;
+		mPerAccountChatLogsDir += "_";
+		mPerAccountChatLogsDir += lastlower;
 	}
 	else
 	{
-		llerrs << "NULL name for LLDir::setPerAccountChatLogsDir" << llendl;
+		llwarns << "Invalid name for LLDir::setPerAccountChatLogsDir" << llendl;
 	}
-	
 }
 
 void LLDir::setSkinFolder(const std::string &skin_folder)
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 05d5efc66feba5f37aacc0257b9694f5a4d9ccbb..9067d75bacad7a978d085edf0898ea7ab312b385 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -137,8 +137,8 @@ class LLDir
 	static std::string getForbiddenFileChars();
 
 	virtual void setChatLogsDir(const std::string &path);		// Set the chat logs dir to this user's dir
-	virtual void setPerAccountChatLogsDir(const std::string &username);		// Set the per user chat log directory.
-	virtual void setLindenUserDir(const std::string &username);		// Set the linden user dir to this user's dir
+	virtual void setPerAccountChatLogsDir(const std::string &first, const std::string &last);		// Set the per user chat log directory.
+	virtual void setLindenUserDir(const std::string &first, const std::string &last);		// Set the linden user dir to this user's dir
 	virtual void setSkinFolder(const std::string &skin_folder);
 	virtual bool setCacheDir(const std::string &path);
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e0a31875c899a1134e2a9f42c6470608fdde1f2f..47fde08a9de671c2a511d154b2f26f6def00808a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -7,7 +7,6 @@ include(Boost)
 include(BuildVersion)
 include(DBusGlib)
 include(DirectX)
-include(OpenSSL)
 include(DragDrop)
 include(ELFIO)
 include(FMOD)
@@ -372,8 +371,6 @@ set(viewer_SOURCE_FILES
     llscrollingpanelparam.cpp
     llsearchcombobox.cpp
     llsearchhistory.cpp
-    llsecapi.cpp
-    llsechandler_basic.cpp
     llselectmgr.cpp
     llsidepanelappearance.cpp
     llsidepanelinventory.cpp
@@ -448,6 +445,7 @@ set(viewer_SOURCE_FILES
     llurldispatcherlistener.cpp
     llurlhistory.cpp
     llurllineeditorctrl.cpp
+    llurlsimstring.cpp
     llurlwhitelist.cpp
     llvectorperfoptions.cpp
     llversioninfo.cpp
@@ -514,9 +512,7 @@ set(viewer_SOURCE_FILES
     llvoground.cpp
     llvoicechannel.cpp
     llvoiceclient.cpp
-    llvoicedw.cpp
     llvoicevisualizer.cpp
-    llvoicevivox.cpp
     llvoinventorylistener.cpp
     llvopartgroup.cpp
     llvosky.cpp
@@ -876,8 +872,6 @@ set(viewer_HEADER_FILES
     llscrollingpanelparam.h
     llsearchcombobox.h
     llsearchhistory.h
-    llsecapi.h
-    llsechandler_basic.h
     llselectmgr.h
     llsidepanelappearance.h
     llsidepanelinventory.h
@@ -954,6 +948,7 @@ set(viewer_HEADER_FILES
     llurldispatcherlistener.h
     llurlhistory.h
     llurllineeditorctrl.h
+    llurlsimstring.h
     llurlwhitelist.h
     llvectorperfoptions.h
     llversioninfo.h
@@ -1017,9 +1012,7 @@ set(viewer_HEADER_FILES
     llvoground.h
     llvoicechannel.h
     llvoiceclient.h
-    llvoicedw.h
     llvoicevisualizer.h
-    llvoicevivox.h
     llvoinventorylistener.h
     llvopartgroup.h
     llvosky.h
@@ -1410,8 +1403,8 @@ if (WINDOWS)
         ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll
         ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll
         )
-     endif(USE_GOOGLE_PERFTOOLS)
- 
+    endif(USE_GOOGLE_PERFTOOLS)
+  
 
     set(COPY_INPUT_DEPENDECIES
       # The following commented dependencies are determined at variably at build time. Can't do this here.
@@ -1628,8 +1621,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${WINDOWS_LIBRARIES}
     ${XMLRPCEPI_LIBRARIES}
     ${ELFIO_LIBRARIES}
-    ${OPENSSL_LIBRARIES}
-    ${CRYPTO_LIBRARIES}
     ${LLLOGIN_LIBRARIES}
     ${GOOGLE_PERFTOOLS_LIBRARIES}
     )
@@ -1806,43 +1797,6 @@ if (LL_TESTS)
     "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py"
     )
 
-  set(test_libs 
-    ${LLMESSAGE_LIBRARIES} 
-    ${WINDOWS_LIBRARIES} 
-    ${LLVFS_LIBRARIES}
-    ${LLMATH_LIBRARIES}
-    ${LLCOMMON_LIBRARIES} 
-    ${GOOGLEMOCK_LIBRARIES}
-    ${OPENSSL_LIBRARIES}
-    ${CRYPTO_LIBRARIES}
-  )
-
-    LL_ADD_INTEGRATION_TEST(llsechandler_basic
-     llsechandler_basic.cpp
-    "${test_libs}"
-    )
-
-  LL_ADD_INTEGRATION_TEST(llsecapi
-     llsecapi.cpp
-    "${test_libs}"
-    )
-
-  set(llslurl_test_sources
-      llslurl.cpp
-      llviewernetwork.cpp
-  )
-
-
-  LL_ADD_INTEGRATION_TEST(llslurl
-     "${llslurl_test_sources}"
-    "${test_libs}"
-    )
-
-  LL_ADD_INTEGRATION_TEST(llviewernetwork
-     llviewernetwork.cpp
-    "${test_libs}"
-    )
-
   #ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
   #ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
   #ADD_VIEWER_BUILD_TEST(llworldmap viewer)
@@ -1850,7 +1804,6 @@ if (LL_TESTS)
   #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
   #ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
   #ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
-
 endif (LL_TESTS)
 
 
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 7436c5642eda2160058c4ebfa7a9adde86b6342e..4cb01a0f338759a56d18093eadfb9a75691592b3 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -18,33 +18,6 @@
 	<string>APPL</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
-        <key>CFBundleDocumentTypes</key>
-        <array>
-                <dict>
-                        <key>CFBundleTypeExtensions</key>
-                        <array>
-                                <string>slurl</string>
-                        </array>
-                        <key>CFBundleTypeIconFile</key>
-                        <string>seconlife</string>
-                        <key>CFBundleTypeMIMETypes</key>
-                        <array>
-                                <string>application/x-grid-location-info</string>
-                        </array>
-                        <key>CFBundleTypeName</key>
-                        <string>Secondlife SLURL</string>
-			<key>CFBundleTypeOSTypes</key>
-			<array>
-			  <string>SLRL</string>
-			</array>
-                        <key>CFBundleTypeRole</key>
-                        <string>Viewer</string>
-                        <key>LSTypeIsPackage</key>
-			<true/>
-                        <key>NSDocumentClass</key>
-                        <string>SecondLifeSLURL</string>
-                </dict>
-        </array>
 	<key>CFBundleURLTypes</key>
 	<array>
 		<dict>
@@ -53,7 +26,6 @@
 			<key>CFBundleURLSchemes</key>
 			<array>
 				<string>secondlife</string>
-				<string>x-grid-location-info</string>
 			</array>
 			<key>LSIsAppleDefaultForScheme</key>
 			<true/>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 442cd5d31e1b38c53695ee3e04368a5cb402a14b..30049b73ea1edf53106ff6cade0020297144ae68 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1264,17 +1264,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>CertStore</key>
-    <map>
-      <key>Comment</key>
-      <string>Specifies the Certificate Store for certificate trust verification</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>default</string>
-    </map>
     <key>ChatBarStealsFocus</key>
     <map>
       <key>Comment</key>
@@ -1651,17 +1640,6 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>CurrentGrid</key>
-    <map>
-      <key>Comment</key>
-      <string>Currently Selected Grid</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string></string>
-    </map>
     <key>CustomServer</key>
     <map>
       <key>Comment</key>
@@ -2388,29 +2366,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-	<key>DefaultFemaleAvatar</key>
-	<map>
-	  <key>Comment</key>
-	  <string>Default Female Avatar</string>
-	  <key>Persist</key>
-	  <integer>1</integer>
-	  <key>Type</key>
-	  <string>String</string>
-	  <key>Value</key>
-	  <string>Female Shape &amp; Outfit</string>
-	</map>
-	<key>DefaultMaleAvatar</key>
-	<map>
-	  <key>Comment</key>
-	  <string>Default Male Avatar</string>
-	  <key>Persist</key>
-	  <integer>1</integer>
-	  <key>Type</key>
-	  <string>String</string>
-	  <key>Value</key>
-	  <string>Male Shape &amp; Outfit</string>
-	</map>
-
     <key>DefaultObjectTexture</key>
     <map>
       <key>Comment</key>
@@ -3487,7 +3442,7 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>1</integer>
+      <integer>0</integer>
     </map>
     <key>ForceMandatoryUpdate</key>
     <map>
@@ -7741,17 +7696,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>SecondLifeEnterprise</key>
-    <map>
-      <key>Comment</key>
-      <string>Enables Second Life Enterprise features</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>	
     <key>SelectMovableOnly</key>
     <map>
       <key>Comment</key>
@@ -8556,7 +8500,7 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>1</integer>
+      <integer>0</integer>
     </map>
     <key>ShowTangentBasis</key>
     <map>
@@ -10449,17 +10393,6 @@
       <key>Value</key>
       <string></string>
     </map>
-    <key>VivoxDebugSIPURIHostName</key>
-    <map>
-      <key>Comment</key>
-      <string>Hostname portion of vivox SIP URIs (empty string for the default).</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string></string>
-    </map>
     <key>VivoxDebugVoiceAccountServerURI</key>
     <map>
       <key>Comment</key>
@@ -10471,28 +10404,6 @@
       <key>Value</key>
       <string></string>
     </map>
-    <key>VivoxVoiceHost</key>
-    <map>
-      <key>Comment</key>
-      <string>Client SLVoice host to connect to</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>127.0.0.1</string>
-    </map>
-    <key>VivoxVoicePort</key>
-    <map>
-      <key>Comment</key>
-      <string>Client SLVoice port to connect to</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>U32</string>
-      <key>Value</key>
-      <integer>44125</integer>
-    </map>
     <key>VoiceCallsFriendsOnly</key>
     <map>
       <key>Comment</key>
@@ -10625,17 +10536,6 @@
       <key>Value</key>
       <string>Default</string>
     </map>
-    <key>VoiceLogFile</key>
-    <map>
-      <key>Comment</key>
-      <string>Log file to use when launching the voice daemon</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string></string>
-    </map>
     <key>VoiceOutputAudioDevice</key>
     <map>
       <key>Comment</key>
@@ -10680,17 +10580,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>VoiceServerType</key>
-    <map>
-      <key>Comment</key>
-      <string>The type of voice server to connect to.</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>vivox</string>
-    </map>
     <key>WLSkyDetail</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index b7b4c540012461948aa2112cf31014fa0521f514..a7322749ca835d4c4be7699a7a207acbe8db1a34 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -797,12 +797,6 @@ WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" '"$INSTDIR\$INSTEXE"'
 ;; URL param must be last item passed to viewer, it ignores subsequent params
 ;; to avoid parameter injection attacks.
 WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"'
-WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info"(default)" "URL:Second Life"
-WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" ""
-WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$INSTEXE"'
-;; URL param must be last item passed to viewer, it ignores subsequent params
-;; to avoid parameter injection attacks.
-WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"'
 
 ; write out uninstaller
 WriteUninstaller "$INSTDIR\uninst.exe"
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 37d1bd15e15d6f2281401677719d3008f86fde6d..f434782977709ed6b93756d949b1191fbb49d9d4 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3231,7 +3231,7 @@ bool LLAgent::teleportCore(bool is_local)
 	
 	// MBW -- Let the voice client know a teleport has begun so it can leave the existing channel.
 	// This was breaking the case of teleporting within a single sim.  Backing it out for now.
-//	LLVoiceClient::getInstance()->leaveChannel();
+//	gVoiceClient->leaveChannel();
 	
 	return true;
 }
@@ -3375,7 +3375,7 @@ void LLAgent::setTeleportState(ETeleportState state)
 	if (mTeleportState == TELEPORT_MOVING)
 	{
 		// We're outa here. Save "back" slurl.
-		LLAgentUI::buildSLURL(mTeleportSourceSLURL);
+		mTeleportSourceSLURL = LLAgentUI::buildSLURL();
 	}
 	else if(mTeleportState == TELEPORT_ARRIVING)
 	{
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 32f9b001356f592cec6b29ca9edc117a48d7df5f..a460077b7e7ae119a3b5970084f82fa86594f113 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -42,7 +42,6 @@
 #include "llpointer.h"
 #include "lluicolor.h"
 #include "llvoavatardefines.h"
-#include "llslurl.h"
 
 extern const BOOL 	ANIMATE;
 extern const U8 	AGENT_STATE_TYPING;  // Typing indication
@@ -515,13 +514,13 @@ class LLAgent : public LLOldEvents::LLObservable
 
 public:
 	static void 	parseTeleportMessages(const std::string& xml_filename);
-	const void getTeleportSourceSLURL(LLSLURL& slurl) const { slurl = mTeleportSourceSLURL; }
+	const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
 public:
 	// ! TODO ! Define ERROR and PROGRESS enums here instead of exposing the mappings.
 	static std::map<std::string, std::string> sTeleportErrorMessages;
 	static std::map<std::string, std::string> sTeleportProgressMessages;
 private:
-	LLSLURL	mTeleportSourceSLURL; 			// SLURL where last TP began
+	std::string		mTeleportSourceSLURL; 			// SLURL where last TP began
 
 	//--------------------------------------------------------------------
 	// Teleport Actions
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
index 7a8205acb581ae7a44de2f0f78f9cc0f289361ed..b3ed7c353ed577a9fc2b75015dc77ec26264a31c 100644
--- a/indra/newview/llagentlistener.cpp
+++ b/indra/newview/llagentlistener.cpp
@@ -53,10 +53,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
 	}
 	else
 	{
-		std::string url = LLSLURL(event_data["regionname"], 
-								  LLVector3(event_data["x"].asReal(), 
-											event_data["y"].asReal(), 
-											event_data["z"].asReal())).getSLURLString();
+		std::string url = LLSLURL::buildSLURL(event_data["regionname"], event_data["x"], event_data["y"], event_data["z"]);
 		LLURLDispatcher::dispatch(url, NULL, false);
 	}
 }
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
index 15d9f36b743fbf2c1ab326303410079107cfff83..c4597ad6f8d55199e584c84be77f5a122fdc752d 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -76,15 +76,16 @@ void LLAgentUI::buildFullname(std::string& name)
 }
 
 //static
-void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /*= true*/)
+std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
 {
-      LLSLURL return_slurl;
-      LLViewerRegion *regionp = gAgent.getRegion();
-      if (regionp)
-      {
-		  return_slurl = LLSLURL(regionp->getName(), gAgent.getPositionGlobal());
-      }
-	slurl = return_slurl;
+	std::string slurl;
+	LLViewerRegion *regionp = gAgent.getRegion();
+	if (regionp)
+	{
+		LLVector3d agentPos = gAgent.getPositionGlobal();
+		slurl = LLSLURL::buildSLURLfromPosGlobal(regionp->getName(), agentPos, escaped);
+	}
+	return slurl;
 }
 
 //static
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index 577b752fbec6249b2183769669eb6606da5b66e2..3478793e38f3f198c5e4af2ca5b24a6892d03c8b 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -33,8 +33,6 @@
 #ifndef LLAGENTUI_H
 #define LLAGENTUI_H
 
-class LLSLURL;
-
 class LLAgentUI
 {
 public:
@@ -50,7 +48,7 @@ class LLAgentUI
 	static void buildName(std::string& name);
 	static void buildFullname(std::string &name);
 
-	static void buildSLURL(LLSLURL& slurl, const bool escaped = true);
+	static std::string buildSLURL(const bool escaped = true);
 	//build location string using the current position of gAgent.
 	static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK);
 	//build location string using a region position of the avatar. 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 2a355474b1cb073ba125205f398e00f8c480851a..43c8c679c69c6ba3c2074d2198d5c5b4f931d834 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -153,7 +153,7 @@
 #include "llworld.h"
 #include "llhudeffecttrail.h"
 #include "llvectorperfoptions.h"
-#include "llslurl.h"
+#include "llurlsimstring.h"
 #include "llwatchdog.h"
 
 // Included so that constants/settings might be initialized
@@ -193,9 +193,6 @@
 #include "llparcel.h"
 #include "llavatariconctrl.h"
 
-// Include for security api initialization
-#include "llsecapi.h"
-
 // *FIX: These extern globals should be cleaned up.
 // The globals either represent state/config/resource-storage of either 
 // this app, or another 'component' of the viewer. App globals should be 
@@ -510,6 +507,35 @@ class LLFastTimerLogThread : public LLThread
 	}
 };
 
+void LLAppViewer::initGridChoice()
+{
+	// Load	up the initial grid	choice from:
+	//	- hard coded defaults...
+	//	- command line settings...
+	//	- if dev build,	persisted settings...
+
+	// Set the "grid choice", this is specified	by command line.
+	std::string	grid_choice	= gSavedSettings.getString("CmdLineGridChoice");
+	LLViewerLogin::getInstance()->setGridChoice(grid_choice);
+
+	// Load last server choice by default 
+	// ignored if the command line grid	choice has been	set
+	if(grid_choice.empty())
+	{
+		S32	server = gSavedSettings.getS32("ServerChoice");
+		server = llclamp(server, 0,	(S32)GRID_INFO_COUNT - 1);
+		if(server == GRID_INFO_OTHER)
+		{
+			std::string custom_server = gSavedSettings.getString("CustomServer");
+			LLViewerLogin::getInstance()->setGridChoice(custom_server);
+		}
+		else if(server != (S32)GRID_INFO_NONE)
+		{
+			LLViewerLogin::getInstance()->setGridChoice((EGridInfo)server);
+		}
+	}
+}
+
 //virtual
 bool LLAppViewer::initSLURLHandler()
 {
@@ -621,6 +647,7 @@ bool LLAppViewer::init()
     LLCurl::initClass();
 
     initThreads();
+
     writeSystemInfo();
 
 	// Build a string representing the current version number.
@@ -750,6 +777,10 @@ bool LLAppViewer::init()
 		return false;
 	}
 
+	// Always fetch the Ethernet MAC address, needed both for login
+	// and password load.
+	LLUUID::getNodeID(gMACAddress);
+
 	// Prepare for out-of-memory situations, during which we will crash on
 	// purpose and save a dump.
 #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
@@ -861,7 +892,6 @@ bool LLAppViewer::init()
 		}
 	}
 
-
 	// save the graphics card
 	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
 
@@ -872,17 +902,6 @@ bool LLAppViewer::init()
 	gSimFrames = (F32)gFrameCount;
 
 	LLViewerJoystick::getInstance()->init(false);
-
-	try {
-		initializeSecHandler();
-	}
-	catch (LLProtectedDataException ex)
-	{
-	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
-	}
-	LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
-
-
 	gGLActive = FALSE;
 	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
 	{
@@ -917,11 +936,13 @@ bool LLAppViewer::mainLoop()
 	gServicePump = new LLPumpIO(gAPRPoolp);
 	LLHTTPClient::setPump(*gServicePump);
 	LLCurl::setCAFile(gDirUtilp->getCAFile());
-
+	LLCurl::setSSLVerify(! gSavedSettings.getBOOL("NoVerifySSLCert"));
+	
 	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
 
 	LLVoiceChannel::initClass();
-	LLVoiceClient::getInstance()->init(gServicePump);
+	LLVoiceClient::init(gServicePump);
+
 	LLTimer frameTimer,idleTimer;
 	LLTimer debugTime;
 	LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
@@ -1252,7 +1273,7 @@ bool LLAppViewer::cleanup()
 	// to ensure shutdown order
 	LLMortician::setZealous(TRUE);
 
-	LLVoiceClient::getInstance()->terminate();
+	LLVoiceClient::terminate();
 	
 	disconnectViewer();
 
@@ -1451,6 +1472,13 @@ bool LLAppViewer::cleanup()
 
 	llinfos << "Saving Data" << llendflush;
 	
+	// Quitting with "Remember Password" turned off should always stomp your
+	// saved password, whether or not you successfully logged in.  JC
+	if (!gSavedSettings.getBOOL("RememberPassword"))
+	{
+		LLStartUp::deletePasswordFromDisk();
+	}
+	
 	// Store the time of our current logoff
 	gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
 
@@ -2019,6 +2047,7 @@ bool LLAppViewer::initConfiguration()
         }
     }
 
+    initGridChoice();
 
 	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
 	if(clp.hasOption("crashonstartup"))
@@ -2112,17 +2141,30 @@ bool LLAppViewer::initConfiguration()
     // injection and steal passwords. Phoenix. SL-55321
     if(clp.hasOption("url"))
     {
-		LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
-		if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION) 
-		{  
-			LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid());
-			
-		}  
+        std::string slurl = clp.getOption("url")[0];
+        if (LLSLURL::isSLURLCommand(slurl))
+        {
+	        LLStartUp::sSLURLCommand = slurl;
+        }
+        else
+        {
+	        LLURLSimString::setString(slurl);
+        }
     }
     else if(clp.hasOption("slurl"))
     {
-		LLSLURL start_slurl(clp.getOption("slurl")[0]);
-		LLStartUp::setStartSLURL(start_slurl);
+        std::string slurl = clp.getOption("slurl")[0];
+        if(LLSLURL::isSLURL(slurl))
+        {
+            if (LLSLURL::isSLURLCommand(slurl))
+            {
+	            LLStartUp::sSLURLCommand = slurl;
+            }
+            else
+            {
+	            LLURLSimString::setString(slurl);
+            }
+        }
     }
 
     const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
@@ -2203,10 +2245,18 @@ bool LLAppViewer::initConfiguration()
 	// don't call anotherInstanceRunning() when doing URL handoff, as
 	// it relies on checking a marker file which will not work when running
 	// out of different directories
-
-	if (LLStartUp::getStartSLURL().isValid())
+	std::string slurl;
+	if (!LLStartUp::sSLURLCommand.empty())
+	{
+		slurl = LLStartUp::sSLURLCommand;
+	}
+	else if (LLURLSimString::parse())
+	{
+		slurl = LLURLSimString::getURL();
+	}
+	if (!slurl.empty())
 	{
-		if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
+		if (sendURLToOtherInstance(slurl))
 		{
 			// successfully handed off URL to existing instance, exit
 			return false;
@@ -2262,9 +2312,9 @@ bool LLAppViewer::initConfiguration()
 
    	// need to do this here - need to have initialized global settings first
 	std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
-	if ( !nextLoginLocation.empty() )
+	if ( nextLoginLocation.length() )
 	{
-		LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
+		LLURLSimString::setString( nextLoginLocation );
 	};
 
 	gLastRunVersion = gSavedSettings.getString("LastRunVersion");
@@ -2485,7 +2535,7 @@ void LLAppViewer::writeSystemInfo()
 
 	// The user is not logged on yet, but record the current grid choice login url
 	// which may have been the intended grid. This can b
-	gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
+	gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel();
 
 	// *FIX:Mani - move this ddown in llappviewerwin32
 #ifdef LL_WINDOWS
@@ -3836,7 +3886,7 @@ void LLAppViewer::sendLogoutRequest()
 		gLogoutMaxTime = LOGOUT_REQUEST_TIME;
 		mLogoutRequestSent = TRUE;
 		
-		LLVoiceClient::getInstance()->leaveChannel();
+		gVoiceClient->leaveChannel();
 
 		//Set internal status variables and marker files
 		gLogoutInProgress = TRUE;
@@ -4256,7 +4306,7 @@ void LLAppViewer::launchUpdater()
 #endif
 	// *TODO change userserver to be grid on both viewer and sim, since
 	// userserver no longer exists.
-	query_map["userserver"] = LLGridManager::getInstance()->getGridLabel();
+	query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel();
 	query_map["channel"] = gSavedSettings.getString("VersionChannelName");
 	// *TODO constantize this guy
 	// *NOTE: This URL is also used in win_setup/lldownloader.cpp
@@ -4269,10 +4319,10 @@ void LLAppViewer::launchUpdater()
 	LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
 
 	// if a sim name was passed in via command line parameter (typically through a SLURL)
-	if ( LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION )
+	if ( LLURLSimString::sInstance.mSimString.length() )
 	{
 		// record the location to start at next time
-		gSavedSettings.setString( "NextLoginLocation", LLStartUp::getStartSLURL().getSLURLString()); 
+		gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); 
 	};
 
 #if LL_WINDOWS
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 27e8bec1d58795a0a525306e309e53a62486869d..a915b7fa50c8da0dc88223b4b9d4ed5fce9cc1a8 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -191,6 +191,7 @@ class LLAppViewer : public LLApp
 
 	bool initThreads(); // Initialize viewer threads, return false on failure.
 	bool initConfiguration(); // Initialize settings from the command line/config file.
+	void initGridChoice();
 
 	bool initCache(); // Initialize local client cache.
 
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 78b0f7ba831d05c01bd4c4f2f370cd664290a803..d34bcb4a685503d4b734523641cceefc960022b1 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -604,7 +604,7 @@ void LLAppViewerLinux::handleCrashReporting(bool reportFreeze)
 				{cmd.c_str(),
 				 ask_dialog,
 				 "-user",
-				 (char*)LLGridManager::getInstance()->getGridLabel().c_str(),
+				 (char*)LLViewerLogin::getInstance()->getGridLabel().c_str(),
 				 "-name",
 				 LLAppViewer::instance()->getSecondLifeTitle().c_str(),
 				 NULL};
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 58d28883c616c1a114531d29b0df27455bfe156e..80d9b143457412dcefa0a8f33302e2417865ab9a 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -44,6 +44,7 @@
 #include "llviewernetwork.h"
 #include "llviewercontrol.h"
 #include "llmd5.h"
+#include "llurlsimstring.h"
 #include "llfloaterworldmap.h"
 #include "llurldispatcher.h"
 #include <Carbon/Carbon.h>
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 48a85dc73f05da741c83a346307c3cfaa89c99c6..c85c72837c17e6b27035a712aad4da01d140df94 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -282,7 +282,7 @@ bool LLAvatarActions::isCalling(const LLUUID &id)
 //static
 bool LLAvatarActions::canCall()
 {
-		return LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+		return LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
 }
 
 // static
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 9824f5935881f42463f29e706928292649073fb7..41bee540fc62d56a72eb306cc5c1cc34ab8f27a5 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -319,7 +319,7 @@ void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, b
 	// skipped to avoid button blinking
 	if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL)
 	{
-		mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
+		mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
 	}
 }
 
@@ -489,7 +489,7 @@ BOOL LLBottomTray::postBuild()
 	mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
 
 	// Registering Chat Bar to receive Voice client status change notifications.
-	LLVoiceClient::getInstance()->addObserver(this);
+	gVoiceClient->addObserver(this);
 
 	mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();
 	mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 132e4f093311e0fcae3321b316b4787b41d33eae..9dc31ec70b9e126598e8e008822fc6c2503fd28c 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -133,7 +133,7 @@ LLCallFloater::~LLCallFloater()
 
 	if(LLVoiceClient::instanceExists())
 	{
-		LLVoiceClient::getInstance()->removeObserver(this);
+		gVoiceClient->removeObserver(this);
 	}
 	LLTransientFloaterMgr::getInstance()->removeControlView(this);
 }
@@ -189,7 +189,7 @@ void LLCallFloater::draw()
 	// Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent)
 //	onChange();
 
-	bool is_moderator_muted = LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID);
+	bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID);
 
 	if (mIsModeratorMutedVoice != is_moderator_muted)
 	{
@@ -207,6 +207,7 @@ void LLCallFloater::draw()
 void LLCallFloater::onChange()
 {
 	if (NULL == mParticipants) return;
+
 	updateParticipantsVoiceState();
 
 	// Add newly joined participants.
@@ -236,11 +237,11 @@ void LLCallFloater::updateSession()
 	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
 	if (voice_channel)
 	{
-		LL_DEBUGS("Voice") << "Current voice channel: " << voice_channel->getSessionID() << LL_ENDL;
+		lldebugs << "Current voice channel: " << voice_channel->getSessionID() << llendl;
 
 		if (mSpeakerManager && voice_channel->getSessionID() == mSpeakerManager->getSessionID())
 		{
-			LL_DEBUGS("Voice") << "Speaker manager is already set for session: " << voice_channel->getSessionID() << LL_ENDL;
+			lldebugs << "Speaker manager is already set for session: " << voice_channel->getSessionID() << llendl;
 			return;
 		}
 		else
@@ -250,6 +251,7 @@ void LLCallFloater::updateSession()
 	}
 
 	const LLUUID& session_id = voice_channel ? voice_channel->getSessionID() : LLUUID::null;
+	lldebugs << "Set speaker manager for session: " << session_id << llendl;
 
 	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
 	if (im_session)
@@ -289,7 +291,7 @@ void LLCallFloater::updateSession()
 	{
 		// by default let show nearby chat participants
 		mSpeakerManager = LLLocalSpeakerMgr::getInstance();
-		LL_DEBUGS("Voice") << "Set DEFAULT speaker manager" << LL_ENDL;
+		lldebugs << "Set DEFAULT speaker manager" << llendl;
 		mVoiceType = VC_LOCAL_CHAT;
 	}
 
@@ -468,15 +470,16 @@ void LLCallFloater::updateAgentModeratorState()
 static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids)
 {
 	// Get a list of participants from VoiceClient
-       std::set<LLUUID> participants;
-       LLVoiceClient::getInstance()->getParticipantList(participants);
-	
-	for (std::set<LLUUID>::const_iterator iter = participants.begin();
-		 iter != participants.end(); ++iter)
+	LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList();
+	if (voice_map)
 	{
-		speakers_uuids.push_back(*iter);
+		for (LLVoiceClient::participantMap::const_iterator iter = voice_map->begin();
+			iter != voice_map->end(); ++iter)
+		{
+			LLUUID id = (*iter).second->mAvatarID;
+			speakers_uuids.push_back(id);
+		}
 	}
-
 }
 
 void LLCallFloater::initParticipantsVoiceState()
@@ -552,7 +555,7 @@ void LLCallFloater::updateParticipantsVoiceState()
 
 		uuid_vec_t::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), participant_id);
 
-		LL_DEBUGS("Voice") << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << LL_ENDL;
+		lldebugs << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << llendl;
 
 		// If an avatarID assigned to a panel is found in a speakers list
 		// obtained from VoiceClient we assign the JOINED status to the owner
@@ -722,7 +725,7 @@ void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
 void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
 {
 	// check is voice operational and if it doesn't work hide VCP (EXT-4397)
-	if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking())
+	if(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking())
 	{
 		updateState(new_state);
 	}
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 1a6c11fa73e66758f72e311ca81108587908d3bb..79a2631c31dd9375c4b2949d3db304fafe121914 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -700,7 +700,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 						args["FIRST"] = first;
 						args["LAST"] = last;
 					}
-
 				}
 			}
 			else
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 1e404d611cd5dc1ff9276106ddcf70c0a2f0a744..71e7ae70610c9f8014d355b132a007fdc45d2227 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -640,19 +640,20 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 			if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())
 			{
 				// for object IMs, create a secondlife:///app/objectim SLapp
-				std::string url = LLSLURL("objectim", chat.mFromID, "").getSLURLString();
+				std::string url = LLSLURL::buildCommand("objectim", chat.mFromID, "");
 				url += "?name=" + chat.mFromName;
 				url += "&owner=" + args["owner_id"].asString();
 
 				std::string slurl = args["slurl"].asString();
 				if (slurl.empty())
 				{
-				    LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
-				    if(region)
-				      {
-					LLSLURL region_slurl(region->getName(), chat.mPosAgent);
-					slurl = region_slurl.getLocationString();
-				      }
+					LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
+					if (region)
+					{
+						S32 x, y, z;
+						LLSLURL::globalPosToXYZ(LLVector3d(chat.mPosAgent), x, y, z);
+						slurl = region->getName() + llformat("/%d/%d/%d", x, y, z);
+					}
 				}
 				url += "&slurl=" + slurl;
 
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index fd3df359bd75fdd2585c847ae7fb3702e8bff51f..be6c15eab4a036be7548f0913d48c09aaf8f4a2e 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -284,7 +284,7 @@ void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
 	static std::string transactionURI;
 	if (transactionURI.empty())
 	{
-		transactionURI = LLGridManager::getInstance()->getHelperURI() + "currency.php";
+		transactionURI = LLViewerLogin::getInstance()->getHelperURI() + "currency.php";
 	}
 
 	delete mTransaction;
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 56bc4a79338189cc65223267209f33ba5786d3ae..ef69f39ad2df5b575ecc7aac9d7575b45c638a94 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -266,18 +266,8 @@ LLSD LLFloaterAbout::getInfo()
 	info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
 	bool want_fullname = true;
 	info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
-	if(LLVoiceClient::getInstance()->voiceEnabled())
-	{
-		LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion();
-		std::ostringstream version_string;
-		version_string << version.serverType << " " << version.serverVersion << std::endl;
-		info["VOICE_VERSION"] = version_string.str();
-	}
-	else 
-	{
-		info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
-	}
-	
+	info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : LLTrans::getString("NotConnected");
+
 	// TODO: Implement media plugin version query
 	info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)";
 
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 464b3a72143264818ada0b04125bc34a44a13e83..d37bc01885ffdf4b3d93e685cef15a836af71759 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -830,7 +830,7 @@ void LLFloaterBuyLandUI::updateNames()
 	else
 	{
 		mParcelSellerName =
-			LLSLURL("agent", parcelp->getOwnerID(), "inspect").getSLURLString();
+			LLSLURL::buildCommand("agent", parcelp->getOwnerID(), "inspect");
 	}
 }
 
@@ -859,7 +859,7 @@ void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCVa
 	static std::string transaction_uri;
 	if (transaction_uri.empty())
 	{
-		transaction_uri = LLGridManager::getInstance()->getHelperURI() + "landtool.php";
+		transaction_uri = LLViewerLogin::getInstance()->getHelperURI() + "landtool.php";
 	}
 	
 	const char* method;
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index 882d12f68ec122c4355fca35e7fd6e1b17a7b1a8..cdb9b8edb869101fae9b577e322672c3095aa415 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -166,7 +166,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
 	if (chat.mSourceType == CHAT_SOURCE_AGENT &&
 		chat.mFromID != LLUUID::null)
 	{
-		chat.mURL = LLSLURL("agent", chat.mFromID, "inspect").getSLURLString();
+		chat.mURL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
 	}
 
 	// If the chat line has an associated url, link it up to the name.
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index a15cef7ea451ffff31907f42ddba7120886cedff..774caaec904ab635702536b4e9d0530f5b754ede 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -318,7 +318,7 @@ LLFloaterChatterBox* LLFloaterChatterBox::getInstance()
 //static 
 LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater()
 {
-	if (!LLVoiceClient::getInstance()->voiceEnabled())
+	if (!LLVoiceClient::voiceEnabled())
 	{
 		return NULL;
 	}
diff --git a/indra/newview/llfloaterevent.cpp b/indra/newview/llfloaterevent.cpp
index 84a5c3dc7751f08c700846286bf7c2a8b232028f..97ebab34258d7c495b48eaa7d63180a45d43a2b3 100644
--- a/indra/newview/llfloaterevent.cpp
+++ b/indra/newview/llfloaterevent.cpp
@@ -193,7 +193,7 @@ void LLFloaterEvent::processEventInfoReply(LLMessageSystem *msg, void **)
 		floater->mTBCategory->setText(floater->mEventInfo.mCategoryStr);
 		floater->mTBDate->setText(floater->mEventInfo.mTimeStr);
 		floater->mTBDesc->setText(floater->mEventInfo.mDesc);
-		floater->mTBRunBy->setText(LLSLURL("agent", floater->mEventInfo.mRunByID, "inspect").getSLURLString());
+		floater->mTBRunBy->setText(LLSLURL::buildCommand("agent", floater->mEventInfo.mRunByID, "inspect"));
 
 		floater->mTBDuration->setText(llformat("%d:%.2d", floater->mEventInfo.mDuration / 60, floater->mEventInfo.mDuration % 60));
 
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 25d3f971b5bdecf990db0aafda2cad180bf28f7e..02c83dcd09e2abeed9f255f55450cd7dcfe9039a 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -42,6 +42,7 @@
 #include "llnotificationsutil.h"
 #include "llparcel.h"
 #include "message.h"
+#include "lluserauth.h"
 
 #include "llagent.h"
 #include "llbutton.h"
@@ -803,7 +804,7 @@ void LLPanelLandGeneral::refreshNames()
 	else
 	{
 		// Figure out the owner's name
-		owner = LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString();
+		owner = LLSLURL::buildCommand("agent", parcel->getOwnerID(), "inspect");
 	}
 
 	if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
@@ -815,7 +816,7 @@ void LLPanelLandGeneral::refreshNames()
 	std::string group;
 	if (!parcel->getGroupID().isNull())
 	{
-		group = LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString();
+		group = LLSLURL::buildCommand("group", parcel->getGroupID(), "inspect");
 	}
 	mTextGroup->setText(group);
 
@@ -824,9 +825,9 @@ void LLPanelLandGeneral::refreshNames()
 		const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
 		if(auth_buyer_id.notNull())
 		{
-		  std::string name;
-		  name = LLSLURL("agent", auth_buyer_id, "inspect").getSLURLString();
-		  mSaleInfoForSale2->setTextArg("[BUYER]", name);
+			std::string name;
+			name = LLSLURL::buildCommand("agent", auth_buyer_id, "inspect");
+			mSaleInfoForSale2->setTextArg("[BUYER]", name);
 		}
 		else
 		{
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 3a73037ae8ffcc6195eb19594c26665864aa109d..764a0dc954a82d757f563f139385a0aa7c765307 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -595,7 +595,7 @@ void LLFloaterPreference::onBtnOK()
 		llinfos << "Can't close preferences!" << llendl;
 	}
 
-	LLPanelLogin::updateLocationCombo( false );
+	LLPanelLogin::refreshLocation( false );
 }
 
 // static 
@@ -612,7 +612,7 @@ void LLFloaterPreference::onBtnApply( )
 	apply();
 	saveSettings();
 
-	LLPanelLogin::updateLocationCombo( false );
+	LLPanelLogin::refreshLocation( false );
 }
 
 // static 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 8c219cb3fdf3cba5bff8273c7cc4f6b0b4acb11d..3758cbe74f41d90f8a2dde797c32413cb33e060d 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -2922,7 +2922,8 @@ bool LLDispatchEstateUpdateInfo::operator()(
 	LLUUID owner_id(strings[1]);
 	regionp->setOwner(owner_id);
 	// Update estate owner name in UI
-	std::string owner_name = LLSLURL("agent", owner_id, "inspect").getSLURLString();
+	std::string owner_name =
+		LLSLURL::buildCommand("agent", owner_id, "inspect");
 	panel->setOwnerName(owner_name);
 
 	U32 estate_id = strtoul(strings[2].c_str(), NULL, 10);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index f7c8855bf6571d2f3583143bb22559e9ea25b871..b42b34835d30f53cedec63594756a38b5cf86770 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -126,9 +126,7 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
 // virtual
 BOOL LLFloaterReporter::postBuild()
 {
-	LLSLURL slurl;
-	LLAgentUI::buildSLURL(slurl);
-	childSetText("abuse_location_edit", slurl.getSLURLString());
+	childSetText("abuse_location_edit", LLAgentUI::buildSLURL());
 
 	enableControls(TRUE);
 
@@ -282,6 +280,7 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
 				{
 					object_owner.append("Unknown");
 				}
+
 				setFromAvatar(mObjectID, object_owner);
 			}
 			else
@@ -326,8 +325,7 @@ void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string
 	mAbuserID = mObjectID = avatar_id;
 	mOwnerName = avatar_name;
 
-	std::string avatar_link =
-	  LLSLURL("agent", mObjectID, "inspect").getSLURLString();
+	std::string avatar_link = LLSLURL::buildCommand("agent", mObjectID, "inspect");
 	childSetText("owner_name", avatar_link);
 	childSetText("object_name", avatar_name);
 	childSetText("abuser_name_edit", avatar_name);
@@ -506,7 +504,7 @@ void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name
 {
 	childSetText("object_name", object_name);
 	std::string owner_link =
-		LLSLURL("agent", owner_id, "inspect").getSLURLString();
+		LLSLURL::buildCommand("agent", owner_id, "inspect");
 	childSetText("owner_name", owner_link);
 	childSetText("abuser_name_edit", owner_name);
 	mAbuserID = owner_id;
@@ -568,7 +566,7 @@ LLSD LLFloaterReporter::gatherReport()
 	mCopyrightWarningSeen = FALSE;
 
 	std::ostringstream summary;
-	if (!LLGridManager::getInstance()->isInProductionGrid())
+	if (!LLViewerLogin::getInstance()->isInProductionGrid())
 	{
 		summary << "Preview ";
 	}
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index aae379afe2125b55b1ff8acb239473542e469ece..adac9861d481cdb08b25e37466447560acaec746 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1123,7 +1123,7 @@ void LLSnapshotLivePreview::saveWeb(std::string url)
 
 void LLSnapshotLivePreview::regionNameCallback(std::string url, LLSD body, const std::string& name, S32 x, S32 y, S32 z)
 {
-	body["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
+	body["slurl"] = LLSLURL::buildSLURL(name, x, y, z);
 
 	LLHTTPClient::post(url, body,
 		new LLSendWebResponder());
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index 63365e34613f02293f28c5e36d7f4c35f4d8d04e..638c9f1b8c83eeca7c8b913f1a98c6d41f914cdb 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -64,6 +64,9 @@ LLPanelVoiceDeviceSettings::LLPanelVoiceDeviceSettings()
 	// grab "live" mic volume level
 	mMicVolume = gSavedSettings.getF32("AudioLevelMic");
 
+	// ask for new device enumeration
+	// now do this in onOpen() instead...
+	//gVoiceClient->refreshDeviceLists();
 }
 
 LLPanelVoiceDeviceSettings::~LLPanelVoiceDeviceSettings()
@@ -102,7 +105,7 @@ void LLPanelVoiceDeviceSettings::draw()
 	refresh();
 
 	// let user know that volume indicator is not yet available
-	bool is_in_tuning_mode = LLVoiceClient::getInstance()->inTuningMode();
+	bool is_in_tuning_mode = gVoiceClient->inTuningMode();
 	childSetVisible("wait_text", !is_in_tuning_mode);
 
 	LLPanel::draw();
@@ -110,7 +113,7 @@ void LLPanelVoiceDeviceSettings::draw()
 	if (is_in_tuning_mode)
 	{
 		const S32 num_bars = 5;
-		F32 voice_power = LLVoiceClient::getInstance()->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
+		F32 voice_power = gVoiceClient->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
 		S32 discrete_power = llmin(num_bars, llfloor(voice_power * (F32)num_bars + 0.1f));
 
 		for(S32 power_bar_idx = 0; power_bar_idx < num_bars; power_bar_idx++)
@@ -191,13 +194,13 @@ void LLPanelVoiceDeviceSettings::refresh()
 	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
 	// set mic volume tuning slider based on last mic volume setting
 	F32 current_volume = (F32)volume_slider->getValue().asReal();
-	LLVoiceClient::getInstance()->tuningSetMicVolume(current_volume);
+	gVoiceClient->tuningSetMicVolume(current_volume);
 
 	// Fill in popup menus
 	mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
 	mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device");
 
-	if(!LLVoiceClient::getInstance()->deviceSettingsAvailable())
+	if(!gVoiceClient->deviceSettingsAvailable())
 	{
 		// The combo boxes are disabled, since we can't get the device settings from the daemon just now.
 		// Put the currently set default (ONLY) in the box, and select it.
@@ -216,16 +219,17 @@ void LLPanelVoiceDeviceSettings::refresh()
 	}
 	else if (!mDevicesUpdated)
 	{
-		LLVoiceDeviceList::const_iterator iter;
+		LLVoiceClient::deviceList *devices;
+		
+		LLVoiceClient::deviceList::iterator iter;
 		
 		if(mCtrlInputDevices)
 		{
 			mCtrlInputDevices->removeall();
 			mCtrlInputDevices->add( getString("default_text"), ADD_BOTTOM );
 
-			for(iter=LLVoiceClient::getInstance()->getCaptureDevices().begin(); 
-				iter != LLVoiceClient::getInstance()->getCaptureDevices().end();
-				iter++)
+			devices = gVoiceClient->getCaptureDevices();
+			for(iter=devices->begin(); iter != devices->end(); iter++)
 			{
 				mCtrlInputDevices->add( *iter, ADD_BOTTOM );
 			}
@@ -241,8 +245,8 @@ void LLPanelVoiceDeviceSettings::refresh()
 			mCtrlOutputDevices->removeall();
 			mCtrlOutputDevices->add( getString("default_text"), ADD_BOTTOM );
 
-			for(iter= LLVoiceClient::getInstance()->getRenderDevices().begin(); 
-				iter !=  LLVoiceClient::getInstance()->getRenderDevices().end(); iter++)
+			devices = gVoiceClient->getRenderDevices();
+			for(iter=devices->begin(); iter != devices->end(); iter++)
 			{
 				mCtrlOutputDevices->add( *iter, ADD_BOTTOM );
 			}
@@ -264,34 +268,37 @@ void LLPanelVoiceDeviceSettings::initialize()
 	mDevicesUpdated = FALSE;
 
 	// ask for new device enumeration
-	LLVoiceClient::getInstance()->refreshDeviceLists();
+	gVoiceClient->refreshDeviceLists();
 
 	// put voice client in "tuning" mode
-	LLVoiceClient::getInstance()->tuningStart();
+	gVoiceClient->tuningStart();
 	LLVoiceChannel::suspend();
 }
 
 void LLPanelVoiceDeviceSettings::cleanup()
 {
-	LLVoiceClient::getInstance()->tuningStop();
+	if (gVoiceClient)
+	{
+		gVoiceClient->tuningStop();
+	}
 	LLVoiceChannel::resume();
 }
 
 // static
 void LLPanelVoiceDeviceSettings::onCommitInputDevice(LLUICtrl* ctrl, void* user_data)
 {
-	if(LLVoiceClient::getInstance())
+	if(gVoiceClient)
 	{
-		LLVoiceClient::getInstance()->setCaptureDevice(ctrl->getValue().asString());
+		gVoiceClient->setCaptureDevice(ctrl->getValue().asString());
 	}
 }
 
 // static
 void LLPanelVoiceDeviceSettings::onCommitOutputDevice(LLUICtrl* ctrl, void* user_data)
 {
-	if(LLVoiceClient::getInstance())
+	if(gVoiceClient)
 	{
-		LLVoiceClient::getInstance()->setRenderDevice(ctrl->getValue().asString());
+		gVoiceClient->setRenderDevice(ctrl->getValue().asString());
 	}
 }
 
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 896c410e32ed7a64cb48af01f316e502785a4e7b..f17c9765b9f167e7db5bfb93a93674419fef0f3e 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -461,7 +461,7 @@ void LLFloaterWorldMap::draw()
 	childSetEnabled("Teleport", (BOOL)tracking_status);
 //	childSetEnabled("Clear", (BOOL)tracking_status);
 	childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->isTracking());
-	childSetEnabled("copy_slurl", (mSLURL.isValid()) );
+	childSetEnabled("copy_slurl", (mSLURL.size() > 0) );
 
 	setMouseOpaque(TRUE);
 	getDragHandle()->setMouseOpaque(TRUE);
@@ -660,8 +660,14 @@ void LLFloaterWorldMap::updateLocation()
 				childSetValue("location", agent_sim_name);
 
 				// Figure out where user is
+				LLVector3d agentPos = gAgent.getPositionGlobal();
+
+				S32 agent_x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) );
+				S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
+				S32 agent_z = llround( (F32)agentPos.mdV[VZ] );
+
 				// Set the current SLURL
-				mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionGlobal());
+				mSLURL = LLSLURL::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z);
 			}
 		}
 
@@ -688,15 +694,18 @@ void LLFloaterWorldMap::updateLocation()
 		}
 
 		childSetValue("location", sim_name);
+		
+		F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
+		F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
 
 		// simNameFromPosGlobal can fail, so don't give the user an invalid SLURL
 		if ( gotSimName )
 		{
-		  mSLURL = LLSLURL(sim_name, pos_global);
+			mSLURL = LLSLURL::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ]));
 		}
 		else
 		{	// Empty SLURL will disable the "Copy SLURL to clipboard" button
-			mSLURL = LLSLURL();
+			mSLURL = "";
 		}
 	}
 }
@@ -1165,7 +1174,7 @@ void LLFloaterWorldMap::onClearBtn()
 	mTrackedStatus = LLTracker::TRACKING_NOTHING;
 	LLTracker::stopTracking((void *)(intptr_t)TRUE);
 	LLWorldMap::getInstance()->cancelTracking();
-	mSLURL = LLSLURL();					// Clear the SLURL since it's invalid
+	mSLURL = "";					// Clear the SLURL since it's invalid
 	mSetToUserPosition = TRUE;	// Revert back to the current user position
 }
 
@@ -1188,10 +1197,10 @@ void LLFloaterWorldMap::onClickTeleportBtn()
 
 void LLFloaterWorldMap::onCopySLURL()
 {
-	getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL.getSLURLString()));
+	getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL));
 	
 	LLSD args;
-	args["SLURL"] = mSLURL.getSLURLString();
+	args["SLURL"] = mSLURL;
 
 	LLNotificationsUtil::add("CopySLURL", args);
 }
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 52809ff8302bb2074118aa9023217325ab00377b..00f5e788fb871910ee7ca95beab36c455be15b5c 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -43,7 +43,6 @@
 #include "llhudtext.h"
 #include "llmapimagetype.h"
 #include "lltracker.h"
-#include "llslurl.h"
 
 class LLEventInfo;
 class LLFriendObserver;
@@ -184,7 +183,7 @@ class LLFloaterWorldMap : public LLFloater
 	LLTracker::ETrackingStatus mTrackedStatus;
 	std::string				mTrackedSimName;
 	std::string				mTrackedAvatarName;
-	LLSLURL  				mSLURL;
+	std::string				mSLURL;
 };
 
 extern LLFloaterWorldMap* gFloaterWorldMap;
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 03a47b598357e817fe00d063a62890853ff440c4..8a056f836f215a84d8f7d2cf85b87e51af4cdc95 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -287,7 +287,7 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
 		return gAgent.getGroupID() != selected_group_id;
 
 	if (userdata.asString() == "call")
-	  return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+		return real_group_selected && LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking();
 
 	return real_group_selected;
 }
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 9704c7537ada9034413052569c681269e69fca0a..3ec8d11fb0cd7c72b5bb092085f2f359494e7276 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -58,6 +58,7 @@
 #include "lltransientfloatermgr.h"
 #include "llinventorymodel.h"
 #include "llrootview.h"
+
 #include "llspeakers.h"
 
 
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 0e3b78df7f2f7512fde8c2cf6f71f08d7cba0545..4bdf5f42dc451f9487eee3d8438534b67ad29df1 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -300,7 +300,7 @@ void LLFloaterIMPanel::onVolumeChange(LLUICtrl* source, void* user_data)
 	LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)user_data;
 	if (floaterp)
 	{
-		LLVoiceClient::getInstance()->setUserVolume(floaterp->mOtherParticipantUUID, (F32)source->getValue().asReal());
+		gVoiceClient->setUserVolume(floaterp->mOtherParticipantUUID, (F32)source->getValue().asReal());
 	}
 }
 
@@ -312,7 +312,7 @@ void LLFloaterIMPanel::draw()
 	
 	BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "")
 					  && mSessionInitialized
-					  && LLVoiceClient::getInstance()->voiceEnabled()
+					  && LLVoiceClient::voiceEnabled()
 					  && mCallBackEnabled;
 
 	// hide/show start call and end call buttons
@@ -320,8 +320,8 @@ void LLFloaterIMPanel::draw()
 	if (!voice_channel)
 		return;
 
-	childSetVisible("end_call_btn", LLVoiceClient::getInstance()->voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
-	childSetVisible("start_call_btn", LLVoiceClient::getInstance()->voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
+	childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+	childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
 	childSetEnabled("start_call_btn", enable_connect);
 	childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty());
 	
@@ -384,11 +384,11 @@ void LLFloaterIMPanel::draw()
 	else
 	{
 		// refresh volume and mute checkbox
-		childSetVisible("speaker_volume", LLVoiceClient::getInstance()->voiceEnabled() && voice_channel->isActive());
-		childSetValue("speaker_volume", LLVoiceClient::getInstance()->getUserVolume(mOtherParticipantUUID));
+		childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && voice_channel->isActive());
+		childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID));
 
 		childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
-		childSetVisible("mute_btn", LLVoiceClient::getInstance()->voiceEnabled() && voice_channel->isActive());
+		childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && voice_channel->isActive());
 	}
 	LLFloater::draw();
 }
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 5201f92dbc9453ece8414fbaaea4d291715ed158..e0f155a6a9a9b51fa0458af61a36fabb3e323a42 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -344,13 +344,13 @@ LLIMModel::LLIMSession::~LLIMSession()
 	mSpeakers = NULL;
 
 	// End the text IM session if necessary
-	if(LLVoiceClient::getInstance() && mOtherParticipantID.notNull())
+	if(gVoiceClient && mOtherParticipantID.notNull())
 	{
 		switch(mType)
 		{
 		case IM_NOTHING_SPECIAL:
 		case IM_SESSION_P2P_INVITE:
-			LLVoiceClient::getInstance()->endUserIMSession(mOtherParticipantID);
+			gVoiceClient->endUserIMSession(mOtherParticipantID);
 			break;
 
 		default:
@@ -925,7 +925,7 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
 	if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
 	{
 		// User is online through the OOW connector, but not with a regular viewer.  Try to send the message via SLVoice.
-		sent = LLVoiceClient::getInstance()->sendTextMessage(other_participant_id, utf8_text);
+		sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
 	}
 	
 	if(!sent)
@@ -1717,7 +1717,7 @@ void LLOutgoingCallDialog::show(const LLSD& key)
 
 		// skipping "You will now be reconnected to nearby" in notification when call is ended by disabling voice,
 		// so no reconnection to nearby chat happens (EXT-4397)
-		bool voice_works = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+		bool voice_works = LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
 		std::string reconnect_nearby = voice_works ? LLTrans::getString("reconnect_nearby") : std::string();
 		childSetTextArg("nearby", "[RECONNECT_NEARBY]", reconnect_nearby);
 
@@ -1843,11 +1843,7 @@ LLCallDialog(payload)
 void LLIncomingCallDialog::onLifetimeExpired()
 {
 	// check whether a call is valid or not
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mPayload["session_id"].asUUID());
-	if(channelp &&
-	   (channelp->getState() != LLVoiceChannel::STATE_NO_CHANNEL_INFO) &&
-	   (channelp->getState() != LLVoiceChannel::STATE_ERROR) &&
-	   (channelp->getState() != LLVoiceChannel::STATE_HUNG_UP))
+	if (LLVoiceClient::getInstance()->findSession(mPayload["caller_id"].asUUID()))
 	{
 		// restart notification's timer if call is still valid
 		mLifetimeTimer.start();
@@ -2081,10 +2077,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
 	{
 		if (type == IM_SESSION_P2P_INVITE)
 		{
-			if(LLVoiceClient::getInstance())
+			if(gVoiceClient)
 			{
 				std::string s = mPayload["session_handle"].asString();
-				LLVoiceClient::getInstance()->declineInvite(s);
+				gVoiceClient->declineInvite(s);
 			}
 		}
 		else
@@ -2172,8 +2168,11 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 	{
 		if (type == IM_SESSION_P2P_INVITE)
 		{
-		  std::string s = payload["session_handle"].asString();
-		  LLVoiceClient::getInstance()->declineInvite(s);
+			if(gVoiceClient)
+			{
+				std::string s = payload["session_handle"].asString();
+				gVoiceClient->declineInvite(s);
+			}
 		}
 		else
 		{
@@ -3079,7 +3078,7 @@ class LLViewerChatterBoxInvitation : public LLHTTPNode
 				return;
 			}
 			
-			if(!LLVoiceClient::getInstance()->voiceEnabled())
+			if(!LLVoiceClient::voiceEnabled())
 			{
 				// Don't display voice invites unless the user has voice enabled.
 				return;
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 1299324105fdac84fceea9a202e8c4bd3c43eaa3..94ea236757281f92285425b032e5e53c0c44b82b 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -536,7 +536,8 @@ void LLInspectAvatar::toggleSelectedVoice(bool enabled)
 
 void LLInspectAvatar::updateVolumeSlider()
 {
-	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID);
+
+	bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID);
 
 	// Do not display volume slider and mute button if it 
 	// is ourself or we are not in a voice channel together
@@ -566,7 +567,6 @@ void LLInspectAvatar::updateVolumeSlider()
 		volume_slider->setEnabled( !is_muted );
 
 		F32 volume;
-		
 		if (is_muted)
 		{
 			// it's clearer to display their volume as zero
@@ -575,7 +575,7 @@ void LLInspectAvatar::updateVolumeSlider()
 		else
 		{
 			// actual volume
-			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID);
+			volume = gVoiceClient->getUserVolume(mAvatarID);
 		}
 		volume_slider->setValue( (F64)volume );
 	}
@@ -604,7 +604,7 @@ void LLInspectAvatar::onClickMuteVolume()
 void LLInspectAvatar::onVolumeChange(const LLSD& data)
 {
 	F32 volume = (F32)data.asReal();
-	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
+	gVoiceClient->setUserVolume(mAvatarID, volume);
 }
 
 void LLInspectAvatar::nameUpdatedCallback(
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
index a2b5ffbac4a22794e5956d057ba0f51dab5dab89..91cbbbf43060093ed96b3c6dba6af5c14b1d4e7d 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -480,7 +480,7 @@ void LLInspectObject::updateCreator(LLSelectNode* nodep)
 		// Objects cannot be created by a group, so use agent URL format
 		LLUUID creator_id = nodep->mPermissions->getCreator();
 		std::string creator_url =
-			LLSLURL("agent", creator_id, "about").getSLURLString();
+			LLSLURL::buildCommand("agent", creator_id, "about");
 		args["[CREATOR]"] = creator_url;
 				
 		// created by one user but owned by another
@@ -490,12 +490,12 @@ void LLInspectObject::updateCreator(LLSelectNode* nodep)
 		if (group_owned)
 		{
 			owner_id = nodep->mPermissions->getGroup();
-			owner_url =	LLSLURL("group", owner_id, "about").getSLURLString();
+			owner_url =	LLSLURL::buildCommand("group", owner_id, "about");
 		}
 		else
 		{
 			owner_id = nodep->mPermissions->getOwner();
-			owner_url =	LLSLURL("agent", owner_id, "about").getSLURLString();
+			owner_url =	LLSLURL::buildCommand("agent", owner_id, "about");
 		}
 		args["[OWNER]"] = owner_url;
 		
diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp
index 97ff771658daa8d4d62f819e4cec723f8ca2dd84..66e4a1bf6602dadb83c3ff2d7f56a74ff1dce826 100644
--- a/indra/newview/llinspectremoteobject.cpp
+++ b/indra/newview/llinspectremoteobject.cpp
@@ -176,11 +176,11 @@ void LLInspectRemoteObject::update()
 	{
 		if (mGroupOwned)
 		{
-			owner = LLSLURL("group", mOwnerID, "about").getSLURLString();
+			owner = LLSLURL::buildCommand("group", mOwnerID, "about");
 		}
 		else
 		{
-			owner = LLSLURL("agent", mOwnerID, "about").getSLURLString();
+			owner = LLSLURL::buildCommand("agent", mOwnerID, "about");
 		}
 	}
 	else
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b6202c6a8c7197e58ee05a1876e7f9e12cd6874d..d1cc0ae936d7032bee8168a3a2b0b6ea0e02ff63 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1329,6 +1329,7 @@ bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
 	return cat->fetchDescendents();
 }
 
+
 void LLInventoryModel::cache(
 	const LLUUID& parent_folder_id,
 	const LLUUID& agent_id)
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index 539ca97a9375335aa283c61a70baf7dfd1107f0b..7336efb62a25c5e3fbb7f8c38bf3636b2203a529 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -299,7 +299,7 @@ void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slur
 	bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal(global_pos, sim_name);
 	if (gotSimName)
 	{
-	  std::string slurl = LLSLURL(sim_name, global_pos).getSLURLString();
+		std::string slurl = LLSLURL::buildSLURLfromPosGlobal(sim_name, global_pos, escaped);
 		cb(slurl);
 
 		return;
@@ -351,7 +351,7 @@ void LLLandmarkActions::onRegionResponseSLURL(slurl_callback_t cb,
 	bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal(global_pos, sim_name);
 	if (gotSimName)
 	{
-	  slurl = LLSLURL(sim_name, global_pos).getSLURLString();
+		slurl = LLSLURL::buildSLURLfromPosGlobal(sim_name, global_pos, escaped);
 	}
 	else
 	{
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 3b4a4a1344f7fd96f65e481be023355e9dbbafeb..ad2e594b49f9538d314d9334c6c07e5e83a99950 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -668,8 +668,9 @@ void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data)
 				value["item_type"] = TELEPORT_HISTORY;
 				value["global_pos"] = result->mGlobalPos.getValue();
 				std::string region_name = result->mTitle.substr(0, result->mTitle.find(','));
-				//TODO*: add Surl to teleportitem or parse region name from title
-				value["tooltip"] = LLSLURL(region_name, result->mGlobalPos).getSLURLString();
+				//TODO*: add slurl to teleportitem or parse region name from title
+				value["tooltip"] = LLSLURL::buildSLURLfromPosGlobal(region_name,
+						result->mGlobalPos,	false);
 				add(result->getTitle(), value); 
 			}
 			result = std::find_if(result + 1, th_items.end(), boost::bind(
@@ -1010,9 +1011,7 @@ void LLLocationInputCtrl::changeLocationPresentation()
 	if(!mTextEntry->hasSelection() && text == mHumanReadableLocation)
 	{
 		//needs unescaped one
-		LLSLURL slurl;
-		LLAgentUI::buildSLURL(slurl, false);
-		mTextEntry->setText(slurl.getSLURLString());
+		mTextEntry->setText(LLAgentUI::buildSLURL(false));
 		mTextEntry->selectAll();
 
 		mMaturityIcon->setVisible(FALSE);
diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp
index 4e0a7594ba9dee0a9e51fc83a60449cf1263a043..e3817eecc45571de5414a16d1bc1c3b5d6c7a3b1 100644
--- a/indra/newview/llloginhandler.cpp
+++ b/indra/newview/llloginhandler.cpp
@@ -35,14 +35,13 @@
 #include "llloginhandler.h"
 
 // viewer includes
-#include "llsecapi.h"
 #include "lllogininstance.h"        // to check if logged in yet
 #include "llpanellogin.h"			// save_password_to_disk()
 #include "llstartup.h"				// getStartupState()
-#include "llslurl.h"
+#include "llurlsimstring.h"
 #include "llviewercontrol.h"		// gSavedSettings
 #include "llviewernetwork.h"		// EGridInfo
-#include "llviewerwindow.h"                    // getWindow()
+#include "llviewerwindow.h"			// getWindow()
 
 // library includes
 #include "llmd5.h"
@@ -61,33 +60,109 @@ bool LLLoginHandler::parseDirectLogin(std::string url)
 	LLURI uri(url);
 	parse(uri.queryMap());
 
-	// NOTE: Need to add direct login as per identity evolution
-	return true;
+	if (/*mWebLoginKey.isNull() ||*/
+		mFirstName.empty() ||
+		mLastName.empty())
+	{
+		return false;
+	}
+	else
+	{
+		return true;
+	}
 }
 
+
 void LLLoginHandler::parse(const LLSD& queryMap)
 {
+	//mWebLoginKey = queryMap["web_login_key"].asUUID();
+	mFirstName = queryMap["first_name"].asString();
+	mLastName = queryMap["last_name"].asString();
 	
-	if (queryMap.has("grid"))
+	EGridInfo grid_choice = GRID_INFO_NONE;
+	if (queryMap["grid"].asString() == "aditi")
 	{
-	  LLGridManager::getInstance()->setGridChoice(queryMap["grid"].asString());
+		grid_choice = GRID_INFO_ADITI;
 	}
-	
-	
-	std::string startLocation = queryMap["location"].asString();
-	
-	if (startLocation == "specify")
+	else if (queryMap["grid"].asString() == "agni")
+	{
+		grid_choice = GRID_INFO_AGNI;
+	}
+	else if (queryMap["grid"].asString() == "siva")
+	{
+		grid_choice = GRID_INFO_SIVA;
+	}
+	else if (queryMap["grid"].asString() == "damballah")
+	{
+		grid_choice = GRID_INFO_DAMBALLAH;
+	}
+	else if (queryMap["grid"].asString() == "durga")
+	{
+		grid_choice = GRID_INFO_DURGA;
+	}
+	else if (queryMap["grid"].asString() == "shakti")
+	{
+		grid_choice = GRID_INFO_SHAKTI;
+	}
+	else if (queryMap["grid"].asString() == "soma")
+	{
+		grid_choice = GRID_INFO_SOMA;
+	}
+	else if (queryMap["grid"].asString() == "ganga")
+	{
+		grid_choice = GRID_INFO_GANGA;
+	}
+	else if (queryMap["grid"].asString() == "vaak")
+	{
+		grid_choice = GRID_INFO_VAAK;
+	}
+	else if (queryMap["grid"].asString() == "uma")
+	{
+		grid_choice = GRID_INFO_UMA;
+	}
+	else if (queryMap["grid"].asString() == "mohini")
+	{
+		grid_choice = GRID_INFO_MOHINI;
+	}
+	else if (queryMap["grid"].asString() == "yami")
 	{
-	  LLStartUp::setStartSLURL(LLSLURL(LLGridManager::getInstance()->getGridLoginID(),
-					   queryMap["region"].asString()));
+		grid_choice = GRID_INFO_YAMI;
 	}
-	else if (startLocation == "home")
+	else if (queryMap["grid"].asString() == "nandi")
 	{
-	  LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
+		grid_choice = GRID_INFO_NANDI;
 	}
-	else if (startLocation == "last")
+	else if (queryMap["grid"].asString() == "mitra")
 	{
-	  LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST));
+		grid_choice = GRID_INFO_MITRA;
+	}
+	else if (queryMap["grid"].asString() == "radha")
+	{
+		grid_choice = GRID_INFO_RADHA;
+	}
+	else if (queryMap["grid"].asString() == "ravi")
+	{
+		grid_choice = GRID_INFO_RAVI;
+	}
+	else if (queryMap["grid"].asString() == "aruna")
+	{
+		grid_choice = GRID_INFO_ARUNA;
+	}
+
+	if(grid_choice != GRID_INFO_NONE)
+	{
+		LLViewerLogin::getInstance()->setGridChoice(grid_choice);
+	}
+
+	std::string startLocation = queryMap["location"].asString();
+
+	if (startLocation == "specify")
+	{
+		LLURLSimString::setString(queryMap["region"].asString());
+	}
+	else if (!startLocation.empty()) // "last" or "home" or ??? (let LLURLSimString figure it out)
+	{
+		LLURLSimString::setString(startLocation);
 	}
 }
 
@@ -145,65 +220,40 @@ bool LLLoginHandler::handle(const LLSD& tokens,
 		return true;
 	}
 	
-	if  (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)  //on splash page         
-	{
-	  // as the login page may change from grid to grid, as well as
-	  // things like username/password/etc, we simply refresh the
-	  // login page to make sure everything is set up correctly
-	  LLPanelLogin::loadLoginPage();
-	  LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
-	}
-	return true;
-}
-
+	std::string password = query_map["password"].asString();
 
+	if (!password.empty())
+	{
+		gSavedSettings.setBOOL("RememberPassword", TRUE);
 
-//  Initialize the credentials                                                                                              
-// If the passed in URL contains login info, parse                                                                          
-// that into a credential and web login key.  Otherwise                                                                     
-// check the command line.  If the command line                                                                             
-// does not contain any login creds, load the last saved                                                                    
-// ones from the protected credential store.                                                                                
-// This always returns with a credential structure set in the                                                               
-// login handler                                                                                                            
-LLPointer<LLCredential> LLLoginHandler::initializeLoginInfo()                                         
-{                                                                                                                           
-	LLPointer<LLCredential> result = NULL;                                                                               
-	// so try to load it from the UserLoginInfo                                                                          
-	result = loadSavedUserLoginInfo();                                                                                   
-	if (result.isNull())                                                                                                 
-	{                                                                                                                    
-		result =  gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());                       
-	}                                                                                                                    
-	
-	return result;                                                                                                       
-} 
-
+		if (password.substr(0,3) != "$1$")
+		{
+			LLMD5 pass((unsigned char*)password.c_str());
+			char md5pass[33];		/* Flawfinder: ignore */
+			pass.hex_digest(md5pass);
+			std::string hashed_password = ll_safe_string(md5pass, 32);
+			LLStartUp::savePasswordToDisk(hashed_password);
+		}
+	}
+			
 
-LLPointer<LLCredential> LLLoginHandler::loadSavedUserLoginInfo()
-{
-  // load the saved user login info into a LLCredential.
-  // perhaps this should be moved.
-	LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
-	if (cmd_line_login.size() == 3) 
+	if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)  //on splash page
 	{
-	
-		LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str());
-		char md5pass[33];               /* Flawfinder: ignore */
-		pass.hex_digest(md5pass);
-		LLSD identifier = LLSD::emptyMap();
-		identifier["type"] = "agent";
-		identifier["first_name"] = cmd_line_login[0];
-		identifier["last_name"] = cmd_line_login[1];
-		
-		LLSD authenticator = LLSD::emptyMap();
-		authenticator["type"] = "hash";
-		authenticator["algorithm"] = "md5";
-		authenticator["secret"] = md5pass;
-		// yuck, we'll fix this with mani's changes.
-		gSavedSettings.setBOOL("AutoLogin", TRUE);
-		return gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), 
-													   identifier, authenticator);
-	}
-	return NULL;
+		if (!mFirstName.empty() || !mLastName.empty())
+		{
+			// Fill in the name, and maybe the password
+			LLPanelLogin::setFields(mFirstName, mLastName, password);
+		}
+
+		//if (mWebLoginKey.isNull())
+		//{
+		//	LLPanelLogin::loadLoginPage();
+		//}
+		//else
+		//{
+		//	LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
+		//}
+		LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
+	}
+	return true;
 }
diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h
index c15b998c9127a4553418d9df219eb70150a0226e..ac4648761b2a447c27bee3e142819059f8bd603e 100644
--- a/indra/newview/llloginhandler.h
+++ b/indra/newview/llloginhandler.h
@@ -34,7 +34,6 @@
 #define LLLOGINHANDLER_H
 
 #include "llcommandhandler.h"
-#include "llsecapi.h"
 
 class LLLoginHandler : public LLCommandHandler
 {
@@ -47,15 +46,19 @@ class LLLoginHandler : public LLCommandHandler
 	// secondlife:///app/login?first=Bob&last=Dobbs
 	bool parseDirectLogin(std::string url);
 
+	std::string getFirstName() const { return mFirstName; }
+	std::string getLastName() const { return mLastName; }
+
 	// Web-based login unsupported
 	//LLUUID getWebLoginKey() const { return mWebLoginKey; }
 
-	LLPointer<LLCredential> loadSavedUserLoginInfo();  
-	LLPointer<LLCredential> initializeLoginInfo();
-
 private:
 	void parse(const LLSD& queryMap);
 
+private:
+	std::string mFirstName;
+	std::string mLastName;
+	//LLUUID mWebLoginKey;
 };
 
 extern LLLoginHandler gLoginHandler;
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 0459c85050716bc7523c491b346193426ebe00aa..24c72c65cede0f674b90b49dcd93a42354d0532e 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -48,16 +48,13 @@
 // newview
 #include "llviewernetwork.h"
 #include "llviewercontrol.h"
-#include "llslurl.h"
-#include "llstartup.h"
+#include "llurlsimstring.h"
 #include "llfloaterreg.h"
 #include "llnotifications.h"
 #include "llwindow.h"
 #if LL_LINUX || LL_SOLARIS
 #include "lltrans.h"
 #endif
-#include "llsecapi.h"
-#include "llstartup.h"
 
 static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
 static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
@@ -86,14 +83,14 @@ LLLoginInstance::~LLLoginInstance()
 {
 }
 
-void LLLoginInstance::connect(LLPointer<LLCredential> credentials)
+void LLLoginInstance::connect(const LLSD& credentials)
 {
 	std::vector<std::string> uris;
-	LLGridManager::getInstance()->getLoginURIs(uris);
+	LLViewerLogin::getInstance()->getLoginURIs(uris);
 	connect(uris.front(), credentials);
 }
 
-void LLLoginInstance::connect(const std::string& uri, LLPointer<LLCredential> credentials)
+void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials)
 {
 	mAttemptComplete = false; // Reset attempt complete at this point!
 	constructAuthParams(credentials);
@@ -105,7 +102,7 @@ void LLLoginInstance::reconnect()
 	// Sort of like connect, only using the pre-existing
 	// request params.
 	std::vector<std::string> uris;
-	LLGridManager::getInstance()->getLoginURIs(uris);
+	LLViewerLogin::getInstance()->getLoginURIs(uris);
 	mLoginModule->connect(uris.front(), mRequestData);
 }
 
@@ -121,7 +118,7 @@ LLSD LLLoginInstance::getResponse()
 	return mResponseData; 
 }
 
-void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credential)
+void LLLoginInstance::constructAuthParams(const LLSD& credentials)
 {
 	// Set up auth request options.
 //#define LL_MINIMIAL_REQUESTED_OPTIONS
@@ -148,10 +145,8 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	requested_options.append("adult_compliant"); 
 	//requested_options.append("inventory-targets");
 	requested_options.append("buddy-list");
-	requested_options.append("newuser-config");
 	requested_options.append("ui-config");
 #endif
-	requested_options.append("voice-config");
 	requested_options.append("tutorial_setting");
 	requested_options.append("login-flags");
 	requested_options.append("global-textures");
@@ -160,18 +155,20 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 		gSavedSettings.setBOOL("UseDebugMenus", TRUE);
 		requested_options.append("god-connect");
 	}
-	
-	// (re)initialize the request params with creds.
-	LLSD request_params = user_credential->getLoginParams();
 
 	char hashed_mac_string[MD5HEX_STR_SIZE];		/* Flawfinder: ignore */
 	LLMD5 hashed_mac;
-	unsigned char MACAddress[MAC_ADDRESS_BYTES];
-	LLUUID::getNodeID(MACAddress);	
-	hashed_mac.update( MACAddress, MAC_ADDRESS_BYTES );
+	hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
 	hashed_mac.finalize();
 	hashed_mac.hex_digest(hashed_mac_string);
-	
+
+	// prepend "$1$" to the password to indicate its the md5'd version.
+	std::string dpasswd("$1$");
+	dpasswd.append(credentials["passwd"].asString());
+
+	// (re)initialize the request params with creds.
+	LLSD request_params(credentials);
+	request_params["passwd"] = dpasswd;
 	request_params["start"] = construct_start_string();
 	request_params["skipoptional"] = mSkipOptionalUpdate;
 	request_params["agree_to_tos"] = false; // Always false here. Set true in 
@@ -250,15 +247,6 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
 			LLSD data(LLSD::emptyMap());
 			data["message"] = message_response;
 			data["reply_pump"] = TOS_REPLY_PUMP;
-			if(response.has("error_code"))
-			{
-				data["error_code"] = response["error_code"];
-			}
-			if(response.has("certificate"))
-			{
-				data["certificate"] = response["certificate"];
-			}
-			
 			LLFloaterReg::showInstance("message_critical", data);
 			LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
 				.listen(TOS_LISTENER_NAME,
@@ -466,31 +454,20 @@ bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD&
 std::string construct_start_string()
 {
 	std::string start;
-	LLSLURL start_slurl = LLStartUp::getStartSLURL();
-	switch(start_slurl.getType())
+	if (LLURLSimString::parse())
 	{
-		case LLSLURL::LOCATION:
-		{
-			// a startup URL was specified
-			LLVector3 position = start_slurl.getPosition();
-			std::string unescaped_start = 
+		// a startup URL was specified
+		std::string unescaped_start = 
 			STRINGIZE(  "uri:" 
-					  << start_slurl.getRegion() << "&" 
-						<< position[VX] << "&" 
-						<< position[VY] << "&" 
-						<< position[VZ]);
-			start = xml_escape_string(unescaped_start);
-			break;
-		}
-		case LLSLURL::HOME_LOCATION:
-		{
-			start = "home";
-			break;
-		}
-		default:
-		{
-			start = "last";
-		}
+						<< LLURLSimString::sInstance.mSimName << "&" 
+						<< LLURLSimString::sInstance.mX << "&" 
+						<< LLURLSimString::sInstance.mY << "&" 
+						<< LLURLSimString::sInstance.mZ);
+		start = xml_escape_string(unescaped_start);
+	}
+	else
+	{
+		start = gSavedSettings.getString("LoginLocation");
 	}
 	return start;
 }
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 44271bb75e617b766a9fcf405313195ef3d39b37..c8704eddb497dfb98ae7bebfe2f790d34fb4fa95 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -36,7 +36,6 @@
 #include "lleventdispatcher.h"
 #include <boost/scoped_ptr.hpp>
 #include <boost/function.hpp>
-#include "llsecapi.h"
 class LLLogin;
 class LLEventStream;
 class LLNotificationsInterface;
@@ -49,8 +48,8 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	LLLoginInstance();
 	~LLLoginInstance();
 
-	void connect(LLPointer<LLCredential> credentials); // Connect to the current grid choice.
-	void connect(const std::string& uri, LLPointer<LLCredential> credentials);	// Connect to the given uri.
+	void connect(const LLSD& credential); // Connect to the current grid choice.
+	void connect(const std::string& uri, const LLSD& credential);	// Connect to the given uri.
 	void reconnect(); // reconnect using the current credentials.
 	void disconnect();
 
@@ -82,7 +81,7 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }
 
 private:
-	void constructAuthParams(LLPointer<LLCredential> user_credentials);
+	void constructAuthParams(const LLSD& credentials); 
 	void updateApp(bool mandatory, const std::string& message);
 	bool updateDialogCallback(const LLSD& notification, const LLSD& response);
 
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index c3d0f1bfc25b8a852eca7b0fb4fb47c3c2d16e85..e11df06d868c6a87b82c28756348bf5ee24949b3 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -52,6 +52,7 @@
 #include "llsearchcombobox.h"
 #include "llsidetray.h"
 #include "llslurl.h"
+#include "llurlsimstring.h"
 #include "llurlregistry.h"
 #include "llurldispatcher.h"
 #include "llviewerinventory.h"
@@ -507,34 +508,29 @@ void LLNavigationBar::onLocationSelection()
 	
 	std::string region_name;
 	LLVector3 local_coords(128, 128, 0);
+	S32 x = 0, y = 0, z = 0;
 	// Is the typed location a SLURL?
-	LLSLURL slurl = LLSLURL(typed_location);
-	if (slurl.getType() == LLSLURL::LOCATION)
+	if (LLSLURL::isSLURL(typed_location))
 	{
-	  region_name = slurl.getRegion();
-	  local_coords = slurl.getPosition();
+		// Yes. Extract region name and local coordinates from it.
+		if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), &region_name, &x, &y, &z))
+				local_coords.set(x, y, z);
+		else
+			return;
 	}
-	else if(!slurl.isValid())
+	// we have to do this check after previous, because LLUrlRegistry contains handlers for slurl too  
+	//but we need to know whether typed_location is a simple http url.
+	else if (LLUrlRegistry::instance().isUrl(typed_location)) 
 	{
-	  // we have to do this check after previous, because LLUrlRegistry contains handlers for slurl too  
-	  // but we need to know whether typed_location is a simple http url.
-	  if (LLUrlRegistry::instance().isUrl(typed_location)) 
-	    {
 		// display http:// URLs in the media browser, or
 		// anything else is sent to the search floater
 		LLWeb::loadURL(typed_location);
 		return;
-	  }
-	  else
-	  {
-	      // assume that an user has typed the {region name} or possible {region_name, parcel}
-	      region_name  = typed_location.substr(0,typed_location.find(','));
-	    }
 	}
 	else
 	{
-	  // was an app slurl, home, whatever.  Bail
-	  return;
+		// assume that an user has typed the {region name} or possible {region_name, parcel}
+		region_name  = typed_location.substr(0,typed_location.find(','));
 	}
 	
 	// Resolve the region name to its global coordinates.
@@ -566,7 +562,7 @@ void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos)
 	 */
 		LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_NO_MATURITY,
 					gAgent.getPosAgentFromGlobal(global_agent_pos));
-	std::string tooltip (LLSLURL(gAgent.getRegion()->getName(), global_agent_pos).getSLURLString());
+	std::string tooltip (LLSLURL::buildSLURLfromPosGlobal(gAgent.getRegion()->getName(), global_agent_pos, false));
 	
 	LLLocationHistoryItem item (location,
 			global_agent_pos, tooltip,TYPED_REGION_SLURL);// we can add into history only TYPED location
@@ -655,7 +651,7 @@ void LLNavigationBar::onRegionNameResponse(
 	LLVector3d region_pos = from_region_handle(region_handle);
 	LLVector3d global_pos = region_pos + (LLVector3d) local_coords;
 
-	llinfos << "Teleporting to: " << LLSLURL(region_name,	global_pos).getSLURLString()  << llendl;
+	llinfos << "Teleporting to: " << LLSLURL::buildSLURLfromPosGlobal(region_name,	global_pos, false)  << llendl;
 	gAgent.teleportViaLocation(global_pos);
 }
 
diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp
index 197a0ef72840e96b895a3814f6461f98a115aa00..d6d48a4eadce51b06436ba6844c24716cdb25a60 100644
--- a/indra/newview/lloutputmonitorctrl.cpp
+++ b/indra/newview/lloutputmonitorctrl.cpp
@@ -142,7 +142,7 @@ void LLOutputMonitorCtrl::draw()
 
 	// Copied from llmediaremotectrl.cpp
 	// *TODO: Give the LLOutputMonitorCtrl an agent-id to monitor, then
-	// call directly into LLVoiceClient::getInstance() to ask if that agent-id is muted, is
+	// call directly into gVoiceClient to ask if that agent-id is muted, is
 	// speaking, and what power.  This avoids duplicating data, which can get
 	// out of sync.
 	const F32 LEVEL_0 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL / 3.f;
@@ -151,14 +151,14 @@ void LLOutputMonitorCtrl::draw()
 
 	if (getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull())
 	{
-		setPower(LLVoiceClient::getInstance()->getCurrentPower(mSpeakerId));
+		setPower(gVoiceClient->getCurrentPower(mSpeakerId));
 		if(mIsAgentControl)
 		{
-			setIsTalking(LLVoiceClient::getInstance()->getUserPTTState());
+			setIsTalking(gVoiceClient->getUserPTTState());
 		}
 		else
 		{
-			setIsTalking(LLVoiceClient::getInstance()->getIsSpeaking(mSpeakerId));
+			setIsTalking(gVoiceClient->getIsSpeaking(mSpeakerId));
 		}
 	}
 
diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h
index 3a83da67e297711dcd69330b8025c510d73e23d3..b7454a5066a60379fd4e47a6dd15970d7e0ab575 100644
--- a/indra/newview/lloutputmonitorctrl.h
+++ b/indra/newview/lloutputmonitorctrl.h
@@ -143,7 +143,7 @@ class LLOutputMonitorCtrl
 	LLPointer<LLUIImage> mImageLevel2;
 	LLPointer<LLUIImage> mImageLevel3;
 
-	/** whether to deal with LLVoiceClient::getInstance() directly */
+	/** whether to deal with gVoiceClient directly */
 	bool			mAutoUpdate;
 
 	/** uuid of a speaker being monitored */
diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp
index 3f1b23ba14542546666911986ef0569830b0e4b2..67e048885f76cbc2c5756408a0346355272f3b5f 100644
--- a/indra/newview/lloverlaybar.cpp
+++ b/indra/newview/lloverlaybar.cpp
@@ -258,7 +258,7 @@ void LLOverlayBar::refresh()
 	{
 		// update "remotes"
 		childSetVisible("media_remote_container", TRUE);
-		childSetVisible("voice_remote_container", LLVoiceClient::getInstance()->voiceEnabled());
+		childSetVisible("voice_remote_container", LLVoiceClient::voiceEnabled());
 		childSetVisible("state_buttons", TRUE);
 	}
 
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index b554af66f05ed9ce37c373ca4b08041e6fdb046b..a0ba2f739b07a28e8fa8f9cec4ecd104331afb64 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -163,7 +163,7 @@ BOOL LLPanelAvatarNotes::postBuild()
 	resetControls();
 	resetData();
 
-	LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this);
+	gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this);
 
 	return TRUE;
 }
@@ -374,7 +374,7 @@ void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channel
 		return;
 	}
 
-	childSetEnabled("call", LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
+	childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
 }
 
 void LLPanelAvatarNotes::setAvatarId(const LLUUID& id)
@@ -518,7 +518,7 @@ BOOL LLPanelAvatarProfile::postBuild()
 	pic = getChild<LLTextureCtrl>("real_world_pic");
 	pic->setFallbackImageName("default_profile_picture.j2c");
 
-	LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this);
+	gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this);
 
 	resetControls();
 	resetData();
@@ -809,7 +809,7 @@ void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &chann
 		return;
 	}
 
-	childSetEnabled("call", LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
+	childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
 }
 
 void LLPanelAvatarProfile::setAvatarId(const LLUUID& id)
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 716166a94552ea68a02b25248c8b4b3e8628b149..c00b6a41473e187e2b3368645cab0ef1263a72bd 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -201,7 +201,7 @@ BOOL LLPanelGroup::postBuild()
 		mJoinText = panel_general->getChild<LLUICtrl>("join_cost_text");
 	}
 
-	LLVoiceClient::getInstance()->addObserver(this);
+	gVoiceClient->addObserver(this);
 	
 	return TRUE;
 }
@@ -322,7 +322,7 @@ void LLPanelGroup::onChange(EStatusType status, const std::string &channelURI, b
 		return;
 	}
 
-	childSetEnabled("btn_call", LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
+	childSetEnabled("btn_call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
 }
 
 void LLPanelGroup::notifyObservers()
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 709bb83fe42097ab83fbe86fe86100687a3870d1..c34f0633b9860445303aef6eefa9862fcfdfa65c 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -81,8 +81,7 @@ void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::E
 
 void LLPanelChatControlPanel::updateCallButton()
 {
-	// hide/show call button
-	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+	bool voice_enabled = LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
 
 	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
 	
@@ -125,7 +124,7 @@ BOOL LLPanelChatControlPanel::postBuild()
 	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
 	childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this));
 
-	LLVoiceClient::getInstance()->addObserver(this);
+	gVoiceClient->addObserver(this);
 
 	return TRUE;
 }
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 42e4b397db2fdf92371f323e1551ddf188d5a8ab..ee4dcc44fe14bf447fa8458acb59173e05a5a3f3 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -51,12 +51,11 @@
 #include "llfocusmgr.h"
 #include "lllineeditor.h"
 #include "llnotificationsutil.h"
-#include "llsecapi.h"
 #include "llstartup.h"
 #include "lltextbox.h"
 #include "llui.h"
 #include "lluiconstants.h"
-#include "llslurl.h"
+#include "llurlsimstring.h"
 #include "llversioninfo.h"
 #include "llviewerhelp.h"
 #include "llviewertexturelist.h"
@@ -78,7 +77,6 @@
 #pragma warning(disable: 4355)      // 'this' used in initializer list
 #endif  // LL_WINDOWS
 
-#include "llsdserialize.h"
 #define USE_VIEWER_AUTH 0
 
 const S32 BLACK_BORDER_HEIGHT = 160;
@@ -106,6 +104,7 @@ class LLLoginRefreshHandler : public LLCommandHandler
 LLLoginRefreshHandler gLoginRefreshHandler;
 
 
+
 // helper class that trys to download a URL from a web site and calls a method 
 // on parent class indicating if the web server is working or not
 class LLIamHereLogin : public LLHTTPClient::Responder
@@ -154,6 +153,10 @@ namespace {
 	boost::intrusive_ptr< LLIamHereLogin > gResponsePtr = 0;
 };
 
+void set_start_location(LLUICtrl* ctrl, void* data)
+{
+    LLURLSimString::setString(ctrl->getValue().asString());
+}
 
 //---------------------------------------------------------------------------
 // Public methods
@@ -184,7 +187,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 		delete LLPanelLogin::sInstance;
 	}
 
-	mPasswordModified = FALSE;
 	LLPanelLogin::sInstance = this;
 
 	// add to front so we are the bottom-most child
@@ -211,7 +213,10 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	}
 
 #if !USE_VIEWER_AUTH
-	childSetPrevalidate("username_edit", LLTextValidate::validateASCIIPrintableNoPipe);
+	childSetPrevalidate("first_name_edit", LLTextValidate::validateASCIIPrintableNoSpace);
+	childSetPrevalidate("last_name_edit", LLTextValidate::validateASCIIPrintableNoSpace);
+
+	childSetCommitCallback("password_edit", mungePassword, this);
 	getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
 
 	// change z sort of clickable text to be behind buttons
@@ -223,19 +228,27 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 
 	LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
 
-	if(LLStartUp::getStartSLURL().getType() != LLSLURL::LOCATION)
+	std::string sim_string = LLURLSimString::sInstance.mSimString;
+	if(sim_string.empty())
 	{
-		LLSLURL slurl(gSavedSettings.getString("LoginLocation"));
-		LLStartUp::setStartSLURL(slurl);
+		LLURLSimString::setString(gSavedSettings.getString("LoginLocation"));
+		sim_string = LLURLSimString::sInstance.mSimString;
 	}
-	updateLocationCombo(false);
-	
-	combo->setCommitCallback(onSelectLocation, NULL);
+
+	if (!sim_string.empty())
+	{
+		// Replace "<Type region name>" with this region name
+		combo->remove(2);
+		combo->add( sim_string );
+		combo->setTextEntry(sim_string);
+		combo->setCurrentByIndex( 2 );
+	}
+
+	combo->setCommitCallback( &set_start_location, NULL );
 
 	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");
 	server_choice_combo->setCommitCallback(onSelectServer, NULL);
 	server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1));
-	updateServerCombo();
 
 	childSetAction("connect_btn", onClickConnect, this);
 
@@ -291,10 +304,17 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 
 	// kick off a request to grab the url manually
 	gResponsePtr = LLIamHereLogin::build( this );
+	std::string login_page = gSavedSettings.getString("LoginPage");
+	if (login_page.empty())
+	{
+		login_page = getString( "real_url" );
+	}
+	LLHTTPClient::head( login_page, gResponsePtr );
 
-	LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr );
-	
-	updateLocationCombo(false);
+#if !USE_VIEWER_AUTH
+	// Initialize visibility (and don't force visibility - use prefs)
+	refreshLocation( false );
+#endif
 
 }
 
@@ -358,6 +378,21 @@ void LLPanelLogin::setSiteIsAlive( bool alive )
 	}
 }
 
+void LLPanelLogin::mungePassword(LLUICtrl* caller, void* user_data)
+{
+	LLPanelLogin* self = (LLPanelLogin*)user_data;
+	LLLineEditor* editor = (LLLineEditor*)caller;
+	std::string password = editor->getText();
+
+	// Re-md5 if we've changed at all
+	if (password != self->mIncomingPassword)
+	{
+		LLMD5 pass((unsigned char *)password.c_str());
+		char munged_password[MD5HEX_STR_SIZE];
+		pass.hex_digest(munged_password);
+		self->mMungedPassword = munged_password;
+	}
+}
 
 LLPanelLogin::~LLPanelLogin()
 {
@@ -464,14 +499,14 @@ void LLPanelLogin::giveFocus()
 	if( sInstance )
 	{
 		// Grab focus and move cursor to first blank input field
-		std::string username = sInstance->childGetText("username_edit");
+		std::string first = sInstance->childGetText("first_name_edit");
 		std::string pass = sInstance->childGetText("password_edit");
 
-		BOOL have_username = !username.empty();
+		BOOL have_first = !first.empty();
 		BOOL have_pass = !pass.empty();
 
 		LLLineEditor* edit = NULL;
-		if (have_username && !have_pass)
+		if (have_first && !have_pass)
 		{
 			// User saved his name but not his password.  Move
 			// focus to password field.
@@ -480,7 +515,7 @@ void LLPanelLogin::giveFocus()
 		else
 		{
 			// User doesn't have a name, so start there.
-			edit = sInstance->getChild<LLLineEditor>("username_edit");
+			edit = sInstance->getChild<LLLineEditor>("first_name_edit");
 		}
 
 		if (edit)
@@ -502,8 +537,8 @@ void LLPanelLogin::showLoginWidgets()
 	// *TODO: Append all the usual login parameters, like first_login=Y etc.
 	std::string splash_screen_url = sInstance->getString("real_url");
 	web_browser->navigateTo( splash_screen_url, "text/html" );
-	LLUICtrl* username_edit = sInstance->getChild<LLUICtrl>("username_edit");
-	username_edit->setFocus(TRUE);
+	LLUICtrl* first_name_edit = sInstance->getChild<LLUICtrl>("first_name_edit");
+	first_name_edit->setFocus(TRUE);
 }
 
 // static
@@ -525,120 +560,77 @@ void LLPanelLogin::show(const LLRect &rect,
 }
 
 // static
-void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
-							 BOOL remember)
+void LLPanelLogin::setFields(const std::string& firstname,
+			     const std::string& lastname,
+			     const std::string& password)
 {
 	if (!sInstance)
 	{
 		llwarns << "Attempted fillFields with no login view shown" << llendl;
 		return;
 	}
-	LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL;
 
-	LLSD identifier = credential->getIdentifier();
-	if((std::string)identifier["type"] == "agent") 
-	{
-		sInstance->childSetText("username_edit", (std::string)identifier["first_name"] + " " + 
-								(std::string)identifier["last_name"]);	
-	}
-	else if((std::string)identifier["type"] == "account")
-	{
-		sInstance->childSetText("username_edit", (std::string)identifier["account_name"]);		
-	}
-	else
-	{
-	  sInstance->childSetText("username_edit", std::string());	
-	}
-	// if the password exists in the credential, set the password field with
-	// a filler to get some stars
-	LLSD authenticator = credential->getAuthenticator();
-	LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL;
-	if(authenticator.isMap() && 
-	   authenticator.has("secret") && 
-	   (authenticator["secret"].asString().size() > 0))
+	sInstance->childSetText("first_name_edit", firstname);
+	sInstance->childSetText("last_name_edit", lastname);
+
+	// Max "actual" password length is 16 characters.
+	// Hex digests are always 32 characters.
+	if (password.length() == 32)
 	{
-		
 		// This is a MD5 hex digest of a password.
 		// We don't actually use the password input field, 
 		// fill it with MAX_PASSWORD characters so we get a 
 		// nice row of asterixes.
 		const std::string filler("123456789!123456");
-		sInstance->childSetText("password_edit", std::string("123456789!123456"));
+		sInstance->childSetText("password_edit", filler);
+		sInstance->mIncomingPassword = filler;
+		sInstance->mMungedPassword = password;
 	}
 	else
 	{
-		sInstance->childSetText("password_edit", std::string());		
+		// this is a normal text password
+		sInstance->childSetText("password_edit", password);
+		sInstance->mIncomingPassword = password;
+		LLMD5 pass((unsigned char *)password.c_str());
+		char munged_password[MD5HEX_STR_SIZE];
+		pass.hex_digest(munged_password);
+		sInstance->mMungedPassword = munged_password;
 	}
-	sInstance->childSetValue("remember_check", remember);
 }
 
 
 // static
-void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
-							 BOOL remember)
+void LLPanelLogin::addServer(const std::string& server, S32 domain_name)
 {
 	if (!sInstance)
 	{
-		llwarns << "Attempted getFields with no login view shown" << llendl;
+		llwarns << "Attempted addServer with no login view shown" << llendl;
 		return;
 	}
-	
-	// load the credential so we can pass back the stored password or hash if the user did
-	// not modify the password field.
-	
-	credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
 
-	LLSD identifier = LLSD::emptyMap();
-	LLSD authenticator = LLSD::emptyMap();
-	
-	if(credential.notNull())
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
+	combo->add(server, LLSD(domain_name) );
+	combo->setCurrentByIndex(0);
+}
+
+// static
+void LLPanelLogin::getFields(std::string *firstname,
+			     std::string *lastname,
+			     std::string *password)
+{
+	if (!sInstance)
 	{
-		authenticator = credential->getAuthenticator();
+		llwarns << "Attempted getFields with no login view shown" << llendl;
+		return;
 	}
 
-	std::string username = sInstance->childGetText("username_edit");
-	LLStringUtil::trim(username);
-	std::string password = sInstance->childGetText("password_edit");
+	*firstname = sInstance->childGetText("first_name_edit");
+	LLStringUtil::trim(*firstname);
 
-	LL_INFOS2("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
-	// determine if the username is a first/last form or not.
-	size_t separator_index = username.find_first_of(' ');
-	if (separator_index == username.npos)
-	{
-		LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL;
-		// single username, so this is a 'clear' identifier
-		identifier["type"] = "account";
-		identifier["account_name"] = username;
-		
-		if (LLPanelLogin::sInstance->mPasswordModified)
-		{
-			authenticator = LLSD::emptyMap();
-			// password is plaintext
-			authenticator["type"] = "clear";
-			authenticator["secret"] = password;
-		}
-	}
-	else if (separator_index == username.find_last_of(' '))
-	{
-		LL_INFOS2("Credentials", "Authentication") << "agent: " << username << LL_ENDL;
-		// traditional firstname / lastname
-		identifier["type"] = "agent";
-		identifier["first_name"] = username.substr(0, separator_index);
-		identifier["last_name"] = username.substr(separator_index+1, username.npos);
-		
-		if (LLPanelLogin::sInstance->mPasswordModified)
-		{
-			authenticator = LLSD::emptyMap();
-			authenticator["type"] = "hash";
-			authenticator["algorithm"] = "md5";
-			LLMD5 pass((const U8 *)password.c_str());
-			char md5pass[33];               /* Flawfinder: ignore */
-			pass.hex_digest(md5pass);
-			authenticator["secret"] = md5pass;
-		}
-	}
-	credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), identifier, authenticator);
-	remember = sInstance->childGetValue("remember_check");
+	*lastname = sInstance->childGetText("last_name_edit");
+	LLStringUtil::trim(*lastname);
+
+	*password = sInstance->mMungedPassword;
 }
 
 // static
@@ -658,147 +650,64 @@ BOOL LLPanelLogin::isGridComboDirty()
 }
 
 // static
-BOOL LLPanelLogin::areCredentialFieldsDirty()
+void LLPanelLogin::getLocation(std::string &location)
 {
 	if (!sInstance)
 	{
-		llwarns << "Attempted getServer with no login view shown" << llendl;
-	}
-	else
-	{
-		std::string username = sInstance->childGetText("username_edit");
-		LLStringUtil::trim(username);
-		std::string password = sInstance->childGetText("password_edit");
-		LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("username_edit");
-		if(ctrl && ctrl->isDirty())
-		{
-			return true;
-		}
-		ctrl = sInstance->getChild<LLLineEditor>("password_edit");
-		if(ctrl && ctrl->isDirty()) 
-		{
-			return true;
-		}
+		llwarns << "Attempted getLocation with no login view shown" << llendl;
+		return;
 	}
-	return false;	
+	
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+	location = combo->getValue().asString();
 }
 
-
 // static
-void LLPanelLogin::updateLocationCombo( bool force_visible )
+void LLPanelLogin::refreshLocation( bool force_visible )
 {
-	if (!sInstance) 
-	{
-		return;
-	}	
-	
-	llinfos << "updatelocationcombo " << LLStartUp::getStartSLURL().asString() << llendl;
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
-	
-	switch(LLStartUp::getStartSLURL().getType())
-	{
-		case LLSLURL::LOCATION:
-		{
-			
-			combo->setCurrentByIndex( 2 );	
-			combo->setTextEntry(LLStartUp::getStartSLURL().getLocationString());	
-			break;
-		}
-		case LLSLURL::HOME_LOCATION:
-			combo->setCurrentByIndex(1);
-			break;
-		default:
-			combo->setCurrentByIndex(0);
-			break;
-	}
-	
+	if (!sInstance) return;
+
+#if USE_VIEWER_AUTH
+	loadLoginPage();
+#else
 	BOOL show_start = TRUE;
-	
+
 	if ( ! force_visible )
+	{
+		// Don't show on first run after install
+		// Otherwise ShowStartLocation defaults to true.
 		show_start = gSavedSettings.getBOOL("ShowStartLocation");
+	}
+
+	// Update the value of the location combo.
+	updateLocationUI();
 	
 	sInstance->childSetVisible("start_location_combo", show_start);
 	sInstance->childSetVisible("start_location_text", show_start);
-	
-	sInstance->childSetVisible("server_combo", TRUE);
-}
 
-// static
-void LLPanelLogin::onSelectLocation(LLUICtrl*, void*)
-{
-	if (!sInstance) return;
-	
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
-	S32 index = combo->getCurrentIndex();
-	
-	switch (index)
-	{
-		case 2:
-		{
-			LLSLURL slurl = LLSLURL(combo->getSelectedValue());
-			if((slurl.getType() == LLSLURL::LOCATION) &&
-			   (slurl.getGrid() != LLStartUp::getStartSLURL().getGrid()))
-			{
-				
-
-				// we've changed the grid, so update the grid selection
-				try 
-				{
-					LLStartUp::setStartSLURL(slurl);
-				}
-				catch (LLInvalidGridName ex)
-				{
-					LLSD args;	
-					args["GRID"] = slurl.getGrid();
-					LLNotificationsUtil::add("InvalidGrid", args);
-					return; 
-				}	
-				loadLoginPage();
-			}
-			break;
-		}
-		case 1:
-		{
-			LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
-			break;
-		}
-		default:
-		{
-			LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST));
-			break;
-		}
-	}
-}
+	BOOL show_server = gSavedSettings.getBOOL("ForceShowGrid");
+	sInstance->childSetVisible("server_combo", show_server);
 
+#endif
+}
 
 // static
-void LLPanelLogin::getLocation(LLSLURL& slurl)
+void LLPanelLogin::updateLocationUI()
 {
-	LLSLURL result;
-	if (!sInstance)
-	{
-		llwarns << "Attempted getLocation with no login view shown" << llendl;
-	}
-	
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+	if (!sInstance) return;
 	
-	switch(combo->getCurrentIndex())
+	std::string sim_string = LLURLSimString::sInstance.mSimString;
+	if (!sim_string.empty())
 	{
-		case 0:
-			slurl = LLSLURL(LLSLURL::SIM_LOCATION_HOME);
-		case 1:
-			slurl =  LLSLURL(LLSLURL::SIM_LOCATION_LAST);
-		default:
-			slurl = LLSLURL(combo->getValue().asString());
+		// Replace "<Type region name>" with this region name
+		LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+		combo->remove(2);
+		combo->add( sim_string );
+		combo->setTextEntry(sim_string);
+		combo->setCurrentByIndex( 2 );
 	}
 }
 
-void LLPanelLogin::setLocation(const LLSLURL& slurl)
-{
-	LLStartUp::setStartSLURL(slurl);
-	updateServer();
-}
-
 // static
 void LLPanelLogin::closePanel()
 {
@@ -832,13 +741,15 @@ void LLPanelLogin::loadLoginPage()
 	
 	std::ostringstream oStr;
 
-	std::string login_page = LLGridManager::getInstance()->getLoginPage();
-
+	std::string login_page = gSavedSettings.getString("LoginPage");
+	if (login_page.empty())
+	{
+		login_page = sInstance->getString( "real_url" );
+	}
 	oStr << login_page;
 	
 	// Use the right delimeter depending on how LLURI parses the URL
 	LLURI login_page_uri = LLURI(login_page);
-	
 	std::string first_query_delimiter = "&";
 	if (login_page_uri.queryMap().size() == 0)
 	{
@@ -870,10 +781,11 @@ void LLPanelLogin::loadLoginPage()
 	curl_free(curl_version);
 
 	// Grid
-	char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLoginID().c_str(), 0);
+	char* curl_grid = curl_escape(LLViewerLogin::getInstance()->getGridLabel().c_str(), 0);
 	oStr << "&grid=" << curl_grid;
 	curl_free(curl_grid);
-	gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
+
+	gViewerWindow->setMenuBackgroundColor(false, !LLViewerLogin::getInstance()->isInProductionGrid());
 	gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
 
 
@@ -898,20 +810,30 @@ void LLPanelLogin::loadLoginPage()
 		location = gSavedSettings.getString("LoginLocation");
 	}
 	
-	std::string username;
+	std::string firstname, lastname;
 
     if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
     {
         LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
-		username = cmd_line_login[0].asString() + " " + cmd_line_login[1];
+		firstname = cmd_line_login[0].asString();
+		lastname = cmd_line_login[1].asString();
         password = cmd_line_login[2].asString();
     }
     	
+	if (firstname.empty())
+	{
+		firstname = gSavedSettings.getString("FirstName");
+	}
+	
+	if (lastname.empty())
+	{
+		lastname = gSavedSettings.getString("LastName");
+	}
 	
 	char* curl_region = curl_escape(region.c_str(), 0);
 
-	oStr <<"username=" << username <<
-		 "&location=" << location <<	"&region=" << curl_region;
+	oStr <<"firstname=" << firstname <<
+		"&lastname=" << lastname << "&location=" << location <<	"&region=" << curl_region;
 	
 	curl_free(curl_region);
 
@@ -944,7 +866,7 @@ void LLPanelLogin::loadLoginPage()
 #endif
 	
 	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
+	
 	// navigate to the "real" page
 	if (gSavedSettings.getBOOL("RegInClient"))
 	{
@@ -993,33 +915,34 @@ void LLPanelLogin::onClickConnect(void *)
 		// JC - Make sure the fields all get committed.
 		sInstance->setFocus(FALSE);
 
-		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
-		LLSD combo_val = combo->getSelectedValue();
-		if (combo_val.isUndefined())
+		std::string first = sInstance->childGetText("first_name_edit");
+		std::string last  = sInstance->childGetText("last_name_edit");
+		LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+		std::string combo_text = combo->getSimple();
+		
+		bool has_first_and_last = !(first.empty() || last.empty());
+		bool has_location = false;
+
+		if(combo_text=="<Type region name>" || combo_text =="")
 		{
-			combo_val = combo->getValue();
+			// *NOTE: Mani - Location field is not always committed by this point!
+			// This may be duplicate work, but better than not doing the work!
+			LLURLSimString::sInstance.setString("");
 		}
-		if(combo_val.isUndefined())
+		else 
 		{
-			LLNotificationsUtil::add("StartRegionEmpty");
-			return;
-		}		
-		try
-		{
-			LLGridManager::getInstance()->setGridChoice(combo_val.asString());
+			// *NOTE: Mani - Location field is not always committed by this point!
+			LLURLSimString::sInstance.setString(combo_text);
+			has_location = true;
 		}
-		catch (LLInvalidGridName ex)
+
+		if(!has_first_and_last)
 		{
-			LLSD args;
-			args["GRID"] = combo_val.asString();
-			LLNotificationsUtil::add("InvalidGrid", args);
-			return;
+			LLNotificationsUtil::add("MustHaveAccountToLogIn");
 		}
-		
-		std::string username = sInstance->childGetText("username_edit");
-		if(username.empty())
+		else if(!has_location)
 		{
-			LLNotificationsUtil::add("MustHaveAccountToLogIn");
+			LLNotificationsUtil::add("StartRegionEmpty");
 		}
 		else
 		{
@@ -1082,8 +1005,6 @@ void LLPanelLogin::onClickHelp(void*)
 // static
 void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
 {
-	LLPanelLogin *This = (LLPanelLogin *) user_data;
-	This->mPasswordModified = TRUE;
 	if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE)
 	{
 		LLNotificationsUtil::add("CapsKeyOn");
@@ -1091,90 +1012,54 @@ void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
 	}
 }
 
-
-void LLPanelLogin::updateServer()
+// static
+void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
 {
-	try 
+	// *NOTE: The paramters for this method are ignored. 
+	// LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
+	// calls this method.
+
+	// The user twiddled with the grid choice ui.
+	// apply the selection to the grid setting.
+	std::string grid_label;
+	S32 grid_index;
+
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
+	LLSD combo_val = combo->getValue();
+
+	if (LLSD::TypeInteger == combo_val.type())
 	{
+		grid_index = combo->getValue().asInteger();
 
-		updateServerCombo();	
-		// if they've selected another grid, we should load the credentials
-		// for that grid and set them to the UI.
-		if(sInstance && !sInstance->areCredentialFieldsDirty())
+		if ((S32)GRID_INFO_OTHER == grid_index)
 		{
-			LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());	
-			bool remember = sInstance->childGetValue("remember_check");
-			sInstance->setFields(credential, remember);
+			// This happens if the user specifies a custom grid
+			// via command line.
+			grid_label = combo->getSimple();
 		}
-		// grid changed so show new splash screen (possibly)
-		loadLoginPage();
-		updateLocationCombo(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION);
 	}
-	catch (LLInvalidGridName ex)
+	else
 	{
-		// do nothing
+		// no valid selection, return other
+		grid_index = (S32)GRID_INFO_OTHER;
+		grid_label = combo_val.asString();
 	}
-}
 
-void LLPanelLogin::updateServerCombo()
-{
-	if (!sInstance) 
+	// This new seelction will override preset uris
+	// from the command line.
+	LLViewerLogin* vl = LLViewerLogin::getInstance();
+	vl->resetURIs();
+	if(grid_index != GRID_INFO_OTHER)
 	{
-		return;	
+		vl->setGridChoice((EGridInfo)grid_index);
 	}
-	// We add all of the possible values, sorted, and then add a bar and the current value at the top
-	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");	
-	server_choice_combo->removeall();
-#ifdef LL_RELEASE_FOR_DOWNLOAD
-	std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(TRUE);
-#else
-	std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(FALSE);	
-#endif
-	for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
-		 grid_choice != known_grids.end();
-		 grid_choice++)
+	else
 	{
-		if (!grid_choice->first.empty())
-		{
-			server_choice_combo->add(grid_choice->second, grid_choice->first, ADD_SORTED);
-		}
+		vl->setGridChoice(grid_label);
 	}
-	
-	server_choice_combo->addSeparator(ADD_TOP);
-	
-	server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(), 
-		LLGridManager::getInstance()->getGrid(), ADD_TOP);	
-	
-	server_choice_combo->selectFirstItem();	
-}
 
-// static
-void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
-{
-	// *NOTE: The paramters for this method are ignored. 
-	// LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
-	// calls this method.
-	LL_INFOS("AppInit") << "onSelectServer" << LL_ENDL;
-	// The user twiddled with the grid choice ui.
-	// apply the selection to the grid setting.
-	LLPointer<LLCredential> credential;
-	
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
-	LLSD combo_val = combo->getSelectedValue();
-	if (combo_val.isUndefined())
-	{
-		combo_val = combo->getValue();
-	}
-	
-	combo = sInstance->getChild<LLComboBox>("start_location_combo");	
-	combo->setCurrentByIndex(1);
-	LLStartUp::setStartSLURL(LLSLURL(gSavedSettings.getString("LoginLocation")));
-	LLGridManager::getInstance()->setGridChoice(combo_val.asString());
-	// This new selection will override preset uris
-	// from the command line.
-	updateServer();
-	updateLocationCombo(false);
-	updateLoginPanelLinks();
+	// grid changed so show new splash screen (possibly)
+	loadLoginPage();
 }
 
 void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe)
@@ -1187,14 +1072,3 @@ void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe)
 		onSelectServer(combo, NULL);	
 	}
 }
-
-void LLPanelLogin::updateLoginPanelLinks()
-{
-	LLSD grid_data = LLGridManager::getInstance()->getGridInfo();
-	bool system_grid = grid_data.has(GRID_IS_SYSTEM_GRID_VALUE);
-	
-	// need to call through sInstance, as it's called from onSelectServer, which
-	// is static.
-	sInstance->childSetVisible("create_new_account_text", system_grid);
-	sInstance->childSetVisible("forgot_password_text", system_grid);
-}
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index 9301c263dab405918cf2e82a1fc3bdfeed44e9bc..1fdc3a936198caab610c955f99e5d6e62cdb40ad 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -41,8 +41,6 @@
 class LLLineEditor;
 class LLUIImage;
 class LLPanelLoginListener;
-class LLSLURL;
-class LLCredential;
 
 class LLPanelLogin:	
 	public LLPanel,
@@ -67,16 +65,20 @@ class LLPanelLogin:
 		void (*callback)(S32 option, void* user_data), 
 		void* callback_data);
 
-	static void setFields(LLPointer<LLCredential> credential, BOOL remember);
+	// Remember password checkbox is set via gSavedSettings "RememberPassword"
+	static void setFields(const std::string& firstname, const std::string& lastname, 
+		const std::string& password);
 
-	static void getFields(LLPointer<LLCredential>& credential, BOOL remember);
+	static void addServer(const std::string& server, S32 domain_name);
+	static void refreshLocation( bool force_visible );
+	static void updateLocationUI();
+
+	static void getFields(std::string *firstname, std::string *lastname,
+						  std::string *password);
 
 	static BOOL isGridComboDirty();
-	static BOOL areCredentialFieldsDirty();
-	static void getLocation(LLSLURL& slurl);
-	static void setLocation(const LLSLURL& slurl);
-	
-	static void updateLocationCombo(bool force_visible);  // simply update the combo box
+	static void getLocation(std::string &location);
+
 	static void closePanel();
 
 	void setSiteIsAlive( bool alive );
@@ -84,10 +86,10 @@ class LLPanelLogin:
 	static void loadLoginPage();	
 	static void giveFocus();
 	static void setAlwaysRefresh(bool refresh); 
+	static void mungePassword(LLUICtrl* caller, void* user_data);
 	
 	// inherited from LLViewerMediaObserver
 	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
-	static void updateServer();  // update the combo box, change the login page to the new server, clear the combo
 
 private:
 	friend class LLPanelLoginListener;
@@ -101,10 +103,6 @@ class LLPanelLogin:
 	static void onPassKey(LLLineEditor* caller, void* user_data);
 	static void onSelectServer(LLUICtrl*, void*);
 	static void onServerComboLostFocus(LLFocusableElement*);
-	static void updateServerCombo();
-	static void onSelectLocation(LLUICtrl*, void*);
-	
-	static void updateLoginPanelLinks();
 
 private:
 	LLPointer<LLUIImage> mLogoImage;
@@ -113,7 +111,8 @@ class LLPanelLogin:
 	void			(*mCallback)(S32 option, void *userdata);
 	void*			mCallbackData;
 
-	BOOL            mPasswordModified;
+	std::string mIncomingPassword;
+	std::string mMungedPassword;
 
 	static LLPanelLogin* sInstance;
 	static BOOL		sCapslockDidNotification;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 7f5e63adeecfe5d0e9aa7fe849832a50a6d4f3f5..288edeb03109427b2c5181f337f10a4c32977240 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -619,7 +619,7 @@ BOOL LLPanelPeople::postBuild()
 	if(recent_view_sort)
 		mRecentViewSortMenuHandle  = recent_view_sort->getHandle();
 
-	LLVoiceClient::getInstance()->addObserver(this);
+	gVoiceClient->addObserver(this);
 
 	// call this method in case some list is empty and buttons can be in inconsistent state
 	updateButtons();
@@ -809,7 +809,7 @@ void LLPanelPeople::updateButtons()
 		}
 	}
 
-	bool enable_calls = LLVoiceClient::getInstance()->isVoiceWorking() && LLVoiceClient::getInstance()->voiceEnabled();
+	bool enable_calls = gVoiceClient->voiceWorking() && gVoiceClient->voiceEnabled();
 
 	buttonSetEnabled("teleport_btn",		friends_tab_active && item_selected && isFriendOnline(selected_uuids.front()));
 	buttonSetEnabled("view_profile_btn",	item_selected);
diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp
index 6b12796e59f4c469424f49d649ea9904c438a267..9806b8c64d55380873494b1f5863fc1e16c1bf4d 100644
--- a/indra/newview/llpanelplacestab.cpp
+++ b/indra/newview/llpanelplacestab.cpp
@@ -70,7 +70,10 @@ void LLPanelPlacesTab::onRegionResponse(const LLVector3d& landmark_global_pos,
 	std::string sl_url;
 	if ( gotSimName )
 	{
-		sl_url = LLSLURL(sim_name, landmark_global_pos).getSLURLString();
+		F32 region_x = (F32)fmod( landmark_global_pos.mdV[VX], (F64)REGION_WIDTH_METERS );
+		F32 region_y = (F32)fmod( landmark_global_pos.mdV[VY], (F64)REGION_WIDTH_METERS );
+
+		sl_url = LLSLURL::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)landmark_global_pos.mdV[VZ]));
 	}
 	else
 	{
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 268738d88c1b94b1466df7828f94b7226e06f2ad..0a20ff6226a6077911ce2f2d8939c6ec4b932a80 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -346,6 +346,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
 {
 	if (mExcludeAgent && gAgent.getID() == avatar_id) return;
 	if (mAvatarList->contains(avatar_id)) return;
+
 	mAvatarList->getIDs().push_back(avatar_id);
 	mAvatarList->setDirty();
 	adjustParticipant(avatar_id);
@@ -631,7 +632,7 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&
 	else if (item == "can_call")
 	{
 		bool not_agent = mUUIDs.front() != gAgentID;
-		bool can_call = not_agent &&  LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+		bool can_call = not_agent && LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
 		return can_call;
 	}
 
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
deleted file mode 100644
index ba343f538759a04b6e38bbd23c73136a92be170f..0000000000000000000000000000000000000000
--- a/indra/newview/llsecapi.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/** 
- * @file llsecapi.cpp
- * @brief Security API for services such as certificate handling
- * secure local storage, etc.
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "llviewerprecompiledheaders.h"
-#include "llsecapi.h"
-#include "llsechandler_basic.h"
-#include <openssl/evp.h>
-#include <map>
-#include "llhttpclient.h"
-
-
-
-std::map<std::string, LLPointer<LLSecAPIHandler> > gHandlerMap;
-LLPointer<LLSecAPIHandler> gSecAPIHandler;
-
-void initializeSecHandler()
-{
-	OpenSSL_add_all_algorithms();
-	OpenSSL_add_all_ciphers();
-	OpenSSL_add_all_digests();	
-	gHandlerMap[BASIC_SECHANDLER] = new LLSecAPIBasicHandler();
-	
-	
-	// Currently, we only have the Basic handler, so we can point the main sechandler
-	// pointer to the basic handler.  Later, we'll create a wrapper handler that
-	// selects the appropriate sechandler as needed, for instance choosing the
-	// mac keyring handler, with fallback to the basic sechandler
-	gSecAPIHandler = gHandlerMap[BASIC_SECHANDLER];
-
-	// initialize all SecAPIHandlers
-	LLProtectedDataException ex = LLProtectedDataException("");
-	std::map<std::string, LLPointer<LLSecAPIHandler> >::const_iterator itr;
-	for(itr = gHandlerMap.begin(); itr != gHandlerMap.end(); ++itr)
-	{
-		LLPointer<LLSecAPIHandler> handler = (*itr).second;
-		try 
-		{
-			handler->init();
-		}
-		catch (LLProtectedDataException e)
-		{
-			ex = e;
-		}
-	}
-	if (ex.getMessage().length() > 0 )  // an exception was thrown.
-	{
-		throw ex;
-	}
-
-}
-// start using a given security api handler.  If the string is empty
-// the default is used
-LLPointer<LLSecAPIHandler> getSecHandler(const std::string& handler_type)
-{
-	if (gHandlerMap.find(handler_type) != gHandlerMap.end())
-	{
-		return gHandlerMap[handler_type];
-	}
-	else
-	{
-		return LLPointer<LLSecAPIHandler>(NULL);
-	}
-}
-// register a handler
-void registerSecHandler(const std::string& handler_type, 
-						LLPointer<LLSecAPIHandler>& handler)
-{
-	gHandlerMap[handler_type] = handler;
-}
-
-std::ostream& operator <<(std::ostream& s, const LLCredential& cred)
-{
-	return s << (std::string)cred;
-}
-
-	
-// secapiSSLCertVerifyCallback
-// basic callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-// not initialized in the above initialization function, due to unit tests
-// see llappviewer
-
-int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
-{
-	LLURLRequest *req = (LLURLRequest *)param;
-	LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
-	LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
-	LLSD validation_params = LLSD::emptyMap();
-	LLURI uri(req->getURL());
-	validation_params[CERT_HOSTNAME] = uri.hostName();
-	try
-	{
-		chain->validate(VALIDATION_POLICY_SSL, store, validation_params);
-	}
-	catch (LLCertValidationTrustException& cert_exception)
-	{
-		LL_WARNS("AppInit") << "Cert not trusted: " << cert_exception.getMessage() << LL_ENDL;
-		return 0;		
-	}
-	catch (LLCertException& cert_exception)
-	{
-		LL_WARNS("AppInit") << "cert error " << cert_exception.getMessage() << LL_ENDL;
-		return 0;
-	}
-	catch (...)
-	{
-		LL_WARNS("AppInit") << "cert error " << LL_ENDL;
-		return 0;
-	}
-	return 1;
-}
-
-LLSD LLCredential::getLoginParams()
-{
-	LLSD result = LLSD::emptyMap();
-	if (mIdentifier["type"].asString() == "agent")
-	{
-		// legacy credential
-		result["passwd"] = "$1$" + mAuthenticator["secret"].asString();
-		result["first"] = mIdentifier["first_name"];
-		result["last"] = mIdentifier["last_name"];
-	
-	}
-	else if (mIdentifier["type"].asString() == "account")
-	{
-		result["username"] = mIdentifier["account_name"];
-		result["passwd"] = mAuthenticator["secret"];
-                                    
-	}
-	return result;
-}
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
deleted file mode 100644
index 5211dc26993eb62cced4f38884fe2a2d68cb969e..0000000000000000000000000000000000000000
--- a/indra/newview/llsecapi.h
+++ /dev/null
@@ -1,493 +0,0 @@
-/** 
- * @file llsecapi.h
- * @brief Security API for services such as certificate handling
- * secure local storage, etc.
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 LLSECAPI_H
-#define LLSECAPI_H
-#include <vector>
-#include <openssl/x509.h>
-#include <ostream>
-
-#ifdef LL_WINDOWS
-#pragma warning(disable:4250)
-#endif // LL_WINDOWS
-
-// All error handling is via exceptions.
-
-
-#define CERT_SUBJECT_NAME "subject_name"
-#define CERT_ISSUER_NAME "issuer_name"
-#define CERT_NAME_CN "commonName"
-		
-#define CERT_SUBJECT_NAME_STRING "subject_name_string"
-#define CERT_ISSUER_NAME_STRING "issuer_name_string"
-		
-#define CERT_SERIAL_NUMBER "serial_number"
-		
-#define CERT_VALID_FROM "valid_from"
-#define CERT_VALID_TO "valid_to"
-#define CERT_SHA1_DIGEST "sha1_digest"
-#define CERT_MD5_DIGEST "md5_digest"
-#define CERT_HOSTNAME "hostname"
-#define CERT_BASIC_CONSTRAINTS "basicConstraints"
-#define CERT_BASIC_CONSTRAINTS_CA "CA"
-#define CERT_BASIC_CONSTRAINTS_PATHLEN "pathLen"
-
-#define CERT_KEY_USAGE "keyUsage"
-#define CERT_KU_DIGITAL_SIGNATURE    "digitalSignature"
-#define CERT_KU_NON_REPUDIATION      "nonRepudiation"
-#define CERT_KU_KEY_ENCIPHERMENT     "keyEncipherment"
-#define CERT_KU_DATA_ENCIPHERMENT    "dataEncipherment"
-#define CERT_KU_KEY_AGREEMENT        "keyAgreement"
-#define CERT_KU_CERT_SIGN        "certSigning"
-#define CERT_KU_CRL_SIGN             "crlSigning"
-#define CERT_KU_ENCIPHER_ONLY        "encipherOnly"
-#define CERT_KU_DECIPHER_ONLY        "decipherOnly"
-
-#define BASIC_SECHANDLER "BASIC_SECHANDLER"
-#define CERT_VALIDATION_DATE "validation_date"
-
-#define CERT_EXTENDED_KEY_USAGE "extendedKeyUsage"
-#define CERT_EKU_SERVER_AUTH SN_server_auth
-
-#define CERT_SUBJECT_KEY_IDENTFIER "subjectKeyIdentifier"
-#define CERT_AUTHORITY_KEY_IDENTIFIER "authorityKeyIdentifier"
-#define CERT_AUTHORITY_KEY_IDENTIFIER_ID "authorityKeyIdentifierId"
-#define CERT_AUTHORITY_KEY_IDENTIFIER_NAME "authorityKeyIdentifierName"
-#define CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL "authorityKeyIdentifierSerial"
-
-// validate the current time lies within 
-// the validation period of the cert
-#define VALIDATION_POLICY_TIME 1
-
-// validate that the CA, or some cert in the chain
-// lies within the certificate store
-#define VALIDATION_POLICY_TRUSTED 2
-
-// validate that the subject name of
-// the cert contains the passed in hostname
-// or validates against the hostname
-#define VALIDATION_POLICY_HOSTNAME 4
-
-
-// validate that the cert contains the SSL EKU
-#define VALIDATION_POLICY_SSL_KU 8
-
-// validate that the cert contains the SSL EKU
-#define VALIDATION_POLICY_CA_KU 16
-
-#define VALIDATION_POLICY_CA_BASIC_CONSTRAINTS 32
-
-// validate that the cert is correct for SSL
-#define VALIDATION_POLICY_SSL (VALIDATION_POLICY_TIME | \
-                               VALIDATION_POLICY_HOSTNAME | \
-                               VALIDATION_POLICY_TRUSTED | \
-                               VALIDATION_POLICY_SSL_KU | \
-                               VALIDATION_POLICY_CA_BASIC_CONSTRAINTS | \
-                               VALIDATION_POLICY_CA_KU)
-
-
-
-
-
-
-class LLProtectedDataException
-{
-public:
-	LLProtectedDataException(const char *msg) 
-	{
-		LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL;
-		mMsg = (std::string)msg;
-	}
-	std::string getMessage() { return mMsg; }
-protected:
-	std::string mMsg;
-};
-
-// class LLCertificate
-// parent class providing an interface for certifiate.
-// LLCertificates are considered unmodifiable
-// Certificates are pulled out of stores, or created via
-// factory calls
-class LLCertificate : public LLRefCount
-{
-	LOG_CLASS(LLCertificate);
-public:
-	LLCertificate() {}
-	
-	virtual ~LLCertificate() {}
-	
-	// return a PEM encoded certificate.  The encoding
-	// includes the -----BEGIN CERTIFICATE----- and end certificate elements
-	virtual std::string getPem() const=0; 
-	
-	// return a DER encoded certificate
-	virtual std::vector<U8> getBinary() const=0;  
-	
-	// return an LLSD object containing information about the certificate
-	// such as its name, signature, expiry time, serial number
-	virtual LLSD getLLSD() const=0; 
-	
-	// return an openSSL X509 struct for the certificate
-	virtual X509* getOpenSSLX509() const=0;
-
-};
-
-// class LLCertificateVector
-// base class for a list of certificates.
-
-
-class LLCertificateVector : public LLRefCount
-{
-	
-public:
-	
-	LLCertificateVector() {};
-	virtual ~LLCertificateVector() {};
-	
-	// base iterator implementation class, providing
-	// the functionality needed for the iterator class.
-	class iterator_impl : public LLRefCount
-	{
-	public:
-		iterator_impl() {};
-		virtual ~iterator_impl() {};
-		virtual void seek(bool incr)=0;
-		virtual LLPointer<iterator_impl> clone() const=0;
-		virtual bool equals(const LLPointer<iterator_impl>& _iter) const=0;
-		virtual LLPointer<LLCertificate> get()=0;
-	};
-	
-	// iterator class
-	class iterator
-	{
-	public:
-		iterator(LLPointer<iterator_impl> impl) : mImpl(impl) {}
-		iterator() : mImpl(NULL) {}
-		iterator(const iterator& _iter) {mImpl = _iter.mImpl->clone(); }
-		~iterator() {}
-		iterator& operator++() { if(mImpl.notNull()) mImpl->seek(true); return *this;}
-		iterator& operator--() { if(mImpl.notNull()) mImpl->seek(false); return *this;}
-		
-		iterator operator++(int) { iterator result = *this; if(mImpl.notNull()) mImpl->seek(true); return result;}
-		iterator operator--(int) { iterator result = *this; if(mImpl.notNull()) mImpl->seek(false); return result;}
-		LLPointer<LLCertificate> operator*() { return mImpl->get(); }		
-		
-		LLPointer<iterator_impl> mImpl;
-	protected:
-		friend bool operator==(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs);
-		bool equals(const iterator& _iter) const { return mImpl->equals(_iter.mImpl); }
-	};
-	
-	// numeric indexer
-	virtual LLPointer<LLCertificate> operator[](int)=0;
-	
-	// Iteration
-	virtual iterator begin()=0;
-	
-	virtual iterator end()=0;
-	
-	// find a cert given params
-	virtual iterator find(const LLSD& params) =0;
-	
-	// return the number of certs in the store
-	virtual int size() const = 0;	
-	
-	// append the cert to the store.  if a copy of the cert already exists in the store, it is removed first
-	virtual void  add(LLPointer<LLCertificate> cert)=0;
-	
-	// insert the cert to the store.  if a copy of the cert already exists in the store, it is removed first
-	virtual void  insert(iterator location, LLPointer<LLCertificate> cert)=0;	
-	
-	// remove a certificate from the store
-	virtual LLPointer<LLCertificate> erase(iterator cert)=0;	
-};
-
-
-// class LLCertificateStore
-// represents a store of certificates, typically a store of root CA
-// certificates.  The store can be persisted, and can be used to validate
-// a cert chain
-//
-class LLCertificateStore : virtual public LLCertificateVector
-{
-	
-public:
-	
-	LLCertificateStore() {}
-	virtual ~LLCertificateStore() {}
-	
-	// persist the store
-	virtual void save()=0;
-	
-	// return the store id
-	virtual std::string storeId() const=0;
-};
-
-// class LLCertificateChain
-// Class representing a chain of certificates in order, with the 
-// first element being the child cert.
-class LLCertificateChain : virtual public LLCertificateVector
-{	
-
-public:
-	LLCertificateChain() {}
-	
-	virtual ~LLCertificateChain() {}
-
-	// validate a certificate chain given the params.
-	// Will throw exceptions on error
-	
-	virtual void validate(int validation_policy,
-						  LLPointer<LLCertificateStore> ca_store,
-						  const LLSD& validation_params) =0;
-};
-
-
-
-
-inline
-bool operator==(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs)
-{
-	return _lhs.equals(_rhs);
-}
-inline
-bool operator!=(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs)
-{
-	return !(_lhs == _rhs);
-}
-
-
-//
-// LLCredential - interface for credentials providing the following functionality:
-// * persistance of credential information based on grid (for saving username/password)
-// * serialization to an OGP identifier/authenticator pair
-// 
-class LLCredential  : public LLRefCount
-{
-public:
-	
-	LLCredential() {}
-	
-	LLCredential(const std::string& grid)
-	{
-		mGrid = grid;
-		mIdentifier = LLSD::emptyMap();
-		mAuthenticator = LLSD::emptyMap();
-	}
-	
-	virtual ~LLCredential() {}
-	
-	virtual void setCredentialData(const LLSD& identifier, const LLSD& authenticator) 
-	{ 
-		mIdentifier = identifier;
-		mAuthenticator = authenticator;
-	}
-	virtual LLSD getIdentifier() { return mIdentifier; }
-	virtual LLSD getAuthenticator() { return mAuthenticator; }
-	virtual LLSD getLoginParams();
-	virtual std::string getGrid() { return mGrid; }
-	
-
-	virtual void clearAuthenticator() { mAuthenticator = LLSD(); } 
-	virtual std::string userID() const { return std::string("unknown");}
-	virtual std::string asString() const { return std::string("unknown");}
-	operator std::string() const { return asString(); }
-protected:
-	LLSD mIdentifier;
-	LLSD mAuthenticator;
-	std::string mGrid;
-};
-
-std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
-
-
-// All error handling is via exceptions.
-
-class LLCertException
-{
-public:
-	LLCertException(LLPointer<LLCertificate> cert, const char* msg)
-	{
-
-		mCert = cert;
-
-		LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL;
-		mMsg = (std::string)msg;
-	}
-	LLPointer<LLCertificate> getCert() { return mCert; }
-	std::string getMessage() { return mMsg; }
-protected:
-	LLPointer<LLCertificate> mCert;
-	std::string mMsg;
-};
-
-class LLInvalidCertificate : public LLCertException
-{
-public:
-	LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")
-	{
-	}
-protected:
-};
-
-class LLCertValidationTrustException : public LLCertException
-{
-public:
-	LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")
-	{
-	}
-protected:
-};
-
-class LLCertValidationHostnameException : public LLCertException
-{
-public:
-	LLCertValidationHostnameException(std::string hostname,
-									  LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidHostname")
-	{
-		mHostname = hostname;
-	}
-	
-	std::string getHostname() { return mHostname; }
-protected:
-	std::string mHostname;
-};
-
-class LLCertValidationExpirationException : public LLCertException
-{
-public:
-	LLCertValidationExpirationException(LLPointer<LLCertificate> cert,
-										LLDate current_time) : LLCertException(cert, "CertExpired")
-	{
-		mTime = current_time;
-	}
-	LLDate GetTime() { return mTime; }
-protected:
-	LLDate mTime;
-};
-
-class LLCertKeyUsageValidationException : public LLCertException
-{
-public:
-	LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")
-	{
-	}
-protected:
-};
-
-class LLCertBasicConstraintsValidationException : public LLCertException
-{
-public:
-	LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")
-	{
-	}
-protected:
-};
-
-class LLCertValidationInvalidSignatureException : public LLCertException
-{
-public:
-	LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")
-	{
-	}
-protected:
-};
-
-// LLSecAPIHandler Class
-// Interface handler class for the various security storage handlers.
-class LLSecAPIHandler : public LLRefCount
-{
-public:
-	
-	
-	LLSecAPIHandler() {}
-	virtual ~LLSecAPIHandler() {}
-	
-	// initialize the SecAPIHandler
-	virtual void init() {};
-	
-	// instantiate a certificate from a pem string
-	virtual LLPointer<LLCertificate> getCertificate(const std::string& pem_cert)=0;
-	
-	
-	
-	// instiate a certificate from an openssl X509 structure
-	virtual LLPointer<LLCertificate> getCertificate(X509* openssl_cert)=0;
-	
-	// instantiate a chain from an X509_STORE_CTX
-	virtual LLPointer<LLCertificateChain> getCertificateChain(const X509_STORE_CTX* chain)=0;
-	
-	// instantiate a cert store given it's id.  if a persisted version
-	// exists, it'll be loaded.  If not, one will be created (but not
-	// persisted)
-	virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id)=0;
-	
-	// persist data in a protected store
-	virtual void setProtectedData(const std::string& data_type,
-								  const std::string& data_id,
-								  const LLSD& data)=0;
-	
-	// retrieve protected data
-	virtual LLSD getProtectedData(const std::string& data_type,
-								  const std::string& data_id)=0;
-	
-	// delete a protected data item from the store
-	virtual void deleteProtectedData(const std::string& data_type,
-									 const std::string& data_id)=0;
-	
-	virtual LLPointer<LLCredential> createCredential(const std::string& grid,
-													 const LLSD& identifier, 
-													 const LLSD& authenticator)=0;
-	
-	virtual LLPointer<LLCredential> loadCredential(const std::string& grid)=0;
-	
-	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)=0;
-	
-	virtual void deleteCredential(LLPointer<LLCredential> cred)=0;
-	
-};
-
-void initializeSecHandler();
-				
-// retrieve a security api depending on the api type
-LLPointer<LLSecAPIHandler> getSecHandler(const std::string& handler_type);
-
-void registerSecHandler(const std::string& handler_type, 
-						LLPointer<LLSecAPIHandler>& handler);
-
-extern LLPointer<LLSecAPIHandler> gSecAPIHandler;
-
-
-int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
-
-
-#endif // LL_SECAPI_H
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
deleted file mode 100644
index 51e250ffc6b6c5b55cf5aa755f6e5cf50ee5a9f6..0000000000000000000000000000000000000000
--- a/indra/newview/llsechandler_basic.cpp
+++ /dev/null
@@ -1,1586 +0,0 @@
-/** 
- * @file llsechandler_basic.cpp
- * @brief Security API for services such as certificate handling
- * secure local storage, etc.
- *
- * $LicenseInfo:firstyear=2003&license=viewergpl$
- * 
- * Copyright (c) 2003-2000, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/flossexception
- * 
-LLS * 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 "llviewerprecompiledheaders.h"
-#include "llsecapi.h"
-#include "llsechandler_basic.h"
-#include "llsdserialize.h"
-#include "llviewernetwork.h"
-#include "llxorcipher.h"
-#include "llfile.h"
-#include "lldir.h"
-#include "llviewercontrol.h"
-#include <vector>
-#include <ios>
-#include <openssl/ossl_typ.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/pem.h>
-#include <openssl/asn1.h>
-#include <openssl/rand.h>
-#include <openssl/err.h>
-#include <iostream>
-#include <iomanip>
-#include <time.h>
-
-
-
-// 128 bits of salt data...
-#define STORE_SALT_SIZE 16 
-#define BUFFER_READ_SIZE 256
-std::string cert_string_from_asn1_string(ASN1_STRING* value);
-std::string cert_string_from_octet_string(ASN1_OCTET_STRING* value);
-
-LLSD _basic_constraints_ext(X509* cert);
-LLSD _key_usage_ext(X509* cert);
-LLSD _ext_key_usage_ext(X509* cert);
-LLSD _subject_key_identifier_ext(X509 *cert);
-LLSD _authority_key_identifier_ext(X509* cert);
-
-LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) 
-{
-	
-	// BIO_new_mem_buf returns a read only bio, but takes a void* which isn't const
-	// so we need to cast it.
-	BIO * pem_bio = BIO_new_mem_buf((void*)pem_cert.c_str(), pem_cert.length());
-	if(pem_bio == NULL)
-	{
-		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
-		throw LLInvalidCertificate(this);
-	}
-	mCert = NULL;
-	PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
-	BIO_free(pem_bio);
-	if (!mCert)
-	{
-		throw LLInvalidCertificate(this);
-	}
-	_initLLSD();
-}
-
-
-LLBasicCertificate::LLBasicCertificate(X509* pCert) 
-{
-	if (!pCert || !pCert->cert_info)
-	{
-		throw LLInvalidCertificate(this);
-	}	
-	mCert = X509_dup(pCert);
-	_initLLSD();
-}
-
-LLBasicCertificate::~LLBasicCertificate() 
-{
-	if(mCert)
-	{
-		X509_free(mCert);
-	}
-}
-
-//
-// retrieve the pem using the openssl functionality
-std::string LLBasicCertificate::getPem() const
-{ 
-	char * pem_bio_chars = NULL;
-	// a BIO is the equivalent of a 'std::stream', and
-	// can be a file, mem stream, whatever.  Grab a memory based
-	// BIO for the result
-	BIO *pem_bio = BIO_new(BIO_s_mem());
-	if (!pem_bio)
-	{
-		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;		
-		return std::string();
-	}
-	PEM_write_bio_X509(pem_bio, mCert);
-	int length = BIO_get_mem_data(pem_bio, &pem_bio_chars);
-	std::string result = std::string(pem_bio_chars, length);
-	BIO_free(pem_bio);
-	return result;
-}
-
-// get the DER encoding for the cert
-// DER is a binary encoding format for certs...
-std::vector<U8> LLBasicCertificate::getBinary() const
-{ 
-	U8 * der_bio_data = NULL;
-	// get a memory bio 
-	BIO *der_bio = BIO_new(BIO_s_mem());
-	if (!der_bio)
-	{
-		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;			
-		return std::vector<U8>();
-	}
-	i2d_X509_bio(der_bio, mCert);
-	int length = BIO_get_mem_data(der_bio, &der_bio_data);
-	std::vector<U8> result(length);
-	// vectors are guranteed to be a contiguous chunk of memory.
-	memcpy(&result[0], der_bio_data,  length);
-	BIO_free(der_bio);
-	return result;
-}
-
-
-LLSD LLBasicCertificate::getLLSD() const
-{
-	return mLLSDInfo;
-}
-
-// Initialize the LLSD info for the certificate
-LLSD& LLBasicCertificate::_initLLSD()
-{ 
-
-	// call the various helpers to build the LLSD
-	mLLSDInfo[CERT_SUBJECT_NAME] = cert_name_from_X509_NAME(X509_get_subject_name(mCert));
-	mLLSDInfo[CERT_ISSUER_NAME] = cert_name_from_X509_NAME(X509_get_issuer_name(mCert));
-	mLLSDInfo[CERT_SUBJECT_NAME_STRING] = cert_string_name_from_X509_NAME(X509_get_subject_name(mCert));
-	mLLSDInfo[CERT_ISSUER_NAME_STRING] = cert_string_name_from_X509_NAME(X509_get_issuer_name(mCert));
-	ASN1_INTEGER *sn = X509_get_serialNumber(mCert);
-	if (sn != NULL)
-	{
-		mLLSDInfo[CERT_SERIAL_NUMBER] = cert_string_from_asn1_integer(sn);
-	}
-	
-	mLLSDInfo[CERT_VALID_TO] = cert_date_from_asn1_time(X509_get_notAfter(mCert));
-	mLLSDInfo[CERT_VALID_FROM] = cert_date_from_asn1_time(X509_get_notBefore(mCert));
-	mLLSDInfo[CERT_SHA1_DIGEST] = cert_get_digest("sha1", mCert);
-	mLLSDInfo[CERT_MD5_DIGEST] = cert_get_digest("md5", mCert);
-	// add the known extensions
-	mLLSDInfo[CERT_BASIC_CONSTRAINTS] = _basic_constraints_ext(mCert);
-	mLLSDInfo[CERT_KEY_USAGE] = _key_usage_ext(mCert);
-	mLLSDInfo[CERT_EXTENDED_KEY_USAGE] = _ext_key_usage_ext(mCert);
-	mLLSDInfo[CERT_SUBJECT_KEY_IDENTFIER] = _subject_key_identifier_ext(mCert);
-	mLLSDInfo[CERT_AUTHORITY_KEY_IDENTIFIER] = _authority_key_identifier_ext(mCert);
-	return mLLSDInfo; 
-}
-
-// Retrieve the basic constraints info
-LLSD _basic_constraints_ext(X509* cert)
-{
-	LLSD result;
-	BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(cert, NID_basic_constraints, NULL, NULL);
-	if(bs)
-	{
-		result = LLSD::emptyMap();
-		// Determines whether the cert can be used as a CA
-		result[CERT_BASIC_CONSTRAINTS_CA] = (bool)bs->ca;
-	
-		if(bs->pathlen) 
-		{
-			// the pathlen determines how deep a certificate chain can be from
-			// this CA
-			if((bs->pathlen->type == V_ASN1_NEG_INTEGER)
-			   || !bs->ca) 
-			{
-				result[CERT_BASIC_CONSTRAINTS_PATHLEN] = 0;
-			} 
-			else 
-			{
-				result[CERT_BASIC_CONSTRAINTS_PATHLEN] = (int)ASN1_INTEGER_get(bs->pathlen);
-			}
-		}
-
-	}
-	return result;
-}
-
-// retrieve the key usage, which specifies how the cert can be used.
-// 
-LLSD _key_usage_ext(X509* cert)
-{
-	LLSD result;
-	ASN1_STRING *usage_str = (ASN1_STRING *)X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL);
-	if(usage_str)
-	{
-		result = LLSD::emptyArray();
-		long usage = 0;
-		if(usage_str->length > 0) 
-		{
-			usage = usage_str->data[0];
-			if(usage_str->length > 1)
-			{
-				usage |= usage_str->data[1] << 8;
-			}
-		}
-		ASN1_STRING_free(usage_str);
-		if(usage)
-		{
-			if(usage & KU_DIGITAL_SIGNATURE) result.append(LLSD((std::string)CERT_KU_DIGITAL_SIGNATURE));
-			if(usage & KU_NON_REPUDIATION) result.append(LLSD((std::string)CERT_KU_NON_REPUDIATION));
-			if(usage & KU_KEY_ENCIPHERMENT) result.append(LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT));
-			if(usage & KU_DATA_ENCIPHERMENT) result.append(LLSD((std::string)CERT_KU_DATA_ENCIPHERMENT));
-			if(usage & KU_KEY_AGREEMENT) result.append(LLSD((std::string)CERT_KU_KEY_AGREEMENT));
-			if(usage & KU_KEY_CERT_SIGN) result.append(LLSD((std::string)CERT_KU_CERT_SIGN));			
-			if(usage & KU_CRL_SIGN) result.append(LLSD((std::string)CERT_KU_CRL_SIGN));	
-			if(usage & KU_ENCIPHER_ONLY) result.append(LLSD((std::string)CERT_KU_ENCIPHER_ONLY));				
-			if(usage & KU_DECIPHER_ONLY) result.append(LLSD((std::string)CERT_KU_DECIPHER_ONLY));		
-		}
-	}
-	return result;
-}
-
-// retrieve the extended key usage for the cert
-LLSD _ext_key_usage_ext(X509* cert)
-{
-	LLSD result;
-	EXTENDED_KEY_USAGE *eku = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL);
-	if(eku)
-	{
-		result = LLSD::emptyArray();
-		while(sk_ASN1_OBJECT_num(eku))
-		{
-			ASN1_OBJECT *usage = sk_ASN1_OBJECT_pop(eku);
-			if(usage)
-			{
-				int nid = OBJ_obj2nid(usage);
-				if (nid)
-				{
-					std::string sn = OBJ_nid2sn(nid);
-					result.append(sn);
-				}
-				ASN1_OBJECT_free(usage);
-			}
-		}
-	}
-	return result;
-}
-
-// retrieve the subject key identifier of the cert
-LLSD _subject_key_identifier_ext(X509 *cert)
-{
-	LLSD result;
-	ASN1_OCTET_STRING *skeyid = (ASN1_OCTET_STRING *)X509_get_ext_d2i(cert, NID_subject_key_identifier, NULL, NULL);
-	if(skeyid)
-	{
-		result = cert_string_from_octet_string(skeyid);
-	}
-	return result;
-}
-
-// retrieve the authority key identifier of the cert
-LLSD _authority_key_identifier_ext(X509* cert)
-{
-	LLSD result;
-	AUTHORITY_KEYID *akeyid = (AUTHORITY_KEYID *)X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
-	if(akeyid)
-	{
-		result = LLSD::emptyMap();
-		if(akeyid->keyid)
-		{
-			result[CERT_AUTHORITY_KEY_IDENTIFIER_ID] = cert_string_from_octet_string(akeyid->keyid);
-		}
-		if(akeyid->serial)
-		{
-			result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial);
-		}	
-	}
-	
-	// we ignore the issuer name in the authority key identifier, we check the issue name via
-	// the the issuer name entry in the cert.
-	
-
-	return result;
-}
-
-// retrieve an openssl x509 object,
-// which must be freed by X509_free
-X509* LLBasicCertificate::getOpenSSLX509() const
-{ 
-	return X509_dup(mCert); 
-}  
-
-// generate a single string containing the subject or issuer
-// name of the cert.
-std::string cert_string_name_from_X509_NAME(X509_NAME* name)
-{
-	char * name_bio_chars = NULL;
-	// get a memory bio
-	BIO *name_bio = BIO_new(BIO_s_mem());
-	// stream the name into the bio.  The name will be in the 'short name' format
-	X509_NAME_print_ex(name_bio, name, 0, XN_FLAG_RFC2253);
-	int length = BIO_get_mem_data(name_bio, &name_bio_chars);
-	std::string result = std::string(name_bio_chars, length);
-	BIO_free(name_bio);
-	return result;
-}
-
-// generate an LLSD from a certificate name (issuer or subject name).  
-// the name will be strings indexed by the 'long form'
-LLSD cert_name_from_X509_NAME(X509_NAME* name)
-{
-	LLSD result = LLSD::emptyMap();
-	int name_entries = X509_NAME_entry_count(name);
-	for (int entry_index=0; entry_index < name_entries; entry_index++) 
-	{
-		char buffer[32];
-		X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, entry_index);
-		
-		std::string name_value = std::string((const char*)M_ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), 
-											 M_ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry)));
-
-		ASN1_OBJECT* name_obj = X509_NAME_ENTRY_get_object(entry);		
-		OBJ_obj2txt(buffer, sizeof(buffer), name_obj, 0);
-		std::string obj_buffer_str = std::string(buffer);
-		result[obj_buffer_str] = name_value;
-	}
-	
-	return result;
-}
-
-// Generate a string from an ASN1 integer.  ASN1 Integers are
-// bignums, so they can be 'infinitely' long, therefore we
-// cannot simply use a conversion to U64 or something.
-// We retrieve as a readable string for UI
-
-std::string cert_string_from_asn1_integer(ASN1_INTEGER* value)
-{
-	std::string result;
-	BIGNUM *bn = ASN1_INTEGER_to_BN(value, NULL);
-	if(bn)
-	{
-		char * ascii_bn = BN_bn2hex(bn);
-
-		if(ascii_bn)
-		{
-			result = ascii_bn;
-			OPENSSL_free(ascii_bn);
-		}
-		BN_free(bn);
-	}
-	return result;
-}
-
-// Generate a string from an OCTET string.
-// we retrieve as a 
-
-std::string cert_string_from_octet_string(ASN1_OCTET_STRING* value)
-{
-	
-	std::stringstream result;
-	result << std::hex << std::setprecision(2);
-	for (int i=0; i < value->length; i++)
-	{
-		if (i != 0) 
-		{
-			result << ":";
-		}
-		result  << std::setfill('0') << std::setw(2) << (int)value->data[i];
-	}
-	return result.str();
-}
-
-// Generate a string from an ASN1 integer.  ASN1 Integers are
-// bignums, so they can be 'infinitely' long, therefore we
-// cannot simply use a conversion to U64 or something.
-// We retrieve as a readable string for UI
-
-std::string cert_string_from_asn1_string(ASN1_STRING* value)
-{
-	char * string_bio_chars = NULL;
-	std::string result;
-	// get a memory bio
-	BIO *string_bio = BIO_new(BIO_s_mem());
-	if(!string_bio)
-	{
-		// stream the name into the bio.  The name will be in the 'short name' format
-		ASN1_STRING_print_ex(string_bio, value, ASN1_STRFLGS_RFC2253);
-		int length = BIO_get_mem_data(string_bio, &string_bio_chars);
-		result = std::string(string_bio_chars, length);
-		BIO_free(string_bio);
-	}
-	else
-	{
-		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
-	}
-	
-	return result;
-}
-
-// retrieve a date structure from an ASN1 time, for 
-// validity checking.
-LLDate cert_date_from_asn1_time(ASN1_TIME* asn1_time)
-{
-	
-	struct tm timestruct = {0};
-	int i = asn1_time->length;
-	
-	if (i < 10)
-	{
-		return LLDate();
-	}	
-	// convert the date from the ASN1 time (which is a string in ZULU time), to
-	// a timeval.
-	timestruct.tm_year = (asn1_time->data[0]-'0') * 10 + (asn1_time->data[1]-'0');
-	
-	/* Deal with Year 2000 */
-	if (timestruct.tm_year < 70)
-		timestruct.tm_year += 100;
-	
-	timestruct.tm_mon = (asn1_time->data[2]-'0') * 10 + (asn1_time->data[3]-'0') - 1;
-	timestruct.tm_mday = (asn1_time->data[4]-'0') * 10 + (asn1_time->data[5]-'0');
-	timestruct.tm_hour = (asn1_time->data[6]-'0') * 10 + (asn1_time->data[7]-'0');
-	timestruct.tm_min = (asn1_time->data[8]-'0') * 10 + (asn1_time->data[9]-'0');
-	timestruct.tm_sec = (asn1_time->data[10]-'0') * 10 + (asn1_time->data[11]-'0');
-
-#if LL_WINDOWS
-	return LLDate((F64)_mkgmtime(&timestruct));
-#else // LL_WINDOWS
-	return LLDate((F64)timegm(&timestruct));
-#endif // LL_WINDOWS
-}
-
-													   
-// Generate a string containing a digest.  The digest time is 'ssh1' or
-// 'md5', and the resulting string is of the form "aa:12:5c:' and so on
-std::string cert_get_digest(const std::string& digest_type, X509 *cert)
-{
-	unsigned char digest_data[BUFFER_READ_SIZE];
-	unsigned int len = sizeof(digest_data);
-	std::stringstream result;
-	const EVP_MD* digest = NULL;
-	// we could use EVP_get_digestbyname, but that requires initializer code which
-	// would require us to complicate things by plumbing it into the system.
-	if (digest_type == "md5")
-	{
-		digest = EVP_md5();
-	}
-	else if (digest_type == "sha1")
-	{
-		digest = EVP_sha1();
-	}
-	else
-	{
-		return std::string();
-	}
-
-	X509_digest(cert, digest, digest_data, &len);
-	result << std::hex << std::setprecision(2);
-	for (unsigned int i=0; i < len; i++)
-	{
-		if (i != 0) 
-		{
-			result << ":";
-		}
-		result  << std::setfill('0') << std::setw(2) << (int)digest_data[i];
-	}
-	return result.str();
-}
-
-
-// class LLBasicCertificateVector
-// This class represents a list of certificates, implemented by a vector of certificate pointers.
-// it contains implementations of the virtual functions for iterators, search, add, remove, etc.
-//
-
-//  Find a certificate in the list.
-// It will find a cert that has minimally the params listed, with the values being the same
-LLBasicCertificateVector::iterator LLBasicCertificateVector::find(const LLSD& params)
-{
-	BOOL found = FALSE;
-	// loop through the entire vector comparing the values in the certs
-	// against those passed in via the params.
-	// params should be a map.  Only the items specified in the map will be
-	// checked, but they must match exactly, even if they're maps or arrays.
-	
-	for(iterator cert = begin();
-		cert != end();
-		cert++)
-	{
-
-			found= TRUE;
-		LLSD cert_info = (*cert)->getLLSD();
-			for (LLSD::map_const_iterator param = params.beginMap();
-			 param != params.endMap();
-			 param++)
-		{
-
-			if (!cert_info.has((std::string)param->first) || 
-				(!valueCompareLLSD(cert_info[(std::string)param->first], param->second)))
-			{
-				found = FALSE;
-				break;
-			}
-		}
-		if (found)
-		{
-			return (cert);
-		}
-	}
-	return end();
-}
-
-// Insert a certificate into the store.  If the certificate already 
-// exists in the store, nothing is done.
-void  LLBasicCertificateVector::insert(iterator _iter, 
-									   LLPointer<LLCertificate> cert)
-{
-	LLSD cert_info = cert->getLLSD();
-	if (cert_info.isMap() && cert_info.has(CERT_SHA1_DIGEST))
-	{
-		LLSD existing_cert_info = LLSD::emptyMap();
-		existing_cert_info[CERT_MD5_DIGEST] = cert_info[CERT_MD5_DIGEST];
-		if(find(existing_cert_info) == end())
-		{
-			BasicIteratorImpl *basic_iter = dynamic_cast<BasicIteratorImpl*>(_iter.mImpl.get());
-			mCerts.insert(basic_iter->mIter, cert);
-		}
-	}
-}
-
-// remove a certificate from the store
-LLPointer<LLCertificate> LLBasicCertificateVector::erase(iterator _iter)
-{
-	
-	if (_iter != end())
-	{
-		BasicIteratorImpl *basic_iter = dynamic_cast<BasicIteratorImpl*>(_iter.mImpl.get());
-		LLPointer<LLCertificate> result = (*_iter);
-		mCerts.erase(basic_iter->mIter);
-		return result;
-	}
-	return NULL;
-}
-
-
-//
-// LLBasicCertificateStore
-// This class represents a store of CA certificates.  The basic implementation
-// uses a pem file such as the legacy CA.pem stored in the existing 
-// SL implementation.
-LLBasicCertificateStore::LLBasicCertificateStore(const std::string& filename)
-{
-	mFilename = filename;
-	load_from_file(filename);
-}
-
-void LLBasicCertificateStore::load_from_file(const std::string& filename)
-{
-	// scan the PEM file extracting each certificate
-	BIO* file_bio = BIO_new(BIO_s_file());
-	if(file_bio)
-	{
-		if (BIO_read_filename(file_bio, filename.c_str()) > 0)
-		{	
-			X509 *cert_x509 = NULL;
-			while((PEM_read_bio_X509(file_bio, &cert_x509, 0, NULL)) && 
-				  (cert_x509 != NULL))
-			{
-				try
-				{
-					add(new LLBasicCertificate(cert_x509));
-				}
-				catch (...)
-				{
-					LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL;
-				}
-				X509_free(cert_x509);
-				cert_x509 = NULL;
-			}
-			BIO_free(file_bio);
-		}
-	}
-	else
-	{
-		LL_WARNS("SECAPI") << "Could not allocate a file BIO" << LL_ENDL;
-	}
-}
-
-
-LLBasicCertificateStore::~LLBasicCertificateStore()
-{
-}
-
-
-// persist the store
-void LLBasicCertificateStore::save()
-{
-	llofstream file_store(mFilename, llofstream::binary);
-	if(!file_store.fail())
-	{
-		for(iterator cert = begin();
-			cert != end();
-			cert++)
-		{
-			std::string pem = (*cert)->getPem();
-			if(!pem.empty())
-			{
-				file_store << (*cert)->getPem() << std::endl;
-			}
-		}
-		file_store.close();
-	}
-	else
-	{
-		LL_WARNS("SECAPI") << "Could not open certificate store " << mFilename << "for save" << LL_ENDL;
-	}
-}
-
-// return the store id
-std::string LLBasicCertificateStore::storeId() const
-{
-	// this is the basic handler which uses the CA.pem store,
-	// so we ignore this.
-	return std::string("");
-}
-
-
-//
-// LLBasicCertificateChain
-// This class represents a chain of certs, each cert being signed by the next cert
-// in the chain.  Certs must be properly signed by the parent
-LLBasicCertificateChain::LLBasicCertificateChain(const X509_STORE_CTX* store)
-{
-
-	// we're passed in a context, which contains a cert, and a blob of untrusted
-	// certificates which compose the chain.
-	if((store == NULL) || (store->cert == NULL))
-	{
-		LL_WARNS("SECAPI") << "An invalid store context was passed in when trying to create a certificate chain" << LL_ENDL;
-		return;
-	}
-	// grab the child cert
-	LLPointer<LLCertificate> current = new LLBasicCertificate(store->cert);
-
-	add(current);
-	if(store->untrusted != NULL)
-	{
-		// if there are other certs in the chain, we build up a vector
-		// of untrusted certs so we can search for the parents of each
-		// consecutive cert.
-		LLBasicCertificateVector untrusted_certs;
-		for(int i = 0; i < sk_X509_num(store->untrusted); i++)
-		{
-			LLPointer<LLCertificate> cert = new LLBasicCertificate(sk_X509_value(store->untrusted, i));
-			untrusted_certs.add(cert);
-
-		}		
-		while(untrusted_certs.size() > 0)
-		{
-			LLSD find_data = LLSD::emptyMap();
-			LLSD cert_data = current->getLLSD();
-			// we simply build the chain via subject/issuer name as the
-			// client should not have passed in multiple CA's with the same 
-			// subject name.  If they did, it'll come out in the wash during
-			// validation.
-			find_data[CERT_SUBJECT_NAME_STRING] = cert_data[CERT_ISSUER_NAME_STRING]; 
-			LLBasicCertificateVector::iterator issuer = untrusted_certs.find(find_data);
-			if (issuer != untrusted_certs.end())
-			{
-				current = untrusted_certs.erase(issuer);
-				add(current);
-			}
-			else
-			{
-				break;
-			}
-		}
-	}
-}
-
-
-// subdomain wildcard specifiers can be divided into 3 parts
-// the part before the first *, the part after the first * but before
-// the second *, and the part after the second *.
-// It then iterates over the second for each place in the string
-// that it matches.  ie if the subdomain was testfoofoobar, and
-// the wildcard was test*foo*bar, it would match test, then
-// recursively match foofoobar and foobar
-
-bool _cert_subdomain_wildcard_match(const std::string& subdomain,
-									const std::string& wildcard)
-{
-	// split wildcard into the portion before the *, and the portion after
-
-	int wildcard_pos = wildcard.find_first_of('*');	
-	// check the case where there is no wildcard.
-	if(wildcard_pos == wildcard.npos)
-	{
-		return (subdomain == wildcard);
-	}
-	
-	// we need to match the first part of the subdomain string up to the wildcard
-	// position
-	if(subdomain.substr(0, wildcard_pos) != wildcard.substr(0, wildcard_pos))
-	{
-		// the first portions of the strings didn't match
-		return FALSE;
-	}
-	
-	// as the portion of the wildcard string before the * matched, we need to check the
-	// portion afterwards.  Grab that portion.
-	std::string new_wildcard_string = wildcard.substr( wildcard_pos+1, wildcard.npos);
-	if(new_wildcard_string.empty())
-	{
-		// we had nothing after the *, so it's an automatic match
-		return TRUE;
-	}
-	
-	// grab the portion of the remaining wildcard string before the next '*'.  We need to find this
-	// within the remaining subdomain string. and then recursively check.
-	std::string new_wildcard_match_string = new_wildcard_string.substr(0, new_wildcard_string.find_first_of('*'));
-	
-	// grab the portion of the subdomain after the part that matched the initial wildcard portion
-	std::string new_subdomain = subdomain.substr(wildcard_pos, subdomain.npos);
-	
-	// iterate through the current subdomain, finding instances of the match string.
-	int sub_pos = new_subdomain.find_first_of(new_wildcard_match_string);
-	while(sub_pos != std::string::npos)
-	{
-		new_subdomain = new_subdomain.substr(sub_pos, std::string::npos);
-		if(_cert_subdomain_wildcard_match(new_subdomain, new_wildcard_string))
-		{
-			return TRUE;
-		}
-		sub_pos = new_subdomain.find_first_of(new_wildcard_match_string, 1);
-
-
-	}
-	// didn't find any instances of the match string that worked in the subdomain, so fail.
-	return FALSE;
-}
-
-
-// RFC2459 does not address wildcards as part of it's name matching
-// specification, and there is no RFC specifying wildcard matching,
-// RFC2818 does a few statements about wildcard matching, but is very 
-// general.  Generally, wildcard matching is per implementation, although
-// it's pretty similar.
-// in our case, we use the '*' wildcard character only, within each
-// subdomain.  The hostname and the CN specification should have the
-// same number of subdomains.
-// We then iterate that algorithm over each subdomain.
-bool _cert_hostname_wildcard_match(const std::string& hostname, const std::string& common_name)
-{
-	std::string new_hostname = hostname;
-	std::string new_cn = common_name;
-	int subdomain_pos = new_hostname.find_first_of('.');
-	int subcn_pos = new_cn.find_first_of('.');
-	
-	while((subcn_pos != std::string::npos) && (subdomain_pos != std::string::npos))
-	{
-		// snip out the first subdomain and cn element
-
-		if(!_cert_subdomain_wildcard_match(new_hostname.substr(0, subdomain_pos),
-										   new_cn.substr(0, subcn_pos)))
-		{
-			return FALSE;
-		}
-		new_hostname = new_hostname.substr(subdomain_pos+1, std::string::npos);
-		new_cn = new_cn.substr(subcn_pos+1, std::string::npos);
-		subdomain_pos = new_hostname.find_first_of('.');
-		subcn_pos = new_cn.find_first_of('.');
-	}
-	return _cert_subdomain_wildcard_match(new_hostname, new_cn);
-
-}
-
-// validate that the LLSD array in llsd_set contains the llsd_value 
-bool _LLSDArrayIncludesValue(const LLSD& llsd_set, LLSD llsd_value)
-{
-	for(LLSD::array_const_iterator set_value = llsd_set.beginArray();
-		set_value != llsd_set.endArray();
-		set_value++)
-	{
-		if(valueCompareLLSD((*set_value), llsd_value))
-		{
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-void _validateCert(int validation_policy,
-				  const LLPointer<LLCertificate> cert,
-				  const LLSD& validation_params,
-				  int depth)
-{
-
-	LLSD current_cert_info = cert->getLLSD();		
-	// check basic properties exist in the cert
-	if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))
-	{
-		throw LLCertException(cert, "Cert doesn't have a Subject Name");				
-	}
-	
-	if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))
-	{
-		throw LLCertException(cert, "Cert doesn't have an Issuer Name");				
-	}
-	
-	// check basic properties exist in the cert
-	if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))
-	{
-		throw LLCertException(cert, "Cert doesn't have an expiration period");				
-	}
-	if (!current_cert_info.has(CERT_SHA1_DIGEST))
-	{
-		throw LLCertException(cert, "No SHA1 digest");
-	}
-
-	if (validation_policy & VALIDATION_POLICY_TIME)
-	{
-
-		LLDate validation_date(time(NULL));
-		if(validation_params.has(CERT_VALIDATION_DATE))
-		{
-			validation_date = validation_params[CERT_VALIDATION_DATE];
-		}
-		
-		if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||
-		   (validation_date > current_cert_info[CERT_VALID_TO].asDate()))
-		{
-			throw LLCertValidationExpirationException(cert, validation_date);
-		}
-	}
-	if (validation_policy & VALIDATION_POLICY_SSL_KU)
-	{
-		if (current_cert_info.has(CERT_KEY_USAGE) && current_cert_info[CERT_KEY_USAGE].isArray() &&
-			(!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], 
-									   LLSD((std::string)CERT_KU_DIGITAL_SIGNATURE))) ||
-			!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], 
-									  LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
-		{
-			throw LLCertKeyUsageValidationException(cert);
-		}
-		// only validate EKU if the cert has it
-		if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&	   
-		   (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE], 
-									LLSD((std::string)CERT_EKU_SERVER_AUTH))))
-		{
-			throw LLCertKeyUsageValidationException(cert);			
-		}
-	}
-	if (validation_policy & VALIDATION_POLICY_CA_KU)
-	{
-		if (current_cert_info.has(CERT_KEY_USAGE) && current_cert_info[CERT_KEY_USAGE].isArray() &&
-			(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], 
-									   (std::string)CERT_KU_CERT_SIGN)))
-			{
-				throw LLCertKeyUsageValidationException(cert);						
-			}
-	}
-	
-	// validate basic constraints
-	if ((validation_policy & VALIDATION_POLICY_CA_BASIC_CONSTRAINTS) &&
-		current_cert_info.has(CERT_BASIC_CONSTRAINTS) && 
-		current_cert_info[CERT_BASIC_CONSTRAINTS].isMap())
-	{
-		if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||
-		   !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])
-		{
-				throw LLCertBasicConstraintsValidationException(cert);
-		}
-		if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&
-			((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&
-			 (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))
-		{
-			throw LLCertBasicConstraintsValidationException(cert);					
-		}
-	}
-}
-
-bool _verify_signature(LLPointer<LLCertificate> parent, 
-					   LLPointer<LLCertificate> child)
-{
-	bool verify_result = FALSE; 
-	LLSD cert1 = parent->getLLSD();
-	LLSD cert2 = child->getLLSD();
-	X509 *signing_cert = parent->getOpenSSLX509();
-	X509 *child_cert = child->getOpenSSLX509();
-	if((signing_cert != NULL) && (child_cert != NULL))
-	{
-		EVP_PKEY *pkey = X509_get_pubkey(signing_cert);
-		
-		
-		if(pkey)
-		{
-			int verify_code = X509_verify(child_cert, pkey);
-			verify_result = ( verify_code > 0);
-			EVP_PKEY_free(pkey);
-		}
-		else
-		{
-			LL_WARNS("SECAPI") << "Could not validate the cert chain signature, as the public key of the signing cert could not be retrieved" << LL_ENDL;
-		}
-
-	}
-	else
-	{
-		LL_WARNS("SECAPI") << "Signature verification failed as there are no certs in the chain" << LL_ENDL;
-	}
-	if(child_cert)
-	{
-		X509_free(child_cert);
-	}
-	if(signing_cert)
-	{
-		X509_free(signing_cert);
-	}
-	return verify_result;
-}
-
-// validate the certificate chain against a store.
-// There are many aspects of cert validatioin policy involved in
-// trust validation.  The policies in this validation algorithm include
-// * Hostname matching for SSL certs
-// * Expiration time matching
-// * Signature validation
-// * Chain trust (is the cert chain trusted against the store)
-// * Basic constraints
-// * key usage and extended key usage
-// TODO: We should add 'authority key identifier' for chaining.
-// This algorithm doesn't simply validate the chain by itself
-// and verify the last cert is in the certificate store, or points
-// to a cert in the store.  It validates whether any cert in the chain
-// is trusted in the store, even if it's not the last one.
-void LLBasicCertificateChain::validate(int validation_policy,
-									   LLPointer<LLCertificateStore> ca_store,
-									   const LLSD& validation_params)
-{
-
-	if(size() < 1)
-	{
-		throw LLCertException(NULL, "No certs in chain");
-	}
-	iterator current_cert = begin();
-	LLSD 	current_cert_info = (*current_cert)->getLLSD();
-	LLSD validation_date;
-	if (validation_params.has(CERT_VALIDATION_DATE))
-	{
-		validation_date = validation_params[CERT_VALIDATION_DATE];
-	}
-
-	if (validation_policy & VALIDATION_POLICY_HOSTNAME)
-	{
-		if(!validation_params.has(CERT_HOSTNAME))
-		{
-			throw LLCertException((*current_cert), "No hostname passed in for validation");			
-		}
-		if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))
-		{
-			throw LLInvalidCertificate((*current_cert));				
-		}
-		
-		LL_INFOS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << 
-		     "against the cert CN " << current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString() << LL_ENDL;
-		if(!_cert_hostname_wildcard_match(validation_params[CERT_HOSTNAME].asString(),
-										  current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString()))
-		{
-			throw LLCertValidationHostnameException(validation_params[CERT_HOSTNAME].asString(),
-													(*current_cert));
-		}
-	}
-	
-
-	int depth = 0;
-	LLPointer<LLCertificate> previous_cert;
-	// loop through the cert chain, validating the current cert against the next one.
-	while(current_cert != end())
-	{
-		
-		int local_validation_policy = validation_policy;
-		if(current_cert == begin())
-		{
-			// for the child cert, we don't validate CA stuff
-			local_validation_policy &= ~(VALIDATION_POLICY_CA_KU | 
-										 VALIDATION_POLICY_CA_BASIC_CONSTRAINTS);
-		}
-		else
-		{
-			// for non-child certs, we don't validate SSL Key usage
-			local_validation_policy &= ~VALIDATION_POLICY_SSL_KU;				
-			if(!_verify_signature((*current_cert),
-								  previous_cert))
-			{
-			   throw LLCertValidationInvalidSignatureException(previous_cert);
-			}
-		}
-		_validateCert(local_validation_policy,
-					  (*current_cert),
-					  validation_params,
-					  depth);
-		
-		// look for a CA in the CA store that may belong to this chain.
-		LLSD cert_llsd = (*current_cert)->getLLSD();
-		LLSD cert_search_params = LLSD::emptyMap();		
-		// is the cert itself in the store?
-		cert_search_params[CERT_SHA1_DIGEST] = cert_llsd[CERT_SHA1_DIGEST];
-		LLCertificateStore::iterator found_store_cert = ca_store->find(cert_search_params);
-		if(found_store_cert != ca_store->end())
-		{
-			return;
-		}
-		
-		// is the parent in the cert store?
-			
-		cert_search_params = LLSD::emptyMap();
-		cert_search_params[CERT_SUBJECT_NAME_STRING] = cert_llsd[CERT_ISSUER_NAME_STRING];
-		if (cert_llsd.has(CERT_AUTHORITY_KEY_IDENTIFIER))
-		{
-			LLSD cert_aki = cert_llsd[CERT_AUTHORITY_KEY_IDENTIFIER];
-			if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_ID))
-			{
-				cert_search_params[CERT_SUBJECT_KEY_IDENTFIER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_ID];
-			}
-			if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL))
-			{
-				cert_search_params[CERT_SERIAL_NUMBER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL];
-			}
-		}
-		found_store_cert = ca_store->find(cert_search_params);
-		
-		if(found_store_cert != ca_store->end())
-		{
-			LLSD foo = (*found_store_cert)->getLLSD();
-			// validate the store cert against the depth
-			_validateCert(validation_policy & VALIDATION_POLICY_CA_BASIC_CONSTRAINTS,
-						  (*found_store_cert),
-						  LLSD(),
-						  depth);
-			
-			// verify the signature of the CA
-			if(!_verify_signature((*found_store_cert),
-								  (*current_cert)))
-			{
-				throw LLCertValidationInvalidSignatureException(*current_cert);
-			}			
-			// successfully validated.
-			return;
-		}
-		previous_cert = (*current_cert);
-		current_cert++;
-			   depth++;
-	}
-	if (validation_policy & VALIDATION_POLICY_TRUSTED)
-	{
-		LLPointer<LLCertificate> untrusted_ca_cert = (*this)[size()-1];
-		// we reached the end without finding a trusted cert.
-		throw LLCertValidationTrustException((*this)[size()-1]);
-
-	}
-}
-
-
-// LLSecAPIBasicHandler Class
-// Interface handler class for the various security storage handlers.
-
-// We read the file on construction, and write it on destruction.  This
-// means multiple processes cannot modify the datastore.
-LLSecAPIBasicHandler::LLSecAPIBasicHandler(const std::string& protected_data_file,
-										   const std::string& legacy_password_path)
-{
-	mProtectedDataFilename = protected_data_file;
-	mProtectedDataMap = LLSD::emptyMap();
-	mLegacyPasswordPath = legacy_password_path;
-
-}
-
-LLSecAPIBasicHandler::LLSecAPIBasicHandler()
-{
-}
-
-
-void LLSecAPIBasicHandler::init()
-{
-	mProtectedDataMap = LLSD::emptyMap();
-	if (mProtectedDataFilename.length() == 0)
-	{
-		mProtectedDataFilename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
-															"bin_conf.dat");
-		mLegacyPasswordPath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "password.dat");
-	
-		mProtectedDataFilename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
-															"bin_conf.dat");	
-		std::string store_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
-														"CA.pem");
-		// copy the CA file to a user writable location so we can manipulate it.
-		// for this provider, by using a user writable file, there is a risk that
-		// an attacking program can modify the file, but OS dependent providers
-		// will reduce that risk.
-		// by using a user file, modifications will be limited to one user if
-		// we read-only the main file
-		if (!LLFile::isfile(store_file))
-		{
-
-			std::string ca_file_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
-			llifstream ca_file(ca_file_path.c_str(), llifstream::binary | llifstream::in);
-			llofstream copied_store_file(store_file.c_str(), llofstream::binary | llofstream::out);
-
-			while(!ca_file.fail())
-			{
-				char buffer[BUFFER_READ_SIZE];
-				ca_file.read(buffer, sizeof(buffer));
-				copied_store_file.write(buffer, ca_file.gcount());
-			}
-			ca_file.close();
-			copied_store_file.close();
-		}
-		LL_INFOS("SECAPI") << "Loading certificate store from " << store_file << LL_ENDL;
-		mStore = new LLBasicCertificateStore(store_file);
-	}
-	_readProtectedData(); // initialize mProtectedDataMap
-						  // may throw LLProtectedDataException if saved datamap is not decryptable
-}
-LLSecAPIBasicHandler::~LLSecAPIBasicHandler()
-{
-	_writeProtectedData();
-}
-
-void LLSecAPIBasicHandler::_readProtectedData()
-{	
-	// attempt to load the file into our map
-	LLPointer<LLSDParser> parser = new LLSDXMLParser();
-	llifstream protected_data_stream(mProtectedDataFilename.c_str(), 
-									llifstream::binary);
-
-	if (!protected_data_stream.fail()) {
-		int offset;
-		U8 salt[STORE_SALT_SIZE];
-		U8 buffer[BUFFER_READ_SIZE];
-		U8 decrypted_buffer[BUFFER_READ_SIZE];
-		int decrypted_length;	
-		unsigned char MACAddress[MAC_ADDRESS_BYTES];
-		LLUUID::getNodeID(MACAddress);
-		LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES);
-
-		// read in the salt and key
-		protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
-		offset = 0;
-		if (protected_data_stream.gcount() < STORE_SALT_SIZE)
-		{
-			throw LLProtectedDataException("Config file too short.");
-		}
-
-		cipher.decrypt(salt, STORE_SALT_SIZE);		
-
-		// totally lame.  As we're not using the OS level protected data, we need to
-		// at least obfuscate the data.  We do this by using a salt stored at the head of the file
-		// to encrypt the data, therefore obfuscating it from someone using simple existing tools.
-		// We do include the MAC address as part of the obfuscation, which would require an
-		// attacker to get the MAC address as well as the protected store, which improves things
-		// somewhat.  It would be better to use the password, but as this store
-		// will be used to store the SL password when the user decides to have SL remember it, 
-		// so we can't use that.  OS-dependent store implementations will use the OS password/storage 
-		// mechanisms and are considered to be more secure.
-		// We've a strong intent to move to OS dependent protected data stores.
-		
-
-		// read in the rest of the file.
-		EVP_CIPHER_CTX ctx;
-		EVP_CIPHER_CTX_init(&ctx);
-		EVP_DecryptInit(&ctx, EVP_rc4(), salt, NULL);
-		// allocate memory:
-		std::string decrypted_data;	
-		
-		while(protected_data_stream.good()) {
-			// read data as a block:
-			protected_data_stream.read((char *)buffer, BUFFER_READ_SIZE);
-			
-			EVP_DecryptUpdate(&ctx, decrypted_buffer, &decrypted_length, 
-							  buffer, protected_data_stream.gcount());
-			decrypted_data.append((const char *)decrypted_buffer, protected_data_stream.gcount());
-		}
-		
-		// RC4 is a stream cipher, so we don't bother to EVP_DecryptFinal, as there is
-		// no block padding.
-		EVP_CIPHER_CTX_cleanup(&ctx);
-		std::istringstream parse_stream(decrypted_data);
-		if (parser->parse(parse_stream, mProtectedDataMap, 
-						  LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
-		{
-			throw LLProtectedDataException("Config file cannot be decrypted.");
-		}
-	}
-}
-
-void LLSecAPIBasicHandler::_writeProtectedData()
-{	
-	std::ostringstream formatted_data_ostream;
-	U8 salt[STORE_SALT_SIZE];
-	U8 buffer[BUFFER_READ_SIZE];
-	U8 encrypted_buffer[BUFFER_READ_SIZE];
-
-	
-	if(mProtectedDataMap.isUndefined())
-	{
-		LLFile::remove(mProtectedDataFilename);
-		return;
-	}
-	// create a string with the formatted data.
-	LLSDSerialize::toXML(mProtectedDataMap, formatted_data_ostream);
-	std::istringstream formatted_data_istream(formatted_data_ostream.str());
-	// generate the seed
-	RAND_bytes(salt, STORE_SALT_SIZE);
-
-	
-	// write to a temp file so we don't clobber the initial file if there is
-	// an error.
-	std::string tmp_filename = mProtectedDataFilename + ".tmp";
-	
-	llofstream protected_data_stream(tmp_filename.c_str(), 
-										llofstream::binary);
-	try
-	{
-		
-		EVP_CIPHER_CTX ctx;
-		EVP_CIPHER_CTX_init(&ctx);
-		EVP_EncryptInit(&ctx, EVP_rc4(), salt, NULL);
-		unsigned char MACAddress[MAC_ADDRESS_BYTES];
-		LLUUID::getNodeID(MACAddress);
-		LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES);
-		cipher.encrypt(salt, STORE_SALT_SIZE);
-		protected_data_stream.write((const char *)salt, STORE_SALT_SIZE);
-
-		while (formatted_data_istream.good())
-		{
-			formatted_data_istream.read((char *)buffer, BUFFER_READ_SIZE);
-			if(formatted_data_istream.gcount() == 0)
-			{
-				break;
-			}
-			int encrypted_length;
-			EVP_EncryptUpdate(&ctx, encrypted_buffer, &encrypted_length, 
-						  buffer, formatted_data_istream.gcount());
-			protected_data_stream.write((const char *)encrypted_buffer, encrypted_length);
-		}
-		
-		// no EVP_EncrypteFinal, as this is a stream cipher
-		EVP_CIPHER_CTX_cleanup(&ctx);
-
-		protected_data_stream.close();
-	}
-	catch (...)
-	{
-		// it's good practice to clean up any secure information on error
-		// (even though this file isn't really secure.  Perhaps in the future
-		// it may be, however.
-		LLFile::remove(tmp_filename);
-		throw LLProtectedDataException("Error writing Protected Data Store");
-	}
-
-	// move the temporary file to the specified file location.
-	if((((LLFile::isfile(mProtectedDataFilename) != 0) && 
-		 (LLFile::remove(mProtectedDataFilename) != 0))) || 
-	   (LLFile::rename(tmp_filename, mProtectedDataFilename)))
-	{
-		LLFile::remove(tmp_filename);
-		throw LLProtectedDataException("Could not overwrite protected data store");
-	}
-}
-		
-// instantiate a certificate from a pem string
-LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert)
-{
-	LLPointer<LLCertificate> result = new LLBasicCertificate(pem_cert);
-	return result;
-}
-		
-
-		
-// instiate a certificate from an openssl X509 structure
-LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(X509* openssl_cert)
-{
-	LLPointer<LLCertificate> result = new LLBasicCertificate(openssl_cert);
-	return result;		
-}
-		
-// instantiate a chain from an X509_STORE_CTX
-LLPointer<LLCertificateChain> LLSecAPIBasicHandler::getCertificateChain(const X509_STORE_CTX* chain)
-{
-	LLPointer<LLCertificateChain> result = new LLBasicCertificateChain(chain);
-	return result;
-}
-		
-// instantiate a cert store given it's id.  if a persisted version
-// exists, it'll be loaded.  If not, one will be created (but not
-// persisted)
-LLPointer<LLCertificateStore> LLSecAPIBasicHandler::getCertificateStore(const std::string& store_id)
-{
-	return mStore;
-}
-		
-// retrieve protected data
-LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type,
-											const std::string& data_id)
-{
-
-	if (mProtectedDataMap.has(data_type) && 
-		mProtectedDataMap[data_type].isMap() && 
-		mProtectedDataMap[data_type].has(data_id))
-	{
-		return mProtectedDataMap[data_type][data_id];
-	}
-																				
-	return LLSD();
-}
-
-void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type,
-											   const std::string& data_id)
-{
-	if (mProtectedDataMap.has(data_type) &&
-		mProtectedDataMap[data_type].isMap() &&
-		mProtectedDataMap[data_type].has(data_id))
-		{
-			mProtectedDataMap[data_type].erase(data_id);
-		}
-}
-
-
-//
-// persist data in a protected store
-//
-void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type,
-											const std::string& data_id,
-											const LLSD& data)
-{
-	if (!mProtectedDataMap.has(data_type) || !mProtectedDataMap[data_type].isMap()) {
-		mProtectedDataMap[data_type] = LLSD::emptyMap();
-	}
-	
-	mProtectedDataMap[data_type][data_id] = data; 
-}
-
-//
-// Create a credential object from an identifier and authenticator.  credentials are
-// per grid.
-LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid,
-															   const LLSD& identifier, 
-															   const LLSD& authenticator)
-{
-	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
-	result->setCredentialData(identifier, authenticator);
-	return result;
-}
-
-// Load a credential from the credential store, given the grid
-LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid)
-{
-	LLSD credential = getProtectedData("credential", grid);
-	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
-	if(credential.isMap() && 
-	   credential.has("identifier"))
-	{
-
-		LLSD identifier = credential["identifier"];
-		LLSD authenticator;
-		if (credential.has("authenticator"))
-		{
-			authenticator = credential["authenticator"];
-		}
-		result->setCredentialData(identifier, authenticator);
-	}
-	else
-	{
-		// credential was not in protected storage, so pull the credential
-		// from the legacy store.
-		std::string first_name = gSavedSettings.getString("FirstName");
-		std::string last_name = gSavedSettings.getString("LastName");
-		
-		if ((first_name != "") &&
-			(last_name != ""))
-		{
-			LLSD identifier = LLSD::emptyMap();
-			LLSD authenticator;
-			identifier["type"] = "agent";
-			identifier["first_name"] = first_name;
-			identifier["last_name"] = last_name;
-			
-			std::string legacy_password = _legacyLoadPassword();
-			if (legacy_password.length() > 0)
-			{
-				authenticator = LLSD::emptyMap();
-				authenticator["type"] = "hash";
-				authenticator["algorithm"] = "md5";
-				authenticator["secret"] = legacy_password;
-			}
-			result->setCredentialData(identifier, authenticator);
-		}		
-	}
-	return result;
-}
-
-// Save the credential to the credential store.  Save the authenticator also if requested.
-// That feature is used to implement the 'remember password' functionality.
-void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)
-{
-	LLSD credential = LLSD::emptyMap();
-	credential["identifier"] = cred->getIdentifier(); 
-	if (save_authenticator) 
-	{
-		credential["authenticator"] = cred->getAuthenticator();
-	}
-	LL_INFOS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
-	setProtectedData("credential", cred->getGrid(), credential);
-	//*TODO: If we're saving Agni credentials, should we write the
-	// credentials to the legacy password.dat/etc?
-	_writeProtectedData();
-}
-
-// Remove a credential from the credential store.
-void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred)
-{
-	LLSD undefVal;
-	deleteProtectedData("credential", cred->getGrid());
-	cred->setCredentialData(undefVal, undefVal);
-	_writeProtectedData();
-}
-
-// load the legacy hash for agni, and decrypt it given the 
-// mac address
-std::string LLSecAPIBasicHandler::_legacyLoadPassword()
-{
-	const S32 HASHED_LENGTH = 32;	
-	std::vector<U8> buffer(HASHED_LENGTH);
-	llifstream password_file(mLegacyPasswordPath, llifstream::binary);
-	
-	if(password_file.fail())
-	{
-		return std::string("");
-	}
-	
-	password_file.read((char*)&buffer[0], buffer.size());
-	if(password_file.gcount() != buffer.size())
-	{
-		return std::string("");
-	}
-	
-	// Decipher with MAC address
-	unsigned char MACAddress[MAC_ADDRESS_BYTES];
-	LLUUID::getNodeID(MACAddress);
-	LLXORCipher cipher(MACAddress, 6);
-	cipher.decrypt(&buffer[0], buffer.size());
-	
-	return std::string((const char*)&buffer[0], buffer.size());
-}
-
-
-// return an identifier for the user
-std::string LLSecAPIBasicCredential::userID() const
-{
-	if (!mIdentifier.isMap())
-	{
-		return mGrid + "(null)";
-	}
-	else if ((std::string)mIdentifier["type"] == "agent")
-	{
-		return  (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
-	}
-	else if ((std::string)mIdentifier["type"] == "account")
-	{
-		return (std::string)mIdentifier["account_name"];
-	}
-
-	return "unknown";
-
-}
-
-// return a printable user identifier
-std::string LLSecAPIBasicCredential::asString() const
-{
-	if (!mIdentifier.isMap())
-	{
-		return mGrid + ":(null)";
-	}
-	else if ((std::string)mIdentifier["type"] == "agent")
-	{
-		return mGrid + ":" + (std::string)mIdentifier["first_name"] + " " + (std::string)mIdentifier["last_name"];
-	}
-	else if ((std::string)mIdentifier["type"] == "account")
-	{
-		return mGrid + ":" + (std::string)mIdentifier["account_name"];
-	}
-
-	return mGrid + ":(unknown type)";
-}
-
-
-bool valueCompareLLSD(const LLSD& lhs, const LLSD& rhs)
-{
-	if (lhs.type() != rhs.type())
-	{
-		return FALSE;
-	}
-    if (lhs.isMap())
-	{
-		// iterate through the map, verifying the right hand side has all of the
-		// values that the left hand side has.
-		for (LLSD::map_const_iterator litt = lhs.beginMap();
-			 litt != lhs.endMap();
-			 litt++)
-		{
-			if (!rhs.has(litt->first))
-			{
-				return FALSE;
-			}
-		}
-		
-		// Now validate that the left hand side has everything the
-		// right hand side has, and that the values are equal.
-		for (LLSD::map_const_iterator ritt = rhs.beginMap();
-			 ritt != rhs.endMap();
-			 ritt++)
-		{
-			if (!lhs.has(ritt->first))
-			{
-				return FALSE;
-			}
-			if (!valueCompareLLSD(lhs[ritt->first], ritt->second))
-			{
-				return FALSE;
-			}
-		}
-		return TRUE;
-	}
-    else if (lhs.isArray())
-	{
-		LLSD::array_const_iterator ritt = rhs.beginArray();
-		// iterate through the array, comparing
-		for (LLSD::array_const_iterator litt = lhs.beginArray();
-			 litt != lhs.endArray();
-			 litt++)
-		{
-			if (!valueCompareLLSD(*ritt, *litt))
-			{
-				return FALSE;
-			}
-			ritt++;
-		}
-		
-		return (ritt == rhs.endArray());
-	}
-    else
-	{
-		// simple type, compare as string
-		return (lhs.asString() == rhs.asString());
-	}
-	
-}
diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h
deleted file mode 100644
index 4bbb73f062a1c0f357f835a12aef056e5606cc49..0000000000000000000000000000000000000000
--- a/indra/newview/llsechandler_basic.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/** 
- * @file llsechandler_basic.h
- * @brief Security API for services such as certificate handling
- * secure local storage, etc.
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 LLSECHANDLER_BASIC
-#define LLSECHANDLER_BASIC
-
-#include "llsecapi.h"
-#include <vector>
-#include <openssl/x509.h>
-
-// helpers
-extern LLSD cert_name_from_X509_NAME(X509_NAME* name);
-extern std::string cert_string_name_from_X509_NAME(X509_NAME* name);
-extern std::string cert_string_from_asn1_integer(ASN1_INTEGER* value);
-extern LLDate cert_date_from_asn1_time(ASN1_TIME* asn1_time);
-extern std::string cert_get_digest(const std::string& digest_type, X509 *cert);
-
-
-// class LLCertificate
-// 
-class LLBasicCertificate : public LLCertificate
-{
-public:		
-	LOG_CLASS(LLBasicCertificate);
-
-	LLBasicCertificate(const std::string& pem_cert);
-	LLBasicCertificate(X509* openSSLX509);
-	
-	virtual ~LLBasicCertificate();
-	
-	virtual std::string getPem() const;
-	virtual std::vector<U8> getBinary() const;
-	virtual LLSD getLLSD() const;
-
-	virtual X509* getOpenSSLX509() const;
-	
-	// set llsd elements for testing
-	void setLLSD(const std::string name, const LLSD& value) { mLLSDInfo[name] = value; }
-protected:
-
-	// certificates are stored as X509 objects, as validation and
-	// other functionality is via openssl
-	X509* mCert;
-	
-	LLSD& _initLLSD();
-	LLSD mLLSDInfo;
-};
-
-
-// class LLBasicCertificateVector
-// Class representing a list of certificates
-// This implementation uses a stl vector of certificates.
-class LLBasicCertificateVector : virtual public LLCertificateVector
-{
-	
-public:
-	LLBasicCertificateVector() {}
-	
-	virtual ~LLBasicCertificateVector() {}
-	
-	// Implementation of the basic iterator implementation.
-	// The implementation uses a vector iterator derived from 
-	// the vector in the LLBasicCertificateVector class
-	class BasicIteratorImpl : public iterator_impl
-	{
-	public:
-		BasicIteratorImpl(std::vector<LLPointer<LLCertificate> >::iterator _iter) { mIter = _iter;}
-		virtual ~BasicIteratorImpl() {};
-		// seek forward or back.  Used by the operator++/operator-- implementations
-		virtual void seek(bool incr)
-		{
-			if(incr)
-			{
-				mIter++;
-			}
-			else
-			{
-				mIter--;
-			}
-		}
-		// create a copy of the iterator implementation class, used by the iterator copy constructor
-		virtual LLPointer<iterator_impl> clone() const
-		{
-			return new BasicIteratorImpl(mIter);
-		}
-		
-		virtual bool equals(const LLPointer<iterator_impl>& _iter) const
-		{
-			const BasicIteratorImpl *rhs_iter = dynamic_cast<const BasicIteratorImpl *>(_iter.get());
-			return (mIter == rhs_iter->mIter);
-		}
-		virtual LLPointer<LLCertificate> get()
-		{
-			return *mIter;
-		}
-	protected:
-		friend class LLBasicCertificateVector;
-		std::vector<LLPointer<LLCertificate> >::iterator mIter;
-	};
-	
-	// numeric index of the vector
-	virtual LLPointer<LLCertificate> operator[](int _index) { return mCerts[_index];}
-	
-	// Iteration
-	virtual iterator begin() { return iterator(new BasicIteratorImpl(mCerts.begin())); }
-	
-	virtual iterator end() {  return iterator(new BasicIteratorImpl(mCerts.end())); }
-	
-	// find a cert given params
-	virtual iterator find(const LLSD& params);
-	
-	// return the number of certs in the store
-	virtual int size() const { return mCerts.size(); }	
-	
-	// insert the cert to the store.  if a copy of the cert already exists in the store, it is removed first
-	virtual void  add(LLPointer<LLCertificate> cert) { insert(end(), cert); }
-	
-	// insert the cert to the store.  if a copy of the cert already exists in the store, it is removed first
-	virtual void  insert(iterator _iter, LLPointer<LLCertificate> cert);	
-	
-	// remove a certificate from the store
-	virtual LLPointer<LLCertificate> erase(iterator _iter);
-	
-protected:
-	std::vector<LLPointer<LLCertificate> >mCerts;	
-};
-
-// class LLCertificateStore
-// represents a store of certificates, typically a store of root CA
-// certificates.  The store can be persisted, and can be used to validate
-// a cert chain
-//
-class LLBasicCertificateStore : virtual public LLBasicCertificateVector, public LLCertificateStore
-{
-public:
-	LLBasicCertificateStore(const std::string& filename);
-	void load_from_file(const std::string& filename);
-	
-	virtual ~LLBasicCertificateStore();
-	
-	// persist the store
-	virtual void save();
-	
-	// return the store id
-	virtual std::string storeId() const;
-	
-protected:
-	std::vector<LLPointer<LLCertificate> >mCerts;
-	std::string mFilename;
-};
-
-// class LLCertificateChain
-// Class representing a chain of certificates in order, with the 
-// first element being the child cert.
-class LLBasicCertificateChain : virtual public LLBasicCertificateVector, public LLCertificateChain
-{
-	
-public:
-	LLBasicCertificateChain(const X509_STORE_CTX * store);
-	
-	virtual ~LLBasicCertificateChain() {}
-	
-	// validate a certificate chain against a certificate store, using the
-	// given validation policy.
-	virtual void validate(int validation_policy,
-						  LLPointer<LLCertificateStore> ca_store,
-						  const LLSD& validation_params);
-};
-
-
-
-// LLSecAPIBasicCredential class
-class LLSecAPIBasicCredential : public LLCredential
-{
-public:
-	LLSecAPIBasicCredential(const std::string& grid) : LLCredential(grid) {} 
-	virtual ~LLSecAPIBasicCredential() {}
-	// return a value representing the user id, (could be guid, name, whatever)
-	virtual std::string userID() const;	
-	
-	// printible string identifying the credential.
-	virtual std::string asString() const;
-};
-
-// LLSecAPIBasicHandler Class
-// Interface handler class for the various security storage handlers.
-class LLSecAPIBasicHandler : public LLSecAPIHandler
-{
-public:
-	
-	LLSecAPIBasicHandler(const std::string& protected_data_filename,
-						 const std::string& legacy_password_path);
-	LLSecAPIBasicHandler();
-	
-	void init();
-	
-	virtual ~LLSecAPIBasicHandler();
-	
-	// instantiate a certificate from a pem string
-	virtual LLPointer<LLCertificate> getCertificate(const std::string& pem_cert);
-	
-	
-	// instiate a certificate from an openssl X509 structure
-	virtual LLPointer<LLCertificate> getCertificate(X509* openssl_cert);
-	
-	// instantiate a chain from an X509_STORE_CTX
-	virtual LLPointer<LLCertificateChain> getCertificateChain(const X509_STORE_CTX* chain);
-	
-	// instantiate a cert store given it's id.  if a persisted version
-	// exists, it'll be loaded.  If not, one will be created (but not
-	// persisted)
-	virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id);
-	
-	// persist data in a protected store
-	virtual void setProtectedData(const std::string& data_type,
-								  const std::string& data_id,
-								  const LLSD& data);
-	
-	// retrieve protected data
-	virtual LLSD getProtectedData(const std::string& data_type,
-								  const std::string& data_id);
-	
-	// delete a protected data item from the store
-	virtual void deleteProtectedData(const std::string& data_type,
-									 const std::string& data_id);
-	
-	// credential management routines
-	
-	virtual LLPointer<LLCredential> createCredential(const std::string& grid,
-													 const LLSD& identifier, 
-													 const LLSD& authenticator);
-	
-	virtual LLPointer<LLCredential> loadCredential(const std::string& grid);
-
-	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator);
-	
-	virtual void deleteCredential(LLPointer<LLCredential> cred);
-	
-protected:
-	void _readProtectedData();
-	void _writeProtectedData();
-	std::string _legacyLoadPassword();
-
-	std::string mProtectedDataFilename;
-	LLSD mProtectedDataMap;
-	LLPointer<LLBasicCertificateStore> mStore;
-	
-	std::string mLegacyPasswordPath;
-};
-
-bool valueCompareLLSD(const LLSD& lhs, const LLSD& rhs);
-
-#endif // LLSECHANDLER_BASIC
-
-
-
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 3ef810c3e95dcbc95a05af6ba41511960d9a5001..d03a492cd1002146da0a6ecc2b074f254bf95836 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2435,7 +2435,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
 	
 	if (identical)
 	{
-		name = LLSLURL("agent", first_id, "inspect").getSLURLString();
+		name = LLSLURL::buildCommand("agent", first_id, "inspect");
 	}
 	else
 	{
@@ -2494,11 +2494,11 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name)
 		BOOL public_owner = (first_id.isNull() && !first_group_owned);
 		if (first_group_owned)
 		{
-			name = LLSLURL("group", first_id, "inspect").getSLURLString();
+			name = LLSLURL::buildCommand("group", first_id, "inspect");
 		}
 		else if(!public_owner)
 		{
-			name = LLSLURL("agent", first_id, "inspect").getSLURLString();
+			name = LLSLURL::buildCommand("agent", first_id, "inspect");
 		}
 		else
 		{
@@ -2558,7 +2558,7 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name)
 		BOOL public_owner = (first_id.isNull());
 		if(!public_owner)
 		{
-			name = LLSLURL("agent", first_id, "inspect").getSLURLString();
+			name = LLSLURL::buildCommand("agent", first_id, "inspect");
 		}
 		else
 		{
diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp
index ff7e479368a6a5ace6f0f8ff46e3dd99aa9666a9..5d20e280b5f23308601a75d0f0c455eeefde3a71 100644
--- a/indra/newview/llslurl.cpp
+++ b/indra/newview/llslurl.cpp
@@ -1,11 +1,10 @@
 /** 
- * @file llurlsimstring.cpp (was llsimurlstring.cpp)
- * @brief Handles "SLURL fragments" like Ahern/123/45 for
- * startup processing, login screen, prefs, etc.
+ * @file llslurl.cpp
+ * @brief SLURL manipulation
  *
- * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
  * 
- * Copyright (c) 2006-2010, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
  * 
  * Second Life Viewer Source Code
  * The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +12,13 @@
  * ("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://secondlife.com/developers/opensource/gplv2
+ * 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://secondlife.com/developers/opensource/flossexception
+ * 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,
@@ -34,443 +34,155 @@
 
 #include "llslurl.h"
 
-#include "llpanellogin.h"
-#include "llviewercontrol.h"
-#include "llviewernetwork.h"
-#include "llfiltersd2xmlrpc.h"
-#include "curl/curl.h"
-const char* LLSLURL::SLURL_HTTP_SCHEME		 = "http";
-const char* LLSLURL::SLURL_HTTPS_SCHEME		 = "https";
-const char* LLSLURL::SLURL_SECONDLIFE_SCHEME	 = "secondlife";
-const char* LLSLURL::SLURL_SECONDLIFE_PATH	 = "secondlife";
-const char* LLSLURL::SLURL_COM		         = "slurl.com";
-// For DnD - even though www.slurl.com redirects to slurl.com in a browser, you  can copy and drag
+#include "llweb.h"
+
+#include "llurlregistry.h"
+
+const std::string LLSLURL::PREFIX_SL_HELP		= "secondlife://app.";
+const std::string LLSLURL::PREFIX_SL			= "sl://";
+const std::string LLSLURL::PREFIX_SECONDLIFE	= "secondlife://";
+const std::string LLSLURL::PREFIX_SLURL_OLD		= "http://slurl.com/secondlife/";
+
+// For DnD - even though www.slurl.com redirects to slurl.com in a browser, you can copy and drag
 // text with www.slurl.com or a link explicitly pointing at www.slurl.com so testing for this
 // version is required also.
+const std::string LLSLURL::PREFIX_SLURL_WWW		= "http://www.slurl.com/secondlife/";
 
-const char* LLSLURL::WWW_SLURL_COM		 = "www.slurl.com";
-const char* LLSLURL::MAPS_SECONDLIFE_COM	 = "maps.secondlife.com";	
-const char* LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME = "x-grid-location-info";
-const char* LLSLURL::SLURL_APP_PATH              = "app";
-const char* LLSLURL::SLURL_REGION_PATH           = "region";
-const char* LLSLURL::SIM_LOCATION_HOME           = "home";
-const char* LLSLURL::SIM_LOCATION_LAST           = "last";
+const std::string LLSLURL::PREFIX_SLURL			= "http://maps.secondlife.com/secondlife/";
 
-// resolve a simstring from a slurl
-LLSLURL::LLSLURL(const std::string& slurl)
+const std::string LLSLURL::APP_TOKEN = "app/";
+
+// static
+std::string LLSLURL::stripProtocol(const std::string& url)
 {
-	// by default we go to agni.
-	mType = INVALID;
-	LL_INFOS("AppInit") << "SLURL: " << slurl << LL_ENDL;
-	if(slurl == SIM_LOCATION_HOME)
+	std::string stripped = url;
+	if (matchPrefix(stripped, PREFIX_SL_HELP))
 	{
-		mType = HOME_LOCATION;
+		stripped.erase(0, PREFIX_SL_HELP.length());
 	}
-	else if(slurl.empty() || (slurl == SIM_LOCATION_LAST))
+	else if (matchPrefix(stripped, PREFIX_SL))
 	{
-
-		mType = LAST_LOCATION;
+		stripped.erase(0, PREFIX_SL.length());
 	}
-	else
+	else if (matchPrefix(stripped, PREFIX_SECONDLIFE))
 	{
-		LLURI slurl_uri;
-		// parse the slurl as a uri
-		if(slurl.find(':') == std::string::npos)
-		{
-			// There may be no scheme ('secondlife:' etc.) passed in.  In that case
-			// we want to normalize the slurl by putting the appropriate scheme
-			// in front of the slurl.  So, we grab the appropriate slurl base
-			// from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or
-			// https://<hostname>/region/ for Standalone grid (the word region, not the region name)
-			// these slurls are typically passed in from the 'starting location' box on the login panel,
-			// where the user can type in <regionname>/<x>/<y>/<z>
-			std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase();
-			// the slurl that was passed in might have a prepended /, or not.  So,
-			// we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife/<region>/<x>/<y>/<z>
-			// or some such.
-			
-			if(slurl[0] == '/')
-		    {
-				fixed_slurl += slurl.substr(1);
-		    }
-			else
-		    {
-				fixed_slurl += slurl;
-		    }
-			// We then load the slurl into a LLURI form
-			slurl_uri = LLURI(fixed_slurl);
-		}
-		else
-		{
-		    // as we did have a scheme, implying a URI style slurl, we
-		    // simply parse it as a URI
-		    slurl_uri = LLURI(slurl);
-		}
-		
-		LLSD path_array = slurl_uri.pathArray();
-		
-		// determine whether it's a maingrid URI or an Standalone/open style URI
-		// by looking at the scheme.  If it's a 'secondlife:' slurl scheme or
-		// 'sl:' scheme, we know it's maingrid
-		
-		// At the end of this if/else block, we'll have determined the grid,
-		// and the slurl type (APP or LOCATION)
-		if(slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
-		{
-			// parse a maingrid style slurl.  We know the grid is maingrid
-			// so grab it.
-			// A location slurl for maingrid (with the special schemes) can be in the form
-			// secondlife://<regionname>/<x>/<y>/<z>
-			// or
-			// secondlife://<Grid>/secondlife/<region>/<x>/<y>/<z>
-			// where if grid is empty, it specifies Agni
-			
-			// An app style slurl for maingrid can be
-			// secondlife://<Grid>/app/<app parameters>
-			// where an empty grid implies Agni
-			
-			// we'll start by checking the top of the 'path' which will be 
-			// either 'app', 'secondlife', or <x>.
-			
-			// default to maingrid
-			
-			mGrid = MAINGRID;
-			
-			if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) ||
-				(path_array[0].asString() == LLSLURL::SLURL_APP_PATH))
-		    {
-				// it's in the form secondlife://<grid>/(app|secondlife)
-				// so parse the grid name to derive the grid ID
-				if (!slurl_uri.hostName().empty())
-				{
-					mGrid = LLGridManager::getInstance()->getGridByLabel(slurl_uri.hostName());
-				}
-				else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
-				{
-					// If the slurl is in the form secondlife:///secondlife/<region> form, 
-					// then we are in fact on maingrid.  
-					mGrid = MAINGRID;
-				}
-				else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
-				{
-					// for app style slurls, where no grid name is specified, assume the currently
-					// selected or logged in grid.
-					mGrid =  LLGridManager::getInstance()->getGrid();
-				}
-
-				if(mGrid.empty())
-				{
-					// we couldn't find the grid in the grid manager, so bail
-					return;
-				}
-				// set the type as appropriate.
-				if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
-				{
-					mType = LOCATION;
-				}
-				else
-				{
-					mType = APP;
-				}
-				path_array.erase(0);
-		    }
-			else
-		    {
-				// it wasn't a /secondlife/<region> or /app/<params>, so it must be secondlife://<region>
-				// therefore the hostname will be the region name, and it's a location type
-				mType = LOCATION;
-				// 'normalize' it so the region name is in fact the head of the path_array
-				path_array.insert(0, slurl_uri.hostName());
-		    }
-		}
-		else if((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) ||
-		   (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || 
-		   (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME))
-		{
-		    // We're dealing with either a Standalone style slurl or slurl.com slurl
-		  if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) ||
-		      (slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) || 
-		      (slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM))
-			{
-				// slurl.com implies maingrid
-				mGrid = MAINGRID;
-			}
-		    else
-			{
-				// As it's a Standalone grid/open, we will always have a hostname, as Standalone/open  style
-				// urls are properly formed, unlike the stinky maingrid style
-				mGrid = slurl_uri.hostName();
-			}
-		    if (path_array.size() == 0)
-			{
-				// um, we need a path...
-				return;
-			}
-			
-			// we need to normalize the urls so
-			// the path portion starts with the 'command' that we want to do
-			// it can either be region or app.  
-		    if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) ||
-				(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH))
-			{
-				// strip off 'region' or 'secondlife'
-				path_array.erase(0);
-				// it's a location
-				mType = LOCATION;
-			}
-			else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
-			{
-				mType = APP;
-				path_array.erase(0);
-				// leave app appended.  
-			}
-			else
-			{
-				// not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL
-				return;
-			}
-		}
-		else
-		{
-		    // invalid scheme, so bail
-		    return;
-		}
-		
-		
-		if(path_array.size() == 0)
-		{
-			// we gotta have some stuff after the specifier as to whether it's a region or command
-			return;
-		}
-		
-		// now that we know whether it's an app slurl or a location slurl,
-		// parse the slurl into the proper data structures.
-		if(mType == APP)
-		{		
-			// grab the app command type and strip it (could be a command to jump somewhere, 
-			// or whatever )
-			mAppCmd = path_array[0].asString();
-			path_array.erase(0);
-			
-			// Grab the parameters
-			mAppPath = path_array;
-			// and the query
-			mAppQuery = slurl_uri.query();
-			mAppQueryMap = slurl_uri.queryMap();
-			return;
-		}
-		else if(mType == LOCATION)
-		{
-			// at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z 
-			// are collectively optional
-			// are optional
-			mRegion = LLURI::unescape(path_array[0].asString());
-			path_array.erase(0);
-			
-			// parse the x, y, z
-			if(path_array.size() >= 3)
-			{	
-			  
-			  mPosition = LLVector3(path_array);
-			  if((F32(mPosition[VX]) < 0.f) || 
-                             (mPosition[VX] > REGION_WIDTH_METERS) ||
-			     (F32(mPosition[VY]) < 0.f) || 
-                             (mPosition[VY] > REGION_WIDTH_METERS) ||
-			     (F32(mPosition[VZ]) < 0.f) || 
-                             (mPosition[VZ] > REGION_HEIGHT_METERS))
-			    {
-			      mType = INVALID;
-			      return;
-			    }
- 
-			}
-			else
-			{
-				// if x, y and z were not fully passed in, go to the middle of the region.
-				// teleport will adjust the actual location to make sure you're on the ground
-				// and such
-				mPosition = LLVector3(REGION_WIDTH_METERS/2, REGION_WIDTH_METERS/2, 0);
-			}
-		}
+		stripped.erase(0, PREFIX_SECONDLIFE.length());
+	}
+	else if (matchPrefix(stripped, PREFIX_SLURL))
+	{
+		stripped.erase(0, PREFIX_SLURL.length());
 	}
+	else if (matchPrefix(stripped, PREFIX_SLURL_OLD))
+	{
+		stripped.erase(0, PREFIX_SLURL_OLD.length());
+	}
+	else if (matchPrefix(stripped, PREFIX_SLURL_WWW))
+	{
+		stripped.erase(0, PREFIX_SLURL_WWW.length());
+	}
+	
+	return stripped;
 }
 
-
-// Create a slurl for the middle of the region
-LLSLURL::LLSLURL(const std::string& grid, 
-				 const std::string& region)
+// static
+bool LLSLURL::isSLURL(const std::string& url)
 {
-	mGrid = grid;
-	mRegion = region;
-	mType = LOCATION;
-	mPosition = LLVector3((F64)REGION_WIDTH_METERS/2, (F64)REGION_WIDTH_METERS/2, 0);
+	if (matchPrefix(url, PREFIX_SL_HELP))		return true;
+	if (matchPrefix(url, PREFIX_SL))			return true;
+	if (matchPrefix(url, PREFIX_SECONDLIFE))	return true;
+	if (matchPrefix(url, PREFIX_SLURL))			return true;
+	if (matchPrefix(url, PREFIX_SLURL_OLD))		return true;
+	if (matchPrefix(url, PREFIX_SLURL_WWW))		return true;
+	
+	return false;
 }
 
-
-
-// create a slurl given the position.  The position will be modded with the region
-// width handling global positions as well
-LLSLURL::LLSLURL(const std::string& grid, 
-		 const std::string& region, 
-		 const LLVector3& position)
+bool LLSLURL::isValidSLURL(const std::string& url)
 {
-	mGrid = grid;
-	mRegion = region;
-	S32 x = llround( (F32)fmod( position[VX], (F32)REGION_WIDTH_METERS ) );
-	S32 y = llround( (F32)fmod( position[VY], (F32)REGION_WIDTH_METERS ) );
-	S32 z = llround( (F32)position[VZ] );
-	mType = LOCATION;
-	mPosition = LLVector3(x, y, z);
+	std::string temp_url(url);
+	//"www." may appear in DnD- see description of PREFIX_SLURL_WWW.
+	// If it is found, we remove it because it isn't expected in regexp.
+	if (matchPrefix(url, PREFIX_SLURL_WWW))
+	{
+		size_t position = url.find("www.");
+		temp_url.erase(position,4);
+	}
+	
+	return LLUrlRegistry::getInstance()->isUrl(temp_url);
 }
 
+// static
+bool LLSLURL::isSLURLCommand(const std::string& url)
+{ 
+	if (matchPrefix(url, PREFIX_SL + APP_TOKEN) ||
+		matchPrefix(url, PREFIX_SECONDLIFE + "/" + APP_TOKEN) ||
+		matchPrefix(url, PREFIX_SLURL + APP_TOKEN) ||
+		matchPrefix(url, PREFIX_SLURL_WWW + APP_TOKEN) ||
+		matchPrefix(url, PREFIX_SLURL_OLD + APP_TOKEN) )
+	{
+		return true;
+	}
 
-// create a simstring
-LLSLURL::LLSLURL(const std::string& region, 
-		 const LLVector3& position)
-{
-  *this = LLSLURL(LLGridManager::getInstance()->getGrid(),
-		  region, position);
+	return false;
 }
 
-// create a slurl from a global position
-LLSLURL::LLSLURL(const std::string& grid, 
-		 const std::string& region, 
-		 const LLVector3d& global_position)
+// static
+bool LLSLURL::isSLURLHelp(const std::string& url)
 {
-  *this = LLSLURL(grid,
-		  region, LLVector3(global_position.mdV[VX],
-				    global_position.mdV[VY],
-				    global_position.mdV[VZ]));
+	return matchPrefix(url, PREFIX_SL_HELP);
 }
 
-// create a slurl from a global position
-LLSLURL::LLSLURL(const std::string& region, 
-		 const LLVector3d& global_position)
+// static
+std::string LLSLURL::buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z)
 {
-  *this = LLSLURL(LLGridManager::getInstance()->getGrid(),
-		  region, global_position);
+	std::string slurl = PREFIX_SLURL + regionname + llformat("/%d/%d/%d",x,y,z); 
+	slurl = LLWeb::escapeURL( slurl );
+	return slurl;
 }
 
-LLSLURL::LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb)
+// static
+std::string LLSLURL::buildCommand(const char* noun, const LLUUID& id, const char* verb)
 {
-  mType = APP;
-  mAppCmd = command;
-  mAppPath = LLSD::emptyArray();
-  mAppPath.append(LLSD(id));
-  mAppPath.append(LLSD(verb));
+	std::string slurl = llformat("secondlife:///app/%s/%s/%s",
+		noun, id.asString().c_str(), verb);
+	return slurl;
 }
 
-
-std::string LLSLURL::getSLURLString() const
+// static
+std::string LLSLURL::buildUnescapedSLURL(const std::string& regionname, S32 x, S32 y, S32 z)
 {
-	switch(mType)
-	{
-		case HOME_LOCATION:
-			return SIM_LOCATION_HOME;
-		case LAST_LOCATION:
-			return SIM_LOCATION_LAST;
-		case LOCATION:
-			{
-				// lookup the grid
-				S32 x = llround( (F32)mPosition[VX] );
-				S32 y = llround( (F32)mPosition[VY] );
-				S32 z = llround( (F32)mPosition[VZ] );	
-				return LLGridManager::getInstance()->getSLURLBase(mGrid) + 
-				LLURI::escape(mRegion) + llformat("/%d/%d/%d",x,y,z); 
-			}
-		case APP:
-		{
-			std::ostringstream app_url;
-			app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd;
-			for(LLSD::array_const_iterator i = mAppPath.beginArray();
-				i != mAppPath.endArray();
-				i++)
-			{
-				app_url << "/" << i->asString();
-			}
-			if(mAppQuery.length() > 0)
-			{
-				app_url << "?" << mAppQuery;
-			}
-			return app_url.str();
-		}	
-		default:
-			LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL;			
-			return std::string();
-	}
+	std::string unescapedslurl = PREFIX_SLURL + regionname + llformat("/%d/%d/%d",x,y,z);
+	return unescapedslurl;
 }
 
-std::string LLSLURL::getLoginString() const
+// static
+std::string LLSLURL::buildSLURLfromPosGlobal(const std::string& regionname,
+											 const LLVector3d& global_pos,
+											 bool escaped /*= true*/)
 {
-	
-	std::stringstream unescaped_start;
-	switch(mType)
+	S32 x, y, z;
+	globalPosToXYZ(global_pos, x, y, z);
+	if(escaped)
 	{
-		case LOCATION:
-			unescaped_start << "uri:" 
-			<< mRegion << "&" 
-			<< llround(mPosition[0]) << "&" 
-			<< llround(mPosition[1]) << "&" 
-			<< llround(mPosition[2]);
-			break;
-		case HOME_LOCATION:
-			unescaped_start << "home";
-			break;
-		case LAST_LOCATION:
-			unescaped_start << "last";
-			break;
-		default:
-			LL_WARNS("AppInit") << "Unexpected SLURL type for login string" << (int)mType << LL_ENDL;
-			break;
+		return buildSLURL(regionname, x, y, z);
 	}
-	return  xml_escape_string(unescaped_start.str());
-}
-
-bool LLSLURL::operator==(const LLSLURL& rhs)
-{
-	if(rhs.mType != mType) return false;
-	switch(mType)
+	else
 	{
-		case LOCATION:
-			return ((mGrid == rhs.mGrid) &&
-					(mRegion == rhs.mRegion) &&
-					(mPosition == rhs.mPosition));
-		case APP:
-			return getSLURLString() == rhs.getSLURLString();
-			
-		case HOME_LOCATION:
-		case LAST_LOCATION:
-			return true;
-		default:
-			return false;
+		return buildUnescapedSLURL(regionname, x, y, z);
 	}
 }
 
-bool LLSLURL::operator !=(const LLSLURL& rhs)
+// static
+bool LLSLURL::matchPrefix(const std::string& url, const std::string& prefix)
 {
-	return !(*this == rhs);
+	std::string test_prefix = url.substr(0, prefix.length());
+	LLStringUtil::toLower(test_prefix);
+	return test_prefix == prefix;
 }
 
-std::string LLSLURL::getLocationString() const
-{
-	return llformat("%s/%d/%d/%d",
-					mRegion.c_str(),
-					(int)llround(mPosition[0]),
-					(int)llround(mPosition[1]),
-					(int)llround(mPosition[2]));						 
-}
-std::string LLSLURL::asString() const
+void LLSLURL::globalPosToXYZ(const LLVector3d& pos, S32& x, S32& y, S32& z)
 {
-    std::ostringstream result;
-    result << "   mAppCmd:"  << getAppCmd() <<
-              "   mAppPath:" + getAppPath().asString() <<
-              "   mAppQueryMap:" + getAppQueryMap().asString() <<
-              "   mAppQuery: " + getAppQuery() <<
-              "   mGrid: " + getGrid() <<
-              "   mRegion: " + getRegion() <<
-              "   mPosition: "  <<
-              "   mType: " << mType <<
-              "   mPosition: " << mPosition;
-    return result.str();
+	x = llround((F32)fmod(pos.mdV[VX], (F64)REGION_WIDTH_METERS));
+	y = llround((F32)fmod(pos.mdV[VY], (F64)REGION_WIDTH_METERS));
+	z = llround((F32)pos.mdV[VZ]);
 }
-
diff --git a/indra/newview/llslurl.h b/indra/newview/llslurl.h
index 28c23561cf5dda643fb8544e6eae07cf899c13a3..a79a8fc97cac7efe6e1ac251fce73a14c809b1df 100644
--- a/indra/newview/llslurl.h
+++ b/indra/newview/llslurl.h
@@ -1,11 +1,10 @@
-/**
+/** 
  * @file llslurl.h
- * @brief Handles "SLURL fragments" like Ahern/123/45 for
- * startup processing, login screen, prefs, etc.
+ * @brief SLURL manipulation
  *
- * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
  * 
- * Copyright (c) 2006-2010, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
  * 
  * Second Life Viewer Source Code
  * The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +12,13 @@
  * ("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://secondlife.com/developers/opensource/gplv2
+ * 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://secondlife.com/developers/opensource/flossexception
+ * 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,
@@ -29,84 +29,85 @@
  * COMPLETENESS OR PERFORMANCE.
  * $/LicenseInfo$
  */
-#ifndef LLSLURL_H
-#define LLSLURL_H
 
-#include "llstring.h"
+#ifndef LL_SLURL_H
+#define LL_SLURL_H
 
+#include <string>
 
-// represents a location in a grid
+// IAN BUG: where should this live?
+// IAN BUG: are static utility functions right?  See LLUUID.
+// question of whether to have a LLSLURL object or a 
+// some of this was moved from LLURLDispatcher
 
+/**
+ * SLURL manipulation
+ */
 class LLSLURL
 {
 public:
-	static const char* SLURL_HTTPS_SCHEME;
-	static const char* SLURL_HTTP_SCHEME;
-	static const char* SLURL_SL_SCHEME;
-	static const char* SLURL_SECONDLIFE_SCHEME;
-	static const char* SLURL_SECONDLIFE_PATH;
-	static const char* SLURL_COM;
-	static const char* WWW_SLURL_COM;
-	static const char* MAPS_SECONDLIFE_COM;
-	static const char* SLURL_X_GRID_LOCATION_INFO_SCHEME;
-	static LLSLURL START_LOCATION;
-	static const char* SIM_LOCATION_HOME;
-	static const char* SIM_LOCATION_LAST;
-	static const char* SLURL_APP_PATH;
-	static const char* SLURL_REGION_PATH;	
-	
-	enum SLURL_TYPE { 
-		INVALID, 
-		LOCATION,
-		HOME_LOCATION,
-		LAST_LOCATION,
-		APP,
-		HELP 
-	};
-		
-	
-	LLSLURL(): mType(LAST_LOCATION)  { }
-	LLSLURL(const std::string& slurl);
-	LLSLURL(const std::string& grid, const std::string& region);
-	LLSLURL(const std::string& region, const LLVector3& position);
-	LLSLURL(const std::string& grid, const std::string& region, const LLVector3& position);
-	LLSLURL(const std::string& grid, const std::string& region, const LLVector3d& global_position);
-	LLSLURL(const std::string& region, const LLVector3d& global_position);
-	LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb);
-	
-	SLURL_TYPE getType() const { return mType; }
-	
-	std::string getSLURLString() const;
-	std::string getLoginString() const;
-	std::string getLocationString() const; 
-	std::string getGrid() const { return mGrid; }
-	std::string getRegion() const { return mRegion; }
-	LLVector3   getPosition() const { return mPosition; }
-	std::string getAppCmd() const { return mAppCmd; }
-	std::string getAppQuery() const { return mAppQuery; }
-	LLSD        getAppQueryMap() const { return mAppQueryMap; }
-	LLSD        getAppPath() const { return mAppPath; }
-	
-	bool        isValid() const { return mType != INVALID; }
-	bool        isSpatial() const { return (mType == LAST_LOCATION) || (mType == HOME_LOCATION) || (mType == LOCATION); }
-	
-	bool operator==(const LLSLURL& rhs);
-	bool operator!=(const LLSLURL&rhs);
-
-    std::string asString() const ;
-
-protected:
-	SLURL_TYPE mType;
-	
-	// used for Apps and Help
-	std::string mAppCmd;
-	LLSD        mAppPath;
-	LLSD        mAppQueryMap;
-	std::string mAppQuery;
-	
-	std::string mGrid;  // reference to grid manager grid
-	std::string mRegion;
-	LLVector3  mPosition;
+	static const std::string PREFIX_SL_HELP;
+	static const std::string PREFIX_SL;
+	static const std::string PREFIX_SECONDLIFE;
+	static const std::string PREFIX_SLURL;
+	static const std::string PREFIX_SLURL_OLD;
+	static const std::string PREFIX_SLURL_WWW;
+
+	static const std::string APP_TOKEN;
+
+	/**
+	 * Is this any sort of secondlife:// or sl:// URL?
+	 */
+	static bool isSLURL(const std::string& url);
+
+	/**
+	 * Returns true if url is proven valid by regexp check from LLUrlRegistry
+	 */
+	static bool isValidSLURL(const std::string& url);
+
+	/**
+	 * Is this a special secondlife://app/ URL?
+	 */
+	static bool isSLURLCommand(const std::string& url);
+
+	/**
+	 * Not sure what it is.
+	 */
+	static bool isSLURLHelp(const std::string& url);
+
+	/**
+	 * builds: http://slurl.com/secondlife/Region%20Name/x/y/z/ escaping result url.
+	 */
+	static std::string buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z);
+
+	/// Build a SLURL like secondlife:///app/agent/<uuid>/inspect
+	static std::string buildCommand(const char* noun, const LLUUID& id, const char* verb);
+
+	/**
+	 * builds: http://slurl.com/secondlife/Region Name/x/y/z/ without escaping result url.
+	 */
+	static std::string buildUnescapedSLURL(const std::string& regionname, S32 x, S32 y, S32 z);
+
+	/**
+	 * builds SLURL from global position. Returns escaped or unescaped url.
+	 * Returns escaped url by default.
+	 */
+	static std::string buildSLURLfromPosGlobal(const std::string& regionname,
+											   const LLVector3d& global_pos,
+											   bool escaped = true);
+	/**
+	 * Strip protocol part from the URL.
+	 */
+	static std::string stripProtocol(const std::string& url);
+
+	/**
+	 * Convert global position to X, Y Z
+	 */
+	static void globalPosToXYZ(const LLVector3d& pos, S32& x, S32& y, S32& z);
+
+private:
+	static bool matchPrefix(const std::string& url, const std::string& prefix);
+
 };
 
-#endif // LLSLURL_H
+#endif
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index d7de050636539819224de84e5dbceb4131675e3f..c5c311ed33cb678ce357ca9420da2d2ef92aab03 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -59,9 +59,9 @@ LLSpeakButton::Params::Params()
 
 void LLSpeakButton::draw()
 {
-	// LLVoiceClient::getInstance() is the authoritative global source of info regarding our open-mic state, we merely reflect that state.
-	bool openmic = LLVoiceClient::getInstance()->getUserPTTState();
-	bool voiceenabled = LLVoiceClient::getInstance()->voiceEnabled();
+	// gVoiceClient is the authoritative global source of info regarding our open-mic state, we merely reflect that state.
+	bool openmic = gVoiceClient->getUserPTTState();
+	bool voiceenabled = gVoiceClient->voiceEnabled();
 	mSpeakBtn->setToggleState(openmic && voiceenabled);
 	mOutputMonitor->setIsMuted(!voiceenabled);
 	LLUICtrl::draw();
@@ -176,11 +176,11 @@ void LLSpeakButton::setLabelVisible(bool visible)
 void LLSpeakButton::onMouseDown_SpeakBtn()
 {
 	bool down = true;
-	LLVoiceClient::getInstance()->inputUserControlState(down); // this method knows/care about whether this translates into a toggle-to-talk or down-to-talk
+	gVoiceClient->inputUserControlState(down); // this method knows/care about whether this translates into a toggle-to-talk or down-to-talk
 }
 void LLSpeakButton::onMouseUp_SpeakBtn()
 {
 	bool down = false;
-	LLVoiceClient::getInstance()->inputUserControlState(down);
+	gVoiceClient->inputUserControlState(down);
 }
 
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index b9534fac9a3187bf9bc53635e5f26881ca6e576c..4573520647b390b06c8c97f3f3de9dde2a00cf50 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -299,7 +299,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
 
 void LLSpeakerMgr::update(BOOL resort_ok)
 {
-	if (!LLVoiceClient::getInstance())
+	if (!gVoiceClient)
 	{
 		return;
 	}
@@ -313,7 +313,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
 	}
 
 	// update status of all current speakers
-	BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
+	BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
 	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
 	{
 		LLUUID speaker_id = speaker_it->first;
@@ -321,21 +321,21 @@ void LLSpeakerMgr::update(BOOL resort_ok)
 		
 		speaker_map_t::iterator  cur_speaker_it = speaker_it++;
 
-		if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
+		if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
 		{
-			speakerp->mSpeechVolume = LLVoiceClient::getInstance()->getCurrentPower(speaker_id);
-			BOOL moderator_muted_voice = LLVoiceClient::getInstance()->getIsModeratorMuted(speaker_id);
+			speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id);
+			BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id);
 			if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
 			{
 				speakerp->mModeratorMutedVoice = moderator_muted_voice;
 				speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
 			}
 
-			if (LLVoiceClient::getInstance()->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
+			if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
 			{
 				speakerp->mStatus = LLSpeaker::STATUS_MUTED;
 			}
-			else if (LLVoiceClient::getInstance()->getIsSpeaking(speaker_id))
+			else if (gVoiceClient->getIsSpeaking(speaker_id))
 			{
 				// reset inactivity expiration
 				if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
@@ -417,21 +417,19 @@ void LLSpeakerMgr::update(BOOL resort_ok)
 void LLSpeakerMgr::updateSpeakerList()
 {
 	// are we bound to the currently active voice channel?
-	if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
-	{
-	        std::set<LLUUID> participants;
-	        LLVoiceClient::getInstance()->getParticipantList(participants);
-		// add new participants to our list of known speakers
-		for (std::set<LLUUID>::iterator participant_it = participants.begin();
-			 participant_it != participants.end(); 
-			 ++participant_it)
+	if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
+	{
+		LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList();
+		if(participants)
 		{
-				setSpeaker(*participant_it, 
-						   LLVoiceClient::getInstance()->getDisplayName(*participant_it),
-						   LLSpeaker::STATUS_VOICE_ACTIVE, 
-						   (LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
-
+			LLVoiceClient::participantMap::iterator participant_it;
 
+			// add new participants to our list of known speakers
+			for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it)
+			{
+				LLVoiceClient::participantState* participantp = participant_it->second;
+				setSpeaker(participantp->mAvatarID, participantp->mDisplayName, LLSpeaker::STATUS_VOICE_ACTIVE, (participantp->isAvatar()?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
+			}
 		}
 	}
 }
@@ -521,7 +519,7 @@ void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
 BOOL LLSpeakerMgr::isVoiceActive()
 {
 	// mVoiceChannel = NULL means current voice channel, whatever it is
-	return LLVoiceClient::getInstance()->voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
+	return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
 }
 
 
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index 29237946d2b7dc63525f1a2dd2664b7d26764e3c..cc06179481696c0afb0d36aa4eb24e0aad6a23f4 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -158,7 +158,7 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i
 	mSpeakingIndicators.insert(value_type);
 
 	speaker_ids_t speakers_uuids;
-	BOOL is_in_same_voice = LLVoiceClient::getInstance()->isParticipant(speaker_id);
+	BOOL is_in_same_voice = LLVoiceClient::getInstance()->findParticipantByID(speaker_id) != NULL;
 
 	speakers_uuids.insert(speaker_id);
 	switchSpeakerIndicators(speakers_uuids, is_in_same_voice);
@@ -210,7 +210,7 @@ void SpeakingIndicatorManager::onChange()
 	LL_DEBUGS("SpeakingIndicator") << "Voice participant list was changed, updating indicators" << LL_ENDL;
 
 	speaker_ids_t speakers_uuids;
-	LLVoiceClient::getInstance()->getParticipantList(speakers_uuids);
+	LLVoiceClient::getInstance()->getParticipantsUUIDSet(speakers_uuids);
 
 	LL_DEBUGS("SpeakingIndicator") << "Switching all OFF, count: " << mSwitchedIndicatorsOn.size() << LL_ENDL;
 	// switch all indicators off
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 4f1bcde302df3b3b3c53458121fcb11e49c2b869..b5a73a3143fab6d8d1c380fcf2a329c8fab131a8 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -147,7 +147,7 @@
 #include "lltrans.h"
 #include "llui.h"
 #include "llurldispatcher.h"
-#include "llslurl.h"
+#include "llurlsimstring.h"
 #include "llurlhistory.h"
 #include "llurlwhitelist.h"
 #include "llvieweraudio.h"
@@ -192,7 +192,6 @@
 #include "llinventorybridge.h"
 #include "llappearancemgr.h"
 #include "llavatariconctrl.h"
-#include "llvoicechannel.h"
 
 #include "lllogin.h"
 #include "llevents.h"
@@ -229,11 +228,11 @@ static std::string sInitialOutfitGender;	// "male" or "female"
 static bool gUseCircuitCallbackCalled = false;
 
 EStartupState LLStartUp::gStartupState = STATE_FIRST;
-LLSLURL LLStartUp::sStartSLURL;
 
-static LLPointer<LLCredential> gUserCredential;
-static std::string gDisplayName;
-static BOOL gRememberPassword = TRUE;     
+// *NOTE:Mani - to reconcile with giab changes...
+static std::string gFirstname;
+static std::string gLastname;
+static std::string gPassword;
 
 static U64 gFirstSimHandle = 0;
 static LLHost gFirstSim;
@@ -250,6 +249,7 @@ boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener(
 
 void login_show();
 void login_callback(S32 option, void* userdata);
+bool is_hex_string(U8* str, S32 len);
 void show_first_run_dialog();
 bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
 void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
@@ -262,9 +262,6 @@ bool callback_choose_gender(const LLSD& notification, const LLSD& response);
 void init_start_screen(S32 location_id);
 void release_start_screen();
 void reset_login();
-LLSD transform_cert_args(LLPointer<LLCertificate> cert);
-void general_cert_done(const LLSD& notification, const LLSD& response);
-void trust_cert_done(const LLSD& notification, const LLSD& response);
 void apply_udp_blacklist(const std::string& csv);
 bool process_login_success_response();
 void transition_back_to_login_panel(const std::string& emsg);
@@ -367,7 +364,7 @@ bool idle_startup()
 
 	if ( STATE_FIRST == LLStartUp::getStartupState() )
 	{
-		gViewerWindow->showCursor(); 
+		gViewerWindow->showCursor();
 		gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
 
 		/////////////////////////////////////////////////
@@ -665,25 +662,69 @@ bool idle_startup()
 		//
 		// Log on to system
 		//
-		if (gUserCredential.isNull())
-		{
-			gUserCredential = gLoginHandler.initializeLoginInfo();
-		}
-		if (gUserCredential.isNull())
-		{
-			show_connect_box = TRUE;
-		}
-		else if (gSavedSettings.getBOOL("AutoLogin"))  
-		{
-			gRememberPassword = TRUE;
-			gSavedSettings.setBOOL("RememberPassword", TRUE);                                                      
-			show_connect_box = false;    			
+		if (!LLStartUp::sSLURLCommand.empty())
+		{
+			// this might be a secondlife:///app/login URL
+			gLoginHandler.parseDirectLogin(LLStartUp::sSLURLCommand);
+		}
+		if (!gLoginHandler.getFirstName().empty()
+			|| !gLoginHandler.getLastName().empty()
+			/*|| !gLoginHandler.getWebLoginKey().isNull()*/ )
+		{
+			// We have at least some login information on a SLURL
+			gFirstname = gLoginHandler.getFirstName();
+			gLastname = gLoginHandler.getLastName();
+			LL_DEBUGS("LLStartup") << "STATE_FIRST: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+
+			// Show the login screen if we don't have everything
+			show_connect_box = 
+				gFirstname.empty() || gLastname.empty();
+		}
+        else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
+        {
+            LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
+			gFirstname = cmd_line_login[0].asString();
+			gLastname = cmd_line_login[1].asString();
+			LL_DEBUGS("LLStartup") << "Setting gFirstname, gLastname from gSavedSettings(\"UserLoginInfo\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+
+			LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str());
+			char md5pass[33];               /* Flawfinder: ignore */
+			pass.hex_digest(md5pass);
+			gPassword = md5pass;
+			
+#ifdef USE_VIEWER_AUTH
+			show_connect_box = true;
+#else
+			show_connect_box = false;
+#endif
+			gSavedSettings.setBOOL("AutoLogin", TRUE);
+        }
+		else if (gSavedSettings.getBOOL("AutoLogin"))
+		{
+			gFirstname = gSavedSettings.getString("FirstName");
+			gLastname = gSavedSettings.getString("LastName");
+			LL_DEBUGS("LLStartup") << "AutoLogin: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+			gPassword = LLStartUp::loadPasswordFromDisk();
+			gSavedSettings.setBOOL("RememberPassword", TRUE);
+			
+#ifdef USE_VIEWER_AUTH
+			show_connect_box = true;
+#else
+			show_connect_box = false;
+#endif
 		}
-		else 
+		else
 		{
-			gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
-			show_connect_box = TRUE;
+			// if not automatically logging in, display login dialog
+			// a valid grid is selected
+			gFirstname = gSavedSettings.getString("FirstName");
+			gLastname = gSavedSettings.getString("LastName");
+			LL_DEBUGS("LLStartup") << "normal login: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+			gPassword = LLStartUp::loadPasswordFromDisk();
+			show_connect_box = true;
 		}
+
+
 		// Go to the next startup state
 		LLStartUp::setStartupState( STATE_BROWSER_INIT );
 		return FALSE;
@@ -715,10 +756,8 @@ bool idle_startup()
 			// Load all the name information out of the login view
 			// NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't
 			// show the login view until login_show() is called below.  
-			if (gUserCredential.isNull())                                                                          
-			{                                                                                                      
-				gUserCredential = gLoginHandler.initializeLoginInfo();                 
-			}     
+			// LLPanelLogin::getFields(gFirstname, gLastname, gPassword);
+
 			if (gNoRender)
 			{
 				LL_ERRS("AppInit") << "Need to autologin or use command line with norender!" << LL_ENDL;
@@ -729,10 +768,8 @@ bool idle_startup()
 			// Show the login dialog
 			login_show();
 			// connect dialog is already shown, so fill in the names
-			if (gUserCredential.notNull())                                                                         
-			{                                                                                                      
-				LLPanelLogin::setFields( gUserCredential, gRememberPassword);                                  
-			}     
+			LLPanelLogin::setFields( gFirstname, gLastname, gPassword);
+
 			LLPanelLogin::giveFocus();
 
 			gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
@@ -802,36 +839,39 @@ bool idle_startup()
 		// DEV-42215: Make sure they're not empty -- gFirstname and gLastname
 		// might already have been set from gSavedSettings, and it's too bad
 		// to overwrite valid values with empty strings.
+		if (! gLoginHandler.getFirstName().empty() && ! gLoginHandler.getLastName().empty())
+		{
+			gFirstname = gLoginHandler.getFirstName();
+			gLastname = gLoginHandler.getLastName();
+			LL_DEBUGS("LLStartup") << "STATE_LOGIN_CLEANUP: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+		}
 
 		if (show_connect_box)
 		{
 			// TODO if not use viewer auth
 			// Load all the name information out of the login view
-			LLPanelLogin::getFields(gUserCredential, gRememberPassword); 
+			LLPanelLogin::getFields(&gFirstname, &gLastname, &gPassword);
 			// end TODO
 	 
 			// HACK: Try to make not jump on login
 			gKeyboard->resetKeys();
 		}
 
-		// save the credentials                                                                                        
-		std::string userid = "unknown";                                                                                
-		if(gUserCredential.notNull())                                                                                  
-		{  
-			userid = gUserCredential->userID();                                                                    
-			gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);  
+		if (!gFirstname.empty() && !gLastname.empty())
+		{
+			gSavedSettings.setString("FirstName", gFirstname);
+			gSavedSettings.setString("LastName", gLastname);
+
+			LL_INFOS("AppInit") << "Attempting login as: " << gFirstname << " " << gLastname << LL_ENDL;
+			gDebugInfo["LoginName"] = gFirstname + " " + gLastname;	
 		}
-		gSavedSettings.setBOOL("RememberPassword", gRememberPassword);                                                 
-		LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;                                           
-		gDebugInfo["LoginName"] = userid;                                                                              
-         
+
 		// create necessary directories
 		// *FIX: these mkdir's should error check
-		gDirUtilp->setLindenUserDir(userid);
+		gDirUtilp->setLindenUserDir(gFirstname, gLastname);
 		LLFile::mkdir(gDirUtilp->getLindenUserDir());
-
+		
 		// Set PerAccountSettingsFile to the default value.
-		std::string per_account_settings_file = LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount");
 		gSavedSettings.setString("PerAccountSettingsFile",
 			gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, 
 				LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")));
@@ -861,8 +901,9 @@ bool idle_startup()
 		{
 			gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));		
 		}
-		gDirUtilp->setPerAccountChatLogsDir(userid);  
 		
+		gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname);
+
 		LLFile::mkdir(gDirUtilp->getChatLogsDir());
 		LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
 
@@ -883,7 +924,11 @@ bool idle_startup()
 
 		if (show_connect_box)
 		{
-			LLSLURL slurl;
+			std::string location;
+			LLPanelLogin::getLocation( location );
+			LLURLSimString::setString( location );
+
+			// END TODO
 			LLPanelLogin::closePanel();
 		}
 
@@ -907,21 +952,26 @@ bool idle_startup()
 		// their last location, or some URL "-url //sim/x/y[/z]"
 		// All accounts have both a home and a last location, and we don't support
 		// more locations than that.  Choose the appropriate one.  JC
-		switch (LLStartUp::getStartSLURL().getType())
-		  {
-		  case LLSLURL::LOCATION:
-		    agent_location_id = START_LOCATION_ID_URL;
-		    location_which = START_LOCATION_ID_LAST;
-		    break;
-		  case LLSLURL::LAST_LOCATION:
-		    agent_location_id = START_LOCATION_ID_LAST;
-		    location_which = START_LOCATION_ID_LAST;
-		    break;
-		  default:
-		    agent_location_id = START_LOCATION_ID_HOME;
-		    location_which = START_LOCATION_ID_HOME;
-		    break;
-		  }
+		if (LLURLSimString::parse())
+		{
+			// a startup URL was specified
+			agent_location_id = START_LOCATION_ID_URL;
+
+			// doesn't really matter what location_which is, since
+			// gAgentStartLookAt will be overwritten when the
+			// UserLoginLocationReply arrives
+			location_which = START_LOCATION_ID_LAST;
+		}
+		else if (gSavedSettings.getString("LoginLocation") == "last" )
+		{
+			agent_location_id = START_LOCATION_ID_LAST;	// last location
+			location_which = START_LOCATION_ID_LAST;
+		}
+		else
+		{
+			agent_location_id = START_LOCATION_ID_HOME;	// home
+			location_which = START_LOCATION_ID_HOME;
+		}
 
 		gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
 
@@ -948,7 +998,7 @@ bool idle_startup()
 
 	if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
 	{
-		gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
+		gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel();
 
 		// Update progress status and the display loop.
 		auth_desc = LLTrans::getString("LoginInProgress");
@@ -972,7 +1022,11 @@ bool idle_startup()
 
 		// This call to LLLoginInstance::connect() starts the 
 		// authentication process.
-		login->connect(gUserCredential);
+		LLSD credentials;
+		credentials["first"] = gFirstname;
+		credentials["last"] = gLastname;
+		credentials["passwd"] = gPassword;
+		login->connect(credentials);
 
 		LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
 		return FALSE;
@@ -997,11 +1051,10 @@ bool idle_startup()
 		{
 			LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
 			                      << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
-			LLSD response = LLLoginInstance::getInstance()->getResponse();
 			// Still have error conditions that may need some 
 			// sort of handling.
-			std::string reason_response = response["reason"];
-			std::string message_response = response["message"];
+			std::string reason_response = LLLoginInstance::getInstance()->getResponse("reason");
+			std::string message_response = LLLoginInstance::getInstance()->getResponse("message");
 	
 			if(!message_response.empty())
 			{
@@ -1021,8 +1074,8 @@ bool idle_startup()
 			if(reason_response == "key")
 			{
 				// Couldn't login because user/password is wrong
-				// Clear the credential
-				gUserCredential->clearAuthenticator();
+				// Clear the password
+				gPassword = "";
 			}
 
 			if(reason_response == "update" 
@@ -1035,65 +1088,18 @@ bool idle_startup()
 				LLLoginInstance::getInstance()->disconnect();
 				LLAppViewer::instance()->forceQuit();
 			}
-			else 
+			else
 			{
-				if (reason_response != "tos") 
+				// Don't pop up a notification in the TOS case because
+				// LLFloaterTOS::onCancel() already scolded the user.
+				if (reason_response != "tos")
 				{
-					// Don't pop up a notification in the TOS case because
-					// LLFloaterTOS::onCancel() already scolded the user.
-					std::string error_code;
-					if(response.has("errorcode"))
-					{
-						error_code = response["errorcode"].asString();
-					}
-					if ((reason_response == "CURLError") && 
-						(error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") && 
-						response.has("certificate"))
-					{
-						// This was a certificate error, so grab the certificate
-						// and throw up the appropriate dialog.
-						LLPointer<LLCertificate> certificate = gSecAPIHandler->getCertificate(response["certificate"]);
-						if(certificate)
-						{
-							LLSD args = transform_cert_args(certificate);
-
-							if(error_code == "SSL_CACERT")
-							{
-								// if we are handling an untrusted CA, throw up the dialog                             
-								// with the 'trust this CA' button.                                                    
-								LLNotificationsUtil::add("TrustCertificateError", args, response,
-														trust_cert_done);
-								
-								show_connect_box = true;
-							}
-							else
-							{
-								// the certificate exception returns a unique string for each type of exception.       
-								// we grab this string via the LLUserAuth object, and use that to grab the localized   
-								// string.                                                                             
-								args["REASON"] = LLTrans::getString(message_response);
-								
-								LLNotificationsUtil::add("GeneralCertificateError", args, response,
-														 general_cert_done);
-								
-								reset_login();
-								gSavedSettings.setBOOL("AutoLogin", FALSE);
-								show_connect_box = true;
-								
-							}
-
-						}
-					}
-					else 
-					{
-						// This wasn't a certificate error, so throw up the normal
-						// notificatioin message.
-						LLSD args;
-						args["ERROR_MESSAGE"] = emsg.str();
-						LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
-						LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
-					}
+					LLSD args;
+					args["ERROR_MESSAGE"] = emsg.str();
+					LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+					LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
 				}
+
 				//setup map of datetime strings to codes and slt & local time offset from utc
 				// *TODO: Does this need to be here?
 				LLStringOps::setupDatetimeInfo (false);
@@ -1106,12 +1112,7 @@ bool idle_startup()
 			if(process_login_success_response())
 			{
 				// Pass the user information to the voice chat server interface.
-				LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID);
-				// create the default proximal channel
-				LLVoiceChannel::initClass();
-				// update the voice settings
-				LLVoiceClient::getInstance()->updateSettings();
-				LLGridManager::getInstance()->setFavorite(); 
+				gVoiceClient->userAuthorized(gFirstname, gLastname, gAgentID);
 				LLStartUp::setStartupState( STATE_WORLD_INIT);
 			}
 			else
@@ -1122,7 +1123,6 @@ bool idle_startup()
 				LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
 				transition_back_to_login_panel(emsg.str());
 				show_connect_box = true;
-				return FALSE;
 			}
 		}
 		return FALSE;
@@ -1807,12 +1807,9 @@ bool idle_startup()
 		// thus, do not show this alert.
 		if (!gAgent.isFirstLogin())
 		{
-			llinfos << "gAgentStartLocation : " << gAgentStartLocation << llendl;
-			LLSLURL start_slurl = LLStartUp::getStartSLURL();
-			
-			if (((start_slurl.getType() == LLSLURL::LOCATION) && (gAgentStartLocation == "url")) ||
-				((start_slurl.getType() == LLSLURL::LAST_LOCATION) && (gAgentStartLocation == "last")) ||
-				((start_slurl.getType() == LLSLURL::HOME_LOCATION) && (gAgentStartLocation == "home")))
+			bool url_ok = LLURLSimString::sInstance.parse();
+			if ((url_ok && gAgentStartLocation == "url") ||
+				(!url_ok && ((gAgentStartLocation == gSavedSettings.getString("LoginLocation")))))
 			{
 				// Start location is OK
 				// Disabled code to restore camera location and focus if logging in to default location
@@ -1834,23 +1831,17 @@ bool idle_startup()
 			else
 			{
 				std::string msg;
-				switch(start_slurl.getType())
+				if (url_ok)
 				{
-					case LLSLURL::LOCATION:
-					{
-						
-						msg = "AvatarMovedDesired";
-						break;
-					}
-					case LLSLURL::HOME_LOCATION:
-					{
-						msg = "AvatarMovedHome";
-						break;
-					}
-					default:
-					{
-						msg = "AvatarMovedLast";
-					}
+					msg = "AvatarMovedDesired";
+				}
+				else if (gSavedSettings.getString("LoginLocation") == "home")
+				{
+					msg = "AvatarMovedHome";
+				}
+				else
+				{
+					msg = "AvatarMovedLast";
 				}
 				LLNotificationsUtil::add(msg);
 			}
@@ -2066,9 +2057,20 @@ void login_show()
 #endif
 
 	LLPanelLogin::show(	gViewerWindow->getWindowRectScaled(),
-						bUseDebugLogin || gSavedSettings.getBOOL("SecondLifeEnterprise"),
+						bUseDebugLogin,
 						login_callback, NULL );
 
+	// UI textures have been previously loaded in doPreloadImages()
+	
+	LL_DEBUGS("AppInit") << "Setting Servers" << LL_ENDL;
+
+	LLPanelLogin::addServer(LLViewerLogin::getInstance()->getGridLabel(), LLViewerLogin::getInstance()->getGridChoice());
+
+	LLViewerLogin* vl = LLViewerLogin::getInstance();
+	for(int grid_index = GRID_INFO_ADITI; grid_index < GRID_INFO_OTHER; ++grid_index)
+	{
+		LLPanelLogin::addServer(vl->getKnownGridLabel((EGridInfo)grid_index), grid_index);
+	}
 }
 
 // Callback for when login screen is closed.  Option 0 = connect, option 1 = quit.
@@ -2084,6 +2086,9 @@ void login_callback(S32 option, void *userdata)
 	}
 	else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION
 	{
+		// Make sure we don't save the password if the user is trying to clear it.
+		std::string first, last, password;
+		LLPanelLogin::getFields(&first, &last, &password);
 		if (!gSavedSettings.getBOOL("RememberPassword"))
 		{
 			// turn off the setting and write out to disk
@@ -2106,6 +2111,142 @@ void login_callback(S32 option, void *userdata)
 	}
 }
 
+
+// static
+std::string LLStartUp::loadPasswordFromDisk()
+{
+	// Only load password if we also intend to save it (otherwise the user
+	// wonders what we're doing behind his back).  JC
+	BOOL remember_password = gSavedSettings.getBOOL("RememberPassword");
+	if (!remember_password)
+	{
+		return std::string("");
+	}
+
+	std::string hashed_password("");
+
+	// Look for legacy "marker" password from settings.ini
+	hashed_password = gSavedSettings.getString("Marker");
+	if (!hashed_password.empty())
+	{
+		// Stomp the Marker entry.
+		gSavedSettings.setString("Marker", "");
+
+		// Return that password.
+		return hashed_password;
+	}
+
+	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+													   "password.dat");
+	LLFILE* fp = LLFile::fopen(filepath, "rb");		/* Flawfinder: ignore */
+	if (!fp)
+	{
+		return hashed_password;
+	}
+
+	// UUID is 16 bytes, written into ASCII is 32 characters
+	// without trailing \0
+	const S32 HASHED_LENGTH = 32;
+	U8 buffer[HASHED_LENGTH+1];
+
+	if (1 != fread(buffer, HASHED_LENGTH, 1, fp))
+	{
+		return hashed_password;
+	}
+
+	fclose(fp);
+
+	// Decipher with MAC address
+	LLXORCipher cipher(gMACAddress, 6);
+	cipher.decrypt(buffer, HASHED_LENGTH);
+
+	buffer[HASHED_LENGTH] = '\0';
+
+	// Check to see if the mac address generated a bad hashed
+	// password. It should be a hex-string or else the mac adress has
+	// changed. This is a security feature to make sure that if you
+	// get someone's password.dat file, you cannot hack their account.
+	if(is_hex_string(buffer, HASHED_LENGTH))
+	{
+		hashed_password.assign((char*)buffer);
+	}
+
+	return hashed_password;
+}
+
+
+// static
+void LLStartUp::savePasswordToDisk(const std::string& hashed_password)
+{
+	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+													   "password.dat");
+	LLFILE* fp = LLFile::fopen(filepath, "wb");		/* Flawfinder: ignore */
+	if (!fp)
+	{
+		return;
+	}
+
+	// Encipher with MAC address
+	const S32 HASHED_LENGTH = 32;
+	U8 buffer[HASHED_LENGTH+1];
+
+	LLStringUtil::copy((char*)buffer, hashed_password.c_str(), HASHED_LENGTH+1);
+
+	LLXORCipher cipher(gMACAddress, 6);
+	cipher.encrypt(buffer, HASHED_LENGTH);
+
+	if (fwrite(buffer, HASHED_LENGTH, 1, fp) != 1)
+	{
+		LL_WARNS("AppInit") << "Short write" << LL_ENDL;
+	}
+
+	fclose(fp);
+}
+
+
+// static
+void LLStartUp::deletePasswordFromDisk()
+{
+	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+														  "password.dat");
+	LLFile::remove(filepath);
+}
+
+
+bool is_hex_string(U8* str, S32 len)
+{
+	bool rv = true;
+	U8* c = str;
+	while(rv && len--)
+	{
+		switch(*c)
+		{
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+			++c;
+			break;
+		default:
+			rv = false;
+			break;
+		}
+	}
+	return rv;
+}
+
 void show_first_run_dialog()
 {
 	LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);
@@ -2147,7 +2288,7 @@ bool login_alert_status(const LLSD& notification, const LLSD& response)
       //      break;
         case 2:     // Teleport
             // Restart the login process, starting at our home locaton
-	  LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
+            LLURLSimString::setString("home");
             LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
             break;
         default:
@@ -2367,35 +2508,30 @@ void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S3
 const std::string COMMON_GESTURES_FOLDER = "Common Gestures";
 const std::string MALE_GESTURES_FOLDER = "Male Gestures";
 const std::string FEMALE_GESTURES_FOLDER = "Female Gestures";
+const std::string MALE_OUTFIT_FOLDER = "Male Shape & Outfit";
+const std::string FEMALE_OUTFIT_FOLDER = "Female Shape & Outfit";
 const S32 OPT_CLOSED_WINDOW = -1;
 const S32 OPT_MALE = 0;
 const S32 OPT_FEMALE = 1;
-const S32 OPT_TRUST_CERT = 0;
-const S32 OPT_CANCEL_TRUST = 1;
-	
+
 bool callback_choose_gender(const LLSD& notification, const LLSD& response)
-{
-	
-    // These defaults are returned from the server on login.  They are set in login.xml.                  
-    // If no default is returned from the server, they are retrieved from settings.xml.                   
-	
-	S32 option = LLNotification::getSelectedOption(notification, response);
+{	
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	switch(option)
 	{
-		case OPT_MALE:
-			LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" );
-			break;
-			
-        case OPT_FEMALE:
-        case OPT_CLOSED_WINDOW:
-        default:
-			LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" );
-			break;
+	case OPT_MALE:
+		LLStartUp::loadInitialOutfit( MALE_OUTFIT_FOLDER, "male" );
+		break;
+
+	case OPT_FEMALE:
+	case OPT_CLOSED_WINDOW:
+	default:
+		LLStartUp::loadInitialOutfit( FEMALE_OUTFIT_FOLDER, "female" );
+		break;
 	}
 	return false;
 }
 
-
 void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 								   const std::string& gender_name )
 {
@@ -2610,6 +2746,7 @@ void reset_login()
 
 //---------------------------------------------------------------------------
 
+std::string LLStartUp::sSLURLCommand;
 
 bool LLStartUp::canGoFullscreen()
 {
@@ -2642,145 +2779,41 @@ void LLStartUp::fontInit()
 bool LLStartUp::dispatchURL()
 {
 	// ok, if we've gotten this far and have a startup URL
-        if (!getStartSLURL().isValid())
+	if (!sSLURLCommand.empty())
 	{
-	  return false;
+		LLMediaCtrl* web = NULL;
+		const bool trusted_browser = false;
+		LLURLDispatcher::dispatch(sSLURLCommand, web, trusted_browser);
 	}
-        if(getStartSLURL().getType() != LLSLURL::APP)
-	  {
-	    
+	else if (LLURLSimString::parse())
+	{
 		// If we started with a location, but we're already
 		// at that location, don't pop dialogs open.
 		LLVector3 pos = gAgent.getPositionAgent();
-		LLVector3 slurlpos = getStartSLURL().getPosition();
-		F32 dx = pos.mV[VX] - slurlpos.mV[VX];
-		F32 dy = pos.mV[VY] - slurlpos.mV[VY];
+		F32 dx = pos.mV[VX] - (F32)LLURLSimString::sInstance.mX;
+		F32 dy = pos.mV[VY] - (F32)LLURLSimString::sInstance.mY;
 		const F32 SLOP = 2.f;	// meters
 
-		if( getStartSLURL().getRegion() != gAgent.getRegion()->getName()
+		if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName()
 			|| (dx*dx > SLOP*SLOP)
 			|| (dy*dy > SLOP*SLOP) )
 		{
-			LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), 
-						  NULL, false);
+			std::string url = LLURLSimString::getURL();
+			LLMediaCtrl* web = NULL;
+			const bool trusted_browser = false;
+			LLURLDispatcher::dispatch(url, web, trusted_browser);
 		}
 		return true;
 	}
 	return false;
 }
 
-void LLStartUp::setStartSLURL(const LLSLURL& slurl) 
-{
-  sStartSLURL = slurl;
-  switch(slurl.getType())
-    {
-    case LLSLURL::HOME_LOCATION:
-      {
-		  gSavedSettings.setString("LoginLocation", LLSLURL::SIM_LOCATION_HOME);
-	break;
-      }
-    case LLSLURL::LAST_LOCATION:
-      {
-	gSavedSettings.setString("LoginLocation", LLSLURL::SIM_LOCATION_LAST);
-	break;
-      }
-    default:
-			LLGridManager::getInstance()->setGridChoice(slurl.getGrid());
-			break;
-    }
-}
-
 bool login_alert_done(const LLSD& notification, const LLSD& response)
 {
 	LLPanelLogin::giveFocus();
 	return false;
 }
 
-// parse the certificate information into args for the 
-// certificate notifications
-LLSD transform_cert_args(LLPointer<LLCertificate> cert)
-{
-	LLSD args = LLSD::emptyMap();
-	std::string value;
-	LLSD cert_info = cert->getLLSD();
-	// convert all of the elements in the cert into                                        
-	// args for the xml dialog, so we have flexability to                                  
-	// display various parts of the cert by only modifying                                 
-	// the cert alert dialog xml.                                                          
-	for(LLSD::map_iterator iter = cert_info.beginMap();
-		iter != cert_info.endMap();
-		iter++)
-	{
-		// key usage and extended key usage                                            
-		// are actually arrays, and we want to format them as comma separated          
-		// strings, so special case those.                                             
-		LLSDSerialize::toXML(cert_info[iter->first], std::cout);
-		if((iter->first== std::string(CERT_KEY_USAGE)) |
-		   (iter->first == std::string(CERT_EXTENDED_KEY_USAGE)))
-		{
-			value = "";
-			LLSD usage = cert_info[iter->first];
-			for (LLSD::array_iterator usage_iter = usage.beginArray();
-				 usage_iter != usage.endArray();
-				 usage_iter++)
-			{
-				
-				if(usage_iter != usage.beginArray())
-				{
-					value += ", ";
-				}
-				
-				value += (*usage_iter).asString();
-			}
-			
-		}
-		else
-		{
-			value = iter->second.asString();
-		}
-		
-		std::string name = iter->first;
-		std::transform(name.begin(), name.end(), name.begin(),
-					   (int(*)(int))toupper);
-		args[name.c_str()] = value;
-	}
-	return args;
-}
-
-
-// when we handle a cert error, give focus back to the login panel
-void general_cert_done(const LLSD& notification, const LLSD& response)
-{
-	LLStartUp::setStartupState( STATE_LOGIN_SHOW );			
-	LLPanelLogin::giveFocus();
-}
-
-// check to see if the user wants to trust the cert.
-// if they do, add it to the cert store and 
-void trust_cert_done(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotification::getSelectedOption(notification, response);	
-	switch(option)
-	{
-		case OPT_TRUST_CERT:
-		{
-			LLPointer<LLCertificate> cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]);
-			LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore"));			
-			store->add(cert);
-			store->save();
-			LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );	
-			break;
-		}
-		case OPT_CANCEL_TRUST:
-			reset_login();
-			gSavedSettings.setBOOL("AutoLogin", FALSE);			
-			LLStartUp::setStartupState( STATE_LOGIN_SHOW );				
-		default:
-			LLPanelLogin::giveFocus();
-			break;
-	}
-
-}
 
 void apply_udp_blacklist(const std::string& csv)
 {
@@ -2828,45 +2861,33 @@ bool process_login_success_response()
 	text = response["secure_session_id"].asString();
 	if(!text.empty()) gAgent.mSecureSessionID.set(text);
 
-	// if the response contains a display name, use that,
-	// otherwise if the response contains a first and/or last name,
-	// use those.  Otherwise use the credential identifier
-
-	gDisplayName = "";
-	if (response.has("display_name"))
+	text = response["first_name"].asString();
+	if(!text.empty()) 
 	{
-		gDisplayName.assign(response["display_name"].asString());
-		if(!gDisplayName.empty())
-		{
-			// Remove quotes from string.  Login.cgi sends these to force
-			// names that look like numbers into strings.
-			LLStringUtil::replaceChar(gDisplayName, '"', ' ');
-			LLStringUtil::trim(gDisplayName);
-		}
+		// Remove quotes from string.  Login.cgi sends these to force
+		// names that look like numbers into strings.
+		gFirstname.assign(text);
+		LLStringUtil::replaceChar(gFirstname, '"', ' ');
+		LLStringUtil::trim(gFirstname);
 	}
-	if(gDisplayName.empty())
+	text = response["last_name"].asString();
+	if(!text.empty()) 
 	{
-		if(response.has("first_name"))
-		{
-			gDisplayName.assign(response["first_name"].asString());
-			LLStringUtil::replaceChar(gDisplayName, '"', ' ');
-			LLStringUtil::trim(gDisplayName);
-		}
-		if(response.has("last_name"))
-		{
-			text.assign(response["last_name"].asString());
-			LLStringUtil::replaceChar(text, '"', ' ');
-			LLStringUtil::trim(text);
-			if(!gDisplayName.empty())
-			{
-				gDisplayName += " ";
-			}
-			gDisplayName += text;
-		}
+		gLastname.assign(text);
 	}
-	if(gDisplayName.empty())
+	gSavedSettings.setString("FirstName", gFirstname);
+	gSavedSettings.setString("LastName", gLastname);
+
+	if (gSavedSettings.getBOOL("RememberPassword"))
 	{
-		gDisplayName.assign(gUserCredential->asString());
+		// Successful login means the password is valid, so save it.
+		LLStartUp::savePasswordToDisk(gPassword);
+	}
+	else
+	{
+		// Don't leave password from previous session sitting around
+		// during this login session.
+		LLStartUp::deletePasswordFromDisk();
 	}
 
 	// this is their actual ability to access content
@@ -2960,7 +2981,7 @@ bool process_login_success_response()
 		// replace the default help URL format
 		gSavedSettings.setString("HelpURLFormat",text);
 		
-		// don't fall back to Standalone's pre-connection static help
+		// don't fall back to Nebraska's pre-connection static help
 		gSavedSettings.setBOOL("HelpUseLocal", false);
 	}
 			
@@ -3022,44 +3043,7 @@ bool process_login_success_response()
 		//setup map of datetime strings to codes and slt & local time offset from utc
 		LLStringOps::setupDatetimeInfo(pacific_daylight_time);
 	}
-	
-	static const char* CONFIG_OPTIONS[] = {"voice-config", "newuser-config"};
-	for (int i = 0; i < sizeof(CONFIG_OPTIONS)/sizeof(CONFIG_OPTIONS[0]); i++)
-	{
-		LLSD options = response[CONFIG_OPTIONS[i]];
-		if (!options.isArray() && (options.size() < 1) && !options[0].isMap())
-		{
-			continue;
-		}
-		llinfos << "config option " << CONFIG_OPTIONS[i][0] << "response " << options << llendl;
-		for(LLSD::map_iterator option_it = options[0].beginMap();
-			option_it != options[0].endMap();
-			option_it++)
-		{
-			llinfos << "trying option " << option_it->first << llendl;
-			LLPointer<LLControlVariable> control = gSavedSettings.getControl(option_it->first);
-			if(control.notNull())
-			{
-				if(control->isType(TYPE_BOOLEAN))
-				{
-					llinfos << "Setting BOOL from login " << option_it->first << " " << option_it->second << llendl;
-					
-					gSavedSettings.setBOOL(option_it->first, !((option_it->second == "F") ||
-															   (option_it->second == "false") ||
-															   (!option_it->second)));
-				}
-				else if (control->isType(TYPE_STRING))
-				{
-					llinfos << "Setting String from login " << option_it->first << " " << option_it->second << llendl;
-					gSavedSettings.setString(option_it->first, option_it->second);
-				}
-				// we don't support other types now                                                                                                            
-				
-			}
-			
-		}
-	}
-	
+
 	LLSD initial_outfit = response["initial-outfit"][0];
 	if(initial_outfit.size())
 	{
@@ -3113,7 +3097,7 @@ bool process_login_success_response()
 
 	bool success = false;
 	// JC: gesture loading done below, when we have an asset system
-	// in place.  Don't delete/clear gUserCredentials until then.
+	// in place.  Don't delete/clear user_credentials until then.
 	if(gAgentID.notNull()
 	   && gAgentSessionID.notNull()
 	   && gMessageSystem->mOurCircuitCode
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index 16cc74504f2a209c5dfb1a5f87730d614468a57b..92fe9521d3eb31b3ca8f2f99e618bc34a5e1c3ad 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -38,7 +38,6 @@
 class LLViewerTexture ;
 class LLEventPump;
 class LLStartupListener;
-class LLSLURL;
 
 // functions
 bool idle_startup();
@@ -102,18 +101,26 @@ class LLStartUp
 	static void loadInitialOutfit( const std::string& outfit_folder_name,
 								   const std::string& gender_name );
 
+	// Load MD5 of user's password from local disk file.
+	static std::string loadPasswordFromDisk();
+	
+	// Record MD5 of user's password for subsequent login.
+	static void savePasswordToDisk(const std::string& hashed_password);
+	
+	// Delete the saved password local disk file.
+	static void deletePasswordFromDisk();
 	
 	static bool dispatchURL();
 		// if we have a SLURL or sim string ("Ahern/123/45") that started
 		// the viewer, dispatch it
 
+	static std::string sSLURLCommand;
+		// *HACK: On startup, if we were passed a secondlife://app/do/foo
+		// command URL, store it for later processing.
+
 	static void postStartupState();
-	static void setStartSLURL(const LLSLURL& slurl); 
-	static LLSLURL& getStartSLURL() { return sStartSLURL; } 
 
 private:
-	static LLSLURL sStartSLURL;
-
 	static std::string startupStateToString(EStartupState state);
 	static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState
 	static boost::scoped_ptr<LLEventPump> sStateWatcher;
diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp
index 8fab3bb361fce9f07ea944cb7941b76a9c0d8ae8..61705c4eb31390b527cb1efdf121fcd7a2c39b9b 100644
--- a/indra/newview/llstylemap.cpp
+++ b/indra/newview/llstylemap.cpp
@@ -51,7 +51,7 @@ const LLStyle::Params &LLStyleMap::lookupAgent(const LLUUID &source)
 			style_params.color.control = "HTMLLinkColor";
 			style_params.readonly_color.control = "HTMLLinkColor";
 			style_params.link_href = 
-					LLSLURL("agent", source, "inspect").getSLURLString();
+					LLSLURL::buildCommand("agent", source, "inspect");
 		}
 		else
 		{
diff --git a/indra/newview/llurl.cpp b/indra/newview/llurl.cpp
index 83a5839a93fc11237ff2bbacb0bae3a74beba990..ab65ead4c51fa5a8c64fe471694e550224827556 100644
--- a/indra/newview/llurl.cpp
+++ b/indra/newview/llurl.cpp
@@ -286,11 +286,5 @@ const char * LLURL::getFullPath()
 	return(sReturnString);
 }
 
-const char * LLURL::getAuthority()
-{
-	strncpy(LLURL::sReturnString,mAuthority, LL_MAX_PATH -1);               /* Flawfinder: ignore */
-	LLURL::sReturnString[LL_MAX_PATH -1] = '\0';
-	return(sReturnString);
-}
 
 char LLURL::sReturnString[LL_MAX_PATH] = "";
diff --git a/indra/newview/llurl.h b/indra/newview/llurl.h
index e41b83d29fe7ef168ff9111e04641f6d52173b11..9a089dd835a75dfb2573ec673733f64cc6ff258d 100644
--- a/indra/newview/llurl.h
+++ b/indra/newview/llurl.h
@@ -79,7 +79,6 @@ class LLURL
 
 	virtual const char *getFQURL() const;
 	virtual const char *getFullPath();
-	virtual const char *getAuthority();
 
 	virtual const char *updateRelativePath(const LLURL &url);
 
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index a31c3a0f1be779709d193d3d2f9537fc7722ff52..b88069cd48926d3fbebdb071438436e31a0063bb 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2007&license=viewergpl$
  * 
- * Copyright (c) 2010, Linden Research, Inc.
+ * Copyright (c) 2007-2009, Linden Research, Inc.
  * 
  * Second Life Viewer Source Code
  * The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
  * ("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://secondlife.com/developers/opensource/gplv2
+ * 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://secondlife.com/developers/opensource/flossexception
+ * 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,
@@ -44,10 +45,10 @@
 #include "llsidetray.h"
 #include "llslurl.h"
 #include "llstartup.h"			// gStartupState
+#include "llurlsimstring.h"
 #include "llweb.h"
 #include "llworldmapmessage.h"
 #include "llurldispatcherlistener.h"
-#include "llviewernetwork.h"
 
 // library includes
 #include "llnotificationsutil.h"
@@ -58,25 +59,25 @@ static LLURLDispatcherListener sURLDispatcherListener;
 class LLURLDispatcherImpl
 {
 public:
-	static bool dispatch(const LLSLURL& slurl,
+	static bool dispatch(const std::string& url,
 						 LLMediaCtrl* web,
 						 bool trusted_browser);
 		// returns true if handled or explicitly blocked.
 
-	static bool dispatchRightClick(const LLSLURL& slurl);
+	static bool dispatchRightClick(const std::string& url);
 
 private:
-	static bool dispatchCore(const LLSLURL& slurl, 
+	static bool dispatchCore(const std::string& url, 
 							 bool right_mouse,
 							 LLMediaCtrl* web,
 							 bool trusted_browser);
 		// handles both left and right click
 
-	static bool dispatchHelp(const LLSLURL& slurl, bool right_mouse);
+	static bool dispatchHelp(const std::string& url, bool right_mouse);
 		// Handles sl://app.floater.html.help by showing Help floater.
 		// Returns true if handled.
 
-	static bool dispatchApp(const LLSLURL& slurl,
+	static bool dispatchApp(const std::string& url,
 							bool right_mouse,
 							LLMediaCtrl* web,
 							bool trusted_browser);
@@ -84,16 +85,16 @@ class LLURLDispatcherImpl
 		// by showing panel in Search floater.
 		// Returns true if handled or explicitly blocked.
 
-	static bool dispatchRegion(const LLSLURL& slurl, bool right_mouse);
+	static bool dispatchRegion(const std::string& url, bool right_mouse);
 		// handles secondlife://Ahern/123/45/67/
 		// Returns true if handled.
 
-	static void regionHandleCallback(U64 handle, const LLSLURL& slurl,
+	static void regionHandleCallback(U64 handle, const std::string& url,
 		const LLUUID& snapshot_id, bool teleport);
 		// Called by LLWorldMap when a location has been resolved to a
 	    // region name
 
-	static void regionNameCallback(U64 handle, const LLSLURL& slurl,
+	static void regionNameCallback(U64 handle, const std::string& url,
 		const LLUUID& snapshot_id, bool teleport);
 		// Called by LLWorldMap when a region name has been resolved to a
 		// location in-world, used by places-panel display.
@@ -102,57 +103,65 @@ class LLURLDispatcherImpl
 };
 
 // static
-bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
+bool LLURLDispatcherImpl::dispatchCore(const std::string& url,
 									   bool right_mouse,
 									   LLMediaCtrl* web,
 									   bool trusted_browser)
 {
-	//if (dispatchHelp(slurl, right_mouse)) return true;
-	switch(slurl.getType())
-	{
-		case LLSLURL::APP: 
-			return dispatchApp(slurl, right_mouse, web, trusted_browser);
-		case LLSLURL::LOCATION:
-			return dispatchRegion(slurl, right_mouse);
-		default:
-			return false;
-	}
+	if (url.empty()) return false;
+	//if (dispatchHelp(url, right_mouse)) return true;
+	if (dispatchApp(url, right_mouse, web, trusted_browser)) return true;
+	if (dispatchRegion(url, right_mouse)) return true;
 
 	/*
 	// Inform the user we can't handle this
 	std::map<std::string, std::string> args;
-	args["SLURL"] = slurl;
+	args["SLURL"] = url;
 	r;
 	*/
+	
+	return false;
 }
 
 // static
-bool LLURLDispatcherImpl::dispatch(const LLSLURL& slurl,
+bool LLURLDispatcherImpl::dispatch(const std::string& url,
 								   LLMediaCtrl* web,
 								   bool trusted_browser)
 {
+	llinfos << "url: " << url << llendl;
 	const bool right_click = false;
-	return dispatchCore(slurl, right_click, web, trusted_browser);
+	return dispatchCore(url, right_click, web, trusted_browser);
 }
 
 // static
-bool LLURLDispatcherImpl::dispatchRightClick(const LLSLURL& slurl)
+bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url)
 {
+	llinfos << "url: " << url << llendl;
 	const bool right_click = true;
 	LLMediaCtrl* web = NULL;
 	const bool trusted_browser = false;
-	return dispatchCore(slurl, right_click, web, trusted_browser);
+	return dispatchCore(url, right_click, web, trusted_browser);
 }
 
 // static
-bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl, 
+bool LLURLDispatcherImpl::dispatchApp(const std::string& url, 
 									  bool right_mouse,
 									  LLMediaCtrl* web,
 									  bool trusted_browser)
 {
-	llinfos << "cmd: " << slurl.getAppCmd() << " path: " << slurl.getAppPath() << " query: " << slurl.getAppQuery() << llendl;
+	// ensure the URL is in the secondlife:///app/ format
+	if (!LLSLURL::isSLURLCommand(url))
+	{
+		return false;
+	}
+
+	LLURI uri(url);
+	LLSD pathArray = uri.pathArray();
+	pathArray.erase(0); // erase "app"
+	std::string cmd = pathArray.get(0);
+	pathArray.erase(0); // erase "cmd"
 	bool handled = LLCommandDispatcher::dispatch(
-			slurl.getAppCmd(), slurl.getAppPath(), slurl.getAppQuery(), web, trusted_browser);
+			cmd, pathArray, uri.queryMap(), web, trusted_browser);
 
 	// alert if we didn't handle this secondlife:///app/ SLURL
 	// (but still return true because it is a valid app SLURL)
@@ -164,72 +173,81 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl,
 }
 
 // static
-bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, bool right_mouse)
+bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mouse)
 {
-  if(slurl.getType() != LLSLURL::LOCATION)
-    {
-      return false;
-    }
+	if (!LLSLURL::isSLURL(url))
+	{
+		return false;
+	}
+
+	std::string sim_string = LLSLURL::stripProtocol(url);
+	std::string region_name;
+	S32 x = 128;
+	S32 y = 128;
+	S32 z = 0;
+	if (! LLURLSimString::parse(sim_string, &region_name, &x, &y, &z))
+	{
+		return false;
+	}
+
 	// Before we're logged in, need to update the startup screen
 	// to tell the user where they are going.
 	if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
 	{
+		// Parse it and stash in globals, it will be dispatched in
+		// STATE_CLEANUP.
+		LLURLSimString::setString(url);
 		// We're at the login screen, so make sure user can see
 		// the login location box to know where they are going.
 		
-		LLPanelLogin::setLocation(slurl);
+		LLPanelLogin::refreshLocation( true );
 		return true;
 	}
 
 	// LLFloaterURLDisplay functionality moved to LLPanelPlaces in Side Tray.
-	//LLFloaterURLDisplay* slurl_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD());
-	//if(slurl_displayp) slurl_displayp->setName(region_name);
+	//LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD());
+	//if(url_displayp) url_displayp->setName(region_name);
 
 	// Request a region handle by name
-	LLWorldMapMessage::getInstance()->sendNamedRegionRequest(slurl.getRegion(),
-									  LLURLDispatcherImpl::regionNameCallback,
-									  slurl.getSLURLString(),
-									  false);	// don't teleport
+	LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name,
+								 LLURLDispatcherImpl::regionNameCallback,
+								 url,
+								 false);	// don't teleport
 	return true;
 }
 
 /*static*/
-void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const LLSLURL& slurl, const LLUUID& snapshot_id, bool teleport)
+void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
 {
-      
-  if(slurl.getType() == LLSLURL::LOCATION)
-    {        
-      regionHandleCallback(region_handle, slurl, snapshot_id, teleport);
-    }
+	std::string sim_string = LLSLURL::stripProtocol(url);
+	std::string region_name;
+	S32 x = 128;
+	S32 y = 128;
+	S32 z = 0;
+
+	if (LLURLSimString::parse(sim_string, &region_name, &x, &y, &z))
+	{
+		regionHandleCallback(region_handle, url, snapshot_id, teleport);
+	}
 }
 
 /* static */
-void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const LLSLURL& slurl, const LLUUID& snapshot_id, bool teleport)
+void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
 {
+	std::string sim_string = LLSLURL::stripProtocol(url);
+	std::string region_name;
+	S32 x = 128;
+	S32 y = 128;
+	S32 z = 0;
+	LLURLSimString::parse(sim_string, &region_name, &x, &y, &z);
+
+	LLVector3 local_pos;
+	local_pos.mV[VX] = (F32)x;
+	local_pos.mV[VY] = (F32)y;
+	local_pos.mV[VZ] = (F32)z;
 
-  // we can't teleport cross grid at this point
-	if((!LLGridManager::getInstance()->isSystemGrid(slurl.getGrid()) || !LLGridManager::getInstance()->isSystemGrid()) &&
-	   (slurl.getGrid() != LLGridManager::getInstance()->getGrid()))
-	{
-		LLSD args;
-		args["SLURL"] = slurl.getLocationString();
-		args["CURRENT_GRID"] = LLGridManager::getInstance()->getGridLabel();
-		LLSD grid_info = LLGridManager::getInstance()->getGridInfo(slurl.getGrid());
-		
-		if(grid_info.has(GRID_LABEL_VALUE))
-		{
-			args["GRID"] = grid_info[GRID_LABEL_VALUE].asString();
-		}
-		else 
-		{
-			args["GRID"] = slurl.getGrid();
-		}
-		LLNotificationsUtil::add("CantTeleportToGrid", args);
-		return;
-	}
-	
 	LLVector3d global_pos = from_region_handle(region_handle);
-	global_pos += LLVector3d(slurl.getPosition());
+	global_pos += LLVector3d(local_pos);
 	
 	if (teleport)
 	{	
@@ -253,8 +271,8 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const LLSLURL&
 		// LLFloaterURLDisplay functionality moved to LLPanelPlaces in Side Tray.
 
 //		// display informational floater, allow user to click teleport btn
-//		LLFloaterURLDisplay* slurl_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD());
-//		if(slurl_displayp)
+//		LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD());
+//		if(url_displayp)
 //		{
 //			url_displayp->displayParcelInfo(region_handle, local_pos);
 //			if(snapshot_id.notNull())
@@ -269,7 +287,7 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const LLSLURL&
 
 //---------------------------------------------------------------------------
 // Teleportation links are handled here because they are tightly coupled
-// to SLURL parsing and sim-fragment parsing
+// to URL parsing and sim-fragment parsing
 class LLTeleportHandler : public LLCommandHandler
 {
 public:
@@ -285,21 +303,18 @@ class LLTeleportHandler : public LLCommandHandler
 		// a global position, and teleport to it
 		if (tokens.size() < 1) return false;
 
-		LLVector3 coords(128, 128, 0);
-		if (tokens.size() <= 4)
-		{
-			coords = LLVector3(tokens[1].asReal(), 
-							   tokens[2].asReal(), 
-							   tokens[3].asReal());
-		}
-		
 		// Region names may be %20 escaped.
-		
-		std::string region_name = LLURI::unescape(tokens[0]);
+		std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]);
 
+		// build secondlife://De%20Haro/123/45/67 for use in callback
+		std::string url = LLSLURL::PREFIX_SECONDLIFE;
+		for (int i = 0; i < tokens.size(); ++i)
+		{
+			url += tokens[i].asString() + "/";
+		}
 		LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name,
 			LLURLDispatcherImpl::regionHandleCallback,
-			LLSLURL(region_name, coords).getSLURLString(),
+			url,
 			true);	// teleport
 		return true;
 	}
@@ -309,21 +324,21 @@ LLTeleportHandler gTeleportHandler;
 //---------------------------------------------------------------------------
 
 // static
-bool LLURLDispatcher::dispatch(const std::string& slurl,
+bool LLURLDispatcher::dispatch(const std::string& url,
 							   LLMediaCtrl* web,
 							   bool trusted_browser)
 {
-	return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), web, trusted_browser);
+	return LLURLDispatcherImpl::dispatch(url, web, trusted_browser);
 }
 
 // static
-bool LLURLDispatcher::dispatchRightClick(const std::string& slurl)
+bool LLURLDispatcher::dispatchRightClick(const std::string& url)
 {
-	return LLURLDispatcherImpl::dispatchRightClick(LLSLURL(slurl));
+	return LLURLDispatcherImpl::dispatchRightClick(url);
 }
 
 // static
-bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl)
+bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url)
 {
 	// *NOTE: Text editors are considered sources of trusted URLs
 	// in order to make avatar profile links in chat history work.
@@ -333,7 +348,5 @@ bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl)
 	// *TODO: Make this trust model more refined.  JC
 	const bool trusted_browser = true;
 	LLMediaCtrl* web = NULL;
-	return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), web, trusted_browser);
+	return LLURLDispatcherImpl::dispatch(url, web, trusted_browser);
 }
-
-
diff --git a/indra/newview/llurldispatcher.h b/indra/newview/llurldispatcher.h
index 407e417e5852b437d322666f98ff21264a7f34a5..ff8a3512539ca5542528c15c09f7cf537b93b035 100644
--- a/indra/newview/llurldispatcher.h
+++ b/indra/newview/llurldispatcher.h
@@ -2,9 +2,9 @@
  * @file llurldispatcher.h
  * @brief Central registry for all SL URL handlers
  *
- * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
  * 
- * Copyright (c) 2007-2010, Linden Research, Inc.
+ * Copyright (c) 2007-2009, Linden Research, Inc.
  * 
  * Second Life Viewer Source Code
  * The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
  * ("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://secondlife.com/developers/opensource/gplv2
+ * 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://secondlife.com/developers/opensource/flossexception
+ * 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,
@@ -30,16 +31,16 @@
  */
 #ifndef LLURLDISPATCHER_H
 #define LLURLDISPATCHER_H
+
 class LLMediaCtrl;
 
 
 class LLURLDispatcher
 {
 public:
-	
-	static bool dispatch(const std::string& slurl,
+	static bool dispatch(const std::string& url,
 						 LLMediaCtrl* web,
-						 bool trusted_browser);	
+						 bool trusted_browser);
 		// At startup time and on clicks in internal web browsers,
 		// teleport, open map, or run requested command.
 		// @param url
@@ -53,9 +54,9 @@ class LLURLDispatcher
 		//   that navigates to trusted (Linden Lab) pages.
 		// Returns true if someone handled the URL.
 
-	static bool dispatchRightClick(const std::string& slurl);
+	static bool dispatchRightClick(const std::string& url);
 
-	static bool dispatchFromTextEditor(const std::string& slurl);
+	static bool dispatchFromTextEditor(const std::string& url);
 };
 
 #endif
diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp
index 8488527185dc7f636e9921d3815b0f7a54faad46..1d2687a8c269073c9893b2777ea99f3ea6922605 100644
--- a/indra/newview/llurllineeditorctrl.cpp
+++ b/indra/newview/llurllineeditorctrl.cpp
@@ -89,7 +89,7 @@ void LLURLLineEditor::copyEscapedURLToClipboard()
 
 	const std::string unescaped_text = wstring_to_utf8str(mText.getWString().substr(left_pos, length));
 	LLWString text_to_copy;
-	if (LLSLURL(unescaped_text).isValid())
+	if (LLSLURL::isSLURL(unescaped_text))
 		text_to_copy = utf8str_to_wstring(LLWeb::escapeURL(unescaped_text));
 	else
 		text_to_copy = utf8str_to_wstring(unescaped_text);
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index ef6f4194e0ca46fd583306785e04b19a9e89c135..2661c9f32b3b9e6aad1a228fdcfacb3c9c037bf6 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -157,21 +157,21 @@ void audio_update_volume(bool force_update)
 	LLViewerMedia::setVolume( media_muted ? 0.0f : media_volume );
 
 	// Voice
-	if (LLVoiceClient::getInstance())
+	if (gVoiceClient)
 	{
 		F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
 		voice_volume = mute_volume * master_volume * voice_volume;
 		BOOL voice_mute = gSavedSettings.getBOOL("MuteVoice");
-		LLVoiceClient::getInstance()->setVoiceVolume(voice_mute ? 0.f : voice_volume);
-		LLVoiceClient::getInstance()->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
+		gVoiceClient->setVoiceVolume(voice_mute ? 0.f : voice_volume);
+		gVoiceClient->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
 
 		if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
 		{
-			LLVoiceClient::getInstance()->setMuteMic(true);
+			gVoiceClient->setMuteMic(true);
 		}
 		else
 		{
-			LLVoiceClient::getInstance()->setMuteMic(false);
+			gVoiceClient->setMuteMic(false);
 		}
 	}
 }
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index ef6379948ac6c1dba57da489768a76bc32520c10..6f037177fabccf8f5c8aa2249540237b2b89c4e3 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -413,6 +413,7 @@ bool handleHighResSnapshotChanged(const LLSD& newvalue)
 
 bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
 {
+	if(LLVoiceClient::getInstance())
 	LLVoiceClient::getInstance()->updateSettings();
 	return true;
 }
@@ -443,7 +444,7 @@ bool handleVelocityInterpolate(const LLSD& newvalue)
 
 bool handleForceShowGrid(const LLSD& newvalue)
 {
-	LLPanelLogin::updateServer( );
+	LLPanelLogin::refreshLocation( false );
 	return true;
 }
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 17221219eb63bfb80e3ffbe2e07ab7666a4aeecc..b42d25c1d88638a3e6c635d26a975319bb83eb5e 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -36,6 +36,7 @@
 #include "llnotificationsutil.h"
 #include "llsdserialize.h"
 #include "message.h"
+#include "indra_constants.h"
 
 #include "llagent.h"
 #include "llagentcamera.h"
@@ -263,14 +264,10 @@ void LLViewerInventoryItem::fetchFromServer(void) const
 		// we have to check region. It can be null after region was destroyed. See EXT-245
 		if (region)
 		{
-		  if(gAgent.getID() != mPermissions.getOwner())
-		    {
-		      url = region->getCapability("FetchLib");
-		    }
-		  else
-		    {	
-		      url = region->getCapability("FetchInventory");
-		    }
+			if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString())
+				url = region->getCapability("FetchLib");
+			else	
+				url = region->getCapability("FetchInventory");
 		}
 		else
 		{
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a8b1257cf68271bd6e88c119009afb5e99f6f5a6..7d87f06794b1d55c4d1ac92aa62ad7a083a58120 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -429,7 +429,7 @@ void init_menus()
 	gPopupMenuView->setBackgroundColor( color );
 
 	// If we are not in production, use a different color to make it apparent.
-	if (LLGridManager::getInstance()->isInProductionGrid())
+	if (LLViewerLogin::getInstance()->isInProductionGrid())
 	{
 		color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
 	}
@@ -445,7 +445,7 @@ void init_menus()
 	menu_bar_holder->addChild(gMenuBarView);
   
     gViewerWindow->setMenuBackgroundColor(false, 
-        LLGridManager::getInstance()->isInProductionGrid());
+        LLViewerLogin::getInstance()->isInProductionGrid());
 
 	// Assume L$10 for now, the server will tell us the real cost at login
 	// *TODO:Also fix cost in llfolderview.cpp for Inventory menus
@@ -3467,7 +3467,7 @@ void set_god_level(U8 god_level)
         if(gViewerWindow)
         {
             gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
-            LLGridManager::getInstance()->isInProductionGrid());
+            LLViewerLogin::getInstance()->isInProductionGrid());
         }
     
         LLSD args;
@@ -3507,7 +3507,7 @@ BOOL check_toggle_hacked_godmode(void*)
 
 bool enable_toggle_hacked_godmode(void*)
 {
-  return !LLGridManager::getInstance()->isInProductionGrid();
+  return !LLViewerLogin::getInstance()->isInProductionGrid();
 }
 #endif
 
@@ -4378,7 +4378,7 @@ BOOL enable_take()
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid() 
+		if (!LLViewerLogin::getInstance()->isInProductionGrid() 
             && gAgent.isGodlike())
 		{
 			return TRUE;
@@ -4991,7 +4991,7 @@ bool enable_object_delete()
 	TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-	(!LLGridManager::getInstance()->isInProductionGrid()
+	(!LLViewerLogin::getInstance()->isInProductionGrid()
      && gAgent.isGodlike()) ||
 # endif
 	LLSelectMgr::getInstance()->canDoDelete();
@@ -6627,7 +6627,7 @@ bool enable_object_take_copy()
 		all_valid = true;
 #ifndef HACKED_GODLIKE_VIEWER
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (LLGridManager::getInstance()->isInProductionGrid()
+		if (LLViewerLogin::getInstance()->isInProductionGrid()
             || !gAgent.isGodlike())
 # endif
 		{
@@ -6689,7 +6689,7 @@ BOOL enable_save_into_inventory(void*)
 	return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-	if (!LLGridManager::getInstance()->isInProductionGrid()
+	if (!LLViewerLogin::getInstance()->isInProductionGrid()
         && gAgent.isGodlike())
 	{
 		return TRUE;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 7346b2a76ef962262bf2ef3eefb826cac67afa56..1426c0b9e2b7e2bd2e374f984a3111cb6fb0ee7f 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1573,9 +1573,9 @@ void inventory_offer_handler(LLOfferInfo* info)
 	payload["give_inventory_notification"] = FALSE;
 	args["OBJECTFROMNAME"] = info->mFromName;
 	args["NAME"] = info->mFromName;
-	args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
+	args["NAME_SLURL"] = LLSLURL::buildCommand("agent", info->mFromID, "about");
 	std::string verb = "select?name=" + LLURI::escape(msg);
-	args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString();
+	args["ITEM_SLURL"] = LLSLURL::buildCommand("inventory", info->mObjectID, verb.c_str());
 
 	LLNotification::Params p("ObjectGiveItem");
 
@@ -2244,7 +2244,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 				query_string["groupowned"] = "true";
 			}	
 
-			chat.mURL = LLSLURL("objectim", session_id, "").getSLURLString();
+			std::ostringstream link;
+			link << "secondlife:///app/objectim/" << session_id << LLURI::mapToQueryString(query_string);
+
+			chat.mURL = link.str();
 			chat.mText = message;
 			chat.mSourceType = CHAT_SOURCE_OBJECT;
 
@@ -2327,7 +2330,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 			{
 				LLSD args;
 				// *TODO: Translate -> [FIRST] [LAST] (maybe)
-				args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
+				args["NAME_SLURL"] = LLSLURL::buildCommand("agent", from_id, "about");
 				args["MESSAGE"] = message;
 				LLSD payload;
 				payload["from_id"] = from_id;
@@ -2393,7 +2396,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 			}
 			else
 			{
-				args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
+				args["NAME_SLURL"] = LLSLURL::buildCommand("agent", from_id, "about");
 				if(message.empty())
 				{
 					//support for frienship offers from clients before July 2008
@@ -3152,9 +3155,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
 		{
 			// Chat the "back" SLURL. (DEV-4907)
 
-			LLSLURL slurl;
-			gAgent.getTeleportSourceSLURL(slurl);
-			LLSD substitution = LLSD().with("[T_SLURL]", slurl.getSLURLString());
+			LLSD substitution = LLSD().with("[T_SLURL]", gAgent.getTeleportSourceSLURL());
 			std::string completed_from = LLAgent::sTeleportProgressMessages["completed_from"];
 			LLStringUtil::format(completed_from, substitution);
 
@@ -5547,9 +5548,7 @@ void send_group_notice(const LLUUID& group_id,
 bool handle_lure_callback(const LLSD& notification, const LLSD& response)
 {
 	std::string text = response["message"].asString();
-	LLSLURL slurl;
-	LLAgentUI::buildSLURL(slurl);
-	text.append("\r\n").append(slurl.getSLURLString());
+	text.append("\r\n").append(LLAgentUI::buildSLURL());
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 
 	if(0 == option)
@@ -5992,7 +5991,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
 	LLFloaterBuyLand::updateEstateName(estate_name);
 
 	std::string owner_name =
-		LLSLURL("agent", estate_owner_id, "inspect").getSLURLString();
+		LLSLURL::buildCommand("agent", estate_owner_id, "inspect");
 	LLPanelEstateCovenant::updateEstateOwnerName(owner_name);
 	LLPanelLandCovenant::updateEstateOwnerName(owner_name);
 	LLFloaterBuyLand::updateEstateOwnerName(owner_name);
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index d7bb4efe8535810ccf7100dfee1a0dd46a879dff..987d23630a9e49b0d1b054beccb9e31346329185 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -5,7 +5,7 @@
  *
  * $LicenseInfo:firstyear=2006&license=viewergpl$
  * 
- * Copyright (c) 2006-2010, Linden Research, Inc.
+ * 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
@@ -13,12 +13,13 @@
  * ("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://secondlife.com/developers/opensource/gplv2
+ * 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://secondlife.com/developers/opensource/flossexception
+ * 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,
@@ -33,478 +34,303 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llviewernetwork.h"
-#include "llviewercontrol.h"
-#include "llsdserialize.h"
-#include "llweb.h"
-
-                                                            
-const char* DEFAULT_LOGIN_PAGE = "http://secondlife.com/app/login/";
 
-const char* SYSTEM_GRID_SLURL_BASE = "secondlife://%s/secondlife/";
-const char* MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/";
-const char* SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app";
+#include "llevents.h"
+#include "net.h"
 
-const char* DEFAULT_SLURL_BASE = "https://%s/region/";
-const char* DEFAULT_APP_SLURL_BASE = "x-grid-location-info://%s/app";
+#include "llviewercontrol.h"
+#include "lllogin.h"
 
-LLGridManager::LLGridManager()
+struct LLGridData
 {
-	// by default, we use the 'grids.xml' file in the user settings directory
-	// this file is an LLSD file containing multiple grid definitions.
-	// This file does not contain definitions for secondlife.com grids,
-	// as that would be a security issue when they are overwritten by
-	// an attacker.  Don't want someone snagging a password.
-	std::string grid_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
-														   "grids.xml");
-	initialize(grid_file);
-	
-}
+	const char* mLabel;
+	const char* mName;
+	const char* mLoginURI;
+	const char* mHelperURI;
+};
 
-
-LLGridManager::LLGridManager(const std::string& grid_file)
+static LLGridData gGridInfo[GRID_INFO_COUNT] = 
 {
-	// initialize with an explicity grid file for testing.
-	initialize(grid_file);
-}
-
-//
-// LLGridManager - class for managing the list of known grids, and the current
-// selection
-//
-
-
-//
-// LLGridManager::initialze - initialize the list of known grids based
-// on the fixed list of linden grids (fixed for security reasons)
-// the grids.xml file
-// and the command line.
-void LLGridManager::initialize(const std::string& grid_file)
+	{ "None", "", "", ""},
+	{ "Aditi", 
+	  "util.aditi.lindenlab.com", 
+	  "https://login.aditi.lindenlab.com/cgi-bin/login.cgi",
+	  "http://aditi-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Agni", 
+	  "util.agni.lindenlab.com", 
+	  "https://login.agni.lindenlab.com/cgi-bin/login.cgi",
+	  "https://secondlife.com/helpers/" },
+	{ "Aruna",
+	  "util.aruna.lindenlab.com",
+	  "https://login.aruna.lindenlab.com/cgi-bin/login.cgi",
+	  "http://aruna-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Bharati",
+	  "util.bharati.lindenlab.com",
+	  "https://login.bharati.lindenlab.com/cgi-bin/login.cgi",
+	  "http://bharati-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Chandra",
+	  "util.chandra.lindenlab.com",
+	  "https://login.chandra.lindenlab.com/cgi-bin/login.cgi",
+	  "http://chandra-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Damballah",
+	  "util.damballah.lindenlab.com",
+	  "https://login.damballah.lindenlab.com/cgi-bin/login.cgi",
+	  "http://damballah-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Danu",
+	  "util.danu.lindenlab.com",
+	  "https://login.danu.lindenlab.com/cgi-bin/login.cgi",
+	  "http://danu-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Durga",
+	  "util.durga.lindenlab.com",
+	  "https://login.durga.lindenlab.com/cgi-bin/login.cgi",
+	  "http://durga-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Ganga",
+	  "util.ganga.lindenlab.com",
+	  "https://login.ganga.lindenlab.com/cgi-bin/login.cgi",
+	  "http://ganga-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Mitra",
+	  "util.mitra.lindenlab.com",
+	  "https://login.mitra.lindenlab.com/cgi-bin/login.cgi",
+	  "http://mitra-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Mohini",
+	  "util.mohini.lindenlab.com",
+	  "https://login.mohini.lindenlab.com/cgi-bin/login.cgi",
+	  "http://mohini-secondlife.webdev.lindenlab.com/helpers/" },
+  	{ "Nandi",
+	  "util.nandi.lindenlab.com",
+	  "https://login.nandi.lindenlab.com/cgi-bin/login.cgi",
+	  "http://nandi-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Parvati",
+	  "util.parvati.lindenlab.com",
+	  "https://login.parvati.lindenlab.com/cgi-bin/login.cgi",
+	  "http://parvati-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Radha",
+	  "util.radha.lindenlab.com",
+	  "https://login.radha.lindenlab.com/cgi-bin/login.cgi",
+	  "http://radha-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Ravi",
+	  "util.ravi.lindenlab.com",
+	  "https://login.ravi.lindenlab.com/cgi-bin/login.cgi",
+	  "http://ravi-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Siva", 
+	  "util.siva.lindenlab.com",
+	  "https://login.siva.lindenlab.com/cgi-bin/login.cgi",
+	  "http://siva-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Shakti",
+	  "util.shakti.lindenlab.com",
+	  "https://login.shakti.lindenlab.com/cgi-bin/login.cgi",
+	  "http://shakti-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Skanda",
+	  "util.skanda.lindenlab.com",
+	  "https://login.skanda.lindenlab.com/cgi-bin/login.cgi",
+	  "http://skanda-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Soma",
+	  "util.soma.lindenlab.com",
+	  "https://login.soma.lindenlab.com/cgi-bin/login.cgi",
+	  "http://soma-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Uma",
+	  "util.uma.lindenlab.com",
+	  "https://login.uma.lindenlab.com/cgi-bin/login.cgi",
+	  "http://uma-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Vaak",
+	  "util.vaak.lindenlab.com",
+	  "https://login.vaak.lindenlab.com/cgi-bin/login.cgi",
+	  "http://vaak-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Yami",
+	  "util.yami.lindenlab.com",
+	  "https://login.yami.lindenlab.com/cgi-bin/login.cgi",
+	  "http://yami-secondlife.webdev.lindenlab.com/helpers/" },
+	{ "Local", 
+	  "localhost", 
+	  "https://login.dmz.lindenlab.com/cgi-bin/login.cgi",
+	  "" },
+	{ "Other", 
+	  "", 
+	  "https://login.dmz.lindenlab.com/cgi-bin/login.cgi",
+	  "" }
+};
+
+const EGridInfo DEFAULT_GRID_CHOICE = GRID_INFO_AGNI;
+
+
+unsigned char gMACAddress[MAC_ADDRESS_BYTES];		/* Flawfinder: ignore */
+
+LLViewerLogin::LLViewerLogin() :
+	mGridChoice(DEFAULT_GRID_CHOICE)
 {
-	// default grid list.
-	// Don't move to a modifiable file for security reasons,
-	mGrid.clear() ;
-	// set to undefined
-	mGridList = LLSD();
-	mGridFile = grid_file;
-	// as we don't want an attacker to override our grid list
-	// to point the default grid to an invalid grid
-	addSystemGrid("None", "", "", "", DEFAULT_LOGIN_PAGE);
-	
-
+}
 
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-  	addSystemGrid("Agni",                                                                                             
-				  MAINGRID,                                               
-				  "https://login.agni.lindenlab.com/cgi-bin/login.cgi",                    
-				  "https://secondlife.com/helpers/",     
-				  DEFAULT_LOGIN_PAGE);
-#else
-	addSystemGrid("Secondlife.com",                                                                                             
-				  MAINGRID,                                               
-				  "https://login.agni.lindenlab.com/cgi-bin/login.cgi",                    
-				  "https://secondlife.com/helpers/",     
-				  DEFAULT_LOGIN_PAGE,
-				  "Agni");
-#endif // LL_RELEASE_FOR_DOWNLOAD	
-	addSystemGrid("Aditi",                                                                                             
-				  "util.aditi.lindenlab.com",                                              
-				  "https://login.aditi.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://aditi-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Aruna",                                                                                            
-				  "util.aruna.lindenlab.com",                                              
-				  "https://login.aruna.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://aruna-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Durga",                                                                                            
-				  "util.durga.lindenlab.com",                                              
-				  "https://login.durga.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://durga-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Ganga",                                                                                            
-				  "util.ganga.lindenlab.com",                                              
-				  "https://login.ganga.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://ganga-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Mitra",                                                                                            
-				  "util.mitra.lindenlab.com",                                              
-				  "https://login.mitra.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://mitra-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Mohini",                                                                                           
-				  "util.mohini.lindenlab.com",                                             
-				  "https://login.mohini.lindenlab.com/cgi-bin/login.cgi",                  
-				  "http://mohini-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Nandi",                                                                                            
-				  "util.nandi.lindenlab.com",                                              
-				  "https://login.nandi.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://nandi-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Radha",                                                                                            
-				  "util.radha.lindenlab.com",                                              
-				  "https://login.radha.lindenlab.com/cgi-bin/login.cgi",                   
-				  "http://radha-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Ravi",                                                                                             
-				  "util.ravi.lindenlab.com",                                               
-				  "https://login.ravi.lindenlab.com/cgi-bin/login.cgi",                    
-				  "http://ravi-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Siva",                                                                                             
-				  "util.siva.lindenlab.com",                                               
-				  "https://login.siva.lindenlab.com/cgi-bin/login.cgi",                    
-				  "http://siva-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Shakti",                                                                                           
-				  "util.shakti.lindenlab.com",                                             
-				  "https://login.shakti.lindenlab.com/cgi-bin/login.cgi",                  
-				  "http://shakti-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Soma",                                                                                             
-				  "util.soma.lindenlab.com",                                               
-				  "https://login.soma.lindenlab.com/cgi-bin/login.cgi",                    
-				  "http://soma-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	
-	addSystemGrid("Uma",                                                                                              
-				  "util.uma.lindenlab.com",                                                
-				  "https://login.uma.lindenlab.com/cgi-bin/login.cgi",                     
-				  "http://uma-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Vaak",                                                                                             
-				  "util.vaak.lindenlab.com",                                               
-				  "https://login.vaak.lindenlab.com/cgi-bin/login.cgi",                    
-				  "http://vaak-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Yami",                                                                                             
-				  "util.yami.lindenlab.com",                                               
-				  "https://login.yami.lindenlab.com/cgi-bin/login.cgi",                    
-				  "http://yami-secondlife.webdev.lindenlab.com/helpers/",
-				  DEFAULT_LOGIN_PAGE);
-	addSystemGrid("Local (Linden)",                                                                                    
-				  "localhost",                                                             
-				  "https://login.dmz.lindenlab.com/cgi-bin/login.cgi",                     
-				  "",
-				  DEFAULT_LOGIN_PAGE); 
+ LLViewerLogin::~LLViewerLogin() 
+ {
+ }
 
-	
-	LLSD other_grids;
-	llifstream llsd_xml;
-	if (!grid_file.empty())
+void LLViewerLogin::setGridChoice(EGridInfo grid)
+{	
+	if(grid < 0 || grid >= GRID_INFO_COUNT)
 	{
-		llsd_xml.open( grid_file.c_str(), std::ios::in | std::ios::binary );
-
-		// parse through the gridfile, inserting grids into the list unless
-		// they overwrite a linden grid.
-		if( llsd_xml.is_open()) 
-		{
-			LLSDSerialize::fromXMLDocument( other_grids, llsd_xml );
-			if(other_grids.isMap())
-			{
-				for(LLSD::map_iterator grid_itr = other_grids.beginMap(); 
-					grid_itr != other_grids.endMap();
-					++grid_itr)
-				{
-					LLSD::String key_name = grid_itr->first;
-					LLSD grid = grid_itr->second;
-					// TODO:  Make sure gridfile specified label is not 
-					// a system grid label
-					LL_INFOS("GridManager") << "reading: " << key_name << LL_ENDL;
-					if (mGridList.has(key_name) &&
-						mGridList[key_name].has(GRID_IS_SYSTEM_GRID_VALUE))
-					{
-						LL_INFOS("GridManager") << "Cannot override grid " << key_name << " as it's a system grid" << LL_ENDL;
-						// If the system grid does exist in the grids file, and it's marked as a favorite, set it as a favorite.
-						if(grid_itr->second.has(GRID_IS_FAVORITE_VALUE) && grid_itr->second[GRID_IS_FAVORITE_VALUE].asBoolean() )
-						{
-							mGridList[key_name][GRID_IS_FAVORITE_VALUE] = TRUE;
-						}
-					}
-					else
-					{
-						try
-						{
-							addGrid(grid);
-							LL_INFOS("GridManager") << "Added grid: " << key_name << LL_ENDL;
-						}
-						catch (...)
-						{
-						}
-					}
-				}
-				llsd_xml.close();
-			}	
-		}     
+		llerrs << "Invalid grid index specified." << llendl;
+		return;
 	}
-	
-	// load a grid from the command line.
-	// if the actual grid name is specified from the command line,
-	// set it as the 'selected' grid.
-	mGrid = gSavedSettings.getString("CmdLineGridChoice");
-	LL_INFOS("GridManager") << "Grid Name: " << mGrid << LL_ENDL;		
-	
-	// If a command line login URI was passed in, so we should add the command
-	// line grid to the list of grids
 
-	LLSD cmd_line_login_uri = gSavedSettings.getLLSD("CmdLineLoginURI");
-	if (cmd_line_login_uri.isString())
+	if(mGridChoice != grid || gSavedSettings.getS32("ServerChoice") != grid)
 	{
-		LL_INFOS("GridManager") << "adding cmd line login uri" << LL_ENDL;
-		// grab the other related URI values
-		std::string cmd_line_helper_uri = gSavedSettings.getString("CmdLineHelperURI");
-		std::string cmd_line_login_page = gSavedSettings.getString("LoginPage");
-		
-		// we've a cmd line login, so add a grid for the command line,
-		// overwriting any existing grids
-		LLSD grid = LLSD::emptyMap();
-		grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray();
-		grid[GRID_LOGIN_URI_VALUE].append(cmd_line_login_uri);
-		LL_INFOS("GridManager") << "cmd line login uri: " << cmd_line_login_uri.asString() << LL_ENDL;
-		LLURI uri(cmd_line_login_uri.asString());
-		if (mGrid.empty())
+		mGridChoice = grid;
+		if(GRID_INFO_LOCAL == mGridChoice)
 		{
-			// if a grid name was not passed in via the command line,
-			// then set the grid name based on the hostname of the 
-			// login uri
-			mGrid = uri.hostName();
+			mGridName = LOOPBACK_ADDRESS_STRING;
 		}
-
-		grid[GRID_VALUE] = mGrid;
-
-		if (mGridList.has(mGrid) && mGridList[mGrid].has(GRID_LABEL_VALUE))
+		else if(GRID_INFO_OTHER == mGridChoice)
 		{
-			grid[GRID_LABEL_VALUE] = mGridList[mGrid][GRID_LABEL_VALUE];
+			// *FIX:Mani - could this possibly be valid?
+			mGridName = "other"; 
 		}
 		else
 		{
-			grid[GRID_LABEL_VALUE] = mGrid;			
-		}
-		if(!cmd_line_helper_uri.empty())
-		{
-			grid[GRID_HELPER_URI_VALUE] = cmd_line_helper_uri;
+			mGridName = gGridInfo[mGridChoice].mLabel;
 		}
 
-		if(!cmd_line_login_page.empty())
-		{
-			grid[GRID_LOGIN_PAGE_VALUE] = cmd_line_login_page;
-		}
-		// if the login page, helper URI value, and so on are not specified,
-		// add grid will generate them.
-
-		// Also, we will override a system grid if values are passed in via the command
-		// line, for testing.  These values will not be remembered though.
-		if (mGridList.has(mGrid) && mGridList[mGrid].has(GRID_IS_SYSTEM_GRID_VALUE))
-		{
-			grid[GRID_IS_SYSTEM_GRID_VALUE] = TRUE;
-		}
-		addGrid(grid);
+		gSavedSettings.setS32("ServerChoice", mGridChoice);
+		gSavedSettings.setString("CustomServer", "");
 	}
-	
-	// if a grid was not passed in via the command line, grab it from the CurrentGrid setting.
-	if (mGrid.empty())
-	{
-
-		mGrid = gSavedSettings.getString("CurrentGrid");
-	}
-
-	if (mGrid.empty() || !mGridList.has(mGrid))
-	{
-		// the grid name was empty, or the grid isn't actually in the list, then set it to the
-		// appropriate default.
-		LL_INFOS("GridManager") << "Resetting grid as grid name " << mGrid << " is not in the list" << LL_ENDL;
-#if LL_RELEASE_FOR_DOWNLOAD
-		mGrid = MAINGRID;
-#else
-		mGrid = "";
-#endif
-	}
-	LL_INFOS("GridManager") << "Selected grid is " << mGrid << LL_ENDL;		
-	gSavedSettings.setString("CurrentGrid", mGrid);
-
 }
 
-LLGridManager::~LLGridManager()
+void LLViewerLogin::setGridChoice(const std::string& grid_name)
 {
-	saveFavorites();
+	// Set the grid choice based on a string.
+	// The string can be:
+	// - a grid label from the gGridInfo table 
+	// - an ip address
+    if(!grid_name.empty())
+    {
+        // find the grid choice from the user setting.
+        int grid_index = GRID_INFO_NONE; 
+        for(;grid_index < GRID_INFO_OTHER; ++grid_index)
+        {
+            if(0 == LLStringUtil::compareInsensitive(gGridInfo[grid_index].mLabel, grid_name))
+            {
+				// Founding a matching label in the list...
+				setGridChoice((EGridInfo)grid_index);
+				break;
+            }
+        }
+
+        if(GRID_INFO_OTHER == grid_index)
+        {
+            // *FIX:MEP Can and should we validate that this is an IP address?
+            mGridChoice = GRID_INFO_OTHER;
+            mGridName = grid_name;
+			gSavedSettings.setS32("ServerChoice", mGridChoice);
+			gSavedSettings.setString("CustomServer", mGridName);
+        }
+    }
 }
 
-//
-// LLGridManager::addGrid - add a grid to the grid list, populating the needed values
-// if they're not populated yet.
-//
-
-void LLGridManager::addGrid(LLSD& grid_data)
+void LLViewerLogin::resetURIs()
 {
-	if (grid_data.isMap() && grid_data.has(GRID_VALUE))
-	{
-		std::string grid = utf8str_tolower(grid_data[GRID_VALUE]);
+    // Clear URIs when picking a new server
+	gSavedSettings.setLLSD("CmdLineLoginURI", LLSD::emptyArray());
+	gSavedSettings.setString("CmdLineHelperURI", "");
+}
 
-		// grid should be in the form of a dns address
-		if (!grid.empty() &&
-			grid.find_first_not_of("abcdefghijklmnopqrstuvwxyz1234567890-_. ") != std::string::npos)
-		{
-			printf("grid name: %s", grid.c_str());
-			throw LLInvalidGridName(grid);
-		}
-		
-		// populate the other values if they don't exist
-		if (!grid_data.has(GRID_LABEL_VALUE)) 
-		{
-			grid_data[GRID_LABEL_VALUE] = grid;
-		}
-		if (!grid_data.has(GRID_ID_VALUE))
-		{
-			grid_data[GRID_ID_VALUE] = grid;
-		}
-		
-		// if the grid data doesn't include any of the URIs, then 
-		// generate them from the grid, which should be a dns address
-		if (!grid_data.has(GRID_LOGIN_URI_VALUE)) 
-		{
-			grid_data[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray();
-			grid_data[GRID_LOGIN_URI_VALUE].append(std::string("https://") + 
-													grid + "/cgi-bin/login.cgi");
-		}
-		// Populate to the default values
-		if (!grid_data.has(GRID_LOGIN_PAGE_VALUE)) 
-		{
-			grid_data[GRID_LOGIN_PAGE_VALUE] = std::string("http://") + grid + "/app/login/";
-		}		
-		if (!grid_data.has(GRID_HELPER_URI_VALUE)) 
-		{
-			grid_data[GRID_HELPER_URI_VALUE] = std::string("https://") + grid + "/helpers/";
-		}		
-		LL_INFOS("GridManager") << "ADDING: " << grid << LL_ENDL;
-		mGridList[grid] = grid_data;		
-	}
+EGridInfo LLViewerLogin::getGridChoice() const
+{
+	return mGridChoice;
 }
 
-//
-// LLGridManager::addSystemGrid - helper for adding a system grid.
-void LLGridManager::addSystemGrid(const std::string& label, 
-								  const std::string& name, 
-								  const std::string& login, 
-								  const std::string& helper,
-								  const std::string& login_page,
-								  const std::string& login_id)
+std::string LLViewerLogin::getGridLabel() const
 {
-	LLSD grid = LLSD::emptyMap();
-	grid[GRID_VALUE] = name;
-	grid[GRID_LABEL_VALUE] = label;
-	grid[GRID_HELPER_URI_VALUE] = helper;
-	grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray();
-	grid[GRID_LOGIN_URI_VALUE].append(login);
-	grid[GRID_LOGIN_PAGE_VALUE] = login_page;
-	grid[GRID_IS_SYSTEM_GRID_VALUE] = TRUE;
-	grid[GRID_LOGIN_CREDENTIAL_PAGE_TYPE_VALUE] = GRID_LOGIN_CREDENTIAL_PAGE_TYPE_AGENT;
-	
-	grid[GRID_APP_SLURL_BASE] = SYSTEM_GRID_APP_SLURL_BASE;
-	if (login_id.empty())
-	{
-		grid[GRID_ID_VALUE] = name;
-	}
-	else
+	if(mGridChoice == GRID_INFO_NONE)
 	{
-		grid[GRID_ID_VALUE] = login_id;
+		return "None";
 	}
-	
-	// only add the system grids beyond agni to the visible list
-	// if we're building a debug version.
-	if (name == std::string(MAINGRID))
+	else if(mGridChoice < GRID_INFO_OTHER)
 	{
-		grid[GRID_SLURL_BASE] = MAIN_GRID_SLURL_BASE;		
-		grid[GRID_IS_FAVORITE_VALUE] = TRUE;		
+		return gGridInfo[mGridChoice].mLabel;
 	}
-	else
-	{
-		grid[GRID_SLURL_BASE] = llformat(SYSTEM_GRID_SLURL_BASE, label.c_str());		
-	}
-	addGrid(grid);
+
+	return mGridName;
 }
 
-// return a list of grid name -> grid label mappings for UI purposes
-std::map<std::string, std::string> LLGridManager::getKnownGrids(bool favorite_only)
+std::string LLViewerLogin::getKnownGridLabel(EGridInfo grid_index) const
 {
-	std::map<std::string, std::string> result;
-	for(LLSD::map_iterator grid_iter = mGridList.beginMap();
-		grid_iter != mGridList.endMap();
-		grid_iter++) 
+	if(grid_index > GRID_INFO_NONE && grid_index < GRID_INFO_OTHER)
 	{
-		if(!favorite_only || grid_iter->second.has(GRID_IS_FAVORITE_VALUE))
-		{
-			result[grid_iter->first] = grid_iter->second[GRID_LABEL_VALUE].asString();
-		}
+		return gGridInfo[grid_index].mLabel;
 	}
-
-	return result;
+	return gGridInfo[GRID_INFO_NONE].mLabel;
 }
 
-void LLGridManager::setGridChoice(const std::string& grid)
+void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const
 {
-	// Set the grid choice based on a string.
-	// The string can be:
-	// - a grid label from the gGridInfo table 
-	// - a hostname
-	// - an ip address
-
-	// loop through.  We could do just a hash lookup but we also want to match
-	// on label
-	for(LLSD::map_iterator grid_iter = mGridList.beginMap();
-		grid_iter != mGridList.endMap();
-		grid_iter++) 
+	// return the login uri set on the command line.
+	LLControlVariable* c = gSavedSettings.getControl("CmdLineLoginURI");
+	if(c)
 	{
-		if((grid == grid_iter->first) || 
-		   (grid == grid_iter->second[GRID_LABEL_VALUE].asString()))
+		LLSD v = c->getValue();
+		if(v.isArray())
 		{
-			mGrid = grid_iter->second[GRID_VALUE].asString();
-			gSavedSettings.setString("CurrentGrid", grid_iter->second[GRID_VALUE]);			
-			return; 
-
+			for(LLSD::array_const_iterator itr = v.beginArray();
+				itr != v.endArray(); ++itr)
+			{
+				std::string uri = itr->asString();
+				if(!uri.empty())
+				{
+					uris.push_back(uri);
+				}
+			}
+		}
+		else
+		{
+			std::string uri = v.asString();
+			if(!uri.empty())
+			{
+				uris.push_back(uri);
+			}
 		}
 	}
-	LLSD grid_data = LLSD::emptyMap();
-	grid_data[GRID_VALUE] = grid;
-	addGrid(grid_data);
-	mGrid = grid;
-	gSavedSettings.setString("CurrentGrid", grid);
-}
 
-std::string LLGridManager::getGridByLabel( const std::string &grid_label)
-{
-	for(LLSD::map_iterator grid_iter = mGridList.beginMap();
-		grid_iter != mGridList.endMap();
-		grid_iter++) 
+	// If there was no command line uri...
+	if(uris.empty())
 	{
-		if (grid_iter->second.has(GRID_LABEL_VALUE) && (grid_iter->second[GRID_LABEL_VALUE].asString() == grid_label))
+		// If its a known grid choice, get the uri from the table,
+		// else try the grid name.
+		if(mGridChoice > GRID_INFO_NONE && mGridChoice < GRID_INFO_OTHER)
+		{
+			uris.push_back(gGridInfo[mGridChoice].mLoginURI);
+		}
+		else
 		{
-			return grid_iter->first;
+			uris.push_back(mGridName);
 		}
 	}
-	return std::string();
 }
 
-void LLGridManager::getLoginURIs(std::vector<std::string>& uris)
+std::string LLViewerLogin::getHelperURI() const
 {
-	uris.clear();
-	for (LLSD::array_iterator llsd_uri = mGridList[mGrid][GRID_LOGIN_URI_VALUE].beginArray();
-		 llsd_uri != mGridList[mGrid][GRID_LOGIN_URI_VALUE].endArray();
-		 llsd_uri++)
+	std::string helper_uri = gSavedSettings.getString("CmdLineHelperURI");
+	if (helper_uri.empty())
 	{
-		uris.push_back(llsd_uri->asString());
+		// grab URI from selected grid
+		if(mGridChoice > GRID_INFO_NONE && mGridChoice < GRID_INFO_OTHER)
+		{
+			helper_uri = gGridInfo[mGridChoice].mHelperURI;
+		}
+
+		if (helper_uri.empty())
+		{
+			// what do we do with unnamed/miscellaneous grids?
+			// for now, operations that rely on the helper URI (currency/land purchasing) will fail
+		}
 	}
+	return helper_uri;
 }
 
-bool LLGridManager::isInProductionGrid()
+bool LLViewerLogin::isInProductionGrid()
 {
 	// *NOTE:Mani This used to compare GRID_INFO_AGNI to gGridChoice,
 	// but it seems that loginURI trumps that.
 	std::vector<std::string> uris;
 	getLoginURIs(uris);
-	if (uris.size() < 1)
-	{
-		return 1;
-	}
 	LLStringUtil::toLower(uris[0]);
 	if((uris[0].find("agni") != std::string::npos))
 	{
@@ -513,51 +339,3 @@ bool LLGridManager::isInProductionGrid()
 
 	return false;
 }
-
-void LLGridManager::saveFavorites()
-{
-	// filter out just those marked as favorites
-	LLSD output_grid_list = LLSD::emptyMap();
-	for(LLSD::map_iterator grid_iter = mGridList.beginMap();
-		grid_iter != mGridList.endMap();
-		grid_iter++)
-	{
-		if(grid_iter->second.has(GRID_IS_FAVORITE_VALUE))
-		{
-			output_grid_list[grid_iter->first] = grid_iter->second;
-		}
-	}       
-	llofstream llsd_xml;
-	llsd_xml.open( mGridFile.c_str(), std::ios::out | std::ios::binary);	
-	LLSDSerialize::toPrettyXML(output_grid_list, llsd_xml);
-	llsd_xml.close();
-}
-
-
-// build a slurl for the given region within the selected grid
-std::string LLGridManager::getSLURLBase(const std::string& grid)
-{
-	std::string grid_base;
-	if(mGridList.has(grid) && mGridList[grid].has(GRID_SLURL_BASE))
-	{
-		return mGridList[grid][GRID_SLURL_BASE].asString();
-	}
-	else
-	{
-		return  llformat(DEFAULT_SLURL_BASE, grid.c_str());
-	}
-}
-
-// build a slurl for the given region within the selected grid
-std::string LLGridManager::getAppSLURLBase(const std::string& grid)
-{
-	std::string grid_base;
-	if(mGridList.has(grid) && mGridList[grid].has(GRID_APP_SLURL_BASE))
-	{
-	  return mGridList[grid][GRID_APP_SLURL_BASE].asString();
-	}
-	else
-	{
-	  return  llformat(DEFAULT_APP_SLURL_BASE, grid.c_str());
-	}
-}
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 46f21bf20f56091e7b80b11c9d6ff625144cc601..edae6dc47b56b87f1770269bf2fde8b61261de56 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -5,7 +5,7 @@
  *
  * $LicenseInfo:firstyear=2006&license=viewergpl$
  * 
- * Copyright (c) 2006-2010, Linden Research, Inc.
+ * 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
@@ -13,12 +13,13 @@
  * ("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://secondlife.com/developers/opensource/gplv2
+ * 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://secondlife.com/developers/opensource/flossexception
+ * 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,
@@ -32,136 +33,83 @@
 
 #ifndef LL_LLVIEWERNETWORK_H
 #define LL_LLVIEWERNETWORK_H
-                                                                                                       
-extern const char* DEFAULT_LOGIN_PAGE;
-      
-#define GRID_VALUE "name"
-#define GRID_LABEL_VALUE "label"
-#define GRID_ID_VALUE "grid_login_id"
-#define GRID_LOGIN_URI_VALUE "login_uri"
-#define GRID_HELPER_URI_VALUE "helper_uri"
-#define GRID_LOGIN_PAGE_VALUE "login_page"
-#define GRID_IS_SYSTEM_GRID_VALUE "system_grid"
-#define GRID_IS_FAVORITE_VALUE "favorite"
-#define GRID_LOGIN_CREDENTIAL_PAGE_TYPE_VALUE "credential_type"
-#define GRID_LOGIN_CREDENTIAL_PAGE_TYPE_AGENT "agent"
-#define GRID_LOGIN_CREDENTIAL_PAGE_TYPE_ACCOUNT "account"
-#define MAINGRID "util.agni.lindenlab.com"
 
-// defines slurl formats associated with various grids.
-// we need to continue to support existing forms, as slurls
-// are shared between viewers that may not understand newer
-// forms.
-#define GRID_SLURL_BASE "slurl_base"
-#define GRID_APP_SLURL_BASE "app_slurl_base"
+#include <boost/scoped_ptr.hpp>
 
-class LLInvalidGridName
+class LLHost;
+class LLLogin;
+
+enum EGridInfo
 {
-public:
-	LLInvalidGridName(std::string grid) : mGrid(grid)
-	{
-	}
-protected:
-	std::string mGrid;
+	GRID_INFO_NONE,
+	GRID_INFO_ADITI,
+	GRID_INFO_AGNI,
+	GRID_INFO_ARUNA,
+	GRID_INFO_BHARATI,
+	GRID_INFO_CHANDRA,
+	GRID_INFO_DAMBALLAH,
+	GRID_INFO_DANU,
+	GRID_INFO_DURGA,
+	GRID_INFO_GANGA,
+	GRID_INFO_MITRA,
+	GRID_INFO_MOHINI,
+	GRID_INFO_NANDI,
+	GRID_INFO_PARVATI,
+	GRID_INFO_RADHA,
+	GRID_INFO_RAVI,
+	GRID_INFO_SIVA,
+	GRID_INFO_SHAKTI,
+	GRID_INFO_SKANDA,
+	GRID_INFO_SOMA,
+	GRID_INFO_UMA,
+	GRID_INFO_VAAK,
+	GRID_INFO_YAMI,
+	GRID_INFO_LOCAL,
+	GRID_INFO_OTHER, // IP address set via command line option
+	GRID_INFO_COUNT
 };
 
-
 /**
- * @brief A class to manage the grids available to the viewer
- * including persistance.  This class also maintains the currently
- * selected grid.
+ * @brief A class to manage the viewer's login state.
  * 
  **/
-class LLGridManager : public LLSingleton<LLGridManager>
+class LLViewerLogin : public LLSingleton<LLViewerLogin>
 {
 public:
-	
-	// when the grid manager is instantiated, the default grids are automatically
-	// loaded, and the grids favorites list is loaded from the xml file.
-	LLGridManager(const std::string& grid_file);
-	LLGridManager();
-	~LLGridManager();
-	
-	void initialize(const std::string& grid_file);
-	// grid list management
-	
-	// add a grid to the list of grids
-	void addGrid(LLSD& grid_info);	
+	LLViewerLogin();
+	~LLViewerLogin();
 
-	// retrieve a map of grid-name <-> label
-	// by default only return the user visible grids
-	std::map<std::string, std::string> getKnownGrids(bool favorites_only=FALSE);
-	
-	LLSD getGridInfo(const std::string& grid)
-	{
-		if(mGridList.has(grid))
-		{
-			return mGridList[grid];
-		}
-		else
-		{
-			return LLSD();
-		}
-	}
-	
-	// current grid management
+	void setGridChoice(EGridInfo grid);
+	void setGridChoice(const std::string& grid_name);
+	void resetURIs();
 
-	// select a given grid as the current grid.  If the grid
-	// is not a known grid, then it's assumed to be a dns name for the
-	// grid, and the various URIs will be automatically generated.
-	void setGridChoice(const std::string& grid);
-	
-	
-	std::string getGridLabel() { return mGridList[mGrid][GRID_LABEL_VALUE]; } 	
-	std::string getGrid() const { return mGrid; }
-	void getLoginURIs(std::vector<std::string>& uris);
-	std::string getHelperURI() {return mGridList[mGrid][GRID_HELPER_URI_VALUE];}
-	std::string getLoginPage() {return mGridList[mGrid][GRID_LOGIN_PAGE_VALUE];}
-	std::string getGridLoginID() { return mGridList[mGrid][GRID_ID_VALUE]; }	
-	std::string getLoginPage(const std::string& grid) { return mGridList[grid][GRID_LOGIN_PAGE_VALUE]; }
-	
-	// build a slurl for the given region within the selected grid
-	std::string getSLURLBase(const std::string& grid);
-	std::string getSLURLBase() { return getSLURLBase(mGrid); }
-	
-	std::string getAppSLURLBase(const std::string& grid);
-	std::string getAppSLURLBase() { return getAppSLURLBase(mGrid); }	
-	
-	LLSD getGridInfo() { return mGridList[mGrid]; }
-	
-	std::string getGridByLabel( const std::string &grid_label);
-	
-	bool isSystemGrid(const std::string& grid) 
-	{ 
-		return mGridList.has(grid) &&
-		      mGridList[grid].has(GRID_IS_SYSTEM_GRID_VALUE) && 
-	           mGridList[grid][GRID_IS_SYSTEM_GRID_VALUE].asBoolean(); 
-	}
-	bool isSystemGrid() { return isSystemGrid(mGrid); }
-	// Mark this grid as a favorite that should be persisited on 'save'
-	// this is currently used to persist a grid after a successful login
-	void setFavorite() { mGridList[mGrid][GRID_IS_FAVORITE_VALUE] = TRUE; }
-	
-	bool isInProductionGrid();
-	void saveFavorites();
-	void clearFavorites();
+	/**
+	* @brief Get the enumeration of the grid choice.
+	* Should only return values > 0 && < GRID_INFO_COUNT
+	**/
+	EGridInfo getGridChoice() const;
 
-protected:
+	/**
+	* @brief Get a readable label for the grid choice.
+	* Returns the readable name for the grid choice. 
+	* If the grid is 'other', returns something
+	* the string used to specifiy the grid.
+	**/
+	std::string getGridLabel() const; 
+
+	std::string getKnownGridLabel(EGridInfo grid_index) const; 
+
+	void getLoginURIs(std::vector<std::string>& uris) const;
+	std::string getHelperURI() const;
+
+	bool isInProductionGrid();
 
-	// helper function for adding the predefined grids
-	void addSystemGrid(const std::string& label, 
-					   const std::string& name, 
-					   const std::string& login, 
-					   const std::string& helper,
-					   const std::string& login_page,
-					   const std::string& login_id = "");	
-	
-	
-	std::string mGrid;
-	std::string mGridFile;
-	LLSD mGridList;
+private:
+	EGridInfo mGridChoice;
+	std::string mGridName;
 };
 
 const S32 MAC_ADDRESS_BYTES = 6;
+extern unsigned char gMACAddress[MAC_ADDRESS_BYTES];		/* Flawfinder: ignore */
 
 #endif
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index e6d14079c91ca94e078e83a101283081c604ccb3..8860b734bbaed200f06ba63d781986212985460d 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -4726,7 +4726,7 @@ BOOL LLViewerObject::permYouOwner() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid()
+		if (!LLViewerLogin::getInstance()->isInProductionGrid()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
@@ -4763,7 +4763,7 @@ BOOL LLViewerObject::permOwnerModify() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid()
+		if (!LLViewerLogin::getInstance()->isInProductionGrid()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 	{
 			return TRUE;
@@ -4787,7 +4787,7 @@ BOOL LLViewerObject::permModify() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid()
+		if (!LLViewerLogin::getInstance()->isInProductionGrid()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 	{
 			return TRUE;
@@ -4811,7 +4811,7 @@ BOOL LLViewerObject::permCopy() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid()
+		if (!LLViewerLogin::getInstance()->isInProductionGrid()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
@@ -4835,7 +4835,7 @@ BOOL LLViewerObject::permMove() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid()
+		if (!LLViewerLogin::getInstance()->isInProductionGrid()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
@@ -4859,7 +4859,7 @@ BOOL LLViewerObject::permTransfer() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid()
+		if (!LLViewerLogin::getInstance()->isInProductionGrid()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index bdc34d0f18dd310f20d69ca1d8dc5c745c85fd39..b7c265be59722502745d63ede413a6a1c5b5f5da 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -768,11 +768,9 @@ void send_stats()
 	system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();
 	system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
 	system["cpu"] = gSysCPU.getCPUString();
-	unsigned char MACAddress[MAC_ADDRESS_BYTES];
-	LLUUID::getNodeID(MACAddress);
 	std::string macAddressString = llformat("%02x-%02x-%02x-%02x-%02x-%02x",
-											MACAddress[0],MACAddress[1],MACAddress[2],
-											MACAddress[3],MACAddress[4],MACAddress[5]);
+											gMACAddress[0],gMACAddress[1],gMACAddress[2],
+											gMACAddress[3],gMACAddress[4],gMACAddress[5]);
 	system["mac_address"] = macAddressString;
 	system["serial_number"] = LLAppViewer::instance()->getSerialNumber();
 	std::string gpu_desc = llformat(
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 4c6a02db87cbd9b0de8e49fe1f4cbc397352b0ae..ae3f680cbfc3b122c4d05397cda4fbafd89e2335 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -85,6 +85,7 @@
 #include "lltooltip.h"
 #include "llmediaentry.h"
 #include "llurldispatcher.h"
+#include "llurlsimstring.h"
 
 // newview includes
 #include "llagent.h"
@@ -798,7 +799,7 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK m
 BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
 	BOOL down = TRUE;
-	LLVoiceClient::getInstance()->middleMouseState(true);
+	gVoiceClient->middleMouseState(true);
  	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
   
   	// Always handled as far as the OS is concerned.
@@ -825,15 +826,20 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
 					
 				if (slurl_dnd_enabled)
 				{
-					LLSLURL dropped_slurl(data);
-					if(dropped_slurl.isSpatial())
+					
+					// special case SLURLs
+					// isValidSLURL() call was added here to make sure that dragged SLURL is valid (EXT-4964)
+					if ( LLSLURL::isSLURL( data ) && LLSLURL::isValidSLURL( data ) )
 					{
 						if (drop)
 						{
-							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), NULL, true );
-							return LLWindowCallbacks::DND_MOVE;
+							LLURLDispatcher::dispatch( data, NULL, true );
+							LLURLSimString::setStringRaw( LLSLURL::stripProtocol( data ) );
+							LLPanelLogin::refreshLocation( true );
+							LLPanelLogin::updateLocationUI();
 						}
-					}
+						return LLWindowCallbacks::DND_MOVE;
+					};
 				}
 
 				if (prim_media_dnd_enabled)
@@ -951,7 +957,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
 BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
 	BOOL down = FALSE;
-	LLVoiceClient::getInstance()->middleMouseState(false);
+	gVoiceClient->middleMouseState(false);
  	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
   
   	// Always handled as far as the OS is concerned.
@@ -1068,7 +1074,7 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
 BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
 {
 	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyDown(key, mask);
+	gVoiceClient->keyDown(key, mask);
 	
 	if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
 	{
@@ -1090,7 +1096,7 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
 BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
 {
 	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyUp(key, mask);
+	gVoiceClient->keyUp(key, mask);
 
 	return FALSE;
 }
@@ -1949,7 +1955,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible )
 
 		// ...and set the menu color appropriately.
 		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
-			LLGridManager::getInstance()->isInProductionGrid());
+			LLViewerLogin::getInstance()->isInProductionGrid());
 	}
         
 	if ( gStatusBar )
@@ -1970,15 +1976,15 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
     LLSD args;
     LLColor4 new_bg_color;
 
-    if(god_mode && LLGridManager::getInstance()->isInProductionGrid())
+    if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid())
     {
         new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
     }
-    else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid())
+    else if(god_mode && !LLViewerLogin::getInstance()->isInProductionGrid())
     {
         new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
     }
-    else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid())
+    else if(!god_mode && !LLViewerLogin::getInstance()->isInProductionGrid())
     {
         new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
     }
@@ -2194,6 +2200,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
 		}
 		return TRUE;
 	}
+
 	// hidden edit menu for cut/copy/paste
 	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))
 	{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 540cb47710e7bb690b2ea4ad1f6e6d4df64ed649..0ce8894872e9aebb244707aa483492689860ce8f 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1266,7 +1266,7 @@ void LLVOAvatar::initInstance(void)
 	
 	//VTPause();  // VTune
 	
-	mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) );
+	mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
 }
 
 const LLVector3 LLVOAvatar::getRenderPosition() const
@@ -2197,8 +2197,8 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 	}
 
 	static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false);
-	bool voice_enabled = (visualizers_in_calls || LLVoiceClient::getInstance()->inProximalChannel()) &&
-						 LLVoiceClient::getInstance()->getVoiceEnabled(mID);
+	bool voice_enabled = (visualizers_in_calls || gVoiceClient->inProximalChannel()) &&
+						 gVoiceClient->getVoiceEnabled(mID);
 
 	idleUpdateVoiceVisualizer( voice_enabled );
 	idleUpdateMisc( detailed_update );
@@ -2261,7 +2261,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 		// Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
 		// "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking. 
 		//-----------------------------------------------------------------------------------------------------------------
-		if (LLVoiceClient::getInstance()->getIsSpeaking( mID ))
+		if (gVoiceClient->getIsSpeaking( mID ))
 		{		
 			if (!mVoiceVisualizer->getCurrentlySpeaking())
 			{
@@ -2270,7 +2270,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 				//printf( "gAwayTimer.reset();\n" );
 			}
 			
-			mVoiceVisualizer->setSpeakingAmplitude( LLVoiceClient::getInstance()->getCurrentPower( mID ) );
+			mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
 			
 			if( isSelf() )
 			{
@@ -2499,7 +2499,7 @@ F32 LLVOAvatar::calcMorphAmount()
 void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
 {
 	// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
-	if ( voice_enabled && (LLVoiceClient::getInstance()->lipSyncEnabled()) && LLVoiceClient::getInstance()->getIsSpeaking( mID ) )
+	if ( voice_enabled && (gVoiceClient->lipSyncEnabled()) && gVoiceClient->getIsSpeaking( mID ) )
 	{
 		F32 ooh_morph_amount = 0.0f;
 		F32 aah_morph_amount = 0.0f;
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 338bc12f047573973b1a92bf0ce75ebfa3b9e022..fac7fa6a18564923ce11f2f4907f88ffed1e38a2 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -72,9 +72,9 @@ class LLVoiceCallCapResponder : public LLHTTPClient::Responder
 
 void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
 {
-	LL_WARNS("Voice") << "LLVoiceCallCapResponder::error("
+	llwarns << "LLVoiceCallCapResponder::error("
 		<< status << ": " << reason << ")"
-		<< LL_ENDL;
+		<< llendl;
 	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
 	if ( channelp )
 	{
@@ -104,8 +104,8 @@ void LLVoiceCallCapResponder::result(const LLSD& content)
 		LLSD::map_const_iterator iter;
 		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 		{
-			LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got " 
-				<< iter->first << LL_ENDL;
+			llinfos << "LLVoiceCallCapResponder::result got " 
+				<< iter->first << llendl;
 		}
 
 		channelp->setChannelInfo(
@@ -131,8 +131,10 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess
 	{
 		// a voice channel already exists for this session id, so this instance will be orphaned
 		// the end result should simply be the failure to make voice calls
-		LL_WARNS("Voice") << "Duplicate voice channels registered for session_id " << session_id << LL_ENDL;
+		llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
 	}
+
+	LLVoiceClient::getInstance()->addObserver(this);
 }
 
 LLVoiceChannel::~LLVoiceChannel()
@@ -143,7 +145,7 @@ LLVoiceChannel::~LLVoiceChannel()
 	// later in other destructors anyway). EXT-5524
 	if(LLVoiceClient::instanceExists())
 	{
-		LLVoiceClient::getInstance()->removeObserver(this);
+		gVoiceClient->removeObserver(this);
 	}
 	
 	sVoiceChannelMap.erase(mSessionID);
@@ -163,13 +165,13 @@ void LLVoiceChannel::setChannelInfo(
 		if (mURI.empty())
 		{
 			LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
-			LL_WARNS("Voice") << "Received empty URI for channel " << mSessionName << LL_ENDL;
+			llwarns << "Received empty URI for channel " << mSessionName << llendl;
 			deactivate();
 		}
 		else if (mCredentials.empty())
 		{
 			LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
-			LL_WARNS("Voice") << "Received empty credentials for channel " << mSessionName << LL_ENDL;
+			llwarns << "Received empty credentials for channel " << mSessionName << llendl;
 			deactivate();
 		}
 		else
@@ -284,14 +286,13 @@ void LLVoiceChannel::deactivate()
 		//Default mic is OFF when leaving voice calls
 		if (gSavedSettings.getBOOL("AutoDisengageMic") && 
 			sCurrentVoiceChannel == this &&
-			LLVoiceClient::getInstance()->getUserPTTState())
+			gVoiceClient->getUserPTTState())
 		{
 			gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
-			LLVoiceClient::getInstance()->inputUserControlState(true);
+			gVoiceClient->inputUserControlState(true);
 		}
 	}
-	LLVoiceClient::getInstance()->removeObserver(this);
-	
+
 	if (sCurrentVoiceChannel == this)
 	{
 		// default channel is proximal channel
@@ -331,9 +332,7 @@ void LLVoiceChannel::activate()
 	{
 		setState(STATE_CALL_STARTED);
 	}
-	
-	LLVoiceClient::getInstance()->addObserver(this);
-	
+
 	//do not send earlier, channel should be initialized, should not be in STATE_NO_CHANNEL_INFO state
 	sCurrentVoiceChannelChangedSignal(this->mSessionID);
 }
@@ -375,11 +374,6 @@ LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
 	}
 }
 
-LLVoiceChannel* LLVoiceChannel::getCurrentVoiceChannel()
-{
-	return sCurrentVoiceChannel;
-}
-
 void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
 {
 	sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
@@ -431,6 +425,7 @@ void LLVoiceChannel::initClass()
 	sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
 }
 
+
 //static 
 void LLVoiceChannel::suspend()
 {
@@ -446,7 +441,7 @@ void LLVoiceChannel::resume()
 {
 	if (sSuspended)
 	{
-		if (LLVoiceClient::getInstance()->voiceEnabled())
+		if (gVoiceClient->voiceEnabled())
 		{
 			if (sSuspendedVoiceChannel)
 			{
@@ -516,9 +511,9 @@ void LLVoiceChannelGroup::activate()
 #endif
 
 		//Mic default state is OFF on initiating/joining Ad-Hoc/Group calls
-		if (LLVoiceClient::getInstance()->getUserPTTState() && LLVoiceClient::getInstance()->getPTTIsToggle())
+		if (gVoiceClient->getUserPTTState() && gVoiceClient->getPTTIsToggle())
 		{
-			LLVoiceClient::getInstance()->inputUserControlState(true);
+			gVoiceClient->inputUserControlState(true);
 		}
 		
 	}
@@ -565,7 +560,7 @@ void LLVoiceChannelGroup::setChannelInfo(
 		else
 		{
 			//*TODO: notify user
-			LL_WARNS("Voice") << "Received invalid credentials for channel " << mSessionName << LL_ENDL;
+			llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
 			deactivate();
 		}
 	}
@@ -664,6 +659,7 @@ void LLVoiceChannelGroup::setState(EState state)
 LLVoiceChannelProximal::LLVoiceChannelProximal() : 
 	LLVoiceChannel(LLUUID::null, LLStringUtil::null)
 {
+	activate();
 }
 
 BOOL LLVoiceChannelProximal::isActive()
@@ -675,13 +671,13 @@ void LLVoiceChannelProximal::activate()
 {
 	if (callStarted()) return;
 
-	if((LLVoiceChannel::sCurrentVoiceChannel != this) && (LLVoiceChannel::getState() == STATE_CONNECTED))
+	LLVoiceChannel::activate();
+
+	if (callStarted())
 	{
-		// we're connected to a non-spatial channel, so disconnect.
-		LLVoiceClient::getInstance()->leaveNonSpatialChannel();	
+		// this implicitly puts you back in the spatial channel
+		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
 	}
-	LLVoiceChannel::activate();
-	
 }
 
 void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
@@ -711,7 +707,7 @@ void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
 		return;
 	case STATUS_VOICE_DISABLED:
 		//skip showing "Voice not available at your current location" when agent voice is disabled (EXT-4749)
-		if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking())
+		if(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking())
 		{
 			//TODO: remove or redirect this call status notification
 //			LLCallInfoDialog::show("unavailable", mNotifyArgs);
@@ -771,7 +767,7 @@ LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string
 
 void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
 {
-	LL_INFOS("Voice") << "P2P CALL CHANNEL STATUS CHANGE: incoming=" << int(mReceivedCall) << " newstatus=" << LLVoiceClientStatusObserver::status2string(type) << " (mState=" << mState << ")" << LL_ENDL;
+	llinfos << "P2P CALL CHANNEL STATUS CHANGE: incoming=" << int(mReceivedCall) << " newstatus=" << LLVoiceClientStatusObserver::status2string(type) << " (mState=" << mState << ")" << llendl;
 
 	// status updates
 	switch(type)
@@ -845,9 +841,9 @@ void LLVoiceChannelP2P::activate()
 		LLRecentPeople::instance().add(mOtherUserID);
 
 		//Default mic is ON on initiating/joining P2P calls
-		if (!LLVoiceClient::getInstance()->getUserPTTState() && LLVoiceClient::getInstance()->getPTTIsToggle())
+		if (!gVoiceClient->getUserPTTState() && gVoiceClient->getPTTIsToggle())
 		{
-			LLVoiceClient::getInstance()->inputUserControlState(true);
+			gVoiceClient->inputUserControlState(true);
 		}
 	}
 }
@@ -910,7 +906,7 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s
 
 void LLVoiceChannelP2P::setState(EState state)
 {
-	LL_INFOS("Voice") << "P2P CALL STATE CHANGE: incoming=" << int(mReceivedCall) << " oldstate=" << mState << " newstate=" << state << LL_ENDL;
+	llinfos << "P2P CALL STATE CHANGE: incoming=" << int(mReceivedCall) << " oldstate=" << mState << " newstate=" << state << llendl;
 
 	if (mReceivedCall) // incoming call
 	{
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 573fab1f4f645bb51fb93a5a85de36f1fcf7ef82..941cccacc3ab9771ba29ad1a1568068c7c879d9e 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -98,8 +98,7 @@ class LLVoiceChannel : public LLVoiceClientStatusObserver
 
 	static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
 	static LLVoiceChannel* getChannelByURI(std::string uri);
-	static LLVoiceChannel* getCurrentVoiceChannel();
-	
+	static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
 	static void initClass();
 	
 	static void suspend();
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index e067754e3ea53408639ba125e0fb4f99c46f5689..2238acd64376a1402c602640bf21a71f3ed11d1a 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -1,6 +1,6 @@
  /** 
  * @file llvoiceclient.cpp
- * @brief Voice client delegation class implementation.
+ * @brief Implementation of LLVoiceClient class which is the interface to the voice client process.
  *
  * $LicenseInfo:firstyear=2001&license=viewergpl$
  * 
@@ -17,7 +17,8 @@
  * 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
+ * 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,
@@ -31,730 +32,7244 @@
 
 #include "llviewerprecompiledheaders.h"
 #include "llvoiceclient.h"
-#include "llviewercontrol.h"
-#include "llviewerwindow.h"
-#include "llvoicedw.h"
-#include "llvoicevivox.h"
-#include "llviewernetwork.h"
-#include "llhttpnode.h"
+
+#include <boost/tokenizer.hpp>
+
+// library includes
 #include "llnotificationsutil.h"
 #include "llsdserialize.h"
-#include "llui.h"
+#include "llsdutil.h"
+
+
+// project includes
+#include "llvoavatar.h"
+#include "llbufferstream.h"
+#include "llfile.h"
+#ifdef LL_STANDALONE
+# include "expat.h"
+#else
+# include "expat/expat.h"
+#endif
+#include "llcallbacklist.h"
+#include "llcallingcard.h"   // for LLFriendObserver
+#include "llviewerregion.h"
+#include "llviewernetwork.h"		// for gGridChoice
+#include "llbase64.h"
+#include "llviewercontrol.h"
+#include "llkeyboard.h"
+#include "llappviewer.h"	// for gDisconnected, gDisableVoice
+#include "llmutelist.h"  // to check for muted avatars
+#include "llagent.h"
+#include "llvoavatarself.h"
+#include "llcachename.h"
+#include "llimview.h" // for LLIMMgr
+#include "llparcel.h"
+#include "llviewerparcelmgr.h"
+//#include "llfirstuse.h"
+#include "llspeakers.h"
+#include "lltrans.h"
+#include "llviewerwindow.h"
+#include "llviewercamera.h"
+#include "llvoavatarself.h"
+#include "llvoicechannel.h"
+
+// for base64 decoding
+#include "apr_base64.h"
+
+// for SHA1 hash
+#include "apr_sha1.h"
+
+// for MD5 hash
+#include "llmd5.h"
+
+#define USE_SESSION_GROUPS 0
+
+static bool sConnectingToAgni = false;
+F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
+
+const F32 LLVoiceClient::VOLUME_MIN = 0.f;
+const F32 LLVoiceClient::VOLUME_DEFAULT = 0.5f;
+const F32 LLVoiceClient::VOLUME_MAX = 1.0f;
+
+const F32 VOLUME_SCALE_VIVOX = 0.01f;
+
+const F32 SPEAKING_TIMEOUT = 1.f;
+
+const int VOICE_MAJOR_VERSION = 1;
+const int VOICE_MINOR_VERSION = 0;
+
+LLVoiceClient *gVoiceClient = NULL;
+
+// Don't retry connecting to the daemon more frequently than this:
+const F32 CONNECT_THROTTLE_SECONDS = 1.0f;
+
+// Don't send positional updates more frequently than this:
+const F32 UPDATE_THROTTLE_SECONDS = 0.1f;
+
+const F32 LOGIN_RETRY_SECONDS = 10.0f;
+const int MAX_LOGIN_RETRIES = 12;
+
+// Defines the maximum number of times(in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine()
+// which is treated as normal. If this number is exceeded we suspect there is a problem with connection
+// to voice server (EXT-4313). When voice works correctly, there is from 1 to 15 times. 50 was chosen 
+// to make sure we don't make mistake when slight connection problems happen- situation when connection to server is 
+// blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability.
+const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50;
+
+static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str)
+{
+	LLMD5 md5_uuid;
+	md5_uuid.update((const unsigned char*)str.data(), str.size());
+	md5_uuid.finalize();
+	md5_uuid.raw_digest(uuid.mData);
+}
+
+static int scale_mic_volume(float volume)
+{
+	// incoming volume has the range [0.0 ... 2.0], with 1.0 as the default.
+	// Map it to Vivox levels as follows: 0.0 -> 30, 1.0 -> 50, 2.0 -> 70
+	return 30 + (int)(volume * 20.0f);
+}
+
+static int scale_speaker_volume(float volume)
+{
+	// incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
+	// Map it to Vivox levels as follows: 0.0 -> 30, 0.5 -> 50, 1.0 -> 70
+	return 30 + (int)(volume * 40.0f);
+}
+
+class LLViewerVoiceAccountProvisionResponder :
+	public LLHTTPClient::Responder
+{
+public:
+	LLViewerVoiceAccountProvisionResponder(int retries)
+	{
+		mRetries = retries;
+	}
+
+	virtual void error(U32 status, const std::string& reason)
+	{
+		if ( mRetries > 0 )
+		{
+			LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying.  status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
+			if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision(
+				mRetries - 1);
+		}
+		else
+		{
+			LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up).  status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
+			if ( gVoiceClient ) gVoiceClient->giveUp();
+		}
+	}
+
+	virtual void result(const LLSD& content)
+	{
+		if ( gVoiceClient )
+		{
+			std::string voice_sip_uri_hostname;
+			std::string voice_account_server_uri;
+			
+			LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+			
+			if(content.has("voice_sip_uri_hostname"))
+				voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
+			
+			// this key is actually misnamed -- it will be an entire URI, not just a hostname.
+			if(content.has("voice_account_server_name"))
+				voice_account_server_uri = content["voice_account_server_name"].asString();
+			
+			gVoiceClient->login(
+				content["username"].asString(),
+				content["password"].asString(),
+				voice_sip_uri_hostname,
+				voice_account_server_uri);
+		}
+	}
+
+private:
+	int mRetries;
+};
+
+/** 
+ * @class LLVivoxProtocolParser
+ * @brief This class helps construct new LLIOPipe specializations
+ * @see LLIOPipe
+ *
+ * THOROUGH_DESCRIPTION
+ */
+class LLVivoxProtocolParser : public LLIOPipe
+{
+	LOG_CLASS(LLVivoxProtocolParser);
+public:
+	LLVivoxProtocolParser();
+	virtual ~LLVivoxProtocolParser();
+
+protected:
+	/* @name LLIOPipe virtual implementations
+	 */
+	//@{
+	/** 
+	 * @brief Process the data in buffer
+	 */
+	virtual EStatus process_impl(
+		const LLChannelDescriptors& channels,
+		buffer_ptr_t& buffer,
+		bool& eos,
+		LLSD& context,
+		LLPumpIO* pump);
+	//@}
+	
+	std::string 	mInput;
+	
+	// Expat control members
+	XML_Parser		parser;
+	int				responseDepth;
+	bool			ignoringTags;
+	bool			isEvent;
+	int				ignoreDepth;
+
+	// Members for processing responses. The values are transient and only valid within a call to processResponse().
+	bool			squelchDebugOutput;
+	int				returnCode;
+	int				statusCode;
+	std::string		statusString;
+	std::string		requestId;
+	std::string		actionString;
+	std::string		connectorHandle;
+	std::string		versionID;
+	std::string		accountHandle;
+	std::string		sessionHandle;
+	std::string		sessionGroupHandle;
+	std::string		alias;
+	std::string		applicationString;
+
+	// Members for processing events. The values are transient and only valid within a call to processResponse().
+	std::string		eventTypeString;
+	int				state;
+	std::string		uriString;
+	bool			isChannel;
+	bool			incoming;
+	bool			enabled;
+	std::string		nameString;
+	std::string		audioMediaString;
+	std::string		displayNameString;
+	std::string		deviceString;
+	int				participantType;
+	bool			isLocallyMuted;
+	bool			isModeratorMuted;
+	bool			isSpeaking;
+	int				volume;
+	F32				energy;
+	std::string		messageHeader;
+	std::string		messageBody;
+	std::string		notificationType;
+	bool			hasText;
+	bool			hasAudio;
+	bool			hasVideo;
+	bool			terminated;
+	std::string		blockMask;
+	std::string		presenceOnly;
+	std::string		autoAcceptMask;
+	std::string		autoAddAsBuddy;
+	int				numberOfAliases;
+	std::string		subscriptionHandle;
+	std::string		subscriptionType;
+		
+
+	// Members for processing text between tags
+	std::string		textBuffer;
+	bool			accumulateText;
+	
+	void			reset();
+
+	void			processResponse(std::string tag);
+
+static void XMLCALL ExpatStartTag(void *data, const char *el, const char **attr);
+static void XMLCALL ExpatEndTag(void *data, const char *el);
+static void XMLCALL ExpatCharHandler(void *data, const XML_Char *s, int len);
+
+	void			StartTag(const char *tag, const char **attr);
+	void			EndTag(const char *tag);
+	void			CharData(const char *buffer, int length);
+	
+};
+
+LLVivoxProtocolParser::LLVivoxProtocolParser()
+{
+	parser = NULL;
+	parser = XML_ParserCreate(NULL);
+	
+	reset();
+}
+
+void LLVivoxProtocolParser::reset()
+{
+	responseDepth = 0;
+	ignoringTags = false;
+	accumulateText = false;
+	energy = 0.f;
+	hasText = false;
+	hasAudio = false;
+	hasVideo = false;
+	terminated = false;
+	ignoreDepth = 0;
+	isChannel = false;
+	incoming = false;
+	enabled = false;
+	isEvent = false;
+	isLocallyMuted = false;
+	isModeratorMuted = false;
+	isSpeaking = false;
+	participantType = 0;
+	squelchDebugOutput = false;
+	returnCode = -1;
+	state = 0;
+	statusCode = 0;
+	volume = 0;
+	textBuffer.clear();
+	alias.clear();
+	numberOfAliases = 0;
+	applicationString.clear();
+}
+
+//virtual 
+LLVivoxProtocolParser::~LLVivoxProtocolParser()
+{
+	if (parser)
+		XML_ParserFree(parser);
+}
+
+// virtual
+LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
+	const LLChannelDescriptors& channels,
+	buffer_ptr_t& buffer,
+	bool& eos,
+	LLSD& context,
+	LLPumpIO* pump)
+{
+	LLBufferStream istr(channels, buffer.get());
+	std::ostringstream ostr;
+	while (istr.good())
+	{
+		char buf[1024];
+		istr.read(buf, sizeof(buf));
+		mInput.append(buf, istr.gcount());
+	}
+	
+	// Look for input delimiter(s) in the input buffer.  If one is found, send the message to the xml parser.
+	int start = 0;
+	int delim;
+	while((delim = mInput.find("\n\n\n", start)) != std::string::npos)
+	{	
+		
+		// Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser)
+		reset();
+		
+		XML_ParserReset(parser, NULL);
+		XML_SetElementHandler(parser, ExpatStartTag, ExpatEndTag);
+		XML_SetCharacterDataHandler(parser, ExpatCharHandler);
+		XML_SetUserData(parser, this);	
+		XML_Parse(parser, mInput.data() + start, delim - start, false);
+		
+		// If this message isn't set to be squelched, output the raw XML received.
+		if(!squelchDebugOutput)
+		{
+			LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
+		}
+		
+		start = delim + 3;
+	}
+	
+	if(start != 0)
+		mInput = mInput.substr(start);
+
+	LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL;
+	
+	if(!gVoiceClient->mConnected)
+	{
+		// If voice has been disabled, we just want to close the socket.  This does so.
+		LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL;
+		return STATUS_STOP;
+	}
+	
+	return STATUS_OK;
+}
+
+void XMLCALL LLVivoxProtocolParser::ExpatStartTag(void *data, const char *el, const char **attr)
+{
+	if (data)
+	{
+		LLVivoxProtocolParser	*object = (LLVivoxProtocolParser*)data;
+		object->StartTag(el, attr);
+	}
+}
+
+// --------------------------------------------------------------------------------
+
+void XMLCALL LLVivoxProtocolParser::ExpatEndTag(void *data, const char *el)
+{
+	if (data)
+	{
+		LLVivoxProtocolParser	*object = (LLVivoxProtocolParser*)data;
+		object->EndTag(el);
+	}
+}
+
+// --------------------------------------------------------------------------------
+
+void XMLCALL LLVivoxProtocolParser::ExpatCharHandler(void *data, const XML_Char *s, int len)
+{
+	if (data)
+	{
+		LLVivoxProtocolParser	*object = (LLVivoxProtocolParser*)data;
+		object->CharData(s, len);
+	}
+}
+
+// --------------------------------------------------------------------------------
+
+
+void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
+{
+	// Reset the text accumulator. We shouldn't have strings that are inturrupted by new tags
+	textBuffer.clear();
+	// only accumulate text if we're not ignoring tags.
+	accumulateText = !ignoringTags;
+	
+	if (responseDepth == 0)
+	{	
+		isEvent = !stricmp("Event", tag);
+		
+		if (!stricmp("Response", tag) || isEvent)
+		{
+			// Grab the attributes
+			while (*attr)
+			{
+				const char	*key = *attr++;
+				const char	*value = *attr++;
+				
+				if (!stricmp("requestId", key))
+				{
+					requestId = value;
+				}
+				else if (!stricmp("action", key))
+				{
+					actionString = value;
+				}
+				else if (!stricmp("type", key))
+				{
+					eventTypeString = value;
+				}
+			}
+		}
+		LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")"  << LL_ENDL;
+	}
+	else
+	{
+		if (ignoringTags)
+		{
+			LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
+		}
+		else
+		{
+			LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")"  << LL_ENDL;
+	
+			// Ignore the InputXml stuff so we don't get confused
+			if (!stricmp("InputXml", tag))
+			{
+				ignoringTags = true;
+				ignoreDepth = responseDepth;
+				accumulateText = false;
+
+				LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
+			}
+			else if (!stricmp("CaptureDevices", tag))
+			{
+				gVoiceClient->clearCaptureDevices();
+			}
+			else if (!stricmp("RenderDevices", tag))
+			{
+				gVoiceClient->clearRenderDevices();
+			}
+			else if (!stricmp("CaptureDevice", tag))
+			{
+				deviceString.clear();
+			}
+			else if (!stricmp("RenderDevice", tag))
+			{
+				deviceString.clear();
+			}
+			else if (!stricmp("Buddies", tag))
+			{
+				gVoiceClient->deleteAllBuddies();
+			}
+			else if (!stricmp("BlockRules", tag))
+			{
+				gVoiceClient->deleteAllBlockRules();
+			}
+			else if (!stricmp("AutoAcceptRules", tag))
+			{
+				gVoiceClient->deleteAllAutoAcceptRules();
+			}
+			
+		}
+	}
+	responseDepth++;
+}
+
+// --------------------------------------------------------------------------------
+
+void LLVivoxProtocolParser::EndTag(const char *tag)
+{
+	const std::string& string = textBuffer;
+
+	responseDepth--;
+
+	if (ignoringTags)
+	{
+		if (ignoreDepth == responseDepth)
+		{
+			LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL;
+			ignoringTags = false;
+		}
+		else
+		{
+			LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
+		}
+	}
+	
+	if (!ignoringTags)
+	{
+		LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
+
+		// Closing a tag. Finalize the text we've accumulated and reset
+		if (!stricmp("ReturnCode", tag))
+			returnCode = strtol(string.c_str(), NULL, 10);
+		else if (!stricmp("SessionHandle", tag))
+			sessionHandle = string;
+		else if (!stricmp("SessionGroupHandle", tag))
+			sessionGroupHandle = string;
+		else if (!stricmp("StatusCode", tag))
+			statusCode = strtol(string.c_str(), NULL, 10);
+		else if (!stricmp("StatusString", tag))
+			statusString = string;
+		else if (!stricmp("ParticipantURI", tag))
+			uriString = string;
+		else if (!stricmp("Volume", tag))
+			volume = strtol(string.c_str(), NULL, 10);
+		else if (!stricmp("Energy", tag))
+			energy = (F32)strtod(string.c_str(), NULL);
+		else if (!stricmp("IsModeratorMuted", tag))
+			isModeratorMuted = !stricmp(string.c_str(), "true");
+		else if (!stricmp("IsSpeaking", tag))
+			isSpeaking = !stricmp(string.c_str(), "true");
+		else if (!stricmp("Alias", tag))
+			alias = string;
+		else if (!stricmp("NumberOfAliases", tag))
+			numberOfAliases = strtol(string.c_str(), NULL, 10);
+		else if (!stricmp("Application", tag))
+			applicationString = string;
+		else if (!stricmp("ConnectorHandle", tag))
+			connectorHandle = string;
+		else if (!stricmp("VersionID", tag))
+			versionID = string;
+		else if (!stricmp("AccountHandle", tag))
+			accountHandle = string;
+		else if (!stricmp("State", tag))
+			state = strtol(string.c_str(), NULL, 10);
+		else if (!stricmp("URI", tag))
+			uriString = string;
+		else if (!stricmp("IsChannel", tag))
+			isChannel = !stricmp(string.c_str(), "true");
+		else if (!stricmp("Incoming", tag))
+			incoming = !stricmp(string.c_str(), "true");
+		else if (!stricmp("Enabled", tag))
+			enabled = !stricmp(string.c_str(), "true");
+		else if (!stricmp("Name", tag))
+			nameString = string;
+		else if (!stricmp("AudioMedia", tag))
+			audioMediaString = string;
+		else if (!stricmp("ChannelName", tag))
+			nameString = string;
+		else if (!stricmp("DisplayName", tag))
+			displayNameString = string;
+		else if (!stricmp("Device", tag))
+			deviceString = string;
+		else if (!stricmp("AccountName", tag))
+			nameString = string;
+		else if (!stricmp("ParticipantType", tag))
+			participantType = strtol(string.c_str(), NULL, 10);
+		else if (!stricmp("IsLocallyMuted", tag))
+			isLocallyMuted = !stricmp(string.c_str(), "true");
+		else if (!stricmp("MicEnergy", tag))
+			energy = (F32)strtod(string.c_str(), NULL);
+		else if (!stricmp("ChannelName", tag))
+			nameString = string;
+		else if (!stricmp("ChannelURI", tag))
+			uriString = string;
+		else if (!stricmp("BuddyURI", tag))
+			uriString = string;
+		else if (!stricmp("Presence", tag))
+			statusString = string;
+		else if (!stricmp("CaptureDevice", tag))
+		{
+			gVoiceClient->addCaptureDevice(deviceString);
+		}
+		else if (!stricmp("RenderDevice", tag))
+		{
+			gVoiceClient->addRenderDevice(deviceString);
+		}
+		else if (!stricmp("Buddy", tag))
+		{
+			gVoiceClient->processBuddyListEntry(uriString, displayNameString);
+		}
+		else if (!stricmp("BlockRule", tag))
+		{
+			gVoiceClient->addBlockRule(blockMask, presenceOnly);
+		}
+		else if (!stricmp("BlockMask", tag))
+			blockMask = string;
+		else if (!stricmp("PresenceOnly", tag))
+			presenceOnly = string;
+		else if (!stricmp("AutoAcceptRule", tag))
+		{
+			gVoiceClient->addAutoAcceptRule(autoAcceptMask, autoAddAsBuddy);
+		}
+		else if (!stricmp("AutoAcceptMask", tag))
+			autoAcceptMask = string;
+		else if (!stricmp("AutoAddAsBuddy", tag))
+			autoAddAsBuddy = string;
+		else if (!stricmp("MessageHeader", tag))
+			messageHeader = string;
+		else if (!stricmp("MessageBody", tag))
+			messageBody = string;
+		else if (!stricmp("NotificationType", tag))
+			notificationType = string;
+		else if (!stricmp("HasText", tag))
+			hasText = !stricmp(string.c_str(), "true");
+		else if (!stricmp("HasAudio", tag))
+			hasAudio = !stricmp(string.c_str(), "true");
+		else if (!stricmp("HasVideo", tag))
+			hasVideo = !stricmp(string.c_str(), "true");
+		else if (!stricmp("Terminated", tag))
+			terminated = !stricmp(string.c_str(), "true");
+		else if (!stricmp("SubscriptionHandle", tag))
+			subscriptionHandle = string;
+		else if (!stricmp("SubscriptionType", tag))
+			subscriptionType = string;
+		
+		textBuffer.clear();
+		accumulateText= false;
+		
+		if (responseDepth == 0)
+		{
+			// We finished all of the XML, process the data
+			processResponse(tag);
+		}
+	}
+}
+
+// --------------------------------------------------------------------------------
+
+void LLVivoxProtocolParser::CharData(const char *buffer, int length)
+{
+	/*
+		This method is called for anything that isn't a tag, which can be text you
+		want that lies between tags, and a lot of stuff you don't want like file formatting
+		(tabs, spaces, CR/LF, etc).
+		
+		Only copy text if we are in accumulate mode...
+	*/
+	if (accumulateText)
+		textBuffer.append(buffer, length);
+}
+
+// --------------------------------------------------------------------------------
+
+void LLVivoxProtocolParser::processResponse(std::string tag)
+{
+	LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL;
+
+	// SLIM SDK: the SDK now returns a statusCode of "200" (OK) for success.  This is a change vs. previous SDKs.
+	// According to Mike S., "The actual API convention is that responses with return codes of 0 are successful, regardless of the status code returned",
+	// so I believe this will give correct behavior.
+	
+	if(returnCode == 0)
+		statusCode = 0;
+		
+	if (isEvent)
+	{
+		const char *eventTypeCstr = eventTypeString.c_str();
+		if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
+		{
+			gVoiceClient->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state);
+		}
+		else if (!stricmp(eventTypeCstr, "SessionAddedEvent"))
+		{
+			/*
+			<Event type="SessionAddedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
+				<Uri>sip:confctl-1408789@bhr.vivox.com</Uri>
+				<IsChannel>true</IsChannel>
+				<Incoming>false</Incoming>
+				<ChannelName />
+			</Event>
+			*/
+			gVoiceClient->sessionAddedEvent(uriString, alias, sessionHandle, sessionGroupHandle, isChannel, incoming, nameString, applicationString);
+		}
+		else if (!stricmp(eventTypeCstr, "SessionRemovedEvent"))
+		{
+			gVoiceClient->sessionRemovedEvent(sessionHandle, sessionGroupHandle);
+		}
+		else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent"))
+		{
+			gVoiceClient->sessionGroupAddedEvent(sessionGroupHandle);
+		}
+		else if (!stricmp(eventTypeCstr, "MediaStreamUpdatedEvent"))
+		{
+			/*
+			<Event type="MediaStreamUpdatedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
+				<StatusCode>200</StatusCode>
+				<StatusString>OK</StatusString>
+				<State>2</State>
+				<Incoming>false</Incoming>
+			</Event>
+			*/
+			gVoiceClient->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming);
+		}		
+		else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent"))
+		{
+			/*
+			<Event type="TextStreamUpdatedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg1</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==1</SessionHandle>
+				<Enabled>true</Enabled>
+				<State>1</State>
+				<Incoming>true</Incoming>
+			</Event>
+			*/
+			gVoiceClient->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming);
+		}
+		else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent"))
+		{
+			/* 
+			<Event type="ParticipantAddedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
+				<ParticipantUri>sip:xI5auBZ60SJWIk606-1JGRQ==@bhr.vivox.com</ParticipantUri>
+				<AccountName>xI5auBZ60SJWIk606-1JGRQ==</AccountName>
+				<DisplayName />
+				<ParticipantType>0</ParticipantType>
+			</Event>
+			*/
+			gVoiceClient->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
+		}
+		else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
+		{
+			/*
+			<Event type="ParticipantRemovedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
+				<ParticipantUri>sip:xtx7YNV-3SGiG7rA1fo5Ndw==@bhr.vivox.com</ParticipantUri>
+				<AccountName>xtx7YNV-3SGiG7rA1fo5Ndw==</AccountName>
+			</Event>
+			*/
+			gVoiceClient->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
+		}
+		else if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
+		{
+			/*
+			<Event type="ParticipantUpdatedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
+				<ParticipantUri>sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com</ParticipantUri>
+				<IsModeratorMuted>false</IsModeratorMuted>
+				<IsSpeaking>true</IsSpeaking>
+				<Volume>44</Volume>
+				<Energy>0.0879437</Energy>
+			</Event>
+			*/
+			
+			// These happen so often that logging them is pretty useless.
+			squelchDebugOutput = true;
+			
+			gVoiceClient->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
+		}
+		else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))
+		{
+			gVoiceClient->auxAudioPropertiesEvent(energy);
+		}
+		else if (!stricmp(eventTypeCstr, "BuddyPresenceEvent"))
+		{
+			gVoiceClient->buddyPresenceEvent(uriString, alias, statusString, applicationString);
+		}
+		else if (!stricmp(eventTypeCstr, "BuddyAndGroupListChangedEvent"))
+		{
+			// The buddy list was updated during parsing.
+			// Need to recheck against the friends list.
+			gVoiceClient->buddyListChanged();
+		}
+		else if (!stricmp(eventTypeCstr, "BuddyChangedEvent"))
+		{
+			/*
+			<Event type="BuddyChangedEvent">
+				<AccountHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==</AccountHandle>
+				<BuddyURI>sip:x9fFHFZjOTN6OESF1DUPrZQ==@bhr.vivox.com</BuddyURI>
+				<DisplayName>Monroe Tester</DisplayName>
+				<BuddyData />
+				<GroupID>0</GroupID>
+				<ChangeType>Set</ChangeType>
+			</Event>
+			*/		
+			// TODO: Question: Do we need to process this at all?
+		}
+		else if (!stricmp(eventTypeCstr, "MessageEvent"))  
+		{
+			gVoiceClient->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString);
+		}
+		else if (!stricmp(eventTypeCstr, "SessionNotificationEvent"))  
+		{
+			gVoiceClient->sessionNotificationEvent(sessionHandle, uriString, notificationType);
+		}
+		else if (!stricmp(eventTypeCstr, "SubscriptionEvent"))  
+		{
+			gVoiceClient->subscriptionEvent(uriString, subscriptionHandle, alias, displayNameString, applicationString, subscriptionType);
+		}
+		else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))  
+		{
+			/*
+			<Event type="SessionUpdatedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
+				<SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
+				<Uri>sip:confctl-9@bhd.vivox.com</Uri>
+				<IsMuted>0</IsMuted>
+				<Volume>50</Volume>
+				<TransmitEnabled>1</TransmitEnabled>
+				<IsFocused>0</IsFocused>
+				<SpeakerPosition><Position><X>0</X><Y>0</Y><Z>0</Z></Position></SpeakerPosition>
+				<SessionFontID>0</SessionFontID>
+			</Event>
+			*/
+			// We don't need to process this, but we also shouldn't warn on it, since that confuses people.
+		}
+		
+		else if (!stricmp(eventTypeCstr, "SessionGroupRemovedEvent"))  
+		{
+			/*
+			<Event type="SessionGroupRemovedEvent">
+				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
+			</Event>
+			*/
+			// We don't need to process this, but we also shouldn't warn on it, since that confuses people.
+		}
+		else
+		{
+			LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
+		}
+	}
+	else
+	{
+		const char *actionCstr = actionString.c_str();
+		if (!stricmp(actionCstr, "Connector.Create.1"))
+		{
+			gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID);
+		}
+		else if (!stricmp(actionCstr, "Account.Login.1"))
+		{
+			gVoiceClient->loginResponse(statusCode, statusString, accountHandle, numberOfAliases);
+		}
+		else if (!stricmp(actionCstr, "Session.Create.1"))
+		{
+			gVoiceClient->sessionCreateResponse(requestId, statusCode, statusString, sessionHandle);			
+		}
+		else if (!stricmp(actionCstr, "SessionGroup.AddSession.1"))
+		{
+			gVoiceClient->sessionGroupAddSessionResponse(requestId, statusCode, statusString, sessionHandle);			
+		}
+		else if (!stricmp(actionCstr, "Session.Connect.1"))
+		{
+			gVoiceClient->sessionConnectResponse(requestId, statusCode, statusString);			
+		}
+		else if (!stricmp(actionCstr, "Account.Logout.1"))
+		{
+			gVoiceClient->logoutResponse(statusCode, statusString);			
+		}
+		else if (!stricmp(actionCstr, "Connector.InitiateShutdown.1"))
+		{
+			gVoiceClient->connectorShutdownResponse(statusCode, statusString);			
+		}
+		else if (!stricmp(actionCstr, "Account.ListBlockRules.1"))
+		{
+			gVoiceClient->accountListBlockRulesResponse(statusCode, statusString);						
+		}
+		else if (!stricmp(actionCstr, "Account.ListAutoAcceptRules.1"))
+		{
+			gVoiceClient->accountListAutoAcceptRulesResponse(statusCode, statusString);						
+		}
+		else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
+		{
+			// We don't need to process these, but they're so spammy we don't want to log them.
+			squelchDebugOutput = true;
+		}
+/*
+		else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
+		{
+			gVoiceClient->channelGetListResponse(statusCode, statusString);
+		}
+		else if (!stricmp(actionCstr, "Connector.AccountCreate.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Connector.MuteLocalMic.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Connector.MuteLocalSpeaker.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Connector.SetLocalMicVolume.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Connector.SetLocalSpeakerVolume.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Session.ListenerSetPosition.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Session.SpeakerSetPosition.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Session.AudioSourceSetPosition.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Session.GetChannelParticipants.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelCreate.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelUpdate.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelDelete.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelCreateAndInvite.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelFolderCreate.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelFolderUpdate.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelFolderDelete.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelAddModerator.1"))
+		{
+			
+		}
+		else if (!stricmp(actionCstr, "Account.ChannelDeleteModerator.1"))
+		{
+			
+		}
+*/
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+class LLVoiceClientMuteListObserver : public LLMuteListObserver
+{
+	/* virtual */ void onChange()  { gVoiceClient->muteListChanged();}
+};
+
+class LLVoiceClientFriendsObserver : public LLFriendObserver
+{
+public:
+	/* virtual */ void changed(U32 mask) { gVoiceClient->updateFriends(mask);}
+};
+
+static LLVoiceClientMuteListObserver mutelist_listener;
+static bool sMuteListListener_listening = false;
+
+static LLVoiceClientFriendsObserver *friendslist_listener = NULL;
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+class LLVoiceClientCapResponder : public LLHTTPClient::Responder
+{
+public:
+	LLVoiceClientCapResponder(void){};
+
+	virtual void error(U32 status, const std::string& reason);	// called with bad status codes
+	virtual void result(const LLSD& content);
+
+private:
+};
+
+void LLVoiceClientCapResponder::error(U32 status, const std::string& reason)
+{
+	LL_WARNS("Voice") << "LLVoiceClientCapResponder::error("
+		<< status << ": " << reason << ")"
+		<< LL_ENDL;
+}
+
+void LLVoiceClientCapResponder::result(const LLSD& content)
+{
+	LLSD::map_const_iterator iter;
+	
+	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+
+	if ( content.has("voice_credentials") )
+	{
+		LLSD voice_credentials = content["voice_credentials"];
+		std::string uri;
+		std::string credentials;
+
+		if ( voice_credentials.has("channel_uri") )
+		{
+			uri = voice_credentials["channel_uri"].asString();
+		}
+		if ( voice_credentials.has("channel_credentials") )
+		{
+			credentials =
+				voice_credentials["channel_credentials"].asString();
+		}
+
+		gVoiceClient->setSpatialChannel(uri, credentials);
+	}
+}
+
+
+
+#if LL_WINDOWS
+static HANDLE sGatewayHandle = 0;
+
+static bool isGatewayRunning()
+{
+	bool result = false;
+	if(sGatewayHandle != 0)		
+	{
+		DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0);
+		if(waitresult != WAIT_OBJECT_0)
+		{
+			result = true;
+		}			
+	}
+	return result;
+}
+static void killGateway()
+{
+	if(sGatewayHandle != 0)
+	{
+		TerminateProcess(sGatewayHandle,0);
+	}
+}
+
+#else // Mac and linux
+
+static pid_t sGatewayPID = 0;
+static bool isGatewayRunning()
+{
+	bool result = false;
+	if(sGatewayPID != 0)
+	{
+		// A kill with signal number 0 has no effect, just does error checking.  It should return an error if the process no longer exists.
+		if(kill(sGatewayPID, 0) == 0)
+		{
+			result = true;
+		}
+	}
+	return result;
+}
+
+static void killGateway()
+{
+	if(sGatewayPID != 0)
+	{
+		kill(sGatewayPID, SIGTERM);
+	}
+}
+
+#endif
+
+class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>
+{
+	LOG_CLASS(LLSpeakerVolumeStorage);
+public:
+
+	/**
+	 * Stores volume level for specified user.
+	 *
+	 * @param[in] speaker_id - LLUUID of user to store volume level for.
+	 * @param[in] volume - volume level to be stored for user.
+	 */
+	void storeSpeakerVolume(const LLUUID& speaker_id, F32 volume);
+
+	/**
+	 * Gets stored volume level for specified speaker
+	 *
+	 * @param[in] speaker_id - LLUUID of user to retrieve volume level for.
+	 * @param[out] volume - set to stored volume if found, otherwise unmodified.
+	 * @return - true if a stored volume is found.
+	 */
+	bool getSpeakerVolume(const LLUUID& speaker_id, F32& volume);
+
+	/**
+	 * Removes stored volume level for specified user.
+	 *
+	 * @param[in] speaker_id - LLUUID of user to remove.
+	 */
+	void removeSpeakerVolume(const LLUUID& speaker_id);
+
+private:
+	friend class LLSingleton<LLSpeakerVolumeStorage>;
+	LLSpeakerVolumeStorage();
+	~LLSpeakerVolumeStorage();
+
+	const static std::string SETTINGS_FILE_NAME;
+
+	void load();
+	void save();
+
+	static F32 transformFromLegacyVolume(F32 volume_in);
+	static F32 transformToLegacyVolume(F32 volume_in);
+
+	typedef std::map<LLUUID, F32> speaker_data_map_t;
+	speaker_data_map_t mSpeakersData;
+};
+
+const std::string LLSpeakerVolumeStorage::SETTINGS_FILE_NAME = "volume_settings.xml";
+
+LLSpeakerVolumeStorage::LLSpeakerVolumeStorage()
+{
+	load();
+}
+
+LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage()
+{
+	save();
+}
+
+void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, F32 volume)
+{
+	if ((volume >= LLVoiceClient::VOLUME_MIN) && (volume <= LLVoiceClient::VOLUME_MAX))
+	{
+		mSpeakersData[speaker_id] = volume;
+
+		// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
+		// LL_DEBUGS("Voice") << "Stored volume = " << volume <<  " for " << id << LL_ENDL;
+	}
+	else
+	{
+		LL_WARNS("Voice") << "Attempted to store out of range volume " << volume << " for " << speaker_id << LL_ENDL;
+		llassert(0);
+	}
+}
+
+bool LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id, F32& volume)
+{
+	speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id);
+	
+	if (it != mSpeakersData.end())
+	{
+		volume = it->second;
+
+		// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
+		// LL_DEBUGS("Voice") << "Retrieved stored volume = " << volume <<  " for " << id << LL_ENDL;
+
+		return true;
+	}
+
+	return false;
+}
+
+void LLSpeakerVolumeStorage::removeSpeakerVolume(const LLUUID& speaker_id)
+{
+	mSpeakersData.erase(speaker_id);
+
+	// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
+	// LL_DEBUGS("Voice") << "Removing stored volume for  " << id << LL_ENDL;
+}
+
+/* static */ F32 LLSpeakerVolumeStorage::transformFromLegacyVolume(F32 volume_in)
+{
+	// Convert to linear-logarithmic [0.0..1.0] with 0.5 = 0dB
+	// from legacy characteristic composed of two square-curves
+	// that intersect at volume_in = 0.5, volume_out = 0.56
+
+	F32 volume_out = 0.f;
+	volume_in = llclamp(volume_in, 0.f, 1.0f);
+
+	if (volume_in <= 0.5f)
+	{
+		volume_out = volume_in * volume_in * 4.f * 0.56f;
+	}
+	else
+	{
+		volume_out = (1.f - 0.56f) * (4.f * volume_in * volume_in - 1.f) / 3.f + 0.56f;
+	}
+
+	return volume_out;
+}
+
+/* static */ F32 LLSpeakerVolumeStorage::transformToLegacyVolume(F32 volume_in)
+{
+	// Convert from linear-logarithmic [0.0..1.0] with 0.5 = 0dB
+	// to legacy characteristic composed of two square-curves
+	// that intersect at volume_in = 0.56, volume_out = 0.5
+
+	F32 volume_out = 0.f;
+	volume_in = llclamp(volume_in, 0.f, 1.0f);
+
+	if (volume_in <= 0.56f)
+	{
+		volume_out = sqrt(volume_in / (4.f * 0.56f));
+	}
+	else
+	{
+		volume_out = sqrt((3.f * (volume_in - 0.56f) / (1.f - 0.56f) + 1.f) / 4.f);
+	}
+
+	return volume_out;
+}
+
+void LLSpeakerVolumeStorage::load()
+{
+	// load per-resident voice volume information
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME);
+
+	LL_INFOS("Voice") << "Loading stored speaker volumes from: " << filename << LL_ENDL;
+
+	LLSD settings_llsd;
+	llifstream file;
+	file.open(filename);
+	if (file.is_open())
+	{
+		LLSDSerialize::fromXML(settings_llsd, file);
+	}
+
+	for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
+		iter != settings_llsd.endMap(); ++iter)
+	{
+		// Maintain compatibility with 1.23 non-linear saved volume levels
+		F32 volume = transformFromLegacyVolume((F32)iter->second.asReal());
+
+		storeSpeakerVolume(LLUUID(iter->first), volume);
+	}
+}
+
+void LLSpeakerVolumeStorage::save()
+{
+	// If we quit from the login screen we will not have an SL account
+	// name.  Don't try to save, otherwise we'll dump a file in
+	// C:\Program Files\SecondLife\ or similar. JC
+	std::string user_dir = gDirUtilp->getLindenUserDir();
+	if (!user_dir.empty())
+	{
+		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME);
+		LLSD settings_llsd;
+
+		LL_INFOS("Voice") << "Saving stored speaker volumes to: " << filename << LL_ENDL;
+
+		for(speaker_data_map_t::const_iterator iter = mSpeakersData.begin(); iter != mSpeakersData.end(); ++iter)
+		{
+			// Maintain compatibility with 1.23 non-linear saved volume levels
+			F32 volume = transformToLegacyVolume(iter->second);
+
+			settings_llsd[iter->first.asString()] = volume;
+		}
+
+		llofstream file;
+		file.open(filename);
+		LLSDSerialize::toPrettyXML(settings_llsd, file);
+	}
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+LLVoiceClient::LLVoiceClient() :
+	mState(stateDisabled),
+	mSessionTerminateRequested(false),
+	mRelogRequested(false),
+	mConnected(false),
+	mPump(NULL),
+	mSpatialJoiningNum(0),
+	
+	mTuningMode(false),
+	mTuningEnergy(0.0f),
+	mTuningMicVolume(0),
+	mTuningMicVolumeDirty(true),
+	mTuningSpeakerVolume(0),
+	mTuningSpeakerVolumeDirty(true),
+	mTuningExitState(stateDisabled),
+	
+	mAreaVoiceDisabled(false),
+	mAudioSession(NULL),
+	mAudioSessionChanged(false),
+	mNextAudioSession(NULL),
+	
+	mCurrentParcelLocalID(0),
+	mNumberOfAliases(0),
+	mCommandCookie(0),
+	mLoginRetryCount(0),
+	
+	mBuddyListMapPopulated(false),
+	mBlockRulesListReceived(false),
+	mAutoAcceptRulesListReceived(false),
+	mCaptureDeviceDirty(false),
+	mRenderDeviceDirty(false),
+	mSpatialCoordsDirty(false),
+
+	mPTTDirty(true),
+	mPTT(true),
+	mUsePTT(true),
+	mPTTIsMiddleMouse(false),
+	mPTTKey(0),
+	mPTTIsToggle(false),
+	mUserPTTState(false),
+	mMuteMic(false),
+	mFriendsListDirty(true),
+	
+	mEarLocation(0),
+	mSpeakerVolumeDirty(true),
+	mSpeakerMuteDirty(true),
+	mMicVolume(0),
+	mMicVolumeDirty(true),
+	
+	mVoiceEnabled(false),
+	mWriteInProgress(false),
+	
+	mLipSyncEnabled(false)
+{	
+	gVoiceClient = this;
+	
+	mAPIVersion = LLTrans::getString("NotConnected");
+
+	mSpeakerVolume = scale_speaker_volume(0);
+	
+#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+		// HACK: THIS DOES NOT BELONG HERE
+		// When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
+		// This should cause us to ignore SIGPIPE and handle the error through proper channels.
+		// This should really be set up elsewhere.  Where should it go?
+		signal(SIGPIPE, SIG_IGN);
+		
+		// Since we're now launching the gateway with fork/exec instead of system(), we need to deal with zombie processes.
+		// Ignoring SIGCHLD should prevent zombies from being created.  Alternately, we could use wait(), but I'd rather not do that.
+		signal(SIGCHLD, SIG_IGN);
+#endif
+
+	// set up state machine
+	setState(stateDisabled);
+	
+	gIdleCallbacks.addFunction(idle, this);
+}
+
+//---------------------------------------------------
+
+LLVoiceClient::~LLVoiceClient()
+{
+}
+
+//----------------------------------------------
+
+void LLVoiceClient::init(LLPumpIO *pump)
+{
+	// constructor will set up gVoiceClient
+	LLVoiceClient::getInstance()->mPump = pump;
+	LLVoiceClient::getInstance()->updateSettings();
+}
+
+void LLVoiceClient::terminate()
+{
+	if(gVoiceClient)
+	{
+//		gVoiceClient->leaveAudioSession();
+		gVoiceClient->logout();
+		// As of SDK version 4885, this should no longer be necessary.  It will linger after the socket close if it needs to.
+		// ms_sleep(2000);
+		gVoiceClient->connectorShutdown();
+		gVoiceClient->closeSocket();		// Need to do this now -- bad things happen if the destructor does it later.
+		
+		// This will do unpleasant things on windows.
+//		killGateway();
+		
+		// Don't do this anymore -- LLSingleton will take care of deleting the object.		
+//		delete gVoiceClient;
+		
+		// Hint to other code not to access the voice client anymore.
+		gVoiceClient = NULL;
+	}
+}
+
+//---------------------------------------------------
+
+void LLVoiceClient::updateSettings()
+{
+	setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat"));
+	setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
+	std::string keyString = gSavedSettings.getString("PushToTalkButton");
+	setPTTKey(keyString);
+	setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
+	setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
+
+	std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
+	setCaptureDevice(inputDevice);
+	std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
+	setRenderDevice(outputDevice);
+	F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
+	setMicGain(mic_level);
+	setLipSyncEnabled(gSavedSettings.getBOOL("LipSyncEnabled"));
+}
+
+/////////////////////////////
+// utility functions
+
+bool LLVoiceClient::writeString(const std::string &str)
+{
+	bool result = false;
+	if(mConnected)
+	{
+		apr_status_t err;
+		apr_size_t size = (apr_size_t)str.size();
+		apr_size_t written = size;
+	
+		//MARK: Turn this on to log outgoing XML
+//		LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
+
+		// check return code - sockets will fail (broken, etc.)
+		err = apr_socket_send(
+				mSocket->getSocket(),
+				(const char*)str.data(),
+				&written);
+		
+		if(err == 0)
+		{
+			// Success.
+			result = true;
+		}
+		// TODO: handle partial writes (written is number of bytes written)
+		// Need to set socket to non-blocking before this will work.
+//		else if(APR_STATUS_IS_EAGAIN(err))
+//		{
+//			// 
+//		}
+		else
+		{
+			// Assume any socket error means something bad.  For now, just close the socket.
+			char buf[MAX_STRING];
+			LL_WARNS("Voice") << "apr error " << err << " ("<< apr_strerror(err, buf, MAX_STRING) << ") sending data to vivox daemon." << LL_ENDL;
+			daemonDied();
+		}
+	}
+		
+	return result;
+}
+
+
+/////////////////////////////
+// session control messages
+void LLVoiceClient::connectorCreate()
+{
+	std::ostringstream stream;
+	std::string logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+	std::string loglevel = "0";
+	
+	// Transition to stateConnectorStarted when the connector handle comes back.
+	setState(stateConnectorStarting);
+
+	std::string savedLogLevel = gSavedSettings.getString("VivoxDebugLevel");
+		
+	if(savedLogLevel != "-1")
+	{
+		LL_DEBUGS("Voice") << "creating connector with logging enabled" << LL_ENDL;
+		loglevel = "10";
+	}
+	
+	stream 
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.Create.1\">"
+		<< "<ClientName>V2 SDK</ClientName>"
+		<< "<AccountManagementServer>" << mVoiceAccountServerURI << "</AccountManagementServer>"
+		<< "<Mode>Normal</Mode>"
+		<< "<Logging>"
+			<< "<Folder>" << logpath << "</Folder>"
+			<< "<FileNamePrefix>Connector</FileNamePrefix>"
+			<< "<FileNameSuffix>.log</FileNameSuffix>"
+			<< "<LogLevel>" << loglevel << "</LogLevel>"
+		<< "</Logging>"
+		<< "<Application>SecondLifeViewer.1</Application>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::connectorShutdown()
+{
+	setState(stateConnectorStopping);
+	
+	if(!mConnectorHandle.empty())
+	{
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.InitiateShutdown.1\">"
+			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
+		<< "</Request>"
+		<< "\n\n\n";
+		
+		mConnectorHandle.clear();
+		
+		writeString(stream.str());
+	}
+}
+
+void LLVoiceClient::userAuthorized(const std::string& firstName, const std::string& lastName, const LLUUID &agentID)
+{
+	mAccountFirstName = firstName;
+	mAccountLastName = lastName;
+
+	mAccountDisplayName = firstName;
+	mAccountDisplayName += " ";
+	mAccountDisplayName += lastName;
+
+	LL_INFOS("Voice") << "name \"" << mAccountDisplayName << "\" , ID " << agentID << LL_ENDL;
+
+	sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid();
+
+	mAccountName = nameFromID(agentID);
+}
+
+void LLVoiceClient::requestVoiceAccountProvision(S32 retries)
+{
+	if ( gAgent.getRegion() && mVoiceEnabled )
+	{
+		std::string url = 
+			gAgent.getRegion()->getCapability(
+				"ProvisionVoiceAccountRequest");
+
+		if ( url == "" ) return;
+
+		LLHTTPClient::post(
+			url,
+			LLSD(),
+			new LLViewerVoiceAccountProvisionResponder(retries));
+	}
+}
+
+void LLVoiceClient::login(
+	const std::string& account_name,
+	const std::string& password,
+	const std::string& voice_sip_uri_hostname,
+	const std::string& voice_account_server_uri)
+{
+	mVoiceSIPURIHostName = voice_sip_uri_hostname;
+	mVoiceAccountServerURI = voice_account_server_uri;
+
+	if(!mAccountHandle.empty())
+	{
+		// Already logged in.
+		LL_WARNS("Voice") << "Called while already logged in." << LL_ENDL;
+		
+		// Don't process another login.
+		return;
+	}
+	else if ( account_name != mAccountName )
+	{
+		//TODO: error?
+		LL_WARNS("Voice") << "Wrong account name! " << account_name
+				<< " instead of " << mAccountName << LL_ENDL;
+	}
+	else
+	{
+		mAccountPassword = password;
+	}
+
+	std::string debugSIPURIHostName = gSavedSettings.getString("VivoxDebugSIPURIHostName");
+	
+	if( !debugSIPURIHostName.empty() )
+	{
+		mVoiceSIPURIHostName = debugSIPURIHostName;
+	}
+	
+	if( mVoiceSIPURIHostName.empty() )
+	{
+		// we have an empty account server name
+		// so we fall back to hardcoded defaults
+
+		if(sConnectingToAgni)
+		{
+			// Use the release account server
+			mVoiceSIPURIHostName = "bhr.vivox.com";
+		}
+		else
+		{
+			// Use the development account server
+			mVoiceSIPURIHostName = "bhd.vivox.com";
+		}
+	}
+	
+	std::string debugAccountServerURI = gSavedSettings.getString("VivoxDebugVoiceAccountServerURI");
+
+	if( !debugAccountServerURI.empty() )
+	{
+		mVoiceAccountServerURI = debugAccountServerURI;
+	}
+	
+	if( mVoiceAccountServerURI.empty() )
+	{
+		// If the account server URI isn't specified, construct it from the SIP URI hostname
+		mVoiceAccountServerURI = "https://www." + mVoiceSIPURIHostName + "/api2/";		
+	}
+}
+
+void LLVoiceClient::idle(void* user_data)
+{
+	LLVoiceClient* self = (LLVoiceClient*)user_data;
+	self->stateMachine();
+}
+
+std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
+{
+	std::string result = "UNKNOWN";
+	
+		// Prevent copy-paste errors when updating this list...
+#define CASE(x)  case x:  result = #x;  break
+
+	switch(inState)
+	{
+		CASE(stateDisableCleanup);
+		CASE(stateDisabled);
+		CASE(stateStart);
+		CASE(stateDaemonLaunched);
+		CASE(stateConnecting);
+		CASE(stateConnected);
+		CASE(stateIdle);
+		CASE(stateMicTuningStart);
+		CASE(stateMicTuningRunning);
+		CASE(stateMicTuningStop);
+		CASE(stateConnectorStart);
+		CASE(stateConnectorStarting);
+		CASE(stateConnectorStarted);
+		CASE(stateLoginRetry);
+		CASE(stateLoginRetryWait);
+		CASE(stateNeedsLogin);
+		CASE(stateLoggingIn);
+		CASE(stateLoggedIn);
+		CASE(stateCreatingSessionGroup);
+		CASE(stateNoChannel);
+		CASE(stateJoiningSession);
+		CASE(stateSessionJoined);
+		CASE(stateRunning);
+		CASE(stateLeavingSession);
+		CASE(stateSessionTerminated);
+		CASE(stateLoggingOut);
+		CASE(stateLoggedOut);
+		CASE(stateConnectorStopping);
+		CASE(stateConnectorStopped);
+		CASE(stateConnectorFailed);
+		CASE(stateConnectorFailedWaiting);
+		CASE(stateLoginFailed);
+		CASE(stateLoginFailedWaiting);
+		CASE(stateJoinSessionFailed);
+		CASE(stateJoinSessionFailedWaiting);
+		CASE(stateJail);
+	}
+
+#undef CASE
+	
+	return result;
+}
+
+std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserver::EStatusType inStatus)
+{
+	std::string result = "UNKNOWN";
+	
+		// Prevent copy-paste errors when updating this list...
+#define CASE(x)  case x:  result = #x;  break
+
+	switch(inStatus)
+	{
+		CASE(STATUS_LOGIN_RETRY);
+		CASE(STATUS_LOGGED_IN);
+		CASE(STATUS_JOINING);
+		CASE(STATUS_JOINED);
+		CASE(STATUS_LEFT_CHANNEL);
+		CASE(STATUS_VOICE_DISABLED);
+		CASE(STATUS_VOICE_ENABLED);
+		CASE(BEGIN_ERROR_STATUS);
+		CASE(ERROR_CHANNEL_FULL);
+		CASE(ERROR_CHANNEL_LOCKED);
+		CASE(ERROR_NOT_AVAILABLE);
+		CASE(ERROR_UNKNOWN);
+	default:
+		break;
+	}
+
+#undef CASE
+	
+	return result;
+}
+
+void LLVoiceClient::setState(state inState)
+{
+	LL_DEBUGS("Voice") << "entering state " << state2string(inState) << LL_ENDL;
+	
+	mState = inState;
+}
+
+void LLVoiceClient::stateMachine()
+{
+	if(gDisconnected)
+	{
+		// The viewer has been disconnected from the sim.  Disable voice.
+		setVoiceEnabled(false);
+	}
+	
+	if(mVoiceEnabled)
+	{
+		updatePosition();
+	}
+	else if(mTuningMode)
+	{
+		// Tuning mode is special -- it needs to launch SLVoice even if voice is disabled.
+	}
+	else
+	{
+		if((getState() != stateDisabled) && (getState() != stateDisableCleanup))
+		{
+			// User turned off voice support.  Send the cleanup messages, close the socket, and reset.
+			if(!mConnected)
+			{
+				// if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill.
+				LL_INFOS("Voice") << "Disabling voice before connection to daemon, terminating." << LL_ENDL;
+				killGateway();
+			}
+			
+			logout();
+			connectorShutdown();
+			
+			setState(stateDisableCleanup);
+		}
+	}
+	
+	// Check for parcel boundary crossing
+	{
+		LLViewerRegion *region = gAgent.getRegion();
+		LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+		
+		if(region && parcel)
+		{
+			S32 parcelLocalID = parcel->getLocalID();
+			std::string regionName = region->getName();
+			std::string capURI = region->getCapability("ParcelVoiceInfoRequest");
+		
+//			LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL;
+
+			// The region name starts out empty and gets filled in later.  
+			// Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
+			// If either is empty, wait for the next time around.
+			if(!regionName.empty())
+			{
+				if(!capURI.empty())
+				{
+					if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName))
+					{
+						// We have changed parcels.  Initiate a parcel channel lookup.
+						mCurrentParcelLocalID = parcelLocalID;
+						mCurrentRegionName = regionName;
+						
+						parcelChanged();
+					}
+				}
+				else
+				{
+					LL_WARNS_ONCE("Voice") << "region doesn't have ParcelVoiceInfoRequest capability.  This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
+				}
+			}
+		}
+	}
+
+	switch(getState())
+	{
+		//MARK: stateDisableCleanup
+		case stateDisableCleanup:
+			// Clean up and reset everything. 
+			closeSocket();
+			deleteAllSessions();
+			deleteAllBuddies();		
+			
+			mConnectorHandle.clear();
+			mAccountHandle.clear();
+			mAccountPassword.clear();
+			mVoiceAccountServerURI.clear();
+			
+			setState(stateDisabled);	
+		break;
+		
+		//MARK: stateDisabled
+		case stateDisabled:
+			if(mTuningMode || (mVoiceEnabled && !mAccountName.empty()))
+			{
+				setState(stateStart);
+			}
+		break;
+		
+		//MARK: stateStart
+		case stateStart:
+			if(gSavedSettings.getBOOL("CmdLineDisableVoice"))
+			{
+				// Voice is locked out, we must not launch the vivox daemon.
+				setState(stateJail);
+			}
+			else if(!isGatewayRunning())
+			{
+				if(true)
+				{
+					// Launch the voice daemon
+					
+					// *FIX:Mani - Using the executable dir instead 
+					// of mAppRODataDir, the working directory from which the app
+					// is launched.
+					//std::string exe_path = gDirUtilp->getAppRODataDir();
+					std::string exe_path = gDirUtilp->getExecutableDir();
+					exe_path += gDirUtilp->getDirDelimiter();
+#if LL_WINDOWS
+					exe_path += "SLVoice.exe";
+#elif LL_DARWIN
+					exe_path += "../Resources/SLVoice";
+#else
+					exe_path += "SLVoice";
+#endif
+					// See if the vivox executable exists
+					llstat s;
+					if(!LLFile::stat(exe_path, &s))
+					{
+						// vivox executable exists.  Build the command line and launch the daemon.
+						// SLIM SDK: these arguments are no longer necessary.
+//						std::string args = " -p tcp -h -c";
+						std::string args;
+						std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
+						
+						if(loglevel.empty())
+						{
+							loglevel = "-1";	// turn logging off completely
+						}
+						
+						args += " -ll ";
+						args += loglevel;
+						
+						LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL;
+
+#if LL_WINDOWS
+						PROCESS_INFORMATION pinfo;
+						STARTUPINFOW sinfo;
+						memset(&sinfo, 0, sizeof(sinfo));
+
+						std::string exe_dir = gDirUtilp->getExecutableDir();
+
+						llutf16string exe_path16 = utf8str_to_utf16str(exe_path);
+						llutf16string exe_dir16 = utf8str_to_utf16str(exe_dir);
+						llutf16string args16 = utf8str_to_utf16str(args);
+						// Create a writeable copy to keep Windows happy.
+						U16 *argscpy_16 = new U16[args16.size() + 1];
+						wcscpy_s(argscpy_16,args16.size()+1,args16.c_str());
+						if(!CreateProcessW(exe_path16.c_str(), argscpy_16, NULL, NULL, FALSE, 0, NULL, exe_dir16.c_str(), &sinfo, &pinfo))
+						{
+//							DWORD dwErr = GetLastError();
+						}
+						else
+						{
+							// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
+							// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
+							sGatewayHandle = pinfo.hProcess;
+							CloseHandle(pinfo.hThread); // stops leaks - nothing else
+						}		
+						
+						delete[] argscpy_16;
+#else	// LL_WINDOWS
+						// This should be the same for mac and linux
+						{
+							std::vector<std::string> arglist;
+							arglist.push_back(exe_path);
+							
+							// Split the argument string into separate strings for each argument
+							typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+							boost::char_separator<char> sep(" ");
+							tokenizer tokens(args, sep);
+							tokenizer::iterator token_iter;
+
+							for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+							{
+								arglist.push_back(*token_iter);
+							}
+							
+							// create an argv vector for the child process
+							char **fakeargv = new char*[arglist.size() + 1];
+							int i;
+							for(i=0; i < arglist.size(); i++)
+								fakeargv[i] = const_cast<char*>(arglist[i].c_str());
+
+							fakeargv[i] = NULL;
+							
+							fflush(NULL); // flush all buffers before the child inherits them
+							pid_t id = vfork();
+							if(id == 0)
+							{
+								// child
+								execv(exe_path.c_str(), fakeargv);
+								
+								// If we reach this point, the exec failed.
+								// Use _exit() instead of exit() per the vfork man page.
+								_exit(0);
+							}
+
+							// parent
+							delete[] fakeargv;
+							sGatewayPID = id;
+						}
+#endif	// LL_WINDOWS
+						mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost").c_str(), gSavedSettings.getU32("VoicePort"));
+					}	
+					else
+					{
+						LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL;
+					}	
+				}
+				else
+				{		
+					// SLIM SDK: port changed from 44124 to 44125.
+					// We can connect to a client gateway running on another host.  This is useful for testing.
+					// To do this, launch the gateway on a nearby host like this:
+					//  vivox-gw.exe -p tcp -i 0.0.0.0:44125
+					// and put that host's IP address here.
+					mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost"), gSavedSettings.getU32("VoicePort"));
+				}
+
+				mUpdateTimer.start();
+				mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
+
+				setState(stateDaemonLaunched);
+				
+				// Dirty the states we'll need to sync with the daemon when it comes up.
+				mPTTDirty = true;
+				mMicVolumeDirty = true;
+				mSpeakerVolumeDirty = true;
+				mSpeakerMuteDirty = true;
+				// These only need to be set if they're not default (i.e. empty string).
+				mCaptureDeviceDirty = !mCaptureDevice.empty();
+				mRenderDeviceDirty = !mRenderDevice.empty();
+				
+				mMainSessionGroupHandle.clear();
+			}
+		break;
+
+		//MARK: stateDaemonLaunched
+		case stateDaemonLaunched:
+			if(mUpdateTimer.hasExpired())
+			{
+				LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
+
+				mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
+
+				if(!mSocket)
+				{
+					mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);	
+				}
+				
+				mConnected = mSocket->blockingConnect(mDaemonHost);
+				if(mConnected)
+				{
+					setState(stateConnecting);
+				}
+				else
+				{
+					// If the connect failed, the socket may have been put into a bad state.  Delete it.
+					closeSocket();
+				}
+			}
+		break;
+
+		//MARK: stateConnecting
+		case stateConnecting:
+		// Can't do this until we have the pump available.
+		if(mPump)
+		{
+			// MBW -- Note to self: pumps and pipes examples in
+			//  indra/test/io.cpp
+			//  indra/test/llpipeutil.{cpp|h}
+
+			// Attach the pumps and pipes
+				
+			LLPumpIO::chain_t readChain;
+
+			readChain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(mSocket)));
+			readChain.push_back(LLIOPipe::ptr_t(new LLVivoxProtocolParser()));
+
+			mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
+
+			setState(stateConnected);
+		}
+
+		break;
+		
+		//MARK: stateConnected
+		case stateConnected:
+			// Initial devices query
+			getCaptureDevicesSendMessage();
+			getRenderDevicesSendMessage();
+
+			mLoginRetryCount = 0;
+
+			setState(stateIdle);
+		break;
+
+		//MARK: stateIdle
+		case stateIdle:
+			// This is the idle state where we're connected to the daemon but haven't set up a connector yet.
+			if(mTuningMode)
+			{
+				mTuningExitState = stateIdle;
+				setState(stateMicTuningStart);
+			}
+			else if(!mVoiceEnabled)
+			{
+				// We never started up the connector.  This will shut down the daemon.
+				setState(stateConnectorStopped);
+			}
+			else if(!mAccountName.empty())
+			{
+				LLViewerRegion *region = gAgent.getRegion();
+				
+				if(region)
+				{
+					if ( region->getCapability("ProvisionVoiceAccountRequest") != "" )
+					{
+						if ( mAccountPassword.empty() )
+						{
+							requestVoiceAccountProvision();
+						}
+						setState(stateConnectorStart);
+					}
+					else
+					{
+						LL_WARNS_ONCE("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL;
+					}
+				}
+			}
+		break;
+
+		//MARK: stateMicTuningStart
+		case stateMicTuningStart:
+			if(mUpdateTimer.hasExpired())
+			{
+				if(mCaptureDeviceDirty || mRenderDeviceDirty)
+				{
+					// These can't be changed while in tuning mode.  Set them before starting.
+					std::ostringstream stream;
+					
+					buildSetCaptureDevice(stream);
+					buildSetRenderDevice(stream);
+
+					if(!stream.str().empty())
+					{
+						writeString(stream.str());
+					}				
+
+					// This will come around again in the same state and start the capture, after the timer expires.
+					mUpdateTimer.start();
+					mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+				}
+				else
+				{
+					// duration parameter is currently unused, per Mike S.
+					tuningCaptureStartSendMessage(10000);
+
+					setState(stateMicTuningRunning);
+				}
+			}
+			
+		break;
+		
+		//MARK: stateMicTuningRunning
+		case stateMicTuningRunning:
+			if(!mTuningMode || mCaptureDeviceDirty || mRenderDeviceDirty)
+			{
+				// All of these conditions make us leave tuning mode.
+				setState(stateMicTuningStop);
+			}
+			else
+			{
+				// process mic/speaker volume changes
+				if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty)
+				{
+					std::ostringstream stream;
+					
+					if(mTuningMicVolumeDirty)
+					{
+						LL_INFOS("Voice") << "setting tuning mic level to " << mTuningMicVolume << LL_ENDL;
+						stream
+						<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetMicLevel.1\">"
+						<< "<Level>" << mTuningMicVolume << "</Level>"
+						<< "</Request>\n\n\n";
+					}
+					
+					if(mTuningSpeakerVolumeDirty)
+					{
+						stream
+						<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetSpeakerLevel.1\">"
+						<< "<Level>" << mTuningSpeakerVolume << "</Level>"
+						<< "</Request>\n\n\n";
+					}
+					
+					mTuningMicVolumeDirty = false;
+					mTuningSpeakerVolumeDirty = false;
+
+					if(!stream.str().empty())
+					{
+						writeString(stream.str());
+					}
+				}
+			}
+		break;
+		
+		//MARK: stateMicTuningStop
+		case stateMicTuningStop:
+		{
+			// transition out of mic tuning
+			tuningCaptureStopSendMessage();
+			
+			setState(mTuningExitState);
+			
+			// if we exited just to change devices, this will keep us from re-entering too fast.
+			mUpdateTimer.start();
+			mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+			
+		}
+		break;
+												
+		//MARK: stateConnectorStart
+		case stateConnectorStart:
+			if(!mVoiceEnabled)
+			{
+				// We were never logged in.  This will shut down the connector.
+				setState(stateLoggedOut);
+			}
+			else if(!mVoiceAccountServerURI.empty())
+			{
+				connectorCreate();
+			}
+		break;
+		
+		//MARK: stateConnectorStarting
+		case stateConnectorStarting:	// waiting for connector handle
+			// connectorCreateResponse() will transition from here to stateConnectorStarted.
+		break;
+		
+		//MARK: stateConnectorStarted
+		case stateConnectorStarted:		// connector handle received
+			if(!mVoiceEnabled)
+			{
+				// We were never logged in.  This will shut down the connector.
+				setState(stateLoggedOut);
+			}
+			else
+			{
+				// The connector is started.  Send a login message.
+				setState(stateNeedsLogin);
+			}
+		break;
+				
+		//MARK: stateLoginRetry
+		case stateLoginRetry:
+			if(mLoginRetryCount == 0)
+			{
+				// First retry -- display a message to the user
+				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGIN_RETRY);
+			}
+			
+			mLoginRetryCount++;
+			
+			if(mLoginRetryCount > MAX_LOGIN_RETRIES)
+			{
+				LL_WARNS("Voice") << "too many login retries, giving up." << LL_ENDL;
+				setState(stateLoginFailed);
+			}
+			else
+			{
+				LL_INFOS("Voice") << "will retry login in " << LOGIN_RETRY_SECONDS << " seconds." << LL_ENDL;
+				mUpdateTimer.start();
+				mUpdateTimer.setTimerExpirySec(LOGIN_RETRY_SECONDS);
+				setState(stateLoginRetryWait);
+			}
+		break;
+		
+		//MARK: stateLoginRetryWait
+		case stateLoginRetryWait:
+			if(mUpdateTimer.hasExpired())
+			{
+				setState(stateNeedsLogin);
+			}
+		break;
+		
+		//MARK: stateNeedsLogin
+		case stateNeedsLogin:
+			if(!mAccountPassword.empty())
+			{
+				setState(stateLoggingIn);
+				loginSendMessage();
+			}		
+		break;
+		
+		//MARK: stateLoggingIn
+		case stateLoggingIn:			// waiting for account handle
+			// loginResponse() will transition from here to stateLoggedIn.
+		break;
+		
+		//MARK: stateLoggedIn
+		case stateLoggedIn:				// account handle received
+
+			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
+
+			// request the current set of block rules (we'll need them when updating the friends list)
+			accountListBlockRulesSendMessage();
+			
+			// request the current set of auto-accept rules
+			accountListAutoAcceptRulesSendMessage();
+			
+			// Set up the mute list observer if it hasn't been set up already.
+			if((!sMuteListListener_listening))
+			{
+				LLMuteList::getInstance()->addObserver(&mutelist_listener);
+				sMuteListListener_listening = true;
+			}
+
+			// Set up the friends list observer if it hasn't been set up already.
+			if(friendslist_listener == NULL)
+			{
+				friendslist_listener = new LLVoiceClientFriendsObserver;
+				LLAvatarTracker::instance().addObserver(friendslist_listener);
+			}
+			
+			// Set the initial state of mic mute, local speaker volume, etc.
+			{
+				std::ostringstream stream;
+				
+				buildLocalAudioUpdates(stream);
+				
+				if(!stream.str().empty())
+				{
+					writeString(stream.str());
+				}
+			}
+			
+#if USE_SESSION_GROUPS			
+			// create the main session group
+			sessionGroupCreateSendMessage();
+			
+			setState(stateCreatingSessionGroup);
+#else
+			// Not using session groups -- skip the stateCreatingSessionGroup state.
+			setState(stateNoChannel);
+
+			// Initial kick-off of channel lookup logic
+			parcelChanged();		
+#endif
+		break;
+		
+		//MARK: stateCreatingSessionGroup
+		case stateCreatingSessionGroup:
+			if(mSessionTerminateRequested || !mVoiceEnabled)
+			{
+				// TODO: Question: is this the right way out of this state
+				setState(stateSessionTerminated);
+			}
+			else if(!mMainSessionGroupHandle.empty())
+			{
+				setState(stateNoChannel);
+				
+				// Start looped recording (needed for "panic button" anti-griefing tool)
+				recordingLoopStart();
+
+				// Initial kick-off of channel lookup logic
+				parcelChanged();		
+			}
+		break;
+					
+		//MARK: stateNoChannel
+		case stateNoChannel:
+			
+			mSpatialJoiningNum = 0;
+			// Do this here as well as inside sendPositionalUpdate().  
+			// Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
+			sendFriendsListUpdates();
+			
+			if(mSessionTerminateRequested || !mVoiceEnabled)
+			{
+				// TODO: Question: Is this the right way out of this state?
+				setState(stateSessionTerminated);
+			}
+			else if(mTuningMode)
+			{
+				mTuningExitState = stateNoChannel;
+				setState(stateMicTuningStart);
+			}
+			else if(sessionNeedsRelog(mNextAudioSession))
+			{
+				requestRelog();
+				setState(stateSessionTerminated);
+			}
+			else if(mNextAudioSession)
+			{				
+				sessionState *oldSession = mAudioSession;
+
+				mAudioSession = mNextAudioSession;
+				if(!mAudioSession->mReconnect)	
+				{
+					mNextAudioSession = NULL;
+				}
+				
+				// The old session may now need to be deleted.
+				reapSession(oldSession);
+				
+				if(!mAudioSession->mHandle.empty())
+				{
+					// Connect to a session by session handle
+
+					sessionMediaConnectSendMessage(mAudioSession);
+				}
+				else
+				{
+					// Connect to a session by URI
+					sessionCreateSendMessage(mAudioSession, true, false);
+				}
+
+				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
+				setState(stateJoiningSession);
+			}
+			else if(!mSpatialSessionURI.empty())
+			{
+				// If we're not headed elsewhere and have a spatial URI, return to spatial.
+				switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
+			}
+		break;
+
+		//MARK: stateJoiningSession
+		case stateJoiningSession:		// waiting for session handle
+
+			// If this is true we have problem with connection to voice server (EXT-4313).
+			// See descriptions of mSpatialJoiningNum and MAX_NORMAL_JOINING_SPATIAL_NUM.
+			if(mSpatialJoiningNum == MAX_NORMAL_JOINING_SPATIAL_NUM) 
+			{
+				// Notify observers to let them know there is problem with voice
+				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
+				llwarns << "There seems to be problem with connection to voice server. Disabling voice chat abilities." << llendl;
+			}
+
+			// Increase mSpatialJoiningNum only for spatial sessions- it's normal to reach this case for
+			// example for p2p many times while waiting for response, so it can't be used to detect errors
+			if(mAudioSession && mAudioSession->mIsSpatial)
+			{
+				mSpatialJoiningNum++;
+			}
+			
+			// joinedAudioSession() will transition from here to stateSessionJoined.
+			if(!mVoiceEnabled)
+			{
+				// User bailed out during connect -- jump straight to teardown.
+				setState(stateSessionTerminated);
+			}
+			else if(mSessionTerminateRequested)
+			{
+				if(mAudioSession && !mAudioSession->mHandle.empty())
+				{
+					// Only allow direct exits from this state in p2p calls (for cancelling an invite).
+					// Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
+					if(mAudioSession->mIsP2P)
+					{
+						sessionMediaDisconnectSendMessage(mAudioSession);
+						setState(stateSessionTerminated);
+					}
+				}
+			}
+		break;
+		
+		//MARK: stateSessionJoined
+		case stateSessionJoined:		// session handle received
+			
+			mSpatialJoiningNum = 0;
+			// It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
+			// before continuing from this state.  They can happen in either order, and if I don't wait for both, things can get stuck.
+			// For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
+			// This is a cheap way to make sure both have happened before proceeding.
+			if(mAudioSession && mAudioSession->mVoiceEnabled)
+			{
+				// Dirty state that may need to be sync'ed with the daemon.
+				mPTTDirty = true;
+				mSpeakerVolumeDirty = true;
+				mSpatialCoordsDirty = true;
+				
+				setState(stateRunning);
+				
+				// Start the throttle timer
+				mUpdateTimer.start();
+				mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+
+				// Events that need to happen when a session is joined could go here.
+				// Maybe send initial spatial data?
+				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
+
+			}
+			else if(!mVoiceEnabled)
+			{
+				// User bailed out during connect -- jump straight to teardown.
+				setState(stateSessionTerminated);
+			}
+			else if(mSessionTerminateRequested)
+			{
+				// Only allow direct exits from this state in p2p calls (for cancelling an invite).
+				// Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
+				if(mAudioSession && mAudioSession->mIsP2P)
+				{
+					sessionMediaDisconnectSendMessage(mAudioSession);
+					setState(stateSessionTerminated);
+				}
+			}
+		break;
+		
+		//MARK: stateRunning
+		case stateRunning:				// steady state
+			// Disabling voice or disconnect requested.
+			if(!mVoiceEnabled || mSessionTerminateRequested)
+			{
+				leaveAudioSession();
+			}
+			else
+			{
+				
+				// Figure out whether the PTT state needs to change
+				{
+					bool newPTT;
+					if(mUsePTT)
+					{
+						// If configured to use PTT, track the user state.
+						newPTT = mUserPTTState;
+					}
+					else
+					{
+						// If not configured to use PTT, it should always be true (otherwise the user will be unable to speak).
+						newPTT = true;
+					}
+					
+					if(mMuteMic)
+					{
+						// This always overrides any other PTT setting.
+						newPTT = false;
+					}
+					
+					// Dirty if state changed.
+					if(newPTT != mPTT)
+					{
+						mPTT = newPTT;
+						mPTTDirty = true;
+					}
+				}
+				
+				if(!inSpatialChannel())
+				{
+					// When in a non-spatial channel, never send positional updates.
+					mSpatialCoordsDirty = false;
+				}
+				else
+				{
+					// Do the calculation that enforces the listener<->speaker tether (and also updates the real camera position)
+					enforceTether();
+				}
+				
+				// Send an update only if the ptt or mute state has changed (which shouldn't be able to happen that often
+				// -- the user can only click so fast) or every 10hz, whichever is sooner.
+				// Sending for every volume update causes an excessive flood of messages whenever a volume slider is dragged.
+				if((mAudioSession && mAudioSession->mMuteDirty) || mPTTDirty || mUpdateTimer.hasExpired())
+				{
+					mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+					sendPositionalUpdate();
+				}
+			}
+		break;
+		
+		//MARK: stateLeavingSession
+		case stateLeavingSession:		// waiting for terminate session response
+			// The handler for the Session.Terminate response will transition from here to stateSessionTerminated.
+		break;
+
+		//MARK: stateSessionTerminated
+		case stateSessionTerminated:
+			
+			// Must do this first, since it uses mAudioSession.
+			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
+			
+			if(mAudioSession)
+			{
+				sessionState *oldSession = mAudioSession;
+
+				mAudioSession = NULL;
+				// We just notified status observers about this change.  Don't do it again.
+				mAudioSessionChanged = false;
+
+				// The old session may now need to be deleted.
+				reapSession(oldSession);
+			}
+			else
+			{
+				LL_WARNS("Voice") << "stateSessionTerminated with NULL mAudioSession" << LL_ENDL;
+			}
+	
+			// Always reset the terminate request flag when we get here.
+			mSessionTerminateRequested = false;
+
+			if(mVoiceEnabled && !mRelogRequested)
+			{				
+				// Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state).
+				setState(stateNoChannel);
+			}
+			else
+			{
+				// Shutting down voice, continue with disconnecting.
+				logout();
+				
+				// The state machine will take it from here
+				mRelogRequested = false;
+			}
+			
+		break;
+		
+		//MARK: stateLoggingOut
+		case stateLoggingOut:			// waiting for logout response
+			// The handler for the AccountLoginStateChangeEvent will transition from here to stateLoggedOut.
+		break;
+		
+		//MARK: stateLoggedOut
+		case stateLoggedOut:			// logout response received
+			
+			// Once we're logged out, all these things are invalid.
+			mAccountHandle.clear();
+			deleteAllSessions();
+			deleteAllBuddies();
+
+			if(mVoiceEnabled && !mRelogRequested)
+			{
+				// User was logged out, but wants to be logged in.  Send a new login request.
+				setState(stateNeedsLogin);
+			}
+			else
+			{
+				// shut down the connector
+				connectorShutdown();
+			}
+		break;
+		
+		//MARK: stateConnectorStopping
+		case stateConnectorStopping:	// waiting for connector stop
+			// The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped.
+		break;
+
+		//MARK: stateConnectorStopped
+		case stateConnectorStopped:		// connector stop received
+			setState(stateDisableCleanup);
+		break;
+
+		//MARK: stateConnectorFailed
+		case stateConnectorFailed:
+			setState(stateConnectorFailedWaiting);
+		break;
+		//MARK: stateConnectorFailedWaiting
+		case stateConnectorFailedWaiting:
+			if(!mVoiceEnabled)
+			{
+				setState(stateDisableCleanup);
+			}
+		break;
+
+		//MARK: stateLoginFailed
+		case stateLoginFailed:
+			setState(stateLoginFailedWaiting);
+		break;
+		//MARK: stateLoginFailedWaiting
+		case stateLoginFailedWaiting:
+			if(!mVoiceEnabled)
+			{
+				setState(stateDisableCleanup);
+			}
+		break;
+
+		//MARK: stateJoinSessionFailed
+		case stateJoinSessionFailed:
+			// Transition to error state.  Send out any notifications here.
+			if(mAudioSession)
+			{
+				LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mAudioSession->mErrorStatusCode << "): " << mAudioSession->mErrorStatusString << LL_ENDL;
+			}
+			else
+			{
+				LL_WARNS("Voice") << "stateJoinSessionFailed with no current session" << LL_ENDL;
+			}
+			
+			notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
+			setState(stateJoinSessionFailedWaiting);
+		break;
+		
+		//MARK: stateJoinSessionFailedWaiting
+		case stateJoinSessionFailedWaiting:
+			// Joining a channel failed, either due to a failed channel name -> sip url lookup or an error from the join message.
+			// Region crossings may leave this state and try the join again.
+			if(mSessionTerminateRequested)
+			{
+				setState(stateSessionTerminated);
+			}
+		break;
+		
+		//MARK: stateJail
+		case stateJail:
+			// We have given up.  Do nothing.
+		break;
+
+	}
+	
+	if(mAudioSession && mAudioSession->mParticipantsChanged)
+	{
+		mAudioSession->mParticipantsChanged = false;
+		mAudioSessionChanged = true;
+	}
+	
+	if(mAudioSessionChanged)
+	{
+		mAudioSessionChanged = false;
+		notifyParticipantObservers();
+	}
+}
+
+void LLVoiceClient::closeSocket(void)
+{
+	mSocket.reset();
+	mConnected = false;	
+}
+
+void LLVoiceClient::loginSendMessage()
+{
+	std::ostringstream stream;
+
+	bool autoPostCrashDumps = gSavedSettings.getBOOL("VivoxAutoPostCrashDumps");
+
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Login.1\">"
+		<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
+		<< "<AccountName>" << mAccountName << "</AccountName>"
+		<< "<AccountPassword>" << mAccountPassword << "</AccountPassword>"
+		<< "<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>"
+		<< "<EnableBuddiesAndPresence>true</EnableBuddiesAndPresence>"
+		<< "<BuddyManagementMode>Application</BuddyManagementMode>"
+		<< "<ParticipantPropertyFrequency>5</ParticipantPropertyFrequency>"
+		<< (autoPostCrashDumps?"<AutopostCrashDumps>true</AutopostCrashDumps>":"")
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::logout()
+{
+	// Ensure that we'll re-request provisioning before logging in again
+	mAccountPassword.clear();
+	mVoiceAccountServerURI.clear();
+	
+	setState(stateLoggingOut);
+	logoutSendMessage();
+}
+
+void LLVoiceClient::logoutSendMessage()
+{
+	if(!mAccountHandle.empty())
+	{
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Logout.1\">"
+			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+		<< "</Request>"
+		<< "\n\n\n";
+
+		mAccountHandle.clear();
+
+		writeString(stream.str());
+	}
+}
+
+void LLVoiceClient::accountListBlockRulesSendMessage()
+{
+	if(!mAccountHandle.empty())
+	{		
+		std::ostringstream stream;
+
+		LL_DEBUGS("Voice") << "requesting block rules" << LL_ENDL;
+
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ListBlockRules.1\">"
+			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+		<< "</Request>"
+		<< "\n\n\n";
+
+		writeString(stream.str());
+	}
+}
+
+void LLVoiceClient::accountListAutoAcceptRulesSendMessage()
+{
+	if(!mAccountHandle.empty())
+	{		
+		std::ostringstream stream;
+
+		LL_DEBUGS("Voice") << "requesting auto-accept rules" << LL_ENDL;
+
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ListAutoAcceptRules.1\">"
+			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+		<< "</Request>"
+		<< "\n\n\n";
+
+		writeString(stream.str());
+	}
+}
+
+void LLVoiceClient::sessionGroupCreateSendMessage()
+{
+	if(!mAccountHandle.empty())
+	{		
+		std::ostringstream stream;
+
+		LL_DEBUGS("Voice") << "creating session group" << LL_ENDL;
+
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Create.1\">"
+			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+			<< "<Type>Normal</Type>"
+		<< "</Request>"
+		<< "\n\n\n";
+
+		writeString(stream.str());
+	}
+}
+
+void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)
+{
+	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
+	
+	session->mCreateInProgress = true;
+	if(startAudio)
+	{
+		session->mMediaConnectInProgress = true;
+	}
+
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << session->mSIPURI << "\" action=\"Session.Create.1\">"
+		<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+		<< "<URI>" << session->mSIPURI << "</URI>";
+
+	static const std::string allowed_chars =
+				"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+				"0123456789"
+				"-._~";
+
+	if(!session->mHash.empty())
+	{
+		stream
+			<< "<Password>" << LLURI::escape(session->mHash, allowed_chars) << "</Password>"
+			<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>";
+	}
+	
+	stream
+		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
+		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
+		<< "<Name>" << mChannelName << "</Name>"
+	<< "</Request>\n\n\n";
+	writeString(stream.str());
+}
+
+void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)
+{
+	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
+	
+	session->mCreateInProgress = true;
+	if(startAudio)
+	{
+		session->mMediaConnectInProgress = true;
+	}
+	
+	std::string password;
+	if(!session->mHash.empty())
+	{
+		static const std::string allowed_chars =
+					"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+					"0123456789"
+					"-._~"
+					;
+		password = LLURI::escape(session->mHash, allowed_chars);
+	}
+
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << session->mSIPURI << "\" action=\"SessionGroup.AddSession.1\">"
+		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
+		<< "<URI>" << session->mSIPURI << "</URI>"
+		<< "<Name>" << mChannelName << "</Name>"
+		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
+		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
+		<< "<Password>" << password << "</Password>"
+		<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>"
+	<< "</Request>\n\n\n"
+	;
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
+{
+	LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL;
+
+	session->mMediaConnectInProgress = true;
+	
+	std::ostringstream stream;
+
+	stream
+	<< "<Request requestId=\"" << session->mHandle << "\" action=\"Session.MediaConnect.1\">"
+		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
+		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+		<< "<Media>Audio</Media>"
+	<< "</Request>\n\n\n";
+
+	writeString(stream.str());
+}
+
+void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
+{
+	LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL;
+	
+	std::ostringstream stream;
+
+	stream
+	<< "<Request requestId=\"" << session->mHandle << "\" action=\"Session.TextConnect.1\">"
+		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
+		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+	<< "</Request>\n\n\n";
+
+	writeString(stream.str());
+}
+
+void LLVoiceClient::sessionTerminate()
+{
+	mSessionTerminateRequested = true;
+}
+
+void LLVoiceClient::requestRelog()
+{
+	mSessionTerminateRequested = true;
+	mRelogRequested = true;
+}
+
+
+void LLVoiceClient::leaveAudioSession()
+{
+	if(mAudioSession)
+	{
+		LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL;
+
+		switch(getState())
+		{
+			case stateNoChannel:
+				// In this case, we want to pretend the join failed so our state machine doesn't get stuck.
+				// Skip the join failed transition state so we don't send out error notifications.
+				setState(stateJoinSessionFailedWaiting);
+			break;
+			case stateJoiningSession:
+			case stateSessionJoined:
+			case stateRunning:
+				if(!mAudioSession->mHandle.empty())
+				{
+
+#if RECORD_EVERYTHING
+					// HACK: for testing only
+					// Save looped recording
+					std::string savepath("/tmp/vivoxrecording");
+					{
+						time_t now = time(NULL);
+						const size_t BUF_SIZE = 64;
+						char time_str[BUF_SIZE];	/* Flawfinder: ignore */
+						
+						strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
+						savepath += time_str;
+					}
+					recordingLoopSave(savepath);
+#endif
+
+					sessionMediaDisconnectSendMessage(mAudioSession);
+					setState(stateLeavingSession);
+				}
+				else
+				{
+					LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;	
+					setState(stateSessionTerminated);
+				}
+			break;
+			case stateJoinSessionFailed:
+			case stateJoinSessionFailedWaiting:
+				setState(stateSessionTerminated);
+			break;
+			
+			default:
+				LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
+			break;
+		}
+	}
+	else
+	{
+		LL_WARNS("Voice") << "called with no active session" << LL_ENDL;
+		setState(stateSessionTerminated);
+	}
+}
+
+void LLVoiceClient::sessionTerminateSendMessage(sessionState *session)
+{
+	std::ostringstream stream;
+	
+	LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL;	
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">"
+		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::sessionGroupTerminateSendMessage(sessionState *session)
+{
+	std::ostringstream stream;
+	
+	LL_DEBUGS("Voice") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL;	
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Terminate.1\">"
+		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session)
+{
+	std::ostringstream stream;
+	
+	LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL;	
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.MediaDisconnect.1\">"
+		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
+		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+		<< "<Media>Audio</Media>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+	
+}
+
+void LLVoiceClient::sessionTextDisconnectSendMessage(sessionState *session)
+{
+	std::ostringstream stream;
+	
+	LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL;	
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextDisconnect.1\">"
+		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
+		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::getCaptureDevicesSendMessage()
+{
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.GetCaptureDevices.1\">"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::getRenderDevicesSendMessage()
+{
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.GetRenderDevices.1\">"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::clearCaptureDevices()
+{
+	LL_DEBUGS("Voice") << "called" << LL_ENDL;
+	mCaptureDevices.clear();
+}
+
+void LLVoiceClient::addCaptureDevice(const std::string& name)
+{
+	LL_DEBUGS("Voice") << name << LL_ENDL;
+
+	mCaptureDevices.push_back(name);
+}
+
+LLVoiceClient::deviceList *LLVoiceClient::getCaptureDevices()
+{
+	return &mCaptureDevices;
+}
+
+void LLVoiceClient::setCaptureDevice(const std::string& name)
+{
+	if(name == "Default")
+	{
+		if(!mCaptureDevice.empty())
+		{
+			mCaptureDevice.clear();
+			mCaptureDeviceDirty = true;	
+		}
+	}
+	else
+	{
+		if(mCaptureDevice != name)
+		{
+			mCaptureDevice = name;
+			mCaptureDeviceDirty = true;	
+		}
+	}
+}
+
+void LLVoiceClient::clearRenderDevices()
+{	
+	LL_DEBUGS("Voice") << "called" << LL_ENDL;
+	mRenderDevices.clear();
+}
+
+void LLVoiceClient::addRenderDevice(const std::string& name)
+{
+	LL_DEBUGS("Voice") << name << LL_ENDL;
+	mRenderDevices.push_back(name);
+}
+
+LLVoiceClient::deviceList *LLVoiceClient::getRenderDevices()
+{
+	return &mRenderDevices;
+}
+
+void LLVoiceClient::setRenderDevice(const std::string& name)
+{
+	if(name == "Default")
+	{
+		if(!mRenderDevice.empty())
+		{
+			mRenderDevice.clear();
+			mRenderDeviceDirty = true;	
+		}
+	}
+	else
+	{
+		if(mRenderDevice != name)
+		{
+			mRenderDevice = name;
+			mRenderDeviceDirty = true;	
+		}
+	}
+	
+}
+
+void LLVoiceClient::tuningStart()
+{
+	mTuningMode = true;
+	if(getState() >= stateNoChannel)
+	{
+		sessionTerminate();
+	}
+}
+
+void LLVoiceClient::tuningStop()
+{
+	mTuningMode = false;
+}
+
+bool LLVoiceClient::inTuningMode()
+{
+	bool result = false;
+	switch(getState())
+	{
+	case stateMicTuningRunning:
+		result = true;
+		break;
+	default:
+		break;
+	}
+	return result;
+}
+
+void LLVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool loop)
+{		
+	mTuningAudioFile = name;
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStart.1\">"
+    << "<SoundFilePath>" << mTuningAudioFile << "</SoundFilePath>"
+    << "<Loop>" << (loop?"1":"0") << "</Loop>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::tuningRenderStopSendMessage()
+{
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">"
+    << "<SoundFilePath>" << mTuningAudioFile << "</SoundFilePath>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::tuningCaptureStartSendMessage(int duration)
+{
+	LL_DEBUGS("Voice") << "sending CaptureAudioStart" << LL_ENDL;
+	
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStart.1\">"
+    << "<Duration>" << duration << "</Duration>"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+}
+
+void LLVoiceClient::tuningCaptureStopSendMessage()
+{
+	LL_DEBUGS("Voice") << "sending CaptureAudioStop" << LL_ENDL;
+	
+	std::ostringstream stream;
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">"
+	<< "</Request>\n\n\n";
+	
+	writeString(stream.str());
+
+	mTuningEnergy = 0.0f;
+}
+
+void LLVoiceClient::tuningSetMicVolume(float volume)
+{
+	int scaled_volume = scale_mic_volume(volume);
+
+	if(scaled_volume != mTuningMicVolume)
+	{
+		mTuningMicVolume = scaled_volume;
+		mTuningMicVolumeDirty = true;
+	}
+}
+
+void LLVoiceClient::tuningSetSpeakerVolume(float volume)
+{
+	int scaled_volume = scale_speaker_volume(volume);	
+
+	if(scaled_volume != mTuningSpeakerVolume)
+	{
+		mTuningSpeakerVolume = scaled_volume;
+		mTuningSpeakerVolumeDirty = true;
+	}
+}
+				
+float LLVoiceClient::tuningGetEnergy(void)
+{
+	return mTuningEnergy;
+}
+
+bool LLVoiceClient::deviceSettingsAvailable()
+{
+	bool result = true;
+	
+	if(!mConnected)
+		result = false;
+	
+	if(mRenderDevices.empty())
+		result = false;
+	
+	return result;
+}
+
+void LLVoiceClient::refreshDeviceLists(bool clearCurrentList)
+{
+	if(clearCurrentList)
+	{
+		clearCaptureDevices();
+		clearRenderDevices();
+	}
+	getCaptureDevicesSendMessage();
+	getRenderDevicesSendMessage();
+}
+
+void LLVoiceClient::daemonDied()
+{
+	// The daemon died, so the connection is gone.  Reset everything and start over.
+	LL_WARNS("Voice") << "Connection to vivox daemon lost.  Resetting state."<< LL_ENDL;
+
+	// Try to relaunch the daemon
+	setState(stateDisableCleanup);
+}
+
+void LLVoiceClient::giveUp()
+{
+	// All has failed.  Clean up and stop trying.
+	closeSocket();
+	deleteAllSessions();
+	deleteAllBuddies();
+	
+	setState(stateJail);
+}
+
+static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel)
+{
+	F32 nat[3], nup[3], nl[3], nvel[3]; // the new at, up, left vectors and the  new position and velocity
+	F64 npos[3];
+	
+	// The original XML command was sent like this:
+	/*
+			<< "<Position>"
+				<< "<X>" << pos[VX] << "</X>"
+				<< "<Y>" << pos[VZ] << "</Y>"
+				<< "<Z>" << pos[VY] << "</Z>"
+			<< "</Position>"
+			<< "<Velocity>"
+				<< "<X>" << mAvatarVelocity[VX] << "</X>"
+				<< "<Y>" << mAvatarVelocity[VZ] << "</Y>"
+				<< "<Z>" << mAvatarVelocity[VY] << "</Z>"
+			<< "</Velocity>"
+			<< "<AtOrientation>"
+				<< "<X>" << l.mV[VX] << "</X>"
+				<< "<Y>" << u.mV[VX] << "</Y>"
+				<< "<Z>" << a.mV[VX] << "</Z>"
+			<< "</AtOrientation>"
+			<< "<UpOrientation>"
+				<< "<X>" << l.mV[VZ] << "</X>"
+				<< "<Y>" << u.mV[VY] << "</Y>"
+				<< "<Z>" << a.mV[VZ] << "</Z>"
+			<< "</UpOrientation>"
+			<< "<LeftOrientation>"
+				<< "<X>" << l.mV [VY] << "</X>"
+				<< "<Y>" << u.mV [VZ] << "</Y>"
+				<< "<Z>" << a.mV [VY] << "</Z>"
+			<< "</LeftOrientation>";
+	*/
+
+#if 1
+	// This was the original transform done when building the XML command
+	nat[0] = left.mV[VX];
+	nat[1] = up.mV[VX];
+	nat[2] = at.mV[VX];
+
+	nup[0] = left.mV[VZ];
+	nup[1] = up.mV[VY];
+	nup[2] = at.mV[VZ];
+
+	nl[0] = left.mV[VY];
+	nl[1] = up.mV[VZ];
+	nl[2] = at.mV[VY];
+
+	npos[0] = pos.mdV[VX];
+	npos[1] = pos.mdV[VZ];
+	npos[2] = pos.mdV[VY];
+
+	nvel[0] = vel.mV[VX];
+	nvel[1] = vel.mV[VZ];
+	nvel[2] = vel.mV[VY];
+
+	for(int i=0;i<3;++i) {
+		at.mV[i] = nat[i];
+		up.mV[i] = nup[i];
+		left.mV[i] = nl[i];
+		pos.mdV[i] = npos[i];
+	}
+	
+	// This was the original transform done in the SDK
+	nat[0] = at.mV[2];
+	nat[1] = 0; // y component of at vector is always 0, this was up[2]
+	nat[2] = -1 * left.mV[2];
+
+	// We override whatever the application gives us
+	nup[0] = 0; // x component of up vector is always 0
+	nup[1] = 1; // y component of up vector is always 1
+	nup[2] = 0; // z component of up vector is always 0
+
+	nl[0] = at.mV[0];
+	nl[1] = 0;  // y component of left vector is always zero, this was up[0]
+	nl[2] = -1 * left.mV[0];
+
+	npos[2] = pos.mdV[2] * -1.0;
+	npos[1] = pos.mdV[1];
+	npos[0] = pos.mdV[0];
+
+	for(int i=0;i<3;++i) {
+		at.mV[i] = nat[i];
+		up.mV[i] = nup[i];
+		left.mV[i] = nl[i];
+		pos.mdV[i] = npos[i];
+	}
+#else
+	// This is the compose of the two transforms (at least, that's what I'm trying for)
+	nat[0] = at.mV[VX];
+	nat[1] = 0; // y component of at vector is always 0, this was up[2]
+	nat[2] = -1 * up.mV[VZ];
+
+	// We override whatever the application gives us
+	nup[0] = 0; // x component of up vector is always 0
+	nup[1] = 1; // y component of up vector is always 1
+	nup[2] = 0; // z component of up vector is always 0
+
+	nl[0] = left.mV[VX];
+	nl[1] = 0;  // y component of left vector is always zero, this was up[0]
+	nl[2] = -1 * left.mV[VY];
+
+	npos[0] = pos.mdV[VX];
+	npos[1] = pos.mdV[VZ];
+	npos[2] = pos.mdV[VY] * -1.0;
+
+	nvel[0] = vel.mV[VX];
+	nvel[1] = vel.mV[VZ];
+	nvel[2] = vel.mV[VY];
+
+	for(int i=0;i<3;++i) {
+		at.mV[i] = nat[i];
+		up.mV[i] = nup[i];
+		left.mV[i] = nl[i];
+		pos.mdV[i] = npos[i];
+	}
+	
+#endif
+}
+
+void LLVoiceClient::sendPositionalUpdate(void)
+{	
+	std::ostringstream stream;
+	
+	if(mSpatialCoordsDirty)
+	{
+		LLVector3 l, u, a, vel;
+		LLVector3d pos;
+
+		mSpatialCoordsDirty = false;
+		
+		// Always send both speaker and listener positions together.
+		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Set3DPosition.1\">"		
+			<< "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>";
+		
+		stream << "<SpeakerPosition>";
+
+//		LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
+		l = mAvatarRot.getLeftRow();
+		u = mAvatarRot.getUpRow();
+		a = mAvatarRot.getFwdRow();
+		pos = mAvatarPosition;
+		vel = mAvatarVelocity;
+
+		// SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore.
+		// The old transform is replicated by this function.
+		oldSDKTransform(l, u, a, pos, vel);
+		
+		stream 
+			<< "<Position>"
+				<< "<X>" << pos.mdV[VX] << "</X>"
+				<< "<Y>" << pos.mdV[VY] << "</Y>"
+				<< "<Z>" << pos.mdV[VZ] << "</Z>"
+			<< "</Position>"
+			<< "<Velocity>"
+				<< "<X>" << vel.mV[VX] << "</X>"
+				<< "<Y>" << vel.mV[VY] << "</Y>"
+				<< "<Z>" << vel.mV[VZ] << "</Z>"
+			<< "</Velocity>"
+			<< "<AtOrientation>"
+				<< "<X>" << a.mV[VX] << "</X>"
+				<< "<Y>" << a.mV[VY] << "</Y>"
+				<< "<Z>" << a.mV[VZ] << "</Z>"
+			<< "</AtOrientation>"
+			<< "<UpOrientation>"
+				<< "<X>" << u.mV[VX] << "</X>"
+				<< "<Y>" << u.mV[VY] << "</Y>"
+				<< "<Z>" << u.mV[VZ] << "</Z>"
+			<< "</UpOrientation>"
+			<< "<LeftOrientation>"
+				<< "<X>" << l.mV [VX] << "</X>"
+				<< "<Y>" << l.mV [VY] << "</Y>"
+				<< "<Z>" << l.mV [VZ] << "</Z>"
+			<< "</LeftOrientation>";
+
+		stream << "</SpeakerPosition>";
+
+		stream << "<ListenerPosition>";
+
+		LLVector3d	earPosition;
+		LLVector3	earVelocity;
+		LLMatrix3	earRot;
+		
+		switch(mEarLocation)
+		{
+			case earLocCamera:
+			default:
+				earPosition = mCameraPosition;
+				earVelocity = mCameraVelocity;
+				earRot = mCameraRot;
+			break;
+			
+			case earLocAvatar:
+				earPosition = mAvatarPosition;
+				earVelocity = mAvatarVelocity;
+				earRot = mAvatarRot;
+			break;
+			
+			case earLocMixed:
+				earPosition = mAvatarPosition;
+				earVelocity = mAvatarVelocity;
+				earRot = mCameraRot;
+			break;
+		}
+
+		l = earRot.getLeftRow();
+		u = earRot.getUpRow();
+		a = earRot.getFwdRow();
+		pos = earPosition;
+		vel = earVelocity;
+
+//		LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
+		
+		oldSDKTransform(l, u, a, pos, vel);
+		
+		stream 
+			<< "<Position>"
+				<< "<X>" << pos.mdV[VX] << "</X>"
+				<< "<Y>" << pos.mdV[VY] << "</Y>"
+				<< "<Z>" << pos.mdV[VZ] << "</Z>"
+			<< "</Position>"
+			<< "<Velocity>"
+				<< "<X>" << vel.mV[VX] << "</X>"
+				<< "<Y>" << vel.mV[VY] << "</Y>"
+				<< "<Z>" << vel.mV[VZ] << "</Z>"
+			<< "</Velocity>"
+			<< "<AtOrientation>"
+				<< "<X>" << a.mV[VX] << "</X>"
+				<< "<Y>" << a.mV[VY] << "</Y>"
+				<< "<Z>" << a.mV[VZ] << "</Z>"
+			<< "</AtOrientation>"
+			<< "<UpOrientation>"
+				<< "<X>" << u.mV[VX] << "</X>"
+				<< "<Y>" << u.mV[VY] << "</Y>"
+				<< "<Z>" << u.mV[VZ] << "</Z>"
+			<< "</UpOrientation>"
+			<< "<LeftOrientation>"
+				<< "<X>" << l.mV [VX] << "</X>"
+				<< "<Y>" << l.mV [VY] << "</Y>"
+				<< "<Z>" << l.mV [VZ] << "</Z>"
+			<< "</LeftOrientation>";
+
+
+		stream << "</ListenerPosition>";
+
+		stream << "</Request>\n\n\n";
+	}	
+	
+	if(mAudioSession && (mAudioSession->mVolumeDirty || mAudioSession->mMuteDirty))
+	{
+		participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
+
+		mAudioSession->mVolumeDirty = false;
+		mAudioSession->mMuteDirty = false;
+		
+		for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
+		{
+			participantState *p = iter->second;
+
+			if(p->mVolumeDirty)
+			{
+				// Can't set volume/mute for yourself
+				if(!p->mIsSelf)
+				{
+					// scale from the range 0.0-1.0 to vivox volume in the range 0-100
+					S32 volume = llround(p->mVolume / VOLUME_SCALE_VIVOX);
+
+					bool mute = p->mOnMuteList;
+
+					if(mute)
+					{
+						// SetParticipantMuteForMe doesn't work in p2p sessions.
+						// If we want the user to be muted, set their volume to 0 as well.
+						// This isn't perfect, but it will at least reduce their volume to a minimum.
+						volume = 0;
+
+						// Mark the current volume level as set to prevent incoming events
+						// changing it to 0, so that we can return to it when unmuting.
+						p->mVolumeSet = true;
+					}
+
+					if(volume == 0)
+					{
+						mute = true;
+					}
+
+					LL_DEBUGS("Voice") << "Setting volume/mute for avatar " << p->mAvatarID << " to " << volume << (mute?"/true":"/false") << LL_ENDL;
+					
+					// SLIM SDK: Send both volume and mute commands.
+					
+					// Send a "volume for me" command for the user.
+					stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantVolumeForMe.1\">"
+						<< "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
+						<< "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
+						<< "<Volume>" << volume << "</Volume>"
+						<< "</Request>\n\n\n";
+
+					if(!mAudioSession->mIsP2P)
+					{
+						// Send a "mute for me" command for the user
+						// Doesn't work in P2P sessions
+						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantMuteForMe.1\">"
+							<< "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
+							<< "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
+							<< "<Mute>" << (mute?"1":"0") << "</Mute>"
+							<< "<Scope>Audio</Scope>"
+							<< "</Request>\n\n\n";
+					}
+				}
+				
+				p->mVolumeDirty = false;
+			}
+		}
+	}
+			
+	buildLocalAudioUpdates(stream);
+	
+	if(!stream.str().empty())
+	{
+		writeString(stream.str());
+	}
+	
+	// Friends list updates can be huge, especially on the first voice login of an account with lots of friends.
+	// Batching them all together can choke SLVoice, so send them in separate writes.
+	sendFriendsListUpdates();
+}
+
+void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
+{
+	if(mCaptureDeviceDirty)
+	{
+		LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
+	
+		stream 
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">"
+			<< "<CaptureDeviceSpecifier>" << mCaptureDevice << "</CaptureDeviceSpecifier>"
+		<< "</Request>"
+		<< "\n\n\n";
+		
+		mCaptureDeviceDirty = false;
+	}
+}
+
+void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
+{
+	if(mRenderDeviceDirty)
+	{
+		LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
+
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetRenderDevice.1\">"
+			<< "<RenderDeviceSpecifier>" << mRenderDevice << "</RenderDeviceSpecifier>"
+		<< "</Request>"
+		<< "\n\n\n";
+		mRenderDeviceDirty = false;
+	}
+}
+
+void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
+{
+	buildSetCaptureDevice(stream);
+
+	buildSetRenderDevice(stream);
+
+	if(mPTTDirty)
+	{
+		mPTTDirty = false;
+
+		// Send a local mute command.
+		// NOTE that the state of "PTT" is the inverse of "local mute".
+		//   (i.e. when PTT is true, we send a mute command with "false", and vice versa)
+		
+		LL_DEBUGS("Voice") << "Sending MuteLocalMic command with parameter " << (mPTT?"false":"true") << LL_ENDL;
+
+		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
+			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
+			<< "<Value>" << (mPTT?"false":"true") << "</Value>"
+			<< "</Request>\n\n\n";
+		
+	}
+
+	if(mSpeakerMuteDirty)
+	{
+		const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0))?"true":"false");
+
+		mSpeakerMuteDirty = false;
+
+		LL_INFOS("Voice") << "Setting speaker mute to " << muteval  << LL_ENDL;
+		
+		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalSpeaker.1\">"
+			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
+			<< "<Value>" << muteval << "</Value>"
+			<< "</Request>\n\n\n";	
+		
+	}
+	
+	if(mSpeakerVolumeDirty)
+	{
+		mSpeakerVolumeDirty = false;
+
+		LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume  << LL_ENDL;
+
+		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalSpeakerVolume.1\">"
+			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
+			<< "<Value>" << mSpeakerVolume << "</Value>"
+			<< "</Request>\n\n\n";
+			
+	}
+	
+	if(mMicVolumeDirty)
+	{
+		mMicVolumeDirty = false;
+
+		LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume  << LL_ENDL;
+
+		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalMicVolume.1\">"
+			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
+			<< "<Value>" << mMicVolume << "</Value>"
+			<< "</Request>\n\n\n";				
+	}
+
+	
+}
+
+void LLVoiceClient::checkFriend(const LLUUID& id)
+{
+	std::string name;
+	buddyListEntry *buddy = findBuddy(id);
+
+	// Make sure we don't add a name before it's been looked up.
+	if(gCacheName->getFullName(id, name))
+	{
+
+		const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
+		bool canSeeMeOnline = false;
+		if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
+			canSeeMeOnline = true;
+		
+		// When we get here, mNeedsSend is true and mInSLFriends is false.  Change them as necessary.
+		
+		if(buddy)
+		{
+			// This buddy is already in both lists.
+
+			if(name != buddy->mDisplayName)
+			{
+				// The buddy is in the list with the wrong name.  Update it with the correct name.
+				LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
+				buddy->mDisplayName = name;
+				buddy->mNeedsNameUpdate = true;		// This will cause the buddy to be resent.
+			}
+		}
+		else
+		{
+			// This buddy was not in the vivox list, needs to be added.
+			buddy = addBuddy(sipURIFromID(id), name);
+			buddy->mUUID = id;
+		}
+		
+		// In all the above cases, the buddy is in the SL friends list (which is how we got here).
+		buddy->mInSLFriends = true;
+		buddy->mCanSeeMeOnline = canSeeMeOnline;
+		buddy->mNameResolved = true;
+		
+	}
+	else
+	{
+		// This name hasn't been looked up yet.  Don't do anything with this buddy list entry until it has.
+		if(buddy)
+		{
+			buddy->mNameResolved = false;
+		}
+		
+		// Initiate a lookup.
+		// The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
+		lookupName(id);
+	}
+}
+
+void LLVoiceClient::clearAllLists()
+{
+	// FOR TESTING ONLY
+	
+	// This will send the necessary commands to delete ALL buddies, autoaccept rules, and block rules SLVoice tells us about.
+	buddyListMap::iterator buddy_it;
+	for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
+	{
+		buddyListEntry *buddy = buddy_it->second;
+		buddy_it++;
+		
+		std::ostringstream stream;
+
+		if(buddy->mInVivoxBuddies)
+		{
+			// delete this entry from the vivox buddy list
+			buddy->mInVivoxBuddies = false;
+			LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
+			stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddyDelete.1\">"
+				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+				<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
+				<< "</Request>\n\n\n";		
+		}
+
+		if(buddy->mHasBlockListEntry)
+		{
+			// Delete the associated block list entry (so the block list doesn't fill up with junk)
+			buddy->mHasBlockListEntry = false;
+			stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
+				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+				<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
+				<< "</Request>\n\n\n";								
+		}
+		if(buddy->mHasAutoAcceptListEntry)
+		{
+			// Delete the associated auto-accept list entry (so the auto-accept list doesn't fill up with junk)
+			buddy->mHasAutoAcceptListEntry = false;
+			stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
+				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+				<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
+				<< "</Request>\n\n\n";
+		}
+
+		writeString(stream.str());
+
+	}
+}
+
+void LLVoiceClient::sendFriendsListUpdates()
+{
+	if(mBuddyListMapPopulated && mBlockRulesListReceived && mAutoAcceptRulesListReceived && mFriendsListDirty)
+	{
+		mFriendsListDirty = false;
+		
+		if(0)
+		{
+			// FOR TESTING ONLY -- clear all buddy list, block list, and auto-accept list entries.
+			clearAllLists();
+			return;
+		}
+		
+		LL_INFOS("Voice") << "Checking vivox buddy list against friends list..." << LL_ENDL;
+		
+		buddyListMap::iterator buddy_it;
+		for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
+		{
+			// reset the temp flags in the local buddy list
+			buddy_it->second->mInSLFriends = false;
+		}
+		
+		// correlate with the friends list
+		{
+			LLCollectAllBuddies collect;
+			LLAvatarTracker::instance().applyFunctor(collect);
+			LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin();
+			LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
+			
+			for ( ; it != end; ++it)
+			{
+				checkFriend(it->second);
+			}
+			it = collect.mOffline.begin();
+			end = collect.mOffline.end();
+			for ( ; it != end; ++it)
+			{
+				checkFriend(it->second);
+			}
+		}
+				
+		LL_INFOS("Voice") << "Sending friend list updates..." << LL_ENDL;
+
+		for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
+		{
+			buddyListEntry *buddy = buddy_it->second;
+			buddy_it++;
+			
+			// Ignore entries that aren't resolved yet.
+			if(buddy->mNameResolved)
+			{
+				std::ostringstream stream;
+
+				if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
+				{					
+					if(mNumberOfAliases > 0)
+					{
+						// Add (or update) this entry in the vivox buddy list
+						buddy->mInVivoxBuddies = true;
+						buddy->mNeedsNameUpdate = false;
+						LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
+						stream 
+							<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
+								<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+								<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
+								<< "<DisplayName>" << buddy->mDisplayName << "</DisplayName>"
+								<< "<BuddyData></BuddyData>"	// Without this, SLVoice doesn't seem to parse the command.
+								<< "<GroupID>0</GroupID>"
+							<< "</Request>\n\n\n";	
+					}
+				}
+				else if(!buddy->mInSLFriends)
+				{
+					// This entry no longer exists in your SL friends list.  Remove all traces of it from the Vivox buddy list.
+ 					if(buddy->mInVivoxBuddies)
+					{
+						// delete this entry from the vivox buddy list
+						buddy->mInVivoxBuddies = false;
+						LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
+						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddyDelete.1\">"
+							<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+							<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
+							<< "</Request>\n\n\n";		
+					}
+
+					if(buddy->mHasBlockListEntry)
+					{
+						// Delete the associated block list entry, if any
+						buddy->mHasBlockListEntry = false;
+						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
+							<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+							<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
+							<< "</Request>\n\n\n";								
+					}
+					if(buddy->mHasAutoAcceptListEntry)
+					{
+						// Delete the associated auto-accept list entry, if any
+						buddy->mHasAutoAcceptListEntry = false;
+						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
+							<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+							<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
+							<< "</Request>\n\n\n";
+					}
+				}
+				
+				if(buddy->mInSLFriends)
+				{
+
+					if(buddy->mCanSeeMeOnline)
+					{
+						// Buddy should not be blocked.
+
+						// If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
+						
+						// If the buddy has a block list entry, delete it.
+						if(buddy->mHasBlockListEntry)
+						{
+							buddy->mHasBlockListEntry = false;
+							stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
+								<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+								<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
+								<< "</Request>\n\n\n";		
+							
+							
+							// If we just deleted a block list entry, add an auto-accept entry.
+							if(!buddy->mHasAutoAcceptListEntry)
+							{
+								buddy->mHasAutoAcceptListEntry = true;								
+								stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.CreateAutoAcceptRule.1\">"
+									<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+									<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
+									<< "<AutoAddAsBuddy>0</AutoAddAsBuddy>"
+									<< "</Request>\n\n\n";
+							}
+						}
+					}
+					else
+					{
+						// Buddy should be blocked.
+						
+						// If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
+
+						// If this buddy has an autoaccept entry, delete it
+						if(buddy->mHasAutoAcceptListEntry)
+						{
+							buddy->mHasAutoAcceptListEntry = false;
+							stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
+								<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+								<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
+								<< "</Request>\n\n\n";
+						
+							// If we just deleted an auto-accept entry, add a block list entry.
+							if(!buddy->mHasBlockListEntry)
+							{
+								buddy->mHasBlockListEntry = true;
+								stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.CreateBlockRule.1\">"
+									<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+									<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
+									<< "<PresenceOnly>1</PresenceOnly>"
+									<< "</Request>\n\n\n";								
+							}
+						}
+					}
+
+					if(!buddy->mInSLFriends && !buddy->mInVivoxBuddies)
+					{
+						// Delete this entry from the local buddy list.  This should NOT invalidate the iterator,
+						// since it has already been incremented to the next entry.
+						deleteBuddy(buddy->mURI);
+					}
+
+				}
+				writeString(stream.str());
+			}
+		}
+	}
+}
+
+/////////////////////////////
+// Response/Event handlers
+
+void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID)
+{	
+	if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "Connector.Create response failure: " << statusString << LL_ENDL;
+		setState(stateConnectorFailed);
+	}
+	else
+	{
+		// Connector created, move forward.
+		LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
+		mAPIVersion = versionID;
+		mConnectorHandle = connectorHandle;
+		if(getState() == stateConnectorStarting)
+		{
+			setState(stateConnectorStarted);
+		}
+	}
+}
+
+void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
+{ 
+	LL_DEBUGS("Voice") << "Account.Login response (" << statusCode << "): " << statusString << LL_ENDL;
+	
+	// Status code of 20200 means "bad password".  We may want to special-case that at some point.
+	
+	if ( statusCode == 401 )
+	{
+		// 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;
+		setState(stateLoginRetry);
+	}
+	else if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL;
+		setState(stateLoginFailed);
+	}
+	else
+	{
+		// Login succeeded, move forward.
+		mAccountHandle = accountHandle;
+		mNumberOfAliases = numberOfAliases;
+		// This needs to wait until the AccountLoginStateChangeEvent is received.
+//		if(getState() == stateLoggingIn)
+//		{
+//			setState(stateLoggedIn);
+//		}
+	}
+}
+
+void LLVoiceClient::sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
+{	
+	sessionState *session = findSessionBeingCreatedByURI(requestId);
+	
+	if(session)
+	{
+		session->mCreateInProgress = false;
+	}
+	
+	if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
+		if(session)
+		{
+			session->mErrorStatusCode = statusCode;		
+			session->mErrorStatusString = statusString;
+			if(session == mAudioSession)
+			{
+				setState(stateJoinSessionFailed);
+			}
+			else
+			{
+				reapSession(session);
+			}
+		}
+	}
+	else
+	{
+		LL_INFOS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
+		if(session)
+		{
+			setSessionHandle(session, sessionHandle);
+		}
+	}
+}
+
+void LLVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
+{	
+	sessionState *session = findSessionBeingCreatedByURI(requestId);
+	
+	if(session)
+	{
+		session->mCreateInProgress = false;
+	}
+	
+	if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "SessionGroup.AddSession response failure (" << statusCode << "): " << statusString << LL_ENDL;
+		if(session)
+		{
+			session->mErrorStatusCode = statusCode;		
+			session->mErrorStatusString = statusString;
+			if(session == mAudioSession)
+			{
+				setState(stateJoinSessionFailed);
+			}
+			else
+			{
+				reapSession(session);
+			}
+		}
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "SessionGroup.AddSession response received (success), session handle is " << sessionHandle << LL_ENDL;
+		if(session)
+		{
+			setSessionHandle(session, sessionHandle);
+		}
+	}
+}
+
+void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString)
+{
+	sessionState *session = findSession(requestId);
+	if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL;
+		if(session)
+		{
+			session->mMediaConnectInProgress = false;
+			session->mErrorStatusCode = statusCode;		
+			session->mErrorStatusString = statusString;
+			if(session == mAudioSession)
+				setState(stateJoinSessionFailed);
+		}
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "Session.Connect response received (success)" << LL_ENDL;
+	}
+}
+
+void LLVoiceClient::logoutResponse(int statusCode, std::string &statusString)
+{	
+	if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL;
+		// Should this ever fail?  do we care if it does?
+	}
+}
+
+void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statusString)
+{
+	if(statusCode != 0)
+	{
+		LL_WARNS("Voice") << "Connector.InitiateShutdown response failure: " << statusString << LL_ENDL;
+		// Should this ever fail?  do we care if it does?
+	}
+	
+	mConnected = false;
+	
+	if(getState() == stateConnectorStopping)
+	{
+		setState(stateConnectorStopped);
+	}
+}
+
+void LLVoiceClient::sessionAddedEvent(
+		std::string &uriString, 
+		std::string &alias, 
+		std::string &sessionHandle, 
+		std::string &sessionGroupHandle, 
+		bool isChannel, 
+		bool incoming,
+		std::string &nameString,
+		std::string &applicationString)
+{
+	sessionState *session = NULL;
+
+	LL_INFOS("Voice") << "session " << uriString << ", alias " << alias << ", name " << nameString << " handle " << sessionHandle << LL_ENDL;
+	
+	session = addSession(uriString, sessionHandle);
+	if(session)
+	{
+		session->mGroupHandle = sessionGroupHandle;
+		session->mIsChannel = isChannel;
+		session->mIncoming = incoming;
+		session->mAlias = alias;
+			
+		// Generate a caller UUID -- don't need to do this for channels
+		if(!session->mIsChannel)
+		{
+			if(IDFromName(session->mSIPURI, session->mCallerID))
+			{
+				// Normal URI(base64-encoded UUID) 
+			}
+			else if(!session->mAlias.empty() && IDFromName(session->mAlias, session->mCallerID))
+			{
+				// Wrong URI, but an alias is available.  Stash the incoming URI as an alternate
+				session->mAlternateSIPURI = session->mSIPURI;
+				
+				// and generate a proper URI from the ID.
+				setSessionURI(session, sipURIFromID(session->mCallerID));
+			}
+			else
+			{
+				LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL;
+				setUUIDFromStringHash(session->mCallerID, session->mSIPURI);
+				session->mSynthesizedCallerID = true;
+				
+				// Can't look up the name in this case -- we have to extract it from the URI.
+				std::string namePortion = nameFromsipURI(session->mSIPURI);
+				if(namePortion.empty())
+				{
+					// Didn't seem to be a SIP URI, just use the whole provided name.
+					namePortion = nameString;
+				}
+				
+				// Some incoming names may be separated with an underscore instead of a space.  Fix this.
+				LLStringUtil::replaceChar(namePortion, '_', ' ');
+				
+				// Act like we just finished resolving the name (this stores it in all the right places)
+				avatarNameResolved(session->mCallerID, namePortion);
+			}
+		
+			LL_INFOS("Voice") << "caller ID: " << session->mCallerID << LL_ENDL;
+
+			if(!session->mSynthesizedCallerID)
+			{
+				// If we got here, we don't have a proper name.  Initiate a lookup.
+				lookupName(session->mCallerID);
+			}
+		}
+	}
+}
+
+void LLVoiceClient::sessionGroupAddedEvent(std::string &sessionGroupHandle)
+{
+	LL_DEBUGS("Voice") << "handle " << sessionGroupHandle << LL_ENDL;
+	
+#if USE_SESSION_GROUPS
+	if(mMainSessionGroupHandle.empty())
+	{
+		// This is the first (i.e. "main") session group.  Save its handle.
+		mMainSessionGroupHandle = sessionGroupHandle;
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "Already had a session group handle " << mMainSessionGroupHandle << LL_ENDL;
+	}
+#endif
+}
+
+void LLVoiceClient::joinedAudioSession(sessionState *session)
+{
+	if(mAudioSession != session)
+	{
+		sessionState *oldSession = mAudioSession;
+
+		mAudioSession = session;
+		mAudioSessionChanged = true;
+
+		// The old session may now need to be deleted.
+		reapSession(oldSession);
+	}
+	
+	// This is the session we're joining.
+	if(getState() == stateJoiningSession)
+	{
+		setState(stateSessionJoined);
+		
+		// SLIM SDK: we don't always receive a participant state change for ourselves when joining a channel now.
+		// Add the current user as a participant here.
+		participantState *participant = session->addParticipant(sipURIFromName(mAccountName));
+		if(participant)
+		{
+			participant->mIsSelf = true;
+			lookupName(participant->mAvatarID);
+
+			LL_INFOS("Voice") << "added self as participant \"" << participant->mAccountName 
+					<< "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
+		}
+		
+		if(!session->mIsChannel)
+		{
+			// this is a p2p session.  Make sure the other end is added as a participant.
+			participantState *participant = session->addParticipant(session->mSIPURI);
+			if(participant)
+			{
+				if(participant->mAvatarIDValid)
+				{
+					lookupName(participant->mAvatarID);
+				}
+				else if(!session->mName.empty())
+				{
+					participant->mDisplayName = session->mName;
+					avatarNameResolved(participant->mAvatarID, session->mName);
+				}
+				
+				// TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here?
+				LL_INFOS("Voice") << "added caller as participant \"" << participant->mAccountName 
+						<< "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
+			}
+		}
+	}
+}
+
+void LLVoiceClient::sessionRemovedEvent(
+	std::string &sessionHandle, 
+	std::string &sessionGroupHandle)
+{
+	LL_INFOS("Voice") << "handle " << sessionHandle << LL_ENDL;
+	
+	sessionState *session = findSession(sessionHandle);
+	if(session)
+	{
+		leftAudioSession(session);
+
+		// This message invalidates the session's handle.  Set it to empty.
+		setSessionHandle(session);
+		
+		// This also means that the session's session group is now empty.
+		// Terminate the session group so it doesn't leak.
+		sessionGroupTerminateSendMessage(session);
+		
+		// Reset the media state (we now have no info)
+		session->mMediaStreamState = streamStateUnknown;
+		session->mTextStreamState = streamStateUnknown;
+		
+		// Conditionally delete the session
+		reapSession(session);
+	}
+	else
+	{
+		LL_WARNS("Voice") << "unknown session " << sessionHandle << " removed" << LL_ENDL;
+	}
+}
+
+void LLVoiceClient::reapSession(sessionState *session)
+{
+	if(session)
+	{
+		if(!session->mHandle.empty())
+		{
+			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL;
+		}
+		else if(session->mCreateInProgress)
+		{
+			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL;
+		}
+		else if(session->mMediaConnectInProgress)
+		{
+			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL;
+		}
+		else if(session == mAudioSession)
+		{
+			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL;
+		}
+		else if(session == mNextAudioSession)
+		{
+			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL;
+		}
+		else
+		{
+			// TODO: Question: Should we check for queued text messages here?
+			// We don't have a reason to keep tracking this session, so just delete it.
+			LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL;
+			deleteSession(session);
+			session = NULL;
+		}	
+	}
+	else
+	{
+//		LL_DEBUGS("Voice") << "session is NULL" << LL_ENDL;
+	}
+}
+
+// Returns true if the session seems to indicate we've moved to a region on a different voice server
+bool LLVoiceClient::sessionNeedsRelog(sessionState *session)
+{
+	bool result = false;
+	
+	if(session != NULL)
+	{
+		// Only make this check for spatial channels (so it won't happen for group or p2p calls)
+		if(session->mIsSpatial)
+		{
+			std::string::size_type atsign;
+			
+			atsign = session->mSIPURI.find("@");
+			
+			if(atsign != std::string::npos)
+			{
+				std::string urihost = session->mSIPURI.substr(atsign + 1);
+				if(stricmp(urihost.c_str(), mVoiceSIPURIHostName.c_str()))
+				{
+					// The hostname in this URI is different from what we expect.  This probably means we need to relog.
+					
+					// We could make a ProvisionVoiceAccountRequest and compare the result with the current values of
+					// mVoiceSIPURIHostName and mVoiceAccountServerURI to be really sure, but this is a pretty good indicator.
+					
+					result = true;
+				}
+			}
+		}
+	}
+	
+	return result;
+}
+
+void LLVoiceClient::leftAudioSession(
+	sessionState *session)
+{
+	if(mAudioSession == session)
+	{
+		switch(getState())
+		{
+			case stateJoiningSession:
+			case stateSessionJoined:
+			case stateRunning:
+			case stateLeavingSession:
+			case stateJoinSessionFailed:
+			case stateJoinSessionFailedWaiting:
+				// normal transition
+				LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
+				setState(stateSessionTerminated);
+			break;
+			
+			case stateSessionTerminated:
+				// this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
+				LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
+			break;
+			
+			default:
+				LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
+				setState(stateSessionTerminated);
+			break;
+		}
+	}
+}
+
+void LLVoiceClient::accountLoginStateChangeEvent(
+		std::string &accountHandle, 
+		int statusCode, 
+		std::string &statusString, 
+		int state)
+{
+	LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
+	/*
+		According to Mike S., status codes for this event are:
+		login_state_logged_out=0,
+        login_state_logged_in = 1,
+        login_state_logging_in = 2,
+        login_state_logging_out = 3,
+        login_state_resetting = 4,
+        login_state_error=100	
+	*/
+	
+	switch(state)
+	{
+		case 1:
+		if(getState() == stateLoggingIn)
+		{
+			setState(stateLoggedIn);
+		}
+		break;
+
+		case 3:
+			// The user is in the process of logging out.
+			setState(stateLoggingOut);
+		break;
+
+		case 0:
+			// The user has been logged out.  
+			setState(stateLoggedOut);
+		break;
+		
+		default:
+			//Used to be a commented out warning
+			LL_DEBUGS("Voice") << "unknown state: " << state << LL_ENDL;
+		break;
+	}
+}
+
+void LLVoiceClient::mediaStreamUpdatedEvent(
+	std::string &sessionHandle, 
+	std::string &sessionGroupHandle, 
+	int statusCode, 
+	std::string &statusString, 
+	int state, 
+	bool incoming)
+{
+	sessionState *session = findSession(sessionHandle);
+	
+	LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL;
+	
+	if(session)
+	{
+		// We know about this session
+		
+		// Save the state for later use
+		session->mMediaStreamState = state;
+		
+		switch(statusCode)
+		{
+			case 0:
+			case 200:
+				// generic success
+				// Don't change the saved error code (it may have been set elsewhere)
+			break;
+			default:
+				// save the status code for later
+				session->mErrorStatusCode = statusCode;
+			break;
+		}
+		
+		switch(state)
+		{
+			case streamStateIdle:
+				// Standard "left audio session"
+				session->mVoiceEnabled = false;
+				session->mMediaConnectInProgress = false;
+				leftAudioSession(session);
+			break;
+
+			case streamStateConnected:
+				session->mVoiceEnabled = true;
+				session->mMediaConnectInProgress = false;
+				joinedAudioSession(session);
+			break;
+			
+			case streamStateRinging:
+				if(incoming)
+				{
+					// Send the voice chat invite to the GUI layer
+					// *TODO: Question: Should we correlate with the mute list here?
+					session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
+					session->mVoiceInvitePending = true;
+					if(session->mName.empty())
+					{
+						lookupName(session->mCallerID);
+					}
+					else
+					{
+						// Act like we just finished resolving the name
+						avatarNameResolved(session->mCallerID, session->mName);
+					}
+				}
+			break;
+			
+			default:
+				LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
+			break;
+			
+		}
+		
+	}
+	else
+	{
+		LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL;
+	}
+}
+
+void LLVoiceClient::textStreamUpdatedEvent(
+	std::string &sessionHandle, 
+	std::string &sessionGroupHandle, 
+	bool enabled,
+	int state, 
+	bool incoming)
+{
+	sessionState *session = findSession(sessionHandle);
+	
+	if(session)
+	{
+		// Save the state for later use
+		session->mTextStreamState = state;
+		
+		// We know about this session
+		switch(state)
+		{
+			case 0:	// We see this when the text stream closes
+				LL_DEBUGS("Voice") << "stream closed" << LL_ENDL;
+			break;
+			
+			case 1:	// We see this on an incoming call from the Connector
+				// Try to send any text messages queued for this session.
+				sendQueuedTextMessages(session);
+
+				// Send the text chat invite to the GUI layer
+				// TODO: Question: Should we correlate with the mute list here?
+				session->mTextInvitePending = true;
+				if(session->mName.empty())
+				{
+					lookupName(session->mCallerID);
+				}
+				else
+				{
+					// Act like we just finished resolving the name
+					avatarNameResolved(session->mCallerID, session->mName);
+				}
+			break;
+
+			default:
+				LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
+			break;
+			
+		}
+	}
+}
+
+void LLVoiceClient::participantAddedEvent(
+		std::string &sessionHandle, 
+		std::string &sessionGroupHandle, 
+		std::string &uriString, 
+		std::string &alias, 
+		std::string &nameString, 
+		std::string &displayNameString, 
+		int participantType)
+{
+	sessionState *session = findSession(sessionHandle);
+	if(session)
+	{
+		participantState *participant = session->addParticipant(uriString);
+		if(participant)
+		{
+			participant->mAccountName = nameString;
+
+			LL_DEBUGS("Voice") << "added participant \"" << participant->mAccountName 
+					<< "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
+
+			if(participant->mAvatarIDValid)
+			{
+				// Initiate a lookup
+				lookupName(participant->mAvatarID);
+			}
+			else
+			{
+				// If we don't have a valid avatar UUID, we need to fill in the display name to make the active speakers floater work.
+				std::string namePortion = nameFromsipURI(uriString);
+				if(namePortion.empty())
+				{
+					// Problem with the SIP URI, fall back to the display name
+					namePortion = displayNameString;
+				}
+				if(namePortion.empty())
+				{
+					// Problems with both of the above, fall back to the account name
+					namePortion = nameString;
+				}
+				
+				// Set the display name (which is a hint to the active speakers window not to do its own lookup)
+				participant->mDisplayName = namePortion;
+				avatarNameResolved(participant->mAvatarID, namePortion);
+			}
+		}
+	}
+}
+
+void LLVoiceClient::participantRemovedEvent(
+		std::string &sessionHandle, 
+		std::string &sessionGroupHandle, 
+		std::string &uriString, 
+		std::string &alias, 
+		std::string &nameString)
+{
+	sessionState *session = findSession(sessionHandle);
+	if(session)
+	{
+		participantState *participant = session->findParticipant(uriString);
+		if(participant)
+		{
+			session->removeParticipant(participant);
+		}
+		else
+		{
+			LL_DEBUGS("Voice") << "unknown participant " << uriString << LL_ENDL;
+		}
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
+	}
+}
+
+
+void LLVoiceClient::participantUpdatedEvent(
+		std::string &sessionHandle, 
+		std::string &sessionGroupHandle, 
+		std::string &uriString, 
+		std::string &alias, 
+		bool isModeratorMuted, 
+		bool isSpeaking, 
+		int volume, 
+		F32 energy)
+{
+	sessionState *session = findSession(sessionHandle);
+	if(session)
+	{
+		participantState *participant = session->findParticipant(uriString);
+		
+		if(participant)
+		{
+			participant->mIsSpeaking = isSpeaking;
+			participant->mIsModeratorMuted = isModeratorMuted;
+
+			// SLIM SDK: convert range: ensure that energy is set to zero if is_speaking is false
+			if (isSpeaking)
+			{
+				participant->mSpeakingTimeout.reset();
+				participant->mPower = energy;
+			}
+			else
+			{
+				participant->mPower = 0.0f;
+			}
+
+			// Ignore incoming volume level if it has been explicitly set, or there
+			//  is a volume or mute change pending.
+			if ( !participant->mVolumeSet && !participant->mVolumeDirty)
+			{
+				participant->mVolume = (F32)volume * VOLUME_SCALE_VIVOX;
+			}
+
+			// *HACK: mantipov: added while working on EXT-3544
+			/*
+			Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE 
+			LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER.
+			
+			participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted
+			Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug.
+			Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates.
+			
+			But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post()
+			voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager
+			and event is not fired.
+
+			So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it
+			in LLCallFloater::draw()
+			*/
+			LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
+
+			// ignore session ID of local chat
+			if (voice_cnl && voice_cnl->getSessionID().notNull())
+			{
+				LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID());
+				if (speaker_manager)
+				{
+					speaker_manager->update(true);
+				}
+			}
+		}
+		else
+		{
+			LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
+		}
+	}
+	else
+	{
+		LL_INFOS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
+	}
+}
+
+void LLVoiceClient::buddyPresenceEvent(
+		std::string &uriString, 
+		std::string &alias, 
+		std::string &statusString,
+		std::string &applicationString)
+{
+	buddyListEntry *buddy = findBuddy(uriString);
+	
+	if(buddy)
+	{
+		LL_DEBUGS("Voice") << "Presence event for " << buddy->mDisplayName << " status \"" << statusString << "\", application \"" << applicationString << "\""<< LL_ENDL;
+		LL_DEBUGS("Voice") << "before: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
+
+		if(applicationString.empty())
+		{
+			// This presence event is from a client that doesn't set up the Application string.  Do things the old-skool way.
+			// NOTE: this will be needed to support people who aren't on the 3010-class SDK yet.
+
+			if ( stricmp("Unknown", statusString.c_str())== 0) 
+			{
+				// User went offline with a non-SLim-enabled viewer.
+				buddy->mOnlineSL = false;
+			}
+			else if ( stricmp("Online", statusString.c_str())== 0) 
+			{
+				// User came online with a non-SLim-enabled viewer.
+				buddy->mOnlineSL = true;
+			}
+			else
+			{
+				// If the user is online through SLim, their status will be "Online-slc", "Away", or something else.
+				// NOTE: we should never see this unless someone is running an OLD version of SLim -- the versions that should be in use now all set the application string.
+				buddy->mOnlineSLim = true;
+			} 
+		}
+		else if(applicationString.find("SecondLifeViewer") != std::string::npos)
+		{
+			// This presence event is from a viewer that sets the application string
+			if ( stricmp("Unknown", statusString.c_str())== 0) 
+			{
+				// Viewer says they're offline
+				buddy->mOnlineSL = false;
+			}
+			else
+			{
+				// Viewer says they're online
+				buddy->mOnlineSL = true;
+			}
+		}
+		else
+		{
+			// This presence event is from something which is NOT the SL viewer (assume it's SLim).
+			if ( stricmp("Unknown", statusString.c_str())== 0) 
+			{
+				// SLim says they're offline
+				buddy->mOnlineSLim = false;
+			}
+			else
+			{
+				// SLim says they're online
+				buddy->mOnlineSLim = true;
+			}
+		} 
+
+		LL_DEBUGS("Voice") << "after: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
+		
+		// HACK -- increment the internal change serial number in the LLRelationship (without changing the actual status), so the UI notices the change.
+		LLAvatarTracker::instance().setBuddyOnline(buddy->mUUID,LLAvatarTracker::instance().isBuddyOnline(buddy->mUUID));
+
+		notifyFriendObservers();
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "Presence for unknown buddy " << uriString << LL_ENDL;
+	}	
+}
+
+void LLVoiceClient::messageEvent(
+		std::string &sessionHandle, 
+		std::string &uriString, 
+		std::string &alias, 
+		std::string &messageHeader, 
+		std::string &messageBody,
+		std::string &applicationString)
+{
+	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)
+	{
+		std::string message;
+
+		{
+			const std::string startMarker = "<body";
+			const std::string startMarker2 = ">";
+			const std::string endMarker = "</body>";
+			const std::string startSpan = "<span";
+			const std::string endSpan = "</span>";
+			std::string::size_type start;
+			std::string::size_type end;
+			
+			// Default to displaying the raw string, so the message gets through.
+			message = messageBody;
+
+			// Find the actual message text within the XML fragment
+			start = messageBody.find(startMarker);
+			start = messageBody.find(startMarker2, start);
+			end = messageBody.find(endMarker);
+
+			if(start != std::string::npos)
+			{
+				start += startMarker2.size();
+				
+				if(end != std::string::npos)
+					end -= start;
+					
+				message.assign(messageBody, start, end);
+			}
+			else 
+			{
+				// Didn't find a <body>, try looking for a <span> instead.
+				start = messageBody.find(startSpan);
+				start = messageBody.find(startMarker2, start);
+				end = messageBody.find(endSpan);
+				
+				if(start != std::string::npos)
+				{
+					start += startMarker2.size();
+					
+					if(end != std::string::npos)
+						end -= start;
+					
+					message.assign(messageBody, start, end);
+				}			
+			}
+		}	
+		
+//		LL_DEBUGS("Voice") << "    raw message = \n" << message << LL_ENDL;
+
+		// strip formatting tags
+		{
+			std::string::size_type start;
+			std::string::size_type end;
+			
+			while((start = message.find('<')) != std::string::npos)
+			{
+				if((end = message.find('>', start + 1)) != std::string::npos)
+				{
+					// Strip out the tag
+					message.erase(start, (end + 1) - start);
+				}
+				else
+				{
+					// Avoid an infinite loop
+					break;
+				}
+			}
+		}
+		
+		// Decode ampersand-escaped chars
+		{
+			std::string::size_type mark = 0;
+
+			// The text may contain text encoded with &lt;, &gt;, and &amp;
+			mark = 0;
+			while((mark = message.find("&lt;", mark)) != std::string::npos)
+			{
+				message.replace(mark, 4, "<");
+				mark += 1;
+			}
+			
+			mark = 0;
+			while((mark = message.find("&gt;", mark)) != std::string::npos)
+			{
+				message.replace(mark, 4, ">");
+				mark += 1;
+			}
+			
+			mark = 0;
+			while((mark = message.find("&amp;", mark)) != std::string::npos)
+			{
+				message.replace(mark, 5, "&");
+				mark += 1;
+			}
+		}
+		
+		// strip leading/trailing whitespace (since we always seem to get a couple newlines)
+		LLStringUtil::trim(message);
+		
+//		LL_DEBUGS("Voice") << "    stripped message = \n" << message << LL_ENDL;
+		
+		sessionState *session = findSession(sessionHandle);
+		if(session)
+		{
+			bool is_busy = gAgent.getBusy();
+			bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
+			bool is_linden = LLMuteList::getInstance()->isLinden(session->mName);
+			bool quiet_chat = false;
+			LLChat chat;
+
+			chat.mMuted = is_muted && !is_linden;
+			
+			if(!chat.mMuted)
+			{
+				chat.mFromID = session->mCallerID;
+				chat.mFromName = session->mName;
+				chat.mSourceType = CHAT_SOURCE_AGENT;
+
+				if(is_busy && !is_linden)
+				{
+					quiet_chat = true;
+					// TODO: Question: Return busy mode response here?  Or maybe when session is started instead?
+				}
+								
+				LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
+				gIMMgr->addMessage(session->mIMSessionID,
+						session->mCallerID,
+						session->mName.c_str(),
+						message.c_str(),
+						LLStringUtil::null,		// default arg
+						IM_NOTHING_SPECIAL,		// default arg
+						0,						// default arg
+						LLUUID::null,			// default arg
+						LLVector3::zero,		// default arg
+						true);					// prepend name and make it a link to the user's profile
+			}
+		}		
+	}
+}
+
+void LLVoiceClient::sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType)
+{
+	sessionState *session = findSession(sessionHandle);
+	
+	if(session)
+	{
+		participantState *participant = session->findParticipant(uriString);
+		if(participant)
+		{
+			if (!stricmp(notificationType.c_str(), "Typing"))
+			{
+				// Other end started typing
+				// TODO: The proper way to add a typing notification seems to be LLIMMgr::processIMTypingStart().
+				// It requires an LLIMInfo for the message, which we don't have here.
+			}
+			else if (!stricmp(notificationType.c_str(), "NotTyping"))
+			{
+				// Other end stopped typing
+				// TODO: The proper way to remove a typing notification seems to be LLIMMgr::processIMTypingStop().
+				// It requires an LLIMInfo for the message, which we don't have here.
+			}
+			else
+			{
+				LL_DEBUGS("Voice") << "Unknown notification type " << notificationType << "for participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
+			}
+		}
+		else
+		{
+			LL_DEBUGS("Voice") << "Unknown participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
+		}
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "Unknown session handle " << sessionHandle << LL_ENDL;
+	}
+}
+
+void LLVoiceClient::subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType)
+{
+	buddyListEntry *buddy = findBuddy(buddyURI);
+	
+	if(!buddy)
+	{
+		// Couldn't find buddy by URI, try converting the alias...
+		if(!alias.empty())
+		{
+			LLUUID id;
+			if(IDFromName(alias, id))
+			{
+				buddy = findBuddy(id);
+			}
+		}
+	}
+	
+	if(buddy)
+	{
+		std::ostringstream stream;
+		
+		if(buddy->mCanSeeMeOnline)
+		{
+			// Sending the response will create an auto-accept rule
+			buddy->mHasAutoAcceptListEntry = true;
+		}
+		else
+		{
+			// Sending the response will create a block rule
+			buddy->mHasBlockListEntry = true;
+		}
+		
+		if(buddy->mInSLFriends)
+		{
+			buddy->mInVivoxBuddies = true;
+		}
+		
+		stream
+			<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.SendSubscriptionReply.1\">"
+				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+				<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
+				<< "<RuleType>" << (buddy->mCanSeeMeOnline?"Allow":"Hide") << "</RuleType>"
+				<< "<AutoAccept>"<< (buddy->mInSLFriends?"1":"0")<< "</AutoAccept>"
+				<< "<SubscriptionHandle>" << subscriptionHandle << "</SubscriptionHandle>"
+			<< "</Request>"
+			<< "\n\n\n";
+			
+		writeString(stream.str());
+	}
+}
+
+void LLVoiceClient::auxAudioPropertiesEvent(F32 energy)
+{
+	LL_DEBUGS("Voice") << "got energy " << energy << LL_ENDL;
+	mTuningEnergy = energy;
+}
+
+void LLVoiceClient::buddyListChanged()
+{
+	// This is called after we receive a BuddyAndGroupListChangedEvent.
+	mBuddyListMapPopulated = true;
+	mFriendsListDirty = true;
+}
+
+void LLVoiceClient::muteListChanged()
+{
+	// The user's mute list has been updated.  Go through the current participant list and sync it with the mute list.
+	if(mAudioSession)
+	{
+		participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
+		
+		for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
+		{
+			participantState *p = iter->second;
+			
+			// Check to see if this participant is on the mute list already
+			if(p->updateMuteState())
+				mAudioSession->mMuteDirty = true;
+		}
+	}
+}
+
+void LLVoiceClient::updateFriends(U32 mask)
+{
+	if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::POWERS))
+	{
+		// Just resend the whole friend list to the daemon
+		mFriendsListDirty = true;
+	}
+}
+
+/////////////////////////////
+// Managing list of participants
+LLVoiceClient::participantState::participantState(const std::string &uri) : 
+	 mURI(uri), 
+	 mPTT(false), 
+	 mIsSpeaking(false), 
+	 mIsModeratorMuted(false), 
+	 mLastSpokeTimestamp(0.f), 
+	 mPower(0.f), 
+	 mVolume(VOLUME_DEFAULT),
+	 mOnMuteList(false),
+	 mVolumeSet(false),
+	 mVolumeDirty(false),
+	 mAvatarIDValid(false),
+	 mIsSelf(false)
+{
+}
+
+LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(const std::string &uri)
+{
+	participantState *result = NULL;
+	bool useAlternateURI = false;
+	
+	// Note: this is mostly the body of LLVoiceClient::sessionState::findParticipant(), but since we need to know if it
+	// matched the alternate SIP URI (so we can add it properly), we need to reproduce it here.
+	{
+		participantMap::iterator iter = mParticipantsByURI.find(&uri);
+
+		if(iter == mParticipantsByURI.end())
+		{
+			if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
+			{
+				// This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
+				// Use mSIPURI instead, since it will be properly encoded.
+				iter = mParticipantsByURI.find(&(mSIPURI));
+				useAlternateURI = true;
+			}
+		}
+
+		if(iter != mParticipantsByURI.end())
+		{
+			result = iter->second;
+		}
+	}
+		
+	if(!result)
+	{
+		// participant isn't already in one list or the other.
+		result = new participantState(useAlternateURI?mSIPURI:uri);
+		mParticipantsByURI.insert(participantMap::value_type(&(result->mURI), result));
+		mParticipantsChanged = true;
+		
+		// Try to do a reverse transform on the URI to get the GUID back.
+		{
+			LLUUID id;
+			if(IDFromName(result->mURI, id))
+			{
+				result->mAvatarIDValid = true;
+				result->mAvatarID = id;
+
+				if(result->updateMuteState())
+					mMuteDirty = true;
+			}
+			else
+			{
+				// Create a UUID by hashing the URI, but do NOT set mAvatarIDValid.
+				// This tells both code in LLVoiceClient and code in llfloateractivespeakers.cpp that the ID will not be in the name cache.
+				setUUIDFromStringHash(result->mAvatarID, uri);
+			}
+		}
+		
+		mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result));
+
+		if (LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID, result->mVolume))
+		{
+			result->mVolumeDirty = true;
+			mVolumeDirty = true;
+		}
+
+		LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
+	}
+	
+	return result;
+}
+
+bool LLVoiceClient::participantState::updateMuteState()
+{
+	bool result = false;
+	
+	if(mAvatarIDValid)
+	{
+		bool isMuted = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
+		if(mOnMuteList != isMuted)
+		{
+			mOnMuteList = isMuted;
+			mVolumeDirty = true;
+			result = true;
+		}
+	}
+	return result;
+}
+
+bool LLVoiceClient::participantState::isAvatar()
+{
+	return mAvatarIDValid;
+}
+
+void LLVoiceClient::sessionState::removeParticipant(LLVoiceClient::participantState *participant)
+{
+	if(participant)
+	{
+		participantMap::iterator iter = mParticipantsByURI.find(&(participant->mURI));
+		participantUUIDMap::iterator iter2 = mParticipantsByUUID.find(&(participant->mAvatarID));
+		
+		LL_DEBUGS("Voice") << "participant \"" << participant->mURI <<  "\" (" << participant->mAvatarID << ") removed." << LL_ENDL;
+		
+		if(iter == mParticipantsByURI.end())
+		{
+			LL_ERRS("Voice") << "Internal error: participant " << participant->mURI << " not in URI map" << LL_ENDL;
+		}
+		else if(iter2 == mParticipantsByUUID.end())
+		{
+			LL_ERRS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL;
+		}
+		else if(iter->second != iter2->second)
+		{
+			LL_ERRS("Voice") << "Internal error: participant mismatch!" << LL_ENDL;
+		}
+		else
+		{
+			mParticipantsByURI.erase(iter);
+			mParticipantsByUUID.erase(iter2);
+			
+			delete participant;
+			mParticipantsChanged = true;
+		}
+	}
+}
+
+void LLVoiceClient::sessionState::removeAllParticipants()
+{
+	LL_DEBUGS("Voice") << "called" << LL_ENDL;
+
+	while(!mParticipantsByURI.empty())
+	{
+		removeParticipant(mParticipantsByURI.begin()->second);
+	}
+	
+	if(!mParticipantsByUUID.empty())
+	{
+		LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL;
+	}
+}
+
+LLVoiceClient::participantMap *LLVoiceClient::getParticipantList(void)
+{
+	participantMap *result = NULL;
+	if(mAudioSession)
+	{
+		result = &(mAudioSession->mParticipantsByURI);
+	}
+	return result;
+}
+
+void LLVoiceClient::getParticipantsUUIDSet(std::set<LLUUID>& participant_uuids)
+{
+	if (NULL == mAudioSession) return;
+
+	participantUUIDMap::const_iterator it = mAudioSession->mParticipantsByUUID.begin(),
+		it_end = mAudioSession->mParticipantsByUUID.end();
+	for (; it != it_end; ++it)
+	{
+		participant_uuids.insert((*(*it).first));
+	}
+}
+
+LLVoiceClient::participantState *LLVoiceClient::sessionState::findParticipant(const std::string &uri)
+{
+	participantState *result = NULL;
+	
+	participantMap::iterator iter = mParticipantsByURI.find(&uri);
+
+	if(iter == mParticipantsByURI.end())
+	{
+		if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
+		{
+			// This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
+			// Look up the other URI
+			iter = mParticipantsByURI.find(&(mSIPURI));
+		}
+	}
+
+	if(iter != mParticipantsByURI.end())
+	{
+		result = iter->second;
+	}
+		
+	return result;
+}
+
+LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByID(const LLUUID& id)
+{
+	participantState * result = NULL;
+	participantUUIDMap::iterator iter = mParticipantsByUUID.find(&id);
+
+	if(iter != mParticipantsByUUID.end())
+	{
+		result = iter->second;
+	}
+
+	return result;
+}
+
+LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID& id)
+{
+	participantState * result = NULL;
+	
+	if(mAudioSession)
+	{
+		result = mAudioSession->findParticipantByID(id);
+	}
+	
+	return result;
+}
+
+
+void LLVoiceClient::parcelChanged()
+{
+	if(getState() >= stateNoChannel)
+	{
+		// If the user is logged in, start a channel lookup.
+		LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
+
+		std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest");
+		LLSD data;
+		LLHTTPClient::post(
+			url,
+			data,
+			new LLVoiceClientCapResponder);
+	}
+	else
+	{
+		// The transition to stateNoChannel needs to kick this off again.
+		LL_INFOS("Voice") << "not logged in yet, deferring" << LL_ENDL;
+	}
+}
+
+void LLVoiceClient::switchChannel(
+	std::string uri,
+	bool spatial,
+	bool no_reconnect,
+	bool is_p2p,
+	std::string hash)
+{
+	bool needsSwitch = false;
+	
+	LL_DEBUGS("Voice") 
+		<< "called in state " << state2string(getState()) 
+		<< " with uri \"" << uri << "\"" 
+		<< (spatial?", spatial is true":", spatial is false")
+		<< LL_ENDL;
+	
+	switch(getState())
+	{
+		case stateJoinSessionFailed:
+		case stateJoinSessionFailedWaiting:
+		case stateNoChannel:
+			// Always switch to the new URI from these states.
+			needsSwitch = true;
+		break;
+
+		default:
+			if(mSessionTerminateRequested)
+			{
+				// If a terminate has been requested, we need to compare against where the URI we're already headed to.
+				if(mNextAudioSession)
+				{
+					if(mNextAudioSession->mSIPURI != uri)
+						needsSwitch = true;
+				}
+				else
+				{
+					// mNextAudioSession is null -- this probably means we're on our way back to spatial.
+					if(!uri.empty())
+					{
+						// We do want to process a switch in this case.
+						needsSwitch = true;
+					}
+				}
+			}
+			else
+			{
+				// Otherwise, compare against the URI we're in now.
+				if(mAudioSession)
+				{
+					if(mAudioSession->mSIPURI != uri)
+					{
+						needsSwitch = true;
+					}
+				}
+				else
+				{
+					if(!uri.empty())
+					{
+						// mAudioSession is null -- it's not clear what case would cause this.
+						// For now, log it as a warning and see if it ever crops up.
+						LL_WARNS("Voice") << "No current audio session." << LL_ENDL;
+					}
+				}
+			}
+		break;
+	}
+	
+	if(needsSwitch)
+	{
+		if(uri.empty())
+		{
+			// Leave any channel we may be in
+			LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL;
+
+			sessionState *oldSession = mNextAudioSession;
+			mNextAudioSession = NULL;
+
+			// The old session may now need to be deleted.
+			reapSession(oldSession);
+
+			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
+		}
+		else
+		{
+			LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL;
+
+			mNextAudioSession = addSession(uri);
+			mNextAudioSession->mHash = hash;
+			mNextAudioSession->mIsSpatial = spatial;
+			mNextAudioSession->mReconnect = !no_reconnect;
+			mNextAudioSession->mIsP2P = is_p2p;
+		}
+		
+		if(getState() <= stateNoChannel)
+		{
+			// We're already set up to join a channel, just needed to fill in the session URI
+		}
+		else
+		{
+			// State machine will come around and rejoin if uri/handle is not empty.
+			sessionTerminate();
+		}
+	}
+}
+
+void LLVoiceClient::joinSession(sessionState *session)
+{
+	mNextAudioSession = session;
+	
+	if(getState() <= stateNoChannel)
+	{
+		// We're already set up to join a channel, just needed to fill in the session handle
+	}
+	else
+	{
+		// State machine will come around and rejoin if uri/handle is not empty.
+		sessionTerminate();
+	}
+}
+
+void LLVoiceClient::setNonSpatialChannel(
+	const std::string &uri,
+	const std::string &credentials)
+{
+	switchChannel(uri, false, false, false, credentials);
+}
+
+void LLVoiceClient::setSpatialChannel(
+	const std::string &uri,
+	const std::string &credentials)
+{
+	mSpatialSessionURI = uri;
+	mSpatialSessionCredentials = credentials;
+	mAreaVoiceDisabled = mSpatialSessionURI.empty();
+
+	LL_DEBUGS("Voice") << "got spatial channel uri: \"" << uri << "\"" << LL_ENDL;
+	
+	if((mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial)))
+	{
+		// User is in a non-spatial chat or joining a non-spatial chat.  Don't switch channels.
+		LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL;
+	}
+	else
+	{
+		switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
+	}
+}
+
+void LLVoiceClient::callUser(const LLUUID &uuid)
+{
+	std::string userURI = sipURIFromID(uuid);
+
+	switchChannel(userURI, false, true, true);
+}
+
+LLVoiceClient::sessionState* LLVoiceClient::startUserIMSession(const LLUUID &uuid)
+{
+	// Figure out if a session with the user already exists
+	sessionState *session = findSession(uuid);
+	if(!session)
+	{
+		// No session with user, need to start one.
+		std::string uri = sipURIFromID(uuid);
+		session = addSession(uri);
+
+		llassert(session);
+		if (!session) return NULL;
+
+		session->mIsSpatial = false;
+		session->mReconnect = false;	
+		session->mIsP2P = true;
+		session->mCallerID = uuid;
+	}
+	
+	if(session->mHandle.empty())
+	{
+		// Session isn't active -- start it up.
+		sessionCreateSendMessage(session, false, true);
+	}
+	else
+	{	
+		// Session is already active -- start up text.
+		sessionTextConnectSendMessage(session);
+	}
+	
+	return session;
+}
+
+bool LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message)
+{
+	bool result = false;
+
+	// Attempt to locate the indicated session
+	sessionState *session = startUserIMSession(participant_id);
+	if(session)
+	{
+		// found the session, attempt to send the message
+		session->mTextMsgQueue.push(message);
+		
+		// Try to send queued messages (will do nothing if the session is not open yet)
+		sendQueuedTextMessages(session);
+
+		// The message is queued, so we succeed.
+		result = true;
+	}	
+	else
+	{
+		LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL;
+	}
+	
+	return result;
+}
+
+void LLVoiceClient::sendQueuedTextMessages(sessionState *session)
+{
+	if(session->mTextStreamState == 1)
+	{
+		if(!session->mTextMsgQueue.empty())
+		{
+			std::ostringstream stream;
+			
+			while(!session->mTextMsgQueue.empty())
+			{
+				std::string message = session->mTextMsgQueue.front();
+				session->mTextMsgQueue.pop();
+				stream
+				<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SendMessage.1\">"
+					<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+					<< "<MessageHeader>text/HTML</MessageHeader>"
+					<< "<MessageBody>" << message << "</MessageBody>"
+				<< "</Request>"
+				<< "\n\n\n";
+			}		
+			writeString(stream.str());
+		}
+	}
+	else
+	{
+		// Session isn't connected yet, defer until later.
+	}
+}
+
+void LLVoiceClient::endUserIMSession(const LLUUID &uuid)
+{
+	// Figure out if a session with the user exists
+	sessionState *session = findSession(uuid);
+	if(session)
+	{
+		// found the session
+		if(!session->mHandle.empty())
+		{
+			sessionTextDisconnectSendMessage(session);
+		}
+	}	
+	else
+	{
+		LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL;
+	}
+}
+
+bool LLVoiceClient::answerInvite(std::string &sessionHandle)
+{
+	// this is only ever used to answer incoming p2p call invites.
+	
+	sessionState *session = findSession(sessionHandle);
+	if(session)
+	{
+		session->mIsSpatial = false;
+		session->mReconnect = false;	
+		session->mIsP2P = true;
+
+		joinSession(session);
+		return true;
+	}
+	
+	return false;
+}
+
+bool LLVoiceClient::isOnlineSIP(const LLUUID &id)
+{
+	bool result = false;
+	buddyListEntry *buddy = findBuddy(id);
+	if(buddy)
+	{
+		result = buddy->mOnlineSLim;
+		LL_DEBUGS("Voice") << "Buddy " << buddy->mDisplayName << " is SIP " << (result?"online":"offline") << LL_ENDL;
+	}
+
+	if(!result)
+	{
+		// This user isn't on the buddy list or doesn't show online status through the buddy list, but could be a participant in an existing session if they initiated a text IM.
+		sessionState *session = findSession(id);
+		if(session && !session->mHandle.empty())
+		{
+			if((session->mTextStreamState != streamStateUnknown) || (session->mMediaStreamState > streamStateIdle))
+			{
+				LL_DEBUGS("Voice") << "Open session with " << id << " found, returning SIP online state" << LL_ENDL;
+				// we have a p2p text session open with this user, so by definition they're online.
+				result = true;
+			}
+		}
+	}
+	
+	return result;
+}
+
+// Returns true if the indicated participant in the current audio session is really an SL avatar.
+// Currently this will be false only for PSTN callers into group chats, and PSTN p2p calls.
+bool LLVoiceClient::isParticipantAvatar(const LLUUID &id)
+{
+	bool result = true; 
+	sessionState *session = findSession(id);
+	
+	if(session != NULL)
+	{
+		// this is a p2p session with the indicated caller, or the session with the specified UUID.
+		if(session->mSynthesizedCallerID)
+			result = false;
+	}
+	else
+	{
+		// Didn't find a matching session -- check the current audio session for a matching participant
+		if(mAudioSession != NULL)
+		{
+			participantState *participant = findParticipantByID(id);
+			if(participant != NULL)
+			{
+				result = participant->isAvatar();
+			}
+		}
+	}
+	
+	return result;
+}
+
+// Returns true if calling back the session URI after the session has closed is possible.
+// Currently this will be false only for PSTN P2P calls.		
+bool LLVoiceClient::isSessionCallBackPossible(const LLUUID &session_id)
+{
+	bool result = true; 
+	sessionState *session = findSession(session_id);
+	
+	if(session != NULL)
+	{
+		result = session->isCallBackPossible();
+	}
+	
+	return result;
+}
+
+// Returns true if the session can accepte text IM's.
+// Currently this will be false only for PSTN P2P calls.
+bool LLVoiceClient::isSessionTextIMPossible(const LLUUID &session_id)
+{
+	bool result = true; 
+	sessionState *session = findSession(session_id);
+	
+	if(session != NULL)
+	{
+		result = session->isTextIMPossible();
+	}
+	
+	return result;
+}
+		
 
-const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
+void LLVoiceClient::declineInvite(std::string &sessionHandle)
+{
+	sessionState *session = findSession(sessionHandle);
+	if(session)
+	{
+		sessionMediaDisconnectSendMessage(session);
+	}
+}
 
-std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserver::EStatusType inStatus)
+void LLVoiceClient::leaveNonSpatialChannel()
 {
-	std::string result = "UNKNOWN";
+	LL_DEBUGS("Voice") 
+		<< "called in state " << state2string(getState()) 
+		<< LL_ENDL;
 	
-	// Prevent copy-paste errors when updating this list...
-#define CASE(x)  case x:  result = #x;  break
+	// Make sure we don't rejoin the current session.	
+	sessionState *oldNextSession = mNextAudioSession;
+	mNextAudioSession = NULL;
 	
-	switch(inStatus)
+	// Most likely this will still be the current session at this point, but check it anyway.
+	reapSession(oldNextSession);
+	
+	verifySessionState();
+	
+	sessionTerminate();
+}
+
+std::string LLVoiceClient::getCurrentChannel()
+{
+	std::string result;
+	
+	if((getState() == stateRunning) && !mSessionTerminateRequested)
 	{
-			CASE(STATUS_LOGIN_RETRY);
-			CASE(STATUS_LOGGED_IN);
-			CASE(STATUS_JOINING);
-			CASE(STATUS_JOINED);
-			CASE(STATUS_LEFT_CHANNEL);
-			CASE(STATUS_VOICE_DISABLED);
-			CASE(BEGIN_ERROR_STATUS);
-			CASE(ERROR_CHANNEL_FULL);
-			CASE(ERROR_CHANNEL_LOCKED);
-			CASE(ERROR_NOT_AVAILABLE);
-			CASE(ERROR_UNKNOWN);
-		default:
-			break;
+		result = getAudioSessionURI();
 	}
 	
-#undef CASE
+	return result;
+}
+
+bool LLVoiceClient::inProximalChannel()
+{
+	bool result = false;
+	
+	if((getState() == stateRunning) && !mSessionTerminateRequested)
+	{
+		result = inSpatialChannel();
+	}
+	
+	return result;
+}
+
+std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
+{
+	std::string result;
+	result = "sip:";
+	result += nameFromID(id);
+	result += "@";
+	result += mVoiceSIPURIHostName;
+	
+	return result;
+}
+
+std::string LLVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar)
+{
+	std::string result;
+	if(avatar)
+	{
+		result = "sip:";
+		result += nameFromID(avatar->getID());
+		result += "@";
+		result += mVoiceSIPURIHostName;
+	}
 	
 	return result;
 }
 
+std::string LLVoiceClient::nameFromAvatar(LLVOAvatar *avatar)
+{
+	std::string result;
+	if(avatar)
+	{
+		result = nameFromID(avatar->getID());
+	}	
+	return result;
+}
 
+std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
+{
+	std::string result;
+	
+	if (uuid.isNull()) {
+		//VIVOX, the uuid emtpy look for the mURIString and return that instead.
+		//result.assign(uuid.mURIStringName);
+		LLStringUtil::replaceChar(result, '_', ' ');
+		return result;
+	}
+	// Prepending this apparently prevents conflicts with reserved names inside the vivox and diamondware code.
+	result = "x";
+	
+	// Base64 encode and replace the pieces of base64 that are less compatible 
+	// with e-mail local-parts.
+	// See RFC-4648 "Base 64 Encoding with URL and Filename Safe Alphabet"
+	result += LLBase64::encode(uuid.mData, UUID_BYTES);
+	LLStringUtil::replaceChar(result, '+', '-');
+	LLStringUtil::replaceChar(result, '/', '_');
+	
+	// If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
+	// echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
+	
+	// The reverse transform can be done with:
+	// echo 'x5mkTKmxDTuGnjWyC__WfMg==' |cut -b 2- -|tr '_-' '/+' |openssl base64 -d|xxd -p
+	
+	return result;
+}
 
+bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
+{
+	bool result = false;
+	
+	// SLIM SDK: The "name" may actually be a SIP URI such as: "sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com"
+	// If it is, convert to a bare name before doing the transform.
+	std::string name = nameFromsipURI(inName);
+	
+	// Doesn't look like a SIP URI, assume it's an actual name.
+	if(name.empty())
+		name = inName;
 
-///////////////////////////////////////////////////////////////////////////////////////////////
+	// This will only work if the name is of the proper form.
+	// As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is:
+	// "xFnPP04IpREWNkuw1cOXlhw=="
+	
+	if((name.size() == 25) && (name[0] == 'x') && (name[23] == '=') && (name[24] == '='))
+	{
+		// The name appears to have the right form.
+
+		// Reverse the transforms done by nameFromID
+		std::string temp = name;
+		LLStringUtil::replaceChar(temp, '-', '+');
+		LLStringUtil::replaceChar(temp, '_', '/');
+
+		U8 rawuuid[UUID_BYTES + 1]; 
+		int len = apr_base64_decode_binary(rawuuid, temp.c_str() + 1);
+		if(len == UUID_BYTES)
+		{
+			// The decode succeeded.  Stuff the bits into the result's UUID
+			memcpy(uuid.mData, rawuuid, UUID_BYTES);
+			result = true;
+		}
+	} 
+	
+	if(!result)
+	{
+		// VIVOX:  not a standard account name, just copy the URI name mURIString field
+		// and hope for the best.  bpj
+		uuid.setNull();  // VIVOX, set the uuid field to nulls
+	}
+	
+	return result;
+}
 
-LLVoiceClient::LLVoiceClient()
+std::string LLVoiceClient::displayNameFromAvatar(LLVOAvatar *avatar)
 {
-	mVoiceModule = NULL;
+	return avatar->getFullname();
 }
 
-//---------------------------------------------------
-// Basic setup/shutdown
+std::string LLVoiceClient::sipURIFromName(std::string &name)
+{
+	std::string result;
+	result = "sip:";
+	result += name;
+	result += "@";
+	result += mVoiceSIPURIHostName;
 
-LLVoiceClient::~LLVoiceClient()
+//	LLStringUtil::toLower(result);
+
+	return result;
+}
+
+std::string LLVoiceClient::nameFromsipURI(const std::string &uri)
+{
+	std::string result;
+
+	std::string::size_type sipOffset, atOffset;
+	sipOffset = uri.find("sip:");
+	atOffset = uri.find("@");
+	if((sipOffset != std::string::npos) && (atOffset != std::string::npos))
+	{
+		result = uri.substr(sipOffset + 4, atOffset - (sipOffset + 4));
+	}
+	
+	return result;
+}
+
+bool LLVoiceClient::inSpatialChannel(void)
 {
+	bool result = false;
+	
+	if(mAudioSession)
+		result = mAudioSession->mIsSpatial;
+		
+	return result;
 }
 
-void LLVoiceClient::init(LLPumpIO *pump)
+std::string LLVoiceClient::getAudioSessionURI()
+{
+	std::string result;
+	
+	if(mAudioSession)
+		result = mAudioSession->mSIPURI;
+		
+	return result;
+}
+
+std::string LLVoiceClient::getAudioSessionHandle()
 {
-	// Initialize all of the voice modules
-	m_servicePump = pump;
+	std::string result;
+	
+	if(mAudioSession)
+		result = mAudioSession->mHandle;
+		
+	return result;
 }
 
-void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID)
+
+/////////////////////////////
+// Sending updates of current state
+
+void LLVoiceClient::enforceTether(void)
 {
-	// In the future, we should change this to allow voice module registration
-	// with a table lookup of sorts.
-	std::string voice_server = gSavedSettings.getString("VoiceServerType");
-	LL_DEBUGS("Voice") << "voice server type " << voice_server << LL_ENDL;
-	if(voice_server == "diamondware")
+	LLVector3d tethered	= mCameraRequestedPosition;
+
+	// constrain 'tethered' to within 50m of mAvatarPosition.
 	{
-		mVoiceModule = (LLVoiceModuleInterface *)LLDiamondwareVoiceClient::getInstance();
+		F32 max_dist = 50.0f;
+		LLVector3d camera_offset = mCameraRequestedPosition - mAvatarPosition;
+		F32 camera_distance = (F32)camera_offset.magVec();
+		if(camera_distance > max_dist)
+		{
+			tethered = mAvatarPosition + 
+				(max_dist / camera_distance) * camera_offset;
+		}
 	}
-	else if(voice_server == "vivox")
+	
+	if(dist_vec(mCameraPosition, tethered) > 0.1)
 	{
-		mVoiceModule = (LLVoiceModuleInterface *)LLVivoxVoiceClient::getInstance();
+		mCameraPosition = tethered;
+		mSpatialCoordsDirty = true;
 	}
-	else
+}
+
+void LLVoiceClient::updatePosition(void)
+{
+	if(gVoiceClient)
+	{
+		LLViewerRegion *region = gAgent.getRegion();
+		if(region && isAgentAvatarValid())
+		{
+			LLMatrix3 rot;
+			LLVector3d pos;
+
+			// TODO: If camera and avatar velocity are actually used by the voice system, we could compute them here...
+			// They're currently always set to zero.
+
+			// Send the current camera position to the voice code
+			rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (),  LLViewerCamera::getInstance()->getUpAxis());		
+			pos = gAgent.getRegion()->getPosGlobalFromRegion(LLViewerCamera::getInstance()->getOrigin());
+			
+			gVoiceClient->setCameraPosition(
+					pos,				// position
+					LLVector3::zero, 	// velocity
+					rot);				// rotation matrix
+					
+			// Send the current avatar position to the voice code
+			rot = gAgentAvatarp->getRootJoint()->getWorldRotation().getMatrix3();
+	
+			pos = gAgentAvatarp->getPositionGlobal();
+			// TODO: Can we get the head offset from outside the LLVOAvatar?
+//			pos += LLVector3d(mHeadOffset);
+			pos += LLVector3d(0.f, 0.f, 1.f);
+		
+			gVoiceClient->setAvatarPosition(
+					pos,				// position
+					LLVector3::zero, 	// velocity
+					rot);				// rotation matrix
+		}
+	}
+}
+
+void LLVoiceClient::setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot)
+{
+	mCameraRequestedPosition = position;
+	
+	if(mCameraVelocity != velocity)
+	{
+		mCameraVelocity = velocity;
+		mSpatialCoordsDirty = true;
+	}
+	
+	if(mCameraRot != rot)
 	{
-		mVoiceModule = NULL;
-		return; 
+		mCameraRot = rot;
+		mSpatialCoordsDirty = true;
 	}
-	mVoiceModule->init(m_servicePump);	
-	mVoiceModule->userAuthorized(user_id, agentID);
 }
 
+void LLVoiceClient::setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot)
+{
+	if(dist_vec(mAvatarPosition, position) > 0.1)
+	{
+		mAvatarPosition = position;
+		mSpatialCoordsDirty = true;
+	}
+	
+	if(mAvatarVelocity != velocity)
+	{
+		mAvatarVelocity = velocity;
+		mSpatialCoordsDirty = true;
+	}
+	
+	if(mAvatarRot != rot)
+	{
+		mAvatarRot = rot;
+		mSpatialCoordsDirty = true;
+	}
+}
 
-void LLVoiceClient::terminate()
+bool LLVoiceClient::channelFromRegion(LLViewerRegion *region, std::string &name)
+{
+	bool result = false;
+	
+	if(region)
+	{
+		name = region->getName();
+	}
+	
+	if(!name.empty())
+		result = true;
+	
+	return result;
+}
+
+void LLVoiceClient::leaveChannel(void)
+{
+	if(getState() == stateRunning)
+	{
+		LL_DEBUGS("Voice") << "leaving channel for teleport/logout" << LL_ENDL;
+		mChannelName.clear();
+		sessionTerminate();
+	}
+}
+
+void LLVoiceClient::setMuteMic(bool muted)
+{
+	mMuteMic = muted;
+}
+
+bool LLVoiceClient::getMuteMic() const
+{
+	return mMuteMic;
+}
+
+void LLVoiceClient::setUserPTTState(bool ptt)
+{
+	mUserPTTState = ptt;
+}
+
+bool LLVoiceClient::getUserPTTState()
+{
+	return mUserPTTState;
+}
+
+void LLVoiceClient::toggleUserPTTState(void)
+{
+	mUserPTTState = !mUserPTTState;
+}
+
+void LLVoiceClient::setVoiceEnabled(bool enabled)
+{
+	if (enabled != mVoiceEnabled)
+	{
+		mVoiceEnabled = enabled;
+		LLVoiceClientStatusObserver::EStatusType status;
+
+		if (enabled)
+		{
+			LLVoiceChannel::getCurrentVoiceChannel()->activate();
+			status = LLVoiceClientStatusObserver::STATUS_VOICE_ENABLED;
+		}
+		else
+		{
+			// Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
+			LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
+			status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED;
+		}
+
+		notifyStatusObservers(status);
+	}
+}
+
+bool LLVoiceClient::voiceEnabled()
+{
+	return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice");
+}
+
+//AD *TODO: investigate possible merge of voiceWorking() and voiceEnabled() into one non-static method
+bool LLVoiceClient::voiceWorking()
+{
+	//Added stateSessionTerminated state to avoid problems with call in parcels with disabled voice (EXT-4758)
+	// Condition with joining spatial num was added to take into account possible problems with connection to voice
+	// server(EXT-4313). See bug descriptions and comments for MAX_NORMAL_JOINING_SPATIAL_NUM for more info.
+	return (mSpatialJoiningNum < MAX_NORMAL_JOINING_SPATIAL_NUM) && (stateLoggedIn <= mState) && (mState <= stateSessionTerminated);
+}
+
+void LLVoiceClient::setLipSyncEnabled(BOOL enabled)
 {
-	if (mVoiceModule) mVoiceModule->terminate();
-	mVoiceModule = NULL;
+	mLipSyncEnabled = enabled;
 }
 
-const LLVoiceVersionInfo LLVoiceClient::getVersion()
+BOOL LLVoiceClient::lipSyncEnabled()
 {
-	if (mVoiceModule) 
+	   
+	if ( mVoiceEnabled && stateDisabled != getState() )
 	{
-		return mVoiceModule->getVersion();
+		return mLipSyncEnabled;
 	}
 	else
 	{
-		LLVoiceVersionInfo result;
-		result.serverVersion = std::string();
-		result.serverType = std::string();
-		return result;
+		return FALSE;
 	}
 }
 
-void LLVoiceClient::updateSettings()
+void LLVoiceClient::setUsePTT(bool usePTT)
 {
-	if (mVoiceModule) mVoiceModule->updateSettings();
+	if(usePTT && !mUsePTT)
+	{
+		// When the user turns on PTT, reset the current state.
+		mUserPTTState = false;
+	}
+	mUsePTT = usePTT;
 }
 
-//--------------------------------------------------
-// tuning
+void LLVoiceClient::setPTTIsToggle(bool PTTIsToggle)
+{
+	if(!PTTIsToggle && mPTTIsToggle)
+	{
+		// When the user turns off toggle, reset the current state.
+		mUserPTTState = false;
+	}
+	
+	mPTTIsToggle = PTTIsToggle;
+}
 
-void LLVoiceClient::tuningStart()
+bool LLVoiceClient::getPTTIsToggle()
 {
-	if (mVoiceModule) mVoiceModule->tuningStart();
+	return mPTTIsToggle;
 }
 
-void LLVoiceClient::tuningStop()
+void LLVoiceClient::setPTTKey(std::string &key)
 {
-	if (mVoiceModule) mVoiceModule->tuningStop();
+	if(key == "MiddleMouse")
+	{
+		mPTTIsMiddleMouse = true;
+	}
+	else
+	{
+		mPTTIsMiddleMouse = false;
+		if(!LLKeyboard::keyFromString(key, &mPTTKey))
+		{
+			// If the call failed, don't match any key.
+			key = KEY_NONE;
+		}
+	}
 }
 
-bool LLVoiceClient::inTuningMode()
+void LLVoiceClient::setEarLocation(S32 loc)
+{
+	if(mEarLocation != loc)
+	{
+		LL_DEBUGS("Voice") << "Setting mEarLocation to " << loc << LL_ENDL;
+		
+		mEarLocation = loc;
+		mSpatialCoordsDirty = true;
+	}
+}
+
+void LLVoiceClient::setVoiceVolume(F32 volume)
+{
+	int scaled_volume = scale_speaker_volume(volume);	
+
+	if(scaled_volume != mSpeakerVolume)
+	{
+		int min_volume = scale_speaker_volume(0);
+		if((scaled_volume == min_volume) || (mSpeakerVolume == min_volume))
+		{
+			mSpeakerMuteDirty = true;
+		}
+
+		mSpeakerVolume = scaled_volume;
+		mSpeakerVolumeDirty = true;
+	}
+}
+
+void LLVoiceClient::setMicGain(F32 volume)
+{
+	int scaled_volume = scale_mic_volume(volume);
+	
+	if(scaled_volume != mMicVolume)
+	{
+		mMicVolume = scaled_volume;
+		mMicVolumeDirty = true;
+	}
+}
+
+void LLVoiceClient::keyDown(KEY key, MASK mask)
+{	
+	if (gKeyboard->getKeyRepeated(key))
+	{
+		// ignore auto-repeat keys
+		return;
+	}
+
+	if(!mPTTIsMiddleMouse)
+	{
+		bool down = (mPTTKey != KEY_NONE)
+			&& gKeyboard->getKeyDown(mPTTKey);
+		inputUserControlState(down);
+	}
+}
+void LLVoiceClient::keyUp(KEY key, MASK mask)
+{
+	if(!mPTTIsMiddleMouse)
+	{
+		bool down = (mPTTKey != KEY_NONE)
+			&& gKeyboard->getKeyDown(mPTTKey);
+		inputUserControlState(down);
+	}
+}
+void LLVoiceClient::inputUserControlState(bool down)
 {
-	if (mVoiceModule) 
+	if(mPTTIsToggle)
 	{
-		return mVoiceModule->inTuningMode();
+		if(down) // toggle open-mic state on 'down'
+		{
+			toggleUserPTTState();
+		}
 	}
-	else
+	else // set open-mic state as an absolute
 	{
-		return false;
+		setUserPTTState(down);
 	}
 }
-
-void LLVoiceClient::tuningSetMicVolume(float volume)
+void LLVoiceClient::middleMouseState(bool down)
 {
-	if (mVoiceModule) mVoiceModule->tuningSetMicVolume(volume);
+	if(mPTTIsMiddleMouse)
+	{
+		inputUserControlState(down);
+	}
 }
 
-void LLVoiceClient::tuningSetSpeakerVolume(float volume)
+/////////////////////////////
+// Accessors for data related to nearby speakers
+BOOL LLVoiceClient::getVoiceEnabled(const LLUUID& id)
 {
-	if (mVoiceModule) mVoiceModule->tuningSetSpeakerVolume(volume);
+	BOOL result = FALSE;
+	participantState *participant = findParticipantByID(id);
+	if(participant)
+	{
+		// I'm not sure what the semantics of this should be.
+		// For now, if we have any data about the user that came through the chat channel, assume they're voice-enabled.
+		result = TRUE;
+	}
+	
+	return result;
 }
 
-float LLVoiceClient::tuningGetEnergy(void)
+BOOL LLVoiceClient::getIsSpeaking(const LLUUID& id)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->tuningGetEnergy();
-	}
-	else
+	BOOL result = FALSE;
+
+	participantState *participant = findParticipantByID(id);
+	if(participant)
 	{
-		return 0.0;
+		if (participant->mSpeakingTimeout.getElapsedTimeF32() > SPEAKING_TIMEOUT)
+		{
+			participant->mIsSpeaking = FALSE;
+		}
+		result = participant->mIsSpeaking;
 	}
+	
+	return result;
 }
 
-
-//------------------------------------------------
-// devices
-
-bool LLVoiceClient::deviceSettingsAvailable()
+BOOL LLVoiceClient::getIsModeratorMuted(const LLUUID& id)
 {
-	if (mVoiceModule) 
+	BOOL result = FALSE;
+
+	participantState *participant = findParticipantByID(id);
+	if(participant)
 	{
-		return mVoiceModule->deviceSettingsAvailable();
+		result = participant->mIsModeratorMuted;
 	}
-	else
+	
+	return result;
+}
+
+F32 LLVoiceClient::getCurrentPower(const LLUUID& id)
+{		
+	F32 result = 0;
+	participantState *participant = findParticipantByID(id);
+	if(participant)
 	{
-		return false;
+		result = participant->mPower;
 	}
+	
+	return result;
 }
 
-void LLVoiceClient::refreshDeviceLists(bool clearCurrentList)
-{
-	if (mVoiceModule) mVoiceModule->refreshDeviceLists(clearCurrentList);
-}
 
-void LLVoiceClient::setCaptureDevice(const std::string& name)
+std::string LLVoiceClient::getDisplayName(const LLUUID& id)
 {
-	if (mVoiceModule) mVoiceModule->setCaptureDevice(name);
+	std::string result;
+	participantState *participant = findParticipantByID(id);
+	if(participant)
+	{
+		result = participant->mDisplayName;
+	}
 	
+	return result;
 }
 
-void LLVoiceClient::setRenderDevice(const std::string& name)
-{
-	if (mVoiceModule) mVoiceModule->setRenderDevice(name);	
-}
 
-const LLVoiceDeviceList& LLVoiceClient::getCaptureDevices()
+BOOL LLVoiceClient::getUsingPTT(const LLUUID& id)
 {
-	static LLVoiceDeviceList nullCaptureDevices;
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getCaptureDevices();
-	}
-	else
+	BOOL result = FALSE;
+
+	participantState *participant = findParticipantByID(id);
+	if(participant)
 	{
-		return nullCaptureDevices;
+		// I'm not sure what the semantics of this should be.
+		// Does "using PTT" mean they're configured with a push-to-talk button?
+		// For now, we know there's no PTT mechanism in place, so nobody is using it.
 	}
+	
+	return result;
 }
 
-
-const LLVoiceDeviceList& LLVoiceClient::getRenderDevices()
+BOOL LLVoiceClient::getOnMuteList(const LLUUID& id)
 {
-	static LLVoiceDeviceList nullRenderDevices;	
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getRenderDevices();
-	}
-	else
+	BOOL result = FALSE;
+	
+	participantState *participant = findParticipantByID(id);
+	if(participant)
 	{
-		return nullRenderDevices;
+		result = participant->mOnMuteList;
 	}
+
+	return result;
 }
 
+// External accessors.
+F32 LLVoiceClient::getUserVolume(const LLUUID& id)
+{
+	// Minimum volume will be returned for users with voice disabled
+	F32 result = VOLUME_MIN;
+	
+	participantState *participant = findParticipantByID(id);
+	if(participant)
+	{
+		result = participant->mVolume;
+
+		// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
+		// LL_DEBUGS("Voice") << "mVolume = " << result <<  " for " << id << LL_ENDL;
+	}
 
-//--------------------------------------------------
-// participants
+	return result;
+}
 
-void LLVoiceClient::getParticipantList(std::set<LLUUID> &participants)
+void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
 {
-	if (mVoiceModule) 
+	if(mAudioSession)
 	{
-	  mVoiceModule->getParticipantList(participants);
+		participantState *participant = findParticipantByID(id);
+		if (participant && !participant->mIsSelf)
+		{
+			if (!is_approx_equal(volume, VOLUME_DEFAULT))
+			{
+				// Store this volume setting for future sessions if it has been
+				// changed from the default
+				LLSpeakerVolumeStorage::getInstance()->storeSpeakerVolume(id, volume);
+			}
+			else
+			{
+				// Remove stored volume setting if it is returned to the default
+				LLSpeakerVolumeStorage::getInstance()->removeSpeakerVolume(id);
+			}
+
+			participant->mVolume = llclamp(volume, VOLUME_MIN, VOLUME_MAX);
+			participant->mVolumeDirty = true;
+			mAudioSession->mVolumeDirty = true;
+		}
 	}
-	else
+}
+
+std::string LLVoiceClient::getGroupID(const LLUUID& id)
+{
+	std::string result;
+
+	participantState *participant = findParticipantByID(id);
+	if(participant)
 	{
-	  participants = std::set<LLUUID>();
+		result = participant->mGroupID;
 	}
+	
+	return result;
 }
 
-bool LLVoiceClient::isParticipant(const LLUUID &speaker_id)
+BOOL LLVoiceClient::getAreaVoiceDisabled()
 {
-  if(mVoiceModule)
-    {
-      return mVoiceModule->isParticipant(speaker_id);
-    }
-  return false;
+	return mAreaVoiceDisabled;
 }
 
+void LLVoiceClient::recordingLoopStart(int seconds, int deltaFramesPerControlFrame)
+{
+//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Start)" << LL_ENDL;
+	
+	if(!mMainSessionGroupHandle.empty())
+	{
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
+		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
+		<< "<RecordingControlType>Start</RecordingControlType>" 
+		<< "<DeltaFramesPerControlFrame>" << deltaFramesPerControlFrame << "</DeltaFramesPerControlFrame>"
+		<< "<Filename>" << "" << "</Filename>"
+		<< "<EnableAudioRecordingEvents>false</EnableAudioRecordingEvents>"
+		<< "<LoopModeDurationSeconds>" << seconds << "</LoopModeDurationSeconds>"
+		<< "</Request>\n\n\n";
 
-//--------------------------------------------------
-// text chat
 
+		writeString(stream.str());
+	}
+}
 
-BOOL LLVoiceClient::isSessionTextIMPossible(const LLUUID& id)
+void LLVoiceClient::recordingLoopSave(const std::string& filename)
 {
-	if (mVoiceModule) 
+//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Flush)" << LL_ENDL;
+
+	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
 	{
-		return mVoiceModule->isSessionTextIMPossible(id);
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
+		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
+		<< "<RecordingControlType>Flush</RecordingControlType>" 
+		<< "<Filename>" << filename << "</Filename>"
+		<< "</Request>\n\n\n";
+
+		writeString(stream.str());
 	}
-	else
-	{
-		return FALSE;
-	}	
 }
 
-BOOL LLVoiceClient::isSessionCallBackPossible(const LLUUID& id)
+void LLVoiceClient::recordingStop()
 {
-	if (mVoiceModule) 
+//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Stop)" << LL_ENDL;
+
+	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
 	{
-		return mVoiceModule->isSessionCallBackPossible(id);
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
+		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
+		<< "<RecordingControlType>Stop</RecordingControlType>" 
+		<< "</Request>\n\n\n";
+
+		writeString(stream.str());
 	}
-	else
-	{
-		return FALSE;
-	}	
 }
 
-BOOL LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message)
+void LLVoiceClient::filePlaybackStart(const std::string& filename)
 {
-	if (mVoiceModule) 
+//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Start)" << LL_ENDL;
+
+	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
 	{
-		return mVoiceModule->sendTextMessage(participant_id, message);
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
+		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
+		<< "<RecordingControlType>Start</RecordingControlType>" 
+		<< "<Filename>" << filename << "</Filename>"
+		<< "</Request>\n\n\n";
+
+		writeString(stream.str());
 	}
-	else
-	{
-		return FALSE;
-	}	
 }
 
-void LLVoiceClient::endUserIMSession(const LLUUID& participant_id)
+void LLVoiceClient::filePlaybackStop()
 {
-	if (mVoiceModule) 
+//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Stop)" << LL_ENDL;
+
+	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
 	{
-		mVoiceModule->endUserIMSession(participant_id);
+		std::ostringstream stream;
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
+		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
+		<< "<RecordingControlType>Stop</RecordingControlType>" 
+		<< "</Request>\n\n\n";
+
+		writeString(stream.str());
 	}
 }
 
-//----------------------------------------------
-// channels
-
-bool LLVoiceClient::inProximalChannel()
+void LLVoiceClient::filePlaybackSetPaused(bool paused)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->inProximalChannel();
-	}
-	else
-	{
-		return false;
-	}
+	// TODO: Implement once Vivox gives me a sample
 }
 
-void LLVoiceClient::setNonSpatialChannel(
-	const std::string &uri,
-	const std::string &credentials)
+void LLVoiceClient::filePlaybackSetMode(bool vox, float speed)
 {
-	if (mVoiceModule) mVoiceModule->setNonSpatialChannel(uri, credentials);
+	// TODO: Implement once Vivox gives me a sample
 }
 
-void LLVoiceClient::setSpatialChannel(
-	const std::string &uri,
-	const std::string &credentials)
+LLVoiceClient::sessionState::sessionState() :
+	mErrorStatusCode(0),
+	mMediaStreamState(streamStateUnknown),
+	mTextStreamState(streamStateUnknown),
+	mCreateInProgress(false),
+	mMediaConnectInProgress(false),
+	mVoiceInvitePending(false),
+	mTextInvitePending(false),
+	mSynthesizedCallerID(false),
+	mIsChannel(false),
+	mIsSpatial(false),
+	mIsP2P(false),
+	mIncoming(false),
+	mVoiceEnabled(false),
+	mReconnect(false),
+	mVolumeDirty(false),
+	mMuteDirty(false),
+	mParticipantsChanged(false)
 {
-	if (mVoiceModule) mVoiceModule->setSpatialChannel(uri, credentials);
 }
 
-void LLVoiceClient::leaveNonSpatialChannel()
+LLVoiceClient::sessionState::~sessionState()
 {
-	if (mVoiceModule) mVoiceModule->leaveNonSpatialChannel();
+	removeAllParticipants();
 }
 
-void LLVoiceClient::leaveChannel(void)
+bool LLVoiceClient::sessionState::isCallBackPossible()
 {
-	if (mVoiceModule) mVoiceModule->leaveChannel();
+	// This may change to be explicitly specified by vivox in the future...
+	// Currently, only PSTN P2P calls cannot be returned.
+	// Conveniently, this is also the only case where we synthesize a caller UUID.
+	return !mSynthesizedCallerID;
 }
 
-std::string LLVoiceClient::getCurrentChannel()
+bool LLVoiceClient::sessionState::isTextIMPossible()
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getCurrentChannel();
-	}
-	else
-	{
-		return std::string();
-	}
+	// This may change to be explicitly specified by vivox in the future...
+	return !mSynthesizedCallerID;
 }
 
 
-//---------------------------------------
-// invitations
+LLVoiceClient::sessionIterator LLVoiceClient::sessionsBegin(void)
+{
+	return mSessions.begin();
+}
 
-void LLVoiceClient::callUser(const LLUUID &uuid)
+LLVoiceClient::sessionIterator LLVoiceClient::sessionsEnd(void)
 {
-	if (mVoiceModule) mVoiceModule->callUser(uuid);
+	return mSessions.end();
 }
 
-bool LLVoiceClient::answerInvite(std::string &channelHandle)
+
+LLVoiceClient::sessionState *LLVoiceClient::findSession(const std::string &handle)
 {
-	if (mVoiceModule) 
+	sessionState *result = NULL;
+	sessionMap::iterator iter = mSessionsByHandle.find(&handle);
+	if(iter != mSessionsByHandle.end())
 	{
-		return mVoiceModule->answerInvite(channelHandle);
+		result = iter->second;
 	}
-	else
+	
+	return result;
+}
+
+LLVoiceClient::sessionState *LLVoiceClient::findSessionBeingCreatedByURI(const std::string &uri)
+{	
+	sessionState *result = NULL;
+	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
 	{
-		return false;
+		sessionState *session = *iter;
+		if(session->mCreateInProgress && (session->mSIPURI == uri))
+		{
+			result = session;
+			break;
+		}
 	}
+	
+	return result;
 }
 
-void LLVoiceClient::declineInvite(std::string &channelHandle)
+LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participant_id)
 {
-	if (mVoiceModule) mVoiceModule->declineInvite(channelHandle);
+	sessionState *result = NULL;
+	
+	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+	{
+		sessionState *session = *iter;
+		if((session->mCallerID == participant_id) || (session->mIMSessionID == participant_id))
+		{
+			result = session;
+			break;
+		}
+	}
+	
+	return result;
 }
 
+LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, const std::string &handle)
+{
+	sessionState *result = NULL;
+	
+	if(handle.empty())
+	{
+		// No handle supplied.
+		// Check whether there's already a session with this URI
+		for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+		{
+			sessionState *s = *iter;
+			if((s->mSIPURI == uri) || (s->mAlternateSIPURI == uri))
+			{
+				// TODO: I need to think about this logic... it's possible that this case should raise an internal error.
+				result = s;
+				break;
+			}
+		}
+	}
+	else // (!handle.empty())
+	{
+		// Check for an existing session with this handle
+		sessionMap::iterator iter = mSessionsByHandle.find(&handle);
+		
+		if(iter != mSessionsByHandle.end())
+		{
+			result = iter->second;
+		}
+	}
 
-//------------------------------------------
-// Volume/gain
+	if(!result)
+	{
+		// No existing session found.
+		
+		LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL;
+		result = new sessionState();
+		result->mSIPURI = uri;
+		result->mHandle = handle;
+		
+		mSessions.insert(result);
 
+		if(!result->mHandle.empty())
+		{
+			mSessionsByHandle.insert(sessionMap::value_type(&(result->mHandle), result));
+		}
+	}
+	else
+	{
+		// Found an existing session
+		
+		if(uri != result->mSIPURI)
+		{
+			// TODO: Should this be an internal error?
+			LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL;
+			setSessionURI(result, uri);
+		}
 
-void LLVoiceClient::setVoiceVolume(F32 volume)
-{
-	if (mVoiceModule) mVoiceModule->setVoiceVolume(volume);
-}
+		if(handle != result->mHandle)
+		{
+			if(handle.empty())
+			{
+				// There's at least one race condition where where addSession was clearing an existing session handle, which caused things to break.
+				LL_DEBUGS("Voice") << "NOT clearing handle " << result->mHandle << LL_ENDL;
+			}
+			else
+			{
+				// TODO: Should this be an internal error?
+				LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL;
+				setSessionHandle(result, handle);
+			}
+		}
+		
+		LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL;
+	}
 
-void LLVoiceClient::setMicGain(F32 volume)
-{
-	if (mVoiceModule) mVoiceModule->setMicGain(volume);
+	verifySessionState();
+		
+	return result;
 }
 
-
-//------------------------------------------
-// enable/disable voice features
-
-bool LLVoiceClient::voiceEnabled()
+void LLVoiceClient::setSessionHandle(sessionState *session, const std::string &handle)
 {
-	if (mVoiceModule) 
+	// Have to remove the session from the handle-indexed map before changing the handle, or things will break badly.
+	
+	if(!session->mHandle.empty())
 	{
-		return mVoiceModule->voiceEnabled();
+		// Remove session from the map if it should have been there.
+		sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
+		if(iter != mSessionsByHandle.end())
+		{
+			if(iter->second != session)
+			{
+				LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL;
+			}
+
+			mSessionsByHandle.erase(iter);
+		}
+		else
+		{
+			LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL;
+		}
 	}
-	else
+			
+	session->mHandle = handle;
+
+	if(!handle.empty())
 	{
-		return false;
+		mSessionsByHandle.insert(sessionMap::value_type(&(session->mHandle), session));
 	}
-}
 
-void LLVoiceClient::setVoiceEnabled(bool enabled)
-{
-	if (mVoiceModule) mVoiceModule->setVoiceEnabled(enabled);
+	verifySessionState();
 }
 
-void LLVoiceClient::setLipSyncEnabled(BOOL enabled)
+void LLVoiceClient::setSessionURI(sessionState *session, const std::string &uri)
 {
-	if (mVoiceModule) mVoiceModule->setLipSyncEnabled(enabled);
+	// There used to be a map of session URIs to sessions, which made this complex....
+	session->mSIPURI = uri;
+
+	verifySessionState();
 }
 
-BOOL LLVoiceClient::lipSyncEnabled()
+void LLVoiceClient::deleteSession(sessionState *session)
 {
-	if (mVoiceModule) 
+	// Remove the session from the handle map
+	if(!session->mHandle.empty())
 	{
-		return mVoiceModule->lipSyncEnabled();
+		sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
+		if(iter != mSessionsByHandle.end())
+		{
+			if(iter->second != session)
+			{
+				LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL;
+			}
+			mSessionsByHandle.erase(iter);
+		}
 	}
-	else
+
+	// Remove the session from the URI map
+	mSessions.erase(session);
+	
+	// At this point, the session should be unhooked from all lists and all state should be consistent.
+	verifySessionState();
+
+	// If this is the current audio session, clean up the pointer which will soon be dangling.
+	if(mAudioSession == session)
 	{
-		return false;
+		mAudioSession = NULL;
+		mAudioSessionChanged = true;
 	}
-}
-
-void LLVoiceClient::setMuteMic(bool muted)
-{
-	if (mVoiceModule) mVoiceModule->setMuteMic(muted);
-}
 
+	// ditto for the next audio session
+	if(mNextAudioSession == session)
+	{
+		mNextAudioSession = NULL;
+	}
 
-// ----------------------------------------------
-// PTT
+	// delete the session
+	delete session;
+}
 
-void LLVoiceClient::setUserPTTState(bool ptt)
+void LLVoiceClient::deleteAllSessions()
 {
-	if (mVoiceModule) mVoiceModule->setUserPTTState(ptt);
+	LL_DEBUGS("Voice") << "called" << LL_ENDL;
+
+	while(!mSessions.empty())
+	{
+		deleteSession(*(sessionsBegin()));
+	}
+	
+	if(!mSessionsByHandle.empty())
+	{
+		LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL;
+	}
 }
 
-bool LLVoiceClient::getUserPTTState()
+void LLVoiceClient::verifySessionState(void)
 {
-	if (mVoiceModule) 
+	// This is mostly intended for debugging problems with session state management.
+	LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL;
+
+	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
 	{
-		return mVoiceModule->getUserPTTState();
+		sessionState *session = *iter;
+
+		LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL;
+		
+		if(!session->mHandle.empty())
+		{
+			// every session with a non-empty handle needs to be in the handle map
+			sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle));
+			if(i2 == mSessionsByHandle.end())
+			{
+				LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL;
+			}
+			else
+			{
+				if(i2->second != session)
+				{
+					LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL;
+				}
+			}
+		}
 	}
-	else
+		
+	// check that every entry in the handle map points to a valid session in the session set
+	for(sessionMap::iterator iter = mSessionsByHandle.begin(); iter != mSessionsByHandle.end(); iter++)
 	{
-		return false;
+		sessionState *session = iter->second;
+		sessionIterator i2 = mSessions.find(session);
+		if(i2 == mSessions.end())
+		{
+			LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL;
+		}
+		else
+		{
+			if(session->mHandle != (*i2)->mHandle)
+			{
+				LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL;
+			}
+		}
 	}
 }
 
-void LLVoiceClient::setUsePTT(bool usePTT)
+LLVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
+	mURI(uri)
 {
-	if (mVoiceModule) mVoiceModule->setUsePTT(usePTT);
+	mOnlineSL = false;
+	mOnlineSLim = false;
+	mCanSeeMeOnline = true;
+	mHasBlockListEntry = false;
+	mHasAutoAcceptListEntry = false;
+	mNameResolved = false;
+	mInVivoxBuddies = false;
+	mInSLFriends = false;
+	mNeedsNameUpdate = false;
 }
 
-void LLVoiceClient::setPTTIsToggle(bool PTTIsToggle)
+void LLVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
 {
-	if (mVoiceModule) mVoiceModule->setPTTIsToggle(PTTIsToggle);
+	buddyListEntry *buddy = addBuddy(uri, displayName);
+	buddy->mInVivoxBuddies = true;	
 }
 
-bool LLVoiceClient::getPTTIsToggle()
+LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri)
 {
-	if (mVoiceModule) 
+	std::string empty;
+	buddyListEntry *buddy = addBuddy(uri, empty);
+	if(buddy->mDisplayName.empty())
 	{
-		return mVoiceModule->getPTTIsToggle();
-	}
-	else {
-		return false;
+		buddy->mNameResolved = false;
 	}
-
-}
-
-void LLVoiceClient::inputUserControlState(bool down)
-{
-	if (mVoiceModule) mVoiceModule->inputUserControlState(down);	
+	return buddy;
 }
 
-void LLVoiceClient::toggleUserPTTState(void)
+LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri, const std::string &displayName)
 {
-	if (mVoiceModule) mVoiceModule->toggleUserPTTState();
-}
+	buddyListEntry *result = NULL;
+	buddyListMap::iterator iter = mBuddyListMap.find(&uri);
+	
+	if(iter != mBuddyListMap.end())
+	{
+		// Found a matching buddy already in the map.
+		LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
+		result = iter->second;
+	}
 
-void LLVoiceClient::keyDown(KEY key, MASK mask)
-{	
-	if (mVoiceModule) mVoiceModule->keyDown(key, mask);
-}
-void LLVoiceClient::keyUp(KEY key, MASK mask)
-{
-	if (mVoiceModule) mVoiceModule->keyUp(key, mask);
-}
-void LLVoiceClient::middleMouseState(bool down)
-{
-	if (mVoiceModule) mVoiceModule->middleMouseState(down);
-}
+	if(!result)
+	{
+		// participant isn't already in one list or the other.
+		LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
+		result = new buddyListEntry(uri);
+		result->mDisplayName = displayName;
 
+		if(IDFromName(uri, result->mUUID)) 
+		{
+			// Extracted UUID from name successfully.
+		}
+		else
+		{
+			LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
+		}
 
-//-------------------------------------------
-// nearby speaker accessors
+		mBuddyListMap.insert(buddyListMap::value_type(&(result->mURI), result));
+	}
+	
+	return result;
+}
 
-BOOL LLVoiceClient::getVoiceEnabled(const LLUUID& id)
+LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const std::string &uri)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getVoiceEnabled(id);
-	} 
-	else
+	buddyListEntry *result = NULL;
+	buddyListMap::iterator iter = mBuddyListMap.find(&uri);
+	if(iter != mBuddyListMap.end())
 	{
-		return FALSE;
+		result = iter->second;
 	}
+	
+	return result;
 }
 
-std::string LLVoiceClient::getDisplayName(const LLUUID& id)
+LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const LLUUID &id)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getDisplayName(id);
-	}
-	else
+	buddyListEntry *result = NULL;
+	buddyListMap::iterator iter;
+
+	for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
 	{
-	  return std::string();
+		if(iter->second->mUUID == id)
+		{
+			result = iter->second;
+			break;
+		}
 	}
+	
+	return result;
 }
 
-bool LLVoiceClient::isVoiceWorking()
+LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddyByDisplayName(const std::string &name)
 {
-	if (mVoiceModule) 
+	buddyListEntry *result = NULL;
+	buddyListMap::iterator iter;
+
+	for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
 	{
-		return mVoiceModule->isVoiceWorking();
+		if(iter->second->mDisplayName == name)
+		{
+			result = iter->second;
+			break;
+		}
 	}
-	return false;
+	
+	return result;
 }
 
-BOOL LLVoiceClient::isParticipantAvatar(const LLUUID& id)
+void LLVoiceClient::deleteBuddy(const std::string &uri)
 {
-	if (mVoiceModule) 
+	buddyListMap::iterator iter = mBuddyListMap.find(&uri);
+	if(iter != mBuddyListMap.end())
 	{
-		return mVoiceModule->isParticipantAvatar(id);
+		LL_DEBUGS("Voice") << "deleting buddy " << uri << LL_ENDL;
+		buddyListEntry *buddy = iter->second;
+		mBuddyListMap.erase(iter);
+		delete buddy;
 	}
 	else
 	{
-		return FALSE;
+		LL_DEBUGS("Voice") << "attempt to delete nonexistent buddy " << uri << LL_ENDL;
 	}
+	
 }
 
-BOOL LLVoiceClient::isOnlineSIP(const LLUUID& id)
+void LLVoiceClient::deleteAllBuddies(void)
 {
-	if (mVoiceModule) 
+	while(!mBuddyListMap.empty())
 	{
-		return mVoiceModule->isOnlineSIP(id);
-	}
-	else
-	{
-		return FALSE;
+		deleteBuddy(*(mBuddyListMap.begin()->first));
 	}
+	
+	// Don't want to correlate with friends list when we've emptied the buddy list.
+	mBuddyListMapPopulated = false;
+	
+	// Don't want to correlate with friends list when we've reset the block rules.
+	mBlockRulesListReceived = false;
+	mAutoAcceptRulesListReceived = false;
 }
 
-BOOL LLVoiceClient::getIsSpeaking(const LLUUID& id)
+void LLVoiceClient::deleteAllBlockRules(void)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getIsSpeaking(id);
-	}
-	else
+	// Clear the block list entry flags from all local buddy list entries
+	buddyListMap::iterator buddy_it;
+	for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
 	{
-		return FALSE;
+		buddy_it->second->mHasBlockListEntry = false;
 	}
 }
 
-BOOL LLVoiceClient::getIsModeratorMuted(const LLUUID& id)
+void LLVoiceClient::deleteAllAutoAcceptRules(void)
 {
-	if (mVoiceModule) 
+	// Clear the auto-accept list entry flags from all local buddy list entries
+	buddyListMap::iterator buddy_it;
+	for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
 	{
-		return mVoiceModule->getIsModeratorMuted(id);
+		buddy_it->second->mHasAutoAcceptListEntry = false;
 	}
-	else
+}
+
+void LLVoiceClient::addBlockRule(const std::string &blockMask, const std::string &presenceOnly)
+{
+	buddyListEntry *buddy = NULL;
+
+	// blockMask is the SIP URI of a friends list entry
+	buddyListMap::iterator iter = mBuddyListMap.find(&blockMask);
+	if(iter != mBuddyListMap.end())
 	{
-		return FALSE;
+		LL_DEBUGS("Voice") << "block list entry for " << blockMask << LL_ENDL;
+		buddy = iter->second;
 	}
-}
 
-F32 LLVoiceClient::getCurrentPower(const LLUUID& id)
-{		
-	if (mVoiceModule) 
+	if(buddy == NULL)
 	{
-		return mVoiceModule->getCurrentPower(id);
+		LL_DEBUGS("Voice") << "block list entry for unknown buddy " << blockMask << LL_ENDL;
+		buddy = addBuddy(blockMask);
 	}
-	else
+	
+	if(buddy != NULL)
 	{
-		return 0.0;
+		buddy->mHasBlockListEntry = true;
 	}
 }
 
-BOOL LLVoiceClient::getOnMuteList(const LLUUID& id)
+void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->getOnMuteList(id);
-	}
-	else
+	buddyListEntry *buddy = NULL;
+
+	// blockMask is the SIP URI of a friends list entry
+	buddyListMap::iterator iter = mBuddyListMap.find(&autoAcceptMask);
+	if(iter != mBuddyListMap.end())
 	{
-		return FALSE;
+		LL_DEBUGS("Voice") << "auto-accept list entry for " << autoAcceptMask << LL_ENDL;
+		buddy = iter->second;
 	}
-}
 
-F32 LLVoiceClient::getUserVolume(const LLUUID& id)
-{
-	if (mVoiceModule) 
+	if(buddy == NULL)
 	{
-		return mVoiceModule->getUserVolume(id);
+		LL_DEBUGS("Voice") << "auto-accept list entry for unknown buddy " << autoAcceptMask << LL_ENDL;
+		buddy = addBuddy(autoAcceptMask);
 	}
-	else
+
+	if(buddy != NULL)
 	{
-		return 0.0;
+		buddy->mHasAutoAcceptListEntry = true;
 	}
 }
 
-void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
+void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
+{
+	// Block list entries were updated via addBlockRule() during parsing.  Just flag that we're done.
+	mBlockRulesListReceived = true;
+}
+
+void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString)
+{
+	// Block list entries were updated via addBlockRule() during parsing.  Just flag that we're done.
+	mAutoAcceptRulesListReceived = true;
+}
+
+void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
+{
+	mParticipantObservers.insert(observer);
+}
+
+void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
 {
-	if (mVoiceModule) mVoiceModule->setUserVolume(id, volume);
+	mParticipantObservers.erase(observer);
 }
 
-//--------------------------------------------------
-// status observers
+void LLVoiceClient::notifyParticipantObservers()
+{
+	for (observer_set_t::iterator it = mParticipantObservers.begin();
+		it != mParticipantObservers.end();
+		)
+	{
+		LLVoiceClientParticipantObserver* observer = *it;
+		observer->onChange();
+		// In case onChange() deleted an entry.
+		it = mParticipantObservers.upper_bound(observer);
+	}
+}
 
 void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
 {
-	if (mVoiceModule) mVoiceModule->addObserver(observer);
+	mStatusObservers.insert(observer);
 }
 
 void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
 {
-	if (mVoiceModule) mVoiceModule->removeObserver(observer);
+	mStatusObservers.erase(observer);
+}
+
+void LLVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status)
+{
+	if(mAudioSession)
+	{
+		if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
+		{
+			switch(mAudioSession->mErrorStatusCode)
+			{
+				case 20713:		status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; 		break;
+				case 20714:		status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; 	break;
+				case 20715:
+					//invalid channel, we may be using a set of poorly cached
+					//info
+					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
+					break;
+				case 1009:
+					//invalid username and password
+					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
+					break;
+			}
+
+			// Reset the error code to make sure it won't be reused later by accident.
+			mAudioSession->mErrorStatusCode = 0;
+		}
+		else if(status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL)
+		{
+			switch(mAudioSession->mErrorStatusCode)
+			{
+				case 404:	// NOT_FOUND
+				case 480:	// TEMPORARILY_UNAVAILABLE
+				case 408:	// REQUEST_TIMEOUT
+					// call failed because other user was not available
+					// treat this as an error case
+					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
+
+					// Reset the error code to make sure it won't be reused later by accident.
+					mAudioSession->mErrorStatusCode = 0;
+				break;
+			}
+		}
+	}
+		
+	LL_DEBUGS("Voice") 
+		<< " " << LLVoiceClientStatusObserver::status2string(status)  
+		<< ", session URI " << getAudioSessionURI() 
+		<< (inSpatialChannel()?", proximal is true":", proximal is false")
+	<< LL_ENDL;
+
+	for (status_observer_set_t::iterator it = mStatusObservers.begin();
+		it != mStatusObservers.end();
+		)
+	{
+		LLVoiceClientStatusObserver* observer = *it;
+		observer->onChange(status, getAudioSessionURI(), inSpatialChannel());
+		// In case onError() deleted an entry.
+		it = mStatusObservers.upper_bound(observer);
+	}
+
 }
 
 void LLVoiceClient::addObserver(LLFriendObserver* observer)
 {
-	if (mVoiceModule) mVoiceModule->addObserver(observer);
+	mFriendObservers.insert(observer);
 }
 
 void LLVoiceClient::removeObserver(LLFriendObserver* observer)
 {
-	if (mVoiceModule) mVoiceModule->removeObserver(observer);
+	mFriendObservers.erase(observer);
 }
 
-void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
+void LLVoiceClient::notifyFriendObservers()
 {
-	if (mVoiceModule) mVoiceModule->addObserver(observer);
+	for (friend_observer_set_t::iterator it = mFriendObservers.begin();
+		it != mFriendObservers.end();
+		)
+	{
+		LLFriendObserver* observer = *it;
+		it++;
+		// The only friend-related thing we notify on is online/offline transitions.
+		observer->changed(LLFriendObserver::ONLINE);
+	}
 }
 
-void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
+void LLVoiceClient::lookupName(const LLUUID &id)
 {
-	if (mVoiceModule) mVoiceModule->removeObserver(observer);
+	BOOL is_group = FALSE;
+	gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
 }
 
-std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
+//static
+void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
 {
-	if (mVoiceModule) 
-	{
-		return mVoiceModule->sipURIFromID(id);
-	}
-	else
+	if(gVoiceClient)
 	{
-		return std::string();
+		std::string name = llformat("%s %s", first.c_str(), last.c_str());
+		gVoiceClient->avatarNameResolved(id, name);
 	}
 }
 
-
-///////////////////
-// version checking
-
-class LLViewerRequiredVoiceVersion : public LLHTTPNode
+void LLVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
 {
-	static BOOL sAlertedUser;
-	virtual void post(
-					  LLHTTPNode::ResponsePtr response,
-					  const LLSD& context,
-					  const LLSD& input) const
+	// If the avatar whose name just resolved is on our friends list, resync the friends list.
+	if(LLAvatarTracker::instance().getBuddyInfo(id) != NULL)
 	{
-		//You received this messsage (most likely on region cross or
-		//teleport)
-		if ( input.has("body") && input["body"].has("major_version") )
+		mFriendsListDirty = true;
+	}
+	
+	// Iterate over all sessions.
+	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+	{
+		sessionState *session = *iter;
+
+		// Check for this user as a participant in this session
+		participantState *participant = session->findParticipantByID(id);
+		if(participant)
 		{
-			int major_voice_version =
-			input["body"]["major_version"].asInteger();
-			// 			int minor_voice_version =
-			// 				input["body"]["minor_version"].asInteger();
-			LLVoiceVersionInfo versionInfo = LLVoiceClient::getInstance()->getVersion();
-			
-			if (major_voice_version > 1)
+			// Found -- fill in the name
+			participant->mAccountName = name;
+			// and post a "participants updated" message to listeners later.
+			session->mParticipantsChanged = true;
+		}
+		
+		// Check whether this is a p2p session whose caller name just resolved
+		if(session->mCallerID == id)
+		{
+			// this session's "caller ID" just resolved.  Fill in the name.
+			session->mName = name;
+			if(session->mTextInvitePending)
 			{
-				if (!sAlertedUser)
-				{
-					//sAlertedUser = TRUE;
-					LLNotificationsUtil::add("VoiceVersionMismatch");
-					gSavedSettings.setBOOL("EnableVoiceChat", FALSE); // toggles listener
-				}
+				session->mTextInvitePending = false;
+
+				// We don't need to call gIMMgr->addP2PSession() here.  The first incoming message will create the panel.				
+			}
+			if(session->mVoiceInvitePending)
+			{
+				session->mVoiceInvitePending = false;
+
+				gIMMgr->inviteToSession(
+					session->mIMSessionID,
+					session->mName,
+					session->mCallerID, 
+					session->mName, 
+					IM_SESSION_P2P_INVITE, 
+					LLIMMgr::INVITATION_TYPE_VOICE,
+					session->mHandle,
+					session->mSIPURI);
 			}
+			
 		}
 	}
-};
+}
 
 class LLViewerParcelVoiceInfo : public LLHTTPNode
 {
 	virtual void post(
-					  LLHTTPNode::ResponsePtr response,
-					  const LLSD& context,
-					  const LLSD& input) const
+		LLHTTPNode::ResponsePtr response,
+		const LLSD& context,
+		const LLSD& input) const
 	{
 		//the parcel you are in has changed something about its
 		//voice information
-		
+
 		//this is a misnomer, as it can also be when you are not in
 		//a parcel at all.  Should really be something like
 		//LLViewerVoiceInfoChanged.....
 		if ( input.has("body") )
 		{
 			LLSD body = input["body"];
-			
+
 			//body has "region_name" (str), "parcel_local_id"(int),
 			//"voice_credentials" (map).
-			
+
 			//body["voice_credentials"] has "channel_uri" (str),
 			//body["voice_credentials"] has "channel_credentials" (str)
-			
+
 			//if we really wanted to be extra careful,
 			//we'd check the supplied
 			//local parcel id to make sure it's for the same parcel
@@ -764,7 +7279,7 @@ class LLViewerParcelVoiceInfo : public LLHTTPNode
 				LLSD voice_credentials = body["voice_credentials"];
 				std::string uri;
 				std::string credentials;
-				
+
 				if ( voice_credentials.has("channel_uri") )
 				{
 					uri = voice_credentials["channel_uri"].asString();
@@ -772,96 +7287,51 @@ class LLViewerParcelVoiceInfo : public LLHTTPNode
 				if ( voice_credentials.has("channel_credentials") )
 				{
 					credentials =
-					voice_credentials["channel_credentials"].asString();
+						voice_credentials["channel_credentials"].asString();
 				}
-				
-				LLVoiceClient::getInstance()->setSpatialChannel(uri, credentials);
+
+				gVoiceClient->setSpatialChannel(uri, credentials);
 			}
 		}
 	}
 };
 
-const std::string LLSpeakerVolumeStorage::SETTINGS_FILE_NAME = "volume_settings.xml";
-
-LLSpeakerVolumeStorage::LLSpeakerVolumeStorage()
-{
-	load();
-}
-
-LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage()
-{
-	save();
-}
-
-void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, F32 volume)
-{
-	mSpeakersData[speaker_id] = volume;
-}
-
-S32 LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id)
-{
-	// Return value of -1 indicates no level is stored for this speaker
-	S32 ret_val = -1;
-	speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id);
-	
-	if (it != mSpeakersData.end())
-	{
-		F32 f_val = it->second;
-		// volume can amplify by as much as 4x!
-		S32 ivol = (S32)(400.f * f_val * f_val);
-		ret_val = llclamp(ivol, 0, 400);
-	}
-	return ret_val;
-}
-
-void LLSpeakerVolumeStorage::load()
-{
-	// load per-resident voice volume information
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME);
-
-	LLSD settings_llsd;
-	llifstream file;
-	file.open(filename);
-	if (file.is_open())
-	{
-		LLSDSerialize::fromXML(settings_llsd, file);
-	}
-
-	for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
-		iter != settings_llsd.endMap(); ++iter)
-	{
-		mSpeakersData.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal()));
-	}
-}
-
-void LLSpeakerVolumeStorage::save()
+class LLViewerRequiredVoiceVersion : public LLHTTPNode
 {
-	// If we quit from the login screen we will not have an SL account
-	// name.  Don't try to save, otherwise we'll dump a file in
-	// C:\Program Files\SecondLife\ or similar. JC
-	std::string user_dir = gDirUtilp->getLindenUserDir();
-	if (!user_dir.empty())
+	static BOOL sAlertedUser;
+	virtual void post(
+		LLHTTPNode::ResponsePtr response,
+		const LLSD& context,
+		const LLSD& input) const
 	{
-		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME);
-		LLSD settings_llsd;
-
-		for(speaker_data_map_t::const_iterator iter = mSpeakersData.begin(); iter != mSpeakersData.end(); ++iter)
+		//You received this messsage (most likely on region cross or
+		//teleport)
+		if ( input.has("body") && input["body"].has("major_version") )
 		{
-			settings_llsd[iter->first.asString()] = iter->second;
-		}
+			int major_voice_version =
+				input["body"]["major_version"].asInteger();
+// 			int minor_voice_version =
+// 				input["body"]["minor_version"].asInteger();
 
-		llofstream file;
-		file.open(filename);
-		LLSDSerialize::toPrettyXML(settings_llsd, file);
+			if (gVoiceClient &&
+				(major_voice_version > VOICE_MAJOR_VERSION) )
+			{
+				if (!sAlertedUser)
+				{
+					//sAlertedUser = TRUE;
+					LLNotificationsUtil::add("VoiceVersionMismatch");
+					gSavedSettings.setBOOL("EnableVoiceChat", FALSE); // toggles listener
+				}
+			}
+		}
 	}
-}
-
+};
 BOOL LLViewerRequiredVoiceVersion::sAlertedUser = FALSE;
 
 LLHTTPRegistration<LLViewerParcelVoiceInfo>
-gHTTPRegistrationMessageParcelVoiceInfo(
-										"/message/ParcelVoiceInfo");
+    gHTTPRegistrationMessageParcelVoiceInfo(
+		"/message/ParcelVoiceInfo");
 
 LLHTTPRegistration<LLViewerRequiredVoiceVersion>
-gHTTPRegistrationMessageRequiredVoiceVersion(
-											 "/message/RequiredVoiceVersion");
+    gHTTPRegistrationMessageRequiredVoiceVersion(
+		"/message/RequiredVoiceVersion");
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index f1a7d3dbec2b22bd2d6fe9aa0a9af930ae5892ab..a29c386182db988b5d96d56ced8b4b1a57a8f2c8 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -17,7 +17,8 @@
  * 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
+ * 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,
@@ -32,6 +33,7 @@
 #define LL_VOICE_CLIENT_H
 
 class LLVOAvatar;
+class LLVivoxProtocolParser;
 
 #include "lliopipe.h"
 #include "llpumpio.h"
@@ -40,14 +42,9 @@ class LLVOAvatar;
 #include "v3math.h"
 #include "llframetimer.h"
 #include "llviewerregion.h"
-#include "llcallingcard.h"   // for LLFriendObserver
-#include "llsecapi.h"
-
-// devices
-
-typedef std::vector<std::string> LLVoiceDeviceList;	
-
+#include "m3math.h"			// LLMatrix3
 
+class LLFriendObserver;
 class LLVoiceClientParticipantObserver
 {
 public:
@@ -55,9 +52,6 @@ class LLVoiceClientParticipantObserver
 	virtual void onChange() = 0;
 };
 
-
-///////////////////////////////////
-/// @class LLVoiceClientStatusObserver
 class LLVoiceClientStatusObserver
 {
 public:
@@ -71,7 +65,11 @@ class LLVoiceClientStatusObserver
 		STATUS_JOINED,
 		STATUS_LEFT_CHANNEL,
 		STATUS_VOICE_DISABLED,
+
+		// Adding STATUS_VOICE_ENABLED as pair status for STATUS_VOICE_DISABLED
+		// See LLVoiceClient::setVoiceEnabled()
 		STATUS_VOICE_ENABLED,
+
 		BEGIN_ERROR_STATUS,
 		ERROR_CHANNEL_FULL,
 		ERROR_CHANNEL_LOCKED,
@@ -85,367 +83,699 @@ class LLVoiceClientStatusObserver
 	static std::string status2string(EStatusType inStatus);
 };
 
-struct LLVoiceVersionInfo
+class LLVoiceClient: public LLSingleton<LLVoiceClient>
 {
-	std::string serverType;
-	std::string serverVersion;
-};
+	LOG_CLASS(LLVoiceClient);
+	public:
+		LLVoiceClient();	
+		~LLVoiceClient();
+		
+	public:
+		static void init(LLPumpIO *pump);	// Call this once at application startup (creates connector)
+		static void terminate();	// Call this to clean up during shutdown
+						
+	protected:
+		bool writeString(const std::string &str);
+
+	public:
+		
+		static F32 OVERDRIVEN_POWER_LEVEL;
 
-//////////////////////////////////
-/// @class LLVoiceModuleInterface
-/// @brief Voice module interface
-///
-/// Voice modules should provide an implementation for this interface.
-/////////////////////////////////
+		static const F32 VOLUME_MIN;
+		static const F32 VOLUME_DEFAULT;
+		static const F32 VOLUME_MAX;
 
-class LLVoiceModuleInterface
-{
-public:
-	LLVoiceModuleInterface() {}
-	virtual ~LLVoiceModuleInterface() {}
-	
-	virtual void init(LLPumpIO *pump)=0;	// Call this once at application startup (creates connector)
-	virtual void terminate()=0;	// Call this to clean up during shutdown
-	
-	virtual void updateSettings()=0; // call after loading settings and whenever they change
+		void updateSettings(); // call after loading settings and whenever they change
 	
-	virtual bool isVoiceWorking()=0; // connected to a voice server and voice channel
+		void getCaptureDevicesSendMessage();
+		void getRenderDevicesSendMessage();
+		
+		void clearCaptureDevices();
+		void addCaptureDevice(const std::string& name);
+		void setCaptureDevice(const std::string& name);
+		
+		void clearRenderDevices();
+		void addRenderDevice(const std::string& name);
+		void setRenderDevice(const std::string& name);
+
+		void tuningStart();
+		void tuningStop();
+		bool inTuningMode();
+		bool inTuningStates();
+		
+		void tuningRenderStartSendMessage(const std::string& name, bool loop);
+		void tuningRenderStopSendMessage();
 
-	virtual const LLVoiceVersionInfo& getVersion()=0;
-	
-	/////////////////////
-	/// @name Tuning
-	//@{
-	virtual void tuningStart()=0;
-	virtual void tuningStop()=0;
-	virtual bool inTuningMode()=0;
-	
-	virtual void tuningSetMicVolume(float volume)=0;
-	virtual void tuningSetSpeakerVolume(float volume)=0;
-	virtual float tuningGetEnergy(void)=0;
-	//@}
-	
-	/////////////////////
-	/// @name Devices
-	//@{
-	// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
-	// i.e. when the daemon is running and connected, and the device lists are populated.
-	virtual bool deviceSettingsAvailable()=0;
-	
-	// Requery the vivox daemon for the current list of input/output devices.
-	// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
-	// (use this if you want to know when it's done).
-	// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
-	virtual void refreshDeviceLists(bool clearCurrentList = true)=0;
-	
-	virtual void setCaptureDevice(const std::string& name)=0;
-	virtual void setRenderDevice(const std::string& name)=0;
-	
-	virtual LLVoiceDeviceList& getCaptureDevices()=0;
-	virtual LLVoiceDeviceList& getRenderDevices()=0;
-	
-	virtual void getParticipantList(std::set<LLUUID> &participants)=0;
-	virtual bool isParticipant(const LLUUID& speaker_id)=0;
-	//@}
-	
-	////////////////////////////
-	/// @ name Channel stuff
-	//@{
-	// returns true iff the user is currently in a proximal (local spatial) channel.
-	// Note that gestures should only fire if this returns true.
-	virtual bool inProximalChannel()=0;
-	
-	virtual void setNonSpatialChannel(const std::string &uri,
-									  const std::string &credentials)=0;
-	
-	virtual void setSpatialChannel(const std::string &uri,
-								   const std::string &credentials)=0;
-	
-	virtual void leaveNonSpatialChannel()=0;
-	
-	virtual void leaveChannel(void)=0;	
-	
-	// Returns the URI of the current channel, or an empty string if not currently in a channel.
-	// NOTE that it will return an empty string if it's in the process of joining a channel.
-	virtual std::string getCurrentChannel()=0;
-	//@}
-	
-	
-	//////////////////////////
-	/// @name invitations
-	//@{
-	// start a voice channel with the specified user
-	virtual void callUser(const LLUUID &uuid)=0;
-	virtual bool answerInvite(std::string &channelHandle)=0;
-	virtual void declineInvite(std::string &channelHandle)=0;
-	//@}
-	
-	/////////////////////////
-	/// @name Volume/gain
-	//@{
-	virtual void setVoiceVolume(F32 volume)=0;
-	virtual void setMicGain(F32 volume)=0;
-	//@}
-	
-	/////////////////////////
-	/// @name enable disable voice and features
-	//@{
-	virtual bool voiceEnabled()=0;
-	virtual void setVoiceEnabled(bool enabled)=0;
-	virtual void setLipSyncEnabled(BOOL enabled)=0;
-	virtual BOOL lipSyncEnabled()=0;	
-	virtual void setMuteMic(bool muted)=0;		// Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
-	//@}
-	
-	////////////////////////
-	/// @name PTT
-	//@{
-	virtual void setUserPTTState(bool ptt)=0;
-	virtual bool getUserPTTState()=0;
-	virtual void setUsePTT(bool usePTT)=0;
-	virtual void setPTTIsToggle(bool PTTIsToggle)=0;
-	virtual bool getPTTIsToggle()=0;	
-	virtual void toggleUserPTTState(void)=0;
-	virtual void inputUserControlState(bool down)=0;  // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
-	
-	virtual void keyDown(KEY key, MASK mask)=0;
-	virtual void keyUp(KEY key, MASK mask)=0;
-	virtual void middleMouseState(bool down)=0;
-	//@}
-	
-	//////////////////////////
-	/// @name nearby speaker accessors
-	//@{
-
-
-	virtual BOOL getVoiceEnabled(const LLUUID& id)=0;		// true if we've received data for this avatar
-	virtual std::string getDisplayName(const LLUUID& id)=0;
-	virtual BOOL isOnlineSIP(const LLUUID &id)=0;	
-	virtual BOOL isParticipantAvatar(const LLUUID &id)=0;
-	virtual BOOL getIsSpeaking(const LLUUID& id)=0;
-	virtual BOOL getIsModeratorMuted(const LLUUID& id)=0;
-	virtual F32 getCurrentPower(const LLUUID& id)=0;		// "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is...
-	virtual BOOL getOnMuteList(const LLUUID& id)=0;
-	virtual F32 getUserVolume(const LLUUID& id)=0;
-	virtual void setUserVolume(const LLUUID& id, F32 volume)=0; // set's volume for specified agent, from 0-1 (where .5 is nominal)	
-	//@}
-	
-	//////////////////////////
-	/// @name text chat
-	//@{
-	virtual BOOL isSessionTextIMPossible(const LLUUID& id)=0;
-	virtual BOOL isSessionCallBackPossible(const LLUUID& id)=0;
-	virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message)=0;
-	virtual void endUserIMSession(const LLUUID &uuid)=0;	
-	//@}
-	
-	// authorize the user
-	virtual void userAuthorized(const std::string& user_id,
-								const LLUUID &agentID)=0;
-	
-	//////////////////////////////
-	/// @name Status notification
-	//@{
-	virtual void addObserver(LLVoiceClientStatusObserver* observer)=0;
-	virtual void removeObserver(LLVoiceClientStatusObserver* observer)=0;
-	virtual void addObserver(LLFriendObserver* observer)=0;
-	virtual void removeObserver(LLFriendObserver* observer)=0;	
-	virtual void addObserver(LLVoiceClientParticipantObserver* observer)=0;
-	virtual void removeObserver(LLVoiceClientParticipantObserver* observer)=0;	
-	//@}
-	
-	virtual std::string sipURIFromID(const LLUUID &id)=0;
-	//@}
-	
-};
+		void tuningCaptureStartSendMessage(int duration);
+		void tuningCaptureStopSendMessage();
+		
+		void tuningSetMicVolume(float volume);
+		void tuningSetSpeakerVolume(float volume);
+		float tuningGetEnergy(void);
+				
+		// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
+		// i.e. when the daemon is running and connected, and the device lists are populated.
+		bool deviceSettingsAvailable();
+		
+		// Requery the vivox daemon for the current list of input/output devices.
+		// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
+		// (use this if you want to know when it's done).
+		// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
+		void refreshDeviceLists(bool clearCurrentList = true);
+		
+		// Call this if the connection to the daemon terminates unexpectedly.  It will attempt to reset everything and relaunch.
+		void daemonDied();
 
+		// Call this if we're just giving up on voice (can't provision an account, etc.).  It will clean up and go away.
+		void giveUp();
+		
+		/////////////////////////////
+		// Response/Event handlers
+		void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
+		void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases);
+		void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
+		void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
+		void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString);
+		void logoutResponse(int statusCode, std::string &statusString);
+		void connectorShutdownResponse(int statusCode, std::string &statusString);
+
+		void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
+		void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);
+		void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming);
+		void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString);
+		void sessionGroupAddedEvent(std::string &sessionGroupHandle);
+		void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle);
+		void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType);
+		void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString);
+		void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
+		void auxAudioPropertiesEvent(F32 energy);
+		void buddyPresenceEvent(std::string &uriString, std::string &alias, std::string &statusString, std::string &applicationString);
+		void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
+		void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType);
+		void subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType);
+		
+		void buddyListChanged();
+		void muteListChanged();
+		void updateFriends(U32 mask);
+		
+		/////////////////////////////
+		// Sending updates of current state
+static	void updatePosition(void);
+		void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
+		void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
+		bool channelFromRegion(LLViewerRegion *region, std::string &name);
+		void leaveChannel(void);		// call this on logout or teleport begin
 
-class LLVoiceClient: public LLSingleton<LLVoiceClient>
-{
-	LOG_CLASS(LLVoiceClient);
-public:
-	LLVoiceClient();	
-	~LLVoiceClient();
+		
+		void setMuteMic(bool muted);		// Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
+		bool getMuteMic() const;
+		void setUserPTTState(bool ptt);
+		bool getUserPTTState();
+		void toggleUserPTTState(void);
+		void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
+		void setVoiceEnabled(bool enabled);
+		static bool voiceEnabled();
+		// Checks is voice working judging from mState
+		// Returns true if vivox has successfully logged in and is not in error state
+		bool voiceWorking();
+		void setUsePTT(bool usePTT);
+		void setPTTIsToggle(bool PTTIsToggle);
+		bool getPTTIsToggle();
+		void setPTTKey(std::string &key);
+		void setEarLocation(S32 loc);
+		void setVoiceVolume(F32 volume);
+		void setMicGain(F32 volume);
+		void setUserVolume(const LLUUID& id, F32 volume); // sets volume for specified agent, from 0-1 (where .5 is nominal)
+		void setLipSyncEnabled(BOOL enabled);
+		BOOL lipSyncEnabled();
+
+		// PTT key triggering
+		void keyDown(KEY key, MASK mask);
+		void keyUp(KEY key, MASK mask);
+		void middleMouseState(bool down);
+
+		// Return the version of the Vivox library
+		std::string getAPIVersion() const { return mAPIVersion; }
+		
+		/////////////////////////////
+		// Accessors for data related to nearby speakers
+		BOOL getVoiceEnabled(const LLUUID& id);		// true if we've received data for this avatar
+		BOOL getIsSpeaking(const LLUUID& id);
+		BOOL getIsModeratorMuted(const LLUUID& id);
+		F32 getCurrentPower(const LLUUID& id);		// "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is...
+		BOOL getOnMuteList(const LLUUID& id);
+		F32 getUserVolume(const LLUUID& id);
+		std::string getDisplayName(const LLUUID& id);
+		
+		// MBW -- XXX -- Not sure how to get this data out of the TVC
+		BOOL getUsingPTT(const LLUUID& id);
+		std::string getGroupID(const LLUUID& id);		// group ID if the user is in group chat (empty string if not applicable)
 
-	void init(LLPumpIO *pump);	// Call this once at application startup (creates connector)
-	void terminate();	// Call this to clean up during shutdown
-	
-	const LLVoiceVersionInfo getVersion();
-	
-static const F32 OVERDRIVEN_POWER_LEVEL;
+		/////////////////////////////
+		BOOL getAreaVoiceDisabled();		// returns true if the area the avatar is in is speech-disabled.
+											// Use this to determine whether to show a "no speech" icon in the menu bar.
+		
+		/////////////////////////////
+		// Recording controls
+		void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
+		void recordingLoopSave(const std::string& filename);
+		void recordingStop();
+		
+		// Playback controls
+		void filePlaybackStart(const std::string& filename);
+		void filePlaybackStop();
+		void filePlaybackSetPaused(bool paused);
+		void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
+		
+		
+		// This is used by the string-keyed maps below, to avoid storing the string twice.
+		// The 'const std::string *' in the key points to a string actually stored in the object referenced by the map.
+		// The add and delete operations for each map allocate and delete in the right order to avoid dangling references.
+		// The default compare operation would just compare pointers, which is incorrect, so they must use this comparitor instead.
+		struct stringMapComparitor
+		{
+			bool operator()(const std::string* a, const std::string * b) const
+			{
+				return a->compare(*b) < 0;
+			}
+		};
+
+		struct uuidMapComparitor
+		{
+			bool operator()(const LLUUID* a, const LLUUID * b) const
+			{
+				return *a < *b;
+			}
+		};
+		
+		struct participantState
+		{
+		public:
+			participantState(const std::string &uri);
+
+			bool updateMuteState();	// true if mute state has changed
+			bool isAvatar();
+
+			std::string mURI;
+			LLUUID mAvatarID;
+			std::string mAccountName;
+			std::string mDisplayName;
+			LLFrameTimer mSpeakingTimeout;
+			F32	mLastSpokeTimestamp;
+			F32 mPower;
+			F32 mVolume;
+			std::string mGroupID;
+			bool mPTT;
+			bool mIsSpeaking;
+			bool mIsModeratorMuted;
+			bool mOnMuteList;		// true if this avatar is on the user's mute list (and should be muted)
+			bool mVolumeSet;		// true if incoming volume messages should not change the volume
+			bool mVolumeDirty;		// true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
+			bool mAvatarIDValid;
+			bool mIsSelf;
+		};
+		typedef std::map<const std::string *, participantState*, stringMapComparitor> participantMap;
+
+		typedef std::map<const LLUUID *, participantState*, uuidMapComparitor> participantUUIDMap;
+	
+		enum streamState
+		{
+			streamStateUnknown = 0,
+			streamStateIdle = 1,
+			streamStateConnected = 2,
+			streamStateRinging = 3,
+		};
+		
+		struct sessionState
+		{
+		public:
+			sessionState();
+			~sessionState();
+
+			participantState *addParticipant(const std::string &uri);
+			// Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
+			// Take care not to use the pointer again after that.
+			void removeParticipant(participantState *participant);
+			void removeAllParticipants();
+
+			participantState *findParticipant(const std::string &uri);
+			participantState *findParticipantByID(const LLUUID& id);
+
+			bool isCallBackPossible();
+			bool isTextIMPossible();
+
+			std::string mHandle;
+			std::string mGroupHandle;
+			std::string mSIPURI;
+			std::string mAlias;
+			std::string mName;
+			std::string mAlternateSIPURI;
+			std::string mHash;			// Channel password
+			std::string mErrorStatusString;
+			std::queue<std::string> mTextMsgQueue;
+			
+			LLUUID		mIMSessionID;
+			LLUUID		mCallerID;
+			int			mErrorStatusCode;
+			int			mMediaStreamState;
+			int			mTextStreamState;
+			bool		mCreateInProgress;	// True if a Session.Create has been sent for this session and no response has been received yet.
+			bool		mMediaConnectInProgress;	// True if a Session.MediaConnect has been sent for this session and no response has been received yet.
+			bool		mVoiceInvitePending;	// True if a voice invite is pending for this session (usually waiting on a name lookup)
+			bool		mTextInvitePending;		// True if a text invite is pending for this session (usually waiting on a name lookup)
+			bool		mSynthesizedCallerID;	// True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup.
+			bool		mIsChannel;	// True for both group and spatial channels (false for p2p, PSTN)
+			bool		mIsSpatial;	// True for spatial channels
+			bool		mIsP2P;
+			bool		mIncoming;
+			bool		mVoiceEnabled;
+			bool		mReconnect;	// Whether we should try to reconnect to this session if it's dropped
+			// Set to true when the mute state of someone in the participant list changes.
+			// The code will have to walk the list to find the changed participant(s).
+			bool		mVolumeDirty;
+			bool		mMuteDirty;
+
+			bool		mParticipantsChanged;
+			participantMap mParticipantsByURI;
+			participantUUIDMap mParticipantsByUUID;
+		};
+
+		participantState *findParticipantByID(const LLUUID& id);
+		participantMap *getParticipantList(void);
+		void getParticipantsUUIDSet(std::set<LLUUID>& participant_uuids);
+		
+		typedef std::map<const std::string*, sessionState*, stringMapComparitor> sessionMap;
+		typedef std::set<sessionState*> sessionSet;
+				
+		typedef sessionSet::iterator sessionIterator;
+		sessionIterator sessionsBegin(void);
+		sessionIterator sessionsEnd(void);
+
+		sessionState *findSession(const std::string &handle);
+		sessionState *findSessionBeingCreatedByURI(const std::string &uri);
+		sessionState *findSession(const LLUUID &participant_id);
+		sessionState *findSessionByCreateID(const std::string &create_id);
+		
+		sessionState *addSession(const std::string &uri, const std::string &handle = LLStringUtil::null);
+		void setSessionHandle(sessionState *session, const std::string &handle = LLStringUtil::null);
+		void setSessionURI(sessionState *session, const std::string &uri);
+		void deleteSession(sessionState *session);
+		void deleteAllSessions(void);
 
-	void updateSettings(); // call after loading settings and whenever they change
+		void verifySessionState(void);
 
-	bool isVoiceWorking(); // connected to a voice server and voice channel
+		void joinedAudioSession(sessionState *session);
+		void leftAudioSession(sessionState *session);
 
-	// tuning
-	void tuningStart();
-	void tuningStop();
-	bool inTuningMode();
+		// This is called in several places where the session _may_ need to be deleted.
+		// It contains logic for whether to delete the session or keep it around.
+		void reapSession(sessionState *session);
+		
+		// Returns true if the session seems to indicate we've moved to a region on a different voice server
+		bool sessionNeedsRelog(sessionState *session);
+		
+		struct buddyListEntry
+		{
+			buddyListEntry(const std::string &uri);
+			std::string mURI;
+			std::string mDisplayName;
+			LLUUID	mUUID;
+			bool mOnlineSL;
+			bool mOnlineSLim;
+			bool mCanSeeMeOnline;
+			bool mHasBlockListEntry;
+			bool mHasAutoAcceptListEntry;
+			bool mNameResolved;
+			bool mInSLFriends;
+			bool mInVivoxBuddies;
+			bool mNeedsNameUpdate;
+		};
+
+		typedef std::map<const std::string*, buddyListEntry*, stringMapComparitor> buddyListMap;
+		
+		// This should be called when parsing a buddy list entry sent by SLVoice.		
+		void processBuddyListEntry(const std::string &uri, const std::string &displayName);
+
+		buddyListEntry *addBuddy(const std::string &uri);
+		buddyListEntry *addBuddy(const std::string &uri, const std::string &displayName);
+		buddyListEntry *findBuddy(const std::string &uri);
+		buddyListEntry *findBuddy(const LLUUID &id);
+		buddyListEntry *findBuddyByDisplayName(const std::string &name);
+		void deleteBuddy(const std::string &uri);
+		void deleteAllBuddies(void);
+
+		void deleteAllBlockRules(void);
+		void addBlockRule(const std::string &blockMask, const std::string &presenceOnly);
+		void deleteAllAutoAcceptRules(void);
+		void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy);
+		void accountListBlockRulesResponse(int statusCode, const std::string &statusString);						
+		void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);						
+		
+		/////////////////////////////
+		// session control messages
+		void connectorCreate();
+		void connectorShutdown();
+
+		void requestVoiceAccountProvision(S32 retries = 3);
+		void userAuthorized(
+			const std::string& firstName,
+			const std::string& lastName,
+			const LLUUID &agentID);
+		void login(
+			const std::string& account_name,
+			const std::string& password,
+			const std::string& voice_sip_uri_hostname,
+			const std::string& voice_account_server_uri);
+		void loginSendMessage();
+		void logout();
+		void logoutSendMessage();
+
+		void accountListBlockRulesSendMessage();
+		void accountListAutoAcceptRulesSendMessage();
 		
-	void tuningSetMicVolume(float volume);
-	void tuningSetSpeakerVolume(float volume);
-	float tuningGetEnergy(void);
+		void sessionGroupCreateSendMessage();
+		void sessionCreateSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
+		void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
+		void sessionMediaConnectSendMessage(sessionState *session);		// just joins the audio session
+		void sessionTextConnectSendMessage(sessionState *session);		// just joins the text session
+		void sessionTerminateSendMessage(sessionState *session);
+		void sessionGroupTerminateSendMessage(sessionState *session);
+		void sessionMediaDisconnectSendMessage(sessionState *session);
+		void sessionTextDisconnectSendMessage(sessionState *session);
+
+		// Pokes the state machine to leave the audio session next time around.
+		void sessionTerminate();	
+		
+		// Pokes the state machine to shut down the connector and restart it.
+		void requestRelog();
+		
+		// Does the actual work to get out of the audio session
+		void leaveAudioSession();
+		
+		void addObserver(LLVoiceClientParticipantObserver* observer);
+		void removeObserver(LLVoiceClientParticipantObserver* observer);
+
+		void addObserver(LLVoiceClientStatusObserver* observer);
+		void removeObserver(LLVoiceClientStatusObserver* observer);
+
+		void addObserver(LLFriendObserver* observer);
+		void removeObserver(LLFriendObserver* observer);
+		
+		void lookupName(const LLUUID &id);
+		static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+		void avatarNameResolved(const LLUUID &id, const std::string &name);
+		
+		typedef std::vector<std::string> deviceList;
+
+		deviceList *getCaptureDevices();
+		deviceList *getRenderDevices();
+		
+		void setNonSpatialChannel(
+			const std::string &uri,
+			const std::string &credentials);
+		void setSpatialChannel(
+			const std::string &uri,
+			const std::string &credentials);
+		// start a voice session with the specified user
+		void callUser(const LLUUID &uuid);
+		
+		// Send a text message to the specified user, initiating the session if necessary.
+		bool sendTextMessage(const LLUUID& participant_id, const std::string& message);
+		
+		// close any existing text IM session with the specified user
+		void endUserIMSession(const LLUUID &uuid);
+		
+		bool answerInvite(std::string &sessionHandle);
+		void declineInvite(std::string &sessionHandle);
+		void leaveNonSpatialChannel();
+
+		// Returns the URI of the current channel, or an empty string if not currently in a channel.
+		// NOTE that it will return an empty string if it's in the process of joining a channel.
+		std::string getCurrentChannel();
+		
+		// returns true iff the user is currently in a proximal (local spatial) channel.
+		// Note that gestures should only fire if this returns true.
+		bool inProximalChannel();
+
+		std::string sipURIFromID(const LLUUID &id);
 				
-	// devices
-	
-	// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
-	// i.e. when the daemon is running and connected, and the device lists are populated.
-	bool deviceSettingsAvailable();
+		// Returns true if the indicated user is online via SIP presence according to SLVoice.
+		// Note that we only get SIP presence data for other users that are in our vivox buddy list.
+		bool isOnlineSIP(const LLUUID &id);
+
+		// Returns true if the indicated participant is really an SL avatar.
+		// This should be used to control the state of the "profile" button.
+		// Currently this will be false only for PSTN callers into group chats, and PSTN p2p calls.
+		bool isParticipantAvatar(const LLUUID &id);
+		
+		// Returns true if calling back the session URI after the session has closed is possible.
+		// Currently this will be false only for PSTN P2P calls.		
+		// NOTE: this will return true if the session can't be found. 
+		bool isSessionCallBackPossible(const LLUUID &session_id);
+		
+		// Returns true if the session can accepte text IM's.
+		// Currently this will be false only for PSTN P2P calls.
+		// NOTE: this will return true if the session can't be found. 
+		bool isSessionTextIMPossible(const LLUUID &session_id);
+		
+	private:
+
+		// internal state for a simple state machine.  This is used to deal with the asynchronous nature of some of the messages.
+		// Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string().
+		enum state
+		{
+			stateDisableCleanup,
+			stateDisabled,				// Voice is turned off.
+			stateStart,					// Class is initialized, socket is created
+			stateDaemonLaunched,		// Daemon has been launched
+			stateConnecting,			// connect() call has been issued
+			stateConnected,				// connection to the daemon has been made, send some initial setup commands.
+			stateIdle,					// socket is connected, ready for messaging
+			stateMicTuningStart,
+			stateMicTuningRunning,		
+			stateMicTuningStop,
+			stateConnectorStart,		// connector needs to be started
+			stateConnectorStarting,		// waiting for connector handle
+			stateConnectorStarted,		// connector handle received
+			stateLoginRetry,			// need to retry login (failed due to changing password)
+			stateLoginRetryWait,		// waiting for retry timer
+			stateNeedsLogin,			// send login request
+			stateLoggingIn,				// waiting for account handle
+			stateLoggedIn,				// account handle received
+			stateCreatingSessionGroup,	// Creating the main session group
+			stateNoChannel,				// 
+			stateJoiningSession,		// waiting for session handle
+			stateSessionJoined,			// session handle received
+			stateRunning,				// in session, steady state
+			stateLeavingSession,		// waiting for terminate session response
+			stateSessionTerminated,		// waiting for terminate session response
+
+			stateLoggingOut,			// waiting for logout response
+			stateLoggedOut,				// logout response received
+			stateConnectorStopping,		// waiting for connector stop
+			stateConnectorStopped,		// connector stop received
+			
+			// We go to this state if the login fails because the account needs to be provisioned.
+			
+			// error states.  No way to recover from these yet.
+			stateConnectorFailed,
+			stateConnectorFailedWaiting,
+			stateLoginFailed,
+			stateLoginFailedWaiting,
+			stateJoinSessionFailed,
+			stateJoinSessionFailedWaiting,
+
+			stateJail					// Go here when all else has failed.  Nothing will be retried, we're done.
+		};
 		
-	// Requery the vivox daemon for the current list of input/output devices.
-	// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
-	// (use this if you want to know when it's done).
-	// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
-	void refreshDeviceLists(bool clearCurrentList = true);
+		state mState;
+		bool mSessionTerminateRequested;
+		bool mRelogRequested;
+		// Number of times (in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine().
+		// The larger it is the greater is possibility there is a problem with connection to voice server.
+		// Introduced while fixing EXT-4313.
+		int mSpatialJoiningNum;
+		
+		void setState(state inState);
+		state getState(void)  { return mState; };
+		static std::string state2string(state inState);
+		
+		void stateMachine();
+		static void idle(void *user_data);
+		
+		LLHost mDaemonHost;
+		LLSocket::ptr_t mSocket;
+		bool mConnected;
+		
+		void closeSocket(void);
+		
+		LLPumpIO *mPump;
+		friend class LLVivoxProtocolParser;
+		
+		std::string mAccountName;
+		std::string mAccountPassword;
+		std::string mAccountDisplayName;
+		std::string mAccountFirstName;
+		std::string mAccountLastName;
+				
+		bool mTuningMode;
+		float mTuningEnergy;
+		std::string mTuningAudioFile;
+		int mTuningMicVolume;
+		bool mTuningMicVolumeDirty;
+		int mTuningSpeakerVolume;
+		bool mTuningSpeakerVolumeDirty;
+		state mTuningExitState;					// state to return to when we leave tuning mode.
+		
+		std::string mSpatialSessionURI;
+		std::string mSpatialSessionCredentials;
 
-	void setCaptureDevice(const std::string& name);
-	void setRenderDevice(const std::string& name);
+		std::string mMainSessionGroupHandle; // handle of the "main" session group.
+		
+		std::string mChannelName;			// Name of the channel to be looked up 
+		bool mAreaVoiceDisabled;
+		sessionState *mAudioSession;		// Session state for the current audio session
+		bool mAudioSessionChanged;			// set to true when the above pointer gets changed, so observers can be notified.
 
-	const LLVoiceDeviceList& getCaptureDevices();
-	const LLVoiceDeviceList& getRenderDevices();
+		sessionState *mNextAudioSession;	// Session state for the audio session we're trying to join
 
-	////////////////////////////
-	// Channel stuff
-	//
-	
-	// returns true iff the user is currently in a proximal (local spatial) channel.
-	// Note that gestures should only fire if this returns true.
-	bool inProximalChannel();
-	void setNonSpatialChannel(
-							  const std::string &uri,
-							  const std::string &credentials);
-	void setSpatialChannel(
-						   const std::string &uri,
-						   const std::string &credentials);
-	void leaveNonSpatialChannel();
-	
-	// Returns the URI of the current channel, or an empty string if not currently in a channel.
-	// NOTE that it will return an empty string if it's in the process of joining a channel.
-	std::string getCurrentChannel();
-	// start a voice channel with the specified user
-	void callUser(const LLUUID &uuid);	
-	bool answerInvite(std::string &channelHandle);
-	void declineInvite(std::string &channelHandle);	
-	void leaveChannel(void);		// call this on logout or teleport begin
-	
-	
-	/////////////////////////////
-	// Sending updates of current state
+//		std::string mSessionURI;			// URI of the session we're in.
+//		std::string mSessionHandle;		// returned by ?
+		
+		S32 mCurrentParcelLocalID;			// Used to detect parcel boundary crossings
+		std::string mCurrentRegionName;		// Used to detect parcel boundary crossings
+		
+		std::string mConnectorHandle;	// returned by "Create Connector" message
+		std::string mAccountHandle;		// returned by login message		
+		int 		mNumberOfAliases;
+		U32 mCommandCookie;
 	
+		std::string mVoiceAccountServerURI;
+		std::string mVoiceSIPURIHostName;
+		
+		int mLoginRetryCount;
+		
+		sessionMap mSessionsByHandle;				// Active sessions, indexed by session handle.  Sessions which are being initiated may not be in this map.
+		sessionSet mSessions;						// All sessions, not indexed.  This is the canonical session list.
+		
+		bool mBuddyListMapPopulated;
+		bool mBlockRulesListReceived;
+		bool mAutoAcceptRulesListReceived;
+		buddyListMap mBuddyListMap;
+		
+		deviceList mCaptureDevices;
+		deviceList mRenderDevices;
 
-	void setVoiceVolume(F32 volume);
-	void setMicGain(F32 volume);
-	void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)		
-	bool voiceEnabled();
-	void setLipSyncEnabled(BOOL enabled);
-	void setMuteMic(bool muted);		// Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
-	void setUserPTTState(bool ptt);
-	bool getUserPTTState();
-	void toggleUserPTTState(void);
-	void inputUserControlState(bool down);  // interpret any sort of up-down mic-open control input according to ptt-toggle prefs	
-	void setVoiceEnabled(bool enabled);
-
-	void setUsePTT(bool usePTT);
-	void setPTTIsToggle(bool PTTIsToggle);
-	bool getPTTIsToggle();	
-	
-	BOOL lipSyncEnabled();
-	
-	// PTT key triggering
-	void keyDown(KEY key, MASK mask);
-	void keyUp(KEY key, MASK mask);
-	void middleMouseState(bool down);
-	
-	
-	/////////////////////////////
-	// Accessors for data related to nearby speakers
-	BOOL getVoiceEnabled(const LLUUID& id);		// true if we've received data for this avatar
-	std::string getDisplayName(const LLUUID& id);	
-	BOOL isOnlineSIP(const LLUUID &id);
-	BOOL isParticipantAvatar(const LLUUID &id);
-	BOOL getIsSpeaking(const LLUUID& id);
-	BOOL getIsModeratorMuted(const LLUUID& id);
-	F32 getCurrentPower(const LLUUID& id);		// "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is...
-	BOOL getOnMuteList(const LLUUID& id);
-	F32 getUserVolume(const LLUUID& id);
-
-	/////////////////////////////
-	BOOL getAreaVoiceDisabled();		// returns true if the area the avatar is in is speech-disabled.
-													  // Use this to determine whether to show a "no speech" icon in the menu bar.
-	void getParticipantList(std::set<LLUUID> &participants);
-	bool isParticipant(const LLUUID& speaker_id);
-	
-	//////////////////////////
-	/// @name text chat
-	//@{
-	BOOL isSessionTextIMPossible(const LLUUID& id);
-	BOOL isSessionCallBackPossible(const LLUUID& id);
-	BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message);
-	void endUserIMSession(const LLUUID &uuid);	
-	//@}
-	
+		std::string mCaptureDevice;
+		std::string mRenderDevice;
+		bool mCaptureDeviceDirty;
+		bool mRenderDeviceDirty;
+		
+		// This should be called when the code detects we have changed parcels.
+		// It initiates the call to the server that gets the parcel channel.
+		void parcelChanged();
+		
+	void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
+		void joinSession(sessionState *session);
+		
+static 	std::string nameFromAvatar(LLVOAvatar *avatar);
+static	std::string nameFromID(const LLUUID &id);
+static	bool IDFromName(const std::string name, LLUUID &uuid);
+static	std::string displayNameFromAvatar(LLVOAvatar *avatar);
+		std::string sipURIFromAvatar(LLVOAvatar *avatar);
+		std::string sipURIFromName(std::string &name);
+		
+		// Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
+static	std::string nameFromsipURI(const std::string &uri);		
 
-	void userAuthorized(const std::string& user_id,
-			const LLUUID &agentID);
-	
-	void addObserver(LLVoiceClientStatusObserver* observer);
-	void removeObserver(LLVoiceClientStatusObserver* observer);
-	void addObserver(LLFriendObserver* observer);
-	void removeObserver(LLFriendObserver* observer);
-	void addObserver(LLVoiceClientParticipantObserver* observer);
-	void removeObserver(LLVoiceClientParticipantObserver* observer);
-	
-	std::string sipURIFromID(const LLUUID &id);	
+		bool inSpatialChannel(void);
+		std::string getAudioSessionURI();
+		std::string getAudioSessionHandle();
+				
+		void sendPositionalUpdate(void);
 		
-protected:
-	LLVoiceModuleInterface* mVoiceModule;
-	LLPumpIO *m_servicePump;
-};
+		void buildSetCaptureDevice(std::ostringstream &stream);
+		void buildSetRenderDevice(std::ostringstream &stream);
+		void buildLocalAudioUpdates(std::ostringstream &stream);
+		
+		void clearAllLists();
+		void checkFriend(const LLUUID& id);
+		void sendFriendsListUpdates();
+
+		// start a text IM session with the specified user
+		// This will be asynchronous, the session may be established at a future time.
+		sessionState* startUserIMSession(const LLUUID& uuid);
+		void sendQueuedTextMessages(sessionState *session);
+		
+		void enforceTether(void);
+		
+		bool		mSpatialCoordsDirty;
+		
+		LLVector3d	mCameraPosition;
+		LLVector3d	mCameraRequestedPosition;
+		LLVector3	mCameraVelocity;
+		LLMatrix3	mCameraRot;
+
+		LLVector3d	mAvatarPosition;
+		LLVector3	mAvatarVelocity;
+		LLMatrix3	mAvatarRot;
+		
+		bool		mPTTDirty;
+		bool		mPTT;
+		
+		bool		mUsePTT;
+		bool		mPTTIsMiddleMouse;
+		KEY			mPTTKey;
+		bool		mPTTIsToggle;
+		bool		mUserPTTState;
+		bool		mMuteMic;
+				
+		// Set to true when the friends list is known to have changed.
+		bool		mFriendsListDirty;
+		
+		enum
+		{
+			earLocCamera = 0,		// ear at camera
+			earLocAvatar,			// ear at avatar
+			earLocMixed				// ear at avatar location/camera direction
+		};
+		
+		S32			mEarLocation;  
+		
+		bool		mSpeakerVolumeDirty;
+		bool		mSpeakerMuteDirty;
+		int			mSpeakerVolume;
+
+		int			mMicVolume;
+		bool		mMicVolumeDirty;
+		
+		bool		mVoiceEnabled;
+		bool		mWriteInProgress;
+		std::string mWriteString;
+		
+		LLTimer		mUpdateTimer;
+		
+		BOOL		mLipSyncEnabled;
 
-/**
- * Speaker volume storage helper class
- **/
+		std::string	mAPIVersion;
 
-class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>
-{
-	LOG_CLASS(LLSpeakerVolumeStorage);
-public:
+		typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
+		observer_set_t mParticipantObservers;
 
-	/**
-	 * Sets internal voluem level for specified user.
-	 *
-	 * @param[in] speaker_id - LLUUID of user to store volume level for
-	 * @param[in] volume - external volume level to be stored for user.
-	 */
-	void storeSpeakerVolume(const LLUUID& speaker_id, F32 volume);
-
-	/**
-	 * Gets stored external volume level for specified speaker.
-	 *
-	 * If specified user is not found default level will be returned. It is equivalent of 
-	 * external level 0.5 from the 0.0..1.0 range.
-	 * Default external level is calculated as: internal = 400 * external^2
-	 * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100
-	 *
-	 * @param[in] speaker_id - LLUUID of user to get his volume level
-	 */
-	S32 getSpeakerVolume(const LLUUID& speaker_id);
-
-private:
-	friend class LLSingleton<LLSpeakerVolumeStorage>;
-	LLSpeakerVolumeStorage();
-	~LLSpeakerVolumeStorage();
-
-	const static std::string SETTINGS_FILE_NAME;
-
-	void load();
-	void save();
-
-	typedef std::map<LLUUID, F32> speaker_data_map_t;
-	speaker_data_map_t mSpeakersData;
+		void notifyParticipantObservers();
+
+		typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
+		status_observer_set_t mStatusObservers;
+		
+		void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
+
+		typedef std::set<LLFriendObserver*> friend_observer_set_t;
+		friend_observer_set_t mFriendObservers;
+		void notifyFriendObservers();
 };
 
+extern LLVoiceClient *gVoiceClient;
+
 #endif //LL_VOICE_CLIENT_H
 
 
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
deleted file mode 100644
index 2f3bd567da46fe4bf3305b5a161c23e6672d8a6f..0000000000000000000000000000000000000000
--- a/indra/newview/llvoicevivox.cpp
+++ /dev/null
@@ -1,6967 +0,0 @@
- /** 
- * @file llvoicevivox.cpp
- * @brief Implementation of LLVivoxVoiceClient class which is the interface to the voice client process.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2010, 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 "llviewerprecompiledheaders.h"
-#include "llvoicevivox.h"
-
-#include <boost/tokenizer.hpp>
-
-#include "llsdutil.h"
-
-#include "llvoavatarself.h"
-#include "llbufferstream.h"
-#include "llfile.h"
-#ifdef LL_STANDALONE
-# include "expat.h"
-#else
-# include "expat/expat.h"
-#endif
-#include "llcallbacklist.h"
-#include "llviewerregion.h"
-#include "llviewernetwork.h"		// for gGridChoice
-#include "llbase64.h"
-#include "llviewercontrol.h"
-#include "llkeyboard.h"
-#include "llappviewer.h"	// for gDisconnected, gDisableVoice
-#include "llmutelist.h"  // to check for muted avatars
-#include "llagent.h"
-#include "llcachename.h"
-#include "llimview.h" // for LLIMMgr
-#include "llparcel.h"
-#include "llviewerparcelmgr.h"
-//#include "llfirstuse.h"
-#include "llspeakers.h"
-#include "llviewerwindow.h"
-#include "llviewercamera.h"
-
-#include "llfloaterfriends.h"  //VIVOX, inorder to refresh communicate panel
-#include "llviewernetwork.h"
-#include "llnotificationsutil.h"
-
-// for base64 decoding
-#include "apr_base64.h"
-
-// for SHA1 hash
-#include "apr_sha1.h"
-
-// for MD5 hash
-#include "llmd5.h"
-
-#define USE_SESSION_GROUPS 0
-
-const F32 SPEAKING_TIMEOUT = 1.f;
-
-static const std::string VOICE_SERVER_TYPE = "Vivox";
-
-// Don't retry connecting to the daemon more frequently than this:
-const F32 CONNECT_THROTTLE_SECONDS = 1.0f;
-
-// Don't send positional updates more frequently than this:
-const F32 UPDATE_THROTTLE_SECONDS = 0.1f;
-
-const F32 LOGIN_RETRY_SECONDS = 10.0f;
-const int MAX_LOGIN_RETRIES = 12;
-
-// Defines the maximum number of times(in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine()
-// which is treated as normal. If this number is exceeded we suspect there is a problem with connection
-// to voice server (EXT-4313). When voice works correctly, there is from 1 to 15 times. 50 was chosen 
-// to make sure we don't make mistake when slight connection problems happen- situation when connection to server is 
-// blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability.
-const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50;
-
-
-static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str)
-{
-	LLMD5 md5_uuid;
-	md5_uuid.update((const unsigned char*)str.data(), str.size());
-	md5_uuid.finalize();
-	md5_uuid.raw_digest(uuid.mData);
-}
-
-static int scale_mic_volume(float volume)
-{
-	// incoming volume has the range [0.0 ... 2.0], with 1.0 as the default.                                                
-	// Map it to Vivox levels as follows: 0.0 -> 30, 1.0 -> 50, 2.0 -> 70                                                   
-	return 30 + (int)(volume * 20.0f);
-}
-
-static int scale_speaker_volume(float volume)
-{
-	// incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.                                                
-	// Map it to Vivox levels as follows: 0.0 -> 30, 0.5 -> 50, 1.0 -> 70                                                   
-	return 30 + (int)(volume * 40.0f);
-	
-}
-
-class LLVivoxVoiceAccountProvisionResponder :
-	public LLHTTPClient::Responder
-{
-public:
-	LLVivoxVoiceAccountProvisionResponder(int retries)
-	{
-		mRetries = retries;
-	}
-
-	virtual void error(U32 status, const std::string& reason)
-	{
-		if ( mRetries > 0 )
-		{
-			LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying.  status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
-			LLVivoxVoiceClient::getInstance()->requestVoiceAccountProvision(
-				mRetries - 1);
-		}
-		else
-		{
-			LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up).  status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
-			LLVivoxVoiceClient::getInstance()->giveUp();
-		}
-	}
-
-	virtual void result(const LLSD& content)
-	{
-
-		std::string voice_sip_uri_hostname;
-		std::string voice_account_server_uri;
-		
-		LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
-		
-		if(content.has("voice_sip_uri_hostname"))
-			voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
-		
-		// this key is actually misnamed -- it will be an entire URI, not just a hostname.
-		if(content.has("voice_account_server_name"))
-			voice_account_server_uri = content["voice_account_server_name"].asString();
-		
-		LLVivoxVoiceClient::getInstance()->login(
-			content["username"].asString(),
-			content["password"].asString(),
-			voice_sip_uri_hostname,
-			voice_account_server_uri);
-
-	}
-
-private:
-	int mRetries;
-};
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-class LLVivoxVoiceClientMuteListObserver : public LLMuteListObserver
-{
-	/* virtual */ void onChange()  { LLVivoxVoiceClient::getInstance()->muteListChanged();}
-};
-
-class LLVivoxVoiceClientFriendsObserver : public LLFriendObserver
-{
-public:
-	/* virtual */ void changed(U32 mask) { LLVivoxVoiceClient::getInstance()->updateFriends(mask);}
-};
-
-static LLVivoxVoiceClientMuteListObserver mutelist_listener;
-static bool sMuteListListener_listening = false;
-
-static LLVivoxVoiceClientFriendsObserver *friendslist_listener = NULL;
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder
-{
-public:
-	LLVivoxVoiceClientCapResponder(void){};
-
-	virtual void error(U32 status, const std::string& reason);	// called with bad status codes
-	virtual void result(const LLSD& content);
-
-private:
-};
-
-void LLVivoxVoiceClientCapResponder::error(U32 status, const std::string& reason)
-{
-	LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder::error("
-		<< status << ": " << reason << ")"
-		<< LL_ENDL;
-}
-
-void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
-{
-	LLSD::map_const_iterator iter;
-	
-	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
-
-	if ( content.has("voice_credentials") )
-	{
-		LLSD voice_credentials = content["voice_credentials"];
-		std::string uri;
-		std::string credentials;
-
-		if ( voice_credentials.has("channel_uri") )
-		{
-			uri = voice_credentials["channel_uri"].asString();
-		}
-		if ( voice_credentials.has("channel_credentials") )
-		{
-			credentials =
-				voice_credentials["channel_credentials"].asString();
-		}
-
-		LLVivoxVoiceClient::getInstance()->setSpatialChannel(uri, credentials);
-	}
-}
-
-
-
-#if LL_WINDOWS
-static HANDLE sGatewayHandle = 0;
-
-static bool isGatewayRunning()
-{
-	bool result = false;
-	if(sGatewayHandle != 0)		
-	{
-		DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0);
-		if(waitresult != WAIT_OBJECT_0)
-		{
-			result = true;
-		}			
-	}
-	return result;
-}
-static void killGateway()
-{
-	if(sGatewayHandle != 0)
-	{
-		TerminateProcess(sGatewayHandle,0);
-	}
-}
-
-#else // Mac and linux
-
-static pid_t sGatewayPID = 0;
-static bool isGatewayRunning()
-{
-	bool result = false;
-	if(sGatewayPID != 0)
-	{
-		// A kill with signal number 0 has no effect, just does error checking.  It should return an error if the process no longer exists.
-		if(kill(sGatewayPID, 0) == 0)
-		{
-			result = true;
-		}
-	}
-	return result;
-}
-
-static void killGateway()
-{
-	if(sGatewayPID != 0)
-	{
-		kill(sGatewayPID, SIGTERM);
-	}
-}
-
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-LLVivoxVoiceClient::LLVivoxVoiceClient() :
-	mState(stateDisabled),
-	mSessionTerminateRequested(false),
-	mRelogRequested(false),
-	mConnected(false),
-	mPump(NULL),
-	mSpatialJoiningNum(0),
-
-	mTuningMode(false),
-	mTuningEnergy(0.0f),
-	mTuningMicVolume(0),
-	mTuningMicVolumeDirty(true),
-	mTuningSpeakerVolume(0),
-	mTuningSpeakerVolumeDirty(true),
-	mTuningExitState(stateDisabled),
-
-	mAreaVoiceDisabled(false),
-	mAudioSession(NULL),
-	mAudioSessionChanged(false),
-	mNextAudioSession(NULL),
-
-	mCurrentParcelLocalID(0),
-	mNumberOfAliases(0),
-	mCommandCookie(0),
-	mLoginRetryCount(0),
-
-	mBuddyListMapPopulated(false),
-	mBlockRulesListReceived(false),
-	mAutoAcceptRulesListReceived(false),
-	mCaptureDeviceDirty(false),
-	mRenderDeviceDirty(false),
-	mSpatialCoordsDirty(false),
-
-	mPTTDirty(true),
-	mPTT(true),
-	mUsePTT(true),
-	mPTTIsMiddleMouse(false),
-	mPTTKey(0),
-	mPTTIsToggle(false),
-	mUserPTTState(false),
-	mMuteMic(false),
-	mFriendsListDirty(true),
-
-	mEarLocation(0),
-	mSpeakerVolumeDirty(true),
-	mSpeakerMuteDirty(true),
-	mMicVolume(0),
-	mMicVolumeDirty(true),
-
-	mVoiceEnabled(false),
-	mWriteInProgress(false),
-
-	mLipSyncEnabled(false)
-
-
-
-{	
-	mSpeakerVolume = scale_speaker_volume(0);
-
-	mVoiceVersion.serverVersion = "";
-	mVoiceVersion.serverType = VOICE_SERVER_TYPE;
-	
-	//  gMuteListp isn't set up at this point, so we defer this until later.
-//	gMuteListp->addObserver(&mutelist_listener);
-	
-	
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
-		// HACK: THIS DOES NOT BELONG HERE
-		// When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
-		// This should cause us to ignore SIGPIPE and handle the error through proper channels.
-		// This should really be set up elsewhere.  Where should it go?
-		signal(SIGPIPE, SIG_IGN);
-		
-		// Since we're now launching the gateway with fork/exec instead of system(), we need to deal with zombie processes.
-		// Ignoring SIGCHLD should prevent zombies from being created.  Alternately, we could use wait(), but I'd rather not do that.
-		signal(SIGCHLD, SIG_IGN);
-#endif
-
-	// set up state machine
-	setState(stateDisabled);
-	
-	gIdleCallbacks.addFunction(idle, this);
-}
-
-//---------------------------------------------------
-
-LLVivoxVoiceClient::~LLVivoxVoiceClient()
-{
-}
-
-//----------------------------------------------
-
-void LLVivoxVoiceClient::init(LLPumpIO *pump)
-{
-	// constructor will set up LLVoiceClient::getInstance()
-	LLVivoxVoiceClient::getInstance()->mPump = pump;
-}
-
-void LLVivoxVoiceClient::terminate()
-{
-
-//	leaveAudioSession();
-	logout();
-	// As of SDK version 4885, this should no longer be necessary.  It will linger after the socket close if it needs to.
-	// ms_sleep(2000);
-	connectorShutdown();
-	closeSocket();		// Need to do this now -- bad things happen if the destructor does it later.
-	
-	// This will do unpleasant things on windows.
-//	killGateway();
-	
-
-
-}
-
-const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion()
-{
-	return mVoiceVersion;
-}
-
-//---------------------------------------------------
-
-void LLVivoxVoiceClient::updateSettings()
-{
-	setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat"));
-	setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
-	std::string keyString = gSavedSettings.getString("PushToTalkButton");
-	setPTTKey(keyString);
-	setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
-	setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
-
-	std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
-	setCaptureDevice(inputDevice);
-	std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
-	setRenderDevice(outputDevice);
-	F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
-	setMicGain(mic_level);
-	setLipSyncEnabled(gSavedSettings.getBOOL("LipSyncEnabled"));
-}
-
-/////////////////////////////
-// utility functions
-
-bool LLVivoxVoiceClient::writeString(const std::string &str)
-{
-	bool result = false;
-	if(mConnected)
-	{
-		apr_status_t err;
-		apr_size_t size = (apr_size_t)str.size();
-		apr_size_t written = size;
-	
-		//MARK: Turn this on to log outgoing XML
-//		LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
-
-		// check return code - sockets will fail (broken, etc.)
-		err = apr_socket_send(
-				mSocket->getSocket(),
-				(const char*)str.data(),
-				&written);
-		
-		if(err == 0)
-		{
-			// Success.
-			result = true;
-		}
-		// TODO: handle partial writes (written is number of bytes written)
-		// Need to set socket to non-blocking before this will work.
-//		else if(APR_STATUS_IS_EAGAIN(err))
-//		{
-//			// 
-//		}
-		else
-		{
-			// Assume any socket error means something bad.  For now, just close the socket.
-			char buf[MAX_STRING];
-			LL_WARNS("Voice") << "apr error " << err << " ("<< apr_strerror(err, buf, MAX_STRING) << ") sending data to vivox daemon." << LL_ENDL;
-			daemonDied();
-		}
-	}
-		
-	return result;
-}
-
-
-/////////////////////////////
-// session control messages
-void LLVivoxVoiceClient::connectorCreate()
-{
-	std::ostringstream stream;
-	std::string logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-	std::string loglevel = "0";
-	
-	// Transition to stateConnectorStarted when the connector handle comes back.
-	setState(stateConnectorStarting);
-
-	std::string savedLogLevel = gSavedSettings.getString("VivoxDebugLevel");
-		
-	if(savedLogLevel != "-1")
-	{
-		LL_DEBUGS("Voice") << "creating connector with logging enabled" << LL_ENDL;
-		loglevel = "10";
-	}
-	
-	stream 
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.Create.1\">"
-		<< "<ClientName>V2 SDK</ClientName>"
-		<< "<AccountManagementServer>" << mVoiceAccountServerURI << "</AccountManagementServer>"
-		<< "<Mode>Normal</Mode>"
-		<< "<Logging>"
-			<< "<Folder>" << logpath << "</Folder>"
-			<< "<FileNamePrefix>Connector</FileNamePrefix>"
-			<< "<FileNameSuffix>.log</FileNameSuffix>"
-			<< "<LogLevel>" << loglevel << "</LogLevel>"
-		<< "</Logging>"
-		<< "<Application>SecondLifeViewer.1</Application>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::connectorShutdown()
-{
-	setState(stateConnectorStopping);
-	
-	if(!mConnectorHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.InitiateShutdown.1\">"
-			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
-		<< "</Request>"
-		<< "\n\n\n";
-		
-		mConnectorHandle.clear();
-		
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID)
-{
-
-	mAccountDisplayName = user_id;
-
-	LL_INFOS("Voice") << "name \"" << mAccountDisplayName << "\" , ID " << agentID << LL_ENDL;
-
-	mAccountName = nameFromID(agentID);
-}
-
-void LLVivoxVoiceClient::requestVoiceAccountProvision(S32 retries)
-{
-	if ( gAgent.getRegion() && mVoiceEnabled )
-	{
-		std::string url = 
-			gAgent.getRegion()->getCapability(
-				"ProvisionVoiceAccountRequest");
-
-		if ( url == "" ) return;
-
-		LLHTTPClient::post(
-			url,
-			LLSD(),
-			new LLVivoxVoiceAccountProvisionResponder(retries));
-	}
-}
-
-void LLVivoxVoiceClient::login(
-	const std::string& account_name,
-	const std::string& password,
-	const std::string& voice_sip_uri_hostname,
-	const std::string& voice_account_server_uri)
-{
-	mVoiceSIPURIHostName = voice_sip_uri_hostname;
-	mVoiceAccountServerURI = voice_account_server_uri;
-
-	if(!mAccountHandle.empty())
-	{
-		// Already logged in.
-		LL_WARNS("Voice") << "Called while already logged in." << LL_ENDL;
-		
-		// Don't process another login.
-		return;
-	}
-	else if ( account_name != mAccountName )
-	{
-		//TODO: error?
-		LL_WARNS("Voice") << "Wrong account name! " << account_name
-				<< " instead of " << mAccountName << LL_ENDL;
-	}
-	else
-	{
-		mAccountPassword = password;
-	}
-
-	std::string debugSIPURIHostName = gSavedSettings.getString("VivoxDebugSIPURIHostName");
-	
-	if( !debugSIPURIHostName.empty() )
-	{
-		mVoiceSIPURIHostName = debugSIPURIHostName;
-	}
-	
-	if( mVoiceSIPURIHostName.empty() )
-	{
-		// we have an empty account server name
-		// so we fall back to hardcoded defaults
-
-		if(LLGridManager::getInstance()->isInProductionGrid())
-		{
-			// Use the release account server
-			mVoiceSIPURIHostName = "bhr.vivox.com";
-		}
-		else
-		{
-			// Use the development account server
-			mVoiceSIPURIHostName = "bhd.vivox.com";
-		}
-	}
-	
-	std::string debugAccountServerURI = gSavedSettings.getString("VivoxDebugVoiceAccountServerURI");
-
-	if( !debugAccountServerURI.empty() )
-	{
-		mVoiceAccountServerURI = debugAccountServerURI;
-	}
-	
-	if( mVoiceAccountServerURI.empty() )
-	{
-		// If the account server URI isn't specified, construct it from the SIP URI hostname
-		mVoiceAccountServerURI = "https://www." + mVoiceSIPURIHostName + "/api2/";		
-	}
-}
-
-void LLVivoxVoiceClient::idle(void* user_data)
-{
-	LLVivoxVoiceClient* self = (LLVivoxVoiceClient*)user_data;
-	self->stateMachine();
-}
-
-std::string LLVivoxVoiceClient::state2string(LLVivoxVoiceClient::state inState)
-{
-	std::string result = "UNKNOWN";
-	
-		// Prevent copy-paste errors when updating this list...
-#define CASE(x)  case x:  result = #x;  break
-
-	switch(inState)
-	{
-		CASE(stateDisableCleanup);
-		CASE(stateDisabled);
-		CASE(stateStart);
-		CASE(stateDaemonLaunched);
-		CASE(stateConnecting);
-		CASE(stateConnected);
-		CASE(stateIdle);
-		CASE(stateMicTuningStart);
-		CASE(stateMicTuningRunning);
-		CASE(stateMicTuningStop);
-		CASE(stateConnectorStart);
-		CASE(stateConnectorStarting);
-		CASE(stateConnectorStarted);
-		CASE(stateLoginRetry);
-		CASE(stateLoginRetryWait);
-		CASE(stateNeedsLogin);
-		CASE(stateLoggingIn);
-		CASE(stateLoggedIn);
-		CASE(stateCreatingSessionGroup);
-		CASE(stateNoChannel);
-		CASE(stateJoiningSession);
-		CASE(stateSessionJoined);
-		CASE(stateRunning);
-		CASE(stateLeavingSession);
-		CASE(stateSessionTerminated);
-		CASE(stateLoggingOut);
-		CASE(stateLoggedOut);
-		CASE(stateConnectorStopping);
-		CASE(stateConnectorStopped);
-		CASE(stateConnectorFailed);
-		CASE(stateConnectorFailedWaiting);
-		CASE(stateLoginFailed);
-		CASE(stateLoginFailedWaiting);
-		CASE(stateJoinSessionFailed);
-		CASE(stateJoinSessionFailedWaiting);
-		CASE(stateJail);
-	}
-
-#undef CASE
-	
-	return result;
-}
-
-
-
-void LLVivoxVoiceClient::setState(state inState)
-{
-	LL_DEBUGS("Voice") << "entering state " << state2string(inState) << LL_ENDL;
-	
-	mState = inState;
-}
-
-void LLVivoxVoiceClient::stateMachine()
-{
-	if(gDisconnected)
-	{
-		// The viewer has been disconnected from the sim.  Disable voice.
-		setVoiceEnabled(false);
-	}
-	
-	if(mVoiceEnabled)
-	{
-		updatePosition();
-	}
-	else if(mTuningMode)
-	{
-		// Tuning mode is special -- it needs to launch SLVoice even if voice is disabled.
-	}
-	else
-	{
-		if((getState() != stateDisabled) && (getState() != stateDisableCleanup))
-		{
-			// User turned off voice support.  Send the cleanup messages, close the socket, and reset.
-			if(!mConnected)
-			{
-				// if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill.
-				LL_INFOS("Voice") << "Disabling voice before connection to daemon, terminating." << LL_ENDL;
-				killGateway();
-			}
-			
-			logout();
-			connectorShutdown();
-			
-			setState(stateDisableCleanup);
-		}
-	}
-	
-	// Check for parcel boundary crossing
-	{
-		LLViewerRegion *region = gAgent.getRegion();
-		LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-		
-		if(region && parcel)
-		{
-			S32 parcelLocalID = parcel->getLocalID();
-			std::string regionName = region->getName();
-			std::string capURI = region->getCapability("ParcelVoiceInfoRequest");
-		
-//			LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL;
-
-			// The region name starts out empty and gets filled in later.  
-			// Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
-			// If either is empty, wait for the next time around.
-			if(!regionName.empty())
-			{
-				if(!capURI.empty())
-				{
-					if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName))
-					{
-						// We have changed parcels.  Initiate a parcel channel lookup.
-						mCurrentParcelLocalID = parcelLocalID;
-						mCurrentRegionName = regionName;
-						
-						parcelChanged();
-					}
-				}
-				else
-				{
-					LL_WARNS_ONCE("Voice") << "region doesn't have ParcelVoiceInfoRequest capability.  This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
-				}
-			}
-		}
-	}
-
-	switch(getState())
-	{
-		//MARK: stateDisableCleanup
-		case stateDisableCleanup:
-			// Clean up and reset everything. 
-			closeSocket();
-			deleteAllSessions();
-			deleteAllBuddies();		
-			
-			mConnectorHandle.clear();
-			mAccountHandle.clear();
-			mAccountPassword.clear();
-			mVoiceAccountServerURI.clear();
-			
-			setState(stateDisabled);	
-		break;
-		
-		//MARK: stateDisabled
-		case stateDisabled:
-			if(mTuningMode || (mVoiceEnabled && !mAccountName.empty()))
-			{
-				setState(stateStart);
-			}
-		break;
-		
-		//MARK: stateStart
-		case stateStart:
-			if(gSavedSettings.getBOOL("CmdLineDisableVoice"))
-			{
-				// Voice is locked out, we must not launch the vivox daemon.
-				setState(stateJail);
-			}
-			else if(!isGatewayRunning())
-			{
-				if(true)
-				{
-					// Launch the voice daemon
-					
-					// *FIX:Mani - Using the executable dir instead 
-					// of mAppRODataDir, the working directory from which the app
-					// is launched.
-					//std::string exe_path = gDirUtilp->getAppRODataDir();
-					std::string exe_path = gDirUtilp->getExecutableDir();
-					exe_path += gDirUtilp->getDirDelimiter();
-#if LL_WINDOWS
-					exe_path += "SLVoice.exe";
-#elif LL_DARWIN
-					exe_path += "../Resources/SLVoice";
-#else
-					exe_path += "SLVoice";
-#endif
-					// See if the vivox executable exists
-					llstat s;
-					if(!LLFile::stat(exe_path, &s))
-					{
-						// vivox executable exists.  Build the command line and launch the daemon.
-						// SLIM SDK: these arguments are no longer necessary.
-//						std::string args = " -p tcp -h -c";
-						std::string args;
-						std::string cmd;
-						std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
-						
-						if(loglevel.empty())
-						{
-							loglevel = "-1";	// turn logging off completely
-						}
-						
-						args += " -ll ";
-						args += loglevel;
-						
-						LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL;
-
-#if LL_WINDOWS
-						PROCESS_INFORMATION pinfo;
-						STARTUPINFOA sinfo;
-						
-						memset(&sinfo, 0, sizeof(sinfo));
-						
-						std::string exe_dir = gDirUtilp->getAppRODataDir();
-						cmd = "SLVoice.exe";
-						cmd += args;
-
-						// So retarded.  Windows requires that the second parameter to CreateProcessA be writable (non-const) string...
-						char *args2 = new char[args.size() + 1];
-						strcpy(args2, args.c_str());
-						if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo))
-						{
-//							DWORD dwErr = GetLastError();
-						}
-						else
-						{
-							// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
-							// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
-							sGatewayHandle = pinfo.hProcess;
-							CloseHandle(pinfo.hThread); // stops leaks - nothing else
-						}		
-						
-						delete[] args2;
-#else	// LL_WINDOWS
-						// This should be the same for mac and linux
-						{
-							std::vector<std::string> arglist;
-							arglist.push_back(exe_path);
-							
-							// Split the argument string into separate strings for each argument
-							typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-							boost::char_separator<char> sep(" ");
-							tokenizer tokens(args, sep);
-							tokenizer::iterator token_iter;
-
-							for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
-							{
-								arglist.push_back(*token_iter);
-							}
-							
-							// create an argv vector for the child process
-							char **fakeargv = new char*[arglist.size() + 1];
-							int i;
-							for(i=0; i < arglist.size(); i++)
-								fakeargv[i] = const_cast<char*>(arglist[i].c_str());
-
-							fakeargv[i] = NULL;
-							
-							fflush(NULL); // flush all buffers before the child inherits them
-							pid_t id = vfork();
-							if(id == 0)
-							{
-								// child
-								execv(exe_path.c_str(), fakeargv);
-								
-								// If we reach this point, the exec failed.
-								// Use _exit() instead of exit() per the vfork man page.
-								_exit(0);
-							}
-
-							// parent
-							delete[] fakeargv;
-							sGatewayPID = id;
-						}
-#endif	// LL_WINDOWS
-						mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost").c_str(), gSavedSettings.getU32("VivoxVoicePort"));
-					}	
-					else
-					{
-						LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL;
-					}	
-				}
-				else
-				{		
-					// SLIM SDK: port changed from 44124 to 44125.
-					// We can connect to a client gateway running on another host.  This is useful for testing.
-					// To do this, launch the gateway on a nearby host like this:
-					//  vivox-gw.exe -p tcp -i 0.0.0.0:44125
-					// and put that host's IP address here.
-					mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost"), gSavedSettings.getU32("VivoxVoicePort"));
-				}
-
-				mUpdateTimer.start();
-				mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
-
-				setState(stateDaemonLaunched);
-				
-				// Dirty the states we'll need to sync with the daemon when it comes up.
-				mPTTDirty = true;
-				mMicVolumeDirty = true;
-				mSpeakerVolumeDirty = true;
-				mSpeakerMuteDirty = true;
-				// These only need to be set if they're not default (i.e. empty string).
-				mCaptureDeviceDirty = !mCaptureDevice.empty();
-				mRenderDeviceDirty = !mRenderDevice.empty();
-				
-				mMainSessionGroupHandle.clear();
-			}
-		break;
-
-		//MARK: stateDaemonLaunched
-		case stateDaemonLaunched:
-			if(mUpdateTimer.hasExpired())
-			{
-				LL_DEBUGS("Voice") << "Connecting to vivox daemon:" << mDaemonHost << LL_ENDL;
-
-				mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
-
-				if(!mSocket)
-				{
-					mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);	
-				}
-				
-				mConnected = mSocket->blockingConnect(mDaemonHost);
-				if(mConnected)
-				{
-					setState(stateConnecting);
-				}
-				else
-				{
-					// If the connect failed, the socket may have been put into a bad state.  Delete it.
-					closeSocket();
-				}
-			}
-		break;
-
-		//MARK: stateConnecting
-		case stateConnecting:
-		// Can't do this until we have the pump available.
-		if(mPump)
-		{
-			// MBW -- Note to self: pumps and pipes examples in
-			//  indra/test/io.cpp
-			//  indra/test/llpipeutil.{cpp|h}
-
-			// Attach the pumps and pipes
-				
-			LLPumpIO::chain_t readChain;
-
-			readChain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(mSocket)));
-			readChain.push_back(LLIOPipe::ptr_t(new LLVivoxProtocolParser()));
-
-			mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
-
-			setState(stateConnected);
-		}
-
-		break;
-		
-		//MARK: stateConnected
-		case stateConnected:
-			// Initial devices query
-			getCaptureDevicesSendMessage();
-			getRenderDevicesSendMessage();
-
-			mLoginRetryCount = 0;
-
-			setState(stateIdle);
-		break;
-
-		//MARK: stateIdle
-		case stateIdle:
-			// This is the idle state where we're connected to the daemon but haven't set up a connector yet.
-			if(mTuningMode)
-			{
-				mTuningExitState = stateIdle;
-				setState(stateMicTuningStart);
-			}
-			else if(!mVoiceEnabled)
-			{
-				// We never started up the connector.  This will shut down the daemon.
-				setState(stateConnectorStopped);
-			}
-			else if(!mAccountName.empty())
-			{
-				LLViewerRegion *region = gAgent.getRegion();
-				
-				if(region)
-				{
-					if ( region->getCapability("ProvisionVoiceAccountRequest") != "" )
-					{
-						if ( mAccountPassword.empty() )
-						{
-							requestVoiceAccountProvision();
-						}
-						setState(stateConnectorStart);
-					}
-					else
-					{
-						LL_WARNS_ONCE("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL;
-					}
-				}
-			}
-		break;
-
-		//MARK: stateMicTuningStart
-		case stateMicTuningStart:
-			if(mUpdateTimer.hasExpired())
-			{
-				if(mCaptureDeviceDirty || mRenderDeviceDirty)
-				{
-					// These can't be changed while in tuning mode.  Set them before starting.
-					std::ostringstream stream;
-					
-					buildSetCaptureDevice(stream);
-					buildSetRenderDevice(stream);
-
-					if(!stream.str().empty())
-					{
-						writeString(stream.str());
-					}				
-
-					// This will come around again in the same state and start the capture, after the timer expires.
-					mUpdateTimer.start();
-					mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
-				}
-				else
-				{
-					// duration parameter is currently unused, per Mike S.
-					tuningCaptureStartSendMessage(10000);
-
-					setState(stateMicTuningRunning);
-				}
-			}
-			
-		break;
-		
-		//MARK: stateMicTuningRunning
-		case stateMicTuningRunning:
-			if(!mTuningMode || mCaptureDeviceDirty || mRenderDeviceDirty)
-			{
-				// All of these conditions make us leave tuning mode.
-				setState(stateMicTuningStop);
-			}
-			else
-			{
-				// process mic/speaker volume changes
-				if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty)
-				{
-					std::ostringstream stream;
-					
-					if(mTuningMicVolumeDirty)
-					{
-						LL_INFOS("Voice") << "setting tuning mic level to " << mTuningMicVolume << LL_ENDL;
-						stream
-						<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetMicLevel.1\">"
-						<< "<Level>" << mTuningMicVolume << "</Level>"
-						<< "</Request>\n\n\n";
-					}
-					
-					if(mTuningSpeakerVolumeDirty)
-					{
-						stream
-						<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetSpeakerLevel.1\">"
-						<< "<Level>" << mTuningSpeakerVolume << "</Level>"
-						<< "</Request>\n\n\n";
-					}
-					
-					mTuningMicVolumeDirty = false;
-					mTuningSpeakerVolumeDirty = false;
-
-					if(!stream.str().empty())
-					{
-						writeString(stream.str());
-					}
-				}
-			}
-		break;
-		
-		//MARK: stateMicTuningStop
-		case stateMicTuningStop:
-		{
-			// transition out of mic tuning
-			tuningCaptureStopSendMessage();
-			
-			setState(mTuningExitState);
-			
-			// if we exited just to change devices, this will keep us from re-entering too fast.
-			mUpdateTimer.start();
-			mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
-			
-		}
-		break;
-												
-		//MARK: stateConnectorStart
-		case stateConnectorStart:
-			if(!mVoiceEnabled)
-			{
-				// We were never logged in.  This will shut down the connector.
-				setState(stateLoggedOut);
-			}
-			else if(!mVoiceAccountServerURI.empty())
-			{
-				connectorCreate();
-			}
-		break;
-		
-		//MARK: stateConnectorStarting
-		case stateConnectorStarting:	// waiting for connector handle
-			// connectorCreateResponse() will transition from here to stateConnectorStarted.
-		break;
-		
-		//MARK: stateConnectorStarted
-		case stateConnectorStarted:		// connector handle received
-			if(!mVoiceEnabled)
-			{
-				// We were never logged in.  This will shut down the connector.
-				setState(stateLoggedOut);
-			}
-			else
-			{
-				// The connector is started.  Send a login message.
-				setState(stateNeedsLogin);
-			}
-		break;
-				
-		//MARK: stateLoginRetry
-		case stateLoginRetry:
-			if(mLoginRetryCount == 0)
-			{
-				// First retry -- display a message to the user
-				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGIN_RETRY);
-			}
-			
-			mLoginRetryCount++;
-			
-			if(mLoginRetryCount > MAX_LOGIN_RETRIES)
-			{
-				LL_WARNS("Voice") << "too many login retries, giving up." << LL_ENDL;
-				setState(stateLoginFailed);
-				LLSD args;
-				std::stringstream errs;
-				errs << mVoiceAccountServerURI << "\n:UDP: 3478, 3479, 5060, 5062, 12000-17000";
-				args["HOSTID"] = errs.str();
-				if (LLGridManager::getInstance()->isSystemGrid())
-				{
-					LLNotificationsUtil::add("NoVoiceConnect", args);	
-				}
-				else
-				{
-					LLNotificationsUtil::add("NoVoiceConnect-GIAB", args);	
-				}				
-			}
-			else
-			{
-				LL_INFOS("Voice") << "will retry login in " << LOGIN_RETRY_SECONDS << " seconds." << LL_ENDL;
-				mUpdateTimer.start();
-				mUpdateTimer.setTimerExpirySec(LOGIN_RETRY_SECONDS);
-				setState(stateLoginRetryWait);
-			}
-		break;
-		
-		//MARK: stateLoginRetryWait
-		case stateLoginRetryWait:
-			if(mUpdateTimer.hasExpired())
-			{
-				setState(stateNeedsLogin);
-			}
-		break;
-		
-		//MARK: stateNeedsLogin
-		case stateNeedsLogin:
-			if(!mAccountPassword.empty())
-			{
-				setState(stateLoggingIn);
-				loginSendMessage();
-			}		
-		break;
-		
-		//MARK: stateLoggingIn
-		case stateLoggingIn:			// waiting for account handle
-			// loginResponse() will transition from here to stateLoggedIn.
-		break;
-		
-		//MARK: stateLoggedIn
-		case stateLoggedIn:				// account handle received
-
-			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
-
-			// request the current set of block rules (we'll need them when updating the friends list)
-			accountListBlockRulesSendMessage();
-			
-			// request the current set of auto-accept rules
-			accountListAutoAcceptRulesSendMessage();
-			
-			// Set up the mute list observer if it hasn't been set up already.
-			if((!sMuteListListener_listening))
-			{
-				LLMuteList::getInstance()->addObserver(&mutelist_listener);
-				sMuteListListener_listening = true;
-			}
-
-			// Set up the friends list observer if it hasn't been set up already.
-			if(friendslist_listener == NULL)
-			{
-				friendslist_listener = new LLVivoxVoiceClientFriendsObserver;
-				LLAvatarTracker::instance().addObserver(friendslist_listener);
-			}
-			
-			// Set the initial state of mic mute, local speaker volume, etc.
-			{
-				std::ostringstream stream;
-				
-				buildLocalAudioUpdates(stream);
-				
-				if(!stream.str().empty())
-				{
-					writeString(stream.str());
-				}
-			}
-			
-#if USE_SESSION_GROUPS			
-			// create the main session group
-			sessionGroupCreateSendMessage();
-			
-			setState(stateCreatingSessionGroup);
-#else
-			// Not using session groups -- skip the stateCreatingSessionGroup state.
-			setState(stateNoChannel);
-
-			// Initial kick-off of channel lookup logic
-			parcelChanged();		
-#endif
-		break;
-		
-		//MARK: stateCreatingSessionGroup
-		case stateCreatingSessionGroup:
-			if(mSessionTerminateRequested || !mVoiceEnabled)
-			{
-				// *TODO: Question: is this the right way out of this state
-				setState(stateSessionTerminated);
-			}
-			else if(!mMainSessionGroupHandle.empty())
-			{
-				setState(stateNoChannel);
-				
-				// Start looped recording (needed for "panic button" anti-griefing tool)
-				recordingLoopStart();
-
-				// Initial kick-off of channel lookup logic
-				parcelChanged();		
-			}
-		break;
-					
-		//MARK: stateNoChannel
-		case stateNoChannel:
-			
-			LL_DEBUGS("Voice") << "State No Channel" << LL_ENDL;
-			mSpatialJoiningNum = 0;
-			// Do this here as well as inside sendPositionalUpdate().  
-			// Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
-			sendFriendsListUpdates();
-			
-			if(mSessionTerminateRequested || !mVoiceEnabled)
-			{
-				// TODO: Question: Is this the right way out of this state?
-				setState(stateSessionTerminated);
-			}
-			else if(mTuningMode)
-			{
-				mTuningExitState = stateNoChannel;
-				setState(stateMicTuningStart);
-			}
-			else if(sessionNeedsRelog(mNextAudioSession))
-			{
-				requestRelog();
-				setState(stateSessionTerminated);
-			}
-			else if(mNextAudioSession)
-			{				
-				sessionState *oldSession = mAudioSession;
-
-				mAudioSession = mNextAudioSession;
-				if(!mAudioSession->mReconnect)	
-				{
-					mNextAudioSession = NULL;
-				}
-				
-				// The old session may now need to be deleted.
-				reapSession(oldSession);
-				
-				if(!mAudioSession->mHandle.empty())
-				{
-					// Connect to a session by session handle
-
-					sessionMediaConnectSendMessage(mAudioSession);
-				}
-				else
-				{
-					// Connect to a session by URI
-					sessionCreateSendMessage(mAudioSession, true, false);
-				}
-
-				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
-				setState(stateJoiningSession);
-			}
-			else if(!mSpatialSessionURI.empty())
-			{
-				// If we're not headed elsewhere and have a spatial URI, return to spatial.
-				switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
-			}
-		break;
-
-		//MARK: stateJoiningSession
-		case stateJoiningSession:		// waiting for session handle
-		  
-		  // If this is true we have problem with connection to voice server (EXT-4313).
-		  // See descriptions of mSpatialJoiningNum and MAX_NORMAL_JOINING_SPATIAL_NUM.
-		  if(mSpatialJoiningNum == MAX_NORMAL_JOINING_SPATIAL_NUM) 
-		    {
-		      // Notify observers to let them know there is problem with voice
-		      notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
-		      llwarns << "There seems to be problem with connection to voice server. Disabling voice chat abilities." << llendl;
-		    }
-		  
-		  // Increase mSpatialJoiningNum only for spatial sessions- it's normal to reach this case for
-		  // example for p2p many times while waiting for response, so it can't be used to detect errors
-		  if(mAudioSession && mAudioSession->mIsSpatial)
-		    {
-		      mSpatialJoiningNum++;
-		    }
-      
-			// joinedAudioSession() will transition from here to stateSessionJoined.
-			if(!mVoiceEnabled)
-			{
-				// User bailed out during connect -- jump straight to teardown.
-				setState(stateSessionTerminated);
-			}
-			else if(mSessionTerminateRequested)
-			{
-				if(mAudioSession && !mAudioSession->mHandle.empty())
-				{
-					// Only allow direct exits from this state in p2p calls (for cancelling an invite).
-					// Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
-					if(mAudioSession->mIsP2P)
-					{
-						sessionMediaDisconnectSendMessage(mAudioSession);
-						setState(stateSessionTerminated);
-					}
-				}
-			}
-		break;
-		
-		//MARK: stateSessionJoined
-		case stateSessionJoined:		// session handle received
-
-		  mSpatialJoiningNum = 0;
-			// It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
-			// before continuing from this state.  They can happen in either order, and if I don't wait for both, things can get stuck.
-			// For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
-			// This is a cheap way to make sure both have happened before proceeding.
-			if(mAudioSession && mAudioSession->mVoiceEnabled)
-			{
-				// Dirty state that may need to be sync'ed with the daemon.
-				mPTTDirty = true;
-				mSpeakerVolumeDirty = true;
-				mSpatialCoordsDirty = true;
-				
-				setState(stateRunning);
-				
-				// Start the throttle timer
-				mUpdateTimer.start();
-				mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
-
-				// Events that need to happen when a session is joined could go here.
-				// Maybe send initial spatial data?
-				notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
-
-			}
-			else if(!mVoiceEnabled)
-			{
-				// User bailed out during connect -- jump straight to teardown.
-				setState(stateSessionTerminated);
-			}
-			else if(mSessionTerminateRequested)
-			{
-				// Only allow direct exits from this state in p2p calls (for cancelling an invite).
-				// Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
-				if(mAudioSession && mAudioSession->mIsP2P)
-				{
-					sessionMediaDisconnectSendMessage(mAudioSession);
-					setState(stateSessionTerminated);
-				}
-			}
-		break;
-		
-		//MARK: stateRunning
-		case stateRunning:				// steady state
-			// Disabling voice or disconnect requested.
-			if(!mVoiceEnabled || mSessionTerminateRequested)
-			{
-				leaveAudioSession();
-			}
-			else
-			{
-				
-				// Figure out whether the PTT state needs to change
-				{
-					bool newPTT;
-					if(mUsePTT)
-					{
-						// If configured to use PTT, track the user state.
-						newPTT = mUserPTTState;
-					}
-					else
-					{
-						// If not configured to use PTT, it should always be true (otherwise the user will be unable to speak).
-						newPTT = true;
-					}
-					
-					if(mMuteMic)
-					{
-						// This always overrides any other PTT setting.
-						newPTT = false;
-					}
-					
-					// Dirty if state changed.
-					if(newPTT != mPTT)
-					{
-						mPTT = newPTT;
-						mPTTDirty = true;
-					}
-				}
-				
-				if(!inSpatialChannel())
-				{
-					// When in a non-spatial channel, never send positional updates.
-					mSpatialCoordsDirty = false;
-				}
-				else
-				{
-					// Do the calculation that enforces the listener<->speaker tether (and also updates the real camera position)
-					enforceTether();
-				}
-				
-				// Send an update if the ptt state has changed (which shouldn't be able to happen that often -- the user can only click so fast)
-				// or every 10hz, whichever is sooner.
-				if((mAudioSession && mAudioSession->mVolumeDirty) || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
-				{
-					mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
-					sendPositionalUpdate();
-				}
-			}
-		break;
-		
-		//MARK: stateLeavingSession
-		case stateLeavingSession:		// waiting for terminate session response
-			// The handler for the Session.Terminate response will transition from here to stateSessionTerminated.
-		break;
-
-		//MARK: stateSessionTerminated
-		case stateSessionTerminated:
-			
-			// Must do this first, since it uses mAudioSession.
-			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
-			
-			if(mAudioSession)
-			{
-				sessionState *oldSession = mAudioSession;
-
-				mAudioSession = NULL;
-				// We just notified status observers about this change.  Don't do it again.
-				mAudioSessionChanged = false;
-
-				// The old session may now need to be deleted.
-				reapSession(oldSession);
-			}
-			else
-			{
-				LL_WARNS("Voice") << "stateSessionTerminated with NULL mAudioSession" << LL_ENDL;
-			}
-	
-			// Always reset the terminate request flag when we get here.
-			mSessionTerminateRequested = false;
-
-			if(mVoiceEnabled && !mRelogRequested)
-			{				
-				// Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state).
-				setState(stateNoChannel);
-			}
-			else
-			{
-				// Shutting down voice, continue with disconnecting.
-				logout();
-				
-				// The state machine will take it from here
-				mRelogRequested = false;
-			}
-			
-		break;
-		
-		//MARK: stateLoggingOut
-		case stateLoggingOut:			// waiting for logout response
-			// The handler for the AccountLoginStateChangeEvent will transition from here to stateLoggedOut.
-		break;
-		
-		//MARK: stateLoggedOut
-		case stateLoggedOut:			// logout response received
-			
-			// Once we're logged out, all these things are invalid.
-			mAccountHandle.clear();
-			deleteAllSessions();
-			deleteAllBuddies();
-
-			if(mVoiceEnabled && !mRelogRequested)
-			{
-				// User was logged out, but wants to be logged in.  Send a new login request.
-				setState(stateNeedsLogin);
-			}
-			else
-			{
-				// shut down the connector
-				connectorShutdown();
-			}
-		break;
-		
-		//MARK: stateConnectorStopping
-		case stateConnectorStopping:	// waiting for connector stop
-			// The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped.
-		break;
-
-		//MARK: stateConnectorStopped
-		case stateConnectorStopped:		// connector stop received
-			setState(stateDisableCleanup);
-		break;
-
-		//MARK: stateConnectorFailed
-		case stateConnectorFailed:
-			setState(stateConnectorFailedWaiting);
-		break;
-		//MARK: stateConnectorFailedWaiting
-		case stateConnectorFailedWaiting:
-			if(!mVoiceEnabled)
-			{
-				setState(stateDisableCleanup);
-			}
-		break;
-
-		//MARK: stateLoginFailed
-		case stateLoginFailed:
-			setState(stateLoginFailedWaiting);
-		break;
-		//MARK: stateLoginFailedWaiting
-		case stateLoginFailedWaiting:
-			if(!mVoiceEnabled)
-			{
-				setState(stateDisableCleanup);
-			}
-		break;
-
-		//MARK: stateJoinSessionFailed
-		case stateJoinSessionFailed:
-			// Transition to error state.  Send out any notifications here.
-			if(mAudioSession)
-			{
-				LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mAudioSession->mErrorStatusCode << "): " << mAudioSession->mErrorStatusString << LL_ENDL;
-			}
-			else
-			{
-				LL_WARNS("Voice") << "stateJoinSessionFailed with no current session" << LL_ENDL;
-			}
-			
-			notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
-			setState(stateJoinSessionFailedWaiting);
-		break;
-		
-		//MARK: stateJoinSessionFailedWaiting
-		case stateJoinSessionFailedWaiting:
-			// Joining a channel failed, either due to a failed channel name -> sip url lookup or an error from the join message.
-			// Region crossings may leave this state and try the join again.
-			if(mSessionTerminateRequested)
-			{
-				setState(stateSessionTerminated);
-			}
-		break;
-		
-		//MARK: stateJail
-		case stateJail:
-			// We have given up.  Do nothing.
-		break;
-
-	}
-	
-	if(mAudioSession && mAudioSession->mParticipantsChanged)
-	{
-		mAudioSession->mParticipantsChanged = false;
-		mAudioSessionChanged = true;
-	}
-	
-	if(mAudioSessionChanged)
-	{
-		mAudioSessionChanged = false;
-		notifyParticipantObservers();
-	}
-}
-
-void LLVivoxVoiceClient::closeSocket(void)
-{
-	mSocket.reset();
-	mConnected = false;	
-}
-
-void LLVivoxVoiceClient::loginSendMessage()
-{
-	std::ostringstream stream;
-
-	bool autoPostCrashDumps = gSavedSettings.getBOOL("VivoxAutoPostCrashDumps");
-
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Login.1\">"
-		<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
-		<< "<AccountName>" << mAccountName << "</AccountName>"
-		<< "<AccountPassword>" << mAccountPassword << "</AccountPassword>"
-		<< "<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>"
-		<< "<EnableBuddiesAndPresence>true</EnableBuddiesAndPresence>"
-		<< "<BuddyManagementMode>Application</BuddyManagementMode>"
-		<< "<ParticipantPropertyFrequency>5</ParticipantPropertyFrequency>"
-		<< (autoPostCrashDumps?"<AutopostCrashDumps>true</AutopostCrashDumps>":"")
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::logout()
-{
-	// Ensure that we'll re-request provisioning before logging in again
-	mAccountPassword.clear();
-	mVoiceAccountServerURI.clear();
-	
-	setState(stateLoggingOut);
-	logoutSendMessage();
-}
-
-void LLVivoxVoiceClient::logoutSendMessage()
-{
-	if(!mAccountHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.Logout.1\">"
-			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-		<< "</Request>"
-		<< "\n\n\n";
-
-		mAccountHandle.clear();
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::accountListBlockRulesSendMessage()
-{
-	if(!mAccountHandle.empty())
-	{		
-		std::ostringstream stream;
-
-		LL_DEBUGS("Voice") << "requesting block rules" << LL_ENDL;
-
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ListBlockRules.1\">"
-			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-		<< "</Request>"
-		<< "\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::accountListAutoAcceptRulesSendMessage()
-{
-	if(!mAccountHandle.empty())
-	{		
-		std::ostringstream stream;
-
-		LL_DEBUGS("Voice") << "requesting auto-accept rules" << LL_ENDL;
-
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ListAutoAcceptRules.1\">"
-			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-		<< "</Request>"
-		<< "\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::sessionGroupCreateSendMessage()
-{
-	if(!mAccountHandle.empty())
-	{		
-		std::ostringstream stream;
-
-		LL_DEBUGS("Voice") << "creating session group" << LL_ENDL;
-
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Create.1\">"
-			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-			<< "<Type>Normal</Type>"
-		<< "</Request>"
-		<< "\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)
-{
-	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
-	
-	session->mCreateInProgress = true;
-	if(startAudio)
-	{
-		session->mMediaConnectInProgress = true;
-	}
-
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << session->mSIPURI << "\" action=\"Session.Create.1\">"
-		<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-		<< "<URI>" << session->mSIPURI << "</URI>";
-
-	static const std::string allowed_chars =
-				"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-				"0123456789"
-				"-._~";
-
-	if(!session->mHash.empty())
-	{
-		stream
-			<< "<Password>" << LLURI::escape(session->mHash, allowed_chars) << "</Password>"
-			<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>";
-	}
-	
-	stream
-		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
-		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
-		<< "<Name>" << mChannelName << "</Name>"
-	<< "</Request>\n\n\n";
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)
-{
-	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
-	
-	session->mCreateInProgress = true;
-	if(startAudio)
-	{
-		session->mMediaConnectInProgress = true;
-	}
-	
-	std::string password;
-	if(!session->mHash.empty())
-	{
-		static const std::string allowed_chars =
-					"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-					"0123456789"
-					"-._~"
-					;
-		password = LLURI::escape(session->mHash, allowed_chars);
-	}
-
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << session->mSIPURI << "\" action=\"SessionGroup.AddSession.1\">"
-		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
-		<< "<URI>" << session->mSIPURI << "</URI>"
-		<< "<Name>" << mChannelName << "</Name>"
-		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
-		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
-		<< "<Password>" << password << "</Password>"
-		<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>"
-	<< "</Request>\n\n\n"
-	;
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
-{
-	LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL;
-
-	session->mMediaConnectInProgress = true;
-	
-	std::ostringstream stream;
-
-	stream
-	<< "<Request requestId=\"" << session->mHandle << "\" action=\"Session.MediaConnect.1\">"
-		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
-		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-		<< "<Media>Audio</Media>"
-	<< "</Request>\n\n\n";
-
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionTextConnectSendMessage(sessionState *session)
-{
-	LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL;
-	
-	std::ostringstream stream;
-
-	stream
-	<< "<Request requestId=\"" << session->mHandle << "\" action=\"Session.TextConnect.1\">"
-		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
-		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-	<< "</Request>\n\n\n";
-
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionTerminate()
-{
-	mSessionTerminateRequested = true;
-}
-
-void LLVivoxVoiceClient::requestRelog()
-{
-	mSessionTerminateRequested = true;
-	mRelogRequested = true;
-}
-
-
-void LLVivoxVoiceClient::leaveAudioSession()
-{
-	if(mAudioSession)
-	{
-		LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL;
-
-		switch(getState())
-		{
-			case stateNoChannel:
-				// In this case, we want to pretend the join failed so our state machine doesn't get stuck.
-				// Skip the join failed transition state so we don't send out error notifications.
-				setState(stateJoinSessionFailedWaiting);
-			break;
-			case stateJoiningSession:
-			case stateSessionJoined:
-			case stateRunning:
-				if(!mAudioSession->mHandle.empty())
-				{
-
-#if RECORD_EVERYTHING
-					// HACK: for testing only
-					// Save looped recording
-					std::string savepath("/tmp/vivoxrecording");
-					{
-						time_t now = time(NULL);
-						const size_t BUF_SIZE = 64;
-						char time_str[BUF_SIZE];	/* Flawfinder: ignore */
-						
-						strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
-						savepath += time_str;
-					}
-					recordingLoopSave(savepath);
-#endif
-
-					sessionMediaDisconnectSendMessage(mAudioSession);
-					setState(stateLeavingSession);
-				}
-				else
-				{
-					LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;	
-					setState(stateSessionTerminated);
-				}
-			break;
-			case stateJoinSessionFailed:
-			case stateJoinSessionFailedWaiting:
-				setState(stateSessionTerminated);
-			break;
-			
-			default:
-				LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
-			break;
-		}
-	}
-	else
-	{
-		LL_WARNS("Voice") << "called with no active session" << LL_ENDL;
-		setState(stateSessionTerminated);
-	}
-}
-
-void LLVivoxVoiceClient::sessionTerminateSendMessage(sessionState *session)
-{
-	std::ostringstream stream;
-	
-	LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL;	
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">"
-		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionGroupTerminateSendMessage(sessionState *session)
-{
-	std::ostringstream stream;
-	
-	LL_DEBUGS("Voice") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL;	
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Terminate.1\">"
-		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session)
-{
-	std::ostringstream stream;
-	
-	LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL;	
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.MediaDisconnect.1\">"
-		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
-		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-		<< "<Media>Audio</Media>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-	
-}
-
-void LLVivoxVoiceClient::sessionTextDisconnectSendMessage(sessionState *session)
-{
-	std::ostringstream stream;
-	
-	LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL;	
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextDisconnect.1\">"
-		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
-		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::getCaptureDevicesSendMessage()
-{
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.GetCaptureDevices.1\">"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::getRenderDevicesSendMessage()
-{
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.GetRenderDevices.1\">"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::clearCaptureDevices()
-{
-	LL_DEBUGS("Voice") << "called" << LL_ENDL;
-	mCaptureDevices.clear();
-}
-
-void LLVivoxVoiceClient::addCaptureDevice(const std::string& name)
-{
-	LL_DEBUGS("Voice") << name << LL_ENDL;
-
-	mCaptureDevices.push_back(name);
-}
-
-LLVoiceDeviceList& LLVivoxVoiceClient::getCaptureDevices()
-{
-	return mCaptureDevices;
-}
-
-void LLVivoxVoiceClient::setCaptureDevice(const std::string& name)
-{
-	if(name == "Default")
-	{
-		if(!mCaptureDevice.empty())
-		{
-			mCaptureDevice.clear();
-			mCaptureDeviceDirty = true;	
-		}
-	}
-	else
-	{
-		if(mCaptureDevice != name)
-		{
-			mCaptureDevice = name;
-			mCaptureDeviceDirty = true;	
-		}
-	}
-}
-
-void LLVivoxVoiceClient::clearRenderDevices()
-{	
-	LL_DEBUGS("Voice") << "called" << LL_ENDL;
-	mRenderDevices.clear();
-}
-
-void LLVivoxVoiceClient::addRenderDevice(const std::string& name)
-{
-	LL_DEBUGS("Voice") << name << LL_ENDL;
-	mRenderDevices.push_back(name);
-}
-
-LLVoiceDeviceList& LLVivoxVoiceClient::getRenderDevices()
-{
-	return mRenderDevices;
-}
-
-void LLVivoxVoiceClient::setRenderDevice(const std::string& name)
-{
-	if(name == "Default")
-	{
-		if(!mRenderDevice.empty())
-		{
-			mRenderDevice.clear();
-			mRenderDeviceDirty = true;	
-		}
-	}
-	else
-	{
-		if(mRenderDevice != name)
-		{
-			mRenderDevice = name;
-			mRenderDeviceDirty = true;	
-		}
-	}
-	
-}
-
-void LLVivoxVoiceClient::tuningStart()
-{
-	mTuningMode = true;
-	LL_DEBUGS("Voice") << "Starting tuning" << LL_ENDL;
-	if(getState() >= stateNoChannel)
-	{
-		LL_DEBUGS("Voice") << "no channel" << LL_ENDL;
-		sessionTerminate();
-	}
-}
-
-void LLVivoxVoiceClient::tuningStop()
-{
-	mTuningMode = false;
-}
-
-bool LLVivoxVoiceClient::inTuningMode()
-{
-	bool result = false;
-	switch(getState())
-	{
-	case stateMicTuningRunning:
-		result = true;
-		break;
-	default:
-		break;
-	}
-	return result;
-}
-
-void LLVivoxVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool loop)
-{		
-	mTuningAudioFile = name;
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStart.1\">"
-    << "<SoundFilePath>" << mTuningAudioFile << "</SoundFilePath>"
-    << "<Loop>" << (loop?"1":"0") << "</Loop>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::tuningRenderStopSendMessage()
-{
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">"
-    << "<SoundFilePath>" << mTuningAudioFile << "</SoundFilePath>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::tuningCaptureStartSendMessage(int duration)
-{
-	LL_DEBUGS("Voice") << "sending CaptureAudioStart" << LL_ENDL;
-	
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStart.1\">"
-    << "<Duration>" << duration << "</Duration>"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-}
-
-void LLVivoxVoiceClient::tuningCaptureStopSendMessage()
-{
-	LL_DEBUGS("Voice") << "sending CaptureAudioStop" << LL_ENDL;
-	
-	std::ostringstream stream;
-	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">"
-	<< "</Request>\n\n\n";
-	
-	writeString(stream.str());
-
-	mTuningEnergy = 0.0f;
-}
-
-void LLVivoxVoiceClient::tuningSetMicVolume(float volume)
-{
-	int scaled_volume = scale_mic_volume(volume);
-
-	if(scaled_volume != mTuningMicVolume)
-	{
-		mTuningMicVolume = scaled_volume;
-		mTuningMicVolumeDirty = true;
-	}
-}
-
-void LLVivoxVoiceClient::tuningSetSpeakerVolume(float volume)
-{
-	int scaled_volume = scale_speaker_volume(volume);	
-
-	if(scaled_volume != mTuningSpeakerVolume)
-	{
-		mTuningSpeakerVolume = scaled_volume;
-		mTuningSpeakerVolumeDirty = true;
-	}
-}
-				
-float LLVivoxVoiceClient::tuningGetEnergy(void)
-{
-	return mTuningEnergy;
-}
-
-bool LLVivoxVoiceClient::deviceSettingsAvailable()
-{
-	bool result = true;
-	
-	if(!mConnected)
-		result = false;
-	
-	if(mRenderDevices.empty())
-		result = false;
-	
-	return result;
-}
-
-void LLVivoxVoiceClient::refreshDeviceLists(bool clearCurrentList)
-{
-	if(clearCurrentList)
-	{
-		clearCaptureDevices();
-		clearRenderDevices();
-	}
-	getCaptureDevicesSendMessage();
-	getRenderDevicesSendMessage();
-}
-
-void LLVivoxVoiceClient::daemonDied()
-{
-	// The daemon died, so the connection is gone.  Reset everything and start over.
-	LL_WARNS("Voice") << "Connection to vivox daemon lost.  Resetting state."<< LL_ENDL;
-
-	// Try to relaunch the daemon
-	setState(stateDisableCleanup);
-}
-
-void LLVivoxVoiceClient::giveUp()
-{
-	// All has failed.  Clean up and stop trying.
-	closeSocket();
-	deleteAllSessions();
-	deleteAllBuddies();
-	
-	setState(stateJail);
-}
-
-static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel)
-{
-	F32 nat[3], nup[3], nl[3], nvel[3]; // the new at, up, left vectors and the  new position and velocity
-	F64 npos[3];
-	
-	// The original XML command was sent like this:
-	/*
-			<< "<Position>"
-				<< "<X>" << pos[VX] << "</X>"
-				<< "<Y>" << pos[VZ] << "</Y>"
-				<< "<Z>" << pos[VY] << "</Z>"
-			<< "</Position>"
-			<< "<Velocity>"
-				<< "<X>" << mAvatarVelocity[VX] << "</X>"
-				<< "<Y>" << mAvatarVelocity[VZ] << "</Y>"
-				<< "<Z>" << mAvatarVelocity[VY] << "</Z>"
-			<< "</Velocity>"
-			<< "<AtOrientation>"
-				<< "<X>" << l.mV[VX] << "</X>"
-				<< "<Y>" << u.mV[VX] << "</Y>"
-				<< "<Z>" << a.mV[VX] << "</Z>"
-			<< "</AtOrientation>"
-			<< "<UpOrientation>"
-				<< "<X>" << l.mV[VZ] << "</X>"
-				<< "<Y>" << u.mV[VY] << "</Y>"
-				<< "<Z>" << a.mV[VZ] << "</Z>"
-			<< "</UpOrientation>"
-			<< "<LeftOrientation>"
-				<< "<X>" << l.mV [VY] << "</X>"
-				<< "<Y>" << u.mV [VZ] << "</Y>"
-				<< "<Z>" << a.mV [VY] << "</Z>"
-			<< "</LeftOrientation>";
-	*/
-
-#if 1
-	// This was the original transform done when building the XML command
-	nat[0] = left.mV[VX];
-	nat[1] = up.mV[VX];
-	nat[2] = at.mV[VX];
-
-	nup[0] = left.mV[VZ];
-	nup[1] = up.mV[VY];
-	nup[2] = at.mV[VZ];
-
-	nl[0] = left.mV[VY];
-	nl[1] = up.mV[VZ];
-	nl[2] = at.mV[VY];
-
-	npos[0] = pos.mdV[VX];
-	npos[1] = pos.mdV[VZ];
-	npos[2] = pos.mdV[VY];
-
-	nvel[0] = vel.mV[VX];
-	nvel[1] = vel.mV[VZ];
-	nvel[2] = vel.mV[VY];
-
-	for(int i=0;i<3;++i) {
-		at.mV[i] = nat[i];
-		up.mV[i] = nup[i];
-		left.mV[i] = nl[i];
-		pos.mdV[i] = npos[i];
-	}
-	
-	// This was the original transform done in the SDK
-	nat[0] = at.mV[2];
-	nat[1] = 0; // y component of at vector is always 0, this was up[2]
-	nat[2] = -1 * left.mV[2];
-
-	// We override whatever the application gives us
-	nup[0] = 0; // x component of up vector is always 0
-	nup[1] = 1; // y component of up vector is always 1
-	nup[2] = 0; // z component of up vector is always 0
-
-	nl[0] = at.mV[0];
-	nl[1] = 0;  // y component of left vector is always zero, this was up[0]
-	nl[2] = -1 * left.mV[0];
-
-	npos[2] = pos.mdV[2] * -1.0;
-	npos[1] = pos.mdV[1];
-	npos[0] = pos.mdV[0];
-
-	for(int i=0;i<3;++i) {
-		at.mV[i] = nat[i];
-		up.mV[i] = nup[i];
-		left.mV[i] = nl[i];
-		pos.mdV[i] = npos[i];
-	}
-#else
-	// This is the compose of the two transforms (at least, that's what I'm trying for)
-	nat[0] = at.mV[VX];
-	nat[1] = 0; // y component of at vector is always 0, this was up[2]
-	nat[2] = -1 * up.mV[VZ];
-
-	// We override whatever the application gives us
-	nup[0] = 0; // x component of up vector is always 0
-	nup[1] = 1; // y component of up vector is always 1
-	nup[2] = 0; // z component of up vector is always 0
-
-	nl[0] = left.mV[VX];
-	nl[1] = 0;  // y component of left vector is always zero, this was up[0]
-	nl[2] = -1 * left.mV[VY];
-
-	npos[0] = pos.mdV[VX];
-	npos[1] = pos.mdV[VZ];
-	npos[2] = pos.mdV[VY] * -1.0;
-
-	nvel[0] = vel.mV[VX];
-	nvel[1] = vel.mV[VZ];
-	nvel[2] = vel.mV[VY];
-
-	for(int i=0;i<3;++i) {
-		at.mV[i] = nat[i];
-		up.mV[i] = nup[i];
-		left.mV[i] = nl[i];
-		pos.mdV[i] = npos[i];
-	}
-	
-#endif
-}
-
-void LLVivoxVoiceClient::sendPositionalUpdate(void)
-{	
-	std::ostringstream stream;
-	
-	if(mSpatialCoordsDirty)
-	{
-		LLVector3 l, u, a, vel;
-		LLVector3d pos;
-
-		mSpatialCoordsDirty = false;
-		
-		// Always send both speaker and listener positions together.
-		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Set3DPosition.1\">"		
-			<< "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>";
-		
-		stream << "<SpeakerPosition>";
-
-//		LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
-		l = mAvatarRot.getLeftRow();
-		u = mAvatarRot.getUpRow();
-		a = mAvatarRot.getFwdRow();
-		pos = mAvatarPosition;
-		vel = mAvatarVelocity;
-
-		// SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore.
-		// The old transform is replicated by this function.
-		oldSDKTransform(l, u, a, pos, vel);
-		
-		stream 
-			<< "<Position>"
-				<< "<X>" << pos.mdV[VX] << "</X>"
-				<< "<Y>" << pos.mdV[VY] << "</Y>"
-				<< "<Z>" << pos.mdV[VZ] << "</Z>"
-			<< "</Position>"
-			<< "<Velocity>"
-				<< "<X>" << vel.mV[VX] << "</X>"
-				<< "<Y>" << vel.mV[VY] << "</Y>"
-				<< "<Z>" << vel.mV[VZ] << "</Z>"
-			<< "</Velocity>"
-			<< "<AtOrientation>"
-				<< "<X>" << a.mV[VX] << "</X>"
-				<< "<Y>" << a.mV[VY] << "</Y>"
-				<< "<Z>" << a.mV[VZ] << "</Z>"
-			<< "</AtOrientation>"
-			<< "<UpOrientation>"
-				<< "<X>" << u.mV[VX] << "</X>"
-				<< "<Y>" << u.mV[VY] << "</Y>"
-				<< "<Z>" << u.mV[VZ] << "</Z>"
-			<< "</UpOrientation>"
-			<< "<LeftOrientation>"
-				<< "<X>" << l.mV [VX] << "</X>"
-				<< "<Y>" << l.mV [VY] << "</Y>"
-				<< "<Z>" << l.mV [VZ] << "</Z>"
-			<< "</LeftOrientation>";
-
-		stream << "</SpeakerPosition>";
-
-		stream << "<ListenerPosition>";
-
-		LLVector3d	earPosition;
-		LLVector3	earVelocity;
-		LLMatrix3	earRot;
-		
-		switch(mEarLocation)
-		{
-			case earLocCamera:
-			default:
-				earPosition = mCameraPosition;
-				earVelocity = mCameraVelocity;
-				earRot = mCameraRot;
-			break;
-			
-			case earLocAvatar:
-				earPosition = mAvatarPosition;
-				earVelocity = mAvatarVelocity;
-				earRot = mAvatarRot;
-			break;
-			
-			case earLocMixed:
-				earPosition = mAvatarPosition;
-				earVelocity = mAvatarVelocity;
-				earRot = mCameraRot;
-			break;
-		}
-
-		l = earRot.getLeftRow();
-		u = earRot.getUpRow();
-		a = earRot.getFwdRow();
-		pos = earPosition;
-		vel = earVelocity;
-
-//		LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
-		
-		oldSDKTransform(l, u, a, pos, vel);
-		
-		stream 
-			<< "<Position>"
-				<< "<X>" << pos.mdV[VX] << "</X>"
-				<< "<Y>" << pos.mdV[VY] << "</Y>"
-				<< "<Z>" << pos.mdV[VZ] << "</Z>"
-			<< "</Position>"
-			<< "<Velocity>"
-				<< "<X>" << vel.mV[VX] << "</X>"
-				<< "<Y>" << vel.mV[VY] << "</Y>"
-				<< "<Z>" << vel.mV[VZ] << "</Z>"
-			<< "</Velocity>"
-			<< "<AtOrientation>"
-				<< "<X>" << a.mV[VX] << "</X>"
-				<< "<Y>" << a.mV[VY] << "</Y>"
-				<< "<Z>" << a.mV[VZ] << "</Z>"
-			<< "</AtOrientation>"
-			<< "<UpOrientation>"
-				<< "<X>" << u.mV[VX] << "</X>"
-				<< "<Y>" << u.mV[VY] << "</Y>"
-				<< "<Z>" << u.mV[VZ] << "</Z>"
-			<< "</UpOrientation>"
-			<< "<LeftOrientation>"
-				<< "<X>" << l.mV [VX] << "</X>"
-				<< "<Y>" << l.mV [VY] << "</Y>"
-				<< "<Z>" << l.mV [VZ] << "</Z>"
-			<< "</LeftOrientation>";
-
-
-		stream << "</ListenerPosition>";
-
-		stream << "</Request>\n\n\n";
-	}	
-	
-	if(mAudioSession && mAudioSession->mVolumeDirty)
-	{
-		participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
-
-		mAudioSession->mVolumeDirty = false;
-		
-		for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
-		{
-			participantState *p = iter->second;
-			
-			if(p->mVolumeDirty)
-			{
-				// Can't set volume/mute for yourself
-				if(!p->mIsSelf)
-				{
-					int volume = 56; // nominal default value
-					bool mute = p->mOnMuteList;
-					
-					if(p->mUserVolume != -1)
-					{
-						// scale from user volume in the range 0-400 (with 100 as "normal") to vivox volume in the range 0-100 (with 56 as "normal")
-						if(p->mUserVolume < 100)
-							volume = (p->mUserVolume * 56) / 100;
-						else
-							volume = (((p->mUserVolume - 100) * (100 - 56)) / 300) + 56;
-					}
-					else if(p->mVolume != -1)
-					{
-						// Use the previously reported internal volume (comes in with a ParticipantUpdatedEvent)
-						volume = p->mVolume;
-					}
-										
-
-					if(mute)
-					{
-						// SetParticipantMuteForMe doesn't work in p2p sessions.
-						// If we want the user to be muted, set their volume to 0 as well.
-						// This isn't perfect, but it will at least reduce their volume to a minimum.
-						volume = 0;
-					}
-					
-					if(volume == 0)
-						mute = true;
-
-					LL_DEBUGS("Voice") << "Setting volume/mute for avatar " << p->mAvatarID << " to " << volume << (mute?"/true":"/false") << LL_ENDL;
-					
-					// SLIM SDK: Send both volume and mute commands.
-					
-					// Send a "volume for me" command for the user.
-					stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantVolumeForMe.1\">"
-						<< "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
-						<< "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
-						<< "<Volume>" << volume << "</Volume>"
-						<< "</Request>\n\n\n";
-
-					if(!mAudioSession->mIsP2P)
-					  {
-					    // Send a "mute for me" command for the user
-					    // Doesn't work in P2P sessions
-					    stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantMuteForMe.1\">"
-					      << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
-					      << "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
-					      << "<Mute>" << (mute?"1":"0") << "</Mute>"
-					      << "<Scope>Audio</Scope>"
-					      << "</Request>\n\n\n";
-					    }
-				}
-				
-				p->mVolumeDirty = false;
-			}
-		}
-	}
-			
-	buildLocalAudioUpdates(stream);
-	
-	if(!stream.str().empty())
-	{
-		writeString(stream.str());
-	}
-	
-	// Friends list updates can be huge, especially on the first voice login of an account with lots of friends.
-	// Batching them all together can choke SLVoice, so send them in separate writes.
-	sendFriendsListUpdates();
-}
-
-void LLVivoxVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
-{
-	if(mCaptureDeviceDirty)
-	{
-		LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
-	
-		stream 
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">"
-			<< "<CaptureDeviceSpecifier>" << mCaptureDevice << "</CaptureDeviceSpecifier>"
-		<< "</Request>"
-		<< "\n\n\n";
-		
-		mCaptureDeviceDirty = false;
-	}
-}
-
-void LLVivoxVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
-{
-	if(mRenderDeviceDirty)
-	{
-		LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
-
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetRenderDevice.1\">"
-			<< "<RenderDeviceSpecifier>" << mRenderDevice << "</RenderDeviceSpecifier>"
-		<< "</Request>"
-		<< "\n\n\n";
-		mRenderDeviceDirty = false;
-	}
-}
-
-void LLVivoxVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
-{
-	buildSetCaptureDevice(stream);
-
-	buildSetRenderDevice(stream);
-
-	if(mPTTDirty)
-	{
-		mPTTDirty = false;
-
-		// Send a local mute command.
-		// NOTE that the state of "PTT" is the inverse of "local mute".
-		//   (i.e. when PTT is true, we send a mute command with "false", and vice versa)
-		
-		LL_DEBUGS("Voice") << "Sending MuteLocalMic command with parameter " << (mPTT?"false":"true") << LL_ENDL;
-
-		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
-			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
-			<< "<Value>" << (mPTT?"false":"true") << "</Value>"
-			<< "</Request>\n\n\n";
-		
-	}
-
-	if(mSpeakerMuteDirty)
-	{
-	  const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0))?"true":"false");
-
-		mSpeakerMuteDirty = false;
-
-		LL_INFOS("Voice") << "Setting speaker mute to " << muteval  << LL_ENDL;
-		
-		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalSpeaker.1\">"
-			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
-			<< "<Value>" << muteval << "</Value>"
-			<< "</Request>\n\n\n";	
-		
-	}
-	
-	if(mSpeakerVolumeDirty)
-	{
-		mSpeakerVolumeDirty = false;
-
-		LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume  << LL_ENDL;
-
-		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalSpeakerVolume.1\">"
-			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
-			<< "<Value>" << mSpeakerVolume << "</Value>"
-			<< "</Request>\n\n\n";
-			
-	}
-	
-	if(mMicVolumeDirty)
-	{
-		mMicVolumeDirty = false;
-
-		LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume  << LL_ENDL;
-
-		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalMicVolume.1\">"
-			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
-			<< "<Value>" << mMicVolume << "</Value>"
-			<< "</Request>\n\n\n";				
-	}
-
-	
-}
-
-void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
-{
-	std::string name;
-	buddyListEntry *buddy = findBuddy(id);
-
-	// Make sure we don't add a name before it's been looked up.
-	if(gCacheName->getFullName(id, name))
-	{
-
-		const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
-		bool canSeeMeOnline = false;
-		if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
-			canSeeMeOnline = true;
-		
-		// When we get here, mNeedsSend is true and mInSLFriends is false.  Change them as necessary.
-		
-		if(buddy)
-		{
-			// This buddy is already in both lists.
-
-			if(name != buddy->mDisplayName)
-			{
-				// The buddy is in the list with the wrong name.  Update it with the correct name.
-				LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
-				buddy->mDisplayName = name;
-				buddy->mNeedsNameUpdate = true;		// This will cause the buddy to be resent.
-			}
-		}
-		else
-		{
-			// This buddy was not in the vivox list, needs to be added.
-			buddy = addBuddy(sipURIFromID(id), name);
-			buddy->mUUID = id;
-		}
-		
-		// In all the above cases, the buddy is in the SL friends list (which is how we got here).
-		buddy->mInSLFriends = true;
-		buddy->mCanSeeMeOnline = canSeeMeOnline;
-		buddy->mNameResolved = true;
-		
-	}
-	else
-	{
-		// This name hasn't been looked up yet.  Don't do anything with this buddy list entry until it has.
-		if(buddy)
-		{
-			buddy->mNameResolved = false;
-		}
-		
-		// Initiate a lookup.
-		// The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
-		lookupName(id);
-	}
-}
-
-void LLVivoxVoiceClient::clearAllLists()
-{
-	// FOR TESTING ONLY
-	
-	// This will send the necessary commands to delete ALL buddies, autoaccept rules, and block rules SLVoice tells us about.
-	buddyListMap::iterator buddy_it;
-	for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
-	{
-		buddyListEntry *buddy = buddy_it->second;
-		buddy_it++;
-		
-		std::ostringstream stream;
-
-		if(buddy->mInVivoxBuddies)
-		{
-			// delete this entry from the vivox buddy list
-			buddy->mInVivoxBuddies = false;
-			LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
-			stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddyDelete.1\">"
-				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-				<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
-				<< "</Request>\n\n\n";		
-		}
-
-		if(buddy->mHasBlockListEntry)
-		{
-			// Delete the associated block list entry (so the block list doesn't fill up with junk)
-			buddy->mHasBlockListEntry = false;
-			stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
-				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-				<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
-				<< "</Request>\n\n\n";								
-		}
-		if(buddy->mHasAutoAcceptListEntry)
-		{
-			// Delete the associated auto-accept list entry (so the auto-accept list doesn't fill up with junk)
-			buddy->mHasAutoAcceptListEntry = false;
-			stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
-				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-				<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
-				<< "</Request>\n\n\n";
-		}
-
-		writeString(stream.str());
-
-	}
-}
-
-void LLVivoxVoiceClient::sendFriendsListUpdates()
-{
-	if(mBuddyListMapPopulated && mBlockRulesListReceived && mAutoAcceptRulesListReceived && mFriendsListDirty)
-	{
-		mFriendsListDirty = false;
-		
-		if(0)
-		{
-			// FOR TESTING ONLY -- clear all buddy list, block list, and auto-accept list entries.
-			clearAllLists();
-			return;
-		}
-		
-		LL_INFOS("Voice") << "Checking vivox buddy list against friends list..." << LL_ENDL;
-		
-		buddyListMap::iterator buddy_it;
-		for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
-		{
-			// reset the temp flags in the local buddy list
-			buddy_it->second->mInSLFriends = false;
-		}
-		
-		// correlate with the friends list
-		{
-			LLCollectAllBuddies collect;
-			LLAvatarTracker::instance().applyFunctor(collect);
-			LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin();
-			LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
-			
-			for ( ; it != end; ++it)
-			{
-				checkFriend(it->second);
-			}
-			it = collect.mOffline.begin();
-			end = collect.mOffline.end();
-			for ( ; it != end; ++it)
-			{
-				checkFriend(it->second);
-			}
-		}
-				
-		LL_INFOS("Voice") << "Sending friend list updates..." << LL_ENDL;
-
-		for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
-		{
-			buddyListEntry *buddy = buddy_it->second;
-			buddy_it++;
-			
-			// Ignore entries that aren't resolved yet.
-			if(buddy->mNameResolved)
-			{
-				std::ostringstream stream;
-
-				if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
-				{					
-					if(mNumberOfAliases > 0)
-					{
-						// Add (or update) this entry in the vivox buddy list
-						buddy->mInVivoxBuddies = true;
-						buddy->mNeedsNameUpdate = false;
-						LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
-						stream 
-							<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
-								<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-								<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
-								<< "<DisplayName>" << buddy->mDisplayName << "</DisplayName>"
-								<< "<BuddyData></BuddyData>"	// Without this, SLVoice doesn't seem to parse the command.
-								<< "<GroupID>0</GroupID>"
-							<< "</Request>\n\n\n";	
-					}
-				}
-				else if(!buddy->mInSLFriends)
-				{
-					// This entry no longer exists in your SL friends list.  Remove all traces of it from the Vivox buddy list.
- 					if(buddy->mInVivoxBuddies)
-					{
-						// delete this entry from the vivox buddy list
-						buddy->mInVivoxBuddies = false;
-						LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
-						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddyDelete.1\">"
-							<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-							<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
-							<< "</Request>\n\n\n";		
-					}
-
-					if(buddy->mHasBlockListEntry)
-					{
-						// Delete the associated block list entry, if any
-						buddy->mHasBlockListEntry = false;
-						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
-							<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-							<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
-							<< "</Request>\n\n\n";								
-					}
-					if(buddy->mHasAutoAcceptListEntry)
-					{
-						// Delete the associated auto-accept list entry, if any
-						buddy->mHasAutoAcceptListEntry = false;
-						stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
-							<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-							<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
-							<< "</Request>\n\n\n";
-					}
-				}
-				
-				if(buddy->mInSLFriends)
-				{
-
-					if(buddy->mCanSeeMeOnline)
-					{
-						// Buddy should not be blocked.
-
-						// If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
-						
-						// If the buddy has a block list entry, delete it.
-						if(buddy->mHasBlockListEntry)
-						{
-							buddy->mHasBlockListEntry = false;
-							stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
-								<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-								<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
-								<< "</Request>\n\n\n";		
-							
-							
-							// If we just deleted a block list entry, add an auto-accept entry.
-							if(!buddy->mHasAutoAcceptListEntry)
-							{
-								buddy->mHasAutoAcceptListEntry = true;								
-								stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.CreateAutoAcceptRule.1\">"
-									<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-									<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
-									<< "<AutoAddAsBuddy>0</AutoAddAsBuddy>"
-									<< "</Request>\n\n\n";
-							}
-						}
-					}
-					else
-					{
-						// Buddy should be blocked.
-						
-						// If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
-
-						// If this buddy has an autoaccept entry, delete it
-						if(buddy->mHasAutoAcceptListEntry)
-						{
-							buddy->mHasAutoAcceptListEntry = false;
-							stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
-								<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-								<< "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
-								<< "</Request>\n\n\n";
-						
-							// If we just deleted an auto-accept entry, add a block list entry.
-							if(!buddy->mHasBlockListEntry)
-							{
-								buddy->mHasBlockListEntry = true;
-								stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.CreateBlockRule.1\">"
-									<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-									<< "<BlockMask>" << buddy->mURI << "</BlockMask>"
-									<< "<PresenceOnly>1</PresenceOnly>"
-									<< "</Request>\n\n\n";								
-							}
-						}
-					}
-
-					if(!buddy->mInSLFriends && !buddy->mInVivoxBuddies)
-					{
-						// Delete this entry from the local buddy list.  This should NOT invalidate the iterator,
-						// since it has already been incremented to the next entry.
-						deleteBuddy(buddy->mURI);
-					}
-
-				}
-				writeString(stream.str());
-			}
-		}
-	}
-}
-
-/////////////////////////////
-// Response/Event handlers
-
-void LLVivoxVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID)
-{	
-	if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "Connector.Create response failure: " << statusString << LL_ENDL;
-		setState(stateConnectorFailed);
-		LLSD args;
-		std::stringstream errs;
-		errs << mVoiceAccountServerURI << "\n:UDP: 3478, 3479, 5060, 5062, 12000-17000";
-		args["HOSTID"] = errs.str();
-		if (LLGridManager::getInstance()->isSystemGrid())
-		{
-			LLNotificationsUtil::add("NoVoiceConnect", args);	
-		}
-		else
-		{
-			LLNotificationsUtil::add("NoVoiceConnect-GIAB", args);	
-		}
-	}
-	else
-	{
-		// Connector created, move forward.
-		LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
-		mVoiceVersion.serverVersion = versionID;
-		mConnectorHandle = connectorHandle;
-		if(getState() == stateConnectorStarting)
-		{
-			setState(stateConnectorStarted);
-		}
-	}
-}
-
-void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
-{ 
-	LL_DEBUGS("Voice") << "Account.Login response (" << statusCode << "): " << statusString << LL_ENDL;
-	
-	// Status code of 20200 means "bad password".  We may want to special-case that at some point.
-	
-	if ( statusCode == 401 )
-	{
-		// 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;
-		setState(stateLoginRetry);
-	}
-	else if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL;
-		setState(stateLoginFailed);
-	}
-	else
-	{
-		// Login succeeded, move forward.
-		mAccountHandle = accountHandle;
-		mNumberOfAliases = numberOfAliases;
-		// This needs to wait until the AccountLoginStateChangeEvent is received.
-//		if(getState() == stateLoggingIn)
-//		{
-//			setState(stateLoggedIn);
-//		}
-	}
-}
-
-void LLVivoxVoiceClient::sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
-{	
-	sessionState *session = findSessionBeingCreatedByURI(requestId);
-	
-	if(session)
-	{
-		session->mCreateInProgress = false;
-	}
-	
-	if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
-		if(session)
-		{
-			session->mErrorStatusCode = statusCode;		
-			session->mErrorStatusString = statusString;
-			if(session == mAudioSession)
-			{
-				setState(stateJoinSessionFailed);
-			}
-			else
-			{
-				reapSession(session);
-			}
-		}
-	}
-	else
-	{
-		LL_INFOS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
-		if(session)
-		{
-			setSessionHandle(session, sessionHandle);
-		}
-	}
-}
-
-void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
-{	
-	sessionState *session = findSessionBeingCreatedByURI(requestId);
-	
-	if(session)
-	{
-		session->mCreateInProgress = false;
-	}
-	
-	if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "SessionGroup.AddSession response failure (" << statusCode << "): " << statusString << LL_ENDL;
-		if(session)
-		{
-			session->mErrorStatusCode = statusCode;		
-			session->mErrorStatusString = statusString;
-			if(session == mAudioSession)
-			{
-				setState(stateJoinSessionFailed);
-			}
-			else
-			{
-				reapSession(session);
-			}
-		}
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "SessionGroup.AddSession response received (success), session handle is " << sessionHandle << LL_ENDL;
-		if(session)
-		{
-			setSessionHandle(session, sessionHandle);
-		}
-	}
-}
-
-void LLVivoxVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString)
-{
-	sessionState *session = findSession(requestId);
-	if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL;
-		if(session)
-		{
-			session->mMediaConnectInProgress = false;
-			session->mErrorStatusCode = statusCode;		
-			session->mErrorStatusString = statusString;
-			if(session == mAudioSession)
-				setState(stateJoinSessionFailed);
-		}
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "Session.Connect response received (success)" << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::logoutResponse(int statusCode, std::string &statusString)
-{	
-	if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL;
-		// Should this ever fail?  do we care if it does?
-	}
-}
-
-void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string &statusString)
-{
-	if(statusCode != 0)
-	{
-		LL_WARNS("Voice") << "Connector.InitiateShutdown response failure: " << statusString << LL_ENDL;
-		// Should this ever fail?  do we care if it does?
-	}
-	
-	mConnected = false;
-	
-	if(getState() == stateConnectorStopping)
-	{
-		setState(stateConnectorStopped);
-	}
-}
-
-void LLVivoxVoiceClient::sessionAddedEvent(
-		std::string &uriString, 
-		std::string &alias, 
-		std::string &sessionHandle, 
-		std::string &sessionGroupHandle, 
-		bool isChannel, 
-		bool incoming,
-		std::string &nameString,
-		std::string &applicationString)
-{
-	sessionState *session = NULL;
-
-	LL_INFOS("Voice") << "session " << uriString << ", alias " << alias << ", name " << nameString << " handle " << sessionHandle << LL_ENDL;
-	
-	session = addSession(uriString, sessionHandle);
-	if(session)
-	{
-		session->mGroupHandle = sessionGroupHandle;
-		session->mIsChannel = isChannel;
-		session->mIncoming = incoming;
-		session->mAlias = alias;
-			
-		// Generate a caller UUID -- don't need to do this for channels
-		if(!session->mIsChannel)
-		{
-			if(IDFromName(session->mSIPURI, session->mCallerID))
-			{
-				// Normal URI(base64-encoded UUID) 
-			}
-			else if(!session->mAlias.empty() && IDFromName(session->mAlias, session->mCallerID))
-			{
-				// Wrong URI, but an alias is available.  Stash the incoming URI as an alternate
-				session->mAlternateSIPURI = session->mSIPURI;
-				
-				// and generate a proper URI from the ID.
-				setSessionURI(session, sipURIFromID(session->mCallerID));
-			}
-			else
-			{
-				LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL;
-				setUUIDFromStringHash(session->mCallerID, session->mSIPURI);
-				session->mSynthesizedCallerID = true;
-				
-				// Can't look up the name in this case -- we have to extract it from the URI.
-				std::string namePortion = nameFromsipURI(session->mSIPURI);
-				if(namePortion.empty())
-				{
-					// Didn't seem to be a SIP URI, just use the whole provided name.
-					namePortion = nameString;
-				}
-				
-				// Some incoming names may be separated with an underscore instead of a space.  Fix this.
-				LLStringUtil::replaceChar(namePortion, '_', ' ');
-				
-				// Act like we just finished resolving the name (this stores it in all the right places)
-				avatarNameResolved(session->mCallerID, namePortion);
-			}
-		
-			LL_INFOS("Voice") << "caller ID: " << session->mCallerID << LL_ENDL;
-
-			if(!session->mSynthesizedCallerID)
-			{
-				// If we got here, we don't have a proper name.  Initiate a lookup.
-				lookupName(session->mCallerID);
-			}
-		}
-	}
-}
-
-void LLVivoxVoiceClient::sessionGroupAddedEvent(std::string &sessionGroupHandle)
-{
-	LL_DEBUGS("Voice") << "handle " << sessionGroupHandle << LL_ENDL;
-	
-#if USE_SESSION_GROUPS
-	if(mMainSessionGroupHandle.empty())
-	{
-		// This is the first (i.e. "main") session group.  Save its handle.
-		mMainSessionGroupHandle = sessionGroupHandle;
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "Already had a session group handle " << mMainSessionGroupHandle << LL_ENDL;
-	}
-#endif
-}
-
-void LLVivoxVoiceClient::joinedAudioSession(sessionState *session)
-{
-	LL_DEBUGS("Voice") << "Joined Audio Session" << LL_ENDL;
-	if(mAudioSession != session)
-	{
-		sessionState *oldSession = mAudioSession;
-
-		mAudioSession = session;
-		mAudioSessionChanged = true;
-
-		// The old session may now need to be deleted.
-		reapSession(oldSession);
-	}
-	
-	// This is the session we're joining.
-	if(getState() == stateJoiningSession)
-	{
-		setState(stateSessionJoined);
-		
-		// SLIM SDK: we don't always receive a participant state change for ourselves when joining a channel now.
-		// Add the current user as a participant here.
-		participantState *participant = session->addParticipant(sipURIFromName(mAccountName));
-		if(participant)
-		{
-			participant->mIsSelf = true;
-			lookupName(participant->mAvatarID);
-
-			LL_INFOS("Voice") << "added self as participant \"" << participant->mAccountName 
-					<< "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-		}
-		
-		if(!session->mIsChannel)
-		{
-			// this is a p2p session.  Make sure the other end is added as a participant.
-			participantState *participant = session->addParticipant(session->mSIPURI);
-			if(participant)
-			{
-				if(participant->mAvatarIDValid)
-				{
-					lookupName(participant->mAvatarID);
-				}
-				else if(!session->mName.empty())
-				{
-					participant->mDisplayName = session->mName;
-					avatarNameResolved(participant->mAvatarID, session->mName);
-				}
-				
-				// TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here?
-				LL_INFOS("Voice") << "added caller as participant \"" << participant->mAccountName 
-						<< "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-			}
-		}
-	}
-}
-
-void LLVivoxVoiceClient::sessionRemovedEvent(
-	std::string &sessionHandle, 
-	std::string &sessionGroupHandle)
-{
-	LL_INFOS("Voice") << "handle " << sessionHandle << LL_ENDL;
-	
-	sessionState *session = findSession(sessionHandle);
-	if(session)
-	{
-		leftAudioSession(session);
-
-		// This message invalidates the session's handle.  Set it to empty.
-		setSessionHandle(session);
-		
-		// This also means that the session's session group is now empty.
-		// Terminate the session group so it doesn't leak.
-		sessionGroupTerminateSendMessage(session);
-		
-		// Reset the media state (we now have no info)
-		session->mMediaStreamState = streamStateUnknown;
-		session->mTextStreamState = streamStateUnknown;
-		
-		// Conditionally delete the session
-		reapSession(session);
-	}
-	else
-	{
-		LL_WARNS("Voice") << "unknown session " << sessionHandle << " removed" << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::reapSession(sessionState *session)
-{
-	if(session)
-	{
-		if(!session->mHandle.empty())
-		{
-			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL;
-		}
-		else if(session->mCreateInProgress)
-		{
-			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL;
-		}
-		else if(session->mMediaConnectInProgress)
-		{
-			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL;
-		}
-		else if(session == mAudioSession)
-		{
-			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL;
-		}
-		else if(session == mNextAudioSession)
-		{
-			LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL;
-		}
-		else
-		{
-			// TODO: Question: Should we check for queued text messages here?
-			// We don't have a reason to keep tracking this session, so just delete it.
-			LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL;
-			deleteSession(session);
-			session = NULL;
-		}	
-	}
-	else
-	{
-//		LL_DEBUGS("Voice") << "session is NULL" << LL_ENDL;
-	}
-}
-
-// Returns true if the session seems to indicate we've moved to a region on a different voice server
-bool LLVivoxVoiceClient::sessionNeedsRelog(sessionState *session)
-{
-	bool result = false;
-	
-	if(session != NULL)
-	{
-		// Only make this check for spatial channels (so it won't happen for group or p2p calls)
-		if(session->mIsSpatial)
-		{	
-			std::string::size_type atsign;
-			
-			atsign = session->mSIPURI.find("@");
-			
-			if(atsign != std::string::npos)
-			{
-				std::string urihost = session->mSIPURI.substr(atsign + 1);
-				if(stricmp(urihost.c_str(), mVoiceSIPURIHostName.c_str()))
-				{
-					// The hostname in this URI is different from what we expect.  This probably means we need to relog.
-					
-					// We could make a ProvisionVoiceAccountRequest and compare the result with the current values of
-					// mVoiceSIPURIHostName and mVoiceAccountServerURI to be really sure, but this is a pretty good indicator.
-					
-					result = true;
-				}
-			}
-		}
-	}
-	
-	return result;
-}
-
-void LLVivoxVoiceClient::leftAudioSession(
-	sessionState *session)
-{
-	if(mAudioSession == session)
-	{
-		switch(getState())
-		{
-			case stateJoiningSession:
-			case stateSessionJoined:
-			case stateRunning:
-			case stateLeavingSession:
-			case stateJoinSessionFailed:
-			case stateJoinSessionFailedWaiting:
-				// normal transition
-				LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
-				setState(stateSessionTerminated);
-			break;
-			
-			case stateSessionTerminated:
-				// this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
-				LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
-			break;
-			
-			default:
-				LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
-				setState(stateSessionTerminated);
-			break;
-		}
-	}
-}
-
-void LLVivoxVoiceClient::accountLoginStateChangeEvent(
-		std::string &accountHandle, 
-		int statusCode, 
-		std::string &statusString, 
-		int state)
-{
-	/*
-		According to Mike S., status codes for this event are:
-		login_state_logged_out=0,
-        login_state_logged_in = 1,
-        login_state_logging_in = 2,
-        login_state_logging_out = 3,
-        login_state_resetting = 4,
-        login_state_error=100	
-	*/
-	
-	LL_DEBUGS("Voice") << "state change event: " << state << LL_ENDL;
-	switch(state)
-	{
-		case 1:
-		if(getState() == stateLoggingIn)
-		{
-			setState(stateLoggedIn);
-		}
-		break;
-
-		case 3:
-			// The user is in the process of logging out.
-			setState(stateLoggingOut);
-		break;
-
-		case 0:
-			// The user has been logged out.  
-			setState(stateLoggedOut);
-		break;
-		
-		default:
-			//Used to be a commented out warning
-			LL_DEBUGS("Voice") << "unknown state: " << state << LL_ENDL;
-		break;
-	}
-}
-
-void LLVivoxVoiceClient::mediaStreamUpdatedEvent(
-	std::string &sessionHandle, 
-	std::string &sessionGroupHandle, 
-	int statusCode, 
-	std::string &statusString, 
-	int state, 
-	bool incoming)
-{
-	sessionState *session = findSession(sessionHandle);
-	
-	LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL;
-	
-	if(session)
-	{
-		// We know about this session
-		
-		// Save the state for later use
-		session->mMediaStreamState = state;
-		
-		switch(statusCode)
-		{
-			case 0:
-			case 200:
-				// generic success
-				// Don't change the saved error code (it may have been set elsewhere)
-			break;
-			default:
-				// save the status code for later
-				session->mErrorStatusCode = statusCode;
-			break;
-		}
-		
-		switch(state)
-		{
-			case streamStateIdle:
-				// Standard "left audio session"
-				session->mVoiceEnabled = false;
-				session->mMediaConnectInProgress = false;
-				leftAudioSession(session);
-			break;
-
-			case streamStateConnected:
-				session->mVoiceEnabled = true;
-				session->mMediaConnectInProgress = false;
-				joinedAudioSession(session);
-			break;
-			
-			case streamStateRinging:
-				if(incoming)
-				{
-					// Send the voice chat invite to the GUI layer
-					// TODO: Question: Should we correlate with the mute list here?
-					session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
-					session->mVoiceInvitePending = true;
-					if(session->mName.empty())
-					{
-						lookupName(session->mCallerID);
-					}
-					else
-					{
-						// Act like we just finished resolving the name
-						avatarNameResolved(session->mCallerID, session->mName);
-					}
-				}
-			break;
-			
-			default:
-				LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
-			break;
-			
-		}
-		
-	}
-	else
-	{
-		LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::textStreamUpdatedEvent(
-	std::string &sessionHandle, 
-	std::string &sessionGroupHandle, 
-	bool enabled,
-	int state, 
-	bool incoming)
-{
-	sessionState *session = findSession(sessionHandle);
-	
-	if(session)
-	{
-		// Save the state for later use
-		session->mTextStreamState = state;
-		
-		// We know about this session
-		switch(state)
-		{
-			case 0:	// We see this when the text stream closes
-				LL_DEBUGS("Voice") << "stream closed" << LL_ENDL;
-			break;
-			
-			case 1:	// We see this on an incoming call from the Connector
-				// Try to send any text messages queued for this session.
-				sendQueuedTextMessages(session);
-
-				// Send the text chat invite to the GUI layer
-				// TODO: Question: Should we correlate with the mute list here?
-				session->mTextInvitePending = true;
-				if(session->mName.empty())
-				{
-					lookupName(session->mCallerID);
-				}
-				else
-				{
-					// Act like we just finished resolving the name
-					avatarNameResolved(session->mCallerID, session->mName);
-				}
-			break;
-
-			default:
-				LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
-			break;
-			
-		}
-	}
-}
-
-void LLVivoxVoiceClient::participantAddedEvent(
-		std::string &sessionHandle, 
-		std::string &sessionGroupHandle, 
-		std::string &uriString, 
-		std::string &alias, 
-		std::string &nameString, 
-		std::string &displayNameString, 
-		int participantType)
-{
-	sessionState *session = findSession(sessionHandle);
-	if(session)
-	{
-		participantState *participant = session->addParticipant(uriString);
-		if(participant)
-		{
-			participant->mAccountName = nameString;
-
-			LL_DEBUGS("Voice") << "added participant \"" << participant->mAccountName 
-					<< "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-
-			if(participant->mAvatarIDValid)
-			{
-				// Initiate a lookup
-				lookupName(participant->mAvatarID);
-			}
-			else
-			{
-				// If we don't have a valid avatar UUID, we need to fill in the display name to make the active speakers floater work.
-				std::string namePortion = nameFromsipURI(uriString);
-				if(namePortion.empty())
-				{
-					// Problem with the SIP URI, fall back to the display name
-					namePortion = displayNameString;
-				}
-				if(namePortion.empty())
-				{
-					// Problems with both of the above, fall back to the account name
-					namePortion = nameString;
-				}
-				
-				// Set the display name (which is a hint to the active speakers window not to do its own lookup)
-				participant->mDisplayName = namePortion;
-				avatarNameResolved(participant->mAvatarID, namePortion);
-			}
-		}
-	}
-}
-
-void LLVivoxVoiceClient::participantRemovedEvent(
-		std::string &sessionHandle, 
-		std::string &sessionGroupHandle, 
-		std::string &uriString, 
-		std::string &alias, 
-		std::string &nameString)
-{
-	sessionState *session = findSession(sessionHandle);
-	if(session)
-	{
-		participantState *participant = session->findParticipant(uriString);
-		if(participant)
-		{
-			session->removeParticipant(participant);
-		}
-		else
-		{
-			LL_DEBUGS("Voice") << "unknown participant " << uriString << LL_ENDL;
-		}
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
-	}
-}
-
-
-void LLVivoxVoiceClient::participantUpdatedEvent(
-		std::string &sessionHandle, 
-		std::string &sessionGroupHandle, 
-		std::string &uriString, 
-		std::string &alias, 
-		bool isModeratorMuted, 
-		bool isSpeaking, 
-		int volume, 
-		F32 energy)
-{
-	sessionState *session = findSession(sessionHandle);
-	if(session)
-	{
-		participantState *participant = session->findParticipant(uriString);
-		
-		if(participant)
-		{
-			participant->mIsSpeaking = isSpeaking;
-			participant->mIsModeratorMuted = isModeratorMuted;
-
-			// SLIM SDK: convert range: ensure that energy is set to zero if is_speaking is false
-			if (isSpeaking)
-			{
-				participant->mSpeakingTimeout.reset();
-				participant->mPower = energy;
-			}
-			else
-			{
-				participant->mPower = 0.0f;
-			}
-
-			// *HACK: Minimal hack to fix EXT-6508, ignore the incoming volume if it is zero.
-			// This happens because we send volume zero to Vivox when someone is muted,
-			// Vivox then send it back to us, overwriting the previous volume.
-			// Remove this hack once volume refactoring from EXT-6031 is applied.
-			if (volume != 0)
-			  {
-			    participant->mVolume = volume;
-			  }
- 
-			
-			// *HACK: mantipov: added while working on EXT-3544                                                                                   
-			/*                                                                                                                                    
-			 Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE                                                            
-			 LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER.                                                                    
-			 
-			 participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted                             
-			 Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug.                 
-			 Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates.                                         
-			 
-			 But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post()                               
-			 voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager                                          
-			 and event is not fired.                                                                                                               
-			 
-			 So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it                                                
-			 in LLCallFloater::draw()                                                                                                              
-			 */
-			LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
-			
-			// ignore session ID of local chat                                                                                                    
-			if (voice_cnl && voice_cnl->getSessionID().notNull())
-			{
-				LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID());
-				if (speaker_manager)
-				{
-					speaker_manager->update(true);
-				}
-			}
-			
-		}
-		else
-		{
-			LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
-		}
-	}
-	else
-	{
-		LL_INFOS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::buddyPresenceEvent(
-		std::string &uriString, 
-		std::string &alias, 
-		std::string &statusString,
-		std::string &applicationString)
-{
-	buddyListEntry *buddy = findBuddy(uriString);
-	
-	if(buddy)
-	{
-		LL_DEBUGS("Voice") << "Presence event for " << buddy->mDisplayName << " status \"" << statusString << "\", application \"" << applicationString << "\""<< LL_ENDL;
-		LL_DEBUGS("Voice") << "before: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
-
-		if(applicationString.empty())
-		{
-			// This presence event is from a client that doesn't set up the Application string.  Do things the old-skool way.
-			// NOTE: this will be needed to support people who aren't on the 3010-class SDK yet.
-
-			if ( stricmp("Unknown", statusString.c_str())== 0) 
-			{
-				// User went offline with a non-SLim-enabled viewer.
-				buddy->mOnlineSL = false;
-			}
-			else if ( stricmp("Online", statusString.c_str())== 0) 
-			{
-				// User came online with a non-SLim-enabled viewer.
-				buddy->mOnlineSL = true;
-			}
-			else
-			{
-				// If the user is online through SLim, their status will be "Online-slc", "Away", or something else.
-				// NOTE: we should never see this unless someone is running an OLD version of SLim -- the versions that should be in use now all set the application string.
-				buddy->mOnlineSLim = true;
-			} 
-		}
-		else if(applicationString.find("SecondLifeViewer") != std::string::npos)
-		{
-			// This presence event is from a viewer that sets the application string
-			if ( stricmp("Unknown", statusString.c_str())== 0) 
-			{
-				// Viewer says they're offline
-				buddy->mOnlineSL = false;
-			}
-			else
-			{
-				// Viewer says they're online
-				buddy->mOnlineSL = true;
-			}
-		}
-		else
-		{
-			// This presence event is from something which is NOT the SL viewer (assume it's SLim).
-			if ( stricmp("Unknown", statusString.c_str())== 0) 
-			{
-				// SLim says they're offline
-				buddy->mOnlineSLim = false;
-			}
-			else
-			{
-				// SLim says they're online
-				buddy->mOnlineSLim = true;
-			}
-		} 
-
-		LL_DEBUGS("Voice") << "after: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
-		
-		// HACK -- increment the internal change serial number in the LLRelationship (without changing the actual status), so the UI notices the change.
-		LLAvatarTracker::instance().setBuddyOnline(buddy->mUUID,LLAvatarTracker::instance().isBuddyOnline(buddy->mUUID));
-
-		notifyFriendObservers();
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "Presence for unknown buddy " << uriString << LL_ENDL;
-	}	
-}
-
-void LLVivoxVoiceClient::messageEvent(
-		std::string &sessionHandle, 
-		std::string &uriString, 
-		std::string &alias, 
-		std::string &messageHeader, 
-		std::string &messageBody,
-		std::string &applicationString)
-{
-	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)
-	{
-		std::string message;
-
-		{
-			const std::string startMarker = "<body";
-			const std::string startMarker2 = ">";
-			const std::string endMarker = "</body>";
-			const std::string startSpan = "<span";
-			const std::string endSpan = "</span>";
-			std::string::size_type start;
-			std::string::size_type end;
-			
-			// Default to displaying the raw string, so the message gets through.
-			message = messageBody;
-
-			// Find the actual message text within the XML fragment
-			start = messageBody.find(startMarker);
-			start = messageBody.find(startMarker2, start);
-			end = messageBody.find(endMarker);
-
-			if(start != std::string::npos)
-			{
-				start += startMarker2.size();
-				
-				if(end != std::string::npos)
-					end -= start;
-					
-				message.assign(messageBody, start, end);
-			}
-			else 
-			{
-				// Didn't find a <body>, try looking for a <span> instead.
-				start = messageBody.find(startSpan);
-				start = messageBody.find(startMarker2, start);
-				end = messageBody.find(endSpan);
-				
-				if(start != std::string::npos)
-				{
-					start += startMarker2.size();
-					
-					if(end != std::string::npos)
-						end -= start;
-					
-					message.assign(messageBody, start, end);
-				}			
-			}
-		}	
-		
-//		LL_DEBUGS("Voice") << "    raw message = \n" << message << LL_ENDL;
-
-		// strip formatting tags
-		{
-			std::string::size_type start;
-			std::string::size_type end;
-			
-			while((start = message.find('<')) != std::string::npos)
-			{
-				if((end = message.find('>', start + 1)) != std::string::npos)
-				{
-					// Strip out the tag
-					message.erase(start, (end + 1) - start);
-				}
-				else
-				{
-					// Avoid an infinite loop
-					break;
-				}
-			}
-		}
-		
-		// Decode ampersand-escaped chars
-		{
-			std::string::size_type mark = 0;
-
-			// The text may contain text encoded with &lt;, &gt;, and &amp;
-			mark = 0;
-			while((mark = message.find("&lt;", mark)) != std::string::npos)
-			{
-				message.replace(mark, 4, "<");
-				mark += 1;
-			}
-			
-			mark = 0;
-			while((mark = message.find("&gt;", mark)) != std::string::npos)
-			{
-				message.replace(mark, 4, ">");
-				mark += 1;
-			}
-			
-			mark = 0;
-			while((mark = message.find("&amp;", mark)) != std::string::npos)
-			{
-				message.replace(mark, 5, "&");
-				mark += 1;
-			}
-		}
-		
-		// strip leading/trailing whitespace (since we always seem to get a couple newlines)
-		LLStringUtil::trim(message);
-		
-//		LL_DEBUGS("Voice") << "    stripped message = \n" << message << LL_ENDL;
-		
-		sessionState *session = findSession(sessionHandle);
-		if(session)
-		{
-			bool is_busy = gAgent.getBusy();
-			bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
-			bool is_linden = LLMuteList::getInstance()->isLinden(session->mName);
-			bool quiet_chat = false;
-			LLChat chat;
-
-			chat.mMuted = is_muted && !is_linden;
-			
-			if(!chat.mMuted)
-			{
-				chat.mFromID = session->mCallerID;
-				chat.mFromName = session->mName;
-				chat.mSourceType = CHAT_SOURCE_AGENT;
-
-				if(is_busy && !is_linden)
-				{
-					quiet_chat = true;
-					// TODO: Question: Return busy mode response here?  Or maybe when session is started instead?
-				}
-				
-				LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
-				gIMMgr->addMessage(session->mIMSessionID,
-						session->mCallerID,
-						session->mName.c_str(),
-						message.c_str(),
-						LLStringUtil::null,		// default arg
-						IM_NOTHING_SPECIAL,		// default arg
-						0,						// default arg
-						LLUUID::null,			// default arg
-						LLVector3::zero,		// default arg
-						true);					// prepend name and make it a link to the user's profile
-
-			}
-		}		
-	}
-}
-
-void LLVivoxVoiceClient::sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType)
-{
-	sessionState *session = findSession(sessionHandle);
-	
-	if(session)
-	{
-		participantState *participant = session->findParticipant(uriString);
-		if(participant)
-		{
-			if (!stricmp(notificationType.c_str(), "Typing"))
-			{
-				// Other end started typing
-				// TODO: The proper way to add a typing notification seems to be LLIMMgr::processIMTypingStart().
-				// It requires an LLIMInfo for the message, which we don't have here.
-			}
-			else if (!stricmp(notificationType.c_str(), "NotTyping"))
-			{
-				// Other end stopped typing
-				// TODO: The proper way to remove a typing notification seems to be LLIMMgr::processIMTypingStop().
-				// It requires an LLIMInfo for the message, which we don't have here.
-			}
-			else
-			{
-				LL_DEBUGS("Voice") << "Unknown notification type " << notificationType << "for participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
-			}
-		}
-		else
-		{
-			LL_DEBUGS("Voice") << "Unknown participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
-		}
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "Unknown session handle " << sessionHandle << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType)
-{
-	buddyListEntry *buddy = findBuddy(buddyURI);
-	
-	if(!buddy)
-	{
-		// Couldn't find buddy by URI, try converting the alias...
-		if(!alias.empty())
-		{
-			LLUUID id;
-			if(IDFromName(alias, id))
-			{
-				buddy = findBuddy(id);
-			}
-		}
-	}
-	
-	if(buddy)
-	{
-		std::ostringstream stream;
-		
-		if(buddy->mCanSeeMeOnline)
-		{
-			// Sending the response will create an auto-accept rule
-			buddy->mHasAutoAcceptListEntry = true;
-		}
-		else
-		{
-			// Sending the response will create a block rule
-			buddy->mHasBlockListEntry = true;
-		}
-		
-		if(buddy->mInSLFriends)
-		{
-			buddy->mInVivoxBuddies = true;
-		}
-		
-		stream
-			<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.SendSubscriptionReply.1\">"
-				<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
-				<< "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
-				<< "<RuleType>" << (buddy->mCanSeeMeOnline?"Allow":"Hide") << "</RuleType>"
-				<< "<AutoAccept>"<< (buddy->mInSLFriends?"1":"0")<< "</AutoAccept>"
-				<< "<SubscriptionHandle>" << subscriptionHandle << "</SubscriptionHandle>"
-			<< "</Request>"
-			<< "\n\n\n";
-			
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::auxAudioPropertiesEvent(F32 energy)
-{
-	LL_DEBUGS("Voice") << "got energy " << energy << LL_ENDL;
-	mTuningEnergy = energy;
-}
-
-void LLVivoxVoiceClient::buddyListChanged()
-{
-	// This is called after we receive a BuddyAndGroupListChangedEvent.
-	mBuddyListMapPopulated = true;
-	mFriendsListDirty = true;
-}
-
-void LLVivoxVoiceClient::muteListChanged()
-{
-	// The user's mute list has been updated.  Go through the current participant list and sync it with the mute list.
-	if(mAudioSession)
-	{
-		participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
-		
-		for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
-		{
-			participantState *p = iter->second;
-			
-			// Check to see if this participant is on the mute list already
-			if(p->updateMuteState())
-				mAudioSession->mVolumeDirty = true;
-		}
-	}
-}
-
-void LLVivoxVoiceClient::updateFriends(U32 mask)
-{
-	if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::POWERS))
-	{
-		// Just resend the whole friend list to the daemon
-		mFriendsListDirty = true;
-	}
-}
-
-/////////////////////////////
-// Managing list of participants
-LLVivoxVoiceClient::participantState::participantState(const std::string &uri) : 
-	 mURI(uri), 
-	 mPTT(false), 
-	 mIsSpeaking(false), 
-	 mIsModeratorMuted(false), 
-	 mLastSpokeTimestamp(0.f), 
-	 mPower(0.f), 
-	 mVolume(-1), 
-	 mOnMuteList(false), 
-	 mUserVolume(-1), 
-	 mVolumeDirty(false), 
-	 mAvatarIDValid(false),
-	 mIsSelf(false)
-{
-}
-
-LLVivoxVoiceClient::participantState *LLVivoxVoiceClient::sessionState::addParticipant(const std::string &uri)
-{
-	participantState *result = NULL;
-	bool useAlternateURI = false;
-	
-	// Note: this is mostly the body of LLVivoxVoiceClient::sessionState::findParticipant(), but since we need to know if it
-	// matched the alternate SIP URI (so we can add it properly), we need to reproduce it here.
-	{
-		participantMap::iterator iter = mParticipantsByURI.find(uri);
-
-		if(iter == mParticipantsByURI.end())
-		{
-			if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
-			{
-				// This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
-				// Use mSIPURI instead, since it will be properly encoded.
-				iter = mParticipantsByURI.find(mSIPURI);
-				useAlternateURI = true;
-			}
-		}
-
-		if(iter != mParticipantsByURI.end())
-		{
-			result = iter->second;
-		}
-	}
-		
-	if(!result)
-	{
-		// participant isn't already in one list or the other.
-		result = new participantState(useAlternateURI?mSIPURI:uri);
-		mParticipantsByURI.insert(participantMap::value_type(result->mURI, result));
-		mParticipantsChanged = true;
-		
-		// Try to do a reverse transform on the URI to get the GUID back.
-		{
-			LLUUID id;
-			if(LLVivoxVoiceClient::getInstance()->IDFromName(result->mURI, id))
-			{
-				result->mAvatarIDValid = true;
-				result->mAvatarID = id;
-
-				if(result->updateMuteState())
-					mVolumeDirty = true;
-			}
-			else
-			{
-				// Create a UUID by hashing the URI, but do NOT set mAvatarIDValid.
-				// This tells both code in LLVivoxVoiceClient and code in llfloateractivespeakers.cpp that the ID will not be in the name cache.
-				setUUIDFromStringHash(result->mAvatarID, uri);
-			}
-		}
-		
-		mParticipantsByUUID.insert(participantUUIDMap::value_type(result->mAvatarID, result));
-
-		result->mUserVolume = LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID);
-		
-		LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
-	}
-	
-	return result;
-}
-
-bool LLVivoxVoiceClient::participantState::updateMuteState()
-{
-	bool result = false;
-	
-	if(mAvatarIDValid)
-	{
-		bool isMuted = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
-		if(mOnMuteList != isMuted)
-		{
-			mOnMuteList = isMuted;
-			mVolumeDirty = true;
-			result = true;
-		}
-	}
-	return result;
-}
-
-bool LLVivoxVoiceClient::participantState::isAvatar()
-{
-	return mAvatarIDValid;
-}
-
-void LLVivoxVoiceClient::sessionState::removeParticipant(LLVivoxVoiceClient::participantState *participant)
-{
-	if(participant)
-	{
-		participantMap::iterator iter = mParticipantsByURI.find(participant->mURI);
-		participantUUIDMap::iterator iter2 = mParticipantsByUUID.find(participant->mAvatarID);
-		
-		LL_DEBUGS("Voice") << "participant \"" << participant->mURI <<  "\" (" << participant->mAvatarID << ") removed." << LL_ENDL;
-		
-		if(iter == mParticipantsByURI.end())
-		{
-			LL_ERRS("Voice") << "Internal error: participant " << participant->mURI << " not in URI map" << LL_ENDL;
-		}
-		else if(iter2 == mParticipantsByUUID.end())
-		{
-			LL_ERRS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL;
-		}
-		else if(iter->second != iter2->second)
-		{
-			LL_ERRS("Voice") << "Internal error: participant mismatch!" << LL_ENDL;
-		}
-		else
-		{
-			mParticipantsByURI.erase(iter);
-			mParticipantsByUUID.erase(iter2);
-			
-			delete participant;
-			mParticipantsChanged = true;
-		}
-	}
-}
-
-void LLVivoxVoiceClient::sessionState::removeAllParticipants()
-{
-	LL_DEBUGS("Voice") << "called" << LL_ENDL;
-
-	while(!mParticipantsByURI.empty())
-	{
-		removeParticipant(mParticipantsByURI.begin()->second);
-	}
-	
-	if(!mParticipantsByUUID.empty())
-	{
-		LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::getParticipantList(std::set<LLUUID> &participants)
-{
-	if(mAudioSession)
-	{
-		for(participantUUIDMap::iterator iter = mAudioSession->mParticipantsByUUID.begin();
-			iter != mAudioSession->mParticipantsByUUID.end(); 
-			iter++)
-		{
-			participants.insert(iter->first);
-		}
-	}
-}
-
-bool LLVivoxVoiceClient::isParticipant(const LLUUID &speaker_id)
-{
-  if(mAudioSession)
-    {
-      return (mAudioSession->mParticipantsByUUID.find(speaker_id) != mAudioSession->mParticipantsByUUID.end());
-    }
-  return false;
-}
-
-
-LLVivoxVoiceClient::participantState *LLVivoxVoiceClient::sessionState::findParticipant(const std::string &uri)
-{
-	participantState *result = NULL;
-	
-	participantMap::iterator iter = mParticipantsByURI.find(uri);
-
-	if(iter == mParticipantsByURI.end())
-	{
-		if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
-		{
-			// This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
-			// Look up the other URI
-			iter = mParticipantsByURI.find(mSIPURI);
-		}
-	}
-
-	if(iter != mParticipantsByURI.end())
-	{
-		result = iter->second;
-	}
-		
-	return result;
-}
-
-LLVivoxVoiceClient::participantState* LLVivoxVoiceClient::sessionState::findParticipantByID(const LLUUID& id)
-{
-	participantState * result = NULL;
-	participantUUIDMap::iterator iter = mParticipantsByUUID.find(id);
-
-	if(iter != mParticipantsByUUID.end())
-	{
-		result = iter->second;
-	}
-
-	return result;
-}
-
-LLVivoxVoiceClient::participantState* LLVivoxVoiceClient::findParticipantByID(const LLUUID& id)
-{
-	participantState * result = NULL;
-	
-	if(mAudioSession)
-	{
-		result = mAudioSession->findParticipantByID(id);
-	}
-	
-	return result;
-}
-
-
-void LLVivoxVoiceClient::parcelChanged()
-{
-	if(getState() >= stateNoChannel)
-	{
-		// If the user is logged in, start a channel lookup.
-		LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
-
-		std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest");
-		LLSD data;
-		LLHTTPClient::post(
-			url,
-			data,
-			new LLVivoxVoiceClientCapResponder);
-	}
-	else
-	{
-		// The transition to stateNoChannel needs to kick this off again.
-		LL_INFOS("Voice") << "not logged in yet, deferring" << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::switchChannel(
-	std::string uri,
-	bool spatial,
-	bool no_reconnect,
-	bool is_p2p,
-	std::string hash)
-{
-	bool needsSwitch = false;
-	
-	LL_DEBUGS("Voice") 
-		<< "called in state " << state2string(getState()) 
-		<< " with uri \"" << uri << "\"" 
-		<< (spatial?", spatial is true":", spatial is false")
-		<< LL_ENDL;
-	
-	switch(getState())
-	{
-		case stateJoinSessionFailed:
-		case stateJoinSessionFailedWaiting:
-		case stateNoChannel:
-			// Always switch to the new URI from these states.
-			needsSwitch = true;
-		break;
-
-		default:
-			if(mSessionTerminateRequested)
-			{
-				// If a terminate has been requested, we need to compare against where the URI we're already headed to.
-				if(mNextAudioSession)
-				{
-					if(mNextAudioSession->mSIPURI != uri)
-						needsSwitch = true;
-				}
-				else
-				{
-					// mNextAudioSession is null -- this probably means we're on our way back to spatial.
-					if(!uri.empty())
-					{
-						// We do want to process a switch in this case.
-						needsSwitch = true;
-					}
-				}
-			}
-			else
-			{
-				// Otherwise, compare against the URI we're in now.
-				if(mAudioSession)
-				{
-					if(mAudioSession->mSIPURI != uri)
-					{
-						needsSwitch = true;
-					}
-				}
-				else
-				{
-					if(!uri.empty())
-					{
-						// mAudioSession is null -- it's not clear what case would cause this.
-						// For now, log it as a warning and see if it ever crops up.
-						LL_WARNS("Voice") << "No current audio session." << LL_ENDL;
-					}
-				}
-			}
-		break;
-	}
-	
-	if(needsSwitch)
-	{
-		if(uri.empty())
-		{
-			// Leave any channel we may be in
-			LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL;
-
-			sessionState *oldSession = mNextAudioSession;
-			mNextAudioSession = NULL;
-
-			// The old session may now need to be deleted.
-			reapSession(oldSession);
-
-			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
-		}
-		else
-		{
-			LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL;
-
-			mNextAudioSession = addSession(uri);
-			mNextAudioSession->mHash = hash;
-			mNextAudioSession->mIsSpatial = spatial;
-			mNextAudioSession->mReconnect = !no_reconnect;
-			mNextAudioSession->mIsP2P = is_p2p;
-		}
-		
-		if(getState() <= stateNoChannel)
-		{
-			// We're already set up to join a channel, just needed to fill in the session URI
-		}
-		else
-		{
-			// State machine will come around and rejoin if uri/handle is not empty.
-			sessionTerminate();
-		}
-	}
-}
-
-void LLVivoxVoiceClient::joinSession(sessionState *session)
-{
-	mNextAudioSession = session;
-	
-	if(getState() <= stateNoChannel)
-	{
-		// We're already set up to join a channel, just needed to fill in the session handle
-	}
-	else
-	{
-		// State machine will come around and rejoin if uri/handle is not empty.
-		sessionTerminate();
-	}
-}
-
-void LLVivoxVoiceClient::setNonSpatialChannel(
-	const std::string &uri,
-	const std::string &credentials)
-{
-	switchChannel(uri, false, false, false, credentials);
-}
-
-void LLVivoxVoiceClient::setSpatialChannel(
-	const std::string &uri,
-	const std::string &credentials)
-{
-	mSpatialSessionURI = uri;
-	mSpatialSessionCredentials = credentials;
-	mAreaVoiceDisabled = mSpatialSessionURI.empty();
-
-	LL_DEBUGS("Voice") << "got spatial channel uri: \"" << uri << "\"" << LL_ENDL;
-	
-	if((mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial)))
-	{
-		// User is in a non-spatial chat or joining a non-spatial chat.  Don't switch channels.
-		LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL;
-	}
-	else
-	{
-		switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
-	}
-}
-
-void LLVivoxVoiceClient::callUser(const LLUUID &uuid)
-{
-	std::string userURI = sipURIFromID(uuid);
-
-	switchChannel(userURI, false, true, true);
-}
-
-LLVivoxVoiceClient::sessionState* LLVivoxVoiceClient::startUserIMSession(const LLUUID &uuid)
-{
-	// Figure out if a session with the user already exists
-	sessionState *session = findSession(uuid);
-	if(!session)
-	{
-		// No session with user, need to start one.
-		std::string uri = sipURIFromID(uuid);
-		session = addSession(uri);
-
-		llassert(session);
-		if (!session) return NULL;
-
-		session->mIsSpatial = false;
-		session->mReconnect = false;	
-		session->mIsP2P = true;
-		session->mCallerID = uuid;
-	}
-	
-	if(session->mHandle.empty())
-	  {
-	    // Session isn't active -- start it up.
-	    sessionCreateSendMessage(session, false, true);
-	  }
-	else
-	  {	
-	    // Session is already active -- start up text.
-	    sessionTextConnectSendMessage(session);
-	  }
-	
-	return session;
-}
-
-BOOL LLVivoxVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message)
-{
-	bool result = false;
-
-	// Attempt to locate the indicated session
-	sessionState *session = startUserIMSession(participant_id);
-	if(session)
-	{
-		// found the session, attempt to send the message
-		session->mTextMsgQueue.push(message);
-		
-		// Try to send queued messages (will do nothing if the session is not open yet)
-		sendQueuedTextMessages(session);
-
-		// The message is queued, so we succeed.
-		result = true;
-	}	
-	else
-	{
-		LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL;
-	}
-	
-	return result;
-}
-
-void LLVivoxVoiceClient::sendQueuedTextMessages(sessionState *session)
-{
-	if(session->mTextStreamState == 1)
-	{
-		if(!session->mTextMsgQueue.empty())
-		{
-			std::ostringstream stream;
-			
-			while(!session->mTextMsgQueue.empty())
-			{
-				std::string message = session->mTextMsgQueue.front();
-				session->mTextMsgQueue.pop();
-				stream
-				<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SendMessage.1\">"
-					<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-					<< "<MessageHeader>text/HTML</MessageHeader>"
-					<< "<MessageBody>" << message << "</MessageBody>"
-				<< "</Request>"
-				<< "\n\n\n";
-			}		
-			writeString(stream.str());
-		}
-	}
-	else
-	{
-		// Session isn't connected yet, defer until later.
-	}
-}
-
-void LLVivoxVoiceClient::endUserIMSession(const LLUUID &uuid)
-{
-	// Figure out if a session with the user exists
-	sessionState *session = findSession(uuid);
-	if(session)
-	{
-		// found the session
-		if(!session->mHandle.empty())
-		{
-			sessionTextDisconnectSendMessage(session);
-		}
-	}	
-	else
-	{
-		LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL;
-	}
-}
-
-bool LLVivoxVoiceClient::answerInvite(std::string &sessionHandle)
-{
-	// this is only ever used to answer incoming p2p call invites.
-	
-	sessionState *session = findSession(sessionHandle);
-	if(session)
-	{
-		session->mIsSpatial = false;
-		session->mReconnect = false;	
-		session->mIsP2P = true;
-
-		joinSession(session);
-		return true;
-	}
-	
-	return false;
-}
-
-BOOL LLVivoxVoiceClient::isOnlineSIP(const LLUUID &id)
-{
-	bool result = false;
-	buddyListEntry *buddy = findBuddy(id);
-	if(buddy)
-	{
-		result = buddy->mOnlineSLim;
-		LL_DEBUGS("Voice") << "Buddy " << buddy->mDisplayName << " is SIP " << (result?"online":"offline") << LL_ENDL;
-	}
-
-	if(!result)
-	{
-		// This user isn't on the buddy list or doesn't show online status through the buddy list, but could be a participant in an existing session if they initiated a text IM.
-		sessionState *session = findSession(id);
-		if(session && !session->mHandle.empty())
-		{
-			if((session->mTextStreamState != streamStateUnknown) || (session->mMediaStreamState > streamStateIdle))
-			{
-				LL_DEBUGS("Voice") << "Open session with " << id << " found, returning SIP online state" << LL_ENDL;
-				// we have a p2p text session open with this user, so by definition they're online.
-				result = true;
-			}
-		}
-	}
-	
-	return result;
-}
-
-bool LLVivoxVoiceClient::isVoiceWorking()
-{
-  //Added stateSessionTerminated state to avoid problems with call in parcels with disabled voice (EXT-4758)
-  // Condition with joining spatial num was added to take into account possible problems with connection to voice
-  // server(EXT-4313). See bug descriptions and comments for MAX_NORMAL_JOINING_SPATIAL_NUM for more info.
-  return (mSpatialJoiningNum < MAX_NORMAL_JOINING_SPATIAL_NUM) && (stateLoggedIn <= mState) && (mState <= stateSessionTerminated);
-}
-
-// Returns true if the indicated participant in the current audio session is really an SL avatar.
-// Currently this will be false only for PSTN callers into group chats, and PSTN p2p calls.
-BOOL LLVivoxVoiceClient::isParticipantAvatar(const LLUUID &id)
-{
-	BOOL result = TRUE; 
-	sessionState *session = findSession(id);
-	
-	if(session != NULL)
-	{
-		// this is a p2p session with the indicated caller, or the session with the specified UUID.
-		if(session->mSynthesizedCallerID)
-			result = FALSE;
-	}
-	else
-	{
-		// Didn't find a matching session -- check the current audio session for a matching participant
-		if(mAudioSession != NULL)
-		{
-			participantState *participant = findParticipantByID(id);
-			if(participant != NULL)
-			{
-				result = participant->isAvatar();
-			}
-		}
-	}
-	
-	return result;
-}
-
-// Returns true if calling back the session URI after the session has closed is possible.
-// Currently this will be false only for PSTN P2P calls.		
-BOOL LLVivoxVoiceClient::isSessionCallBackPossible(const LLUUID &session_id)
-{
-	BOOL result = TRUE; 
-	sessionState *session = findSession(session_id);
-	
-	if(session != NULL)
-	{
-		result = session->isCallBackPossible();
-	}
-	
-	return result;
-}
-
-// Returns true if the session can accepte text IM's.
-// Currently this will be false only for PSTN P2P calls.
-BOOL LLVivoxVoiceClient::isSessionTextIMPossible(const LLUUID &session_id)
-{
-	bool result = TRUE; 
-	sessionState *session = findSession(session_id);
-	
-	if(session != NULL)
-	{
-		result = session->isTextIMPossible();
-	}
-	
-	return result;
-}
-		
-
-void LLVivoxVoiceClient::declineInvite(std::string &sessionHandle)
-{
-	sessionState *session = findSession(sessionHandle);
-	if(session)
-	{
-		sessionMediaDisconnectSendMessage(session);
-	}
-}
-
-void LLVivoxVoiceClient::leaveNonSpatialChannel()
-{
-	LL_DEBUGS("Voice") 
-		<< "called in state " << state2string(getState()) 
-		<< LL_ENDL;
-	
-	// Make sure we don't rejoin the current session.	
-	sessionState *oldNextSession = mNextAudioSession;
-	mNextAudioSession = NULL;
-	
-	// Most likely this will still be the current session at this point, but check it anyway.
-	reapSession(oldNextSession);
-	
-	verifySessionState();
-	
-	sessionTerminate();
-}
-
-std::string LLVivoxVoiceClient::getCurrentChannel()
-{
-	std::string result;
-	
-	if((getState() == stateRunning) && !mSessionTerminateRequested)
-	{
-		result = getAudioSessionURI();
-	}
-	
-	return result;
-}
-
-bool LLVivoxVoiceClient::inProximalChannel()
-{
-	bool result = false;
-	
-	if((getState() == stateRunning) && !mSessionTerminateRequested)
-	{
-		result = inSpatialChannel();
-	}
-	
-	return result;
-}
-
-std::string LLVivoxVoiceClient::sipURIFromID(const LLUUID &id)
-{
-	std::string result;
-	result = "sip:";
-	result += nameFromID(id);
-	result += "@";
-	result += mVoiceSIPURIHostName;
-	
-	return result;
-}
-
-std::string LLVivoxVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar)
-{
-	std::string result;
-	if(avatar)
-	{
-		result = "sip:";
-		result += nameFromID(avatar->getID());
-		result += "@";
-		result += mVoiceSIPURIHostName;
-	}
-	
-	return result;
-}
-
-std::string LLVivoxVoiceClient::nameFromAvatar(LLVOAvatar *avatar)
-{
-	std::string result;
-	if(avatar)
-	{
-		result = nameFromID(avatar->getID());
-	}	
-	return result;
-}
-
-std::string LLVivoxVoiceClient::nameFromID(const LLUUID &uuid)
-{
-	std::string result;
-	
-	if (uuid.isNull()) {
-		//VIVOX, the uuid emtpy look for the mURIString and return that instead.
-		//result.assign(uuid.mURIStringName);
-		LLStringUtil::replaceChar(result, '_', ' ');
-		return result;
-	}
-	// Prepending this apparently prevents conflicts with reserved names inside the vivox and diamondware code.
-	result = "x";
-	
-	// Base64 encode and replace the pieces of base64 that are less compatible 
-	// with e-mail local-parts.
-	// See RFC-4648 "Base 64 Encoding with URL and Filename Safe Alphabet"
-	result += LLBase64::encode(uuid.mData, UUID_BYTES);
-	LLStringUtil::replaceChar(result, '+', '-');
-	LLStringUtil::replaceChar(result, '/', '_');
-	
-	// If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
-	// echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
-	
-	// The reverse transform can be done with:
-	// echo 'x5mkTKmxDTuGnjWyC__WfMg==' |cut -b 2- -|tr '_-' '/+' |openssl base64 -d|xxd -p
-	
-	return result;
-}
-
-bool LLVivoxVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
-{
-	bool result = false;
-	
-	// SLIM SDK: The "name" may actually be a SIP URI such as: "sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com"
-	// If it is, convert to a bare name before doing the transform.
-	std::string name = nameFromsipURI(inName);
-	
-	// Doesn't look like a SIP URI, assume it's an actual name.
-	if(name.empty())
-		name = inName;
-
-	// This will only work if the name is of the proper form.
-	// As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is:
-	// "xFnPP04IpREWNkuw1cOXlhw=="
-	
-	if((name.size() == 25) && (name[0] == 'x') && (name[23] == '=') && (name[24] == '='))
-	{
-		// The name appears to have the right form.
-
-		// Reverse the transforms done by nameFromID
-		std::string temp = name;
-		LLStringUtil::replaceChar(temp, '-', '+');
-		LLStringUtil::replaceChar(temp, '_', '/');
-
-		U8 rawuuid[UUID_BYTES + 1]; 
-		int len = apr_base64_decode_binary(rawuuid, temp.c_str() + 1);
-		if(len == UUID_BYTES)
-		{
-			// The decode succeeded.  Stuff the bits into the result's UUID
-			memcpy(uuid.mData, rawuuid, UUID_BYTES);
-			result = true;
-		}
-	} 
-	
-	if(!result)
-	{
-		// VIVOX:  not a standard account name, just copy the URI name mURIString field
-		// and hope for the best.  bpj
-		uuid.setNull();  // VIVOX, set the uuid field to nulls
-	}
-	
-	return result;
-}
-
-std::string LLVivoxVoiceClient::displayNameFromAvatar(LLVOAvatar *avatar)
-{
-	return avatar->getFullname();
-}
-
-std::string LLVivoxVoiceClient::sipURIFromName(std::string &name)
-{
-	std::string result;
-	result = "sip:";
-	result += name;
-	result += "@";
-	result += mVoiceSIPURIHostName;
-
-//	LLStringUtil::toLower(result);
-
-	return result;
-}
-
-std::string LLVivoxVoiceClient::nameFromsipURI(const std::string &uri)
-{
-	std::string result;
-
-	std::string::size_type sipOffset, atOffset;
-	sipOffset = uri.find("sip:");
-	atOffset = uri.find("@");
-	if((sipOffset != std::string::npos) && (atOffset != std::string::npos))
-	{
-		result = uri.substr(sipOffset + 4, atOffset - (sipOffset + 4));
-	}
-	
-	return result;
-}
-
-bool LLVivoxVoiceClient::inSpatialChannel(void)
-{
-	bool result = false;
-	
-	if(mAudioSession)
-		result = mAudioSession->mIsSpatial;
-		
-	return result;
-}
-
-std::string LLVivoxVoiceClient::getAudioSessionURI()
-{
-	std::string result;
-	
-	if(mAudioSession)
-		result = mAudioSession->mSIPURI;
-		
-	return result;
-}
-
-std::string LLVivoxVoiceClient::getAudioSessionHandle()
-{
-	std::string result;
-	
-	if(mAudioSession)
-		result = mAudioSession->mHandle;
-		
-	return result;
-}
-
-
-/////////////////////////////
-// Sending updates of current state
-
-void LLVivoxVoiceClient::enforceTether(void)
-{
-	LLVector3d tethered	= mCameraRequestedPosition;
-
-	// constrain 'tethered' to within 50m of mAvatarPosition.
-	{
-		F32 max_dist = 50.0f;
-		LLVector3d camera_offset = mCameraRequestedPosition - mAvatarPosition;
-		F32 camera_distance = (F32)camera_offset.magVec();
-		if(camera_distance > max_dist)
-		{
-			tethered = mAvatarPosition + 
-				(max_dist / camera_distance) * camera_offset;
-		}
-	}
-	
-	if(dist_vec(mCameraPosition, tethered) > 0.1)
-	{
-		mCameraPosition = tethered;
-		mSpatialCoordsDirty = true;
-	}
-}
-
-void LLVivoxVoiceClient::updatePosition(void)
-{
-	
-	LLViewerRegion *region = gAgent.getRegion();
-	if(region && isAgentAvatarValid())
-	{
-		LLMatrix3 rot;
-		LLVector3d pos;
-		
-		// TODO: If camera and avatar velocity are actually used by the voice system, we could compute them here...
-		// They're currently always set to zero.
-		
-		// Send the current camera position to the voice code
-		rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (),  LLViewerCamera::getInstance()->getUpAxis());		
-		pos = gAgent.getRegion()->getPosGlobalFromRegion(LLViewerCamera::getInstance()->getOrigin());
-		
-		LLVivoxVoiceClient::getInstance()->setCameraPosition(
-															 pos,				// position
-															 LLVector3::zero, 	// velocity
-															 rot);				// rotation matrix
-		
-		// Send the current avatar position to the voice code
-		rot = gAgentAvatarp->getRootJoint()->getWorldRotation().getMatrix3();
-		pos = gAgentAvatarp->getPositionGlobal();
-
-		// TODO: Can we get the head offset from outside the LLVOAvatar?
-		//			pos += LLVector3d(mHeadOffset);
-		pos += LLVector3d(0.f, 0.f, 1.f);
-		
-		LLVivoxVoiceClient::getInstance()->setAvatarPosition(
-															 pos,				// position
-															 LLVector3::zero, 	// velocity
-															 rot);				// rotation matrix
-	}
-}
-
-void LLVivoxVoiceClient::setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot)
-{
-	mCameraRequestedPosition = position;
-	
-	if(mCameraVelocity != velocity)
-	{
-		mCameraVelocity = velocity;
-		mSpatialCoordsDirty = true;
-	}
-	
-	if(mCameraRot != rot)
-	{
-		mCameraRot = rot;
-		mSpatialCoordsDirty = true;
-	}
-}
-
-void LLVivoxVoiceClient::setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot)
-{
-	if(dist_vec(mAvatarPosition, position) > 0.1)
-	{
-		mAvatarPosition = position;
-		mSpatialCoordsDirty = true;
-	}
-	
-	if(mAvatarVelocity != velocity)
-	{
-		mAvatarVelocity = velocity;
-		mSpatialCoordsDirty = true;
-	}
-	
-	if(mAvatarRot != rot)
-	{
-		mAvatarRot = rot;
-		mSpatialCoordsDirty = true;
-	}
-}
-
-bool LLVivoxVoiceClient::channelFromRegion(LLViewerRegion *region, std::string &name)
-{
-	bool result = false;
-	
-	if(region)
-	{
-		name = region->getName();
-	}
-	
-	if(!name.empty())
-		result = true;
-	
-	return result;
-}
-
-void LLVivoxVoiceClient::leaveChannel(void)
-{
-	if(getState() == stateRunning)
-	{
-		LL_DEBUGS("Voice") << "leaving channel for teleport/logout" << LL_ENDL;
-		mChannelName.clear();
-		sessionTerminate();
-	}
-}
-
-void LLVivoxVoiceClient::setMuteMic(bool muted)
-{
-	mMuteMic = muted;
-}
-
-void LLVivoxVoiceClient::setUserPTTState(bool ptt)
-{
-	mUserPTTState = ptt;
-}
-
-bool LLVivoxVoiceClient::getUserPTTState()
-{
-	return mUserPTTState;
-}
-
-void LLVivoxVoiceClient::inputUserControlState(bool down)
-{
-	if(mPTTIsToggle)
-	{
-		if(down) // toggle open-mic state on 'down'                                                        
-		{
-			toggleUserPTTState();
-		}
-	}
-	else // set open-mic state as an absolute                                                                  
-	{
-		setUserPTTState(down);
-	}
-}
-
-
-void LLVivoxVoiceClient::toggleUserPTTState(void)
-{
-	mUserPTTState = !mUserPTTState;
-}
-
-void LLVivoxVoiceClient::setVoiceEnabled(bool enabled)
-{
-	if (enabled != mVoiceEnabled)
-	{
-		// TODO: Refactor this so we don't call into LLVoiceChannel, but simply
-		// use the status observer
-		mVoiceEnabled = enabled;
-		LLVoiceClientStatusObserver::EStatusType status;
-		
-		
-		if (enabled)
-		{
-			LLVoiceChannel::getCurrentVoiceChannel()->activate();
-			status = LLVoiceClientStatusObserver::STATUS_VOICE_ENABLED;
-		}
-		else
-		{
-			// Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
-			LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
-			status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED;
-		}
-	}
-}
-
-bool LLVivoxVoiceClient::voiceEnabled()
-{
-	return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice");
-}
-
-void LLVivoxVoiceClient::setLipSyncEnabled(BOOL enabled)
-{
-	mLipSyncEnabled = enabled;
-}
-
-BOOL LLVivoxVoiceClient::lipSyncEnabled()
-{
-	   
-	if ( mVoiceEnabled && stateDisabled != getState() )
-	{
-		return mLipSyncEnabled;
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
-void LLVivoxVoiceClient::setUsePTT(bool usePTT)
-{
-	if(usePTT && !mUsePTT)
-	{
-		// When the user turns on PTT, reset the current state.
-		mUserPTTState = false;
-	}
-	mUsePTT = usePTT;
-}
-
-void LLVivoxVoiceClient::setPTTIsToggle(bool PTTIsToggle)
-{
-	if(!PTTIsToggle && mPTTIsToggle)
-	{
-		// When the user turns off toggle, reset the current state.
-		mUserPTTState = false;
-	}
-	
-	mPTTIsToggle = PTTIsToggle;
-}
-
-bool LLVivoxVoiceClient::getPTTIsToggle()
-{
-	return mPTTIsToggle;
-}
-
-void LLVivoxVoiceClient::setPTTKey(std::string &key)
-{
-	if(key == "MiddleMouse")
-	{
-		mPTTIsMiddleMouse = true;
-	}
-	else
-	{
-		mPTTIsMiddleMouse = false;
-		if(!LLKeyboard::keyFromString(key, &mPTTKey))
-		{
-			// If the call failed, don't match any key.
-			key = KEY_NONE;
-		}
-	}
-}
-
-void LLVivoxVoiceClient::setEarLocation(S32 loc)
-{
-	if(mEarLocation != loc)
-	{
-		LL_DEBUGS("Voice") << "Setting mEarLocation to " << loc << LL_ENDL;
-		
-		mEarLocation = loc;
-		mSpatialCoordsDirty = true;
-	}
-}
-
-void LLVivoxVoiceClient::setVoiceVolume(F32 volume)
-{
-	int scaled_volume = scale_speaker_volume(volume);	
-
-	if(scaled_volume != mSpeakerVolume)
-	{
-	  int min_volume = scale_speaker_volume(0);
-		if((scaled_volume == min_volume) || (mSpeakerVolume == min_volume))
-		{
-			mSpeakerMuteDirty = true;
-		}
-
-		mSpeakerVolume = scaled_volume;
-		mSpeakerVolumeDirty = true;
-	}
-}
-
-void LLVivoxVoiceClient::setMicGain(F32 volume)
-{
-	int scaled_volume = scale_mic_volume(volume);
-	
-	if(scaled_volume != mMicVolume)
-	{
-		mMicVolume = scaled_volume;
-		mMicVolumeDirty = true;
-	}
-}
-
-void LLVivoxVoiceClient::keyDown(KEY key, MASK mask)
-{	
-	if (gKeyboard->getKeyRepeated(key))
-	{
-		// ignore auto-repeat keys                                                                         
-		return;
-	}
-	
-	if(!mPTTIsMiddleMouse)
-	{
-		bool down = (mPTTKey != KEY_NONE)
-		&& gKeyboard->getKeyDown(mPTTKey);
-		inputUserControlState(down);
-	}
-	
-	
-}
-void LLVivoxVoiceClient::keyUp(KEY key, MASK mask)
-{
-	if(!mPTTIsMiddleMouse)
-	{
-		bool down = (mPTTKey != KEY_NONE)
-		&& gKeyboard->getKeyDown(mPTTKey);
-		inputUserControlState(down);
-	}
-	
-}
-void LLVivoxVoiceClient::middleMouseState(bool down)
-{
-	if(mPTTIsMiddleMouse)
-	{
-        if(mPTTIsMiddleMouse)
-        {
-			inputUserControlState(down);
-        }		
-	}
-}
-
-/////////////////////////////
-// Accessors for data related to nearby speakers
-BOOL LLVivoxVoiceClient::getVoiceEnabled(const LLUUID& id)
-{
-	BOOL result = FALSE;
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		// I'm not sure what the semantics of this should be.
-		// For now, if we have any data about the user that came through the chat channel, assume they're voice-enabled.
-		result = TRUE;
-	}
-	
-	return result;
-}
-
-std::string LLVivoxVoiceClient::getDisplayName(const LLUUID& id)
-{
-	std::string result;
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		result = participant->mDisplayName;
-	}
-	
-	return result;
-}
-
-
-
-BOOL LLVivoxVoiceClient::getIsSpeaking(const LLUUID& id)
-{
-	BOOL result = FALSE;
-
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		if (participant->mSpeakingTimeout.getElapsedTimeF32() > SPEAKING_TIMEOUT)
-		{
-			participant->mIsSpeaking = FALSE;
-		}
-		result = participant->mIsSpeaking;
-	}
-	
-	return result;
-}
-
-BOOL LLVivoxVoiceClient::getIsModeratorMuted(const LLUUID& id)
-{
-	BOOL result = FALSE;
-
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		result = participant->mIsModeratorMuted;
-	}
-	
-	return result;
-}
-
-F32 LLVivoxVoiceClient::getCurrentPower(const LLUUID& id)
-{		
-	F32 result = 0;
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		result = participant->mPower;
-	}
-	
-	return result;
-}
-
-
-
-BOOL LLVivoxVoiceClient::getUsingPTT(const LLUUID& id)
-{
-	BOOL result = FALSE;
-
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		// I'm not sure what the semantics of this should be.
-		// Does "using PTT" mean they're configured with a push-to-talk button?
-		// For now, we know there's no PTT mechanism in place, so nobody is using it.
-	}
-	
-	return result;
-}
-
-BOOL LLVivoxVoiceClient::getOnMuteList(const LLUUID& id)
-{
-	BOOL result = FALSE;
-	
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		result = participant->mOnMuteList;
-	}
-
-	return result;
-}
-
-// External accessiors. Maps 0.0 to 1.0 to internal values 0-400 with .5 == 100
-// internal = 400 * external^2
-F32 LLVivoxVoiceClient::getUserVolume(const LLUUID& id)
-{
-	F32 result = 0.0f;
-	
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		S32 ires = 100; // nominal default volume
-		
-		if(participant->mIsSelf)
-		{
-			// Always make it look like the user's own volume is set at the default.
-		}
-		else if(participant->mUserVolume != -1)
-		{
-			// Use the internal volume
-			ires = participant->mUserVolume;
-			
-			// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
-//			LL_DEBUGS("Voice") << "mapping from mUserVolume " << ires << LL_ENDL;
-		}
-		else if(participant->mVolume != -1)
-		{
-			// Map backwards from vivox volume 
-
-			// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
-//			LL_DEBUGS("Voice") << "mapping from mVolume " << participant->mVolume << LL_ENDL;
-
-			if(participant->mVolume < 56)
-			{
-				ires = (participant->mVolume * 100) / 56;
-			}
-			else
-			{
-				ires = (((participant->mVolume - 56) * 300) / (100 - 56)) + 100;
-			}
-		}
-		result = sqrtf(((F32)ires) / 400.f);
-	}
-
-	// Enable this when debugging voice slider issues.  It's way to spammy even for debug-level logging.
-//	LL_DEBUGS("Voice") << "returning " << result << LL_ENDL;
-
-	return result;
-}
-
-void LLVivoxVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
-{
-	if(mAudioSession)
-	{
-		participantState *participant = findParticipantByID(id);
-		if (participant)
-		{
-			// store this volume setting for future sessions
-			LLSpeakerVolumeStorage::getInstance()->storeSpeakerVolume(id, volume);
-			// volume can amplify by as much as 4x!
-			S32 ivol = (S32)(400.f * volume * volume);
-			participant->mUserVolume = llclamp(ivol, 0, 400);
-			participant->mVolumeDirty = TRUE;
-			mAudioSession->mVolumeDirty = TRUE;
-
-		}
-	}
-}
-
-std::string LLVivoxVoiceClient::getGroupID(const LLUUID& id)
-{
-	std::string result;
-
-	participantState *participant = findParticipantByID(id);
-	if(participant)
-	{
-		result = participant->mGroupID;
-	}
-	
-	return result;
-}
-
-BOOL LLVivoxVoiceClient::getAreaVoiceDisabled()
-{
-	return mAreaVoiceDisabled;
-}
-
-void LLVivoxVoiceClient::recordingLoopStart(int seconds, int deltaFramesPerControlFrame)
-{
-//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Start)" << LL_ENDL;
-	
-	if(!mMainSessionGroupHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
-		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
-		<< "<RecordingControlType>Start</RecordingControlType>" 
-		<< "<DeltaFramesPerControlFrame>" << deltaFramesPerControlFrame << "</DeltaFramesPerControlFrame>"
-		<< "<Filename>" << "" << "</Filename>"
-		<< "<EnableAudioRecordingEvents>false</EnableAudioRecordingEvents>"
-		<< "<LoopModeDurationSeconds>" << seconds << "</LoopModeDurationSeconds>"
-		<< "</Request>\n\n\n";
-
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::recordingLoopSave(const std::string& filename)
-{
-//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Flush)" << LL_ENDL;
-
-	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
-		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
-		<< "<RecordingControlType>Flush</RecordingControlType>" 
-		<< "<Filename>" << filename << "</Filename>"
-		<< "</Request>\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::recordingStop()
-{
-//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Stop)" << LL_ENDL;
-
-	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
-		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
-		<< "<RecordingControlType>Stop</RecordingControlType>" 
-		<< "</Request>\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::filePlaybackStart(const std::string& filename)
-{
-//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Start)" << LL_ENDL;
-
-	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
-		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
-		<< "<RecordingControlType>Start</RecordingControlType>" 
-		<< "<Filename>" << filename << "</Filename>"
-		<< "</Request>\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::filePlaybackStop()
-{
-//	LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Stop)" << LL_ENDL;
-
-	if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-	{
-		std::ostringstream stream;
-		stream
-		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
-		<< "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
-		<< "<RecordingControlType>Stop</RecordingControlType>" 
-		<< "</Request>\n\n\n";
-
-		writeString(stream.str());
-	}
-}
-
-void LLVivoxVoiceClient::filePlaybackSetPaused(bool paused)
-{
-	// TODO: Implement once Vivox gives me a sample
-}
-
-void LLVivoxVoiceClient::filePlaybackSetMode(bool vox, float speed)
-{
-	// TODO: Implement once Vivox gives me a sample
-}
-
-LLVivoxVoiceClient::sessionState::sessionState() :
-        mErrorStatusCode(0),
-	mMediaStreamState(streamStateUnknown),
-	mTextStreamState(streamStateUnknown),
-	mCreateInProgress(false),
-	mMediaConnectInProgress(false),
-	mVoiceInvitePending(false),
-	mTextInvitePending(false),
-	mSynthesizedCallerID(false),
-	mIsChannel(false),
-	mIsSpatial(false),
-	mIsP2P(false),
-	mIncoming(false),
-	mVoiceEnabled(false),
-	mReconnect(false),
-	mVolumeDirty(false),
-	mParticipantsChanged(false)
-{
-}
-
-LLVivoxVoiceClient::sessionState::~sessionState()
-{
-	removeAllParticipants();
-}
-
-bool LLVivoxVoiceClient::sessionState::isCallBackPossible()
-{
-	// This may change to be explicitly specified by vivox in the future...
-	// Currently, only PSTN P2P calls cannot be returned.
-	// Conveniently, this is also the only case where we synthesize a caller UUID.
-	return !mSynthesizedCallerID;
-}
-
-bool LLVivoxVoiceClient::sessionState::isTextIMPossible()
-{
-	// This may change to be explicitly specified by vivox in the future...
-	return !mSynthesizedCallerID;
-}
-
-
-LLVivoxVoiceClient::sessionIterator LLVivoxVoiceClient::sessionsBegin(void)
-{
-	return mSessions.begin();
-}
-
-LLVivoxVoiceClient::sessionIterator LLVivoxVoiceClient::sessionsEnd(void)
-{
-	return mSessions.end();
-}
-
-
-LLVivoxVoiceClient::sessionState *LLVivoxVoiceClient::findSession(const std::string &handle)
-{
-	sessionState *result = NULL;
-	sessionMap::iterator iter = mSessionsByHandle.find(handle);
-	if(iter != mSessionsByHandle.end())
-	{
-		result = iter->second;
-	}
-	
-	return result;
-}
-
-LLVivoxVoiceClient::sessionState *LLVivoxVoiceClient::findSessionBeingCreatedByURI(const std::string &uri)
-{	
-	sessionState *result = NULL;
-	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-	{
-		sessionState *session = *iter;
-		if(session->mCreateInProgress && (session->mSIPURI == uri))
-		{
-			result = session;
-			break;
-		}
-	}
-	
-	return result;
-}
-
-LLVivoxVoiceClient::sessionState *LLVivoxVoiceClient::findSession(const LLUUID &participant_id)
-{
-	sessionState *result = NULL;
-	
-	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-	{
-		sessionState *session = *iter;
-		if((session->mCallerID == participant_id) || (session->mIMSessionID == participant_id))
-		{
-			result = session;
-			break;
-		}
-	}
-	
-	return result;
-}
-
-LLVivoxVoiceClient::sessionState *LLVivoxVoiceClient::addSession(const std::string &uri, const std::string &handle)
-{
-	sessionState *result = NULL;
-	
-	if(handle.empty())
-	{
-		// No handle supplied.
-		// Check whether there's already a session with this URI
-		for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-		{
-			sessionState *s = *iter;
-			if((s->mSIPURI == uri) || (s->mAlternateSIPURI == uri))
-			{
-				// TODO: I need to think about this logic... it's possible that this case should raise an internal error.
-				result = s;
-				break;
-			}
-		}
-	}
-	else // (!handle.empty())
-	{
-		// Check for an existing session with this handle
-		sessionMap::iterator iter = mSessionsByHandle.find(handle);
-		
-		if(iter != mSessionsByHandle.end())
-		{
-			result = iter->second;
-		}
-	}
-
-	if(!result)
-	{
-		// No existing session found.
-		
-		LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL;
-		result = new sessionState();
-		result->mSIPURI = uri;
-		result->mHandle = handle;
-		
-		mSessions.insert(result);
-
-		if(!result->mHandle.empty())
-		{
-			mSessionsByHandle.insert(sessionMap::value_type(result->mHandle, result));
-		}
-	}
-	else
-	{
-		// Found an existing session
-		
-		if(uri != result->mSIPURI)
-		{
-			// TODO: Should this be an internal error?
-			LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL;
-			setSessionURI(result, uri);
-		}
-
-		if(handle != result->mHandle)
-		{
-			if(handle.empty())
-			{
-				// There's at least one race condition where where addSession was clearing an existing session handle, which caused things to break.
-				LL_DEBUGS("Voice") << "NOT clearing handle " << result->mHandle << LL_ENDL;
-			}
-			else
-			{
-				// TODO: Should this be an internal error?
-				LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL;
-				setSessionHandle(result, handle);
-			}
-		}
-		
-		LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL;
-	}
-
-	verifySessionState();
-		
-	return result;
-}
-
-void LLVivoxVoiceClient::setSessionHandle(sessionState *session, const std::string &handle)
-{
-	// Have to remove the session from the handle-indexed map before changing the handle, or things will break badly.
-	
-	if(!session->mHandle.empty())
-	{
-		// Remove session from the map if it should have been there.
-		sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
-		if(iter != mSessionsByHandle.end())
-		{
-			if(iter->second != session)
-			{
-				LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL;
-			}
-
-			mSessionsByHandle.erase(iter);
-		}
-		else
-		{
-			LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL;
-		}
-	}
-			
-	session->mHandle = handle;
-
-	if(!handle.empty())
-	{
-		mSessionsByHandle.insert(sessionMap::value_type(session->mHandle, session));
-	}
-
-	verifySessionState();
-}
-
-void LLVivoxVoiceClient::setSessionURI(sessionState *session, const std::string &uri)
-{
-	// There used to be a map of session URIs to sessions, which made this complex....
-	session->mSIPURI = uri;
-
-	verifySessionState();
-}
-
-void LLVivoxVoiceClient::deleteSession(sessionState *session)
-{
-	// Remove the session from the handle map
-	if(!session->mHandle.empty())
-	{
-		sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
-		if(iter != mSessionsByHandle.end())
-		{
-			if(iter->second != session)
-			{
-				LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL;
-			}
-			mSessionsByHandle.erase(iter);
-		}
-	}
-
-	// Remove the session from the URI map
-	mSessions.erase(session);
-	
-	// At this point, the session should be unhooked from all lists and all state should be consistent.
-	verifySessionState();
-
-	// If this is the current audio session, clean up the pointer which will soon be dangling.
-	if(mAudioSession == session)
-	{
-		mAudioSession = NULL;
-		mAudioSessionChanged = true;
-	}
-
-	// ditto for the next audio session
-	if(mNextAudioSession == session)
-	{
-		mNextAudioSession = NULL;
-	}
-
-	// delete the session
-	delete session;
-}
-
-void LLVivoxVoiceClient::deleteAllSessions()
-{
-	LL_DEBUGS("Voice") << "called" << LL_ENDL;
-
-	while(!mSessions.empty())
-	{
-		deleteSession(*(sessionsBegin()));
-	}
-	
-	if(!mSessionsByHandle.empty())
-	{
-		LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL;
-	}
-}
-
-void LLVivoxVoiceClient::verifySessionState(void)
-{
-	// This is mostly intended for debugging problems with session state management.
-	LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL;
-
-	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-	{
-		sessionState *session = *iter;
-
-		LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL;
-		
-		if(!session->mHandle.empty())
-		{
-			// every session with a non-empty handle needs to be in the handle map
-			sessionMap::iterator i2 = mSessionsByHandle.find(session->mHandle);
-			if(i2 == mSessionsByHandle.end())
-			{
-				LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL;
-			}
-			else
-			{
-				if(i2->second != session)
-				{
-					LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL;
-				}
-			}
-		}
-	}
-		
-	// check that every entry in the handle map points to a valid session in the session set
-	for(sessionMap::iterator iter = mSessionsByHandle.begin(); iter != mSessionsByHandle.end(); iter++)
-	{
-		sessionState *session = iter->second;
-		sessionIterator i2 = mSessions.find(session);
-		if(i2 == mSessions.end())
-		{
-			LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL;
-		}
-		else
-		{
-			if(session->mHandle != (*i2)->mHandle)
-			{
-				LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL;
-			}
-		}
-	}
-}
-
-LLVivoxVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
-	mURI(uri)
-{
-	mOnlineSL = false;
-	mOnlineSLim = false;
-	mCanSeeMeOnline = true;
-	mHasBlockListEntry = false;
-	mHasAutoAcceptListEntry = false;
-	mNameResolved = false;
-	mInVivoxBuddies = false;
-	mInSLFriends = false;
-	mNeedsNameUpdate = false;
-}
-
-void LLVivoxVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
-{
-	buddyListEntry *buddy = addBuddy(uri, displayName);
-	buddy->mInVivoxBuddies = true;	
-}
-
-LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::addBuddy(const std::string &uri)
-{
-	std::string empty;
-	buddyListEntry *buddy = addBuddy(uri, empty);
-	if(buddy->mDisplayName.empty())
-	{
-		buddy->mNameResolved = false;
-	}
-	return buddy;
-}
-
-LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::addBuddy(const std::string &uri, const std::string &displayName)
-{
-	buddyListEntry *result = NULL;
-	buddyListMap::iterator iter = mBuddyListMap.find(uri);
-	
-	if(iter != mBuddyListMap.end())
-	{
-		// Found a matching buddy already in the map.
-		LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
-		result = iter->second;
-	}
-
-	if(!result)
-	{
-		// participant isn't already in one list or the other.
-		LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
-		result = new buddyListEntry(uri);
-		result->mDisplayName = displayName;
-
-		if(IDFromName(uri, result->mUUID)) 
-		{
-			// Extracted UUID from name successfully.
-		}
-		else
-		{
-			LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
-		}
-
-		mBuddyListMap.insert(buddyListMap::value_type(result->mURI, result));
-	}
-	
-	return result;
-}
-
-LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::findBuddy(const std::string &uri)
-{
-	buddyListEntry *result = NULL;
-	buddyListMap::iterator iter = mBuddyListMap.find(uri);
-	if(iter != mBuddyListMap.end())
-	{
-		result = iter->second;
-	}
-	
-	return result;
-}
-
-LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::findBuddy(const LLUUID &id)
-{
-	buddyListEntry *result = NULL;
-	buddyListMap::iterator iter;
-
-	for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
-	{
-		if(iter->second->mUUID == id)
-		{
-			result = iter->second;
-			break;
-		}
-	}
-	
-	return result;
-}
-
-LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::findBuddyByDisplayName(const std::string &name)
-{
-	buddyListEntry *result = NULL;
-	buddyListMap::iterator iter;
-
-	for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
-	{
-		if(iter->second->mDisplayName == name)
-		{
-			result = iter->second;
-			break;
-		}
-	}
-	
-	return result;
-}
-
-void LLVivoxVoiceClient::deleteBuddy(const std::string &uri)
-{
-	buddyListMap::iterator iter = mBuddyListMap.find(uri);
-	if(iter != mBuddyListMap.end())
-	{
-		LL_DEBUGS("Voice") << "deleting buddy " << uri << LL_ENDL;
-		buddyListEntry *buddy = iter->second;
-		mBuddyListMap.erase(iter);
-		delete buddy;
-	}
-	else
-	{
-		LL_DEBUGS("Voice") << "attempt to delete nonexistent buddy " << uri << LL_ENDL;
-	}
-	
-}
-
-void LLVivoxVoiceClient::deleteAllBuddies(void)
-{
-	while(!mBuddyListMap.empty())
-	{
-		deleteBuddy(mBuddyListMap.begin()->first);
-	}
-	
-	// Don't want to correlate with friends list when we've emptied the buddy list.
-	mBuddyListMapPopulated = false;
-	
-	// Don't want to correlate with friends list when we've reset the block rules.
-	mBlockRulesListReceived = false;
-	mAutoAcceptRulesListReceived = false;
-}
-
-void LLVivoxVoiceClient::deleteAllBlockRules(void)
-{
-	// Clear the block list entry flags from all local buddy list entries
-	buddyListMap::iterator buddy_it;
-	for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
-	{
-		buddy_it->second->mHasBlockListEntry = false;
-	}
-}
-
-void LLVivoxVoiceClient::deleteAllAutoAcceptRules(void)
-{
-	// Clear the auto-accept list entry flags from all local buddy list entries
-	buddyListMap::iterator buddy_it;
-	for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
-	{
-		buddy_it->second->mHasAutoAcceptListEntry = false;
-	}
-}
-
-void LLVivoxVoiceClient::addBlockRule(const std::string &blockMask, const std::string &presenceOnly)
-{
-	buddyListEntry *buddy = NULL;
-
-	// blockMask is the SIP URI of a friends list entry
-	buddyListMap::iterator iter = mBuddyListMap.find(blockMask);
-	if(iter != mBuddyListMap.end())
-	{
-		LL_DEBUGS("Voice") << "block list entry for " << blockMask << LL_ENDL;
-		buddy = iter->second;
-	}
-
-	if(buddy == NULL)
-	{
-		LL_DEBUGS("Voice") << "block list entry for unknown buddy " << blockMask << LL_ENDL;
-		buddy = addBuddy(blockMask);
-	}
-	
-	if(buddy != NULL)
-	{
-		buddy->mHasBlockListEntry = true;
-	}
-}
-
-void LLVivoxVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy)
-{
-	buddyListEntry *buddy = NULL;
-
-	// blockMask is the SIP URI of a friends list entry
-	buddyListMap::iterator iter = mBuddyListMap.find(autoAcceptMask);
-	if(iter != mBuddyListMap.end())
-	{
-		LL_DEBUGS("Voice") << "auto-accept list entry for " << autoAcceptMask << LL_ENDL;
-		buddy = iter->second;
-	}
-
-	if(buddy == NULL)
-	{
-		LL_DEBUGS("Voice") << "auto-accept list entry for unknown buddy " << autoAcceptMask << LL_ENDL;
-		buddy = addBuddy(autoAcceptMask);
-	}
-
-	if(buddy != NULL)
-	{
-		buddy->mHasAutoAcceptListEntry = true;
-	}
-}
-
-void LLVivoxVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
-{
-	// Block list entries were updated via addBlockRule() during parsing.  Just flag that we're done.
-	mBlockRulesListReceived = true;
-}
-
-void LLVivoxVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString)
-{
-	// Block list entries were updated via addBlockRule() during parsing.  Just flag that we're done.
-	mAutoAcceptRulesListReceived = true;
-}
-
-void LLVivoxVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
-{
-	mParticipantObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
-{
-	mParticipantObservers.erase(observer);
-}
-
-void LLVivoxVoiceClient::notifyParticipantObservers()
-{
-	for (observer_set_t::iterator it = mParticipantObservers.begin();
-		it != mParticipantObservers.end();
-		)
-	{
-		LLVoiceClientParticipantObserver* observer = *it;
-		observer->onChange();
-		// In case onChange() deleted an entry.
-		it = mParticipantObservers.upper_bound(observer);
-	}
-}
-
-void LLVivoxVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
-{
-	mStatusObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
-{
-	mStatusObservers.erase(observer);
-}
-
-void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status)
-{
-	if(mAudioSession)
-	{
-		if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
-		{
-			switch(mAudioSession->mErrorStatusCode)
-			{
-				case 20713:		status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; 		break;
-				case 20714:		status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; 	break;
-				case 20715:
-					//invalid channel, we may be using a set of poorly cached
-					//info
-					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-					break;
-				case 1009:
-					//invalid username and password
-					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-					break;
-			}
-
-			// Reset the error code to make sure it won't be reused later by accident.
-			mAudioSession->mErrorStatusCode = 0;
-		}
-		else if(status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL)
-		{
-			switch(mAudioSession->mErrorStatusCode)
-			{
-				case 404:	// NOT_FOUND
-				case 480:	// TEMPORARILY_UNAVAILABLE
-				case 408:	// REQUEST_TIMEOUT
-					// call failed because other user was not available
-					// treat this as an error case
-					status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-
-					// Reset the error code to make sure it won't be reused later by accident.
-					mAudioSession->mErrorStatusCode = 0;
-				break;
-			}
-		}
-	}
-		
-	LL_DEBUGS("Voice") 
-		<< " " << LLVoiceClientStatusObserver::status2string(status)  
-		<< ", session URI " << getAudioSessionURI() 
-		<< (inSpatialChannel()?", proximal is true":", proximal is false")
-	<< LL_ENDL;
-
-	for (status_observer_set_t::iterator it = mStatusObservers.begin();
-		it != mStatusObservers.end();
-		)
-	{
-		LLVoiceClientStatusObserver* observer = *it;
-		observer->onChange(status, getAudioSessionURI(), inSpatialChannel());
-		// In case onError() deleted an entry.
-		it = mStatusObservers.upper_bound(observer);
-	}
-
-}
-
-void LLVivoxVoiceClient::addObserver(LLFriendObserver* observer)
-{
-	mFriendObservers.insert(observer);
-}
-
-void LLVivoxVoiceClient::removeObserver(LLFriendObserver* observer)
-{
-	mFriendObservers.erase(observer);
-}
-
-void LLVivoxVoiceClient::notifyFriendObservers()
-{
-	for (friend_observer_set_t::iterator it = mFriendObservers.begin();
-		it != mFriendObservers.end();
-		)
-	{
-		LLFriendObserver* observer = *it;
-		it++;
-		// The only friend-related thing we notify on is online/offline transitions.
-		observer->changed(LLFriendObserver::ONLINE);
-	}
-}
-
-void LLVivoxVoiceClient::lookupName(const LLUUID &id)
-{
-	BOOL is_group = FALSE;
-	gCacheName->get(id, is_group, &LLVivoxVoiceClient::onAvatarNameLookup);
-}
-
-//static
-void LLVivoxVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
-{
-		std::string name = llformat("%s %s", first.c_str(), last.c_str());
-		LLVivoxVoiceClient::getInstance()->avatarNameResolved(id, name);
-	
-}
-
-void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
-{
-	// If the avatar whose name just resolved is on our friends list, resync the friends list.
-	if(LLAvatarTracker::instance().getBuddyInfo(id) != NULL)
-	{
-		mFriendsListDirty = true;
-	}
-	
-	// Iterate over all sessions.
-	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-	{
-		sessionState *session = *iter;
-
-		// Check for this user as a participant in this session
-		participantState *participant = session->findParticipantByID(id);
-		if(participant)
-		{
-			// Found -- fill in the name
-			participant->mAccountName = name;
-			// and post a "participants updated" message to listeners later.
-			session->mParticipantsChanged = true;
-		}
-		
-		// Check whether this is a p2p session whose caller name just resolved
-		if(session->mCallerID == id)
-		{
-			// this session's "caller ID" just resolved.  Fill in the name.
-			session->mName = name;
-			if(session->mTextInvitePending)
-			{
-				session->mTextInvitePending = false;
-
-				// We don't need to call gIMMgr->addP2PSession() here.  The first incoming message will create the panel.				
-			}
-			if(session->mVoiceInvitePending)
-			{
-				session->mVoiceInvitePending = false;
-
-				gIMMgr->inviteToSession(
-										LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID),
-										session->mName,
-										session->mCallerID, 
-										session->mName, 
-										IM_SESSION_P2P_INVITE, 
-										LLIMMgr::INVITATION_TYPE_VOICE,
-										session->mHandle);
-			}
-			
-		}
-	}
-}
-
-
-LLVivoxProtocolParser::LLVivoxProtocolParser()
-{
-	parser = NULL;
-	parser = XML_ParserCreate(NULL);
-	
-	reset();
-}
-
-void LLVivoxProtocolParser::reset()
-{
-	responseDepth = 0;
-	ignoringTags = false;
-	accumulateText = false;
-	energy = 0.f;
-	hasText = false;
-	hasAudio = false;
-	hasVideo = false;
-	terminated = false;
-	ignoreDepth = 0;
-	isChannel = false;
-	incoming = false;
-	enabled = false;
-	isEvent = false;
-	isLocallyMuted = false;
-	isModeratorMuted = false;
-	isSpeaking = false;
-	participantType = 0;
-	squelchDebugOutput = false;
-	returnCode = -1;
-	state = 0;
-	statusCode = 0;
-	volume = 0;
-	textBuffer.clear();
-	alias.clear();
-	numberOfAliases = 0;
-	applicationString.clear();
-}
-
-//virtual 
-LLVivoxProtocolParser::~LLVivoxProtocolParser()
-{
-	if (parser)
-		XML_ParserFree(parser);
-}
-
-// virtual
-LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
-													  const LLChannelDescriptors& channels,
-													  buffer_ptr_t& buffer,
-													  bool& eos,
-													  LLSD& context,
-													  LLPumpIO* pump)
-{
-	LLBufferStream istr(channels, buffer.get());
-	std::ostringstream ostr;
-	while (istr.good())
-	{
-		char buf[1024];
-		istr.read(buf, sizeof(buf));
-		mInput.append(buf, istr.gcount());
-	}
-	
-	// Look for input delimiter(s) in the input buffer.  If one is found, send the message to the xml parser.
-	int start = 0;
-	int delim;
-	while((delim = mInput.find("\n\n\n", start)) != std::string::npos)
-	{	
-		
-		// Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser)
-		reset();
-		
-		XML_ParserReset(parser, NULL);
-		XML_SetElementHandler(parser, ExpatStartTag, ExpatEndTag);
-		XML_SetCharacterDataHandler(parser, ExpatCharHandler);
-		XML_SetUserData(parser, this);	
-		XML_Parse(parser, mInput.data() + start, delim - start, false);
-		
-		// If this message isn't set to be squelched, output the raw XML received.
-		if(!squelchDebugOutput)
-		{
-			LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
-		}
-		
-		start = delim + 3;
-	}
-	
-	if(start != 0)
-		mInput = mInput.substr(start);
-	
-	LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL;
-	
-	if(!LLVivoxVoiceClient::getInstance()->mConnected)
-	{
-		// If voice has been disabled, we just want to close the socket.  This does so.
-		LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL;
-		return STATUS_STOP;
-	}
-	
-	return STATUS_OK;
-}
-
-void XMLCALL LLVivoxProtocolParser::ExpatStartTag(void *data, const char *el, const char **attr)
-{
-	if (data)
-	{
-		LLVivoxProtocolParser	*object = (LLVivoxProtocolParser*)data;
-		object->StartTag(el, attr);
-	}
-}
-
-// --------------------------------------------------------------------------------
-
-void XMLCALL LLVivoxProtocolParser::ExpatEndTag(void *data, const char *el)
-{
-	if (data)
-	{
-		LLVivoxProtocolParser	*object = (LLVivoxProtocolParser*)data;
-		object->EndTag(el);
-	}
-}
-
-// --------------------------------------------------------------------------------
-
-void XMLCALL LLVivoxProtocolParser::ExpatCharHandler(void *data, const XML_Char *s, int len)
-{
-	if (data)
-	{
-		LLVivoxProtocolParser	*object = (LLVivoxProtocolParser*)data;
-		object->CharData(s, len);
-	}
-}
-
-// --------------------------------------------------------------------------------
-
-
-void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
-{
-	// Reset the text accumulator. We shouldn't have strings that are inturrupted by new tags
-	textBuffer.clear();
-	// only accumulate text if we're not ignoring tags.
-	accumulateText = !ignoringTags;
-	
-	if (responseDepth == 0)
-	{	
-		isEvent = !stricmp("Event", tag);
-		
-		if (!stricmp("Response", tag) || isEvent)
-		{
-			// Grab the attributes
-			while (*attr)
-			{
-				const char	*key = *attr++;
-				const char	*value = *attr++;
-				
-				if (!stricmp("requestId", key))
-				{
-					requestId = value;
-				}
-				else if (!stricmp("action", key))
-				{
-					actionString = value;
-				}
-				else if (!stricmp("type", key))
-				{
-					eventTypeString = value;
-				}
-			}
-		}
-		LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")"  << LL_ENDL;
-	}
-	else
-	{
-		if (ignoringTags)
-		{
-			LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-		}
-		else
-		{
-			LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")"  << LL_ENDL;
-			
-			// Ignore the InputXml stuff so we don't get confused
-			if (!stricmp("InputXml", tag))
-			{
-				ignoringTags = true;
-				ignoreDepth = responseDepth;
-				accumulateText = false;
-				
-				LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
-			}
-			else if (!stricmp("CaptureDevices", tag))
-			{
-				LLVivoxVoiceClient::getInstance()->clearCaptureDevices();
-			}			
-			else if (!stricmp("RenderDevices", tag))
-			{
-				LLVivoxVoiceClient::getInstance()->clearRenderDevices();
-			}
-			else if (!stricmp("CaptureDevice", tag))
-			{
-				deviceString.clear();
-			}
-			else if (!stricmp("RenderDevice", tag))
-			{
-				deviceString.clear();
-			}			
-			else if (!stricmp("Buddies", tag))
-			{
-				LLVivoxVoiceClient::getInstance()->deleteAllBuddies();
-			}
-			else if (!stricmp("BlockRules", tag))
-			{
-				LLVivoxVoiceClient::getInstance()->deleteAllBlockRules();
-			}
-			else if (!stricmp("AutoAcceptRules", tag))
-			{
-				LLVivoxVoiceClient::getInstance()->deleteAllAutoAcceptRules();
-			}
-			
-		}
-	}
-	responseDepth++;
-}
-
-// --------------------------------------------------------------------------------
-
-void LLVivoxProtocolParser::EndTag(const char *tag)
-{
-	const std::string& string = textBuffer;
-	
-	responseDepth--;
-	
-	if (ignoringTags)
-	{
-		if (ignoreDepth == responseDepth)
-		{
-			LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL;
-			ignoringTags = false;
-		}
-		else
-		{
-			LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-		}
-	}
-	
-	if (!ignoringTags)
-	{
-		LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-		
-		// Closing a tag. Finalize the text we've accumulated and reset
-		if (!stricmp("ReturnCode", tag))
-			returnCode = strtol(string.c_str(), NULL, 10);
-		else if (!stricmp("SessionHandle", tag))
-			sessionHandle = string;
-		else if (!stricmp("SessionGroupHandle", tag))
-			sessionGroupHandle = string;
-		else if (!stricmp("StatusCode", tag))
-			statusCode = strtol(string.c_str(), NULL, 10);
-		else if (!stricmp("StatusString", tag))
-			statusString = string;
-		else if (!stricmp("ParticipantURI", tag))
-			uriString = string;
-		else if (!stricmp("Volume", tag))
-			volume = strtol(string.c_str(), NULL, 10);
-		else if (!stricmp("Energy", tag))
-			energy = (F32)strtod(string.c_str(), NULL);
-		else if (!stricmp("IsModeratorMuted", tag))
-			isModeratorMuted = !stricmp(string.c_str(), "true");
-		else if (!stricmp("IsSpeaking", tag))
-			isSpeaking = !stricmp(string.c_str(), "true");
-		else if (!stricmp("Alias", tag))
-			alias = string;
-		else if (!stricmp("NumberOfAliases", tag))
-			numberOfAliases = strtol(string.c_str(), NULL, 10);
-		else if (!stricmp("Application", tag))
-			applicationString = string;
-		else if (!stricmp("ConnectorHandle", tag))
-			connectorHandle = string;
-		else if (!stricmp("VersionID", tag))
-			versionID = string;
-		else if (!stricmp("AccountHandle", tag))
-			accountHandle = string;
-		else if (!stricmp("State", tag))
-			state = strtol(string.c_str(), NULL, 10);
-		else if (!stricmp("URI", tag))
-			uriString = string;
-		else if (!stricmp("IsChannel", tag))
-			isChannel = !stricmp(string.c_str(), "true");
-		else if (!stricmp("Incoming", tag))
-			incoming = !stricmp(string.c_str(), "true");
-		else if (!stricmp("Enabled", tag))
-			enabled = !stricmp(string.c_str(), "true");
-		else if (!stricmp("Name", tag))
-			nameString = string;
-		else if (!stricmp("AudioMedia", tag))
-			audioMediaString = string;
-		else if (!stricmp("ChannelName", tag))
-			nameString = string;
-		else if (!stricmp("DisplayName", tag))
-			displayNameString = string;
-		else if (!stricmp("Device", tag))
-			deviceString = string;		
-		else if (!stricmp("AccountName", tag))
-			nameString = string;
-		else if (!stricmp("ParticipantType", tag))
-			participantType = strtol(string.c_str(), NULL, 10);
-		else if (!stricmp("IsLocallyMuted", tag))
-			isLocallyMuted = !stricmp(string.c_str(), "true");
-		else if (!stricmp("MicEnergy", tag))
-			energy = (F32)strtod(string.c_str(), NULL);
-		else if (!stricmp("ChannelName", tag))
-			nameString = string;
-		else if (!stricmp("ChannelURI", tag))
-			uriString = string;
-		else if (!stricmp("BuddyURI", tag))
-			uriString = string;
-		else if (!stricmp("Presence", tag))
-			statusString = string;
-		else if (!stricmp("CaptureDevice", tag))
-		{
-			LLVivoxVoiceClient::getInstance()->addCaptureDevice(deviceString);
-		}
-		else if (!stricmp("RenderDevice", tag))
-		{
-			LLVivoxVoiceClient::getInstance()->addRenderDevice(deviceString);
-		}
-		else if (!stricmp("Buddy", tag))
-		{
-			LLVivoxVoiceClient::getInstance()->processBuddyListEntry(uriString, displayNameString);
-		}
-		else if (!stricmp("BlockRule", tag))
-		{
-			LLVivoxVoiceClient::getInstance()->addBlockRule(blockMask, presenceOnly);
-		}
-		else if (!stricmp("BlockMask", tag))
-			blockMask = string;
-		else if (!stricmp("PresenceOnly", tag))
-			presenceOnly = string;
-		else if (!stricmp("AutoAcceptRule", tag))
-		{
-			LLVivoxVoiceClient::getInstance()->addAutoAcceptRule(autoAcceptMask, autoAddAsBuddy);
-		}
-		else if (!stricmp("AutoAcceptMask", tag))
-			autoAcceptMask = string;
-		else if (!stricmp("AutoAddAsBuddy", tag))
-			autoAddAsBuddy = string;
-		else if (!stricmp("MessageHeader", tag))
-			messageHeader = string;
-		else if (!stricmp("MessageBody", tag))
-			messageBody = string;
-		else if (!stricmp("NotificationType", tag))
-			notificationType = string;
-		else if (!stricmp("HasText", tag))
-			hasText = !stricmp(string.c_str(), "true");
-		else if (!stricmp("HasAudio", tag))
-			hasAudio = !stricmp(string.c_str(), "true");
-		else if (!stricmp("HasVideo", tag))
-			hasVideo = !stricmp(string.c_str(), "true");
-		else if (!stricmp("Terminated", tag))
-			terminated = !stricmp(string.c_str(), "true");
-		else if (!stricmp("SubscriptionHandle", tag))
-			subscriptionHandle = string;
-		else if (!stricmp("SubscriptionType", tag))
-			subscriptionType = string;
-		
-	
-		textBuffer.clear();
-		accumulateText= false;
-		
-		if (responseDepth == 0)
-		{
-			// We finished all of the XML, process the data
-			processResponse(tag);
-		}
-	}
-}
-
-// --------------------------------------------------------------------------------
-
-void LLVivoxProtocolParser::CharData(const char *buffer, int length)
-{
-	/*
-	 This method is called for anything that isn't a tag, which can be text you
-	 want that lies between tags, and a lot of stuff you don't want like file formatting
-	 (tabs, spaces, CR/LF, etc).
-	 
-	 Only copy text if we are in accumulate mode...
-	 */
-	if (accumulateText)
-		textBuffer.append(buffer, length);
-}
-
-// --------------------------------------------------------------------------------
-
-void LLVivoxProtocolParser::processResponse(std::string tag)
-{
-	LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL;
-	
-	// SLIM SDK: the SDK now returns a statusCode of "200" (OK) for success.  This is a change vs. previous SDKs.
-	// According to Mike S., "The actual API convention is that responses with return codes of 0 are successful, regardless of the status code returned",
-	// so I believe this will give correct behavior.
-	
-	if(returnCode == 0)
-		statusCode = 0;
-	
-	if (isEvent)
-	{
-		const char *eventTypeCstr = eventTypeString.c_str();
-		if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
-		{
-			LLVivoxVoiceClient::getInstance()->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state);
-		}
-		else if (!stricmp(eventTypeCstr, "SessionAddedEvent"))
-		{
-			/*
-			 <Event type="SessionAddedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
-			 <Uri>sip:confctl-1408789@bhr.vivox.com</Uri>
-			 <IsChannel>true</IsChannel>
-			 <Incoming>false</Incoming>
-			 <ChannelName />
-			 </Event>
-			 */
-			LLVivoxVoiceClient::getInstance()->sessionAddedEvent(uriString, alias, sessionHandle, sessionGroupHandle, isChannel, incoming, nameString, applicationString);
-		}
-		else if (!stricmp(eventTypeCstr, "SessionRemovedEvent"))
-		{
-			LLVivoxVoiceClient::getInstance()->sessionRemovedEvent(sessionHandle, sessionGroupHandle);
-		}
-		else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent"))
-		{
-			LLVivoxVoiceClient::getInstance()->sessionGroupAddedEvent(sessionGroupHandle);
-		}
-		else if (!stricmp(eventTypeCstr, "MediaStreamUpdatedEvent"))
-		{
-			/*
-			 <Event type="MediaStreamUpdatedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
-			 <StatusCode>200</StatusCode>
-			 <StatusString>OK</StatusString>
-			 <State>2</State>
-			 <Incoming>false</Incoming>
-			 </Event>
-			 */
-			LLVivoxVoiceClient::getInstance()->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming);
-		}		
-		else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent"))
-		{
-			/*
-			 <Event type="TextStreamUpdatedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg1</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==1</SessionHandle>
-			 <Enabled>true</Enabled>
-			 <State>1</State>
-			 <Incoming>true</Incoming>
-			 </Event>
-			 */
-			LLVivoxVoiceClient::getInstance()->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming);
-		}
-		else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent"))
-		{
-			/* 
-			 <Event type="ParticipantAddedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
-			 <ParticipantUri>sip:xI5auBZ60SJWIk606-1JGRQ==@bhr.vivox.com</ParticipantUri>
-			 <AccountName>xI5auBZ60SJWIk606-1JGRQ==</AccountName>
-			 <DisplayName />
-			 <ParticipantType>0</ParticipantType>
-			 </Event>
-			 */
-			LLVivoxVoiceClient::getInstance()->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
-		}
-		else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
-		{
-			/*
-			 <Event type="ParticipantRemovedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
-			 <ParticipantUri>sip:xtx7YNV-3SGiG7rA1fo5Ndw==@bhr.vivox.com</ParticipantUri>
-			 <AccountName>xtx7YNV-3SGiG7rA1fo5Ndw==</AccountName>
-			 </Event>
-			 */
-			LLVivoxVoiceClient::getInstance()->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
-		}
-		else if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
-		{
-			/*
-			 <Event type="ParticipantUpdatedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
-			 <ParticipantUri>sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com</ParticipantUri>
-			 <IsModeratorMuted>false</IsModeratorMuted>
-			 <IsSpeaking>true</IsSpeaking>
-			 <Volume>44</Volume>
-			 <Energy>0.0879437</Energy>
-			 </Event>
-			 */
-			
-			// These happen so often that logging them is pretty useless.
-			squelchDebugOutput = true;
-			
-			LLVivoxVoiceClient::getInstance()->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
-		}
-		else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))
-		{
-			LLVivoxVoiceClient::getInstance()->auxAudioPropertiesEvent(energy);
-		}
-		else if (!stricmp(eventTypeCstr, "BuddyPresenceEvent"))
-		{
-			LLVivoxVoiceClient::getInstance()->buddyPresenceEvent(uriString, alias, statusString, applicationString);
-		}
-		else if (!stricmp(eventTypeCstr, "BuddyAndGroupListChangedEvent"))
-		{
-			// The buddy list was updated during parsing.
-			// Need to recheck against the friends list.
-			LLVivoxVoiceClient::getInstance()->buddyListChanged();
-		}
-		else if (!stricmp(eventTypeCstr, "BuddyChangedEvent"))
-		{
-			/*
-			 <Event type="BuddyChangedEvent">
-			 <AccountHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==</AccountHandle>
-			 <BuddyURI>sip:x9fFHFZjOTN6OESF1DUPrZQ==@bhr.vivox.com</BuddyURI>
-			 <DisplayName>Monroe Tester</DisplayName>
-			 <BuddyData />
-			 <GroupID>0</GroupID>
-			 <ChangeType>Set</ChangeType>
-			 </Event>
-			 */		
-			// TODO: Question: Do we need to process this at all?
-		}
-		else if (!stricmp(eventTypeCstr, "MessageEvent"))  
-		{
-			LLVivoxVoiceClient::getInstance()->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString);
-		}
-		else if (!stricmp(eventTypeCstr, "SessionNotificationEvent"))  
-		{
-			LLVivoxVoiceClient::getInstance()->sessionNotificationEvent(sessionHandle, uriString, notificationType);
-		}
-		else if (!stricmp(eventTypeCstr, "SubscriptionEvent"))  
-		{
-			LLVivoxVoiceClient::getInstance()->subscriptionEvent(uriString, subscriptionHandle, alias, displayNameString, applicationString, subscriptionType);
-		}
-		else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))  
-		{
-			/*
-			 <Event type="SessionUpdatedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
-			 <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
-			 <Uri>sip:confctl-9@bhd.vivox.com</Uri>
-			 <IsMuted>0</IsMuted>
-			 <Volume>50</Volume>
-			 <TransmitEnabled>1</TransmitEnabled>
-			 <IsFocused>0</IsFocused>
-			 <SpeakerPosition><Position><X>0</X><Y>0</Y><Z>0</Z></Position></SpeakerPosition>
-			 <SessionFontID>0</SessionFontID>
-			 </Event>
-			 */
-			// We don't need to process this, but we also shouldn't warn on it, since that confuses people.
-		}
-		
-		else if (!stricmp(eventTypeCstr, "SessionGroupRemovedEvent"))  
-		{
-			/*
-			 <Event type="SessionGroupRemovedEvent">
-			 <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
-			 </Event>
-			 */
-			// We don't need to process this, but we also shouldn't warn on it, since that confuses people.
-		}
-		else
-		{
-			LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
-		}
-	}
-	else
-	{
-		const char *actionCstr = actionString.c_str();
-		if (!stricmp(actionCstr, "Connector.Create.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID);
-		}
-		else if (!stricmp(actionCstr, "Account.Login.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->loginResponse(statusCode, statusString, accountHandle, numberOfAliases);
-		}
-		else if (!stricmp(actionCstr, "Session.Create.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->sessionCreateResponse(requestId, statusCode, statusString, sessionHandle);			
-		}
-		else if (!stricmp(actionCstr, "SessionGroup.AddSession.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->sessionGroupAddSessionResponse(requestId, statusCode, statusString, sessionHandle);			
-		}
-		else if (!stricmp(actionCstr, "Session.Connect.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->sessionConnectResponse(requestId, statusCode, statusString);			
-		}
-		else if (!stricmp(actionCstr, "Account.Logout.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->logoutResponse(statusCode, statusString);			
-		}
-		else if (!stricmp(actionCstr, "Connector.InitiateShutdown.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->connectorShutdownResponse(statusCode, statusString);			
-		}
-		else if (!stricmp(actionCstr, "Account.ListBlockRules.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->accountListBlockRulesResponse(statusCode, statusString);						
-		}
-		else if (!stricmp(actionCstr, "Account.ListAutoAcceptRules.1"))
-		{
-			LLVivoxVoiceClient::getInstance()->accountListAutoAcceptRulesResponse(statusCode, statusString);						
-		}
-		else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
-		{
-			// We don't need to process these, but they're so spammy we don't want to log them.
-			squelchDebugOutput = true;
-		}
-		/*
-		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
-		 {
-		 LLVoiceClient::getInstance()->channelGetListResponse(statusCode, statusString);
-		 }
-		 else if (!stricmp(actionCstr, "Connector.AccountCreate.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Connector.MuteLocalMic.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Connector.MuteLocalSpeaker.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Connector.SetLocalMicVolume.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Connector.SetLocalSpeakerVolume.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Session.ListenerSetPosition.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Session.SpeakerSetPosition.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Session.AudioSourceSetPosition.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Session.GetChannelParticipants.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelCreate.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelUpdate.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelDelete.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelCreateAndInvite.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelFolderCreate.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelFolderUpdate.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelFolderDelete.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelAddModerator.1"))
-		 {
-		 
-		 }
-		 else if (!stricmp(actionCstr, "Account.ChannelDeleteModerator.1"))
-		 {
-		 
-		 }
-		 */
-	}
-}
-
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
deleted file mode 100644
index 10577254e891e5d8d49e909a3ee81492a7b3f699..0000000000000000000000000000000000000000
--- a/indra/newview/llvoicevivox.h
+++ /dev/null
@@ -1,914 +0,0 @@
-/** 
- * @file llvoicevivox.h
- * @brief Declaration of LLDiamondwareVoiceClient class which is the interface to the voice client process.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- * 
- * Copyright (c) 2001-2010, 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_VOICE_VIVOX_H
-#define LL_VOICE_VIVOX_H
-
-class LLVOAvatar;
-class LLVivoxProtocolParser;
-
-#include "lliopipe.h"
-#include "llpumpio.h"
-#include "llchainio.h"
-#include "lliosocket.h"
-#include "v3math.h"
-#include "llframetimer.h"
-#include "llviewerregion.h"
-#include "llcallingcard.h"   // for LLFriendObserver
-
-#ifdef LL_STANDALONE
-# include "expat.h"
-#else
-# include "expat/expat.h"
-#endif
-#include "llvoiceclient.h"
-
-
-class LLVivoxVoiceAccountProvisionResponder;
-class LLVivoxVoiceClientMuteListObserver;
-class LLVivoxVoiceClientFriendsObserver;	
-
-
-class LLVivoxVoiceClientParticipantObserver
-{
-public:
-	virtual ~LLVivoxVoiceClientParticipantObserver() { }
-	virtual void onChange() = 0;
-};
-
-
-class LLVivoxVoiceClient: public LLSingleton<LLVivoxVoiceClient>, virtual public LLVoiceModuleInterface
-{
-	LOG_CLASS(LLVivoxVoiceClient);
-public:
-	LLVivoxVoiceClient();	
-	virtual ~LLVivoxVoiceClient();
-	
-	
-	/// @name LLVoiceModuleInterface virtual implementations
-	///  @see LLVoiceModuleInterface
-	//@{
-	virtual void init(LLPumpIO *pump);	// Call this once at application startup (creates connector)
-	virtual void terminate();	// Call this to clean up during shutdown
-	
-	virtual const LLVoiceVersionInfo& getVersion();
-	
-	virtual void updateSettings(); // call after loading settings and whenever they change
-
-	// Returns true if vivox has successfully logged in and is not in error state	
-	virtual bool isVoiceWorking();
-
-	/////////////////////
-	/// @name Tuning
-	//@{
-	virtual void tuningStart();
-	virtual void tuningStop();
-	virtual bool inTuningMode();
-	
-	virtual void tuningSetMicVolume(float volume);
-	virtual void tuningSetSpeakerVolume(float volume);
-	virtual float tuningGetEnergy(void);
-	//@}
-	
-	/////////////////////
-	/// @name Devices
-	//@{
-	// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
-	// i.e. when the daemon is running and connected, and the device lists are populated.
-	virtual bool deviceSettingsAvailable();
-	
-	// Requery the vivox daemon for the current list of input/output devices.
-	// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
-	// (use this if you want to know when it's done).
-	// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
-	virtual void refreshDeviceLists(bool clearCurrentList = true);
-	
-	virtual void setCaptureDevice(const std::string& name);
-	virtual void setRenderDevice(const std::string& name);
-	
-	virtual LLVoiceDeviceList& getCaptureDevices();
-	virtual LLVoiceDeviceList& getRenderDevices();
-	//@}	
-	
-	virtual void getParticipantList(std::set<LLUUID> &participants);
-	virtual bool isParticipant(const LLUUID& speaker_id);
-
-	// Send a text message to the specified user, initiating the session if necessary.
-	virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message);
-	
-	// close any existing text IM session with the specified user
-	virtual void endUserIMSession(const LLUUID &uuid);
-	
-	// Returns true if calling back the session URI after the session has closed is possible.
-	// Currently this will be false only for PSTN P2P calls.		
-	// NOTE: this will return true if the session can't be found. 
-	virtual BOOL isSessionCallBackPossible(const LLUUID &session_id);
-	
-	// Returns true if the session can accepte text IM's.
-	// Currently this will be false only for PSTN P2P calls.
-	// NOTE: this will return true if the session can't be found. 
-	virtual BOOL isSessionTextIMPossible(const LLUUID &session_id);
-	
-	
-	////////////////////////////
-	/// @name Channel stuff
-	//@{
-	// returns true iff the user is currently in a proximal (local spatial) channel.
-	// Note that gestures should only fire if this returns true.
-	virtual bool inProximalChannel();
-	
-	virtual void setNonSpatialChannel(const std::string &uri,
-									  const std::string &credentials);
-	
-	virtual void setSpatialChannel(const std::string &uri,
-								   const std::string &credentials);
-	
-	virtual void leaveNonSpatialChannel();
-	
-	virtual void leaveChannel(void);	
-	
-	// Returns the URI of the current channel, or an empty string if not currently in a channel.
-	// NOTE that it will return an empty string if it's in the process of joining a channel.
-	virtual std::string getCurrentChannel();
-	//@}
-	
-	
-	//////////////////////////
-	/// @name invitations
-	//@{
-	// start a voice channel with the specified user
-	virtual void callUser(const LLUUID &uuid);	
-	virtual bool answerInvite(std::string &channelHandle);
-	virtual void declineInvite(std::string &channelHandle);
-	//@}
-	
-	/////////////////////////
-	/// @name Volume/gain
-	//@{
-	virtual void setVoiceVolume(F32 volume);
-	virtual void setMicGain(F32 volume);
-	//@}
-	
-	/////////////////////////
-	/// @name enable disable voice and features
-	//@{
-	virtual bool voiceEnabled();
-	virtual void setVoiceEnabled(bool enabled);
-	virtual BOOL lipSyncEnabled();	
-	virtual void setLipSyncEnabled(BOOL enabled);
-	virtual void setMuteMic(bool muted);		// Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
-	//@}
-	
-	////////////////////////
-	/// @name PTT
-	//@{
-	virtual void setUserPTTState(bool ptt);
-	virtual bool getUserPTTState();
-	virtual void setUsePTT(bool usePTT);
-	virtual void setPTTIsToggle(bool PTTIsToggle);
-	virtual bool getPTTIsToggle();
-	virtual void inputUserControlState(bool down);  // interpret any sort of up-down mic-open control input according to ptt-toggle prefs	
-	virtual void toggleUserPTTState(void);
-	
-	virtual void keyDown(KEY key, MASK mask);
-	virtual void keyUp(KEY key, MASK mask);
-	virtual void middleMouseState(bool down);
-	//@}
-	
-	//////////////////////////
-	/// @name nearby speaker accessors
-	//@{
-	virtual BOOL getVoiceEnabled(const LLUUID& id);		// true if we've received data for this avatar
-	virtual std::string getDisplayName(const LLUUID& id);
-	virtual BOOL isOnlineSIP(const LLUUID &id);
-	virtual BOOL isParticipantAvatar(const LLUUID &id);
-	virtual BOOL getIsSpeaking(const LLUUID& id);
-	virtual BOOL getIsModeratorMuted(const LLUUID& id);
-	virtual F32 getCurrentPower(const LLUUID& id);		// "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is...
-	virtual BOOL getOnMuteList(const LLUUID& id);
-	virtual F32 getUserVolume(const LLUUID& id);
-	virtual void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)	
-	//@}
-	
-	// authorize the user
-	virtual void userAuthorized(const std::string& user_id,
-								const LLUUID &agentID);
-	
-	//////////////////////////////
-	/// @name Status notification
-	//@{
-	virtual void addObserver(LLVoiceClientStatusObserver* observer);
-	virtual void removeObserver(LLVoiceClientStatusObserver* observer);
-	virtual void addObserver(LLFriendObserver* observer);
-	virtual void removeObserver(LLFriendObserver* observer);		
-	virtual void addObserver(LLVoiceClientParticipantObserver* observer);
-	virtual void removeObserver(LLVoiceClientParticipantObserver* observer);
-	
-	
-	
-	//@}
-	
-	virtual std::string sipURIFromID(const LLUUID &id);
-	//@}
-
-				
-protected:
-	//////////////////////
-	// Vivox Specific definitions	
-	
-	friend class LLVivoxVoiceAccountProvisionResponder;
-	friend class LLVivoxVoiceClientMuteListObserver;
-	friend class LLVivoxVoiceClientFriendsObserver;	
-	
-	enum streamState
-	{
-		streamStateUnknown = 0,
-		streamStateIdle = 1,
-		streamStateConnected = 2,
-		streamStateRinging = 3,
-	};	
-	struct participantState
-	{
-	public:
-		participantState(const std::string &uri);
-		
-		bool updateMuteState();
-		bool isAvatar();
-		
-		std::string mURI;
-		LLUUID mAvatarID;
-		std::string mAccountName;
-		std::string mDisplayName;
-		LLFrameTimer mSpeakingTimeout;
-		F32	mLastSpokeTimestamp;
-		F32 mPower;
-		int mVolume;
-		std::string mGroupID;
-		int mUserVolume;
-		bool mPTT;
-		bool mIsSpeaking;
-		bool mIsModeratorMuted;
-		bool mOnMuteList;		// true if this avatar is on the user's mute list (and should be muted)
-		bool mVolumeDirty;		// true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
-		bool mAvatarIDValid;
-		bool mIsSelf;
-	};
-	
-	typedef std::map<const std::string, participantState*> participantMap;
-	
-	typedef std::map<const LLUUID, participantState*> participantUUIDMap;
-	
-	struct sessionState
-	{
-	public:
-		sessionState();
-		~sessionState();
-		
-		participantState *addParticipant(const std::string &uri);
-		// Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
-		// Take care not to use the pointer again after that.
-		void removeParticipant(participantState *participant);
-		void removeAllParticipants();
-		
-		participantState *findParticipant(const std::string &uri);
-		participantState *findParticipantByID(const LLUUID& id);
-		
-		bool isCallBackPossible();
-		bool isTextIMPossible();
-		
-		std::string mHandle;
-		std::string mGroupHandle;
-		std::string mSIPURI;
-		std::string mAlias;
-		std::string mName;
-		std::string mAlternateSIPURI;
-		std::string mHash;			// Channel password
-		std::string mErrorStatusString;
-		std::queue<std::string> mTextMsgQueue;
-		
-		LLUUID		mIMSessionID;
-		LLUUID		mCallerID;
-		int			mErrorStatusCode;
-		int			mMediaStreamState;
-		int			mTextStreamState;
-		bool		mCreateInProgress;	// True if a Session.Create has been sent for this session and no response has been received yet.
-		bool		mMediaConnectInProgress;	// True if a Session.MediaConnect has been sent for this session and no response has been received yet.
-		bool		mVoiceInvitePending;	// True if a voice invite is pending for this session (usually waiting on a name lookup)
-		bool		mTextInvitePending;		// True if a text invite is pending for this session (usually waiting on a name lookup)
-		bool		mSynthesizedCallerID;	// True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup.
-		bool		mIsChannel;	// True for both group and spatial channels (false for p2p, PSTN)
-		bool		mIsSpatial;	// True for spatial channels
-		bool		mIsP2P;
-		bool		mIncoming;
-		bool		mVoiceEnabled;
-		bool		mReconnect;	// Whether we should try to reconnect to this session if it's dropped
-		// Set to true when the mute state of someone in the participant list changes.
-		// The code will have to walk the list to find the changed participant(s).
-		bool		mVolumeDirty;
-		
-		bool		mParticipantsChanged;
-		participantMap mParticipantsByURI;
-		participantUUIDMap mParticipantsByUUID;
-	};
-
-	// internal state for a simple state machine.  This is used to deal with the asynchronous nature of some of the messages.
-	// Note: if you change this list, please make corresponding changes to LLVivoxVoiceClient::state2string().
-	enum state
-	{
-		stateDisableCleanup,
-		stateDisabled,				// Voice is turned off.
-		stateStart,					// Class is initialized, socket is created
-		stateDaemonLaunched,		// Daemon has been launched
-		stateConnecting,			// connect() call has been issued
-		stateConnected,				// connection to the daemon has been made, send some initial setup commands.
-		stateIdle,					// socket is connected, ready for messaging
-		stateMicTuningStart,
-		stateMicTuningRunning,		
-		stateMicTuningStop,
-		stateConnectorStart,		// connector needs to be started
-		stateConnectorStarting,		// waiting for connector handle
-		stateConnectorStarted,		// connector handle received
-		stateLoginRetry,			// need to retry login (failed due to changing password)
-		stateLoginRetryWait,		// waiting for retry timer
-		stateNeedsLogin,			// send login request
-		stateLoggingIn,				// waiting for account handle
-		stateLoggedIn,				// account handle received
-		stateCreatingSessionGroup,	// Creating the main session group
-		stateNoChannel,				// 
-		stateJoiningSession,		// waiting for session handle
-		stateSessionJoined,			// session handle received
-		stateRunning,				// in session, steady state
-		stateLeavingSession,		// waiting for terminate session response
-		stateSessionTerminated,		// waiting for terminate session response
-		
-		stateLoggingOut,			// waiting for logout response
-		stateLoggedOut,				// logout response received
-		stateConnectorStopping,		// waiting for connector stop
-		stateConnectorStopped,		// connector stop received
-		
-		// We go to this state if the login fails because the account needs to be provisioned.
-		
-		// error states.  No way to recover from these yet.
-		stateConnectorFailed,
-		stateConnectorFailedWaiting,
-		stateLoginFailed,
-		stateLoginFailedWaiting,
-		stateJoinSessionFailed,
-		stateJoinSessionFailedWaiting,
-		
-		stateJail					// Go here when all else has failed.  Nothing will be retried, we're done.
-	};
-	
-	typedef std::map<std::string, sessionState*> sessionMap;
-	
-	
-	
-	///////////////////////////////////////////////////////
-	// Private Member Functions
-	//////////////////////////////////////////////////////
-	
-	//////////////////////////////
-	/// @name TVC/Server management and communication
-	//@{
-	// Call this if the connection to the daemon terminates unexpectedly.  It will attempt to reset everything and relaunch.
-	void daemonDied();
-	
-	// Call this if we're just giving up on voice (can't provision an account, etc.).  It will clean up and go away.
-	void giveUp();	
-	
-	// write to the tvc
-	bool writeString(const std::string &str);
-	
-	void connectorCreate();
-	void connectorShutdown();	
-	void closeSocket(void);	
-	
-	void requestVoiceAccountProvision(S32 retries = 3);
-	void login(
-			   const std::string& account_name,
-			   const std::string& password,
-			   const std::string& voice_sip_uri_hostname,
-			   const std::string& voice_account_server_uri);
-	void loginSendMessage();
-	void logout();
-	void logoutSendMessage();	
-	
-	
-	//@}
-	
-	//------------------------------------
-	// tuning
-	
-	void tuningRenderStartSendMessage(const std::string& name, bool loop);
-	void tuningRenderStopSendMessage();
-
-	void tuningCaptureStartSendMessage(int duration);
-	void tuningCaptureStopSendMessage();
-
-	bool inTuningStates();
-
-	//----------------------------------
-	// devices
-	void clearCaptureDevices();
-	void addCaptureDevice(const std::string& name);
-	void clearRenderDevices();
-	void addRenderDevice(const std::string& name);	
-	void buildSetAudioDevices(std::ostringstream &stream);
-	
-	void getCaptureDevicesSendMessage();
-	void getRenderDevicesSendMessage();
-	
-	// local audio updates
-	void buildLocalAudioUpdates(std::ostringstream &stream);		
-
-
-	/////////////////////////////
-	// Response/Event handlers
-	void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
-	void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases);
-	void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
-	void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
-	void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString);
-	void logoutResponse(int statusCode, std::string &statusString);
-	void connectorShutdownResponse(int statusCode, std::string &statusString);
-
-	void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
-	void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);
-	void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming);
-	void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString);
-	void sessionGroupAddedEvent(std::string &sessionGroupHandle);
-	void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle);
-	void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType);
-	void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString);
-	void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
-	void auxAudioPropertiesEvent(F32 energy);
-	void buddyPresenceEvent(std::string &uriString, std::string &alias, std::string &statusString, std::string &applicationString);
-	void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
-	void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType);
-	void subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType);
-	
-	void buddyListChanged();
-	void muteListChanged();
-	void updateFriends(U32 mask);
-		
-	/////////////////////////////
-	// Sending updates of current state
-	void updatePosition(void);
-	void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
-	void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot);
-	bool channelFromRegion(LLViewerRegion *region, std::string &name);
-
-	void setEarLocation(S32 loc);
-
-	
-	/////////////////////////////
-	// Accessors for data related to nearby speakers
-
-	// MBW -- XXX -- Not sure how to get this data out of the TVC
-	BOOL getUsingPTT(const LLUUID& id);
-	std::string getGroupID(const LLUUID& id);		// group ID if the user is in group chat (empty string if not applicable)
-
-	/////////////////////////////
-	BOOL getAreaVoiceDisabled();		// returns true if the area the avatar is in is speech-disabled.
-										// Use this to determine whether to show a "no speech" icon in the menu bar.
-		
-	
-	// PTT
-	void setPTTKey(std::string &key);
-	
-	/////////////////////////////
-	// Recording controls
-	void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
-	void recordingLoopSave(const std::string& filename);
-	void recordingStop();
-	
-	// Playback controls
-	void filePlaybackStart(const std::string& filename);
-	void filePlaybackStop();
-	void filePlaybackSetPaused(bool paused);
-	void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
-	
-	participantState *findParticipantByID(const LLUUID& id);
-	
-
-	////////////////////////////////////////
-	// voice sessions.
-	typedef std::set<sessionState*> sessionSet;
-			
-	typedef sessionSet::iterator sessionIterator;
-	sessionIterator sessionsBegin(void);
-	sessionIterator sessionsEnd(void);
-
-	sessionState *findSession(const std::string &handle);
-	sessionState *findSessionBeingCreatedByURI(const std::string &uri);
-	sessionState *findSession(const LLUUID &participant_id);
-	sessionState *findSessionByCreateID(const std::string &create_id);
-	
-	sessionState *addSession(const std::string &uri, const std::string &handle = LLStringUtil::null);
-	void setSessionHandle(sessionState *session, const std::string &handle = LLStringUtil::null);
-	void setSessionURI(sessionState *session, const std::string &uri);
-	void deleteSession(sessionState *session);
-	void deleteAllSessions(void);
-
-	void verifySessionState(void);
-
-	void joinedAudioSession(sessionState *session);
-	void leftAudioSession(sessionState *session);
-
-	// This is called in several places where the session _may_ need to be deleted.
-	// It contains logic for whether to delete the session or keep it around.
-	void reapSession(sessionState *session);
-	
-	// Returns true if the session seems to indicate we've moved to a region on a different voice server
-	bool sessionNeedsRelog(sessionState *session);
-	
-	
-	//////////////////////////////////////
-	// buddy list stuff, needed for SLIM later
-	struct buddyListEntry
-	{
-		buddyListEntry(const std::string &uri);
-		std::string mURI;
-		std::string mDisplayName;
-		LLUUID	mUUID;
-		bool mOnlineSL;
-		bool mOnlineSLim;
-		bool mCanSeeMeOnline;
-		bool mHasBlockListEntry;
-		bool mHasAutoAcceptListEntry;
-		bool mNameResolved;
-		bool mInSLFriends;
-		bool mInVivoxBuddies;
-		bool mNeedsNameUpdate;
-	};
-
-	typedef std::map<std::string, buddyListEntry*> buddyListMap;
-	
-	// This should be called when parsing a buddy list entry sent by SLVoice.		
-	void processBuddyListEntry(const std::string &uri, const std::string &displayName);
-
-	buddyListEntry *addBuddy(const std::string &uri);
-	buddyListEntry *addBuddy(const std::string &uri, const std::string &displayName);
-	buddyListEntry *findBuddy(const std::string &uri);
-	buddyListEntry *findBuddy(const LLUUID &id);
-	buddyListEntry *findBuddyByDisplayName(const std::string &name);
-	void deleteBuddy(const std::string &uri);
-	void deleteAllBuddies(void);
-
-	void deleteAllBlockRules(void);
-	void addBlockRule(const std::string &blockMask, const std::string &presenceOnly);
-	void deleteAllAutoAcceptRules(void);
-	void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy);
-	void accountListBlockRulesResponse(int statusCode, const std::string &statusString);						
-	void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);						
-	
-	/////////////////////////////
-	// session control messages
-
-	void accountListBlockRulesSendMessage();
-	void accountListAutoAcceptRulesSendMessage();
-	
-	void sessionGroupCreateSendMessage();
-	void sessionCreateSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
-	void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
-	void sessionMediaConnectSendMessage(sessionState *session);		// just joins the audio session
-	void sessionTextConnectSendMessage(sessionState *session);		// just joins the text session
-	void sessionTerminateSendMessage(sessionState *session);
-	void sessionGroupTerminateSendMessage(sessionState *session);
-	void sessionMediaDisconnectSendMessage(sessionState *session);
-	void sessionTextDisconnectSendMessage(sessionState *session);
-
-	// Pokes the state machine to leave the audio session next time around.
-	void sessionTerminate();	
-	
-	// Pokes the state machine to shut down the connector and restart it.
-	void requestRelog();
-	
-	// Does the actual work to get out of the audio session
-	void leaveAudioSession();
-	
-	void lookupName(const LLUUID &id);
-	static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
-	void avatarNameResolved(const LLUUID &id, const std::string &name);
-		
-private:
-	LLVoiceVersionInfo mVoiceVersion;
-		
-	state mState;
-	bool mSessionTerminateRequested;
-	bool mRelogRequested;
-	// Number of times (in a row) "stateJoiningSession" case for spatial channel is reached in stateMachine().
-	// The larger it is the greater is possibility there is a problem with connection to voice server.
-	// Introduced while fixing EXT-4313.
-	int mSpatialJoiningNum;
-	
-	void setState(state inState);
-	state getState(void)  { return mState; };
-	std::string state2string(state inState);
-	
-	void stateMachine();
-	static void idle(void *user_data);
-	
-	LLHost mDaemonHost;
-	LLSocket::ptr_t mSocket;
-	bool mConnected;
-	
-	
-	LLPumpIO *mPump;
-	friend class LLVivoxProtocolParser;
-	
-	std::string mAccountName;
-	std::string mAccountPassword;
-	std::string mAccountDisplayName;
-			
-	bool mTuningMode;
-	float mTuningEnergy;
-	std::string mTuningAudioFile;
-	int mTuningMicVolume;
-	bool mTuningMicVolumeDirty;
-	int mTuningSpeakerVolume;
-	bool mTuningSpeakerVolumeDirty;
-	state mTuningExitState;					// state to return to when we leave tuning mode.
-	
-	std::string mSpatialSessionURI;
-	std::string mSpatialSessionCredentials;
-
-	std::string mMainSessionGroupHandle; // handle of the "main" session group.
-	
-	std::string mChannelName;			// Name of the channel to be looked up 
-	bool mAreaVoiceDisabled;
-	sessionState *mAudioSession;		// Session state for the current audio session
-	bool mAudioSessionChanged;			// set to true when the above pointer gets changed, so observers can be notified.
-
-	sessionState *mNextAudioSession;	// Session state for the audio session we're trying to join
-
-//		std::string mSessionURI;			// URI of the session we're in.
-//		std::string mSessionHandle;		// returned by ?
-	
-	S32 mCurrentParcelLocalID;			// Used to detect parcel boundary crossings
-	std::string mCurrentRegionName;		// Used to detect parcel boundary crossings
-	
-	std::string mConnectorHandle;	// returned by "Create Connector" message
-	std::string mAccountHandle;		// returned by login message		
-	int 		mNumberOfAliases;
-	U32 mCommandCookie;
-
-	std::string mVoiceAccountServerURI;
-	std::string mVoiceSIPURIHostName;
-	
-	int mLoginRetryCount;
-	
-	sessionMap mSessionsByHandle;				// Active sessions, indexed by session handle.  Sessions which are being initiated may not be in this map.
-	sessionSet mSessions;						// All sessions, not indexed.  This is the canonical session list.
-	
-	bool mBuddyListMapPopulated;
-	bool mBlockRulesListReceived;
-	bool mAutoAcceptRulesListReceived;
-	buddyListMap mBuddyListMap;
-	
-	LLVoiceDeviceList mCaptureDevices;
-	LLVoiceDeviceList mRenderDevices;
-
-	std::string mCaptureDevice;
-	std::string mRenderDevice;
-	bool mCaptureDeviceDirty;
-	bool mRenderDeviceDirty;
-	
-	// This should be called when the code detects we have changed parcels.
-	// It initiates the call to the server that gets the parcel channel.
-	void parcelChanged();
-	
-	void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
-	void joinSession(sessionState *session);
-	
-	std::string nameFromAvatar(LLVOAvatar *avatar);
-	std::string nameFromID(const LLUUID &id);
-	bool IDFromName(const std::string name, LLUUID &uuid);
-	std::string displayNameFromAvatar(LLVOAvatar *avatar);
-	std::string sipURIFromAvatar(LLVOAvatar *avatar);
-	std::string sipURIFromName(std::string &name);
-	
-	// Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
-	std::string nameFromsipURI(const std::string &uri);		
-
-	bool inSpatialChannel(void);
-	std::string getAudioSessionURI();
-	std::string getAudioSessionHandle();
-			
-	void sendPositionalUpdate(void);
-	
-	void buildSetCaptureDevice(std::ostringstream &stream);
-	void buildSetRenderDevice(std::ostringstream &stream);
-	
-	void clearAllLists();
-	void checkFriend(const LLUUID& id);
-	void sendFriendsListUpdates();
-
-	// start a text IM session with the specified user
-	// This will be asynchronous, the session may be established at a future time.
-	sessionState* startUserIMSession(const LLUUID& uuid);
-	void sendQueuedTextMessages(sessionState *session);
-	
-	void enforceTether(void);
-	
-	bool		mSpatialCoordsDirty;
-	
-	LLVector3d	mCameraPosition;
-	LLVector3d	mCameraRequestedPosition;
-	LLVector3	mCameraVelocity;
-	LLMatrix3	mCameraRot;
-
-	LLVector3d	mAvatarPosition;
-	LLVector3	mAvatarVelocity;
-	LLMatrix3	mAvatarRot;
-	
-	bool		mPTTDirty;
-	bool		mPTT;
-	
-	bool		mUsePTT;
-	bool		mPTTIsMiddleMouse;
-	KEY			mPTTKey;
-	bool		mPTTIsToggle;
-	bool		mUserPTTState;
-	bool		mMuteMic;
-			
-	// Set to true when the friends list is known to have changed.
-	bool		mFriendsListDirty;
-	
-	enum
-	{
-		earLocCamera = 0,		// ear at camera
-		earLocAvatar,			// ear at avatar
-		earLocMixed				// ear at avatar location/camera direction
-	};
-	
-	S32			mEarLocation;  
-	
-	bool		mSpeakerVolumeDirty;
-	bool		mSpeakerMuteDirty;
-	int			mSpeakerVolume;
-
-	int			mMicVolume;
-	bool		mMicVolumeDirty;
-	
-	bool		mVoiceEnabled;
-	bool		mWriteInProgress;
-	std::string mWriteString;
-	size_t		mWriteOffset;
-	
-	LLTimer		mUpdateTimer;
-	
-	BOOL		mLipSyncEnabled;
-
-	typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
-	observer_set_t mParticipantObservers;
-
-	void notifyParticipantObservers();
-
-	typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
-	status_observer_set_t mStatusObservers;
-	
-	void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
-
-	typedef std::set<LLFriendObserver*> friend_observer_set_t;
-	friend_observer_set_t mFriendObservers;
-	void notifyFriendObservers();
-};
-
-/** 
- * @class LLVivoxProtocolParser
- * @brief This class helps construct new LLIOPipe specializations
- * @see LLIOPipe
- *
- * THOROUGH_DESCRIPTION
- */
-class LLVivoxProtocolParser : public LLIOPipe
-{
-	LOG_CLASS(LLVivoxProtocolParser);
-public:
-	LLVivoxProtocolParser();
-	virtual ~LLVivoxProtocolParser();
-	
-protected:
-	/* @name LLIOPipe virtual implementations
-	 */
-	//@{
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-								 const LLChannelDescriptors& channels,
-								 buffer_ptr_t& buffer,
-								 bool& eos,
-								 LLSD& context,
-								 LLPumpIO* pump);
-	//@}
-	
-	std::string 	mInput;
-	
-	// Expat control members
-	XML_Parser		parser;
-	int				responseDepth;
-	bool			ignoringTags;
-	bool			isEvent;
-	int				ignoreDepth;
-	
-	// Members for processing responses. The values are transient and only valid within a call to processResponse().
-	bool			squelchDebugOutput;
-	int				returnCode;
-	int				statusCode;
-	std::string		statusString;
-	std::string		requestId;
-	std::string		actionString;
-	std::string		connectorHandle;
-	std::string		versionID;
-	std::string		accountHandle;
-	std::string		sessionHandle;
-	std::string		sessionGroupHandle;
-	std::string		alias;
-	std::string		applicationString;
-	
-	// Members for processing events. The values are transient and only valid within a call to processResponse().
-	std::string		eventTypeString;
-	int				state;
-	std::string		uriString;
-	bool			isChannel;
-	bool			incoming;
-	bool			enabled;
-	std::string		nameString;
-	std::string		audioMediaString;
-	std::string     deviceString;
-	std::string		displayNameString;
-	int				participantType;
-	bool			isLocallyMuted;
-	bool			isModeratorMuted;
-	bool			isSpeaking;
-	int				volume;
-	F32				energy;
-	std::string		messageHeader;
-	std::string		messageBody;
-	std::string		notificationType;
-	bool			hasText;
-	bool			hasAudio;
-	bool			hasVideo;
-	bool			terminated;
-	std::string		blockMask;
-	std::string		presenceOnly;
-	std::string		autoAcceptMask;
-	std::string		autoAddAsBuddy;
-	int				numberOfAliases;
-	std::string		subscriptionHandle;
-	std::string		subscriptionType;
-	
-	
-	// Members for processing text between tags
-	std::string		textBuffer;
-	bool			accumulateText;
-	
-	void			reset();
-	
-	void			processResponse(std::string tag);
-	
-	static void XMLCALL ExpatStartTag(void *data, const char *el, const char **attr);
-	static void XMLCALL ExpatEndTag(void *data, const char *el);
-	static void XMLCALL ExpatCharHandler(void *data, const XML_Char *s, int len);
-	
-	void			StartTag(const char *tag, const char **attr);
-	void			EndTag(const char *tag);
-	void			CharData(const char *buffer, int length);
-	
-};
-
-
-#endif //LL_VIVOX_VOICE_CLIENT_H
-
-
-
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index aa03b1afd1b80e12897514a91fb65633f29cb580..1a64f9d881e5fa8881065d7d94d94e49befa5347 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -155,7 +155,7 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
 	substitution["VERSION_PATCH"] = LLVersionInfo::getPatch();
 	substitution["VERSION_BUILD"] = LLVersionInfo::getBuild();
 	substitution["CHANNEL"] = LLVersionInfo::getChannel();
-	substitution["GRID"] = LLGridManager::getInstance()->getGridLabel();
+	substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel();
 	substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
 	substitution["SESSION_ID"] = gAgent.getSessionID();
 	substitution["FIRST_LOGIN"] = gAgent.isFirstLogin();
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 58b9f5ce188154184e6acce1590758a8df5a5598..0b63f5efbde8023e9dba3b608cbd33bb2bdf7fcc 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -133,11 +133,10 @@ void LLWorld::destroyClass()
 LLViewerRegion* LLWorld::addRegion(const U64 &region_handle, const LLHost &host)
 {
 	LLMemType mt(LLMemType::MTYPE_REGIONS);
-	llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl;
+	
 	LLViewerRegion *regionp = getRegionFromHandle(region_handle);
 	if (regionp)
 	{
-		llinfos << "Region exists, removing it " << llendl;
 		LLHost old_host = regionp->getHost();
 		// region already exists!
 		if (host == old_host && regionp->isAlive())
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
index 8237132ac51c604feb1d97315fa0c9ca1eb9e545..15417614af905117eb42c2ab66d9d837ccb1ef38 100644
--- a/indra/newview/llxmlrpclistener.cpp
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -28,7 +28,6 @@
 #include "llerror.h"
 #include "stringize.h"
 #include "llxmlrpctransaction.h"
-#include "llsecapi.h"
 
 #if LL_WINDOWS
 #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
@@ -357,22 +356,7 @@ class Poller
                                      << data["errorcode"].asString()
                                      << " (" << data["error"].asString() << ")"
                                      << LL_ENDL;
-		
-		switch (curlcode)
-		{
-			case CURLE_SSL_PEER_CERTIFICATE:
-			case CURLE_SSL_CACERT:
-			{
-				LLPointer<LLCertificate> error_cert(mTransaction->getErrorCert());
-				if(error_cert)
-				{
-					data["certificate"] = error_cert->getPem();
-				}
-				break;
-			}
-			default:
-				break;
-		}
+        // In addition to CURLE_OK, LLUserAuth distinguishes different error
         // values of 'curlcode':
         // CURLE_COULDNT_RESOLVE_HOST,
         // CURLE_SSL_PEER_CERTIFICATE,
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index d75c8ff1fb2b129c5f682ce30291f0e8a38b373f..012c668ee40fcabcec5ac108d7ddfcb4a0c68509 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -179,8 +179,6 @@ class LLXMLRPCTransaction::Impl
 
 	std::string			mResponseText;
 	XMLRPC_REQUEST		mResponse;
-	std::string         mCertStore;
-	LLPointer<LLCertificate> mErrorCert;
 	
 	Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip);
 	Impl(const std::string& uri,
@@ -195,8 +193,7 @@ class LLXMLRPCTransaction::Impl
 
 private:
 	void init(XMLRPC_REQUEST request, bool useGzip);
-	static int _sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
-	static CURLcode _sslCtxFunction(CURL * curl, void *sslctx, void *param);
+
 	static size_t curlDownloadCallback(
 		char* data, size_t size, size_t nmemb, void* user_data);
 };
@@ -234,74 +231,8 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
     XMLRPC_RequestFree(request, 1);
 }
 
-// _sslCertVerifyCallback
-// callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-int LLXMLRPCTransaction::Impl::_sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
-{
-	LLXMLRPCTransaction::Impl *transaction = (LLXMLRPCTransaction::Impl *)param;
-	LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(transaction->mCertStore);
-	LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
-	LLSD validation_params = LLSD::emptyMap();
-	LLURI uri(transaction->mURI);
-	validation_params[CERT_HOSTNAME] = uri.hostName();
-	try
-	{
-		chain->validate(VALIDATION_POLICY_SSL, store, validation_params);
-	}
-	catch (LLCertValidationTrustException& cert_exception)
-	{
-		// this exception is is handled differently than the general cert
-		// exceptions, as we allow the user to actually add the certificate
-		// for trust.
-		// therefore we pass back a different error code
-		// NOTE: We're currently 'wired' to pass around CURL error codes.  This is
-		// somewhat clumsy, as we may run into errors that do not map directly to curl
-		// error codes.  Should be refactored with login refactoring, perhaps.
-		transaction->mCurlCode = CURLE_SSL_CACERT;
-		// set the status directly.  set curl status generates error messages and we want
-		// to use the fixed ones from the exceptions
-		transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
-		// We should probably have a more generic way of passing information
-		// back to the error handlers.
-		transaction->mErrorCert = cert_exception.getCert();
-		return 0;		
-	}
-	catch (LLCertException& cert_exception)
-	{
-		transaction->mCurlCode = CURLE_SSL_PEER_CERTIFICATE;
-		// set the status directly.  set curl status generates error messages and we want
-		// to use the fixed ones from the exceptions
-		transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
-		transaction->mErrorCert = cert_exception.getCert();
-		return 0;
-	}
-	catch (...)
-	{
-		// any other odd error, we just handle as a connect error.
-		transaction->mCurlCode = CURLE_SSL_CONNECT_ERROR;
-		transaction->setCurlStatus(CURLE_SSL_CONNECT_ERROR);
-		return 0;
-	}
-	return 1;
-}
 
-// _sslCtxFunction
-// Callback function called when an SSL Context is created via CURL
-// used to configure the context for custom cert validate(<, <#const & xs#>, <#T * #>, <#long #>)tion
-// based on SECAPI
 
-CURLcode LLXMLRPCTransaction::Impl::_sslCtxFunction(CURL * curl, void *sslctx, void *param)
-{
-	SSL_CTX * ctx = (SSL_CTX *) sslctx;
-	// disable any default verification for server certs
-	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
-	// set the verification callback.
-	SSL_CTX_set_cert_verify_callback(ctx, _sslCertVerifyCallback, param);
-	// the calls are void
-	return CURLE_OK;
-	
-}
 
 void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 {
@@ -309,7 +240,6 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	{
 		mCurlRequest = new LLCurlEasyRequest();
 	}
-	mErrorCert = NULL;
 	
 	if (gSavedSettings.getBOOL("BrowserProxyEnabled"))
 	{
@@ -326,12 +256,11 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
 	mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
 	BOOL verifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
-	mCertStore = gSavedSettings.getString("CertStore");
+	mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify() ? 2 : 0);
 	mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, verifySSLCert);
 	mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, verifySSLCert ? 2 : 0);
 	// Be a little impatient about establishing connections.
 	mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
-	mCurlRequest->setSSLCtxCallback(_sslCtxFunction, (void *)this);
 
 	/* Setting the DNS cache timeout to -1 disables it completely.
 	   This might help with bug #503 */
@@ -417,19 +346,11 @@ bool LLXMLRPCTransaction::Impl::process()
 		{
 			if (result != CURLE_OK)
 			{
-				if ((result != CURLE_SSL_PEER_CERTIFICATE) &&
-					(result != CURLE_SSL_CACERT))
-				{
-					// if we have a curl error that's not already been handled
-					// (a non cert error), then generate the error message as
-					// appropriate
-					setCurlStatus(result);
-				
-					llwarns << "LLXMLRPCTransaction CURL error "
-					<< mCurlCode << ": " << mCurlRequest->getErrorString() << llendl;
-					llwarns << "LLXMLRPCTransaction request URI: "
-					<< mURI << llendl;
-				}
+				setCurlStatus(result);
+				llwarns << "LLXMLRPCTransaction CURL error "
+						<< mCurlCode << ": " << mCurlRequest->getErrorString() << llendl;
+				llwarns << "LLXMLRPCTransaction request URI: "
+						<< mURI << llendl;
 					
 				return true;
 			}
@@ -507,6 +428,7 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status,
 			case StatusComplete:
 				mStatusMessage = "(done)";
 				break;
+				
 			default:
 				// Usually this means that there's a problem with the login server,
 				// not with the client.  Direct user to status page.
@@ -622,11 +544,6 @@ std::string LLXMLRPCTransaction::statusMessage()
 	return impl.mStatusMessage;
 }
 
-LLPointer<LLCertificate> LLXMLRPCTransaction::getErrorCert()
-{
-	return impl.mErrorCert;
-}
-
 std::string LLXMLRPCTransaction::statusURI()
 {
 	return impl.mStatusURI;
diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h
index 8beb2e262368af96ddafc2adf331b61217160515..c835423d67c6fe719541a4fc3aa8f74303a9a5c5 100644
--- a/indra/newview/llxmlrpctransaction.h
+++ b/indra/newview/llxmlrpctransaction.h
@@ -38,7 +38,6 @@
 typedef struct _xmlrpc_request* XMLRPC_REQUEST;
 typedef struct _xmlrpc_value* XMLRPC_VALUE;
 	// foward decl of types from xmlrpc.h (this usage is type safe)
-class LLCertificate;
 
 class LLXMLRPCValue
 	// a c++ wrapper around XMLRPC_VALUE
@@ -116,8 +115,6 @@ class LLXMLRPCTransaction
 		
 	EStatus status(int* curlCode);
 		// return status, and extended CURL code, if code isn't null
-	
-	LLPointer<LLCertificate> getErrorCert();
 	std::string statusMessage();
 		// return a message string, suitable for showing the user
 	std::string statusURI();
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index a55201fd538c171e0d16a41e5c6da0ce3357ef7f..d03231a3fa26d45b05077fe606c2bc7ad064ca4c 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -49,7 +49,7 @@ libcurl Version: [LIBCURL_VERSION]
 J2C Decoder Version: [J2C_VERSION]
 Audio Driver Version: [AUDIO_DRIVER_VERSION]
 Qt Webkit Version: [QT_WEBKIT_VERSION]
-Voice Server Version: [VOICE_VERSION]
+Vivox Version: [VIVOX_VERSION]
 </floater.string>
   <floater.string
      name="none">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index c42b846dbbf879ba1e27a621fa50011886a40324..e8ba8c683df497d40fa8fe6da605586382c7faf0 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1382,18 +1382,6 @@ Unknown Vorbis encode failure on: [FILE]
 Unable to encode file: [FILE]
   </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   name="CorruptedProtectedDataStore"
-   type="alertmodal">
-  We are unable to read your protected data so it is being reset.
-   This may happen when you change network setup.
-
-    <usetemplate
-     name="okbutton"
-     yestext="OK"/>
-  </notification>
-    
   <notification
    icon="alertmodal.tga"
    name="CorruptResourceFile"
@@ -2429,57 +2417,6 @@ Please choose the male or female avatar. You can change your mind later.
      notext="Female"
      yestext="Male"/>
   </notification>
-  <notification icon="alertmodal.tga"
-		name="CantTeleportToGrid"
-		type="alertmodal">
-Could not teleport to [SLURL] as it's on a different grid ([GRID]) than the current grid ([CURRENT_GRID]).  Please close your viewer and try again.
-    <usetemplate
-     name="okbutton"
-     yestext="OK"/>
-  </notification>
-
-  <notification icon="alertmodal.tga"
-		name="GeneralCertificateError"
-		type="alertmodal">
-Could not connect to the server.
-[REASON]
-
-SubjectName: [SUBJECT_NAME_STRING]
-IssuerName: [ISSUER_NAME_STRING]
-Valid From: [VALID_FROM]
-Valid To: [VALID_TO]
-MD5 Fingerprint: [SHA1_DIGEST]
-SHA1 Fingerprint: [MD5_DIGEST]
-Key Usage: [KEYUSAGE]
-Extended Key Usage: [EXTENDEDKEYUSAGE]
-Subject Key Identifier: [SUBJECTKEYIDENTIFIER]
-    <usetemplate
-     name="okbutton"
-     yestext="OK"/>
-   </notification>
-
-  <notification icon="alertmodal.tga"
-		name="TrustCertificateError"
-		type="alertmodal">
-The certification authority for this server is not known.
-
-Certificate Information:
-SubjectName: [SUBJECT_NAME_STRING]
-IssuerName: [ISSUER_NAME_STRING]
-Valid From: [VALID_FROM]
-Valid To: [VALID_TO]
-MD5 Fingerprint: [SHA1_DIGEST]
-SHA1 Fingerprint: [MD5_DIGEST]
-Key Usage: [KEYUSAGE]
-Extended Key Usage: [EXTENDEDKEYUSAGE]
-Subject Key Identifier: [SUBJECTKEYIDENTIFIER]
-
-Would you like to trust this authority?
-    <usetemplate
-     name="okcancelbuttons"
-     notext="Cancel"
-     yestext="Trust"/>
-  </notification>
 
   <notification
    icon="alertmodal.tga"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 539c5f785cc3f34d8cf7c8c77860ee48c7ca5ac7..01adc00e1a16f3a42d1fdc48737597afe8d51333 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -48,31 +48,50 @@ auto_resize="false"
 follows="left|bottom"
 name="login"
 layout="topleft"
-width="850"
-min_width="850"
+width="695"
+min_width="695"
 user_resize="false"
 height="80">
 <text
 follows="left|bottom"
 font="SansSerifSmall"
 height="16"
-name="username_text"
+name="first_name_text"
 top="20"
 left="20"
 width="150">
-Username:
+First name:
 </text>
 <line_editor
 follows="left|bottom"
 height="22"
-label="Username"
+label="First"
 left_delta="0"
 max_length="31"
-name="username_edit"
+name="first_name_edit"
 select_on_focus="true"
-tool_tip="[SECOND_LIFE] Username"
+tool_tip="[SECOND_LIFE] First Name"
 top_pad="0"
-width="150" />
+   width="135" />
+  <text
+   follows="left|bottom"
+   font="SansSerifSmall"
+   height="16"
+   left_pad="8"
+   name="last_name_text"
+   top="20"
+   width="150">
+    Last name:   </text>
+<line_editor
+follows="left|bottom"
+height="22"
+label="Last"
+max_length="31"
+name="last_name_edit"
+select_on_focus="true"
+tool_tip="[SECOND_LIFE] Last Name"
+  top_pad="0"
+  width="135" />
 <text
 follows="left|bottom"
 font="SansSerifSmall"
@@ -80,7 +99,7 @@ height="15"
 left_pad="8"
 name="password_text"
 top="20"
-    width="135">
+    width="150">
        Password:
 </text>
 <line_editor
@@ -100,14 +119,26 @@ label="Remember password"
   top_pad="3"
   name="remember_check"
  width="135" />
+<button
+  follows="left|bottom"
+  height="23"
+  image_unselected="PushButton_On"
+  image_selected="PushButton_On_Selected"
+  label="Log In"
+  label_color="White"
+  layout="topleft"
+  left_pad="10"
+  name="connect_btn"
+  top="35"
+  width="90" />
   <text
   follows="left|bottom"
   font="SansSerifSmall"
   height="15"
-  left_pad="10"
+  left_pad="18"
   name="start_location_text"
 top="20"
-  width="250">
+  width="130">
        Start at:
  </text>
 <combo_box
@@ -118,7 +149,7 @@ control_name="LoginLocation"
 max_chars="128"
 top_pad="0"
 name="start_location_combo"
-     width="250">
+     width="135">
 <combo_box.item
 label="My last location"
 name="MyLastLocation"
@@ -131,37 +162,16 @@ name="MyHome"
 label="&lt;Type region name&gt;"
 name="Typeregionname"   value="" />
 </combo_box>
-<button
-  height="23"
-  image_unselected="PushButton_On"
-  image_selected="PushButton_On_Selected"
-  label="Log In"
-  label_color="White"
-  layout="topleft"
-  left_pad="10"
-  name="connect_btn"
-  top="35"
-  width="90" />
-  <text
-  follows="left|bottom"
-  font="SansSerifSmall"
-  height="15"
-  left_pad="10"
-  name="start_location_text"
-top="20"
-  width="150">
-       Grid Name:
- </text>
 <combo_box
-follows="left|bottom"
 allow_text_entry="true"
 font="SansSerifSmall"
-height="23"
+   follows="left|right|bottom"
+   height="23"
+layout="topleft"
+top_pad="2"
 name="server_combo"
-top_pad="0"
-width="150"
-max_chars="255"
-visible="false" />
+width="135"
+  visible="false" />
 </layout_panel>
 <layout_panel
 follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 9ac4ef9b3779dd36af1537c41fbb051bb14fbb14..0c73b8d7692eef339fb731053adee4e7e10e170c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -46,15 +46,6 @@
 	<string name="LoginWaitingForRegionHandshake">Waiting for region handshake...</string>
 	<string name="LoginConnectingToRegion">Connecting to region...</string>
 	<string name="LoginDownloadingClothing">Downloading clothing...</string>
-        <string name="InvalidCertificate">The server returned an invalid or corrupt certificate. Please contact the Grid administrator.</string>
-        <string name="CertInvalidHostname">An invalid hostname was used to access the server, please check your SLURL or Grid hostname.</string>
-        <string name="CertExpired">The certificate returned by the Grid appears to be expired.  Please check your system clock, or contact your Grid administr\
-ator.</string>
-        <string name="CertKeyUsage">The certificate returned by the server could not be used for SSL.  Please contact your Grid administrator.</string>
-        <string name="CertBasicConstraints">Too many certificates were in the servers Certificate chain.  Please contact your Grid administrator.</string>
-        <string name="CertInvalidSignature">The certificate signature returned by the Grid server could not be verified.  Please contact your Grid administrat
-or.</string>
-
 	<string name="LoginFailedNoNetwork">Network Error: Could not establish connection, please check your network connection.</string>
 	<string name="LoginFailed">Login failed.</string>
 	<string name="Quit">Quit</string>
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index 67da9f2cdf4012d02dd6259121b9c1a7f239df31..ef93586c6e852c6b713f477639184321e6a02368 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -10,10 +10,7 @@
 // Precompiled header
 #include "../llviewerprecompiledheaders.h"
 // Own header
-#include "../llsecapi.h"
-#include "../llviewernetwork.h"
 #include "../lllogininstance.h"
-
 // STL headers
 // std headers
 // external library headers
@@ -36,12 +33,7 @@ const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
 //-----------------------------------------------------------------------------
 static LLEventStream gTestPump("test_pump");
 
-#include "../llslurl.h"
-#include "../llstartup.h"
-LLSLURL LLStartUp::sStartSLURL;
-
 #include "lllogin.h"
-
 static std::string gLoginURI;
 static LLSD gLoginCreds;
 static bool gDisconnectCalled = false;
@@ -62,68 +54,17 @@ void LLLogin::disconnect()
 	gDisconnectCalled = true;
 }
 
-LLSD LLCredential::getLoginParams()
-{
-	LLSD result = LLSD::emptyMap();
-
-	// legacy credential
-	result["passwd"] = "$1$testpasssd";
-	result["first"] = "myfirst";
-	result["last"] ="mylast";
-	return result;
-}
-
 //-----------------------------------------------------------------------------
 #include "../llviewernetwork.h"
-LLGridManager::~LLGridManager()
-{
-}
-
-void LLGridManager::addGrid(LLSD& grid_data)
-{
-}
-LLGridManager::LLGridManager()
-{	
-}
+unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'};
 
-void LLGridManager::getLoginURIs(std::vector<std::string>& uris)
+LLViewerLogin::LLViewerLogin() : mGridChoice(GRID_INFO_NONE) {}
+LLViewerLogin::~LLViewerLogin() {}
+void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const 
 {
 	uris.push_back(VIEWERLOGIN_URI);
 }
-
-void LLGridManager::addSystemGrid(const std::string& label, 
-								  const std::string& name, 
-								  const std::string& login, 
-								  const std::string& helper,
-								  const std::string& login_page,
-								  const std::string& login_id)
-{
-}
-std::map<std::string, std::string> LLGridManager::getKnownGrids(bool favorite_only)
-{
-	std::map<std::string, std::string> result;
-	return result;
-}
-
-void LLGridManager::setGridChoice(const std::string& grid_name)
-{
-}
-
-bool LLGridManager::isInProductionGrid()
-{
-	return false;
-}
-
-void LLGridManager::saveFavorites()
-{}
-std::string LLGridManager::getSLURLBase(const std::string& grid_name)
-{
-	return "myslurl";
-}
-std::string LLGridManager::getAppSLURLBase(const std::string& grid_name)
-{
-	return "myappslurl";
-}
+std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; }
 
 //-----------------------------------------------------------------------------
 #include "../llviewercontrol.h"
@@ -145,6 +86,10 @@ BOOL LLControlGroup::declareString(const std::string& name, const std::string &i
 #include "lluicolortable.h"
 void LLUIColorTable::saveUserSettings(void)const {}
 
+//-----------------------------------------------------------------------------
+#include "../llurlsimstring.h"
+LLURLSimString LLURLSimString::sInstance;
+bool LLURLSimString::parse() { return true; }
 
 //-----------------------------------------------------------------------------
 #include "llnotifications.h"
@@ -252,29 +197,15 @@ namespace tut
 			gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
 			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
 
-			LLSD authenticator = LLSD::emptyMap();
-			LLSD identifier = LLSD::emptyMap();
-			identifier["type"] = "agent";
-			identifier["first_name"] = "testfirst";
-			identifier["last_name"] = "testlast";
-			authenticator["passwd"] = "testpass";
-			agentCredential = new LLCredential();
-			agentCredential->setCredentialData(identifier, authenticator);
-			
-			authenticator = LLSD::emptyMap();
-			identifier = LLSD::emptyMap();
-			identifier["type"] = "account";
-			identifier["username"] = "testuser";
-			authenticator["secret"] = "testsecret";
-			accountCredential = new LLCredential();
-			accountCredential->setCredentialData(identifier, authenticator);			
+			credentials["first"] = "testfirst";
+			credentials["last"] = "testlast";
+			credentials["passwd"] = "testpass";
 
 			logininstance->setNotificationsInterface(&notifications);
 		}
 
 		LLLoginInstance* logininstance;
-		LLPointer<LLCredential> agentCredential;
-		LLPointer<LLCredential> accountCredential;
+		LLSD credentials;
 		MockNotifications notifications;
     };
 
@@ -288,7 +219,7 @@ namespace tut
 		set_test_name("Test Simple Success And Disconnect");
 
 		// Test default connect.
-		logininstance->connect(agentCredential);
+		logininstance->connect(credentials);
 
 		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
 
@@ -329,7 +260,7 @@ namespace tut
 		const std::string test_uri = "testing-uri";
 
 		// Test default connect.
-		logininstance->connect(test_uri, agentCredential);
+		logininstance->connect(test_uri, credentials);
 
 		// connect should call LLLogin::connect to init gLoginURI and gLoginCreds.
 		ensure_equals("Default connect uri", gLoginURI, "testing-uri"); 
@@ -351,7 +282,7 @@ namespace tut
 		ensure("No TOS, failed auth", logininstance->authFailure());
 
 		// Start again.
-		logininstance->connect(test_uri, agentCredential);
+		logininstance->connect(test_uri, credentials);
 		gTestPump.post(response); // Fail for tos again.
 		gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos.
 		ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true);
@@ -363,11 +294,11 @@ namespace tut
 		gTestPump.post(response);
 		ensure("TOS auth failure", logininstance->authFailure());
 
-		logininstance->connect(test_uri, agentCredential);
+		logininstance->connect(test_uri, credentials);
 		ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
 
 		// Critical Message failure response.
-		logininstance->connect(test_uri, agentCredential);
+		logininstance->connect(test_uri, credentials);
 		response["data"]["reason"] = "critical"; // Change response to "critical message"
 		gTestPump.post(response);
 
@@ -381,7 +312,7 @@ namespace tut
 		response["data"]["reason"] = "key"; // bad creds.
 		gTestPump.post(response);
 		ensure("TOS auth failure", logininstance->authFailure());
-		logininstance->connect(test_uri, agentCredential);
+		logininstance->connect(test_uri, credentials);
 		ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false);
 	}
 
@@ -392,7 +323,7 @@ namespace tut
 
 		// Part 1 - Mandatory Update, with User accepts response.
 		// Test connect with update needed.
-		logininstance->connect(agentCredential);
+		logininstance->connect(credentials);
 
 		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
 
@@ -418,7 +349,7 @@ namespace tut
 		set_test_name("Test Mandatory Update User Decline");
 
 		// Test connect with update needed.
-		logininstance->connect(agentCredential);
+		logininstance->connect(credentials);
 
 		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
 
@@ -444,7 +375,7 @@ namespace tut
 
 		// Part 3 - Mandatory Update, with bogus response.
 		// Test connect with update needed.
-		logininstance->connect(agentCredential);
+		logininstance->connect(credentials);
 
 		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
 
@@ -470,7 +401,7 @@ namespace tut
 
 		// Part 3 - Mandatory Update, with bogus response.
 		// Test connect with update needed.
-		logininstance->connect(agentCredential);
+		logininstance->connect(credentials);
 
 		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); 
 
diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp
deleted file mode 100644
index caa1461987ef5cfc9543332461a3ad3ef834d6f3..0000000000000000000000000000000000000000
--- a/indra/newview/tests/llsecapi_test.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/** 
- * @file llsecapi_test.cpp
- * @author Roxie
- * @date 2009-02-10
- * @brief Test the sec api functionality
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden LregisterSecAPIab
- * 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 "../llviewerprecompiledheaders.h"
-#include "../llviewernetwork.h"
-#include "../test/lltut.h"
-#include "../llsecapi.h"
-#include "../../llxml/llcontrol.h"
-
-
-//----------------------------------------------------------------------------               
-// Mock objects for the dependencies of the code we're testing                               
-
-LLControlGroup::LLControlGroup(const std::string& name)
-: LLInstanceTracker<LLControlGroup, std::string>(name) {}
-LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
-                                   const std::string& initial_val,
-                                   const std::string& comment,
-                                   BOOL persist) {return TRUE;}
-void LLControlGroup::setString(const std::string& name, const std::string& val){}
-std::string LLControlGroup::getString(const std::string& name)
-{
-	return "";
-}
-
-
-LLControlGroup gSavedSettings("test");
-class LLSecAPIBasicHandler : public LLSecAPIHandler
-{
-protected:
-	LLPointer<LLCertificateChain> mCertChain;
-	LLPointer<LLCertificate> mCert;
-	LLPointer<LLCertificateStore> mCertStore;
-	LLSD mLLSD;
-	
-public:
-	LLSecAPIBasicHandler() {}
-	
-	virtual ~LLSecAPIBasicHandler() {}
-	
-	// instantiate a certificate from a pem string
-	virtual LLPointer<LLCertificate> getCertificate(const std::string& pem_cert) 
-	{ 
-		return mCert; 
-	}
-	
-	
-	// instiate a certificate from an openssl X509 structure
-	virtual LLPointer<LLCertificate> getCertificate(X509* openssl_cert) 
-	{	
-		return mCert; 
-	}
-	
-	
-	// instantiate a chain from an X509_STORE_CTX
-	virtual LLPointer<LLCertificateChain> getCertificateChain(const X509_STORE_CTX* chain) 
-	{ 
-		return mCertChain; 
-	}
-	
-	// instantiate a cert store given it's id.  if a persisted version
-	// exists, it'll be loaded.  If not, one will be created (but not
-	// persisted)
-	virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id) 
-	{ 
-		return mCertStore; 
-	}
-	
-	// persist data in a protected store
-	virtual void setProtectedData(const std::string& data_type,
-								  const std::string& data_id,
-								  const LLSD& data) {}
-	
-	// retrieve protected data
-	virtual LLSD getProtectedData(const std::string& data_type,
-								  const std::string& data_id) 
-	{ 
-		return mLLSD;
-	}
-	
-	virtual void deleteProtectedData(const std::string& data_type,
-									 const std::string& data_id)
-	{
-	}
-	
-	virtual LLPointer<LLCredential> createCredential(const std::string& grid,
-													 const LLSD& identifier, 
-													 const LLSD& authenticator)
-	{
-		LLPointer<LLCredential> cred = NULL;
-		return cred;
-	}
-	
-	virtual LLPointer<LLCredential> loadCredential(const std::string& grid)
-	{
-		LLPointer<LLCredential> cred = NULL;
-		return cred;
-	}
-	
-	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator) {}
-	
-	virtual void deleteCredential(LLPointer<LLCredential> cred) {}
-};
-
-// -------------------------------------------------------------------------------------------
-// TUT
-// -------------------------------------------------------------------------------------------
-namespace tut
-{
-	// Test wrapper declaration : wrapping nothing for the moment
-	struct secapiTest
-	{
-		
-		secapiTest()
-		{
-		}
-		~secapiTest()
-		{
-		}
-	};
-	
-	// Tut templating thingamagic: test group, object and test instance
-	typedef test_group<secapiTest> secapiTestFactory;
-	typedef secapiTestFactory::object secapiTestObject;
-	tut::secapiTestFactory tut_test("llsecapi");
-	
-	// ---------------------------------------------------------------------------------------
-	// Test functions 
-	// ---------------------------------------------------------------------------------------
-	// registration
-	template<> template<>
-	void secapiTestObject::test<1>()
-	{
-		// retrieve an unknown handler
-
-		ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown"));
-		LLPointer<LLSecAPIHandler> test1_handler =  new LLSecAPIBasicHandler();
-		registerSecHandler("sectest1", test1_handler);
-		ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown"));
-		LLPointer<LLSecAPIHandler> retrieved_test1_handler = getSecHandler("sectest1");
-		ensure("Retrieved sectest1 handler should be the same", 
-			   retrieved_test1_handler == test1_handler);
-		
-		// insert a second handler
-		LLPointer<LLSecAPIHandler> test2_handler =  new LLSecAPIBasicHandler();
-		registerSecHandler("sectest2", test2_handler);
-		ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown"));
-		retrieved_test1_handler = getSecHandler("sectest1");
-		ensure("Retrieved sectest1 handler should be the same", 
-			   retrieved_test1_handler == test1_handler);
-
-		LLPointer<LLSecAPIHandler> retrieved_test2_handler = getSecHandler("sectest2");
-		ensure("Retrieved sectest1 handler should be the same", 
-			   retrieved_test2_handler == test2_handler);
-		
-	}
-}
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
deleted file mode 100644
index 236d17c59191557f701b2a4a248e72cbc22ff184..0000000000000000000000000000000000000000
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ /dev/null
@@ -1,964 +0,0 @@
-/** 
- * @file llsechandler_basic_test.cpp
- * @author Roxie
- * @date 2009-02-10
- * @brief Test the 'basic' sec handler functions
- *
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- * 
- * Copyright (c) 2005-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 "../llviewerprecompiledheaders.h"
-#include "../test/lltut.h"
-#include "../llsecapi.h"
-#include "../llsechandler_basic.h"
-#include "../../llxml/llcontrol.h"
-#include "../llviewernetwork.h"
-#include "lluuid.h"
-#include "llxorcipher.h"
-#include "apr_base64.h"
-#include <vector>
-#include <ios>
-#include <llsdserialize.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include "llxorcipher.h"
-
-#define ensure_throws(str, exc_type, cert, func, ...) \
-try \
-{ \
-func(__VA_ARGS__); \
-fail("throws, " str); \
-} \
-catch(exc_type& except) \
-{ \
-ensure("Exception cert is incorrect for " str, except.getCert() == cert); \
-}
-
-extern bool _cert_hostname_wildcard_match(const std::string& hostname, const std::string& wildcard_string);
-
-//----------------------------------------------------------------------------               
-// Mock objects for the dependencies of the code we're testing                               
-
-std::string gFirstName;
-std::string gLastName;
-LLControlGroup::LLControlGroup(const std::string& name)
-: LLInstanceTracker<LLControlGroup, std::string>(name) {}
-LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
-                                   const std::string& initial_val,
-                                   const std::string& comment,
-                                   BOOL persist) {return TRUE;}
-void LLControlGroup::setString(const std::string& name, const std::string& val){}
-std::string LLControlGroup::getString(const std::string& name)
-{
-
-	if (name == "FirstName")
-		return gFirstName;
-	else if (name == "LastName")
-		return gLastName;
-	return "";
-}
-
-LLSD LLCredential::getLoginParams()
-{
-	LLSD result = LLSD::emptyMap();
-	
-	// legacy credential
-	result["passwd"] = "$1$testpasssd";
-	result["first"] = "myfirst";
-	result["last"] ="mylast";
-	return result;
-}
-
-
-
-LLControlGroup gSavedSettings("test");
-unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {77,21,46,31,89,2};
-
-// -------------------------------------------------------------------------------------------
-// TUT
-// -------------------------------------------------------------------------------------------
-namespace tut
-{
-	// Test wrapper declaration : wrapping nothing for the moment
-	struct sechandler_basic_test
-	{
-		std::string mPemTestCert, mPemRootCert, mPemIntermediateCert, mPemChildCert;
-		std::string mDerFormat;
-		X509 *mX509TestCert, *mX509RootCert, *mX509IntermediateCert, *mX509ChildCert;
-
-		sechandler_basic_test()
-		{
-			OpenSSL_add_all_algorithms();
-			OpenSSL_add_all_ciphers();
-			OpenSSL_add_all_digests();	
-			ERR_load_crypto_strings();
-			gFirstName = "";
-			gLastName = "";
-			LLFile::remove("test_password.dat");
-			LLFile::remove("sechandler_settings.tmp");			
-			mPemTestCert = "-----BEGIN CERTIFICATE-----\n"
-				"MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx\n"
-				"EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h\n"
-				"bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy\n"
-				"YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp\n"
-				"Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy\n"
-				"MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG\n"
-				"A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt\n"
-				"YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD\n"
-				"VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB\n"
-				"IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA\n"
-				"isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj\n"
-				"Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50\n"
-				"QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt\n"
-				"bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR\n"
-				"yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID\n"
-				"AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0\n"
-				"cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f\n"
-				"BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj\n"
-				"cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB\n"
-				"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1\n"
-				"U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl\n"
-				"YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos\n"
-				"SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/\n"
-				"t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u\n"
-				"mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb\n"
-				"K+9A46sd33oqK8n8\n"
-				"-----END CERTIFICATE-----\n";
-
-			mPemRootCert = "-----BEGIN CERTIFICATE-----\n"
-			"MIIB0TCCATqgAwIBAgIJANaTqrzEvHaRMA0GCSqGSIb3DQEBBAUAMBsxGTAXBgNV\n"
-			"BAMTEFJveGllcyB0ZXN0IHJvb3QwHhcNMDkwNDE1MjEwNzQ3WhcNMTAwNDE1MjEw\n"
-			"NzQ3WjAbMRkwFwYDVQQDExBSb3hpZXMgdGVzdCByb290MIGfMA0GCSqGSIb3DQEB\n"
-			"AQUAA4GNADCBiQKBgQCpo5nDW6RNz9IHUVZd7Tw2XAQiBniDF4xH0N1w7sUYTiFq\n"
-			"21mABsnOPJD3ra+MtOsXPHcaljm661JjTD8L40v5sfEbqDUPcOw76ClrPqnuAeyT\n"
-			"38qk8DHku/mT8YdprevGZdVcUXQg3vosVzOL93HOOHK+u61mEEoM9W5xoNVEdQID\n"
-			"AQABox0wGzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQQF\n"
-			"AAOBgQAzn0aW/+zWPmcTbvxonyiYYUr9b4SOB/quhAkT8KT4ir1dcZAXRR59+kEn\n"
-			"HSTu1FAodV0gvESqyobftF5hZ1XMxdJqGu//xP+YCwlv244G/0pp7KLI8ihNO2+N\n"
-			"lPBUJgbo++ZkhiE1jotZi9Ay0Oedh3s/AfbMZPyfpJ23ll6+BA==\n"
-			"-----END CERTIFICATE-----\n";
-			
-			
-			
-			mPemIntermediateCert = "-----BEGIN CERTIFICATE-----\n"
-			"MIIBzzCCATigAwIBAgIBATANBgkqhkiG9w0BAQQFADAbMRkwFwYDVQQDExBSb3hp\n"
-			"ZXMgdGVzdCByb290MB4XDTA5MDQxNTIxMzE1NloXDTEwMDQxNTIxMzE1NlowITEf\n"
-			"MB0GA1UEAxMWUm94aWVzIGludGVybWVkaWF0ZSBDQTCBnzANBgkqhkiG9w0BAQEF\n"
-			"AAOBjQAwgYkCgYEA15MM0W1R37rx/24Q2Qkb5bSiQZxTUcQAhJ2pA8mwUucXuCVt\n"
-			"6ayI2TuN32nkjmsCgUkiT/bdXWp0OJo7/MXRIFeUNMCRxrpeFnxuigYEqbIXAdN6\n"
-			"qu/vdG2X4PRv/v9Ijrju4cBEiKIldIgOurWEIfXEsVSFP2XmFQHesF04qDcCAwEA\n"
-			"AaMdMBswDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQAD\n"
-			"gYEAYljikYgak3W1jSo0vYthNHUy3lBVAKzDhpM96lY5OuXFslpCRX42zNL8X3kN\n"
-			"U/4IaJUVtZqx8WsUXl1eXHzBCaXCftapV4Ir6cENLIsXCdXs8paFYzN5nPJA5GYU\n"
-			"zWgkSEl1MEhNIc+bJW34vwi29EjrAShAhsIZ84Mt/lvD3Pc=\n"
-			"-----END CERTIFICATE-----\n";
-			
-			mPemChildCert = "-----BEGIN CERTIFICATE-----\n"
-			"MIIB5DCCAU0CBEnm9eUwDQYJKoZIhvcNAQEEBQAwITEfMB0GA1UEAxMWUm94aWVz\n"
-			"IGludGVybWVkaWF0ZSBDQTAeFw0wOTA0MTYwMDAzNDlaFw0xMDA0MTYwMDAzNDla\n"
-			"MCAxHjAcBgNVBAMTFWVuaWFjNjMubGluZGVubGFiLmNvbTCBnzANBgkqhkiG9w0B\n"
-			"AQEFAAOBjQAwgYkCgYEAp9I5rofEzbjNht+9QejfnsIlEPqSxskoWKCG255TesWR\n"
-			"RTmw9wafHQQkJk/VIsaU4RMBYHkknGbHX2dGvMHmKZoWUPSQ/8FZz09o0Qx3TNUZ\n"
-			"l7KlGOD2d1c7ZxXDPqlLC6QW8DrE1/8zfwJ5cbYBXc8e7OKdSZeRrnwHyw4Q8r8C\n"
-			"AwEAAaMvMC0wEwYDVR0lBAwwCgYIKwYBBQUHAwEwCQYDVR0TBAIwADALBgNVHQ8E\n"
-			"BAMCBaAwDQYJKoZIhvcNAQEEBQADgYEAIG0M5tqYlXyMiGKPZfXy/R3M3ZZOapDk\n"
-			"W0dsXJYXAc35ftwtn0VYu9CNnZCcli17/d+AKhkK8a/oGPazqudjFF6WLJLTXaY9\n"
-			"NmhkJcOPADXkbyQPUPXzLe4YRrkEQeGhzMb4rKDQ1TKAcXfs0Y068pTpsixNSxja\n"
-			"NhAUUcve5Is=\n"
-			"-----END CERTIFICATE-----\n";
-			
-			mDerFormat = "MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIxEzARBgNVBAoT"
-"CklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25hbCBkZSBUZWNub2xvZ2lhIGRh"
-"IEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJyYXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UE"
-"AxMoQXV0b3JpZGFkZSBDZXJ0aWZpY2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4"
-"MDBaFw0xMTExMzAyMzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9"
-"MDsGA1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3JtYWNhbyAt"
-"IElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYDVQQDEyhBdXRvcmlkYWRl"
-"IENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB"
-"CgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVAisamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma"
-"/3pUpgcfNAj0vYm5gsyjQo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt"
-"4CyNrY50QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYtbRhF"
-"boUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbURyEeNvZneVRKAAU6o"
-"uwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwIDAQABo4HSMIHPME4GA1UdIARHMEUw"
-"QwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQ"
-"Q2FjcmFpei5wZGYwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292"
-"LmJyL0xDUmFjcmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB"
-"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1U/hgIh6OcgLA"
-"fiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGlYjJe+9zd+izPRbBqXPVQA34E"
-"Xcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75FosSzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQf"
-"S//JYeIc7Fue2JNLd00UOSMMaiK/t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr"
-"1ME7a55lFEnSeT0umlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5"
-"nmPbK+9A46sd33oqK8n8";
-			
-			mX509TestCert = NULL;
-			mX509RootCert = NULL;
-			mX509IntermediateCert = NULL;
-			mX509ChildCert = NULL;
-			
-			BIO * validation_bio = BIO_new_mem_buf((void*)mPemTestCert.c_str(), mPemTestCert.length());			
-			PEM_read_bio_X509(validation_bio, &mX509TestCert, 0, NULL);
-			BIO_free(validation_bio);
-			validation_bio = BIO_new_mem_buf((void*)mPemRootCert.c_str(), mPemRootCert.length());
-			PEM_read_bio_X509(validation_bio, &mX509RootCert, 0, NULL);
-			BIO_free(validation_bio);
-			validation_bio = BIO_new_mem_buf((void*)mPemIntermediateCert.c_str(), mPemIntermediateCert.length());
-			PEM_read_bio_X509(validation_bio, &mX509IntermediateCert, 0, NULL);
-			BIO_free(validation_bio);	
-			validation_bio = BIO_new_mem_buf((void*)mPemChildCert.c_str(), mPemChildCert.length());
-			PEM_read_bio_X509(validation_bio, &mX509ChildCert, 0, NULL);
-			BIO_free(validation_bio);				
-		}
-		~sechandler_basic_test()
-		{
-			LLFile::remove("test_password.dat");
-			LLFile::remove("sechandler_settings.tmp");
-			LLFile::remove("mycertstore.pem");
-			X509_free(mX509TestCert);
-			X509_free(mX509RootCert);
-			X509_free(mX509IntermediateCert);
-			X509_free(mX509ChildCert);
-		}
-	};
-	
-	// Tut templating thingamagic: test group, object and test instance
-	typedef test_group<sechandler_basic_test> sechandler_basic_test_factory;
-	typedef sechandler_basic_test_factory::object sechandler_basic_test_object;
-	tut::sechandler_basic_test_factory tut_test("llsechandler_basic");
-	
-	// ---------------------------------------------------------------------------------------
-	// Test functions 
-	// ---------------------------------------------------------------------------------------
-	// test cert data retrieval
-	template<> template<>
-	void sechandler_basic_test_object::test<1>()
-	
-	{
-		char buffer[4096];
-		LLPointer<LLCertificate> test_cert = new LLBasicCertificate(mPemTestCert);
-		
-		ensure_equals("Resultant pem is correct",
-			   mPemTestCert, test_cert->getPem());
-		std::vector<U8> binary_cert = test_cert->getBinary();
-
-		apr_base64_encode(buffer, (const char *)&binary_cert[0], binary_cert.size());
-		
-		ensure_equals("Der Format is correct", memcmp(buffer, mDerFormat.c_str(), mDerFormat.length()), 0);
-		
-		LLSD llsd_cert = test_cert->getLLSD();
-		std::ostringstream llsd_value;
-		llsd_value << LLSDOStreamer<LLSDNotationFormatter>(llsd_cert) << std::endl;
-		std::string llsd_cert_str = llsd_value.str();
-		ensure_equals("Issuer Name/commonName", 
-			   (std::string)llsd_cert["issuer_name"]["commonName"], "Autoridade Certificadora Raiz Brasileira");
-		ensure_equals("Issure Name/countryName", (std::string)llsd_cert["issuer_name"]["countryName"], "BR");
-		ensure_equals("Issuer Name/localityName", (std::string)llsd_cert["issuer_name"]["localityName"], "Brasilia");
-		ensure_equals("Issuer Name/org name", (std::string)llsd_cert["issuer_name"]["organizationName"], "ICP-Brasil");
-		ensure_equals("IssuerName/org unit", 
-			   (std::string)llsd_cert["issuer_name"]["organizationalUnitName"], "Instituto Nacional de Tecnologia da Informacao - ITI");
-		ensure_equals("IssuerName/state", (std::string)llsd_cert["issuer_name"]["stateOrProvinceName"], "DF");
-		ensure_equals("Issuer name string", 
-			   (std::string)llsd_cert["issuer_name_string"], "CN=Autoridade Certificadora Raiz Brasileira,ST=DF,"
-															   "L=Brasilia,OU=Instituto Nacional de Tecnologia da Informacao - ITI,O=ICP-Brasil,C=BR");
-		ensure_equals("subject Name/commonName", 
-			   (std::string)llsd_cert["subject_name"]["commonName"], "Autoridade Certificadora Raiz Brasileira");
-		ensure_equals("subject Name/countryName", (std::string)llsd_cert["subject_name"]["countryName"], "BR");
-		ensure_equals("subject Name/localityName", (std::string)llsd_cert["subject_name"]["localityName"], "Brasilia");
-		ensure_equals("subject Name/org name", (std::string)llsd_cert["subject_name"]["organizationName"], "ICP-Brasil");
-		ensure_equals("subjectName/org unit", 
-			   (std::string)llsd_cert["subject_name"]["organizationalUnitName"], "Instituto Nacional de Tecnologia da Informacao - ITI");
-		ensure_equals("subjectName/state", (std::string)llsd_cert["subject_name"]["stateOrProvinceName"], "DF");
-		ensure_equals("subject name string", 
-			   (std::string)llsd_cert["subject_name_string"], "CN=Autoridade Certificadora Raiz Brasileira,ST=DF,"
-			                                                    "L=Brasilia,OU=Instituto Nacional de Tecnologia da Informacao - ITI,O=ICP-Brasil,C=BR");
-		
-		ensure_equals("md5 digest", (std::string)llsd_cert["md5_digest"], "96:89:7d:61:d1:55:2b:27:e2:5a:39:b4:2a:6c:44:6f");
-		ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "04");
-		// sha1 digest is giving a weird value, and I've no idea why...feh
-		//ensure_equals("sha1 digest", (std::string)llsd_cert["sha1_digest"], "8e:fd:ca:bc:93:e6:1e:92:5d:4d:1d:ed:18:1a:43:20:a4:67:a1:39");
-		ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2001-11-30T12:58:00Z");
-		ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2011-11-30T23:59:00Z");
-		LLSD expectedKeyUsage = LLSD::emptyArray();
-		expectedKeyUsage.append(LLSD((std::string)"certSigning"));
-		expectedKeyUsage.append(LLSD((std::string)"crlSigning"));
-		ensure("key usage", valueCompareLLSD(llsd_cert["keyUsage"], expectedKeyUsage));
-		ensure("basic constraints", (bool)llsd_cert["basicConstraints"]["CA"]);
-		
-		ensure("x509 is equal", !X509_cmp(mX509TestCert, test_cert->getOpenSSLX509()));
-	}
-
-	
-	// test protected data
-	template<> template<>
-	void sechandler_basic_test_object::test<2>()
-
-	{
-		unsigned char MACAddress[MAC_ADDRESS_BYTES];
-		LLUUID::getNodeID(MACAddress);
-		
-		std::string protected_data = "sUSh3wj77NG9oAMyt3XIhaej3KLZhLZWFZvI6rIGmwUUOmmelrRg0NI9rkOj8ZDpTPxpwToaBT5u"
-		"GQhakdaGLJznr9bHr4/6HIC1bouKj4n2rs4TL6j2WSjto114QdlNfLsE8cbbE+ghww58g8SeyLQO"
-		"nyzXoz+/PBz0HD5SMFDuObccoPW24gmqYySz8YoEWhSwO0pUtEEqOjVRsAJgF5wLAtJZDeuilGsq"
-		"4ZT9Y4wZ9Rh8nnF3fDUL6IGamHe1ClXM1jgBu10F6UMhZbnH4C3aJ2E9+LiOntU+l3iCb2MpkEpr"
-		"82r2ZAMwIrpnirL/xoYoyz7MJQYwUuMvBPToZJrxNSsjI+S2Z+I3iEJAELMAAA==";
-		
-		std::vector<U8> binary_data(apr_base64_decode_len(protected_data.c_str()));
-		apr_base64_decode_binary(&binary_data[0], protected_data.c_str());
-
-		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
-		cipher.decrypt(&binary_data[0], 16);
-		LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES);
-		cipher2.encrypt(&binary_data[0], 16);
-		std::ofstream temp_file("sechandler_settings.tmp", std::ofstream::binary);
-		temp_file.write((const char *)&binary_data[0], binary_data.size());
-		temp_file.close();
-
-		LLPointer<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp",
-																		   "test_password.dat");
-		handler->init();																		
-		// data retrieval for existing data
-		LLSD data = handler->getProtectedData("test_data_type", "test_data_id");
-
-
-		ensure_equals("retrieve existing data1", (std::string)data["data1"], "test_data_1");
-		ensure_equals("retrieve existing data2", (std::string)data["data2"], "test_data_2");
-		ensure_equals("retrieve existing data3", (std::string)data["data3"]["elem1"], "test element1");
-		
-		// data storage
-		LLSD store_data = LLSD::emptyMap();
-		store_data["store_data1"] = "test_store_data1";
-		store_data["store_data2"] = 27;
-		store_data["store_data3"] = LLSD::emptyMap();
-		store_data["store_data3"]["subelem1"] = "test_subelem1";
-		
-		handler->setProtectedData("test_data_type", "test_data_id1", store_data);
-		data = handler->getProtectedData("test_data_type", "test_data_id");
-		
-		data = handler->getProtectedData("test_data_type", "test_data_id");
-		// verify no overwrite of existing data
-		ensure_equals("verify no overwrite 1", (std::string)data["data1"], "test_data_1");
-		ensure_equals("verify no overwrite 2", (std::string)data["data2"], "test_data_2");
-		ensure_equals("verify no overwrite 3", (std::string)data["data3"]["elem1"], "test element1");
-		
-		// verify written data is good
-		data = handler->getProtectedData("test_data_type", "test_data_id1");
-		ensure_equals("verify stored data1", (std::string)data["store_data1"], "test_store_data1");
-		ensure_equals("verify stored data2", (int)data["store_data2"], 27);
-		ensure_equals("verify stored data3", (std::string)data["store_data3"]["subelem1"], "test_subelem1");
-		
-		// verify overwrite works
-		handler->setProtectedData("test_data_type", "test_data_id", store_data);	
-		data = handler->getProtectedData("test_data_type", "test_data_id");
-		ensure_equals("verify overwrite stored data1", (std::string)data["store_data1"], "test_store_data1");
-		ensure_equals("verify overwrite stored data2", (int)data["store_data2"], 27);
-		ensure_equals("verify overwrite stored data3", (std::string)data["store_data3"]["subelem1"], "test_subelem1");
-		
-		// verify other datatype doesn't conflict
-		store_data["store_data3"] = "test_store_data3";
-		store_data["store_data4"] = 28;
-		store_data["store_data5"] = LLSD::emptyMap();
-		store_data["store_data5"]["subelem2"] = "test_subelem2";
-		
-		handler->setProtectedData("test_data_type1", "test_data_id", store_data);	
-		data = handler->getProtectedData("test_data_type1", "test_data_id");
-		ensure_equals("verify datatype stored data3", (std::string)data["store_data3"], "test_store_data3");
-		ensure_equals("verify datatype stored data4", (int)data["store_data4"], 28);
-		ensure_equals("verify datatype stored data5", (std::string)data["store_data5"]["subelem2"], "test_subelem2");	
-		
-		// test data not found
-
-		data = handler->getProtectedData("test_data_type1", "test_data_not_found");
-		ensure("not found", data.isUndefined());
-
-		// cause a 'write' by using 'LLPointer' to delete then instantiate a handler
-		handler = NULL;
-		handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
-		handler->init();
-
-		data = handler->getProtectedData("test_data_type1", "test_data_id");
-		ensure_equals("verify datatype stored data3a", (std::string)data["store_data3"], "test_store_data3");
-		ensure_equals("verify datatype stored data4a", (int)data["store_data4"], 28);
-		ensure_equals("verify datatype stored data5a", (std::string)data["store_data5"]["subelem2"], "test_subelem2");	
-		
-		// rewrite the initial file to verify reloads
-		handler = NULL;
-		std::ofstream temp_file2("sechandler_settings.tmp", std::ofstream::binary);
-		temp_file2.write((const char *)&binary_data[0], binary_data.size());
-		temp_file2.close();
-		
-		// cause a 'write'
-		handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
-		handler->init();		
-		data = handler->getProtectedData("test_data_type1", "test_data_id");
-		ensure("not found", data.isUndefined());
-		
-		handler->deleteProtectedData("test_data_type", "test_data_id");
-		ensure("Deleted data not found", handler->getProtectedData("test_data_type", "test_data_id").isUndefined());
-		
-		LLFile::remove("sechandler_settings.tmp");
-		handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
-		handler->init();		
-		data = handler->getProtectedData("test_data_type1", "test_data_id");
-		ensure("not found", data.isUndefined());
-		handler = NULL;
-		
-		ensure(LLFile::isfile("sechandler_settings.tmp"));
-	}
-	
-	// test credenitals
-	template<> template<>
-	void sechandler_basic_test_object::test<3>()
-	{
-		LLPointer<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
-		handler->init();
-
-		LLSD my_id = LLSD::emptyMap();
-		LLSD my_authenticator = LLSD::emptyMap();
-		my_id["type"] = "test_type";
-		my_id["username"] = "testuser@lindenlab.com";
-		my_authenticator["type"] = "test_auth";
-		my_authenticator["creds"] = "12345";
-
-		// test creation of credentials		
-		LLPointer<LLCredential> my_cred = handler->createCredential("my_grid", my_id, my_authenticator);
-
-		// test retrieval of credential components
-		ensure_equals("basic credential creation: identifier", my_id, my_cred->getIdentifier());
-		ensure_equals("basic credential creation: authenticator", my_authenticator, my_cred->getAuthenticator());
-		ensure_equals("basic credential creation: grid", "my_grid", my_cred->getGrid());
-		
-		// test setting/overwriting of credential components
-		my_id["first_name"] = "firstname";
-		my_id.erase("username");
-		my_authenticator.erase("creds");
-		my_authenticator["hash"] = "6563245";
-		
-		my_cred->setCredentialData(my_id, my_authenticator);
-		ensure_equals("set credential data: identifier", my_id, my_cred->getIdentifier());
-		ensure_equals("set credential data: authenticator", my_authenticator, my_cred->getAuthenticator());
-		ensure_equals("set credential data: grid", "my_grid", my_cred->getGrid());		
-			
-		// test loading of a credential, that hasn't been saved, without
-		// any legacy saved credential data
-		LLPointer<LLCredential> my_new_cred = handler->loadCredential("my_grid2");
-		ensure("unknown credential load test", my_new_cred->getIdentifier().isMap());
-		ensure("unknown credential load test", !my_new_cred->getIdentifier().has("type"));		
-		ensure("unknown credential load test", my_new_cred->getAuthenticator().isMap());
-		ensure("unknown credential load test", !my_new_cred->getAuthenticator().has("type"));	
-		// test saving of a credential
-		handler->saveCredential(my_cred, true);
-
-		// test loading of a known credential
-		my_new_cred = handler->loadCredential("my_grid");
-		ensure_equals("load a known credential: identifier", my_id, my_new_cred->getIdentifier());
-		ensure_equals("load a known credential: authenticator",my_authenticator, my_new_cred->getAuthenticator());
-		ensure_equals("load a known credential: grid", "my_grid", my_cred->getGrid());
-	
-		// test deletion of a credential
-		handler->deleteCredential(my_new_cred);
-
-		ensure("delete credential: identifier", my_new_cred->getIdentifier().isUndefined());
-		ensure("delete credentialt: authenticator", my_new_cred->getIdentifier().isUndefined());
-		ensure_equals("delete credential: grid", "my_grid", my_cred->getGrid());		
-		// load unknown cred
-		
-		my_new_cred = handler->loadCredential("my_grid");
-		ensure("deleted credential load test", my_new_cred->getIdentifier().isMap());
-		ensure("deleted credential load test", !my_new_cred->getIdentifier().has("type"));		
-		ensure("deleted credential load test", my_new_cred->getAuthenticator().isMap());
-		ensure("deleted credential load test", !my_new_cred->getAuthenticator().has("type"));
-		
-		// test loading of an unknown credential with legacy saved username, but without
-		// saved password
-		gFirstName = "myfirstname";
-		gLastName = "mylastname";
-		my_new_cred = handler->loadCredential("my_legacy_grid");
-		ensure_equals("legacy credential with no password: type", 
-					  (const std::string)my_new_cred->getIdentifier()["type"], "agent");
-		ensure_equals("legacy credential with no password: first_name", 
-					  (const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname");
-		ensure_equals("legacy credential with no password: last_name",
-					  (const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname");
-		
-		ensure("legacy credential with no password: no authenticator", my_new_cred->getAuthenticator().isUndefined());
-		
-		// test loading of an unknown credential with legacy saved password and username
-
-		std::string hashed_password = "fSQcLG03eyIWJmkzfyYaKm81dSweLmsxeSAYKGE7fSQ=";		
-		int length = apr_base64_decode_len(hashed_password.c_str());
-		std::vector<char> decoded_password(length);
-		apr_base64_decode(&decoded_password[0], hashed_password.c_str());
-		unsigned char MACAddress[MAC_ADDRESS_BYTES];
-		LLUUID::getNodeID(MACAddress);
-		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
-		cipher.decrypt((U8*)&decoded_password[0], length);
-		LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES);
-		cipher2.encrypt((U8*)&decoded_password[0], length);
-		llofstream password_file("test_password.dat", std::ofstream::binary);
-		password_file.write(&decoded_password[0], length); 
-		password_file.close();
-		
-		my_new_cred = handler->loadCredential("my_legacy_grid2");		
-		ensure_equals("legacy credential with password: type", 
-					  (const std::string)my_new_cred->getIdentifier()["type"], "agent");
-		ensure_equals("legacy credential with password: first_name", 
-					  (const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname");
-		ensure_equals("legacy credential with password: last_name",
-					  (const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname");
-		
-		LLSD legacy_authenticator = my_new_cred->getAuthenticator();
-		ensure_equals("legacy credential with password: type", 
-					  (std::string)legacy_authenticator["type"], 
-					  "hash");
-		ensure_equals("legacy credential with password: algorithm", 
-					  (std::string)legacy_authenticator["algorithm"], 
-					  "md5");	
-		ensure_equals("legacy credential with password: algorithm", 
-					  (std::string)legacy_authenticator["secret"], 
-					  "01234567890123456789012345678901");
-		
-		// test creation of credentials		
-		my_cred = handler->createCredential("mysavedgrid", my_id, my_authenticator);
-		// test save without saving authenticator. 		
-		handler->saveCredential(my_cred, FALSE);
-		my_new_cred = handler->loadCredential("mysavedgrid");	
-		ensure_equals("saved credential without auth", 
-					  (const std::string)my_new_cred->getIdentifier()["type"], "test_type");
-		ensure("no authenticator values were saved", my_new_cred->getAuthenticator().isUndefined());
-	}
-
-	// test cert vector
-	template<> template<>
-	void sechandler_basic_test_object::test<4>()
-	{
-		
-		// validate create from empty vector
-		LLPointer<LLBasicCertificateVector> test_vector = new LLBasicCertificateVector();
-		ensure_equals("when loading with nothing, we should result in no certs in vector", test_vector->size(), 0);
-		
-		test_vector->add(new LLBasicCertificate(mPemTestCert));
-		ensure_equals("one element in vector", test_vector->size(), 1);
-		test_vector->add(new LLBasicCertificate(mPemChildCert));
-		ensure_equals("two elements in vector after add", test_vector->size(), 2);
-		
-		test_vector->add(new LLBasicCertificate(mPemChildCert));
-		ensure_equals("two elements in vector after re-add", test_vector->size(), 2);
-		// validate order
-		X509* test_cert = (*test_vector)[0]->getOpenSSLX509();		
-		ensure("first cert added remains first cert", !X509_cmp(test_cert, mX509TestCert));
-		X509_free(test_cert);
-		
-		test_cert = (*test_vector)[1]->getOpenSSLX509();	
-		ensure("adding a duplicate cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);		
-		
-		//
-		// validate iterator
-		//
-		LLBasicCertificateVector::iterator current_cert = test_vector->begin();
-		LLBasicCertificateVector::iterator copy_current_cert = current_cert;
-		// operator++(int)
-		ensure("validate iterator++ element in vector is expected cert", *current_cert++ == (*test_vector)[0]);
-		ensure("validate 2nd iterator++ element in vector is expected cert", *current_cert++ == (*test_vector)[1]);
-		ensure("validate end iterator++", current_cert == test_vector->end());
-		
-		// copy 
-		ensure("validate copy iterator element in vector is expected cert", *copy_current_cert == (*test_vector)[0]);		
-		
-		// operator--(int)
-		current_cert--;
-		ensure("validate iterator-- element in vector is expected cert", *current_cert-- == (*test_vector)[1]);		
-		ensure("validate iterator-- element in vector is expected cert", *current_cert == (*test_vector)[0]);
-		
-		ensure("begin iterator is equal", current_cert == test_vector->begin());
-		
-		// operator++
-		ensure("validate ++iterator element in vector is expected cert", *++current_cert == (*test_vector)[1]);				
-		ensure("end of cert vector after ++iterator", ++current_cert == test_vector->end());
-		// operator--
-		ensure("validate --iterator element in vector is expected cert", *--current_cert == (*test_vector)[1]);		
-		ensure("validate 2nd --iterator element in vector is expected cert", *--current_cert == (*test_vector)[0]);		
-		
-		// validate remove
-		// validate create from empty vector
-		test_vector = new LLBasicCertificateVector();
-		test_vector->add(new LLBasicCertificate(mPemTestCert));
-		test_vector->add(new LLBasicCertificate(mPemChildCert));
-		test_vector->erase(test_vector->begin());
-		ensure_equals("one element in store after remove", test_vector->size(), 1);
-		test_cert = (*test_vector)[0]->getOpenSSLX509();
-		ensure("validate cert was removed", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);
-		
-		// validate insert
-		test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemChildCert));
-		test_cert = (*test_vector)[0]->getOpenSSLX509();
-		
-		ensure("validate cert was inserted", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);	
-
-		//validate find
-		LLSD find_info = LLSD::emptyMap();
-		test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemRootCert));
-		find_info["issuer_name"] = LLSD::emptyMap();
-		find_info["issuer_name"]["commonName"] = "Roxies intermediate CA";
-		find_info["md5_digest"] = "97:24:c7:4c:d4:ba:2d:0e:9c:a1:18:8e:3a:c6:1f:c3";
-		current_cert = test_vector->find(find_info);
-		ensure("found", current_cert != test_vector->end());
-		ensure("found cert", (*current_cert).get() == (*test_vector)[1].get());
-		find_info["sha1_digest"] = "bad value";
-		current_cert =test_vector->find(find_info);
-		ensure("didn't find cert", current_cert == test_vector->end());		
-	}	
-	
-	// test cert store
-	template<> template<>
-	void sechandler_basic_test_object::test<5>()
-	{
-		// validate load with nothing
-		LLFile::remove("mycertstore.pem");
-		LLPointer<LLBasicCertificateStore> test_store = new LLBasicCertificateStore("mycertstore.pem");
-		ensure_equals("when loading with nothing, we should result in no certs in store", test_store->size(), 0);
-		
-		// validate load with empty file
-		test_store->save();
-		test_store = NULL;
-		test_store = new LLBasicCertificateStore("mycertstore.pem");
-		ensure_equals("when loading with nothing, we should result in no certs in store", test_store->size(), 0);
-		test_store=NULL;
-		
-		// instantiate a cert store from a file
-		llofstream certstorefile("mycertstore.pem", std::ios::out);
-		certstorefile << mPemChildCert << std::endl << mPemTestCert << std::endl;
-		certstorefile.close();
-		// validate loaded certs
-		test_store = new LLBasicCertificateStore("mycertstore.pem");
-		ensure_equals("two elements in store", test_store->size(), 2);
-		
-		// operator[]
-		X509* test_cert = (*test_store)[0]->getOpenSSLX509();
-
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);
-		test_cert = (*test_store)[1]->getOpenSSLX509();
-		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509TestCert));	
-		X509_free(test_cert);
-
-
-		// validate save
-		LLFile::remove("mycertstore.pem");
-		test_store->save();
-		test_store = NULL;
-		test_store = new LLBasicCertificateStore("mycertstore.pem");
-		ensure_equals("two elements in store after save", test_store->size(), 2);				
-		LLCertificateStore::iterator current_cert = test_store->begin();		
-		test_cert = (*current_cert)->getOpenSSLX509();
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		current_cert++;
-		X509_free(test_cert);
-		test_cert = (*current_cert)->getOpenSSLX509();
-		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509TestCert));	
-		X509_free(test_cert);
-		current_cert++;
-		ensure("end of cert store", current_cert == test_store->end());
-		
-	}
-	
-	// cert name wildcard matching
-	template<> template<>
-	void sechandler_basic_test_object::test<6>()
-	{
-		ensure("simple name match", 
-			   _cert_hostname_wildcard_match("foo", "foo"));
-		
-		ensure("simple name match, with end period", 
-			   _cert_hostname_wildcard_match("foo.", "foo."));
-		
-		ensure("simple name match, with begin period", 
-			   _cert_hostname_wildcard_match(".foo", ".foo"));		
-		
-		ensure("simple name match, with subdomain", 
-			   _cert_hostname_wildcard_match("foo.bar", "foo.bar"));	
-		
-		ensure("stutter name match", 
-			   _cert_hostname_wildcard_match("foobbbbfoo", "foo*bbbfoo"));			
-		
-		ensure("simple name match, with beginning wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "*bar"));	
-		
-		ensure("simple name match, with ending wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "foo*"));
-		
-		ensure("simple name match, with beginning null wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "*foobar"));			
-
-		ensure("simple name match, with ending null wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "foobar*"));
-		
-		ensure("simple name match, with embedded wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "f*r"));		
-		
-		ensure("simple name match, with embedded null wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "foo*bar"));
-
-		ensure("simple name match, with dual embedded wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "f*o*ar"));		
-
-		ensure("simple name mismatch", 
-			   !_cert_hostname_wildcard_match("bar", "foo"));
-		
-		ensure("simple name mismatch, with end period", 
-			   !_cert_hostname_wildcard_match("foobar.", "foo."));
-		
-		ensure("simple name mismatch, with begin period", 
-			   !_cert_hostname_wildcard_match(".foobar", ".foo"));		
-		
-		ensure("simple name mismatch, with subdomain", 
-			   !_cert_hostname_wildcard_match("foobar.bar", "foo.bar"));	
-		
-		ensure("simple name mismatch, with beginning wildcard", 
-			   !_cert_hostname_wildcard_match("foobara", "*bar"));	
-		
-		ensure("simple name mismatch, with ending wildcard", 
-			   !_cert_hostname_wildcard_match("oobar", "foo*"));
-		
-		ensure("simple name mismatch, with embedded wildcard", 
-			   !_cert_hostname_wildcard_match("oobar", "f*r"));		
-		
-		ensure("simple name mismatch, with dual embedded wildcard", 
-			   !_cert_hostname_wildcard_match("foobar", "f*d*ar"));
-		
-		ensure("simple wildcard", 
-			   _cert_hostname_wildcard_match("foobar", "*"));
-		
-		ensure("long domain", 
-			   _cert_hostname_wildcard_match("foo.bar.com", "foo.bar.com"));
-		
-		ensure("long domain with multiple wildcards", 
-			   _cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com"));	
-
-		ensure("end periods", 
-			   _cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com."));	
-		
-		ensure("mismatch end period", 
-			   !_cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com"));
-		
-		ensure("mismatch end period2", 
-			   !_cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com."));				
-	}
-	
-	// test cert chain
-	template<> template<>
-	void sechandler_basic_test_object::test<7>()
-	{
-		// validate create from empty chain
-		LLPointer<LLBasicCertificateChain> test_chain = new LLBasicCertificateChain(NULL);
-		ensure_equals("when loading with nothing, we should result in no certs in chain", test_chain->size(), 0);
-
-		// Single cert in the chain.
-		X509_STORE_CTX *test_store = X509_STORE_CTX_new();
-		test_store->cert = mX509ChildCert;		
-		test_store->untrusted = NULL;
-		test_chain = new LLBasicCertificateChain(test_store);
-		X509_STORE_CTX_free(test_store);
-		ensure_equals("two elements in store", test_chain->size(), 1);		
-		X509* test_cert = (*test_chain)[0]->getOpenSSLX509();
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);		
-		
-		// cert + CA
-		
-		test_store = X509_STORE_CTX_new();
-		test_store->cert = mX509ChildCert;
-		test_store->untrusted = sk_X509_new_null();
-		sk_X509_push(test_store->untrusted, mX509IntermediateCert);
-		test_chain = new LLBasicCertificateChain(test_store);
-		X509_STORE_CTX_free(test_store);
-		ensure_equals("two elements in store", test_chain->size(), 2);	
-		test_cert = (*test_chain)[0]->getOpenSSLX509();
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);
-		test_cert = (*test_chain)[1]->getOpenSSLX509();
-		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));	
-		X509_free(test_cert);
-
-		// cert + nonrelated
-		
-		test_store = X509_STORE_CTX_new();
-		test_store->cert = mX509ChildCert;
-		test_store->untrusted = sk_X509_new_null();
-		sk_X509_push(test_store->untrusted, mX509TestCert);
-		test_chain = new LLBasicCertificateChain(test_store);
-		X509_STORE_CTX_free(test_store);
-		ensure_equals("two elements in store", test_chain->size(), 1);	
-		test_cert = (*test_chain)[0]->getOpenSSLX509();
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);
-		
-		// cert + CA + nonrelated
-		test_store = X509_STORE_CTX_new();
-		test_store->cert = mX509ChildCert;
-		test_store->untrusted = sk_X509_new_null();
-		sk_X509_push(test_store->untrusted, mX509IntermediateCert);
-		sk_X509_push(test_store->untrusted, mX509TestCert);
-		test_chain = new LLBasicCertificateChain(test_store);
-		X509_STORE_CTX_free(test_store);
-		ensure_equals("two elements in store", test_chain->size(), 2);	
-		test_cert = (*test_chain)[0]->getOpenSSLX509();
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);
-		test_cert = (*test_chain)[1]->getOpenSSLX509();
-		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));	
-		X509_free(test_cert);
-
-		// cert + intermediate + CA 
-		test_store = X509_STORE_CTX_new();
-		test_store->cert = mX509ChildCert;
-		test_store->untrusted = sk_X509_new_null();
-		sk_X509_push(test_store->untrusted, mX509IntermediateCert);
-		sk_X509_push(test_store->untrusted, mX509RootCert);
-		test_chain = new LLBasicCertificateChain(test_store);
-		X509_STORE_CTX_free(test_store);
-		ensure_equals("three elements in store", test_chain->size(), 3);	
-		test_cert = (*test_chain)[0]->getOpenSSLX509();
-		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
-		X509_free(test_cert);
-		test_cert = (*test_chain)[1]->getOpenSSLX509();
-		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));	
-		X509_free(test_cert);
-
-		test_cert = (*test_chain)[2]->getOpenSSLX509();
-		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509RootCert));	
-		X509_free(test_cert);		
-	}
-	// test cert validation
-	template<> template<>
-	void sechandler_basic_test_object::test<8>()
-	{
-		// start with a trusted store with our known root cert
-		LLFile::remove("mycertstore.pem");
-		LLPointer<LLBasicCertificateStore> test_store = new LLBasicCertificateStore("mycertstore.pem");
-		test_store->add(new LLBasicCertificate(mX509RootCert));
-		LLSD validation_params;
-		
-		// validate basic trust for a chain containing only the intermediate cert.  (1 deep)
-		LLPointer<LLBasicCertificateChain> test_chain = new LLBasicCertificateChain(NULL);
-
-		test_chain->add(new LLBasicCertificate(mX509IntermediateCert));
-
-		test_chain->validate(0, test_store, validation_params);
-
-		// add the root certificate to the chain and revalidate
-		test_chain->add(new LLBasicCertificate(mX509RootCert));	
-		test_chain->validate(0, test_store, validation_params);
-
-		// add the child cert at the head of the chain, and revalidate (3 deep chain)
-		test_chain->insert(test_chain->begin(), new LLBasicCertificate(mX509ChildCert));
-		test_chain->validate(0, test_store, validation_params);
-
-		// basic failure cases
-		test_chain = new LLBasicCertificateChain(NULL);
-		//validate with only the child cert
-		test_chain->add(new LLBasicCertificate(mX509ChildCert));
-		ensure_throws("no CA, with only a child cert", 
-					  LLCertValidationTrustException, 
-					  (*test_chain)[0],
-					  test_chain->validate, 
-					  VALIDATION_POLICY_TRUSTED, 
-					  test_store, 
-					  validation_params);
-
-
-		// validate without the trust flag.
-		test_chain->validate(0, test_store, validation_params);		
-
-		// clear out the store
-		test_store = new LLBasicCertificateStore("mycertstore.pem");
-		// append the intermediate cert
-		test_chain->add(new LLBasicCertificate(mX509IntermediateCert));		
-		ensure_throws("no CA, with child and intermediate certs", 
-					  LLCertValidationTrustException, 
-					  (*test_chain)[1],
-					  test_chain->validate, 
-					  VALIDATION_POLICY_TRUSTED, 
-					  test_store, 
-					  validation_params);
-		// validate without the trust flag
-		test_chain->validate(0, test_store, validation_params);
-
-		// Test time validity
-		LLSD child_info = (*test_chain)[0]->getLLSD();
-		validation_params = LLSD::emptyMap();
-		validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() + 1.0);  
-		test_chain->validate(VALIDATION_POLICY_TIME, test_store, validation_params);
-
-		validation_params = LLSD::emptyMap();		
-		validation_params[CERT_VALIDATION_DATE] = child_info[CERT_VALID_FROM].asDate();
-		
-		validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() - 1.0);
- 		
-		// test not yet valid
-		ensure_throws("Child cert not yet valid", 
-					  LLCertValidationExpirationException, 
-					  (*test_chain)[0],
-					  test_chain->validate, 
-					  VALIDATION_POLICY_TIME, 
-					  test_store, 
-					  validation_params);	
-		validation_params = LLSD::emptyMap();		
-		validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_TO].asDate().secondsSinceEpoch() + 1.0);
- 		
-		// test cert expired
-		ensure_throws("Child cert expired", 
-					  LLCertValidationExpirationException, 
-					  (*test_chain)[0],
-					  test_chain->validate, 
-					  VALIDATION_POLICY_TIME, 
-					  test_store, 
-					  validation_params);
-
-		// test SSL KU
-		// validate basic trust for a chain containing child and intermediate.
-		test_chain = new LLBasicCertificateChain(NULL);
-		test_chain->add(new LLBasicCertificate(mX509ChildCert));
-		test_chain->add(new LLBasicCertificate(mX509IntermediateCert));
-		test_chain->validate(VALIDATION_POLICY_SSL_KU, test_store, validation_params);	
-
-		test_chain = new LLBasicCertificateChain(NULL);
-		test_chain->add(new LLBasicCertificate(mX509TestCert));
-
-		ensure_throws("Cert doesn't have ku", 
-					  LLCertKeyUsageValidationException, 
-					  (*test_chain)[0],
-					  test_chain->validate, 
-					  VALIDATION_POLICY_SSL_KU, 
-					  test_store, 
-					  validation_params);
-	}
-};
-
diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp
deleted file mode 100644
index 803020dc7a5afbccf97d093dcb804eb3a8308ebb..0000000000000000000000000000000000000000
--- a/indra/newview/tests/llslurl_test.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/** 
- * @file llsecapi_test.cpp
- * @author Roxie
- * @date 2009-02-10
- * @brief Test the sec api functionality
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 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 maps.secondlife.com2.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 "../llviewerprecompiledheaders.h"
-#include "../llviewernetwork.h"
-#include "../test/lltut.h"
-#include "../llslurl.h"
-#include "../../llxml/llcontrol.h"
-#include "llsdserialize.h"
-//----------------------------------------------------------------------------               
-// Mock objects for the dependencies of the code we're testing                               
-
-LLControlGroup::LLControlGroup(const std::string& name)
-: LLInstanceTracker<LLControlGroup, std::string>(name) {}
-LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
-                                   const std::string& initial_val,
-                                   const std::string& comment,
-                                   BOOL persist) {return TRUE;}
-void LLControlGroup::setString(const std::string& name, const std::string& val){}
-
-std::string gCmdLineLoginURI;
-std::string gCmdLineGridChoice;
-std::string gCmdLineHelperURI;
-std::string gLoginPage;
-std::string gCurrentGrid;
-std::string LLControlGroup::getString(const std::string& name)
-{
-	if (name == "CmdLineGridChoice")
-		return gCmdLineGridChoice;
-	else if (name == "CmdLineHelperURI")
-		return gCmdLineHelperURI;
-	else if (name == "LoginPage")
-		return gLoginPage;
-	else if (name == "CurrentGrid")
-		return gCurrentGrid;
-	return "";
-}
-
-LLSD LLControlGroup::getLLSD(const std::string& name)
-{
-	if (name == "CmdLineLoginURI")
-	{
-		if(!gCmdLineLoginURI.empty())
-		{
-			return LLSD(gCmdLineLoginURI);
-		}
-	}
-	return LLSD();
-}
-
-
-LLControlGroup gSavedSettings("test");
-
-// -------------------------------------------------------------------------------------------
-// TUT
-// -------------------------------------------------------------------------------------------
-namespace tut
-{
-	// Test wrapper declaration : wrapping nothing for the moment
-	struct slurlTest
-	{
-		slurlTest()
-		{	
-			LLGridManager::getInstance()->initialize(std::string(""));
-		}
-		~slurlTest()
-		{
-		}
-	};
-	
-	// Tut templating thingamagic: test group, object and test instance
-	typedef test_group<slurlTest> slurlTestFactory;
-	typedef slurlTestFactory::object slurlTestObject;
-	tut::slurlTestFactory tut_test("llslurl");
-	
-	// ---------------------------------------------------------------------------------------
-	// Test functions 
-	// ---------------------------------------------------------------------------------------
-	// construction from slurl string
-	template<> template<>
-	void slurlTestObject::test<1>()
-	{
-		LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com");
-		
-		LLSLURL slurl = LLSLURL("");
-		ensure_equals("null slurl", (int)slurl.getType(), LLSLURL::LAST_LOCATION);
-		
-		slurl = LLSLURL("http://slurl.com/secondlife/myregion");
-		ensure_equals("slurl.com slurl, region only - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("slurl.com slurl, region only", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/myregion/128/128/0");
-		
-		slurl = LLSLURL("http://maps.secondlife.com/secondlife/myregion/1/2/3");
-		ensure_equals("maps.secondlife.com slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("maps.secondlife.com slurl, region + coords", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/myregion/1/2/3");
-
-		slurl = LLSLURL("secondlife://myregion");
-		ensure_equals("secondlife: slurl, region only - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("secondlife: slurl, region only", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/myregion/128/128/0");
-		
-		slurl = LLSLURL("secondlife://myregion/1/2/3");
-		ensure_equals("secondlife: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("secondlife slurl, region + coords", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/myregion/1/2/3");
-		
-		slurl = LLSLURL("/myregion");
-		ensure_equals("/region slurl, region- type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("/region slurl, region ", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/myregion/128/128/0");
-		
-		slurl = LLSLURL("/myregion/1/2/3");
-		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("/ slurl, region + coords", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/myregion/1/2/3");	
-		
-		slurl = LLSLURL("my region/1/2/3");
-		ensure_equals(" slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals(" slurl, region + coords", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/my%20region/1/2/3");	
-		
-		slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3");
-		ensure_equals("grid slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("grid slurl, region + coords", slurl.getSLURLString(), 
-					  "https://my.grid.com/region/my%20region/1/2/3");	
-		
-		slurl = LLSLURL("https://my.grid.com/region/my region");
-		ensure_equals("grid slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("grid slurl, region + coords", slurl.getSLURLString(), 
-					  "https://my.grid.com/region/my%20region/128/128/0");
-		
-		LLGridManager::getInstance()->setGridChoice("foo.bar.com");		
-		slurl = LLSLURL("/myregion/1/2/3");
-		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("/ slurl, region + coords", slurl.getSLURLString(), 
-					  "https://foo.bar.com/region/myregion/1/2/3");		
-		
-		slurl = LLSLURL("myregion/1/2/3");
-		ensure_equals(": slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals(" slurl, region + coords", slurl.getSLURLString(), 
-					  "https://foo.bar.com/region/myregion/1/2/3");		
-		
-		slurl = LLSLURL(LLSLURL::SIM_LOCATION_HOME);
-		ensure_equals("home", slurl.getType(), LLSLURL::HOME_LOCATION);
-
-		slurl = LLSLURL(LLSLURL::SIM_LOCATION_LAST);
-		ensure_equals("last", slurl.getType(), LLSLURL::LAST_LOCATION);
-		
-		slurl = LLSLURL("secondlife:///app/foo/bar?12345");
-		ensure_equals("app", slurl.getType(), LLSLURL::APP);		
-		ensure_equals("appcmd", slurl.getAppCmd(), "foo");
-		ensure_equals("apppath", slurl.getAppPath().size(), 1);
-		ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar");
-		ensure_equals("appquery", slurl.getAppQuery(), "12345");
-		ensure_equals("grid1", "foo.bar.com", slurl.getGrid());
-	
-		slurl = LLSLURL("secondlife://Aditi/app/foo/bar?12345");
-		ensure_equals("app", slurl.getType(), LLSLURL::APP);		
-		ensure_equals("appcmd", slurl.getAppCmd(), "foo");
-		ensure_equals("apppath", slurl.getAppPath().size(), 1);
-		ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar");
-		ensure_equals("appquery", slurl.getAppQuery(), "12345");
-		ensure_equals("grid2", "util.aditi.lindenlab.com", slurl.getGrid());		
-
-		LLGridManager::getInstance()->setGridChoice("foo.bar.com");			
-		slurl = LLSLURL("secondlife:///secondlife/myregion/1/2/3");
-		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("location", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("region" , "myregion", slurl.getRegion());
-		ensure_equals("grid3", "util.agni.lindenlab.com", slurl.getGrid());
-				
-		slurl = LLSLURL("secondlife://Aditi/secondlife/myregion/1/2/3");
-		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("location", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("region" , "myregion", slurl.getRegion());
-		ensure_equals("grid4", "util.aditi.lindenlab.com", slurl.getGrid());		
-		
-		slurl = LLSLURL("https://my.grid.com/app/foo/bar?12345");
-		ensure_equals("app", slurl.getType(), LLSLURL::APP);		
-		ensure_equals("appcmd", slurl.getAppCmd(), "foo");
-		ensure_equals("apppath", slurl.getAppPath().size(), 1);
-		ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar");
-		ensure_equals("appquery", slurl.getAppQuery(), "12345");	
-		
-	}
-	
-	// construction from grid/region/vector combos
-	template<> template<>
-	void slurlTestObject::test<2>()
-	{
-		LLSLURL slurl = LLSLURL("mygrid.com", "my region");
-		ensure_equals("grid/region - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals("grid/region", slurl.getSLURLString(), 
-					  "https://mygrid.com/region/my%20region/128/128/0");	
-		
-		slurl = LLSLURL("mygrid.com", "my region", LLVector3(1,2,3));
-		ensure_equals("grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals(" grid/region/vector", slurl.getSLURLString(), 
-					  "https://mygrid.com/region/my%20region/1/2/3");			
-
-		LLGridManager::getInstance()->setGridChoice("foo.bar.com.bar");			
-		slurl = LLSLURL("my region", LLVector3(1,2,3));
-		ensure_equals("grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals(" grid/region/vector", slurl.getSLURLString(), 
-					  "https://foo.bar.com.bar/region/my%20region/1/2/3");	
-		
-		LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com");	
-		slurl = LLSLURL("my region", LLVector3(1,2,3));
-		ensure_equals("default grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION);
-		ensure_equals(" default grid/region/vector", slurl.getSLURLString(), 
-					  "http://maps.secondlife.com/secondlife/my%20region/1/2/3");	
-		
-	}
-	// Accessors
-	template<> template<>
-	void slurlTestObject::test<3>()
-	{
-		LLSLURL slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3");
-		ensure_equals("login string", slurl.getLoginString(), "uri:my region&amp;1&amp;2&amp;3");
-		ensure_equals("location string", slurl.getLocationString(), "my region/1/2/3");
-		ensure_equals("grid", slurl.getGrid(), "my.grid.com");
-		ensure_equals("region", slurl.getRegion(), "my region");
-		ensure_equals("position", slurl.getPosition(), LLVector3(1, 2, 3));
-		
-	}
-}
diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp
deleted file mode 100644
index f9f42cfc8620f0344d8886676215bfcf15e21a00..0000000000000000000000000000000000000000
--- a/indra/newview/tests/llviewernetwork_test.cpp
+++ /dev/null
@@ -1,486 +0,0 @@
-/** 
- * @file llviewernetwork_test.cpp
- * @author Roxie
- * @date 2009-03-9
- * @brief Test the viewernetwork functionality
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * 
- * Copyright (c) 2009, Linden Research, Inc.
- * 
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden LregisterSecAPIab
- * 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 "../llviewerprecompiledheaders.h"
-#include "../llviewernetwork.h"
-#include "../test/lltut.h"
-#include "../../llxml/llcontrol.h"
-#include "llfile.h"
-
-//----------------------------------------------------------------------------               
-// Mock objects for the dependencies of the code we're testing                               
-
-LLControlGroup::LLControlGroup(const std::string& name)
-: LLInstanceTracker<LLControlGroup, std::string>(name) {}
-LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
-                                   const std::string& initial_val,
-                                   const std::string& comment,
-                                   BOOL persist) {return TRUE;}
-void LLControlGroup::setString(const std::string& name, const std::string& val){}
-
-std::string gCmdLineLoginURI;
-std::string gCmdLineGridChoice;
-std::string gCmdLineHelperURI;
-std::string gLoginPage;
-std::string gCurrentGrid;
-std::string LLControlGroup::getString(const std::string& name)
-{
-	if (name == "CmdLineGridChoice")
-		return gCmdLineGridChoice;
-	else if (name == "CmdLineHelperURI")
-		return gCmdLineHelperURI;
-	else if (name == "LoginPage")
-		return gLoginPage;
-	else if (name == "CurrentGrid")
-		return gCurrentGrid;
-	return "";
-}
-
-LLSD LLControlGroup::getLLSD(const std::string& name)
-{
-	if (name == "CmdLineLoginURI")
-	{
-		if(!gCmdLineLoginURI.empty())
-		{
-			return LLSD(gCmdLineLoginURI);
-		}
-	}
-	return LLSD();
-}
-
-
-LLControlGroup gSavedSettings("test");
-
-const char *gSampleGridFile = "<llsd><map>"
-"<key>grid1</key><map>"
-"  <key>favorite</key><integer>1</integer>"
-"  <key>helper_uri</key><string>https://helper1/helpers/</string>"
-"  <key>label</key><string>mylabel</string>"
-"  <key>login_page</key><string>loginpage</string>"
-"  <key>login_uri</key><array><string>myloginuri</string></array>"
-"  <key>name</key><string>grid1</string>"
-"  <key>visible</key><integer>1</integer>"
-"  <key>credential_type</key><string>agent</string>"
-"  <key>grid_login_id</key><string>MyGrid</string>"
-"</map>"
-"<key>util.agni.lindenlab.com</key><map>"
-"  <key>favorite</key><integer>1</integer>"
-"  <key>helper_uri</key><string>https://helper1/helpers/</string>"
-"  <key>label</key><string>mylabel</string>"
-"  <key>login_page</key><string>loginpage</string>"
-"  <key>login_uri</key><array><string>myloginuri</string></array>"
-"  <key>name</key><string>util.agni.lindenlab.com</string>"
-"</map></map></llsd>";
-// -------------------------------------------------------------------------------------------
-// TUT
-// -------------------------------------------------------------------------------------------
-namespace tut
-{
-  // Test wrapper declaration : wrapping nothing for the moment
-  struct viewerNetworkTest
-	{
-		viewerNetworkTest()
-		{
-			LLFile::remove("grid_test.xml");
-			gCmdLineLoginURI.clear();
-			gCmdLineGridChoice.clear();
-			gCmdLineHelperURI.clear();
-			gLoginPage.clear();
-			gCurrentGrid.clear();			
-		}
-		~viewerNetworkTest()
-		{
-			LLFile::remove("grid_test.xml");
-		}
-	};
-	
-	// Tut templating thingamagic: test group, object and test instance
-	typedef test_group<viewerNetworkTest> viewerNetworkTestFactory;
-	typedef viewerNetworkTestFactory::object viewerNetworkTestObject;
-	tut::viewerNetworkTestFactory tut_test("llviewernetwork");
-	
-	// ---------------------------------------------------------------------------------------
-	// Test functions 
-	// ---------------------------------------------------------------------------------------
-	// initialization without a grid file
-	template<> template<>
-	void viewerNetworkTestObject::test<1>()
-	{
-
-		LLGridManager *manager = LLGridManager::getInstance();
-		// grid file doesn't exist
-		manager->initialize("grid_test.xml");
-		// validate that some of the defaults are available.
-		std::map<std::string, std::string> known_grids = manager->getKnownGrids();
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 18);
-		ensure_equals("Agni has the right name and label", 
-					  known_grids[std::string("util.agni.lindenlab.com")], std::string("Agni"));
-#else // LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("Known grids is a string-string map of size 2", known_grids.size(), 2);
-		ensure_equals("Agni has the right name and label", 
-					  known_grids[std::string("util.agni.lindenlab.com")], std::string("Secondlife.com"));		
-#endif // LL_RELEASE_FOR_DOWNLOAD
-
-
-		ensure_equals("None exists", known_grids[""], "None");
-		
-		LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com");
-		ensure("Grid info for agni is a map", grid.isMap());
-		ensure_equals("name is correct for agni", 
-					  grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com"));
-#ifndef LL_RELEASE_FOR_DOWNLOAD		
-		ensure_equals("label is correct for agni", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("Agni"));
-#else // LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("label is correct for agni", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com"));		
-#endif // LL_RELEASE_FOR_DOWNLOAD
-		ensure("Login URI is an array", 
-			   grid[GRID_LOGIN_URI_VALUE].isArray());
-		ensure_equals("Agni login uri is correct", 
-					  grid[GRID_LOGIN_URI_VALUE][0].asString(), 
-					  std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi"));
-		ensure_equals("Agni helper uri is correct",
-					  grid[GRID_HELPER_URI_VALUE].asString(), 
-					  std::string("https://secondlife.com/helpers/"));
-		ensure_equals("Agni login page is correct",
-					  grid[GRID_LOGIN_PAGE_VALUE].asString(), 
-					  std::string("http://secondlife.com/app/login/"));
-		ensure("Agni is a favorite",
-			   grid.has(GRID_IS_FAVORITE_VALUE));
-		ensure("Agni is a system grid", 
-			   grid.has(GRID_IS_SYSTEM_GRID_VALUE));
-		ensure("Grid file wasn't greated as it wasn't saved", 
-			   !LLFile::isfile("grid_test.xml"));
-	}
-	
-	// initialization with a grid file
-	template<> template<>
-	void viewerNetworkTestObject::test<2>()
-	{
-		llofstream gridfile("grid_test.xml");
-		gridfile << gSampleGridFile;
-		gridfile.close();
-		
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("adding a grid via a grid file increases known grid size", 
-					  known_grids.size(), 19);
-		ensure_equals("Agni is still there after we've added a grid via a grid file", 
-					  known_grids["util.agni.lindenlab.com"], std::string("Agni"));
-	
-#else
-		ensure_equals("adding a grid via a grid file increases known grid size", 
-					  known_grids.size(), 3);
-		ensure_equals("Agni is still there after we've added a grid via a grid file", 
-					  known_grids["util.agni.lindenlab.com"], std::string("Secondlife.com"));
-
-#endif
-	
-		
-		// assure Agni doesn't get overwritten
-		LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com");
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("Agni grid label was not modified by grid file", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("Agni"));
-#else \\ LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("Agni grid label was not modified by grid file", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com"));
-#endif \\ LL_RELEASE_FOR_DOWNLOAD
-		
-		ensure_equals("Agni name wasn't modified by grid file",
-					  grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com"));
-		ensure("Agni grid URI is still an array after grid file", 
-			   grid[GRID_LOGIN_URI_VALUE].isArray());
-		ensure_equals("Agni login uri still the same after grid file", 
-					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  
-					  std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi"));
-		ensure_equals("Agni helper uri still the same after grid file", 
-					  grid[GRID_HELPER_URI_VALUE].asString(), 
-					  std::string("https://secondlife.com/helpers/"));
-		ensure_equals("Agni login page the same after grid file", 
-					  grid[GRID_LOGIN_PAGE_VALUE].asString(), 
-					  std::string("http://secondlife.com/app/login/"));
-		ensure("Agni still a favorite after grid file", 
-			   grid.has(GRID_IS_FAVORITE_VALUE));
-		ensure("Agni system grid still set after grid file", 
-			   grid.has(GRID_IS_SYSTEM_GRID_VALUE));
-		
-		ensure_equals("Grid file adds to name<->label map", 
-					  known_grids["grid1"], std::string("mylabel"));
-		grid = LLGridManager::getInstance()->getGridInfo("grid1");
-		ensure_equals("grid file grid name is set",
-					  grid[GRID_VALUE].asString(), std::string("grid1"));
-		ensure_equals("grid file label is set", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("mylabel"));
-		ensure("grid file login uri is an array",
-			   grid[GRID_LOGIN_URI_VALUE].isArray());
-		ensure_equals("grid file login uri is set",
-					  grid[GRID_LOGIN_URI_VALUE][0].asString(), 
-					  std::string("myloginuri"));
-		ensure_equals("grid file helper uri is set",
-					  grid[GRID_HELPER_URI_VALUE].asString(), 
-					  std::string("https://helper1/helpers/"));
-		ensure_equals("grid file login page is set",
-					  grid[GRID_LOGIN_PAGE_VALUE].asString(), 
-					  std::string("loginpage"));
-		ensure("grid file favorite is set",
-			   grid.has(GRID_IS_FAVORITE_VALUE));
-		ensure("grid file isn't a system grid",
-			   !grid.has(GRID_IS_SYSTEM_GRID_VALUE));		
-		ensure("Grid file still exists after loading", 
-			   LLFile::isfile("grid_test.xml"));
-	}
-	
-	// Initialize via command line
-	
-	template<> template<>
-	void viewerNetworkTestObject::test<3>()
-	{	
-		gCmdLineLoginURI = "https://my.login.uri/cgi-bin/login.cgi";
-		
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		// with single login uri specified.
-		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure_equals("adding a command line grid increases known grid size", 
-					  known_grids.size(), 19);
-		ensure_equals("Command line grid is added to the list of grids", 
-					  known_grids["my.login.uri"], std::string("my.login.uri"));
-		LLSD grid = LLGridManager::getInstance()->getGridInfo("my.login.uri");
-		ensure_equals("Command line grid name is set",
-					  grid[GRID_VALUE].asString(), std::string("my.login.uri"));
-		ensure_equals("Command line grid label is set", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("my.login.uri"));
-		ensure("Command line grid login uri is an array",
-			   grid[GRID_LOGIN_URI_VALUE].isArray());
-		ensure_equals("Command line grid login uri is set",
-					  grid[GRID_LOGIN_URI_VALUE][0].asString(), 
-					  std::string("https://my.login.uri/cgi-bin/login.cgi"));
-		ensure_equals("Command line grid helper uri is set",
-					  grid[GRID_HELPER_URI_VALUE].asString(), 
-					  std::string("https://my.login.uri/helpers/"));
-		ensure_equals("Command line grid login page is set",
-					  grid[GRID_LOGIN_PAGE_VALUE].asString(), 
-					  std::string("http://my.login.uri/app/login/"));
-		ensure("Command line grid favorite is set",
-			   !grid.has(GRID_IS_FAVORITE_VALUE));
-		ensure("Command line grid isn't a system grid",
-			   !grid.has(GRID_IS_SYSTEM_GRID_VALUE));		
-		
-		// now try a command line with a custom grid identifier
-		gCmdLineGridChoice = "mycustomgridchoice";		
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure_equals("adding a command line grid with custom name increases known grid size", 
-					  known_grids.size(), 19);
-		ensure_equals("Custom Command line grid is added to the list of grids", 
-					  known_grids["mycustomgridchoice"], std::string("mycustomgridchoice"));
-		grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice");
-		ensure_equals("Custom Command line grid name is set",
-					  grid[GRID_VALUE].asString(), std::string("mycustomgridchoice"));
-		ensure_equals("Custom Command line grid label is set", 
-					  grid[GRID_LABEL_VALUE].asString(), std::string("mycustomgridchoice"));		
-		ensure("Custom Command line grid login uri is an array",
-			   grid[GRID_LOGIN_URI_VALUE].isArray());
-		ensure_equals("Custom Command line grid login uri is set",
-					  grid[GRID_LOGIN_URI_VALUE][0].asString(), 
-					  std::string("https://my.login.uri/cgi-bin/login.cgi"));
-		
-		// add a helperuri
-		gCmdLineHelperURI = "myhelperuri";
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice");		
-		ensure_equals("Validate command line helper uri", 
-					  grid[GRID_HELPER_URI_VALUE].asString(), std::string("myhelperuri"));		
-		
-		// add a login page
-		gLoginPage = "myloginpage";
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice");		
-		ensure_equals("Validate command line helper uri", 
-					  grid[GRID_LOGIN_PAGE_VALUE].asString(), std::string("myloginpage"));			
-	}
-	
-	// validate grid selection
-	template<> template<>
-	void viewerNetworkTestObject::test<4>()
-	{	
-		LLSD loginURI = LLSD::emptyArray();
-		LLSD grid = LLSD::emptyMap();
-		// adding a grid with simply a name will populate the values.
-		grid[GRID_VALUE] = "myaddedgrid";
-
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		LLGridManager::getInstance()->addGrid(grid);
-		LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com");
-#ifndef LL_RELEASE_FOR_DOWNLOAD		
-		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Agni"));
-#else // LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Secondlife.com"));		
-#endif // LL_RELEASE_FOR_DOWNLOAD
-		ensure_equals("getGrid", LLGridManager::getInstance()->getGrid(), 
-					  std::string("util.agni.lindenlab.com"));
-		ensure_equals("getHelperURI", LLGridManager::getInstance()->getHelperURI(), 
-					  std::string("https://secondlife.com/helpers/"));
-		ensure_equals("getLoginPage", LLGridManager::getInstance()->getLoginPage(), 
-					  std::string("http://secondlife.com/app/login/"));
-		ensure_equals("getLoginPage2", LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"), 
-					  std::string("http://secondlife.com/app/login/"));
-		ensure("Is Agni a production grid", LLGridManager::getInstance()->isInProductionGrid());		
-		std::vector<std::string> uris;
-		LLGridManager::getInstance()->getLoginURIs(uris);
-		ensure_equals("getLoginURIs size", uris.size(), 1);
-		ensure_equals("getLoginURIs", uris[0], 
-					  std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi"));
-		LLGridManager::getInstance()->setGridChoice("myaddedgrid");
-		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("myaddedgrid"));		
-		ensure("Is myaddedgrid a production grid", !LLGridManager::getInstance()->isInProductionGrid());
-		
-		LLGridManager::getInstance()->setFavorite();
-		grid = LLGridManager::getInstance()->getGridInfo("myaddedgrid");
-		ensure("setting favorite", grid.has(GRID_IS_FAVORITE_VALUE));
-	}
-	
-	// name based grid population
-	template<> template<>
-	void viewerNetworkTestObject::test<5>()
-	{
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		LLSD grid = LLSD::emptyMap();
-		// adding a grid with simply a name will populate the values.
-		grid[GRID_VALUE] = "myaddedgrid";
-		LLGridManager::getInstance()->addGrid(grid);
-		grid = LLGridManager::getInstance()->getGridInfo("myaddedgrid");
-		
-		ensure_equals("name based grid has name value", 
-					  grid[GRID_VALUE].asString(),
-					  std::string("myaddedgrid"));
-		ensure_equals("name based grid has label value", 
-					  grid[GRID_LABEL_VALUE].asString(),
-					  std::string("myaddedgrid"));
-		ensure_equals("name based grid has name value", 
-					  grid[GRID_HELPER_URI_VALUE].asString(),
-					  std::string("https://myaddedgrid/helpers/"));
-		ensure_equals("name based grid has name value", 
-					  grid[GRID_LOGIN_PAGE_VALUE].asString(),
-					  std::string("http://myaddedgrid/app/login/"));
-		ensure("name based grid has array loginuri", 
-			   grid[GRID_LOGIN_URI_VALUE].isArray());
-		ensure_equals("name based grid has single login uri value",
-			   grid[GRID_LOGIN_URI_VALUE].size(), 1);
-		ensure_equals("Name based grid login uri is correct",
-					  grid[GRID_LOGIN_URI_VALUE][0].asString(),
-					  std::string("https://myaddedgrid/cgi-bin/login.cgi"));
-		ensure("name based grid is not a favorite yet", 
-			   !grid.has(GRID_IS_FAVORITE_VALUE));
-		ensure("name based grid does not have system setting",
-			   !grid.has(GRID_IS_SYSTEM_GRID_VALUE));
-		
-		llofstream gridfile("grid_test.xml");
-		gridfile << gSampleGridFile;
-		gridfile.close();
-	}
-	
-	// persistence of the grid list with an empty gridfile.
-	template<> template<>
-	void viewerNetworkTestObject::test<6>()
-	{
-		// try with initial grid list without a grid file,
-		// without setting the grid to a saveable favorite.
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		LLSD grid = LLSD::emptyMap();
-		grid[GRID_VALUE] = std::string("mynewgridname");
-		LLGridManager::getInstance()->addGrid(grid);
-		LLGridManager::getInstance()->saveFavorites();
-		ensure("Grid file exists after saving", 
-			   LLFile::isfile("grid_test.xml"));
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		// should not be there
-		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure("New grid wasn't added to persisted list without being marked a favorite",
-					  known_grids.find(std::string("mynewgridname")) == known_grids.end());
-		
-		// mark a grid a favorite to make sure it's persisted
-		LLGridManager::getInstance()->addGrid(grid);
-		LLGridManager::getInstance()->setGridChoice("mynewgridname");
-		LLGridManager::getInstance()->setFavorite();
-		LLGridManager::getInstance()->saveFavorites();
-		ensure("Grid file exists after saving", 
-			   LLFile::isfile("grid_test.xml"));
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		// should not be there
-		known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure("New grid wasn't added to persisted list after being marked a favorite",
-					  known_grids.find(std::string("mynewgridname")) !=
-					  known_grids.end());
-	}
-	
-	// persistence of the grid file with existing gridfile
-	template<> template<>
-	void viewerNetworkTestObject::test<7>()
-	{
-		
-		llofstream gridfile("grid_test.xml");
-		gridfile << gSampleGridFile;
-		gridfile.close();
-		
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		LLSD grid = LLSD::emptyMap();
-		grid[GRID_VALUE] = std::string("mynewgridname");
-		LLGridManager::getInstance()->addGrid(grid);
-		LLGridManager::getInstance()->saveFavorites();
-		// validate we didn't lose existing favorites
-		LLGridManager::getInstance()->initialize("grid_test.xml");
-		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure("New grid wasn't added to persisted list after being marked a favorite",
-			   known_grids.find(std::string("grid1")) !=
-			   known_grids.end());
-		
-		// add a grid
-		LLGridManager::getInstance()->addGrid(grid);
-		LLGridManager::getInstance()->setGridChoice("mynewgridname");
-		LLGridManager::getInstance()->setFavorite();
-		LLGridManager::getInstance()->saveFavorites();
-		known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure("New grid wasn't added to persisted list after being marked a favorite",
-			   known_grids.find(std::string("grid1")) !=
-			   known_grids.end());
-		known_grids = LLGridManager::getInstance()->getKnownGrids();
-		ensure("New grid wasn't added to persisted list after being marked a favorite",
-			   known_grids.find(std::string("mynewgridname")) !=
-			   known_grids.end());
-	}
-}
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 659da31007e3b57544d281c76f04547f1fd1fa04..18ac10fe389ef2f91ae46f89605914d8d7056ee0 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -397,15 +397,6 @@ def construct(self):
 
         self.disable_manifest_check()
 
-        # Diamondware Runtimes
-        if self.prefix(src="diamondware-runtime/i686-win32", dst=""):
-            self.path("SLVoice_dwTVC.exe")
-            self.path("libcurl.dll")
-            self.path("libeay32.dll")
-            self.path("ssleay32.dll")
-            self.path("zlib1.dll")
-            self.end_prefix()
-
         # pull in the crash logger and updater from other projects
         # tag:"crash-logger" here as a cue to the exporter
         self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
@@ -615,9 +606,6 @@ def construct(self):
                 self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
                 self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib")
                 self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
-                # DiamondWare runtime                                           
-                self.path("diamondware-runtime/universal-darwin/SLVoice_dwTVC","SLVoice_dwTVC")
-                self.path("diamondware-runtime/universal-darwin/libfmodex.dylib", "libfmodex.dylib")
 
                 libdir = "../../libraries/universal-darwin/lib_release"
                 dylibs = {}
@@ -913,11 +901,6 @@ def construct(self):
                     pass
             self.end_prefix("lib")
 
-            # Diamondware runtimes
-            if self.prefix(src="diamondware-runtime/i686-linux", dst="bin"):
-                    self.path("SLVoice_dwTVC")
-                    self.end_prefix()
-
             # Vivox runtimes
             if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
                     self.path("SLVoice")
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index e1922367bfe95ec4642b5bb00496a6ac26e235c0..b9f61ca7e1e4014b2f0c98bc586ab1871ef0b1df 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -122,35 +122,29 @@ class LLLogin::Impl
 	LLSD mAuthResponse, mValidAuthResponse;
 };
 
-void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
+void LLLogin::Impl::connect(const std::string& uri, const LLSD& credentials)
 {
-    LL_DEBUGS("LLLogin") << " connect with  uri '" << uri << "', login_params " << login_params << LL_ENDL;
-	
     // Launch a coroutine with our login_() method. Run the coroutine until
     // its first wait; at that point, return here.
     std::string coroname = 
         LLCoros::instance().launch("LLLogin::Impl::login_",
-                                   boost::bind(&Impl::login_, this, _1, uri, login_params));
-    LL_DEBUGS("LLLogin") << " connected with  uri '" << uri << "', login_params " << login_params << LL_ENDL;	
+                                   boost::bind(&Impl::login_, this, _1, uri, credentials));
 }
 
-void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_params)
+void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credentials)
 {
-	try
+	LLSD printable_credentials = credentials;
+	if(printable_credentials.has("params") 
+		&& printable_credentials["params"].has("passwd")) 
 	{
-	LLSD printable_params = login_params;
-	//if(printable_params.has("params") 
-	//	&& printable_params["params"].has("passwd")) 
-	//{
-	//	printable_params["params"]["passwd"] = "*******";
-	//}
+		printable_credentials["params"]["passwd"] = "*******";
+	}
     LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self)
-                        << " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
+                        << " with uri '" << uri << "', credentials " << printable_credentials << LL_ENDL;
 
 	// Arriving in SRVRequest state
     LLEventStream replyPump("SRVreply", true);
     // Should be an array of one or more uri strings.
-
     LLSD rewrittenURIs;
     {
         LLEventTimeout filter(replyPump);
@@ -161,9 +155,9 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
 
         // *NOTE:Mani - Completely arbitrary default timeout value for SRV request.
 		F32 seconds_to_timeout = 5.0f;
-		if(login_params.has("cfg_srv_timeout"))
+		if(credentials.has("cfg_srv_timeout"))
 		{
-			seconds_to_timeout = login_params["cfg_srv_timeout"].asReal();
+			seconds_to_timeout = credentials["cfg_srv_timeout"].asReal();
 		}
 
         // If the SRV request times out (e.g. EXT-3934), simulate response: an
@@ -173,9 +167,9 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
 		filter.eventAfter(seconds_to_timeout, fakeResponse);
 
 		std::string srv_pump_name = "LLAres";
-		if(login_params.has("cfg_srv_pump"))
+		if(credentials.has("cfg_srv_pump"))
 		{
-			srv_pump_name = login_params["cfg_srv_pump"].asString();
+			srv_pump_name = credentials["cfg_srv_pump"].asString();
 		}
 
 		// Make request
@@ -200,7 +194,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
              urend(rewrittenURIs.endArray());
          urit != urend; ++urit)
     {
-        LLSD request(login_params);
+        LLSD request(credentials);
         request["reply"] = loginReplyPump.getName();
         request["uri"] = *urit;
         std::string status;
@@ -297,17 +291,8 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
 	// to success, add a data/message and data/reason fields.
 	LLSD error_response;
 	error_response["reason"] = mAuthResponse["status"];
-	error_response["errorcode"] = mAuthResponse["errorcode"];
 	error_response["message"] = mAuthResponse["error"];
-	if(mAuthResponse.has("certificate"))
-	{
-		error_response["certificate"] = mAuthResponse["certificate"];
-	}
 	sendProgressEvent("offline", "fail.login", error_response);
-	}
-	catch (...) {
-		llerrs << "login exception caught" << llendl; 
-	}
 }
 
 void LLLogin::Impl::disconnect()