aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Capabilities
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to 'OpenSim/Capabilities')
-rw-r--r--OpenSim/Capabilities/Caps.cs102
-rw-r--r--OpenSim/Capabilities/CapsHandlers.cs19
-rw-r--r--OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs116
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs848
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs (renamed from OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs)8
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs (renamed from OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs)41
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs170
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs292
-rw-r--r--OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs120
-rw-r--r--OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs (renamed from OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs)32
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs239
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs29
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs17
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs3
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs76
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs438
-rw-r--r--OpenSim/Capabilities/LLSD.cs29
-rw-r--r--OpenSim/Capabilities/LLSDAvatarPicker.cs51
-rw-r--r--OpenSim/Capabilities/LLSDStreamHandler.cs2
-rw-r--r--OpenSim/Capabilities/Properties/AssemblyInfo.cs2
22 files changed, 2069 insertions, 573 deletions
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index bc6f6f9..049afab 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -50,8 +50,7 @@ namespace OpenSim.Framework.Capabilities
50 50
51 public class Caps 51 public class Caps
52 { 52 {
53// private static readonly ILog m_log = 53// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 54
56 private string m_httpListenerHostName; 55 private string m_httpListenerHostName;
57 private uint m_httpListenPort; 56 private uint m_httpListenPort;
@@ -63,7 +62,11 @@ namespace OpenSim.Framework.Capabilities
63 public string CapsObjectPath { get { return m_capsObjectPath; } } 62 public string CapsObjectPath { get { return m_capsObjectPath; } }
64 63
65 private CapsHandlers m_capsHandlers; 64 private CapsHandlers m_capsHandlers;
66 private Dictionary<string, string> m_externalCapsHandlers; 65
66 private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
67 = new Dictionary<string, PollServiceEventArgs>();
68
69 private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
67 70
68 private IHttpServer m_httpListener; 71 private IHttpServer m_httpListener;
69 private UUID m_agentID; 72 private UUID m_agentID;
@@ -132,7 +135,6 @@ namespace OpenSim.Framework.Capabilities
132 135
133 m_agentID = agent; 136 m_agentID = agent;
134 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); 137 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
135 m_externalCapsHandlers = new Dictionary<string, string>();
136 m_regionName = regionName; 138 m_regionName = regionName;
137 } 139 }
138 140
@@ -143,8 +145,33 @@ namespace OpenSim.Framework.Capabilities
143 /// <param name="handler"></param> 145 /// <param name="handler"></param>
144 public void RegisterHandler(string capName, IRequestHandler handler) 146 public void RegisterHandler(string capName, IRequestHandler handler)
145 { 147 {
146 m_capsHandlers[capName] = handler;
147 //m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path); 148 //m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
149 m_capsHandlers[capName] = handler;
150 }
151
152 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
153 {
154// m_log.DebugFormat(
155// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
156// capName, pollServiceHandler.Url, m_agentID, m_regionName);
157
158 m_pollServiceHandlers.Add(capName, pollServiceHandler);
159
160 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
161
162// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
163// string protocol = "http";
164// string hostName = m_httpListenerHostName;
165//
166// if (MainServer.Instance.UseSSL)
167// {
168// hostName = MainServer.Instance.SSLCommonName;
169// port = MainServer.Instance.SSLPort;
170// protocol = "https";
171// }
172
173// RegisterHandler(
174// capName, String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, pollServiceHandler.Url));
148 } 175 }
149 176
150 /// <summary> 177 /// <summary>
@@ -163,13 +190,70 @@ namespace OpenSim.Framework.Capabilities
163 /// </summary> 190 /// </summary>
164 public void DeregisterHandlers() 191 public void DeregisterHandlers()
165 { 192 {
166 if (m_capsHandlers != null) 193 foreach (string capsName in m_capsHandlers.Caps)
194 {
195 m_capsHandlers.Remove(capsName);
196 }
197
198 foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
167 { 199 {
168 foreach (string capsName in m_capsHandlers.Caps) 200 m_httpListener.RemovePollServiceHTTPHandler("", handler.Url);
201 }
202 }
203
204 public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
205 {
206 return m_pollServiceHandlers.TryGetValue(name, out pollHandler);
207 }
208
209 public Dictionary<string, PollServiceEventArgs> GetPollHandlers()
210 {
211 return new Dictionary<string, PollServiceEventArgs>(m_pollServiceHandlers);
212 }
213
214 /// <summary>
215 /// Return an LLSD-serializable Hashtable describing the
216 /// capabilities and their handler details.
217 /// </summary>
218 /// <param name="excludeSeed">If true, then exclude the seed cap.</param>
219 public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
220 {
221 Hashtable caps = CapsHandlers.GetCapsDetails(excludeSeed, requestedCaps);
222
223 lock (m_pollServiceHandlers)
224 {
225 foreach (KeyValuePair <string, PollServiceEventArgs> kvp in m_pollServiceHandlers)
169 { 226 {
170 m_capsHandlers.Remove(capsName); 227 if (!requestedCaps.Contains(kvp.Key))
228 continue;
229
230 string hostName = m_httpListenerHostName;
231 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
232 string protocol = "http";
233
234 if (MainServer.Instance.UseSSL)
235 {
236 hostName = MainServer.Instance.SSLCommonName;
237 port = MainServer.Instance.SSLPort;
238 protocol = "https";
239 }
240 //
241 // caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
242
243 caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
171 } 244 }
172 } 245 }
246
247 // Add the external too
248 foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
249 {
250 if (!requestedCaps.Contains(kvp.Key))
251 continue;
252
253 caps[kvp.Key] = kvp.Value;
254 }
255
256 return caps;
173 } 257 }
174 } 258 }
175} 259} \ No newline at end of file
diff --git a/OpenSim/Capabilities/CapsHandlers.cs b/OpenSim/Capabilities/CapsHandlers.cs
index 1709f46..890df90 100644
--- a/OpenSim/Capabilities/CapsHandlers.cs
+++ b/OpenSim/Capabilities/CapsHandlers.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Capabilities
39 /// </summary> 39 /// </summary>
40 public class CapsHandlers 40 public class CapsHandlers
41 { 41 {
42 private Dictionary <string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>(); 42 private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
43 private IHttpServer m_httpListener; 43 private IHttpServer m_httpListener;
44 private string m_httpListenerHostName; 44 private string m_httpListenerHostName;
45 private uint m_httpListenerPort; 45 private uint m_httpListenerPort;
@@ -158,7 +158,7 @@ namespace OpenSim.Framework.Capabilities
158 /// capabilities and their handler details. 158 /// capabilities and their handler details.
159 /// </summary> 159 /// </summary>
160 /// <param name="excludeSeed">If true, then exclude the seed cap.</param> 160 /// <param name="excludeSeed">If true, then exclude the seed cap.</param>
161 public Hashtable GetCapsDetails(bool excludeSeed) 161 public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
162 { 162 {
163 Hashtable caps = new Hashtable(); 163 Hashtable caps = new Hashtable();
164 string protocol = "http://"; 164 string protocol = "http://";
@@ -175,11 +175,26 @@ namespace OpenSim.Framework.Capabilities
175 if (excludeSeed && "SEED" == capsName) 175 if (excludeSeed && "SEED" == capsName)
176 continue; 176 continue;
177 177
178 if (requestedCaps != null && !requestedCaps.Contains(capsName))
179 continue;
180
178 caps[capsName] = baseUrl + m_capsHandlers[capsName].Path; 181 caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
179 } 182 }
180 } 183 }
181 184
182 return caps; 185 return caps;
183 } 186 }
187
188 /// <summary>
189 /// Returns a copy of the dictionary of all the HTTP cap handlers
190 /// </summary>
191 /// <returns>
192 /// The dictionary copy. The key is the capability name, the value is the HTTP handler.
193 /// </returns>
194 public Dictionary<string, IRequestHandler> GetCapsHandlers()
195 {
196 lock (m_capsHandlers)
197 return new Dictionary<string, IRequestHandler>(m_capsHandlers);
198 }
184 } 199 }
185} \ No newline at end of file 200} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs
new file mode 100644
index 0000000..426174d
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs
@@ -0,0 +1,116 @@
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.Collections.Generic;
30using System.Collections.Specialized;
31using System.IO;
32using System.Reflection;
33using System.Web;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Capabilities;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41//using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Services.Interfaces;
43using Caps = OpenSim.Framework.Capabilities.Caps;
44
45namespace OpenSim.Capabilities.Handlers
46{
47 public class AvatarPickerSearchHandler : BaseStreamHandler
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private IPeople m_PeopleService;
52
53 public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description)
54 : base("GET", path, name, description)
55 {
56 m_PeopleService = peopleService;
57 }
58
59 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 {
61 // Try to parse the texture ID from the request URL
62 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
63 string names = query.GetOne("names");
64 string psize = query.GetOne("page_size");
65 string pnumber = query.GetOne("page");
66
67 if (m_PeopleService == null)
68 return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse);
69
70 if (string.IsNullOrEmpty(names) || names.Length < 3)
71 return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse);
72
73 m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names);
74
75 int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize));
76 int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber));
77
78 // Full content request
79 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
80 //httpResponse.ContentLength = ??;
81 httpResponse.ContentType = "application/llsd+xml";
82
83 List<UserData> users = m_PeopleService.GetUserData(names, page_size, page_number);
84
85 LLSDAvatarPicker osdReply = new LLSDAvatarPicker();
86 osdReply.next_page_url = httpRequest.RawUrl;
87 foreach (UserData u in users)
88 osdReply.agents.Array.Add(ConvertUserData(u));
89
90 string reply = LLSDHelpers.SerialiseLLSDReply(osdReply);
91 return System.Text.Encoding.UTF8.GetBytes(reply);
92 }
93
94 private LLSDPerson ConvertUserData(UserData user)
95 {
96 LLSDPerson p = new LLSDPerson();
97 p.legacy_first_name = user.FirstName;
98 p.legacy_last_name = user.LastName;
99 p.display_name = user.FirstName + " " + user.LastName;
100 if (user.LastName.StartsWith("@"))
101 p.username = user.FirstName.ToLower() + user.LastName.ToLower();
102 else
103 p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
104 p.id = user.Id;
105 p.is_display_name_default = false;
106 return p;
107 }
108
109 private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse)
110 {
111 m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names);
112 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
113 return System.Text.Encoding.UTF8.GetBytes(string.Empty);
114 }
115 }
116} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
new file mode 100644
index 0000000..7197049
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
@@ -0,0 +1,848 @@
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.Collections;
30using System.Collections.Generic;
31using System.Linq;
32using System.Reflection;
33using log4net;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Framework.Capabilities;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps;
43
44namespace OpenSim.Capabilities.Handlers
45{
46 public class FetchInvDescHandler
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IInventoryService m_InventoryService;
52 private ILibraryService m_LibraryService;
53 private IScene m_Scene;
54// private object m_fetchLock = new Object();
55
56 public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s)
57 {
58 m_InventoryService = invService;
59 m_LibraryService = libService;
60 m_Scene = s;
61 }
62
63
64 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
65 {
66 //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);
67
68 // nasty temporary hack here, the linden client falsely
69 // identifies the uuid 00000000-0000-0000-0000-000000000000
70 // as a string which breaks us
71 //
72 // correctly mark it as a uuid
73 //
74 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
75
76 // another hack <integer>1</integer> results in a
77 // System.ArgumentException: Object type System.Int32 cannot
78 // be converted to target type: System.Boolean
79 //
80 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
81 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
82
83 Hashtable hash = new Hashtable();
84 try
85 {
86 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
87 }
88 catch (LLSD.LLSDParseException e)
89 {
90 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
91 m_log.Error("Request: " + request);
92 }
93
94 ArrayList foldersrequested = (ArrayList)hash["folders"];
95
96 string response = "";
97 string bad_folders_response = "";
98
99 List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
100 for (int i = 0; i < foldersrequested.Count; i++)
101 {
102 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
103
104 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
105
106 try
107 {
108 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
109 }
110 catch (Exception e)
111 {
112 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
113 continue;
114 }
115
116 // Filter duplicate folder ids that bad viewers may send
117 if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
118 folders.Add(llsdRequest);
119
120 }
121
122 if (folders.Count > 0)
123 {
124 List<UUID> bad_folders = new List<UUID>();
125 List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
126 //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
127
128 if (invcollSet == null)
129 {
130 m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
131#pragma warning disable 0612
132 return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
133#pragma warning restore 0612
134 }
135
136 string inventoryitemstr = string.Empty;
137 foreach (InventoryCollectionWithDescendents icoll in invcollSet)
138 {
139 LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
140
141 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
142 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
143 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
144
145 response += inventoryitemstr;
146 }
147
148 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
149 foreach (UUID bad in bad_folders)
150 bad_folders_response += "<uuid>" + bad + "</uuid>";
151 }
152
153 if (response.Length == 0)
154 {
155 /* Viewers expect a bad_folders array when not available */
156 if (bad_folders_response.Length != 0)
157 {
158 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
159 }
160 else
161 {
162 response = "<llsd><map><key>folders</key><array /></map></llsd>";
163 }
164 }
165 else
166 {
167 if (bad_folders_response.Length != 0)
168 {
169 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
170 }
171 else
172 {
173 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
174 }
175 }
176
177 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count);
178 //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
179
180 return response;
181
182 }
183
184 /// <summary>
185 /// Construct an LLSD reply packet to a CAPS inventory request
186 /// </summary>
187 /// <param name="invFetch"></param>
188 /// <returns></returns>
189 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
190 {
191 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
192 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
193 contents.agent_id = invFetch.owner_id;
194 contents.owner_id = invFetch.owner_id;
195 contents.folder_id = invFetch.folder_id;
196
197 reply.folders.Array.Add(contents);
198 InventoryCollection inv = new InventoryCollection();
199 inv.Folders = new List<InventoryFolderBase>();
200 inv.Items = new List<InventoryItemBase>();
201 int version = 0;
202 int descendents = 0;
203
204#pragma warning disable 0612
205 inv = Fetch(
206 invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
207 invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
208#pragma warning restore 0612
209
210 if (inv != null && inv.Folders != null)
211 {
212 foreach (InventoryFolderBase invFolder in inv.Folders)
213 {
214 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
215 }
216
217 descendents += inv.Folders.Count;
218 }
219
220 if (inv != null && inv.Items != null)
221 {
222 foreach (InventoryItemBase invItem in inv.Items)
223 {
224 contents.items.Array.Add(ConvertInventoryItem(invItem));
225 }
226 }
227
228 contents.descendents = descendents;
229 contents.version = version;
230
231 //m_log.DebugFormat(
232 // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
233 // invFetch.folder_id,
234 // invFetch.fetch_items,
235 // invFetch.fetch_folders,
236 // contents.items.Array.Count,
237 // contents.categories.Array.Count,
238 // invFetch.owner_id);
239
240 return reply;
241 }
242
243 private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
244 {
245 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
246 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
247 contents.agent_id = inv.OwnerID;
248 contents.owner_id = inv.OwnerID;
249 contents.folder_id = inv.FolderID;
250
251 reply.folders.Array.Add(contents);
252
253 if (inv.Folders != null)
254 {
255 foreach (InventoryFolderBase invFolder in inv.Folders)
256 {
257 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
258 }
259
260 descendents += inv.Folders.Count;
261 }
262
263 if (inv.Items != null)
264 {
265 foreach (InventoryItemBase invItem in inv.Items)
266 {
267 contents.items.Array.Add(ConvertInventoryItem(invItem));
268 }
269 }
270
271 contents.descendents = descendents;
272 contents.version = inv.Version;
273
274 return reply;
275 }
276 /// <summary>
277 /// Old style. Soon to be deprecated.
278 /// </summary>
279 /// <param name="request"></param>
280 /// <param name="httpRequest"></param>
281 /// <param name="httpResponse"></param>
282 /// <returns></returns>
283 [Obsolete]
284 private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
285 {
286 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
287
288 string response = "";
289 string bad_folders_response = "";
290
291 for (int i = 0; i < foldersrequested.Count; i++)
292 {
293 string inventoryitemstr = "";
294 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
295
296 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
297
298 try
299 {
300 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
301 }
302 catch (Exception e)
303 {
304 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
305 }
306
307 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
308
309 if (null == reply)
310 {
311 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
312 }
313 else
314 {
315 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
316 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
317 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
318 }
319
320 response += inventoryitemstr;
321 }
322
323 if (response.Length == 0)
324 {
325 /* Viewers expect a bad_folders array when not available */
326 if (bad_folders_response.Length != 0)
327 {
328 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
329 }
330 else
331 {
332 response = "<llsd><map><key>folders</key><array /></map></llsd>";
333 }
334 }
335 else
336 {
337 if (bad_folders_response.Length != 0)
338 {
339 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
340 }
341 else
342 {
343 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
344 }
345 }
346
347 // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
348 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
349
350 return response;
351
352 // }
353 }
354
355 /// <summary>
356 /// Handle the caps inventory descendents fetch.
357 /// </summary>
358 /// <param name="agentID"></param>
359 /// <param name="folderID"></param>
360 /// <param name="ownerID"></param>
361 /// <param name="fetchFolders"></param>
362 /// <param name="fetchItems"></param>
363 /// <param name="sortOrder"></param>
364 /// <param name="version"></param>
365 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
366 [Obsolete]
367 private InventoryCollection Fetch(
368 UUID agentID, UUID folderID, UUID ownerID,
369 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
370 {
371 //m_log.DebugFormat(
372 // "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
373 // fetchFolders, fetchItems, folderID, agentID);
374
375 // FIXME MAYBE: We're not handling sortOrder!
376
377 version = 0;
378 descendents = 0;
379
380 InventoryFolderImpl fold;
381 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
382 {
383 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
384 {
385 InventoryCollection ret = new InventoryCollection();
386 ret.Folders = new List<InventoryFolderBase>();
387 ret.Items = fold.RequestListOfItems();
388 descendents = ret.Folders.Count + ret.Items.Count;
389
390 return ret;
391 }
392 }
393
394 InventoryCollection contents = new InventoryCollection();
395
396 if (folderID != UUID.Zero)
397 {
398 InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
399
400 if (fetchedContents == null)
401 {
402 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
403 return contents;
404 }
405 contents = fetchedContents;
406 InventoryFolderBase containingFolder = new InventoryFolderBase();
407 containingFolder.ID = folderID;
408 containingFolder.Owner = agentID;
409 containingFolder = m_InventoryService.GetFolder(containingFolder);
410
411 if (containingFolder != null)
412 {
413 //m_log.DebugFormat(
414 // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
415 // containingFolder.Name, containingFolder.ID, agentID);
416
417 version = containingFolder.Version;
418
419 if (fetchItems)
420 {
421 List<InventoryItemBase> itemsToReturn = contents.Items;
422 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
423
424 // descendents must only include the links, not the linked items we add
425 descendents = originalItems.Count;
426
427 // Add target items for links in this folder before the links themselves.
428 foreach (InventoryItemBase item in originalItems)
429 {
430 if (item.AssetType == (int)AssetType.Link)
431 {
432 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
433
434 // Take care of genuinely broken links where the target doesn't exist
435 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
436 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
437 // rather than having to keep track of every folder requested in the recursion.
438 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
439 itemsToReturn.Insert(0, linkedItem);
440 }
441 }
442
443 // Now scan for folder links and insert the items they target and those links at the head of the return data
444 foreach (InventoryItemBase item in originalItems)
445 {
446 if (item.AssetType == (int)AssetType.LinkFolder)
447 {
448 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
449 List<InventoryItemBase> links = linkedFolderContents.Items;
450
451 itemsToReturn.InsertRange(0, links);
452
453 foreach (InventoryItemBase link in linkedFolderContents.Items)
454 {
455 // Take care of genuinely broken links where the target doesn't exist
456 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
457 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
458 // rather than having to keep track of every folder requested in the recursion.
459 if (link != null)
460 {
461// m_log.DebugFormat(
462// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
463// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
464
465 InventoryItemBase linkedItem
466 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
467
468 if (linkedItem != null)
469 itemsToReturn.Insert(0, linkedItem);
470 }
471 }
472 }
473 }
474 }
475
476// foreach (InventoryItemBase item in contents.Items)
477// {
478// m_log.DebugFormat(
479// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
480// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
481// }
482
483 // =====
484
485//
486// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
487// {
488// m_log.DebugFormat(
489// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
490// linkedItem.Name, folderID, agentID);
491//
492// contents.Items.Add(linkedItem);
493// }
494//
495// // If the folder requested contains links, then we need to send those folders first, otherwise the links
496// // will be broken in the viewer.
497// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
498// foreach (InventoryItemBase item in contents.Items)
499// {
500// if (item.AssetType == (int)AssetType.Link)
501// {
502// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
503//
504// // Take care of genuinely broken links where the target doesn't exist
505// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
506// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
507// // rather than having to keep track of every folder requested in the recursion.
508// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
509// {
510// // We don't need to send the folder if source and destination of the link are in the same
511// // folder.
512// if (linkedItem.Folder != containingFolder.ID)
513// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
514// }
515// }
516// }
517//
518// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
519// {
520// m_log.DebugFormat(
521// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
522// linkedItemFolderId, folderID, agentID);
523//
524// int dummyVersion;
525// InventoryCollection linkedCollection
526// = Fetch(
527// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
528//
529// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
530// linkedFolder.Owner = agentID;
531// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
532//
533//// contents.Folders.AddRange(linkedCollection.Folders);
534//
535// contents.Folders.Add(linkedFolder);
536// contents.Items.AddRange(linkedCollection.Items);
537// }
538// }
539 }
540 }
541 else
542 {
543 // Lost items don't really need a version
544 version = 1;
545 }
546
547 return contents;
548
549 }
550
551 private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
552 {
553 InventoryFolderImpl fold;
554 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
555 {
556 List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
557 fetchFolders.RemoveAll(f => libfolders.Contains(f));
558
559 //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count);
560
561 foreach (LLSDFetchInventoryDescendents f in libfolders)
562 {
563 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
564 {
565 InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
566 ret.Collection = new InventoryCollection();
567 ret.Collection.Folders = new List<InventoryFolderBase>();
568 ret.Collection.Items = fold.RequestListOfItems();
569 ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
570 ret.Collection.FolderID = f.folder_id;
571 ret.Collection.Version = fold.Version;
572
573 ret.Descendents = ret.Collection.Items.Count;
574 result.Add(ret);
575
576 //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
577 }
578 }
579 }
580 }
581
582 private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders)
583 {
584 //m_log.DebugFormat(
585 // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
586
587 // FIXME MAYBE: We're not handling sortOrder!
588
589 List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
590
591 AddLibraryFolders(fetchFolders, result);
592
593 // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense
594 // and can kill the sim (all root folders have parent_id Zero)
595 LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero);
596 if (zero != null)
597 {
598 fetchFolders.Remove(zero);
599 BadFolder(zero, null, bad_folders);
600 }
601
602 if (fetchFolders.Count > 0)
603 {
604 UUID[] fids = new UUID[fetchFolders.Count];
605 int i = 0;
606 foreach (LLSDFetchInventoryDescendents f in fetchFolders)
607 fids[i++] = f.folder_id;
608
609 //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
610
611 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
612
613 if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
614 {
615 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
616 foreach (LLSDFetchInventoryDescendents freq in fetchFolders)
617 BadFolder(freq, null, bad_folders);
618 return null;
619 }
620
621 i = 0;
622 // Do some post-processing. May need to fetch more from inv server for links
623 foreach (InventoryCollection contents in fetchedContents)
624 {
625 // Find the original request
626 LLSDFetchInventoryDescendents freq = fetchFolders[i++];
627
628 InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
629 coll.Collection = contents;
630
631 if (BadFolder(freq, contents, bad_folders))
632 continue;
633
634 // Next: link management
635 ProcessLinks(freq, coll);
636
637 result.Add(coll);
638 }
639 }
640
641 return result;
642 }
643
644 private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders)
645 {
646 bool bad = false;
647 if (contents == null)
648 {
649 bad_folders.Add(freq.folder_id);
650 bad = true;
651 }
652
653 // The inventory server isn't sending FolderID in the collection...
654 // Must fetch it individually
655 else if (contents.FolderID == UUID.Zero)
656 {
657 InventoryFolderBase containingFolder = new InventoryFolderBase();
658 containingFolder.ID = freq.folder_id;
659 containingFolder.Owner = freq.owner_id;
660 containingFolder = m_InventoryService.GetFolder(containingFolder);
661
662 if (containingFolder != null)
663 {
664 contents.FolderID = containingFolder.ID;
665 contents.OwnerID = containingFolder.Owner;
666 contents.Version = containingFolder.Version;
667 }
668 else
669 {
670 // Was it really a request for folder Zero?
671 // This is an overkill, but Firestorm really asks for folder Zero.
672 // I'm leaving the code here for the time being, but commented.
673 if (freq.folder_id == UUID.Zero)
674 {
675 //coll.Collection.OwnerID = freq.owner_id;
676 //coll.Collection.FolderID = contents.FolderID;
677 //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
678 //if (containingFolder != null)
679 //{
680 // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
681 // coll.Collection.Folders.Clear();
682 // coll.Collection.Folders.Add(containingFolder);
683 // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
684 // {
685 // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
686 // lib.Name = m_LibraryService.LibraryRootFolder.Name;
687 // lib.Type = m_LibraryService.LibraryRootFolder.Type;
688 // lib.Version = m_LibraryService.LibraryRootFolder.Version;
689 // coll.Collection.Folders.Add(lib);
690 // }
691 // coll.Collection.Items.Clear();
692 //}
693 }
694 else
695 {
696 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
697 bad_folders.Add(freq.folder_id);
698 }
699 bad = true;
700 }
701 }
702
703 return bad;
704 }
705
706 private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll)
707 {
708 InventoryCollection contents = coll.Collection;
709
710 if (freq.fetch_items && contents.Items != null)
711 {
712 List<InventoryItemBase> itemsToReturn = contents.Items;
713
714 // descendents must only include the links, not the linked items we add
715 coll.Descendents = itemsToReturn.Count;
716
717 // Add target items for links in this folder before the links themselves.
718 List<UUID> itemIDs = new List<UUID>();
719 List<UUID> folderIDs = new List<UUID>();
720 foreach (InventoryItemBase item in itemsToReturn)
721 {
722 //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
723 if (item.AssetType == (int)AssetType.Link)
724 itemIDs.Add(item.AssetID);
725
726 else if (item.AssetType == (int)AssetType.LinkFolder)
727 folderIDs.Add(item.AssetID);
728 }
729
730 //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
731
732 // Scan for folder links and insert the items they target and those links at the head of the return data
733 if (folderIDs.Count > 0)
734 {
735 InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
736 foreach (InventoryCollection linkedFolderContents in linkedFolders)
737 {
738 if (linkedFolderContents == null)
739 continue;
740
741 List<InventoryItemBase> links = linkedFolderContents.Items;
742
743 itemsToReturn.InsertRange(0, links);
744
745 }
746 }
747
748 if (itemIDs.Count > 0)
749 {
750 InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
751 if (linked == null)
752 {
753 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
754 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
755 linked = new InventoryItemBase[itemIDs.Count];
756 int i = 0;
757 InventoryItemBase item = new InventoryItemBase();
758 item.Owner = freq.owner_id;
759 foreach (UUID id in itemIDs)
760 {
761 item.ID = id;
762 linked[i++] = m_InventoryService.GetItem(item);
763 }
764 }
765
766 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
767 //foreach (InventoryItemBase item in itemsToReturn)
768 // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
769
770 if (linked != null)
771 {
772 foreach (InventoryItemBase linkedItem in linked)
773 {
774 // Take care of genuinely broken links where the target doesn't exist
775 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
776 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
777 // rather than having to keep track of every folder requested in the recursion.
778 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
779 {
780 itemsToReturn.Insert(0, linkedItem);
781 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
782 }
783 }
784 }
785 }
786 }
787
788 }
789
790 /// <summary>
791 /// Convert an internal inventory folder object into an LLSD object.
792 /// </summary>
793 /// <param name="invFolder"></param>
794 /// <returns></returns>
795 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
796 {
797 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
798 llsdFolder.folder_id = invFolder.ID;
799 llsdFolder.parent_id = invFolder.ParentID;
800 llsdFolder.name = invFolder.Name;
801 llsdFolder.type = invFolder.Type;
802 llsdFolder.preferred_type = -1;
803
804 return llsdFolder;
805 }
806
807 /// <summary>
808 /// Convert an internal inventory item object into an LLSD object.
809 /// </summary>
810 /// <param name="invItem"></param>
811 /// <returns></returns>
812 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
813 {
814 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
815 llsdItem.asset_id = invItem.AssetID;
816 llsdItem.created_at = invItem.CreationDate;
817 llsdItem.desc = invItem.Description;
818 llsdItem.flags = (int)invItem.Flags;
819 llsdItem.item_id = invItem.ID;
820 llsdItem.name = invItem.Name;
821 llsdItem.parent_id = invItem.Folder;
822 llsdItem.type = invItem.AssetType;
823 llsdItem.inv_type = invItem.InvType;
824
825 llsdItem.permissions = new LLSDPermissions();
826 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
827 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
828 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
829 llsdItem.permissions.group_id = invItem.GroupID;
830 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
831 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
832 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
833 llsdItem.permissions.owner_id = invItem.Owner;
834 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
835 llsdItem.sale_info = new LLSDSaleInfo();
836 llsdItem.sale_info.sale_price = invItem.SalePrice;
837 llsdItem.sale_info.sale_type = invItem.SaleType;
838
839 return llsdItem;
840 }
841 }
842
843 class InventoryCollectionWithDescendents
844 {
845 public InventoryCollection Collection;
846 public int Descendents;
847 }
848} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs
index 5d86557..9dcfaa4 100644
--- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs
@@ -35,13 +35,13 @@ using OpenMetaverse;
35 35
36namespace OpenSim.Capabilities.Handlers 36namespace OpenSim.Capabilities.Handlers
37{ 37{
38 public class WebFetchInvDescServerConnector : ServiceConnector 38 public class FetchInvDescServerConnector : ServiceConnector
39 { 39 {
40 private IInventoryService m_InventoryService; 40 private IInventoryService m_InventoryService;
41 private ILibraryService m_LibraryService; 41 private ILibraryService m_LibraryService;
42 private string m_ConfigName = "CapsService"; 42 private string m_ConfigName = "CapsService";
43 43
44 public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) : 44 public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
45 base(config, server, configName) 45 base(config, server, configName)
46 { 46 {
47 if (configName != String.Empty) 47 if (configName != String.Empty)
@@ -67,13 +67,13 @@ namespace OpenSim.Capabilities.Handlers
67 m_LibraryService = 67 m_LibraryService =
68 ServerUtils.LoadPlugin<ILibraryService>(libService, args); 68 ServerUtils.LoadPlugin<ILibraryService>(libService, args);
69 69
70 WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); 70 FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
71 IRequestHandler reqHandler 71 IRequestHandler reqHandler
72 = new RestStreamHandler( 72 = new RestStreamHandler(
73 "POST", 73 "POST",
74 "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, 74 "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
75 webFetchHandler.FetchInventoryDescendentsRequest, 75 webFetchHandler.FetchInventoryDescendentsRequest,
76 "WebFetchInvDesc", 76 "FetchInvDescendents",
77 null); 77 null);
78 server.AddStreamHandler(reqHandler); 78 server.AddStreamHandler(reqHandler);
79 } 79 }
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
index c0ca1e1..c904392 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
@@ -25,23 +25,18 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection; 28using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse; 29using OpenMetaverse;
35using OpenMetaverse.StructuredData; 30using OpenMetaverse.StructuredData;
36using OpenSim.Framework; 31using OpenSim.Framework;
37using OpenSim.Framework.Capabilities; 32using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer; 33using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42using OSDArray = OpenMetaverse.StructuredData.OSDArray; 35using OSDArray = OpenMetaverse.StructuredData.OSDArray;
43using OSDMap = OpenMetaverse.StructuredData.OSDMap; 36using OSDMap = OpenMetaverse.StructuredData.OSDMap;
44 37
38using log4net;
39
45namespace OpenSim.Capabilities.Handlers 40namespace OpenSim.Capabilities.Handlers
46{ 41{
47 public class FetchInventory2Handler 42 public class FetchInventory2Handler
@@ -49,15 +44,17 @@ namespace OpenSim.Capabilities.Handlers
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 45
51 private IInventoryService m_inventoryService; 46 private IInventoryService m_inventoryService;
47 private UUID m_agentID;
52 48
53 public FetchInventory2Handler(IInventoryService invService) 49 public FetchInventory2Handler(IInventoryService invService, UUID agentId)
54 { 50 {
55 m_inventoryService = invService; 51 m_inventoryService = invService;
52 m_agentID = agentId;
56 } 53 }
57 54
58 public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 55 public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 56 {
60// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); 57 //m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request);
61 58
62 OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); 59 OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request));
63 OSDArray itemsRequested = (OSDArray)requestmap["items"]; 60 OSDArray itemsRequested = (OSDArray)requestmap["items"];
@@ -65,12 +62,32 @@ namespace OpenSim.Capabilities.Handlers
65 string reply; 62 string reply;
66 LLSDFetchInventory llsdReply = new LLSDFetchInventory(); 63 LLSDFetchInventory llsdReply = new LLSDFetchInventory();
67 64
65 UUID[] itemIDs = new UUID[itemsRequested.Count];
66 int i = 0;
68 foreach (OSDMap osdItemId in itemsRequested) 67 foreach (OSDMap osdItemId in itemsRequested)
69 { 68 {
70 UUID itemId = osdItemId["item_id"].AsUUID(); 69 itemIDs[i++] = osdItemId["item_id"].AsUUID();
70 }
71
72 InventoryItemBase[] items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs);
71 73
72 InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId)); 74 if (items == null)
75 {
76 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
77 m_log.WarnFormat("[FETCH INVENTORY HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
78 items = new InventoryItemBase[itemsRequested.Count];
79 i = 0;
80 InventoryItemBase item = new InventoryItemBase();
81 item.Owner = m_agentID;
82 foreach (UUID id in itemIDs)
83 {
84 item.ID = id;
85 items[i++] = m_inventoryService.GetItem(item);
86 }
87 }
73 88
89 foreach (InventoryItemBase item in items)
90 {
74 if (item != null) 91 if (item != null)
75 { 92 {
76 // We don't know the agent that this request belongs to so we'll use the agent id of the item 93 // We don't know the agent that this request belongs to so we'll use the agent id of the item
@@ -121,4 +138,4 @@ namespace OpenSim.Capabilities.Handlers
121 return llsdItem; 138 return llsdItem;
122 } 139 }
123 } 140 }
124} 141} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs
new file mode 100644
index 0000000..8af3c64
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs
@@ -0,0 +1,170 @@
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.Collections.Generic;
30using System.Linq;
31using System.Net;
32using System.Text.RegularExpressions;
33using log4net;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Capabilities.Handlers;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43
44namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
45{
46 [TestFixture]
47 public class FetchInventory2HandlerTests : OpenSimTestCase
48 {
49 private UUID m_userID = UUID.Random();
50 private Scene m_scene;
51 private UUID m_rootFolderID;
52 private UUID m_notecardsFolder;
53 private UUID m_objectsFolder;
54
55 private void Init()
56 {
57 // Create an inventory that looks like this:
58 //
59 // /My Inventory
60 // <other system folders>
61 // /Objects
62 // Object 1
63 // Object 2
64 // Object 3
65 // /Notecards
66 // Notecard 1
67 // Notecard 2
68 // Notecard 3
69 // Notecard 4
70 // Notecard 5
71
72 m_scene = new SceneHelpers().SetupScene();
73
74 m_scene.InventoryService.CreateUserInventory(m_userID);
75
76 m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
77
78 InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object);
79 m_objectsFolder = of.ID;
80
81 // Add 3 objects
82 InventoryItemBase item;
83 for (int i = 1; i <= 3; i++)
84 {
85 item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-0000000000b" + i), m_userID);
86 item.AssetID = UUID.Random();
87 item.AssetType = (int)AssetType.Object;
88 item.Folder = m_objectsFolder;
89 item.Name = "Object " + i;
90 m_scene.InventoryService.AddItem(item);
91 }
92
93 InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard);
94 m_notecardsFolder = ncf.ID;
95
96 // Add 5 notecards
97 for (int i = 1; i <= 5; i++)
98 {
99 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-00000000000" + i), m_userID);
100 item.AssetID = UUID.Random();
101 item.AssetType = (int)AssetType.Notecard;
102 item.Folder = m_notecardsFolder;
103 item.Name = "Notecard " + i;
104 m_scene.InventoryService.AddItem(item);
105 }
106
107 }
108
109 [Test]
110 public void Test_001_RequestOne()
111 {
112 TestHelpers.InMethod();
113
114 Init();
115
116 FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID);
117 TestOSHttpRequest req = new TestOSHttpRequest();
118 TestOSHttpResponse resp = new TestOSHttpResponse();
119
120 string request = "<llsd><map><key>items</key><array><map><key>item_id</key><uuid>";
121 request += "10000000-0000-0000-0000-000000000001"; // Notecard 1
122 request += "</uuid></map></array></map></llsd>";
123
124 string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp);
125
126 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
127 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
128 Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
129
130 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain item uuid");
131 Assert.That(llsdresponse.Contains("Notecard 1"), Is.True, "Response does not contain item Name");
132 Console.WriteLine(llsdresponse);
133 }
134
135 [Test]
136 public void Test_002_RequestMany()
137 {
138 TestHelpers.InMethod();
139
140 Init();
141
142 FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID);
143 TestOSHttpRequest req = new TestOSHttpRequest();
144 TestOSHttpResponse resp = new TestOSHttpResponse();
145
146 string request = "<llsd><map><key>items</key><array>";
147 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000001</uuid></map>"; // Notecard 1
148 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000002</uuid></map>"; // Notecard 2
149 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000003</uuid></map>"; // Notecard 3
150 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000004</uuid></map>"; // Notecard 4
151 request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000005</uuid></map>"; // Notecard 5
152 request += "</array></map></llsd>";
153
154 string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp);
155
156 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
157 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
158 Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
159
160 Console.WriteLine(llsdresponse);
161 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain notecard 1");
162 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000002"), Is.True, "Response does not contain notecard 2");
163 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000003"), Is.True, "Response does not contain notecard 3");
164 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000004"), Is.True, "Response does not contain notecard 4");
165 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000005"), Is.True, "Response does not contain notecard 5");
166 }
167
168 }
169
170} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
new file mode 100644
index 0000000..2d5531a
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
@@ -0,0 +1,292 @@
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.Collections.Generic;
30using System.Linq;
31using System.Net;
32using System.Text.RegularExpressions;
33using log4net;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Capabilities.Handlers;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43
44namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
45{
46 [TestFixture]
47 public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase
48 {
49 private UUID m_userID = UUID.Zero;
50 private Scene m_scene;
51 private UUID m_rootFolderID;
52 private int m_rootDescendents;
53 private UUID m_notecardsFolder;
54 private UUID m_objectsFolder;
55
56 private void Init()
57 {
58 // Create an inventory that looks like this:
59 //
60 // /My Inventory
61 // <other system folders>
62 // /Objects
63 // Some Object
64 // /Notecards
65 // Notecard 1
66 // Notecard 2
67 // /Test Folder
68 // Link to notecard -> /Notecards/Notecard 2
69 // Link to Objects folder -> /Objects
70
71 m_scene = new SceneHelpers().SetupScene();
72
73 m_scene.InventoryService.CreateUserInventory(m_userID);
74
75 m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
76
77 InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object);
78 m_objectsFolder = of.ID;
79
80 // Add an object
81 InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID);
82 item.AssetID = UUID.Random();
83 item.AssetType = (int)AssetType.Object;
84 item.Folder = m_objectsFolder;
85 item.Name = "Some Object";
86 m_scene.InventoryService.AddItem(item);
87
88 InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard);
89 m_notecardsFolder = ncf.ID;
90
91 // Add a notecard
92 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID);
93 item.AssetID = UUID.Random();
94 item.AssetType = (int)AssetType.Notecard;
95 item.Folder = m_notecardsFolder;
96 item.Name = "Test Notecard 1";
97 m_scene.InventoryService.AddItem(item);
98 // Add another notecard
99 item.ID = new UUID("20000000-0000-0000-0000-000000000002");
100 item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a");
101 item.Name = "Test Notecard 2";
102 m_scene.InventoryService.AddItem(item);
103
104 // Add a folder
105 InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID);
106 m_scene.InventoryService.AddFolder(folder);
107
108 // Add a link to notecard 2 in Test Folder
109 item.AssetID = item.ID; // use item ID of notecard 2
110 item.ID = new UUID("40000000-0000-0000-0000-000000000004");
111 item.AssetType = (int)AssetType.Link;
112 item.Folder = folder.ID;
113 item.Name = "Link to notecard";
114 m_scene.InventoryService.AddItem(item);
115
116 // Add a link to the Objects folder in Test Folder
117 item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object).ID; // use item ID of Objects folder
118 item.ID = new UUID("50000000-0000-0000-0000-000000000005");
119 item.AssetType = (int)AssetType.LinkFolder;
120 item.Folder = folder.ID;
121 item.Name = "Link to Objects folder";
122 m_scene.InventoryService.AddItem(item);
123
124 InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID);
125 m_rootDescendents = coll.Items.Count + coll.Folders.Count;
126 Console.WriteLine("Number of descendents: " + m_rootDescendents);
127 }
128
129 [Test]
130 public void Test_001_SimpleFolder()
131 {
132 TestHelpers.InMethod();
133
134 Init();
135
136 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
137 TestOSHttpRequest req = new TestOSHttpRequest();
138 TestOSHttpResponse resp = new TestOSHttpResponse();
139
140 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
141 request += m_rootFolderID;
142 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
143
144 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
145
146 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
147 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
148 Assert.That(llsdresponse.Contains("00000000-0000-0000-0000-000000000000"), Is.True, "Response should contain userID");
149
150 string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
151 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents");
152 Console.WriteLine(llsdresponse);
153 }
154
155 [Test]
156 public void Test_002_MultipleFolders()
157 {
158 TestHelpers.InMethod();
159
160 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
161 TestOSHttpRequest req = new TestOSHttpRequest();
162 TestOSHttpResponse resp = new TestOSHttpResponse();
163
164 string request = "<llsd><map><key>folders</key><array>";
165 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
166 request += m_rootFolderID;
167 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
168 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
169 request += m_notecardsFolder;
170 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
171 request += "</array></map></llsd>";
172
173 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
174 Console.WriteLine(llsdresponse);
175
176 string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
177 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder");
178 descendents = "descendents</key><integer>2</integer>";
179 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder");
180
181 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response");
182 Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response");
183 }
184
185 [Test]
186 public void Test_003_Links()
187 {
188 TestHelpers.InMethod();
189
190 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
191 TestOSHttpRequest req = new TestOSHttpRequest();
192 TestOSHttpResponse resp = new TestOSHttpResponse();
193
194 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
195 request += "f0000000-0000-0000-0000-00000000000f";
196 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
197
198 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
199 Console.WriteLine(llsdresponse);
200
201 string descendents = "descendents</key><integer>2</integer>";
202 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder");
203
204 // Make sure that the note card link is included
205 Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing");
206
207 //Make sure the notecard item itself is included
208 Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing");
209
210 // Make sure that the source item is before the link item
211 int pos1 = llsdresponse.IndexOf("Test Notecard 2");
212 int pos2 = llsdresponse.IndexOf("Link to notecard");
213 Assert.Less(pos1, pos2, "Source of link is after link");
214
215 // Make sure the folder link is included
216 Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing");
217
218 // Make sure the objects inside the Objects folder are included
219 // Note: I'm not entirely sure this is needed, but that's what I found in the implementation
220 Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing");
221
222 // Make sure that the source item is before the link item
223 pos1 = llsdresponse.IndexOf("Some Object");
224 pos2 = llsdresponse.IndexOf("Link to Objects folder");
225 Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link");
226 }
227
228 [Test]
229 public void Test_004_DuplicateFolders()
230 {
231 TestHelpers.InMethod();
232
233 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
234 TestOSHttpRequest req = new TestOSHttpRequest();
235 TestOSHttpResponse resp = new TestOSHttpResponse();
236
237 string request = "<llsd><map><key>folders</key><array>";
238 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
239 request += m_rootFolderID;
240 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
241 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
242 request += m_notecardsFolder;
243 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
244 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
245 request += m_rootFolderID;
246 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
247 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
248 request += m_notecardsFolder;
249 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
250 request += "</array></map></llsd>";
251
252 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
253 Console.WriteLine(llsdresponse);
254
255 string root_folder = "<key>folder_id</key><uuid>" + m_rootFolderID + "</uuid>";
256 string notecards_folder = "<key>folder_id</key><uuid>" + m_notecardsFolder + "</uuid>";
257
258 Assert.That(llsdresponse.Contains(root_folder), "Missing root folder");
259 Assert.That(llsdresponse.Contains(notecards_folder), "Missing notecards folder");
260 int count = Regex.Matches(llsdresponse, root_folder).Count;
261 Assert.AreEqual(1, count, "More than 1 root folder in response");
262 count = Regex.Matches(llsdresponse, notecards_folder).Count;
263 Assert.AreEqual(2, count, "More than 1 notecards folder in response"); // Notecards will also be under root, so 2
264 }
265
266 [Test]
267 public void Test_005_FolderZero()
268 {
269 TestHelpers.InMethod();
270
271 Init();
272
273 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
274 TestOSHttpRequest req = new TestOSHttpRequest();
275 TestOSHttpResponse resp = new TestOSHttpResponse();
276
277 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
278 request += UUID.Zero;
279 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
280
281 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
282
283 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
284 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
285 Assert.That(llsdresponse.Contains("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder");
286
287 Console.WriteLine(llsdresponse);
288 }
289
290 }
291
292} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
new file mode 100644
index 0000000..589602d
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
@@ -0,0 +1,120 @@
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.Collections;
30using System.Collections.Generic;
31using System.Collections.Specialized;
32using System.Drawing;
33using System.Drawing.Imaging;
34using System.Reflection;
35using System.IO;
36using System.Web;
37using log4net;
38using Nini.Config;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenMetaverse.Imaging;
42using OpenSim.Framework;
43using OpenSim.Framework.Capabilities;
44using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Services.Interfaces;
48using Caps = OpenSim.Framework.Capabilities.Caps;
49using OSDMap = OpenMetaverse.StructuredData.OSDMap;
50using OSDArray = OpenMetaverse.StructuredData.OSDArray;
51
52namespace OpenSim.Capabilities.Handlers
53{
54 public class GetDisplayNamesHandler : BaseStreamHandler
55 {
56 private static readonly ILog m_log =
57 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 private IUserManagement m_UserManagement;
59
60 public GetDisplayNamesHandler(string path, IUserManagement umService, string name, string description)
61 : base("GET", path, name, description)
62 {
63 m_UserManagement = umService;
64 }
65
66 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
67 {
68 m_log.DebugFormat("[GET_DISPLAY_NAMES]: called {0}", httpRequest.Url.Query);
69
70 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
71 string[] ids = query.GetValues("ids");
72
73
74 if (m_UserManagement == null)
75 {
76 m_log.Error("[GET_DISPLAY_NAMES]: Cannot fetch display names without a user management component");
77 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
78 return new byte[0];
79 }
80
81 OSDMap osdReply = new OSDMap();
82 OSDArray agents = new OSDArray();
83
84 osdReply["agents"] = agents;
85 foreach (string id in ids)
86 {
87 UUID uuid = UUID.Zero;
88 if (UUID.TryParse(id, out uuid))
89 {
90 string name = m_UserManagement.GetUserName(uuid);
91 if (!string.IsNullOrEmpty(name))
92 {
93 string[] parts = name.Split(new char[] {' '});
94 OSDMap osdname = new OSDMap();
95 osdname["display_name_next_update"] = OSD.FromDate(DateTime.MinValue);
96 osdname["display_name_expires"] = OSD.FromDate(DateTime.Now.AddMonths(1));
97 osdname["display_name"] = OSD.FromString(name);
98 osdname["legacy_first_name"] = parts[0];
99 osdname["legacy_last_name"] = parts[1];
100 osdname["username"] = OSD.FromString(name);
101 osdname["id"] = OSD.FromUUID(uuid);
102 osdname["is_display_name_default"] = OSD.FromBoolean(true);
103
104 agents.Add(osdname);
105 }
106 }
107 }
108
109 // Full content request
110 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
111 //httpResponse.ContentLength = ??;
112 httpResponse.ContentType = "application/llsd+xml";
113
114 string reply = OSDParser.SerializeLLSDXmlString(osdReply);
115 return System.Text.Encoding.UTF8.GetBytes(reply);
116
117 }
118
119 }
120} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs
index 5bab52f..d42de56 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs
@@ -35,13 +35,13 @@ using OpenMetaverse;
35 35
36namespace OpenSim.Capabilities.Handlers 36namespace OpenSim.Capabilities.Handlers
37{ 37{
38 public class FetchInventory2ServerConnector : ServiceConnector 38 public class GetDisplayNamesServerConnector : ServiceConnector
39 { 39 {
40 private IInventoryService m_InventoryService; 40 private IUserManagement m_UserManagement;
41 private string m_ConfigName = "CapsService"; 41 private string m_ConfigName = "CapsService";
42 42
43 public FetchInventory2ServerConnector(IConfigSource config, IHttpServer server, string configName) 43 public GetDisplayNamesServerConnector(IConfigSource config, IHttpServer server, string configName) :
44 : base(config, server, configName) 44 base(config, server, configName)
45 { 45 {
46 if (configName != String.Empty) 46 if (configName != String.Empty)
47 m_ConfigName = configName; 47 m_ConfigName = configName;
@@ -50,22 +50,22 @@ namespace OpenSim.Capabilities.Handlers
50 if (serverConfig == null) 50 if (serverConfig == null)
51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); 51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
52 52
53 string invService = serverConfig.GetString("InventoryService", String.Empty); 53 string umService = serverConfig.GetString("AssetService", String.Empty);
54 54
55 if (invService == String.Empty) 55 if (umService == String.Empty)
56 throw new Exception("No InventoryService in config file"); 56 throw new Exception("No AssetService in config file");
57 57
58 Object[] args = new Object[] { config }; 58 Object[] args = new Object[] { config };
59 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); 59 m_UserManagement =
60 ServerUtils.LoadPlugin<IUserManagement>(umService, args);
60 61
61 if (m_InventoryService == null) 62 if (m_UserManagement == null)
62 throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); 63 throw new Exception(String.Format("Failed to load UserManagement from {0}; config is {1}", umService, m_ConfigName));
63 64
64 FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService); 65 string rurl = serverConfig.GetString("GetTextureRedirectURL");
65 IRequestHandler reqHandler 66
66 = new RestStreamHandler( 67 server.AddStreamHandler(
67 "POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null); 68 new GetDisplayNamesHandler("/CAPS/agents/", m_UserManagement, "GetDisplayNames", null));
68 server.AddStreamHandler(reqHandler);
69 } 69 }
70 } 70 }
71} 71} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 720640e..6b67da1 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -25,92 +25,229 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using log4net; 28using log4net;
35using Nini.Config;
36using OpenMetaverse; 29using OpenMetaverse;
37using OpenMetaverse.StructuredData; 30using OpenMetaverse.Imaging;
38using OpenSim.Framework; 31using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer; 32using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces; 33using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps; 34using System;
35using System.Collections.Specialized;
36using System.Drawing;
37using System.Drawing.Imaging;
38using System.IO;
39using System.Reflection;
40using System.Web;
43 41
44namespace OpenSim.Capabilities.Handlers 42namespace OpenSim.Capabilities.Handlers
45{ 43{
46 public class GetMeshHandler 44 public class GetMeshHandler : BaseStreamHandler
47 { 45 {
48// private static readonly ILog m_log = 46 private static readonly ILog m_log =
49// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IAssetService m_assetService; 48 private IAssetService m_assetService;
52 49
53 public GetMeshHandler(IAssetService assService) 50 // TODO: Change this to a config option
51 private string m_RedirectURL = null;
52
53 public GetMeshHandler(string path, IAssetService assService, string name, string description, string redirectURL)
54 : base("GET", path, name, description)
54 { 55 {
55 m_assetService = assService; 56 m_assetService = assService;
57 m_RedirectURL = redirectURL;
58 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
59 m_RedirectURL += "/";
56 } 60 }
57 61
58 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap) 62 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 63 {
60 Hashtable responsedata = new Hashtable(); 64 // Try to parse the texture ID from the request URL
61 responsedata["int_response_code"] = 400; //501; //410; //404; 65 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
62 responsedata["content_type"] = "text/plain"; 66 string textureStr = query.GetOne("mesh_id");
63 responsedata["keepalive"] = false;
64 responsedata["str_response_string"] = "Request wasn't what was expected";
65 67
66 string meshStr = string.Empty; 68 if (m_assetService == null)
67 69 {
68 if (request.ContainsKey("mesh_id")) 70 m_log.Error("[GETMESH]: Cannot fetch mesh " + textureStr + " without an asset service");
69 meshStr = request["mesh_id"].ToString(); 71 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
72 }
70 73
71 UUID meshID = UUID.Zero; 74 UUID meshID;
72 if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID)) 75 if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out meshID))
73 { 76 {
74 if (m_assetService == null) 77 // OK, we have an array with preferred formats, possibly with only one entry
78
79 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
80 AssetBase mesh;
81
82 if (!String.IsNullOrEmpty(m_RedirectURL))
75 { 83 {
76 responsedata["int_response_code"] = 404; //501; //410; //404; 84 // Only try to fetch locally cached meshes. Misses are redirected
77 responsedata["content_type"] = "text/plain"; 85 mesh = m_assetService.GetCached(meshID.ToString());
78 responsedata["keepalive"] = false; 86
79 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh."; 87 if (mesh != null)
80 return responsedata; 88 {
89 if (mesh.Type != (sbyte)AssetType.Mesh)
90 {
91 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
92 }
93 WriteMeshData(httpRequest, httpResponse, mesh);
94 }
95 else
96 {
97 string textureUrl = m_RedirectURL + "?mesh_id="+ meshID.ToString();
98 m_log.Debug("[GETMESH]: Redirecting mesh request to " + textureUrl);
99 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
100 httpResponse.RedirectLocation = textureUrl;
101 return null;
102 }
103 }
104 else // no redirect
105 {
106 // try the cache
107 mesh = m_assetService.GetCached(meshID.ToString());
108
109 if (mesh == null)
110 {
111 // Fetch locally or remotely. Misses return a 404
112 mesh = m_assetService.Get(meshID.ToString());
113
114 if (mesh != null)
115 {
116 if (mesh.Type != (sbyte)AssetType.Mesh)
117 {
118 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
119 return null;
120 }
121 WriteMeshData(httpRequest, httpResponse, mesh);
122 return null;
123 }
124 }
125 else // it was on the cache
126 {
127 if (mesh.Type != (sbyte)AssetType.Mesh)
128 {
129 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
130 return null;
131 }
132 WriteMeshData(httpRequest, httpResponse, mesh);
133 return null;
134 }
81 } 135 }
82 136
83 AssetBase mesh = m_assetService.Get(meshID.ToString()); 137 // not found
138 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
139 return null;
140 }
141 else
142 {
143 m_log.Warn("[GETTEXTURE]: Failed to parse a mesh_id from GetMesh request: " + httpRequest.Url);
144 }
145
146 return null;
147 }
148
149 private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
150 {
151 string range = request.Headers.GetOne("Range");
84 152
85 if (mesh != null) 153 if (!String.IsNullOrEmpty(range))
154 {
155 // Range request
156 int start, end;
157 if (TryParseRange(range, out start, out end))
86 { 158 {
87 if (mesh.Type == (SByte)AssetType.Mesh) 159 // Before clamping start make sure we can satisfy it in order to avoid
160 // sending back the last byte instead of an error status
161 if (start >= texture.Data.Length)
88 { 162 {
89 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); 163 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
90 responsedata["content_type"] = "application/vnd.ll.mesh"; 164 response.ContentType = texture.Metadata.ContentType;
91 responsedata["int_response_code"] = 200;
92 } 165 }
93 // Optionally add additional mesh types here
94 else 166 else
95 { 167 {
96 responsedata["int_response_code"] = 404; //501; //410; //404; 168 // Handle the case where no second range value was given. This is equivalent to requesting
97 responsedata["content_type"] = "text/plain"; 169 // the rest of the entity.
98 responsedata["keepalive"] = false; 170 if (end == -1)
99 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh."; 171 end = int.MaxValue;
100 return responsedata; 172
173 end = Utils.Clamp(end, 0, texture.Data.Length - 1);
174 start = Utils.Clamp(start, 0, end);
175 int len = end - start + 1;
176
177 if (0 == start && len == texture.Data.Length)
178 {
179 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
180 }
181 else
182 {
183 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
184 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
185 }
186
187 response.ContentLength = len;
188 response.ContentType = "application/vnd.ll.mesh";
189
190 response.Body.Write(texture.Data, start, len);
101 } 191 }
102 } 192 }
103 else 193 else
104 { 194 {
105 responsedata["int_response_code"] = 404; //501; //410; //404; 195 m_log.Warn("[GETMESH]: Malformed Range header: " + range);
106 responsedata["content_type"] = "text/plain"; 196 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
107 responsedata["keepalive"] = false; 197 }
108 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!"; 198 }
109 return responsedata; 199 else
200 {
201 // Full content request
202 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
203 response.ContentLength = texture.Data.Length;
204 response.ContentType = "application/vnd.ll.mesh";
205 response.Body.Write(texture.Data, 0, texture.Data.Length);
206 }
207 }
208
209 /// <summary>
210 /// Parse a range header.
211 /// </summary>
212 /// <remarks>
213 /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
214 /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
215 /// Where there is no value, -1 is returned.
216 /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
217 /// for start.</remarks>
218 /// <returns></returns>
219 /// <param name='header'></param>
220 /// <param name='start'>Start of the range. Undefined if this was not a number.</param>
221 /// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
222 private bool TryParseRange(string header, out int start, out int end)
223 {
224 start = end = 0;
225
226 if (header.StartsWith("bytes="))
227 {
228 string[] rangeValues = header.Substring(6).Split('-');
229
230 if (rangeValues.Length == 2)
231 {
232 if (!Int32.TryParse(rangeValues[0], out start))
233 return false;
234
235 string rawEnd = rangeValues[1];
236
237 if (rawEnd == "")
238 {
239 end = -1;
240 return true;
241 }
242 else if (Int32.TryParse(rawEnd, out end))
243 {
244 return true;
245 }
110 } 246 }
111 } 247 }
112 248
113 return responsedata; 249 start = end = 0;
250 return false;
114 } 251 }
115 } 252 }
116} \ No newline at end of file 253} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
index 8a275f3..19de3cf 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
@@ -25,16 +25,13 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using Nini.Config; 28using Nini.Config;
31using OpenSim.Server.Base; 29using OpenMetaverse;
32using OpenSim.Services.Interfaces;
33using OpenSim.Framework.Servers.HttpServer; 30using OpenSim.Framework.Servers.HttpServer;
31using OpenSim.Server.Base;
34using OpenSim.Server.Handlers.Base; 32using OpenSim.Server.Handlers.Base;
35using OpenSim.Framework.Servers; 33using OpenSim.Services.Interfaces;
36 34using System;
37using OpenMetaverse;
38 35
39namespace OpenSim.Capabilities.Handlers 36namespace OpenSim.Capabilities.Handlers
40{ 37{
@@ -65,15 +62,15 @@ namespace OpenSim.Capabilities.Handlers
65 if (m_AssetService == null) 62 if (m_AssetService == null)
66 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
67 64
68 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); 65 string rurl = serverConfig.GetString("GetMeshRedirectURL");
69 IRequestHandler reqHandler 66
70 = new RestHTTPHandler( 67 server.AddStreamHandler(
71 "GET", 68 new GetTextureHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null, rurl));
72 "/CAPS/" + UUID.Random(), 69
73 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), 70 rurl = serverConfig.GetString("GetMesh2RedirectURL");
74 "GetMesh", 71
75 null); 72 server.AddStreamHandler(
76 server.AddStreamHandler(reqHandler); 73 new GetTextureHandler("/CAPS/GetMesh2/" /*+ UUID.Random() */, m_AssetService, "GetMesh2", null, rurl));
77 } 74 }
78 } 75 }
79} \ No newline at end of file 76} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index b497fde..828e943 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -56,15 +56,18 @@ namespace OpenSim.Capabilities.Handlers
56 public const string DefaultFormat = "x-j2c"; 56 public const string DefaultFormat = "x-j2c";
57 57
58 // TODO: Change this to a config option 58 // TODO: Change this to a config option
59 const string REDIRECT_URL = null; 59 private string m_RedirectURL = null;
60 60
61 public GetTextureHandler(string path, IAssetService assService, string name, string description) 61 public GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL)
62 : base("GET", path, name, description) 62 : base("GET", path, name, description)
63 { 63 {
64 m_assetService = assService; 64 m_assetService = assService;
65 m_RedirectURL = redirectURL;
66 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
67 m_RedirectURL += "/";
65 } 68 }
66 69
67 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 70 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
68 { 71 {
69 // Try to parse the texture ID from the request URL 72 // Try to parse the texture ID from the request URL
70 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 73 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
@@ -85,7 +88,7 @@ namespace OpenSim.Capabilities.Handlers
85// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID); 88// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
86 89
87 string[] formats; 90 string[] formats;
88 if (format != null && format != string.Empty) 91 if (!string.IsNullOrEmpty(format))
89 { 92 {
90 formats = new string[1] { format.ToLower() }; 93 formats = new string[1] { format.ToLower() };
91 } 94 }
@@ -134,7 +137,7 @@ namespace OpenSim.Capabilities.Handlers
134 if (format != DefaultFormat) 137 if (format != DefaultFormat)
135 fullID = fullID + "-" + format; 138 fullID = fullID + "-" + format;
136 139
137 if (!String.IsNullOrEmpty(REDIRECT_URL)) 140 if (!String.IsNullOrEmpty(m_RedirectURL))
138 { 141 {
139 // Only try to fetch locally cached textures. Misses are redirected 142 // Only try to fetch locally cached textures. Misses are redirected
140 texture = m_assetService.GetCached(fullID); 143 texture = m_assetService.GetCached(fullID);
@@ -150,8 +153,9 @@ namespace OpenSim.Capabilities.Handlers
150 } 153 }
151 else 154 else
152 { 155 {
153 string textureUrl = REDIRECT_URL + textureID.ToString(); 156 string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
154 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); 157 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
158 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
155 httpResponse.RedirectLocation = textureUrl; 159 httpResponse.RedirectLocation = textureUrl;
156 return true; 160 return true;
157 } 161 }
@@ -189,6 +193,7 @@ namespace OpenSim.Capabilities.Handlers
189 193
190 newTexture.Flags = AssetFlags.Collectable; 194 newTexture.Flags = AssetFlags.Collectable;
191 newTexture.Temporary = true; 195 newTexture.Temporary = true;
196 newTexture.Local = true;
192 m_assetService.Store(newTexture); 197 m_assetService.Store(newTexture);
193 WriteTextureData(httpRequest, httpResponse, newTexture, format); 198 WriteTextureData(httpRequest, httpResponse, newTexture, format);
194 return true; 199 return true;
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
index 71cf033..fa0b228 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
@@ -62,8 +62,10 @@ namespace OpenSim.Capabilities.Handlers
62 if (m_AssetService == null) 62 if (m_AssetService == null)
63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
64 64
65 string rurl = serverConfig.GetString("GetTextureRedirectURL");
66 ;
65 server.AddStreamHandler( 67 server.AddStreamHandler(
66 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null)); 68 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl));
67 } 69 }
68 } 70 }
69} \ No newline at end of file 71} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
index d4d6d10..e5d9618 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
@@ -37,7 +37,6 @@ using OpenSim.Framework;
37using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Tests.Common; 39using OpenSim.Tests.Common;
40using OpenSim.Tests.Common.Mock;
41 40
42namespace OpenSim.Capabilities.Handlers.GetTexture.Tests 41namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
43{ 42{
@@ -52,7 +51,7 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
52 // Overkill - we only really need the asset service, not a whole scene. 51 // Overkill - we only really need the asset service, not a whole scene.
53 Scene scene = new SceneHelpers().SetupScene(); 52 Scene scene = new SceneHelpers().SetupScene();
54 53
55 GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService, "TestGetTexture", null); 54 GetTextureHandler handler = new GetTextureHandler("/gettexture", scene.AssetService, "TestGetTexture", null, null);
56 TestOSHttpRequest req = new TestOSHttpRequest(); 55 TestOSHttpRequest req = new TestOSHttpRequest();
57 TestOSHttpResponse resp = new TestOSHttpResponse(); 56 TestOSHttpResponse resp = new TestOSHttpResponse();
58 req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012"); 57 req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012");
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
index a681fb6..1a6d04f 100644
--- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.8.3.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs
new file mode 100644
index 0000000..10ea8ee
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs
@@ -0,0 +1,76 @@
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 Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse;
35
36namespace OpenSim.Capabilities.Handlers
37{
38 public class UploadBakedTextureServerConnector : ServiceConnector
39 {
40 private IAssetService m_AssetService;
41 private string m_ConfigName = "CapsService";
42
43 public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
44 base(config, server, configName)
45 {
46 if (configName != String.Empty)
47 m_ConfigName = configName;
48
49 IConfig serverConfig = config.Configs[m_ConfigName];
50 if (serverConfig == null)
51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
52
53 string assetService = serverConfig.GetString("AssetService", String.Empty);
54
55 if (assetService == String.Empty)
56 throw new Exception("No AssetService in config file");
57
58 Object[] args = new Object[] { config };
59 m_AssetService =
60 ServerUtils.LoadPlugin<IAssetService>(assetService, args);
61
62 if (m_AssetService == null)
63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
64
65 // NEED TO FIX THIS
66 OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, "");
67 server.AddStreamHandler(new RestStreamHandler(
68 "POST",
69 "/CAPS/UploadBakedTexture/",
70 new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture,
71 "UploadBakedTexture",
72 "Upload Baked Texture Capability"));
73
74 }
75 }
76} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
deleted file mode 100644
index 9a6ca86..0000000
--- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
+++ /dev/null
@@ -1,438 +0,0 @@
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.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42
43namespace OpenSim.Capabilities.Handlers
44{
45 public class WebFetchInvDescHandler
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private IInventoryService m_InventoryService;
51 private ILibraryService m_LibraryService;
52// private object m_fetchLock = new Object();
53
54 public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)
55 {
56 m_InventoryService = invService;
57 m_LibraryService = libService;
58 }
59
60 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 {
62// lock (m_fetchLock)
63// {
64// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);
65
66 // nasty temporary hack here, the linden client falsely
67 // identifies the uuid 00000000-0000-0000-0000-000000000000
68 // as a string which breaks us
69 //
70 // correctly mark it as a uuid
71 //
72 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
73
74 // another hack <integer>1</integer> results in a
75 // System.ArgumentException: Object type System.Int32 cannot
76 // be converted to target type: System.Boolean
77 //
78 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
79 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
80
81 Hashtable hash = new Hashtable();
82 try
83 {
84 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
85 }
86 catch (LLSD.LLSDParseException e)
87 {
88 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
89 m_log.Error("Request: " + request);
90 }
91
92 ArrayList foldersrequested = (ArrayList)hash["folders"];
93
94 string response = "";
95
96 for (int i = 0; i < foldersrequested.Count; i++)
97 {
98 string inventoryitemstr = "";
99 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
100
101 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
102
103 try
104 {
105 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
106 }
107 catch (Exception e)
108 {
109 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
110 }
111 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
112
113 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
114 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
115 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
116
117 response += inventoryitemstr;
118 }
119
120 if (response.Length == 0)
121 {
122 // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
123 // Therefore, I'm concluding that the client only has so many threads available to do requests
124 // and when a thread stalls.. is stays stalled.
125 // Therefore we need to return something valid
126 response = "<llsd><map><key>folders</key><array /></map></llsd>";
127 }
128 else
129 {
130 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
131 }
132
133// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
134 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
135
136 return response;
137
138// }
139 }
140
141 /// <summary>
142 /// Construct an LLSD reply packet to a CAPS inventory request
143 /// </summary>
144 /// <param name="invFetch"></param>
145 /// <returns></returns>
146 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
147 {
148 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
149 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
150 contents.agent_id = invFetch.owner_id;
151 contents.owner_id = invFetch.owner_id;
152 contents.folder_id = invFetch.folder_id;
153
154 reply.folders.Array.Add(contents);
155 InventoryCollection inv = new InventoryCollection();
156 inv.Folders = new List<InventoryFolderBase>();
157 inv.Items = new List<InventoryItemBase>();
158 int version = 0;
159 int descendents = 0;
160
161 inv
162 = Fetch(
163 invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
164 invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
165
166 if (inv != null && inv.Folders != null)
167 {
168 foreach (InventoryFolderBase invFolder in inv.Folders)
169 {
170 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
171 }
172
173 descendents += inv.Folders.Count;
174 }
175
176 if (inv != null && inv.Items != null)
177 {
178 foreach (InventoryItemBase invItem in inv.Items)
179 {
180 contents.items.Array.Add(ConvertInventoryItem(invItem));
181 }
182 }
183
184 contents.descendents = descendents;
185 contents.version = version;
186
187// m_log.DebugFormat(
188// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
189// invFetch.folder_id,
190// invFetch.fetch_items,
191// invFetch.fetch_folders,
192// contents.items.Array.Count,
193// contents.categories.Array.Count,
194// invFetch.owner_id);
195
196 return reply;
197 }
198
199 /// <summary>
200 /// Handle the caps inventory descendents fetch.
201 /// </summary>
202 /// <param name="agentID"></param>
203 /// <param name="folderID"></param>
204 /// <param name="ownerID"></param>
205 /// <param name="fetchFolders"></param>
206 /// <param name="fetchItems"></param>
207 /// <param name="sortOrder"></param>
208 /// <param name="version"></param>
209 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
210 private InventoryCollection Fetch(
211 UUID agentID, UUID folderID, UUID ownerID,
212 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
213 {
214// m_log.DebugFormat(
215// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
216// fetchFolders, fetchItems, folderID, agentID);
217
218 // FIXME MAYBE: We're not handling sortOrder!
219
220 version = 0;
221 descendents = 0;
222
223 InventoryFolderImpl fold;
224 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
225 {
226 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
227 {
228 InventoryCollection ret = new InventoryCollection();
229 ret.Folders = new List<InventoryFolderBase>();
230 ret.Items = fold.RequestListOfItems();
231 descendents = ret.Folders.Count + ret.Items.Count;
232
233 return ret;
234 }
235 }
236
237 InventoryCollection contents = new InventoryCollection();
238
239 if (folderID != UUID.Zero)
240 {
241 contents = m_InventoryService.GetFolderContent(agentID, folderID);
242 InventoryFolderBase containingFolder = new InventoryFolderBase();
243 containingFolder.ID = folderID;
244 containingFolder.Owner = agentID;
245 containingFolder = m_InventoryService.GetFolder(containingFolder);
246
247 if (containingFolder != null)
248 {
249// m_log.DebugFormat(
250// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
251// containingFolder.Name, containingFolder.ID, agentID);
252
253 version = containingFolder.Version;
254
255 if (fetchItems)
256 {
257 List<InventoryItemBase> itemsToReturn = contents.Items;
258 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
259
260 // descendents must only include the links, not the linked items we add
261 descendents = originalItems.Count;
262
263 // Add target items for links in this folder before the links themselves.
264 foreach (InventoryItemBase item in originalItems)
265 {
266 if (item.AssetType == (int)AssetType.Link)
267 {
268 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
269
270 // Take care of genuinely broken links where the target doesn't exist
271 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
272 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
273 // rather than having to keep track of every folder requested in the recursion.
274 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
275 itemsToReturn.Insert(0, linkedItem);
276 }
277 }
278
279 // Now scan for folder links and insert the items they target and those links at the head of the return data
280 foreach (InventoryItemBase item in originalItems)
281 {
282 if (item.AssetType == (int)AssetType.LinkFolder)
283 {
284 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
285 List<InventoryItemBase> links = linkedFolderContents.Items;
286
287 itemsToReturn.InsertRange(0, links);
288
289 foreach (InventoryItemBase link in linkedFolderContents.Items)
290 {
291 // Take care of genuinely broken links where the target doesn't exist
292 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
293 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
294 // rather than having to keep track of every folder requested in the recursion.
295 if (link != null)
296 {
297// m_log.DebugFormat(
298// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
299// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
300
301 InventoryItemBase linkedItem
302 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
303
304 if (linkedItem != null)
305 itemsToReturn.Insert(0, linkedItem);
306 }
307 }
308 }
309 }
310 }
311
312// foreach (InventoryItemBase item in contents.Items)
313// {
314// m_log.DebugFormat(
315// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
316// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
317// }
318
319 // =====
320
321//
322// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
323// {
324// m_log.DebugFormat(
325// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
326// linkedItem.Name, folderID, agentID);
327//
328// contents.Items.Add(linkedItem);
329// }
330//
331// // If the folder requested contains links, then we need to send those folders first, otherwise the links
332// // will be broken in the viewer.
333// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
334// foreach (InventoryItemBase item in contents.Items)
335// {
336// if (item.AssetType == (int)AssetType.Link)
337// {
338// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
339//
340// // Take care of genuinely broken links where the target doesn't exist
341// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
342// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
343// // rather than having to keep track of every folder requested in the recursion.
344// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
345// {
346// // We don't need to send the folder if source and destination of the link are in the same
347// // folder.
348// if (linkedItem.Folder != containingFolder.ID)
349// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
350// }
351// }
352// }
353//
354// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
355// {
356// m_log.DebugFormat(
357// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
358// linkedItemFolderId, folderID, agentID);
359//
360// int dummyVersion;
361// InventoryCollection linkedCollection
362// = Fetch(
363// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
364//
365// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
366// linkedFolder.Owner = agentID;
367// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
368//
369//// contents.Folders.AddRange(linkedCollection.Folders);
370//
371// contents.Folders.Add(linkedFolder);
372// contents.Items.AddRange(linkedCollection.Items);
373// }
374// }
375 }
376 }
377 else
378 {
379 // Lost items don't really need a version
380 version = 1;
381 }
382
383 return contents;
384
385 }
386 /// <summary>
387 /// Convert an internal inventory folder object into an LLSD object.
388 /// </summary>
389 /// <param name="invFolder"></param>
390 /// <returns></returns>
391 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
392 {
393 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
394 llsdFolder.folder_id = invFolder.ID;
395 llsdFolder.parent_id = invFolder.ParentID;
396 llsdFolder.name = invFolder.Name;
397 llsdFolder.type = invFolder.Type;
398 llsdFolder.preferred_type = -1;
399
400 return llsdFolder;
401 }
402
403 /// <summary>
404 /// Convert an internal inventory item object into an LLSD object.
405 /// </summary>
406 /// <param name="invItem"></param>
407 /// <returns></returns>
408 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
409 {
410 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
411 llsdItem.asset_id = invItem.AssetID;
412 llsdItem.created_at = invItem.CreationDate;
413 llsdItem.desc = invItem.Description;
414 llsdItem.flags = (int)invItem.Flags;
415 llsdItem.item_id = invItem.ID;
416 llsdItem.name = invItem.Name;
417 llsdItem.parent_id = invItem.Folder;
418 llsdItem.type = invItem.AssetType;
419 llsdItem.inv_type = invItem.InvType;
420
421 llsdItem.permissions = new LLSDPermissions();
422 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
423 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
424 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
425 llsdItem.permissions.group_id = invItem.GroupID;
426 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
427 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
428 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
429 llsdItem.permissions.owner_id = invItem.Owner;
430 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
431 llsdItem.sale_info = new LLSDSaleInfo();
432 llsdItem.sale_info.sale_price = invItem.SalePrice;
433 llsdItem.sale_info.sale_type = invItem.SaleType;
434
435 return llsdItem;
436 }
437 }
438} \ No newline at end of file
diff --git a/OpenSim/Capabilities/LLSD.cs b/OpenSim/Capabilities/LLSD.cs
index eec9e61..c59cede 100644
--- a/OpenSim/Capabilities/LLSD.cs
+++ b/OpenSim/Capabilities/LLSD.cs
@@ -68,7 +68,10 @@ namespace OpenSim.Framework.Capabilities
68 /// <returns></returns> 68 /// <returns></returns>
69 public static object LLSDDeserialize(byte[] b) 69 public static object LLSDDeserialize(byte[] b)
70 { 70 {
71 return LLSDDeserialize(new MemoryStream(b, false)); 71 using (MemoryStream ms = new MemoryStream(b, false))
72 {
73 return LLSDDeserialize(ms);
74 }
72 } 75 }
73 76
74 /// <summary> 77 /// <summary>
@@ -78,21 +81,23 @@ namespace OpenSim.Framework.Capabilities
78 /// <returns></returns> 81 /// <returns></returns>
79 public static object LLSDDeserialize(Stream st) 82 public static object LLSDDeserialize(Stream st)
80 { 83 {
81 XmlTextReader reader = new XmlTextReader(st); 84 using (XmlTextReader reader = new XmlTextReader(st))
82 reader.Read(); 85 {
83 SkipWS(reader); 86 reader.Read();
87 SkipWS(reader);
84 88
85 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd") 89 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd")
86 throw new LLSDParseException("Expected <llsd>"); 90 throw new LLSDParseException("Expected <llsd>");
87 91
88 reader.Read(); 92 reader.Read();
89 object ret = LLSDParseOne(reader); 93 object ret = LLSDParseOne(reader);
90 SkipWS(reader); 94 SkipWS(reader);
91 95
92 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd") 96 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd")
93 throw new LLSDParseException("Expected </llsd>"); 97 throw new LLSDParseException("Expected </llsd>");
94 98
95 return ret; 99 return ret;
100 }
96 } 101 }
97 102
98 /// <summary> 103 /// <summary>
diff --git a/OpenSim/Capabilities/LLSDAvatarPicker.cs b/OpenSim/Capabilities/LLSDAvatarPicker.cs
new file mode 100644
index 0000000..d0b3f3a
--- /dev/null
+++ b/OpenSim/Capabilities/LLSDAvatarPicker.cs
@@ -0,0 +1,51 @@
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 OpenMetaverse;
29
30namespace OpenSim.Framework.Capabilities
31{
32 [OSDMap]
33 public class LLSDAvatarPicker
34 {
35 public string next_page_url;
36 // an array of LLSDPerson
37 public OSDArray agents = new OSDArray();
38 }
39
40 [OSDMap]
41 public class LLSDPerson
42 {
43 public string username;
44 public string display_name;
45 //'display_name_next_update':d"1970-01-01T00:00:00Z"
46 public string legacy_first_name;
47 public string legacy_last_name;
48 public UUID id;
49 public bool is_display_name_default;
50 }
51} \ No newline at end of file
diff --git a/OpenSim/Capabilities/LLSDStreamHandler.cs b/OpenSim/Capabilities/LLSDStreamHandler.cs
index 5df24b2..4fa1153 100644
--- a/OpenSim/Capabilities/LLSDStreamHandler.cs
+++ b/OpenSim/Capabilities/LLSDStreamHandler.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Capabilities
48 m_method = method; 48 m_method = method;
49 } 49 }
50 50
51 public override byte[] Handle(string path, Stream request, 51 protected override byte[] ProcessRequest(string path, Stream request,
52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
53 { 53 {
54 //Encoding encoding = Util.UTF8; 54 //Encoding encoding = Util.UTF8;
diff --git a/OpenSim/Capabilities/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Properties/AssemblyInfo.cs
index 26254f2..f8a9dae 100644
--- a/OpenSim/Capabilities/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]