aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/ViewerSupport
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/ViewerSupport')
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs238
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs285
2 files changed, 523 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs
new file mode 100644
index 0000000..e76e8f2
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs
@@ -0,0 +1,238 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using OpenSim;
36using OpenSim.Region;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using Nini.Config;
44using log4net;
45using Mono.Addins;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47using OSDMap = OpenMetaverse.StructuredData.OSDMap;
48
49namespace OpenSim.Region.OptionalModules.ViewerSupport
50{
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicFloater")]
52 public class DynamicFloaterModule : INonSharedRegionModule, IDynamicFloaterModule
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Scene m_scene;
57
58 private Dictionary<UUID, Dictionary<int, FloaterData>> m_floaters = new Dictionary<UUID, Dictionary<int, FloaterData>>();
59
60 public string Name
61 {
62 get { return "DynamicFloaterModule"; }
63 }
64
65 public Type ReplaceableInterface
66 {
67 get { return null; }
68 }
69
70 public void Initialise(IConfigSource config)
71 {
72 }
73
74 public void Close()
75 {
76 }
77
78 public void AddRegion(Scene scene)
79 {
80 m_scene = scene;
81 scene.EventManager.OnNewClient += OnNewClient;
82 scene.EventManager.OnClientClosed += OnClientClosed;
83 m_scene.RegisterModuleInterface<IDynamicFloaterModule>(this);
84 }
85
86 public void RegionLoaded(Scene scene)
87 {
88 }
89
90 public void RemoveRegion(Scene scene)
91 {
92 }
93
94 private void OnNewClient(IClientAPI client)
95 {
96 client.OnChatFromClient += OnChatFromClient;
97 }
98
99 private void OnClientClosed(UUID agentID, Scene scene)
100 {
101 m_floaters.Remove(agentID);
102 }
103
104 private void SendToClient(ScenePresence sp, string msg)
105 {
106 sp.ControllingClient.SendChatMessage(msg,
107 (byte)ChatTypeEnum.Owner,
108 sp.AbsolutePosition,
109 "Server",
110 UUID.Zero,
111 UUID.Zero,
112 (byte)ChatSourceType.Object,
113 (byte)ChatAudibleLevel.Fully);
114 }
115
116 public void DoUserFloater(UUID agentID, FloaterData dialogData, string configuration)
117 {
118 ScenePresence sp = m_scene.GetScenePresence(agentID);
119 if (sp == null || sp.IsChildAgent)
120 return;
121
122 if (!m_floaters.ContainsKey(agentID))
123 m_floaters[agentID] = new Dictionary<int, FloaterData>();
124
125 if (m_floaters[agentID].ContainsKey(dialogData.Channel))
126 return;
127
128 m_floaters[agentID].Add(dialogData.Channel, dialogData);
129
130 string xml;
131 if (dialogData.XmlText != null && dialogData.XmlText != String.Empty)
132 {
133 xml = dialogData.XmlText;
134 }
135 else
136 {
137 using (FileStream fs = File.Open(dialogData.XmlName + ".xml", FileMode.Open))
138 {
139 using (StreamReader sr = new StreamReader(fs))
140 xml = sr.ReadToEnd().Replace("\n", "");
141 }
142 }
143
144 List<string> xparts = new List<string>();
145
146 while (xml.Length > 0)
147 {
148 string x = xml;
149 if (x.Length > 600)
150 {
151 x = x.Substring(0, 600);
152 xml = xml.Substring(600);
153 }
154 else
155 {
156 xml = String.Empty;
157 }
158
159 xparts.Add(x);
160 }
161
162 for (int i = 0 ; i < xparts.Count ; i++)
163 SendToClient(sp, String.Format("># floater {2} create {0}/{1} " + xparts[i], i + 1, xparts.Count, dialogData.FloaterName));
164
165 SendToClient(sp, String.Format("># floater {0} {{notify:1}} {{channel: {1}}} {{node:cancel {{notify:1}}}} {{node:ok {{notify:1}}}} {2}", dialogData.FloaterName, (uint)dialogData.Channel, configuration));
166 }
167
168 private void OnChatFromClient(object sender, OSChatMessage msg)
169 {
170 if (msg.Sender == null)
171 return;
172
173 //m_log.DebugFormat("chan {0} msg {1}", msg.Channel, msg.Message);
174
175 IClientAPI client = msg.Sender;
176
177 if (!m_floaters.ContainsKey(client.AgentId))
178 return;
179
180 string[] parts = msg.Message.Split(new char[] {':'});
181 if (parts.Length == 0)
182 return;
183
184 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
185 if (sp == null || sp.IsChildAgent)
186 return;
187
188 Dictionary<int, FloaterData> d = m_floaters[client.AgentId];
189
190 // Work around a viewer bug - VALUE from any
191 // dialog can appear on this channel and needs to
192 // be dispatched to ALL open dialogs for the user
193 if (msg.Channel == 427169570)
194 {
195 if (parts[0] == "VALUE")
196 {
197 foreach (FloaterData dd in d.Values)
198 {
199 if(dd.Handler(client, dd, parts))
200 {
201 m_floaters[client.AgentId].Remove(dd.Channel);
202 SendToClient(sp, String.Format("># floater {0} destroy", dd.FloaterName));
203 break;
204 }
205 }
206 }
207 return;
208 }
209
210 if (!d.ContainsKey(msg.Channel))
211 return;
212
213 FloaterData data = d[msg.Channel];
214
215 if (parts[0] == "NOTIFY")
216 {
217 if (parts[1] == "cancel" || parts[1] == data.FloaterName)
218 {
219 m_floaters[client.AgentId].Remove(data.Channel);
220 SendToClient(sp, String.Format("># floater {0} destroy", data.FloaterName));
221 }
222 }
223
224 if (data.Handler != null && data.Handler(client, data, parts))
225 {
226 m_floaters[client.AgentId].Remove(data.Channel);
227 SendToClient(sp, String.Format("># floater {0} destroy", data.FloaterName));
228 }
229 }
230
231 public void FloaterControl(ScenePresence sp, FloaterData d, string msg)
232 {
233 string sendData = String.Format("># floater {0} {1}", d.FloaterName, msg);
234 SendToClient(sp, sendData);
235
236 }
237 }
238}
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
new file mode 100644
index 0000000..c68fe99
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
@@ -0,0 +1,285 @@
1// ******************************************************************
2// Copyright (c) 2008, 2009 Melanie Thielker
3//
4// All rights reserved
5//
6
7using System;
8using System.IO;
9using System.Reflection;
10using System.Text;
11using System.Collections.Generic;
12using OpenMetaverse;
13using OpenMetaverse.StructuredData;
14using OpenSim;
15using OpenSim.Region;
16using OpenSim.Region.Framework;
17using OpenSim.Region.Framework.Scenes;
18using OpenSim.Region.Framework.Interfaces;
19using OpenSim.Framework;
20//using OpenSim.Framework.Capabilities;
21using OpenSim.Framework.Servers;
22using OpenSim.Framework.Servers.HttpServer;
23using Nini.Config;
24using log4net;
25using Mono.Addins;
26using Caps = OpenSim.Framework.Capabilities.Caps;
27using OSDMap = OpenMetaverse.StructuredData.OSDMap;
28
29namespace OpenSim.Region.OptionalModules.ViewerSupport
30{
31 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicMenu")]
32 public class DynamicMenuModule : INonSharedRegionModule, IDynamicMenuModule
33 {
34 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
35
36 private class MenuItemData
37 {
38 public string Title;
39 public UUID AgentID;
40 public InsertLocation Location;
41 public UserMode Mode;
42 public CustomMenuHandler Handler;
43 }
44
45 private Dictionary<UUID, List<MenuItemData>> m_menuItems =
46 new Dictionary<UUID, List<MenuItemData>>();
47
48 private Scene m_scene;
49
50 public string Name
51 {
52 get { return "DynamicMenuModule"; }
53 }
54
55 public Type ReplaceableInterface
56 {
57 get { return null; }
58 }
59
60 public void Initialise(IConfigSource config)
61 {
62 }
63
64 public void Close()
65 {
66 }
67
68 public void AddRegion(Scene scene)
69 {
70 m_scene = scene;
71 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
72 m_scene.RegisterModuleInterface<IDynamicMenuModule>(this);
73 }
74
75 public void RegionLoaded(Scene scene)
76 {
77 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
78
79 if (featuresModule != null)
80 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
81 }
82
83 public void RemoveRegion(Scene scene)
84 {
85 }
86
87 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
88 {
89 OSD menus = new OSDMap();
90 if (features.ContainsKey("menus"))
91 menus = features["menus"];
92
93 OSDMap agent = new OSDMap();
94 OSDMap world = new OSDMap();
95 OSDMap tools = new OSDMap();
96 OSDMap advanced = new OSDMap();
97 OSDMap admin = new OSDMap();
98 if (((OSDMap)menus).ContainsKey("agent"))
99 agent = (OSDMap)((OSDMap)menus)["agent"];
100 if (((OSDMap)menus).ContainsKey("world"))
101 world = (OSDMap)((OSDMap)menus)["world"];
102 if (((OSDMap)menus).ContainsKey("tools"))
103 tools = (OSDMap)((OSDMap)menus)["tools"];
104 if (((OSDMap)menus).ContainsKey("advanced"))
105 advanced = (OSDMap)((OSDMap)menus)["advanced"];
106 if (((OSDMap)menus).ContainsKey("admin"))
107 admin = (OSDMap)((OSDMap)menus)["admin"];
108
109 if (m_menuItems.ContainsKey(UUID.Zero))
110 {
111 foreach (MenuItemData d in m_menuItems[UUID.Zero])
112 {
113 if (!m_scene.Permissions.IsGod(agentID))
114 {
115 if (d.Mode == UserMode.RegionManager && (!m_scene.Permissions.IsAdministrator(agentID)))
116 continue;
117 }
118
119 OSDMap loc = null;
120 switch (d.Location)
121 {
122 case InsertLocation.Agent:
123 loc = agent;
124 break;
125 case InsertLocation.World:
126 loc = world;
127 break;
128 case InsertLocation.Tools:
129 loc = tools;
130 break;
131 case InsertLocation.Advanced:
132 loc = advanced;
133 break;
134 case InsertLocation.Admin:
135 loc = admin;
136 break;
137 }
138
139 if (loc == null)
140 continue;
141
142 loc[d.Title] = OSD.FromString(d.Title);
143 }
144 }
145
146 if (m_menuItems.ContainsKey(agentID))
147 {
148 foreach (MenuItemData d in m_menuItems[agentID])
149 {
150 if (d.Mode == UserMode.God && (!m_scene.Permissions.IsGod(agentID)))
151 continue;
152
153 OSDMap loc = null;
154 switch (d.Location)
155 {
156 case InsertLocation.Agent:
157 loc = agent;
158 break;
159 case InsertLocation.World:
160 loc = world;
161 break;
162 case InsertLocation.Tools:
163 loc = tools;
164 break;
165 case InsertLocation.Advanced:
166 loc = advanced;
167 break;
168 case InsertLocation.Admin:
169 loc = admin;
170 break;
171 }
172
173 if (loc == null)
174 continue;
175
176 loc[d.Title] = OSD.FromString(d.Title);
177 }
178 }
179
180
181 ((OSDMap)menus)["agent"] = agent;
182 ((OSDMap)menus)["world"] = world;
183 ((OSDMap)menus)["tools"] = tools;
184 ((OSDMap)menus)["advanced"] = advanced;
185 ((OSDMap)menus)["admin"] = admin;
186
187 features["menus"] = menus;
188 }
189
190 private void OnRegisterCaps(UUID agentID, Caps caps)
191 {
192 string capUrl = "/CAPS/" + UUID.Random() + "/";
193
194 capUrl = "/CAPS/" + UUID.Random() + "/";
195 caps.RegisterHandler("CustomMenuAction", new MenuActionHandler(capUrl, "CustomMenuAction", agentID, this, m_scene));
196 }
197
198 internal void HandleMenuSelection(string action, UUID agentID, List<uint> selection)
199 {
200 if (m_menuItems.ContainsKey(agentID))
201 {
202 foreach (MenuItemData d in m_menuItems[agentID])
203 {
204 if (d.Title == action)
205 d.Handler(action, agentID, selection);
206 }
207 }
208
209 if (m_menuItems.ContainsKey(UUID.Zero))
210 {
211 foreach (MenuItemData d in m_menuItems[UUID.Zero])
212 {
213 if (d.Title == action)
214 d.Handler(action, agentID, selection);
215 }
216 }
217 }
218
219 public void AddMenuItem(string title, InsertLocation location, UserMode mode, CustomMenuHandler handler)
220 {
221 AddMenuItem(UUID.Zero, title, location, mode, handler);
222 }
223
224 public void AddMenuItem(UUID agentID, string title, InsertLocation location, UserMode mode, CustomMenuHandler handler)
225 {
226 if (!m_menuItems.ContainsKey(agentID))
227 m_menuItems[agentID] = new List<MenuItemData>();
228
229 m_menuItems[agentID].Add(new MenuItemData() { Title = title, AgentID = agentID, Location = location, Mode = mode, Handler = handler });
230 }
231
232 public void RemoveMenuItem(string action)
233 {
234 foreach (KeyValuePair<UUID,List< MenuItemData>> kvp in m_menuItems)
235 {
236 List<MenuItemData> pendingDeletes = new List<MenuItemData>();
237 foreach (MenuItemData d in kvp.Value)
238 {
239 if (d.Title == action)
240 pendingDeletes.Add(d);
241 }
242
243 foreach (MenuItemData d in pendingDeletes)
244 kvp.Value.Remove(d);
245 }
246 }
247 }
248
249 public class MenuActionHandler : BaseStreamHandler
250 {
251 private static readonly ILog m_log =
252 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
253
254 private UUID m_agentID;
255 private Scene m_scene;
256 private DynamicMenuModule m_module;
257
258 public MenuActionHandler(string path, string name, UUID agentID, DynamicMenuModule module, Scene scene)
259 :base("POST", path, name, agentID.ToString())
260 {
261 m_agentID = agentID;
262 m_scene = scene;
263 m_module = module;
264 }
265
266 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
267 {
268 StreamReader reader = new StreamReader(request);
269 string requestBody = reader.ReadToEnd();
270
271 OSD osd = OSDParser.DeserializeLLSDXml(requestBody);
272
273 string action = ((OSDMap)osd)["action"].AsString();
274 OSDArray selection = (OSDArray)((OSDMap)osd)["selection"];
275 List<uint> sel = new List<uint>();
276 for (int i = 0 ; i < selection.Count ; i++)
277 sel.Add(selection[i].AsUInteger());
278
279 Util.FireAndForget(x => { m_module.HandleMenuSelection(action, m_agentID, sel); });
280
281 Encoding encoding = Encoding.UTF8;
282 return encoding.GetBytes(OSDParser.SerializeLLSDXmlString(new OSD()));
283 }
284 }
285}