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); GridClient client; AvatarTracker avatars; Events events; StreamReader reader = new StreamReader(request.PostData); string qstring = reader.ReadToEnd(); reader.Dispose(); Dictionary<string,string> POST = deviMobile.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["MT"]; // 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 "chat": client.Self.Chat(POST["msg"], int.Parse(POST["chan"]), (ChatType)((byte)int.Parse(POST["type"]))); break; case "im": if (POST.ContainsKey("id")) { client.Self.InstantMessage(new UUID(POST["to"]), POST["msg"], new UUID(POST["id"])); } else { client.Self.InstantMessage(new UUID(POST["to"]), POST["msg"]); } break; case "avatarlist": { 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 "friends_count": { Hashtable Total = new Hashtable(); Total.Add("t", client.Friends.FriendList.Count); textwriter.Write(MakeJson.FromHashtable(Total)); } break; case "friends": { InternalDictionary<UUID, FriendInfo> friends = client.Friends.FriendList; List<Hashtable> friendlist = new List<Hashtable>(); int added = 0; int total = 0; decimal start = Convert.ToDecimal(POST["s"]); // Contiene el inicio de la lista friends.ForEach(delegate(FriendInfo friend) { if (added < 5 && total >= start) // si está en línea { Hashtable friendhash = new Hashtable(); friendhash.Add("id", friend.UUID.ToString()); friendhash.Add("name", friend.Name.ToString()); friendhash.Add("on", friend.IsOnline); friendlist.Add(friendhash); added++; } total++; }); textwriter.Write(MakeJson.FromObject(friendlist)); } break; case "getname": client.Avatars.RequestAvatarName(new UUID(POST["id"])); break; case "Teleport": { Hashtable hash = new Hashtable(); bool status; if (POST.ContainsKey("Landmark")) { status = client.Self.Teleport(new UUID(POST["Landmark"])); } else { status = client.Self.Teleport(POST["Sim"], new Vector3(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("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("deviMobileSessions", users.Count); hash.Add("PingSim", client.Network.CurrentSim.Stats.LastLag); hash.Add("IncomingBPS", client.Network.CurrentSim.Stats.IncomingBPS); hash.Add("OutgoingBPS", client.Network.CurrentSim.Stats.OutgoingBPS); hash.Add("DroppedPackets", client.Network.CurrentSim.Stats.ReceivedResends + client.Network.CurrentSim.Stats.ResentPackets); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "TeleportLureRespond": client.Self.TeleportLureRespond(new UUID(POST["RequesterID"]), bool.Parse(POST["Accept"])); break; case "GodlikeTeleportLureRespond": { UUID lurer = new UUID(POST["RequesterID"]); UUID session = new UUID(POST["SessionID"]); client.Self.InstantMessage(client.Self.Name, lurer, "", UUID.Random(), InstantMessageDialog.AcceptTeleport, InstantMessageOnline.Offline, client.Self.SimPosition, UUID.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)TeleportFlags.ViaGodlikeLure; client.Network.SendPacket(lure); } break; case "FindPeople": { Hashtable hash = new Hashtable(); hash.Add("QueryID", client.Directory.StartPeopleSearch(POST["Search"], int.Parse(POST["Start"]))); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "FindGroups": { Hashtable hash = new Hashtable(); hash.Add("QueryID", client.Directory.StartGroupSearch(POST["Search"], int.Parse(POST["Start"]))); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "GetAgentData": client.Avatars.RequestAvatarProperties(new UUID(POST["AgentID"])); break; case "StartAnimation": client.Self.AnimationStart(new UUID(POST["Animation"]), false); break; case "StopAnimation": client.Self.AnimationStop(new UUID(POST["Animation"]), true); break; case "SendAppearance": client.Appearance.RequestSetAppearance(); 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 = ushort.Parse(POST["MinX"]); req.PositionData.MinY = ushort.Parse(POST["MinY"]); req.PositionData.MaxX = ushort.Parse(POST["MaxX"]); req.PositionData.MaxY = ushort.Parse(POST["MaxY"]); client.Network.SendPacket((Packet)req); } break; case "FindRegion": { OpenMetaverse.Packets.MapNameRequestPacket packet = new OpenMetaverse.Packets.MapNameRequestPacket(); packet.NameData = new MapNameRequestPacket.NameDataBlock(); packet.NameData.Name = Utils.StringToBytes(POST["Name"]); packet.AgentData.AgentID = client.Self.AgentID; packet.AgentData.SessionID = client.Self.SessionID; client.Network.SendPacket((Packet)packet); } 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 "ChangeRights": { UUID uuid = new UUID(POST["Friend"]); client.Friends.GrantRights(uuid, (FriendRights)int.Parse(POST["Rights"])); } break; case "RequestLocation": client.Friends.MapFriend(new UUID(POST["Friend"])); break; case "RequestTexture": { // This one's confusing, so it gets some comments. // First, we get the image's UUID. UUID image = new UUID(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 (deviMobile.CachedTextures.Contains(image)) { exists = true; } else { // If we're using S3, check the S3 bucket if (deviMobile.USE_S3) { // Otherwise, make that HEAD request and find out. HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(deviMobile.TEXTURE_ROOT + image + ".png"); webrequest.Method = "HEAD"; webrequest.KeepAlive = false; webrequest.ReadWriteTimeout = 1000; webrequest.Timeout = 2500; HttpWebResponse response = null; try { response = (HttpWebResponse)webrequest.GetResponse(); if(response.StatusCode == HttpStatusCode.OK) { exists = true; } } catch(WebException e) { deviMobile.Debug("SendMessage", "WebException (" + e.Status.ToString() + "): " + e.Message); } finally { request.Dispose(); if(response != null) { response.Close(); } } } // If we aren't using S3, just check the texture cache. else { exists = File.Exists(deviMobile.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: \"" + deviMobile.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, new TextureDownloadCallback(events.Assets_TextureDownloadCallback)); textwriter.Write("{Ready: false}"); } } break; case "AcceptFriendship": client.Friends.AcceptFriendship(client.Self.AgentID, new UUID(POST["IMSessionID"])); break; case "DeclineFriendship": client.Friends.DeclineFriendship(client.Self.AgentID, new UUID(POST["IMSessionID"])); break; case "OfferFriendship": client.Friends.OfferFriendship(new UUID(POST["Target"])); break; case "TerminateFriendship": client.Friends.TerminateFriendship(new UUID(POST["Target"])); break; case "SendAgentMoney": client.Self.GiveAvatarMoney(new UUID(POST["Target"]), int.Parse(POST["Amount"])); break; case "LoadInventoryFolder": client.Inventory.RequestFolderContents(new UUID(POST["UUID"]), client.Self.AgentID, true, true, InventorySortOrder.ByDate | InventorySortOrder.SystemFoldersToTop); break; case "RequestAsset": { try { UUID inventoryID = new UUID(POST["InventoryID"]); client.Assets.RequestInventoryAsset(new UUID(POST["AssetID"]), inventoryID, UUID.Zero, new UUID(POST["OwnerID"]), (AssetType)int.Parse(POST["AssetType"]), false, delegate(AssetDownload transfer, OpenMetaverse.Assets.Asset asset) { events.Assets_OnAssetReceived(transfer, asset, inventoryID); } ); } catch // Try catching the error that sometimes gets thrown... but sometimes doesn't. { } } break; case "SendTeleportLure": client.Self.SendTeleportLure(new UUID(POST["Target"]), POST["Message"]); break; case "ScriptPermissionResponse": client.Self.ScriptQuestionReply(client.Network.CurrentSim, new UUID(POST["ItemID"]), new UUID(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 = Utils.StringToBytes(POST["ButtonLabel"]); packet.Data.ChatChannel = int.Parse(POST["ChatChannel"]); packet.Data.ObjectID = new UUID(POST["ObjectID"]); client.Network.SendPacket((Packet)packet); } break; case "SaveNotecard": client.Inventory.RequestUploadNotecardAsset(Utils.StringToBytes(POST["AssetData"]), new UUID(POST["ItemID"]), new InventoryManager.InventoryUploadedAssetCallback(events.Inventory_OnNoteUploaded)); break; case "CreateInventory": client.Inventory.RequestCreateItem(new UUID(POST["Folder"]), POST["Name"], POST["Description"], (AssetType)int.Parse(POST["AssetType"]), UUID.Random(), (InventoryType)int.Parse(POST["InventoryType"]), PermissionMask.All, new InventoryManager.ItemCreatedCallback(events.Inventory_OnItemCreated)); break; case "CreateFolder": { UUID folder = client.Inventory.CreateFolder(new UUID(POST["Parent"]), POST["Name"]); textwriter.Write("{FolderID: \"" + folder + "\"}"); } break; case "EmptyTrash": client.Inventory.EmptyTrash(); break; case "MoveItem": client.Inventory.MoveItem(new UUID(POST["Item"]), new UUID(POST["TargetFolder"]), POST["NewName"]); break; case "MoveFolder": client.Inventory.MoveFolder(new UUID(POST["Folder"]), new UUID(POST["NewParent"])); break; case "MoveItems": case "MoveFolders": { Dictionary<UUID, UUID> dict = new Dictionary<UUID, UUID>(); string[] moves = POST["ToMove"].Split(','); for (int i = 0; i < moves.Length; ++i) { string[] move = moves[i].Split(' '); dict.Add(new UUID(move[0]), new UUID(move[1])); } if (messagetype == "MoveItems") { client.Inventory.MoveItems(dict); } else if (messagetype == "MoveFolders") { client.Inventory.MoveFolders(dict); } } break; case "DeleteItem": client.Inventory.RemoveItem(new UUID(POST["Item"])); break; case "DeleteFolder": client.Inventory.RemoveFolder(new UUID(POST["Folder"])); break; case "DeleteMultiple": { string[] items = POST["Items"].Split(','); List<UUID> itemlist = new List<UUID>(); for (int i = 0; i < items.Length; ++i) { itemlist.Add(new UUID(items[i])); } string[] folders = POST["Folders"].Split(','); List<UUID> folderlist = new List<UUID>(); for (int i = 0; i < items.Length; ++i) { folderlist.Add(new UUID(folders[i])); } client.Inventory.Remove(itemlist, folderlist); } break; case "GiveInventory": { client.Inventory.GiveItem(new UUID(POST["ItemID"]), POST["ItemName"], (AssetType)int.Parse(POST["AssetType"]), new UUID(POST["Recipient"]), true); } break; case "UpdateItem": { InventoryItem item = client.Inventory.FetchItem(new UUID(POST["ItemID"]), new UUID(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 UUID(POST["FolderID"]); packet.FolderData[0].ParentID = new UUID(POST["ParentID"]); packet.FolderData[0].Type = sbyte.Parse(POST["Type"]); packet.FolderData[0].Name = Utils.StringToBytes(POST["Name"]); client.Network.SendPacket((Packet)packet); } break; case "FetchItem": client.Inventory.FetchItem(new UUID(POST["Item"]), new UUID(POST["Owner"]), 5000); break; case "ReRotate": user.Rotation = -Math.PI; break; case "StartGroupIM": deviMobile.Debug("SendMessage", "RequestJoinGroupChat(" + POST["Group"] + ")"); client.Self.RequestJoinGroupChat(new UUID(POST["Group"])); break; case "GroupInstantMessage": client.Self.InstantMessageGroup(new UUID(POST["Group"]), POST["Message"]); break; case "RequestGroupProfile": client.Groups.RequestGroupProfile(new UUID(POST["Group"])); break; case "RequestGroupMembers": client.Groups.RequestGroupMembers(new UUID(POST["Group"])); break; case "RequestGroupName": client.Groups.RequestGroupName(new UUID(POST["ID"])); break; case "JoinGroup": client.Groups.RequestJoinGroup(new UUID(POST["Group"])); break; case "LeaveGroup": client.Groups.LeaveGroup(new UUID(POST["Group"])); break; case "RequestCurrentGroups": client.Groups.RequestCurrentGroups(); break; case "GetParcelID": textwriter.Write("{LocalID: "+client.Parcels.GetParcelLocalID(client.Network.CurrentSim, new Vector3(float.Parse(POST["X"]), float.Parse(POST["Y"]), float.Parse(POST["Z"])))+"}"); break; case "RequestParcelProperties": client.Parcels.RequestParcelProperties(client.Network.CurrentSim, int.Parse(POST["LocalID"]), int.Parse(POST["SequenceID"])); break; } textwriter.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); GridClient 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 UUID(POST["Target"]), POST["Message"], new UUID(POST["IMSessionID"])); } else { client.Self.InstantMessage(new UUID(POST["Target"]), POST["Message"]); } break; case "GenericInstantMessage": client.Self.InstantMessage( client.Self.FirstName + " " + client.Self.LastName, new UUID(POST["Target"]), POST["Message"], new UUID(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 UUID(POST["ID"])); break; case "Teleport": { Hashtable hash = new Hashtable(); bool status; if (POST.ContainsKey("Landmark")) { status = client.Self.Teleport(new UUID(POST["Landmark"])); } else { status = client.Self.Teleport(POST["Sim"], new Vector3(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("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("PingSim", client.Network.CurrentSim.Stats.LastLag); hash.Add("IncomingBPS", client.Network.CurrentSim.Stats.IncomingBPS); hash.Add("OutgoingBPS", client.Network.CurrentSim.Stats.OutgoingBPS); hash.Add("DroppedPackets", client.Network.CurrentSim.Stats.ReceivedResends + client.Network.CurrentSim.Stats.ResentPackets); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "TeleportLureRespond": client.Self.TeleportLureRespond(new UUID(POST["RequesterID"]), new UUID(POST["SessionID"]), bool.Parse(POST["Accept"])); break; case "GodlikeTeleportLureRespond": { UUID lurer = new UUID(POST["RequesterID"]); UUID session = new UUID(POST["SessionID"]); client.Self.InstantMessage(client.Self.Name, lurer, "", UUID.Random(), InstantMessageDialog.AcceptTeleport, InstantMessageOnline.Offline, client.Self.SimPosition, UUID.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)TeleportFlags.ViaGodlikeLure; client.Network.SendPacket(lure); } break; case "FindPeople": { Hashtable hash = new Hashtable(); hash.Add("QueryID", client.Directory.StartPeopleSearch(POST["Search"], int.Parse(POST["Start"]))); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "FindGroups": { Hashtable hash = new Hashtable(); hash.Add("QueryID", client.Directory.StartGroupSearch(POST["Search"], int.Parse(POST["Start"]))); textwriter.WriteLine(MakeJson.FromHashtable(hash)); } break; case "GetAgentData": client.Avatars.RequestAvatarProperties(new UUID(POST["AgentID"])); break; case "StartAnimation": client.Self.AnimationStart(new UUID(POST["Animation"]), false); break; case "StopAnimation": client.Self.AnimationStop(new UUID(POST["Animation"]), true); break; case "SendAppearance": client.Appearance.RequestSetAppearance(); 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 = ushort.Parse(POST["MinX"]); req.PositionData.MinY = ushort.Parse(POST["MinY"]); req.PositionData.MaxX = ushort.Parse(POST["MaxX"]); req.PositionData.MaxY = ushort.Parse(POST["MaxY"]); client.Network.SendPacket((Packet)req); } break; case "FindRegion": { OpenMetaverse.Packets.MapNameRequestPacket packet = new OpenMetaverse.Packets.MapNameRequestPacket(); packet.NameData = new MapNameRequestPacket.NameDataBlock(); packet.NameData.Name = Utils.StringToBytes(POST["Name"]); packet.AgentData.AgentID = client.Self.AgentID; packet.AgentData.SessionID = client.Self.SessionID; client.Network.SendPacket((Packet)packet); } 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 <UUID, 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": { UUID uuid = new UUID(POST["Friend"]); client.Friends.GrantRights(uuid, (FriendRights)int.Parse(POST["Rights"])); } break; case "RequestLocation": client.Friends.MapFriend(new UUID(POST["Friend"])); break; case "RequestTexture": { // This one's confusing, so it gets some comments. // First, we get the image's UUID. UUID image = new UUID(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. HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(AjaxLife.TEXTURE_ROOT + image + ".png"); webrequest.Method = "HEAD"; webrequest.KeepAlive = false; webrequest.ReadWriteTimeout = 1000; webrequest.Timeout = 2500; HttpWebResponse response = null; try { response = (HttpWebResponse)webrequest.GetResponse(); if (response.StatusCode == HttpStatusCode.OK) { exists = true; } } catch (WebException e) { AjaxLife.Debug("SendMessage", "WebException (" + e.Status.ToString() + "): " + e.Message); } finally { request.Dispose(); if (response != null) { response.Close(); } } } // 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, new TextureDownloadCallback(events.Assets_TextureDownloadCallback)); textwriter.Write("{Ready: false}"); } } break; case "AcceptFriendship": client.Friends.AcceptFriendship(client.Self.AgentID, new UUID(POST["IMSessionID"])); break; case "DeclineFriendship": client.Friends.DeclineFriendship(client.Self.AgentID, new UUID(POST["IMSessionID"])); break; case "OfferFriendship": client.Friends.OfferFriendship(new UUID(POST["Target"])); break; case "TerminateFriendship": client.Friends.TerminateFriendship(new UUID(POST["Target"])); break; case "SendAgentMoney": client.Self.GiveAvatarMoney(new UUID(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 UUID(POST["UUID"]), client.Self.AgentID, true, true, InventorySortOrder.ByDate | InventorySortOrder.SystemFoldersToTop); break; case "RequestAsset": { try { UUID inventoryID = new UUID(POST["InventoryID"]); client.Assets.RequestInventoryAsset(new UUID(POST["AssetID"]), inventoryID, UUID.Zero, new UUID(POST["OwnerID"]), (AssetType)int.Parse(POST["AssetType"]), false, delegate(AssetDownload transfer, OpenMetaverse.Assets.Asset asset) { events.Assets_OnAssetReceived(transfer, asset, inventoryID); } ); } catch // Try catching the error that sometimes gets thrown... but sometimes doesn't. { } } break; case "SendTeleportLure": client.Self.SendTeleportLure(new UUID(POST["Target"]), POST["Message"]); break; case "ScriptPermissionResponse": client.Self.ScriptQuestionReply(client.Network.CurrentSim, new UUID(POST["ItemID"]), new UUID(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 = Utils.StringToBytes(POST["ButtonLabel"]); packet.Data.ChatChannel = int.Parse(POST["ChatChannel"]); packet.Data.ObjectID = new UUID(POST["ObjectID"]); client.Network.SendPacket((Packet)packet); } break; case "SaveNotecard": client.Inventory.RequestUploadNotecardAsset(Utils.StringToBytes(POST["AssetData"]), new UUID(POST["ItemID"]), new InventoryManager.InventoryUploadedAssetCallback(events.Inventory_OnNoteUploaded)); break; case "CreateInventory": client.Inventory.RequestCreateItem(new UUID(POST["Folder"]), POST["Name"], POST["Description"], (AssetType)int.Parse(POST["AssetType"]), UUID.Random(), (InventoryType)int.Parse(POST["InventoryType"]), PermissionMask.All, new InventoryManager.ItemCreatedCallback(events.Inventory_OnItemCreated)); break; case "CreateFolder": { UUID folder = client.Inventory.CreateFolder(new UUID(POST["Parent"]), POST["Name"]); textwriter.Write("{FolderID: \"" + folder + "\"}"); } break; case "EmptyTrash": client.Inventory.EmptyTrash(); break; case "MoveItem": client.Inventory.MoveItem(new UUID(POST["Item"]), new UUID(POST["TargetFolder"]), POST["NewName"]); break; case "MoveFolder": client.Inventory.MoveFolder(new UUID(POST["Folder"]), new UUID(POST["NewParent"])); break; case "MoveItems": case "MoveFolders": { Dictionary <UUID, UUID> dict = new Dictionary <UUID, UUID>(); string[] moves = POST["ToMove"].Split(','); for (int i = 0; i < moves.Length; ++i) { string[] move = moves[i].Split(' '); dict.Add(new UUID(move[0]), new UUID(move[1])); } if (messagetype == "MoveItems") { client.Inventory.MoveItems(dict); } else if (messagetype == "MoveFolders") { client.Inventory.MoveFolders(dict); } } break; case "DeleteItem": client.Inventory.RemoveItem(new UUID(POST["Item"])); break; case "DeleteFolder": client.Inventory.RemoveFolder(new UUID(POST["Folder"])); break; case "DeleteMultiple": { string[] items = POST["Items"].Split(','); List <UUID> itemlist = new List <UUID>(); for (int i = 0; i < items.Length; ++i) { itemlist.Add(new UUID(items[i])); } string[] folders = POST["Folders"].Split(','); List <UUID> folderlist = new List <UUID>(); for (int i = 0; i < items.Length; ++i) { folderlist.Add(new UUID(folders[i])); } client.Inventory.Remove(itemlist, folderlist); } break; case "GiveInventory": { client.Inventory.GiveItem(new UUID(POST["ItemID"]), POST["ItemName"], (AssetType)int.Parse(POST["AssetType"]), new UUID(POST["Recipient"]), true); } break; case "UpdateItem": { InventoryItem item = client.Inventory.FetchItem(new UUID(POST["ItemID"]), new UUID(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 UUID(POST["FolderID"]); packet.FolderData[0].ParentID = new UUID(POST["ParentID"]); packet.FolderData[0].Type = sbyte.Parse(POST["Type"]); packet.FolderData[0].Name = Utils.StringToBytes(POST["Name"]); client.Network.SendPacket((Packet)packet); } break; case "FetchItem": client.Inventory.FetchItem(new UUID(POST["Item"]), new UUID(POST["Owner"]), 5000); break; case "ReRotate": user.Rotation = -Math.PI; break; case "StartGroupIM": AjaxLife.Debug("SendMessage", "RequestJoinGroupChat(" + POST["Group"] + ")"); client.Self.RequestJoinGroupChat(new UUID(POST["Group"])); break; case "GroupInstantMessage": client.Self.InstantMessageGroup(new UUID(POST["Group"]), POST["Message"]); break; case "RequestGroupProfile": client.Groups.RequestGroupProfile(new UUID(POST["Group"])); break; case "RequestGroupMembers": client.Groups.RequestGroupMembers(new UUID(POST["Group"])); break; case "RequestGroupName": client.Groups.RequestGroupName(new UUID(POST["ID"])); break; case "JoinGroup": client.Groups.RequestJoinGroup(new UUID(POST["Group"])); break; case "LeaveGroup": client.Groups.LeaveGroup(new UUID(POST["Group"])); break; case "RequestCurrentGroups": client.Groups.RequestCurrentGroups(); break; case "GetParcelID": textwriter.Write("{\"LocalID\": " + client.Parcels.GetParcelLocalID(client.Network.CurrentSim, new Vector3(float.Parse(POST["X"]), float.Parse(POST["Y"]), float.Parse(POST["Z"]))) + "}"); break; case "RequestParcelProperties": client.Parcels.RequestParcelProperties(client.Network.CurrentSim, int.Parse(POST["LocalID"]), int.Parse(POST["SequenceID"])); break; } textwriter.Flush(); }