// Methods private bool VerifySignature(User user, string querystring) { // Check that we have enough characters to avoid an ArgumentOutOfRangeException. // If we don't have at least this many, there's certainly no hash anyway. if (querystring.Length < 38) { return(false); } // All this does the same job as the following on the client side: // var tohash = (++AjaxLife.SignedCallCount).toString() + querystring + AjaxLife.Signature; // var hash = md5(tohash); // First we have to remove the hash from the incoming string. We may assume the has is always at the end. // This makes the job easy - we just chop the end off. No parsing required. // MD5s are 128 bits, or 32 hex characters, so we chop off "&hash=00000000000000000000000000000000", which is // 38 characters. string receivedhash = querystring.Substring(querystring.Length - 32); // Grab the last 32 characters. querystring = querystring.Remove(querystring.Length - 38); // Strip the hash off. ++user.SignedCallCount; // Increment the call count to ensure the same hash can't be used multiple times. string tohash = user.SignedCallCount.ToString() + querystring + user.Signature; // Build the to hash string. string expectedhash = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(tohash))).Replace("-", "").ToLower(); // Actually hash it. AjaxLife.Debug("SendMessage", "VerifySignature: Received hash " + receivedhash + ", expected " + expectedhash + " (based on '" + tohash + "')"); // Check if they're equal. return(receivedhash == expectedhash); }
// Someone wants logout.kat? public void OnFileRequested(HttpRequest request, IDirectory directory) { request.Response.ResponseContent = new MemoryStream(); StreamWriter writer = new StreamWriter(request.Response.ResponseContent); try { StreamReader reader = new StreamReader(request.PostData); string post = reader.ReadToEnd(); reader.Dispose(); // Get the user session and GridClient object. Dictionary <string, string> POST = AjaxLife.PostDecode(post); Guid session = new Guid(POST["sid"]); GridClient client; User user; lock (users) { user = users[session]; client = user.Client; user.LastRequest = DateTime.Now; } // If we're connected, request a logout. if (client.Network.Connected) { client.Network.Logout(); client.Network.Shutdown(NetworkManager.DisconnectType.ClientInitiated); System.Threading.Thread.Sleep(2000); } // Deactivate the event queue. if (user.Events != null) { user.Events.deactivate(); } // Unset everything for garbage collection purposes. user.Events = null; user.Client = null; client = null; user.Avatars = null; // Remove the user lock (users) { users.Remove(session); } // Announce our success. writer.WriteLine("{success: true}"); } catch (Exception e) { request.Response.ContentType = "text/plain"; writer.WriteLine(e.Message); } writer.Flush(); }
public void OnFileRequested(HttpRequest request, IDirectory directory) { request.Response.ResponseContent = new MemoryStream(); StreamWriter writer = new StreamWriter(request.Response.ResponseContent); StreamReader reader = new StreamReader(request.PostData); string post = reader.ReadToEnd(); reader.Dispose(); Dictionary <string, string> POST = AjaxLife.PostDecode(post); Hashtable hash = new Hashtable(); hash.Add("SESSION_ID", POST["sid"]); hash.Add("STATIC_ROOT", AjaxLife.STATIC_ROOT); Html.Template.Parser parser = new Html.Template.Parser(hash); writer.Write(parser.Parse(File.ReadAllText("client/Templates/iPhone.html")));; writer.Flush(); }
public void OnFileRequested(HttpRequest request, IDirectory directory) { request.Response.ResponseContent = new MemoryStream(); StreamWriter writer = new StreamWriter(request.Response.ResponseContent); try { SecondLife client; User user; // Get the session. Dictionary <string, string> POST = AjaxLife.PostDecode((new StreamReader(request.PostData)).ReadToEnd()); Guid sessionid = new Guid(POST["sid"]); // Standard user stuff. lock (users) { user = users[sessionid]; client = user.Client; user.LastRequest = DateTime.Now; // Clear the inventory cache to avoid confusion. user.Events.ClearInventory(); } Hashtable data = new Hashtable(); Dictionary <string, int> pos = new Dictionary <string, int>(); pos.Add("x", (int)Math.Floor(client.Self.GlobalPosition.X / 256)); pos.Add("y", (int)Math.Floor(client.Self.GlobalPosition.Y / 256)); data.Add("RegionCoords", pos); data.Add("Region", client.Network.CurrentSim.Name); data.Add("Position", client.Self.SimPosition); data.Add("MOTD", client.Network.LoginMessage); data.Add("UserName", client.Self.FirstName + " " + client.Self.LastName); data.Add("AgentID", client.Self.AgentID); data.Add("InventoryRoot", client.Inventory.Store.RootFolder.UUID); writer.Write(MakeJson.FromHashtable(data)); writer.Flush(); } catch (Exception e) { writer.WriteLine("Error: " + e.Message); } writer.Flush(); }
public void OnFileRequested(HttpRequest request, IDirectory directory) { request.Response.ResponseContent = new MemoryStream(); StreamWriter writer = new StreamWriter(request.Response.ResponseContent); try { StreamReader reader = new StreamReader(request.PostData); string post = reader.ReadToEnd(); reader.Dispose(); // Decode the POST data. Dictionary <string, string> POST = AjaxLife.PostDecode(post); Guid session = new Guid(POST["sid"]); Events eventqueue; User user; SecondLife client; // Load in the session data. lock (users) { user = users[session]; eventqueue = user.Events; client = user.Client; user.LastRequest = DateTime.Now; } bool sent = false; double heading = user.Rotation; // Check once per second, timing out after 15 seconds. for (int i = 0; i < 15; ++i) { // Ugly hack - we're riding on the back of the event poll to rotate our camera. if (user.Rotation != -4) { // If we've reached π, having started at -π, we're done. Quit rotating, because it // appears to annoy people and/or make them dizzy. heading += 0.5d; if (heading > Math.PI) { // We use -4 because -4 < -π, so will never occur during normal operation. user.Rotation = -4; heading = Math.PI; } else { user.Rotation = heading; } client.Self.Movement.UpdateFromHeading(heading, false); } if (eventqueue.GetEventCount() > 0) { writer.WriteLine(eventqueue.GetPendingJson(client)); sent = true; break; } else { System.Threading.Thread.Sleep(1000); } } // If nothing of interest ever came up, we just send the standard footer. if (!sent) { JsonWriter w = new JsonWriter(writer); w.WriteStartArray(); (new JsonSerializer()).Serialize(w, eventqueue.GetFooter(client)); w.WriteEndArray(); w.Flush(); } } catch (Exception e) { request.Response.ContentType = "text/plain"; writer.WriteLine(e.Message); } writer.Flush(); }
public void OnFileRequested(HttpRequest request, IDirectory directory) { //request.Response.SetHeader("Content-Type", "text/plain; charset=utf-8"); request.Response.ResponseContent = new MemoryStream(); StreamWriter textwriter = new StreamWriter(request.Response.ResponseContent); SecondLife client; AvatarTracker avatars; Events events; StreamReader reader = new StreamReader(request.PostData); string qstring = reader.ReadToEnd(); reader.Dispose(); Dictionary <string, string> POST = AjaxLife.PostDecode(qstring); // Pull out the session. if (!POST.ContainsKey("sid")) { textwriter.WriteLine("Need an SID."); textwriter.Flush(); return; } Guid guid = new Guid(POST["sid"]); User user = new User(); lock (this.users) { if (!this.users.ContainsKey(guid)) { textwriter.WriteLine("Error: invalid SID"); textwriter.Flush(); return; } user = this.users[guid]; client = user.Client; avatars = user.Avatars; events = user.Events; user.LastRequest = DateTime.Now; } // Get the message type. string messagetype = POST["MessageType"]; // Check that the message is signed if it should be. if (Array.IndexOf(REQUIRED_SIGNATURES, messagetype) > -1) { if (!VerifySignature(user, qstring)) { textwriter.WriteLine("Error: Received hash and expected hash do not match."); textwriter.Flush(); return; } } // Right. This file is fun. It takes information in POST paramaters and sends them to // the server in the appropriate format. Some will return data immediately, some will return // keys to data that will arrive in the message queue, some return nothing but you get // something in the message queue later, and some return nother ever. // // The joys of dealing with multiple bizarre message types. switch (messagetype) { case "SpatialChat": client.Self.Chat(POST["Message"], int.Parse(POST["Channel"]), (ChatType)((byte)int.Parse(POST["Type"]))); break; case "SimpleInstantMessage": if (POST.ContainsKey("IMSessionID")) { client.Self.InstantMessage(new LLUUID(POST["Target"]), POST["Message"], new LLUUID(POST["IMSessionID"])); } else { client.Self.InstantMessage(new LLUUID(POST["Target"]), POST["Message"]); } break; case "GenericInstantMessage": client.Self.InstantMessage( client.Self.FirstName + " " + client.Self.LastName, new LLUUID(POST["Target"]), POST["Message"], new LLUUID(POST["IMSessionID"]), (InstantMessageDialog)((byte)int.Parse(POST["Dialog"])), (InstantMessageOnline)int.Parse(POST["Online"]), client.Self.SimPosition, client.Network.CurrentSim.ID, new byte[0]); break; case "NameLookup": client.Avatars.RequestAvatarName(new LLUUID(POST["ID"])); break; case "Teleport": { Hashtable hash = new Hashtable(); bool status; if (POST.ContainsKey("Landmark")) { status = client.Self.Teleport(new LLUUID(POST["Landmark"])); } else { status = client.Self.Teleport(POST["Sim"], new LLVector3(float.Parse(POST["X"]), float.Parse(POST["Y"]), float.Parse(POST["Z"]))); } if (status) { hash.Add("Success", true); hash.Add("Sim", client.Network.CurrentSim.Name); hash.Add("Position", client.Self.SimPosition); } else { hash.Add("Success", false); hash.Add("Reason", client.Self.TeleportMessage); } textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "GoHome": client.Self.GoHome(); break; case "GetPosition": { Hashtable hash = new Hashtable(); hash.Add("Sim", client.Network.CurrentSim.Name); hash.Add("Position", client.Self.SimPosition); textwriter.WriteLine(JavaScriptConvert.SerializeObject(hash)); } break; case "RequestBalance": client.Self.RequestBalance(); break; case "GetStats": { Hashtable hash = new Hashtable(); hash.Add("FPS", client.Network.CurrentSim.Stats.FPS); hash.Add("TimeDilation", client.Network.CurrentSim.Stats.Dilation); hash.Add("LSLIPS", client.Network.CurrentSim.Stats.LSLIPS); hash.Add("Objects", client.Network.CurrentSim.Stats.Objects); hash.Add("ActiveScripts", client.Network.CurrentSim.Stats.ActiveScripts); hash.Add("Agents", client.Network.CurrentSim.Stats.Agents); hash.Add("ChildAgents", client.Network.CurrentSim.Stats.ChildAgents); hash.Add("AjaxLifeSessions", users.Count); hash.Add("TextureCacheCount", AjaxLife.TextureCacheCount); hash.Add("TextureCacheSize", AjaxLife.TextureCacheSize); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "TeleportLureRespond": client.Self.TeleportLureRespond(new LLUUID(POST["RequesterID"]), bool.Parse(POST["Accept"])); break; case "GodlikeTeleportLureRespond": { LLUUID lurer = new LLUUID(POST["RequesterID"]); LLUUID session = new LLUUID(POST["SessionID"]); client.Self.InstantMessage(client.Self.Name, lurer, "", LLUUID.Random(), InstantMessageDialog.AcceptTeleport, InstantMessageOnline.Offline, client.Self.SimPosition, LLUUID.Zero, new byte[0]); TeleportLureRequestPacket lure = new TeleportLureRequestPacket(); lure.Info.AgentID = client.Self.AgentID; lure.Info.SessionID = client.Self.SessionID; lure.Info.LureID = session; lure.Info.TeleportFlags = (uint)AgentManager.TeleportFlags.ViaGodlikeLure; client.Network.SendPacket(lure); } break; case "FindPeople": { Hashtable hash = new Hashtable(); hash.Add("QueryID", client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, POST["Search"], int.Parse(POST["Start"]))); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "FindGroups": { Hashtable hash = new Hashtable(); hash.Add("QueryID", client.Directory.StartGroupSearch(DirectoryManager.DirFindFlags.Groups, POST["Search"], int.Parse(POST["Start"]))); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "GetAgentData": client.Avatars.RequestAvatarProperties(new LLUUID(POST["AgentID"])); break; case "StartAnimation": client.Self.AnimationStart(new LLUUID(POST["Animation"]), false); break; case "StopAnimation": client.Self.AnimationStop(new LLUUID(POST["Animation"]), true); break; case "SendAppearance": client.Appearance.SetPreviousAppearance(false); break; case "GetMapItems": { MapItemRequestPacket req = new MapItemRequestPacket(); req.AgentData.AgentID = client.Self.AgentID; req.AgentData.SessionID = client.Self.SessionID; GridRegion region; client.Grid.GetGridRegion(POST["Region"], GridLayerType.Objects, out region); req.RequestData.RegionHandle = region.RegionHandle; req.RequestData.ItemType = uint.Parse(POST["ItemType"]); client.Network.SendPacket((Packet)req); } break; case "GetMapBlocks": { MapBlockRequestPacket req = new MapBlockRequestPacket(); req.AgentData.AgentID = client.Self.AgentID; req.AgentData.SessionID = client.Self.SessionID; req.PositionData.MinX = 0; req.PositionData.MinY = 0; req.PositionData.MaxX = ushort.MaxValue; req.PositionData.MaxY = ushort.MaxValue; client.Network.SendPacket((Packet)req); } break; case "GetMapBlock": { ushort x = ushort.Parse(POST["X"]); ushort y = ushort.Parse(POST["Y"]); MapBlockRequestPacket req = new MapBlockRequestPacket(); req.AgentData.AgentID = client.Self.AgentID; req.AgentData.SessionID = client.Self.SessionID; req.PositionData.MinX = x; req.PositionData.MinY = y; req.PositionData.MaxX = x; req.PositionData.MaxY = y; client.Network.SendPacket((Packet)req); } break; case "GetOfflineMessages": { RetrieveInstantMessagesPacket req = new RetrieveInstantMessagesPacket(); req.AgentData.AgentID = client.Self.AgentID; req.AgentData.SessionID = client.Self.SessionID; client.Network.SendPacket((Packet)req); } break; case "GetFriendList": { InternalDictionary <LLUUID, FriendInfo> friends = client.Friends.FriendList; List <Hashtable> friendlist = new List <Hashtable>(); friends.ForEach(delegate(FriendInfo friend) { Hashtable friendhash = new Hashtable(); friendhash.Add("ID", friend.UUID.ToString()); friendhash.Add("Name", friend.Name); friendhash.Add("Online", friend.IsOnline); friendhash.Add("MyRights", friend.MyFriendRights); friendhash.Add("TheirRights", friend.TheirFriendRights); friendlist.Add(friendhash); }); textwriter.Write(MakeJson.FromObject(friendlist)); } break; case "ChangeRights": { LLUUID uuid = new LLUUID(POST["Friend"]); client.Friends.GrantRights(uuid, (FriendRights)int.Parse(POST["Rights"])); } break; case "RequestLocation": client.Friends.MapFriend(new LLUUID(POST["Friend"])); break; case "RequestTexture": { // This one's confusing, so it gets some comments. // First, we get the image's UUID. LLUUID image = new LLUUID(POST["ID"]); // We prepare a query to ask if S3 has it. HEAD only to avoid wasting // GET requests and bandwidth. bool exists = false; // If we already know we have it, note this. if (AjaxLife.CachedTextures.Contains(image)) { exists = true; } else { // If we're using S3, check the S3 bucket if (AjaxLife.USE_S3) { // Otherwise, make that HEAD request and find out. try { IThreeSharp query = new ThreeSharpQuery(AjaxLife.S3Config); Affirma.ThreeSharp.Model.ObjectGetRequest s3request = new Affirma.ThreeSharp.Model.ObjectGetRequest(AjaxLife.TEXTURE_BUCKET, image.ToString() + ".png"); s3request.Method = "HEAD"; Affirma.ThreeSharp.Model.ObjectGetResponse s3response = query.ObjectGet(s3request); if (s3response.StatusCode == System.Net.HttpStatusCode.OK) { exists = true; } s3response.DataStream.Close(); } catch { } } // If we aren't using S3, just check the texture cache. else { exists = File.Exists(AjaxLife.TEXTURE_CACHE + image.ToString() + ".png"); } } // If it exists, reply with Ready = true and the URL to find it at. if (exists) { textwriter.Write("{Ready: true, URL: \"" + AjaxLife.TEXTURE_ROOT + image + ".png\"}"); } // If it doesn't, request the image from SL and note its lack of readiness. // Notification will arrive later in the message queue. else { client.Assets.RequestImage(image, ImageType.Normal, 125000.0f, 0); textwriter.Write("{Ready: false}"); } } break; case "AcceptFriendship": client.Friends.AcceptFriendship(client.Self.AgentID, POST["IMSessionID"]); break; case "DeclineFriendship": client.Friends.DeclineFriendship(client.Self.AgentID, POST["IMSessionID"]); break; case "OfferFriendship": client.Friends.OfferFriendship(new LLUUID(POST["Target"])); break; case "TerminateFriendship": client.Friends.TerminateFriendship(new LLUUID(POST["Target"])); break; case "SendAgentMoney": client.Self.GiveAvatarMoney(new LLUUID(POST["Target"]), int.Parse(POST["Amount"])); break; case "RequestAvatarList": { List <Hashtable> list = new List <Hashtable>(); foreach (KeyValuePair <uint, Avatar> pair in avatars.Avatars) { Avatar avatar = pair.Value; Hashtable hash = new Hashtable(); hash.Add("Name", avatar.Name); hash.Add("ID", avatar.ID); hash.Add("LocalID", avatar.LocalID); hash.Add("Position", avatar.Position); //hash.Add("Rotation", avatar.Rotation); hash.Add("Scale", avatar.Scale); hash.Add("GroupName", avatar.GroupName); list.Add(hash); } textwriter.Write(MakeJson.FromObject(list)); } break; case "LoadInventoryFolder": client.Inventory.RequestFolderContents(new LLUUID(POST["UUID"]), client.Self.AgentID, true, true, InventorySortOrder.ByDate | InventorySortOrder.SystemFoldersToTop); break; case "RequestAsset": { try { LLUUID transferid = client.Assets.RequestInventoryAsset(new LLUUID(POST["AssetID"]), new LLUUID(POST["InventoryID"]), LLUUID.Zero, new LLUUID(POST["OwnerID"]), (AssetType)int.Parse(POST["AssetType"]), false); textwriter.Write("{TransferID: \"" + transferid + "\"}"); } catch // Try catching the error that sometimes gets thrown... but sometimes doesn't. { } } break; case "SendTeleportLure": client.Self.SendTeleportLure(new LLUUID(POST["Target"]), POST["Message"]); break; case "ScriptPermissionResponse": client.Self.ScriptQuestionReply(client.Network.CurrentSim, new LLUUID(POST["ItemID"]), new LLUUID(POST["TaskID"]), (ScriptPermission)int.Parse(POST["Permissions"])); break; case "ScriptDialogReply": { ScriptDialogReplyPacket packet = new ScriptDialogReplyPacket(); packet.AgentData.AgentID = client.Self.AgentID; packet.AgentData.SessionID = client.Self.SessionID; packet.Data.ButtonIndex = int.Parse(POST["ButtonIndex"]); packet.Data.ButtonLabel = Helpers.StringToField(POST["ButtonLabel"]); packet.Data.ChatChannel = int.Parse(POST["ChatChannel"]); packet.Data.ObjectID = new LLUUID(POST["ObjectID"]); client.Network.SendPacket((Packet)packet); } break; case "SaveNotecard": client.Inventory.RequestUploadNotecardAsset(Helpers.StringToField(POST["AssetData"]), new LLUUID(POST["ItemID"]), new InventoryManager.NotecardUploadedAssetCallback(events.Inventory_OnNoteUploaded)); break; case "CreateInventory": client.Inventory.RequestCreateItem(new LLUUID(POST["Folder"]), POST["Name"], POST["Description"], (AssetType)int.Parse(POST["AssetType"]), LLUUID.Random(), (InventoryType)int.Parse(POST["InventoryType"]), PermissionMask.All, new InventoryManager.ItemCreatedCallback(events.Inventory_OnItemCreated)); break; case "CreateFolder": { LLUUID folder = client.Inventory.CreateFolder(new LLUUID(POST["Parent"]), POST["Name"]); textwriter.Write("{FolderID: \"" + folder + "\"}"); } break; case "EmptyTrash": client.Inventory.EmptyTrash(); break; case "MoveItem": client.Inventory.MoveItem(new LLUUID(POST["Item"]), new LLUUID(POST["TargetFolder"]), POST["NewName"]); break; case "MoveFolder": client.Inventory.MoveFolder(new LLUUID(POST["Folder"]), new LLUUID(POST["NewParent"])); break; case "MoveItems": case "MoveFolders": { Dictionary <LLUUID, LLUUID> dict = new Dictionary <LLUUID, LLUUID>(); string[] moves = POST["ToMove"].Split(','); for (int i = 0; i < moves.Length; ++i) { string[] move = moves[i].Split(' '); dict.Add(new LLUUID(move[0]), new LLUUID(move[1])); } if (messagetype == "MoveItems") { client.Inventory.MoveItems(dict); } else if (messagetype == "MoveFolders") { client.Inventory.MoveFolders(dict); } } break; case "DeleteItem": client.Inventory.RemoveItem(new LLUUID(POST["Item"])); break; case "DeleteFolder": client.Inventory.RemoveFolder(new LLUUID(POST["Folder"])); break; case "DeleteMultiple": { string[] items = POST["Items"].Split(','); List <LLUUID> itemlist = new List <LLUUID>(); for (int i = 0; i < items.Length; ++i) { itemlist.Add(new LLUUID(items[i])); } string[] folders = POST["Folders"].Split(','); List <LLUUID> folderlist = new List <LLUUID>(); for (int i = 0; i < items.Length; ++i) { folderlist.Add(new LLUUID(folders[i])); } client.Inventory.Remove(itemlist, folderlist); } break; case "GiveInventory": { client.Inventory.GiveItem(new LLUUID(POST["ItemID"]), POST["ItemName"], (AssetType)int.Parse(POST["AssetType"]), new LLUUID(POST["Recipient"]), true); } break; case "UpdateItem": { InventoryItem item = client.Inventory.FetchItem(new LLUUID(POST["ItemID"]), new LLUUID(POST["OwnerID"]), 1000); if (POST.ContainsKey("Name")) { item.Name = POST["Name"]; } if (POST.ContainsKey("Description")) { item.Description = POST["Description"]; } if (POST.ContainsKey("NextOwnerMask")) { item.Permissions.NextOwnerMask = (PermissionMask)uint.Parse(POST["NextOwnerMask"]); } if (POST.ContainsKey("SalePrice")) { item.SalePrice = int.Parse(POST["SalePrice"]); } if (POST.ContainsKey("SaleType")) { item.SaleType = (SaleType)int.Parse(POST["SaleType"]); // This should be byte.Parse, but this upsets mono's compiler (CS1002) } client.Inventory.RequestUpdateItem(item); } break; case "UpdateFolder": { UpdateInventoryFolderPacket packet = new UpdateInventoryFolderPacket(); packet.AgentData.AgentID = client.Self.AgentID; packet.AgentData.SessionID = client.Self.SessionID; packet.FolderData = new UpdateInventoryFolderPacket.FolderDataBlock[1]; packet.FolderData[0] = new UpdateInventoryFolderPacket.FolderDataBlock(); packet.FolderData[0].FolderID = new LLUUID(POST["FolderID"]); packet.FolderData[0].ParentID = new LLUUID(POST["ParentID"]); packet.FolderData[0].Type = sbyte.Parse(POST["Type"]); packet.FolderData[0].Name = Helpers.StringToField(POST["Name"]); client.Network.SendPacket((Packet)packet); } break; case "FetchItem": client.Inventory.FetchItem(new LLUUID(POST["Item"]), new LLUUID(POST["Owner"]), 5000); break; case "ReRotate": user.Rotation = -Math.PI; break; case "StartGroupIM": AjaxLife.Debug("SendMessage", "RequestJoinGroupChat(" + POST["Group"] + ")"); client.Self.RequestJoinGroupChat(new LLUUID(POST["Group"])); break; case "GroupInstantMessage": client.Self.InstantMessageGroup(new LLUUID(POST["Group"]), POST["Message"]); break; case "RequestGroupProfile": client.Groups.RequestGroupProfile(new LLUUID(POST["Group"])); break; case "RequestGroupMembers": client.Groups.RequestGroupMembers(new LLUUID(POST["Group"])); break; case "RequestGroupName": client.Groups.RequestGroupName(new LLUUID(POST["ID"])); break; case "JoinGroup": client.Groups.RequestJoinGroup(new LLUUID(POST["Group"])); break; case "LeaveGroup": client.Groups.LeaveGroup(new LLUUID(POST["Group"])); break; case "RequestCurrentGroups": client.Groups.RequestCurrentGroups(); break; case "GetParcelID": textwriter.Write("{LocalID: " + client.Parcels.GetParcelLocalID(client.Network.CurrentSim, new LLVector3(float.Parse(POST["X"]), float.Parse(POST["Y"]), float.Parse(POST["Z"]))) + "}"); break; case "RequestParcelProperties": client.Parcels.PropertiesRequest(client.Network.CurrentSim, int.Parse(POST["LocalID"]), int.Parse(POST["SequenceID"])); break; } textwriter.Flush(); }
// Someone wants connect.kat. public void OnFileRequested(HttpRequest request, IDirectory directory) { request.Response.ResponseContent = new MemoryStream(); StreamWriter textWriter = new StreamWriter(request.Response.ResponseContent); try { // Grab various bits of data from the User object. // If we can't do that, complain. // While we're at it, decode the post data. User user; SecondLife client; StreamReader reader = new StreamReader(request.PostData); string qstring = reader.ReadToEnd(); reader.Dispose(); Dictionary <string, string> POST = AjaxLife.PostDecode(qstring); Guid key = new Guid(POST["session"]); // The session doesn't exist. Get upset. if (!this.users.ContainsKey(key)) { this.invalidSessionID(key, textWriter); return; } lock (this.users) { user = users[key]; } user.LastRequest = DateTime.Now; client = user.GetClient(); string first = ""; string last = ""; string pass = ""; // Decrypt the incoming login data string decrypted = StringHelper.ASCIIBytesToString(AjaxLife.RSA.Decrypt(StringHelper.HexStringToBytes(POST["logindata"]))); // Split it into its component parts. string[] data = decrypted.Split('\\'); // Get upset if the challenge was incorrect. if (data[0] == null || data[0] != user.Challenge) { throw new Exception("Invalid request."); } // Decode the login data. first = StringHelper.ASCIIBytesToString(StringHelper.FromBase64(data[1])); last = StringHelper.ASCIIBytesToString(StringHelper.FromBase64(data[2])); pass = data[3]; user.Signature = data[4]; // Check if they're banned first. if (AjaxLife.BannedUsers.IsBanned(first, last)) { textWriter.WriteLine("{success: false, message: \"You have been banned from AjaxLife by the administrator.\"}"); textWriter.Flush(); return; } LoginParams login = client.Network.DefaultLoginParams(first, last, pass, "AjaxLife", "Katharine Berry <*****@*****.**>"); login.Platform = "web"; login.Channel = "AjaxLife"; login.MAC = AjaxLife.MAC_ADDRESS; login.id0 = AjaxLife.ID0; login.Start = (POST["location"] != "arbitrary") ? POST["location"] : NetworkManager.StartLocation(POST["sim"], 128, 128, 20); // Pick the correct loginuri. lock (AjaxLife.LOGIN_SERVERS) login.URI = AjaxLife.LOGIN_SERVERS[POST["grid"]]; client.Settings.LOGIN_SERVER = login.URI; user.LindenGrid = POST["grid"].EndsWith("(Linden Lab)"); Console.WriteLine(login.FirstName + " " + login.LastName + " is attempting to log into " + POST["grid"] + " (" + login.URI + ")"); if (client.Network.Login(login)) { // Ensure that the challenge isn't matched by another request with the same SID. // We don't do this until after successful login because otherwise a second attempt will always fail. user.Challenge = null; AvatarTracker avatars = new AvatarTracker(client); Events events = new Events(user); user.Events = events; user.Avatars = avatars; // Register event handlers this.RegisterCallbacks(user); // De-ruth. client.Appearance.SetPreviousAppearance(false); // Pythagoras says that 181.0193m is the optimal view distance to see the whole sim. client.Self.Movement.Camera.Far = 181.0193f; // This doesn't seem to work. // client.Self.Movement.Camera.SetPositionOrientation(new LLVector3(128, 128, 0), 0, 0, 0); // Everything's happy. Log the requested message list, if any. if (POST.ContainsKey("events")) { user.ParseRequestedEvents(POST["events"]); } // If we got this far, it worked. Announce this. textWriter.WriteLine("{\"success\": 1}"); } else { // Return whatever errors may have transpired. textWriter.WriteLine("{success: false, message: " + AjaxLife.StringToJSON(client.Network.LoginMessage) + "}"); } } catch (Exception exception) { request.Response.ContentType = "text/plain"; textWriter.WriteLine(exception.Message); } textWriter.Flush(); }