Files
libremetaverse/libsecondlife/libsecondlife.Utilities/RegistrationApi.cs
John Hurliman 813875d7b2 * CapsResponseCallback now passes an object instead of a Hashtable
* Added a skeleton implementation of RegistrationApi to libsecondlife.Utilities. It does not work yet! Anyone with RegAPI access that wants to help test let me know. Original code submitted by fkollmann

git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1343 52acb1d6-8a22-11de-b505-999d5b087335
2007-08-02 02:35:40 +00:00

326 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Text;
namespace libsecondlife
{
public class RegistrationApi
{
private struct UserInfo
{
public string FirstName;
public string LastName;
public string Password;
}
private struct RegistrationCaps
{
public Uri CreateUser;
public Uri CheckName;
public Uri GetLastNames;
public Uri GetErrorCodes;
}
public struct LastName
{
public int ID;
public string Name;
}
/// <summary>
/// see https://secure-web6.secondlife.com/developers/third_party_reg/#service_create_user or
/// https://wiki.secondlife.com/wiki/RegAPIDoc for description
/// </summary>
public class CreateUserParam
{
public string FirstName;
public LastName LastName;
public string Email;
public string Password;
public DateTime Birthdate;
// optional:
public Nullable<int> LimitedToEstate;
public string StartRegionName;
public Nullable<LLVector3> StartLocation;
public Nullable<LLVector3> StartLookAt;
}
private UserInfo _userInfo;
private RegistrationCaps _caps;
private int _initializing;
private List<LastName> _lastNames = new List<LastName>();
private Dictionary<int, string> _errors = new Dictionary<int, string>();
public bool Initializing
{
get
{
System.Diagnostics.Debug.Assert(_initializing <= 0);
return (_initializing < 0);
}
}
public List<LastName> LastNames
{
get
{
lock (_lastNames)
{
if (_lastNames.Count <= 0)
GatherLastNames();
}
return _lastNames;
}
}
public RegistrationApi(string firstName, string lastName, string password)
{
_initializing = -2;
_userInfo = new UserInfo();
_userInfo.FirstName = firstName;
_userInfo.LastName = lastName;
_userInfo.Password = password;
GatherCaps();
}
public void WaitForInitialization()
{
while (Initializing)
System.Threading.Thread.Sleep(10);
}
public Uri RegistrationApiCaps
{
get { return new Uri("https://cap.secondlife.com/get_reg_capabilities"); }
}
private void GatherCaps()
{
CapsRequest request = new CapsRequest(RegistrationApiCaps.AbsoluteUri);
request.OnCapsResponse += new CapsRequest.CapsResponseCallback(GatherCapsResponse);
// build post data
byte[] postData = Encoding.ASCII.GetBytes(
String.Format("first_name={0}&last_name={1}&password={2}", _userInfo.FirstName, _userInfo.LastName,
_userInfo.Password));
// send
request.MakeRequest(postData);
}
private void GatherCapsResponse(object response, HttpRequestState state)
{
if (response is Hashtable)
{
Hashtable respTable = (Hashtable)response;
// parse
_caps = new RegistrationCaps();
_caps.CreateUser = new Uri((string)respTable["create_user"]);
_caps.CheckName = new Uri((string)respTable["check_name"]);
_caps.GetLastNames = new Uri((string)respTable["get_last_names"]);
_caps.GetErrorCodes = new Uri((string)respTable["get_error_codes"]);
// finalize
_initializing++;
GatherErrorMessages();
}
}
private void GatherErrorMessages()
{
if (_caps.GetErrorCodes == null)
throw new InvalidOperationException("access denied"); // this should work even for not-approved users
CapsRequest request = new CapsRequest(_caps.GetErrorCodes.AbsoluteUri);
request.OnCapsResponse += new CapsRequest.CapsResponseCallback(GatherErrorMessagesResponse);
request.MakeRequest();
}
private void GatherErrorMessagesResponse(object response, HttpRequestState state)
{
if (response is Hashtable)
{
// parse
foreach (ArrayList error in (Hashtable)response)
{
StringBuilder sb = new StringBuilder();
sb.Append(error[1]);
sb.Append(" (");
sb.Append(error[0]);
sb.Append("): ");
sb.Append(error[2]);
_errors.Add((int)error[0], sb.ToString());
}
// finalize
_initializing++;
}
}
public void GatherLastNames()
{
if (Initializing)
throw new InvalidOperationException("still initializing");
if (_caps.GetLastNames == null)
throw new InvalidOperationException("access denied: only approved developers have access to the registration api");
CapsRequest request = new CapsRequest(_caps.GetLastNames.AbsoluteUri);
request.OnCapsResponse += new CapsRequest.CapsResponseCallback(GatherLastNamesResponse);
request.MakeRequest();
// FIXME: Block
}
private void GatherLastNamesResponse(object response, HttpRequestState state)
{
if (response is Hashtable)
{
Hashtable respTable = (Hashtable)response;
_lastNames = new List<LastName>(respTable.Count);
for (IDictionaryEnumerator it = respTable.GetEnumerator(); it.MoveNext(); )
{
LastName ln = new LastName();
ln.ID = int.Parse(it.Key.ToString());
ln.Name = it.Value.ToString();
_lastNames.Add(ln);
}
_lastNames.Sort(new Comparison<LastName>(delegate(LastName a, LastName b) { return a.Name.CompareTo(b.Name); }));
}
}
public bool CheckName(string firstName, LastName lastName)
{
if (Initializing)
throw new InvalidOperationException("still initializing");
if (_caps.CheckName == null)
throw new InvalidOperationException("access denied; only approved developers have access to the registration api");
// Create the POST data
Hashtable query = new Hashtable();
query.Add("username", firstName);
query.Add("last_name_id", lastName.ID);
byte[] postData = LLSD.LLSDSerialize(query);
CapsRequest request = new CapsRequest(_caps.CheckName.AbsoluteUri);
request.OnCapsResponse += new CapsRequest.CapsResponseCallback(CheckNameResponse);
request.MakeRequest(postData);
// FIXME:
return false;
}
private void CheckNameResponse(object response, HttpRequestState state)
{
if (response is bool)
{
// FIXME:
//(bool)response;
}
else
{
// FIXME:
}
}
/// <summary>
/// Returns the new user ID or throws an exception containing the error code
/// The error codes can be found here: https://wiki.secondlife.com/wiki/RegAPIError
/// </summary>
/// <param name="user">New user account to create</param>
/// <returns>The UUID of the new user account</returns>
public LLUUID CreateUser(CreateUserParam user)
{
if (Initializing)
throw new InvalidOperationException("still initializing");
if (_caps.CreateUser == null)
throw new InvalidOperationException("access denied; only approved developers have access to the registration api");
// Create the POST data
Hashtable query = new Hashtable();
query.Add("username", user.FirstName);
query.Add("last_name_id", user.LastName.ID);
query.Add("email", user.Email);
query.Add("password", user.Password);
query.Add("dob", user.Birthdate.ToString("yyyy-MM-dd"));
if (user.LimitedToEstate != null)
query.Add("limited_to_estate", user.LimitedToEstate.Value);
if (!string.IsNullOrEmpty(user.StartRegionName))
query.Add("start_region_name", user.LimitedToEstate.Value);
if (user.StartLocation != null)
{
query.Add("start_local_x", user.StartLocation.Value.X);
query.Add("start_local_y", user.StartLocation.Value.Y);
query.Add("start_local_z", user.StartLocation.Value.Z);
}
if (user.StartLookAt != null)
{
query.Add("start_look_at_x", user.StartLookAt.Value.X);
query.Add("start_look_at_y", user.StartLookAt.Value.Y);
query.Add("start_look_at_z", user.StartLookAt.Value.Z);
}
byte[] postData = LLSD.LLSDSerialize(query);
// Make the request
CapsRequest request = new CapsRequest(_caps.CreateUser.AbsoluteUri);
request.OnCapsResponse += new CapsRequest.CapsResponseCallback(CreateUserResponse);
request.MakeRequest(postData);
// FIXME: Block
return LLUUID.Zero;
}
private void CreateUserResponse(object response, HttpRequestState state)
{
if (response is Hashtable)
{
// everything is okay
// FIXME:
//return new LLUUID(((Hashtable)response)["agent_id"].ToString());
}
else
{
// an error happened
ArrayList al = (ArrayList)response;
StringBuilder sb = new StringBuilder();
foreach (int ec in al)
{
if (sb.Length > 0)
sb.Append("; ");
sb.Append(_errors[ec]);
}
// FIXME:
//throw new Exception("failed to create user: " + sb.ToString());
}
}
}
}