diff options
Moved some files around, so that it's easier to share code between standalone and the grid services. Should not affect any functionality.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Communications/Services/HGInventoryService.cs (renamed from OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs) | 1443 |
1 files changed, 636 insertions, 807 deletions
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs b/OpenSim/Framework/Communications/Services/HGInventoryService.cs index e619f13..f0b2259 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs +++ b/OpenSim/Framework/Communications/Services/HGInventoryService.cs | |||
@@ -1,807 +1,636 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (c) 2008, Contributors. All rights reserved. | 2 | * Copyright (c) 2008, Contributors. All rights reserved. |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without modification, | 5 | * Redistribution and use in source and binary forms, with or without modification, |
6 | * are permitted provided that the following conditions are met: | 6 | * are permitted provided that the following conditions are met: |
7 | * | 7 | * |
8 | * * Redistributions of source code must retain the above copyright notice, | 8 | * * Redistributions of source code must retain the above copyright notice, |
9 | * this list of conditions and the following disclaimer. | 9 | * this list of conditions and the following disclaimer. |
10 | * * Redistributions in binary form must reproduce the above copyright notice, | 10 | * * Redistributions in binary form must reproduce the above copyright notice, |
11 | * this list of conditions and the following disclaimer in the documentation | 11 | * this list of conditions and the following disclaimer in the documentation |
12 | * and/or other materials provided with the distribution. | 12 | * and/or other materials provided with the distribution. |
13 | * * Neither the name of the Organizations nor the names of Individual | 13 | * * Neither the name of the Organizations nor the names of Individual |
14 | * Contributors may be used to endorse or promote products derived from | 14 | * Contributors may be used to endorse or promote products derived from |
15 | * this software without specific prior written permission. | 15 | * this software without specific prior written permission. |
16 | * | 16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
20 | * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 20 | * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
24 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 24 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
25 | * OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | using System; | 29 | using System; |
30 | using System.Collections; | 30 | using System.Collections; |
31 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using log4net; | 33 | using log4net; |
34 | using Nini.Config; | 34 | using Nini.Config; |
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenSim.Data; | 36 | using OpenSim.Data; |
37 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Communications; | 38 | //using OpenSim.Framework.Communications; |
39 | using OpenSim.Framework.Communications.Cache; | 39 | using OpenSim.Framework.Communications.Cache; |
40 | using Caps = OpenSim.Framework.Communications.Capabilities.Caps; | 40 | using Caps = OpenSim.Framework.Communications.Capabilities.Caps; |
41 | using LLSDHelpers = OpenSim.Framework.Communications.Capabilities.LLSDHelpers; | 41 | using LLSDHelpers = OpenSim.Framework.Communications.Capabilities.LLSDHelpers; |
42 | using OpenSim.Framework.Servers; | 42 | using OpenSim.Framework.Servers; |
43 | using OpenSim.Framework.Servers.Interfaces; | 43 | using OpenSim.Framework.Servers.Interfaces; |
44 | using OpenSim.Region.Framework.Interfaces; | 44 | |
45 | using OpenSim.Region.Framework.Scenes; | 45 | using OpenMetaverse.StructuredData; |
46 | using OpenSim.Region.CoreModules.Communications.REST; | 46 | |
47 | 47 | namespace OpenSim.Framework.Communications.Services | |
48 | using OpenMetaverse.StructuredData; | 48 | { |
49 | 49 | public class HGInventoryService | |
50 | namespace OpenSim.Region.CoreModules.Hypergrid | 50 | { |
51 | { | 51 | private static readonly ILog m_log |
52 | public class HGStandaloneInventoryService : IRegionModule | 52 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
53 | { | 53 | |
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private InventoryServiceBase m_inventoryService; |
55 | private static bool initialized = false; | 55 | private UserManagerBase m_userService; |
56 | private static bool enabled = false; | 56 | IAssetDataPlugin m_assetProvider; |
57 | 57 | IHttpServer httpServer; | |
58 | Scene m_scene; | 58 | private string m_thisInventoryUrl = "http://localhost:9000"; |
59 | //InventoryService m_inventoryService; | 59 | private string m_thisHostname = "127.0.0.1"; |
60 | 60 | private uint m_thisPort = 9000; | |
61 | #region IRegionModule interface | 61 | |
62 | 62 | ||
63 | public void Initialise(Scene scene, IConfigSource config) | 63 | public HGInventoryService(InventoryServiceBase invService, IAssetDataPlugin assetService, UserManagerBase userService, IHttpServer httpserver, string url) |
64 | { | 64 | { |
65 | if (!initialized) | 65 | m_inventoryService = invService; |
66 | { | 66 | m_userService = userService; |
67 | initialized = true; | 67 | m_thisInventoryUrl = url; |
68 | m_scene = scene; | 68 | if (!m_thisInventoryUrl.EndsWith("/")) |
69 | 69 | m_thisInventoryUrl += "/"; | |
70 | // This module is only on for standalones | 70 | |
71 | enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false); | 71 | Uri uri = new Uri(m_thisInventoryUrl); |
72 | } | 72 | if (uri != null) |
73 | } | 73 | { |
74 | 74 | m_thisHostname = uri.Host; | |
75 | public void PostInitialise() | 75 | m_thisPort = (uint)uri.Port; |
76 | { | 76 | } |
77 | if (enabled) | 77 | |
78 | { | 78 | m_assetProvider = assetService; |
79 | m_log.Info("[HGStandaloneInvService]: Starting..."); | 79 | httpServer = httpserver; |
80 | //m_inventoryService = new InventoryService(m_scene); | 80 | |
81 | new InventoryService(m_scene); | 81 | AddHttpHandlers(); |
82 | } | 82 | } |
83 | } | 83 | |
84 | 84 | public virtual void AddHttpHandlers() | |
85 | public void Close() | 85 | { |
86 | { | 86 | httpServer.AddHTTPHandler("/InvCap/", CapHandler); |
87 | } | 87 | } |
88 | 88 | ||
89 | public string Name | 89 | public bool CheckAuthSession(string session_id, string avatar_id) |
90 | { | 90 | { |
91 | get { return "HGStandaloneInventoryService"; } | 91 | return true; |
92 | } | 92 | } |
93 | 93 | ||
94 | public bool IsSharedModule | 94 | |
95 | { | 95 | // In truth, this is not called from the outside, for standalones. I'm just making it |
96 | get { return true; } | 96 | // a handler already so that this can be reused for the InventoryServer. |
97 | } | 97 | public string CreateCapUrl(Guid _userid) |
98 | 98 | { | |
99 | #endregion | 99 | UUID userID = new UUID(_userid); |
100 | } | 100 | UUID random = UUID.Random(); |
101 | 101 | string url = m_thisInventoryUrl + random.ToString() + "/"; | |
102 | public class InventoryService | 102 | m_log.InfoFormat("[HGStandaloneInvService] Creating Cap URL {0} for user {1}", url, userID.ToString()); |
103 | { | 103 | return url; |
104 | private static readonly ILog m_log | 104 | } |
105 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 105 | |
106 | 106 | /// <summary> | |
107 | private InventoryServiceBase m_inventoryService; | 107 | /// Return a user's entire inventory |
108 | private UserManagerBase m_userService; | 108 | /// </summary> |
109 | IAssetDataPlugin m_assetProvider; | 109 | /// <param name="rawUserID"></param> |
110 | private Scene m_scene; | 110 | /// <returns>The user's inventory. If an inventory cannot be found then an empty collection is returned.</returns> |
111 | private bool m_doLookup = false; | 111 | public InventoryCollection GetUserInventory(Guid rawUserID) |
112 | private string m_thisInventoryUrl = "http://localhost:9000"; | 112 | { |
113 | private string m_thisHostname = "127.0.0.1"; | 113 | UUID userID = new UUID(rawUserID); |
114 | private uint m_thisPort = 9000; | 114 | |
115 | 115 | m_log.Info("[HGStandaloneInvModule]: Processing request for inventory of " + userID); | |
116 | public bool DoLookup | 116 | |
117 | { | 117 | // Uncomment me to simulate a slow responding inventory server |
118 | get { return m_doLookup; } | 118 | //Thread.Sleep(16000); |
119 | set { m_doLookup = value; } | 119 | |
120 | } | 120 | InventoryCollection invCollection = new InventoryCollection(); |
121 | 121 | ||
122 | public InventoryService(Scene _m_scene) | 122 | List<InventoryFolderBase> allFolders = m_inventoryService.GetInventorySkeleton(userID); |
123 | { | 123 | |
124 | m_scene = _m_scene; | 124 | if (null == allFolders) |
125 | m_inventoryService = (InventoryServiceBase)m_scene.CommsManager.SecureInventoryService; | 125 | { |
126 | m_userService = (UserManagerBase)m_scene.CommsManager.UserService; | 126 | m_log.WarnFormat("[HGStandaloneInvModule]: No inventory found for user {0}", rawUserID); |
127 | m_thisInventoryUrl = m_scene.CommsManager.NetworkServersInfo.InventoryURL; | 127 | |
128 | if (!m_thisInventoryUrl.EndsWith("/")) | 128 | return invCollection; |
129 | m_thisInventoryUrl += "/"; | 129 | } |
130 | 130 | ||
131 | Uri uri = new Uri(m_thisInventoryUrl); | 131 | List<InventoryItemBase> allItems = new List<InventoryItemBase>(); |
132 | if (uri != null) | 132 | |
133 | { | 133 | foreach (InventoryFolderBase folder in allFolders) |
134 | m_thisHostname = uri.Host; | 134 | { |
135 | m_thisPort = (uint)uri.Port; | 135 | List<InventoryItemBase> items = m_inventoryService.RequestFolderItems(folder.ID); |
136 | } | 136 | |
137 | 137 | if (items != null) | |
138 | m_assetProvider = ((AssetServerBase)m_scene.CommsManager.AssetCache.AssetServer).AssetProviderPlugin; | 138 | { |
139 | 139 | allItems.InsertRange(0, items); | |
140 | AddHttpHandlers(); | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | protected void AddHttpHandlers() | 143 | invCollection.UserID = userID; |
144 | { | 144 | invCollection.Folders = allFolders; |
145 | IHttpServer httpServer = m_scene.CommsManager.HttpServer; | 145 | invCollection.Items = allItems; |
146 | 146 | ||
147 | httpServer.AddHTTPHandler("/InvCap/", CapHandler); | 147 | // foreach (InventoryFolderBase folder in invCollection.Folders) |
148 | 148 | // { | |
149 | httpServer.AddStreamHandler( | 149 | // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back folder {0} {1}", folder.Name, folder.ID); |
150 | new RestDeserialiseSecureHandler<Guid, InventoryCollection>( | 150 | // } |
151 | "POST", "/GetInventory/", GetUserInventory, CheckAuthSession)); | 151 | // |
152 | 152 | // foreach (InventoryItemBase item in invCollection.Items) | |
153 | httpServer.AddStreamHandler( | 153 | // { |
154 | new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | 154 | // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder); |
155 | "POST", "/NewFolder/", m_inventoryService.AddFolder, CheckAuthSession)); | 155 | // } |
156 | 156 | ||
157 | httpServer.AddStreamHandler( | 157 | m_log.InfoFormat( |
158 | new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | 158 | "[HGStandaloneInvModule]: Sending back inventory response to user {0} containing {1} folders and {2} items", |
159 | "POST", "/UpdateFolder/", m_inventoryService.UpdateFolder, CheckAuthSession)); | 159 | invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count); |
160 | 160 | ||
161 | httpServer.AddStreamHandler( | 161 | return invCollection; |
162 | new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | 162 | } |
163 | "POST", "/MoveFolder/", m_inventoryService.MoveFolder, CheckAuthSession)); | 163 | |
164 | 164 | public InventoryCollection FetchDescendants(InventoryFolderBase fb) | |
165 | httpServer.AddStreamHandler( | 165 | { |
166 | new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | 166 | m_log.Info("[HGStandaloneInvService]: Processing request for folder " + fb.ID); |
167 | "POST", "/PurgeFolder/", m_inventoryService.PurgeFolder, CheckAuthSession)); | 167 | |
168 | 168 | // Uncomment me to simulate a slow responding inventory server | |
169 | httpServer.AddStreamHandler( | 169 | //Thread.Sleep(16000); |
170 | new RestDeserialiseSecureHandler<InventoryItemBase, bool>( | 170 | |
171 | "POST", "/NewItem/", m_inventoryService.AddItem, CheckAuthSession)); | 171 | InventoryCollection invCollection = new InventoryCollection(); |
172 | 172 | ||
173 | httpServer.AddStreamHandler( | 173 | List<InventoryItemBase> items = m_inventoryService.RequestFolderItems(fb.ID); |
174 | new RestDeserialiseSecureHandler<InventoryItemBase, bool>( | 174 | List<InventoryFolderBase> folders = m_inventoryService.RequestSubFolders(fb.ID); |
175 | "POST", "/DeleteItem/", m_inventoryService.DeleteItem, CheckAuthSession)); | 175 | |
176 | 176 | invCollection.UserID = fb.Owner; | |
177 | //// WARNING: Root folders no longer just delivers the root and immediate child folders (e.g | 177 | invCollection.Folders = folders; |
178 | //// system folders such as Objects, Textures), but it now returns the entire inventory skeleton. | 178 | invCollection.Items = items; |
179 | //// It would have been better to rename this request, but complexities in the BaseHttpServer | 179 | |
180 | //// (e.g. any http request not found is automatically treated as an xmlrpc request) make it easier | 180 | m_log.DebugFormat("[HGStandaloneInvService]: Found {0} items and {1} folders", items.Count, folders.Count); |
181 | //// to do this for now. | 181 | |
182 | //m_scene.AddStreamHandler( | 182 | return invCollection; |
183 | // new RestDeserialiseTrustedHandler<Guid, List<InventoryFolderBase>> | 183 | } |
184 | // ("POST", "/RootFolders/", GetInventorySkeleton, CheckTrustSource)); | 184 | |
185 | 185 | public bool RemoveFolder(InventoryFolderBase folder) | |
186 | //// for persistent active gestures | 186 | { |
187 | //m_scene.AddStreamHandler( | 187 | m_log.Debug("[HGStandaloneInvService]: Removefolder: Operation not implemented yet."); |
188 | // new RestDeserialiseTrustedHandler<Guid, List<InventoryItemBase>> | 188 | return false; |
189 | // ("POST", "/ActiveGestures/", GetActiveGestures, CheckTrustSource)); | 189 | } |
190 | } | 190 | |
191 | 191 | public InventoryItemBase GetInventoryItem(InventoryItemBase item) | |
192 | 192 | { | |
193 | ///// <summary> | 193 | m_log.Info("[HGStandaloneInvService]: Get item " + item.ID); |
194 | ///// Check that the source of an inventory request is one that we trust. | 194 | |
195 | ///// </summary> | 195 | item = m_inventoryService.GetInventoryItem(item.ID); |
196 | ///// <param name="peer"></param> | 196 | if (item == null) |
197 | ///// <returns></returns> | 197 | m_log.Debug("[HGStandaloneInvService]: null item"); |
198 | //public bool CheckTrustSource(IPEndPoint peer) | 198 | return item; |
199 | //{ | 199 | } |
200 | // if (m_doLookup) | 200 | |
201 | // { | 201 | public InventoryItemBase AddItem(InventoryItemBase item) |
202 | // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer); | 202 | { |
203 | // UriBuilder ub = new UriBuilder(m_userserver_url); | 203 | m_log.DebugFormat("[HGStandaloneInvService]: Add item {0} from {1}", item.ID, item.Owner); |
204 | // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host); | 204 | if (m_inventoryService.AddItem(item)) |
205 | // foreach (IPAddress uaddr in uaddrs) | 205 | return item; |
206 | // { | 206 | else |
207 | // if (uaddr.Equals(peer.Address)) | 207 | { |
208 | // { | 208 | item.ID = UUID.Zero; |
209 | // return true; | 209 | return item; |
210 | // } | 210 | } |
211 | // } | 211 | } |
212 | 212 | ||
213 | // m_log.WarnFormat( | 213 | public InventoryItemBase UpdateItem(InventoryItemBase item) |
214 | // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources", | 214 | { |
215 | // peer); | 215 | m_log.DebugFormat("[HGStandaloneInvService]: Update item {0} from {1}", item.ID, item.Owner); |
216 | 216 | InventoryItemBase it = m_inventoryService.GetInventoryItem(item.ID); | |
217 | // return false; | 217 | item.CurrentPermissions = it.CurrentPermissions; |
218 | // } | 218 | item.AssetID = it.AssetID; |
219 | // else | 219 | if (m_inventoryService.UpdateItem(item)) |
220 | // { | 220 | return item; |
221 | // return true; | 221 | else |
222 | // } | 222 | { |
223 | //} | 223 | item.ID = UUID.Zero; |
224 | 224 | return item; | |
225 | /// <summary> | 225 | } |
226 | /// Check that the source of an inventory request for a particular agent is a current session belonging to | 226 | } |
227 | /// that agent. | 227 | |
228 | /// </summary> | 228 | public InventoryItemBase MoveItem(InventoryItemBase newitem) |
229 | /// <param name="session_id"></param> | 229 | { |
230 | /// <param name="avatar_id"></param> | 230 | m_log.DebugFormat("[HGStandaloneInvService]: Move item {0} from {1}", newitem.ID, newitem.Owner); |
231 | /// <returns></returns> | 231 | InventoryItemBase Item = m_inventoryService.GetInventoryItem(newitem.ID); |
232 | public bool CheckAuthSession(string session_id, string avatar_id) | 232 | if (Item != null) |
233 | { | 233 | { |
234 | if (m_doLookup) | 234 | if (newitem.Name != String.Empty) |
235 | { | 235 | { |
236 | m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id); | 236 | Item.Name = newitem.Name; |
237 | UUID userID = UUID.Zero; | 237 | } |
238 | UUID sessionID = UUID.Zero; | 238 | Item.Folder = newitem.Folder; |
239 | UUID.TryParse(avatar_id, out userID); | 239 | m_inventoryService.UpdateItem(Item); |
240 | UUID.TryParse(session_id, out sessionID); | 240 | return Item; |
241 | if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero)) | 241 | } |
242 | { | 242 | else |
243 | m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id); | 243 | { |
244 | return false; | 244 | m_log.Debug("[HGStandaloneInvService]: Failed to find item " + newitem.ID); |
245 | } | 245 | newitem.ID = UUID.Zero; |
246 | UserProfileData userProfile = m_userService.GetUserProfile(userID); | 246 | return newitem; |
247 | if (userProfile != null && userProfile.CurrentAgent != null && | 247 | } |
248 | userProfile.CurrentAgent.SessionID == sessionID) | 248 | |
249 | { | 249 | } |
250 | m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access."); | 250 | |
251 | return true; | 251 | public InventoryItemBase DeleteItem(InventoryItemBase item) |
252 | } | 252 | { |
253 | 253 | item = m_inventoryService.GetInventoryItem(item.ID); | |
254 | m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected"); | 254 | if (m_inventoryService.DeleteItem(item)) |
255 | return false; | 255 | return item; |
256 | } | 256 | else |
257 | else | 257 | { |
258 | { | 258 | item.ID = UUID.Zero; |
259 | return true; | 259 | return item; |
260 | } | 260 | } |
261 | } | 261 | } |
262 | 262 | ||
263 | // In truth, this is not called from the outside, for standalones. I'm just making it | 263 | public InventoryItemBase CopyItem(InventoryItemBase olditem) |
264 | // a handler already so that this can be reused for the InventoryServer. | 264 | { |
265 | public string CreateCapUrl(Guid _userid) | 265 | m_log.DebugFormat("[HGStandaloneInvService]: Copy item {0} from {1}", olditem.ID, olditem.Owner); |
266 | { | 266 | InventoryItemBase Item = m_inventoryService.GetInventoryItem(olditem.ID); // this is the old item id |
267 | UUID userID = new UUID(_userid); | 267 | // BIG HACK here |
268 | UUID random = UUID.Random(); | 268 | UUID newID = olditem.AssetID; |
269 | string url = m_thisInventoryUrl + random.ToString() + "/"; | 269 | if (Item != null) |
270 | m_log.InfoFormat("[HGStandaloneInvService] Creating Cap URL {0} for user {1}", url, userID.ToString()); | 270 | { |
271 | return url; | 271 | if (olditem.Name != String.Empty) |
272 | } | 272 | { |
273 | 273 | Item.Name = olditem.Name; | |
274 | 274 | } | |
275 | /// <summary> | 275 | Item.ID = newID; |
276 | /// Return a user's entire inventory | 276 | Item.Folder = olditem.Folder; |
277 | /// </summary> | 277 | Item.Owner = olditem.Owner; |
278 | /// <param name="rawUserID"></param> | 278 | // There should be some tests here about the owner, etc but I'm going to ignore that |
279 | /// <returns>The user's inventory. If an inventory cannot be found then an empty collection is returned.</returns> | 279 | // because I'm not sure it makes any sense |
280 | public InventoryCollection GetUserInventory(Guid rawUserID) | 280 | // Also I should probably close the asset... |
281 | { | 281 | m_inventoryService.AddItem(Item); |
282 | UUID userID = new UUID(rawUserID); | 282 | return Item; |
283 | 283 | } | |
284 | m_log.Info("[HGStandaloneInvService]: Processing request for inventory of " + userID); | 284 | else |
285 | 285 | { | |
286 | // Uncomment me to simulate a slow responding inventory server | 286 | m_log.Debug("[HGStandaloneInvService]: Failed to find item " + olditem.ID); |
287 | //Thread.Sleep(16000); | 287 | olditem.ID = UUID.Zero; |
288 | 288 | return olditem; | |
289 | InventoryCollection invCollection = new InventoryCollection(); | 289 | } |
290 | 290 | ||
291 | List<InventoryFolderBase> allFolders = ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); | 291 | } |
292 | 292 | ||
293 | if (null == allFolders) | 293 | /// <summary> |
294 | { | 294 | /// Guid to UUID wrapper for same name IInventoryServices method |
295 | m_log.WarnFormat("[HGStandaloneInvService]: No inventory found for user {0}", rawUserID); | 295 | /// </summary> |
296 | 296 | /// <param name="rawUserID"></param> | |
297 | return invCollection; | 297 | /// <returns></returns> |
298 | } | 298 | public List<InventoryFolderBase> GetInventorySkeleton(Guid rawUserID) |
299 | 299 | { | |
300 | List<InventoryItemBase> allItems = new List<InventoryItemBase>(); | 300 | UUID userID = new UUID(rawUserID); |
301 | 301 | return ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); | |
302 | foreach (InventoryFolderBase folder in allFolders) | 302 | } |
303 | { | 303 | |
304 | List<InventoryItemBase> items = ((InventoryServiceBase)m_inventoryService).RequestFolderItems(folder.ID); | 304 | public List<InventoryItemBase> GetActiveGestures(Guid rawUserID) |
305 | 305 | { | |
306 | if (items != null) | 306 | UUID userID = new UUID(rawUserID); |
307 | { | 307 | |
308 | allItems.InsertRange(0, items); | 308 | m_log.InfoFormat("[HGStandaloneInvService]: fetching active gestures for user {0}", userID); |
309 | } | 309 | |
310 | } | 310 | return ((InventoryServiceBase)m_inventoryService).GetActiveGestures(userID); |
311 | 311 | } | |
312 | invCollection.UserID = userID; | 312 | |
313 | invCollection.Folders = allFolders; | 313 | public AssetBase GetAsset(InventoryItemBase item) |
314 | invCollection.Items = allItems; | 314 | { |
315 | 315 | m_log.Info("[HGStandaloneInvService]: Get asset " + item.AssetID + " for item " + item.ID); | |
316 | // foreach (InventoryFolderBase folder in invCollection.Folders) | 316 | AssetBase asset = new AssetBase(item.AssetID, "NULL"); // send an asset with no data |
317 | // { | 317 | InventoryItemBase item2 = m_inventoryService.GetInventoryItem(item.ID); |
318 | // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back folder {0} {1}", folder.Name, folder.ID); | 318 | if (item2 == null) |
319 | // } | 319 | { |
320 | // | 320 | m_log.Debug("[HGStandaloneInvService]: null item"); |
321 | // foreach (InventoryItemBase item in invCollection.Items) | 321 | return asset; |
322 | // { | 322 | } |
323 | // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder); | 323 | if (item2.Owner != item.Owner) |
324 | // } | 324 | { |
325 | 325 | m_log.DebugFormat("[HGStandaloneInvService]: client with uuid {0} is trying to get an item of owner {1}", item.Owner, item2.Owner); | |
326 | m_log.InfoFormat( | 326 | return asset; |
327 | "[HGStandaloneInvService]: Sending back inventory response to user {0} containing {1} folders and {2} items", | 327 | } |
328 | invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count); | 328 | |
329 | 329 | // All good, get the asset | |
330 | return invCollection; | 330 | AssetBase theasset = m_assetProvider.FetchAsset(item.AssetID); |
331 | } | 331 | m_log.Debug("[HGStandaloneInvService] Found asset " + ((theasset == null)? "NULL" : "Not Null")); |
332 | 332 | if (theasset != null) | |
333 | public InventoryCollection FetchDescendants(InventoryFolderBase fb) | 333 | { |
334 | { | 334 | asset = theasset; |
335 | m_log.Info("[HGStandaloneInvService]: Processing request for folder " + fb.ID); | 335 | //m_log.Debug(" >> Sending assetID " + item.AssetID); |
336 | 336 | } | |
337 | // Uncomment me to simulate a slow responding inventory server | 337 | return asset; |
338 | //Thread.Sleep(16000); | 338 | } |
339 | 339 | ||
340 | InventoryCollection invCollection = new InventoryCollection(); | 340 | public bool PostAsset(AssetBase asset) |
341 | 341 | { | |
342 | List<InventoryItemBase> items = ((InventoryServiceBase)m_inventoryService).RequestFolderItems(fb.ID); | 342 | m_log.Info("[HGStandaloneInvService]: Post asset " + asset.FullID); |
343 | List<InventoryFolderBase> folders = ((InventoryServiceBase)m_inventoryService).RequestSubFolders(fb.ID); | 343 | m_assetProvider.CreateAsset(asset); |
344 | 344 | ||
345 | invCollection.UserID = fb.Owner; | 345 | return true; |
346 | invCollection.Folders = folders; | 346 | } |
347 | invCollection.Items = items; | 347 | |
348 | 348 | /// <summary> | |
349 | m_log.DebugFormat("[HGStandaloneInvService]: Found {0} items and {1} folders", items.Count, folders.Count); | 349 | /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see> |
350 | 350 | /// </summary> | |
351 | return invCollection; | 351 | public UUID UpdateInventoryItemAsset(UUID userID, UUID itemID, byte[] data) |
352 | } | 352 | { |
353 | 353 | m_log.Debug("[HGStandaloneInvService]: UpdateInventoryitemAsset for user " + userID + " item " + itemID); | |
354 | public bool RemoveFolder(InventoryFolderBase folder) | 354 | InventoryItemBase item = m_inventoryService.GetInventoryItem(itemID); |
355 | { | 355 | |
356 | m_log.Debug("[HGStandaloneInvService]: Removefolder: Operation not implemented yet."); | 356 | if (item != null) |
357 | return false; | 357 | { |
358 | } | 358 | // We're still not dealing with permissions |
359 | 359 | //if ((InventoryType)item.InvType == InventoryType.Notecard) | |
360 | public InventoryItemBase GetInventoryItem(InventoryItemBase item) | 360 | //{ |
361 | { | 361 | // if (!Permissions.CanEditNotecard(itemID, UUID.Zero, userID)) |
362 | m_log.Info("[HGStandaloneInvService]: Get item " + item.ID); | 362 | // { |
363 | 363 | // //remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); | |
364 | item = ((InventoryServiceBase)m_inventoryService).GetInventoryItem(item.ID); | 364 | // return UUID.Zero; |
365 | if (item == null) | 365 | // } |
366 | m_log.Debug("[HGStandaloneInvService]: null item"); | 366 | |
367 | return item; | 367 | // //remoteClient.SendAgentAlertMessage("Notecard saved", false); |
368 | } | 368 | //} |
369 | 369 | //else if ((InventoryType)item.InvType == InventoryType.LSL) | |
370 | public InventoryItemBase AddItem(InventoryItemBase item) | 370 | //{ |
371 | { | 371 | // if (!Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId)) |
372 | m_log.DebugFormat("[HGStandaloneInvService]: Add item {0} from {1}", item.ID, item.Owner); | 372 | // { |
373 | if (m_inventoryService.AddItem(item)) | 373 | // //remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); |
374 | return item; | 374 | // return UUID.Zero; |
375 | else | 375 | // } |
376 | { | 376 | |
377 | item.ID = UUID.Zero; | 377 | // //remoteClient.SendAgentAlertMessage("Script saved", false); |
378 | return item; | 378 | //} |
379 | } | 379 | |
380 | } | 380 | AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data); |
381 | 381 | PostAsset(asset); | |
382 | public InventoryItemBase UpdateItem(InventoryItemBase item) | 382 | |
383 | { | 383 | item.AssetID = asset.FullID; |
384 | m_log.DebugFormat("[HGStandaloneInvService]: Update item {0} from {1}", item.ID, item.Owner); | 384 | item.Owner = userID; |
385 | InventoryItemBase it = m_inventoryService.GetInventoryItem(item.ID); | 385 | m_inventoryService.UpdateItem(item); |
386 | item.CurrentPermissions = it.CurrentPermissions; | 386 | |
387 | item.AssetID = it.AssetID; | 387 | return (asset.FullID); |
388 | if (m_inventoryService.UpdateItem(item)) | 388 | } |
389 | return item; | 389 | return UUID.Zero; |
390 | else | 390 | } |
391 | { | 391 | |
392 | item.ID = UUID.Zero; | 392 | private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data) |
393 | return item; | 393 | { |
394 | } | 394 | AssetBase asset = new AssetBase(); |
395 | } | 395 | asset.Name = name; |
396 | 396 | asset.Description = description; | |
397 | public InventoryItemBase MoveItem(InventoryItemBase newitem) | 397 | asset.Type = assetType; |
398 | { | 398 | asset.FullID = UUID.Random(); |
399 | m_log.DebugFormat("[HGStandaloneInvService]: Move item {0} from {1}", newitem.ID, newitem.Owner); | 399 | asset.Data = (data == null) ? new byte[1] : data; |
400 | InventoryItemBase Item = m_inventoryService.GetInventoryItem(newitem.ID); | 400 | |
401 | if (Item != null) | 401 | return asset; |
402 | { | 402 | } |
403 | if (newitem.Name != String.Empty) | 403 | |
404 | { | 404 | #region Caps |
405 | Item.Name = newitem.Name; | 405 | |
406 | } | 406 | Dictionary<UUID, Hashtable> invCaps = new Dictionary<UUID, Hashtable>(); |
407 | Item.Folder = newitem.Folder; | 407 | |
408 | m_inventoryService.UpdateItem(Item); | 408 | public Hashtable CapHandler(Hashtable request) |
409 | return Item; | 409 | { |
410 | } | 410 | m_log.Debug("[CONNECTION DEBUGGING]: InvCapHandler Called"); |
411 | else | 411 | |
412 | { | 412 | m_log.Debug("---------------------------"); |
413 | m_log.Debug("[HGStandaloneInvService]: Failed to find item " + newitem.ID); | 413 | m_log.Debug(" >> uri=" + request["uri"]); |
414 | newitem.ID = UUID.Zero; | 414 | m_log.Debug(" >> content-type=" + request["content-type"]); |
415 | return newitem; | 415 | m_log.Debug(" >> http-method=" + request["http-method"]); |
416 | } | 416 | m_log.Debug("---------------------------\n"); |
417 | 417 | ||
418 | } | 418 | // these are requests if the type |
419 | 419 | // http://inventoryserver/InvCap/uuuuuuuu-uuuu-uuuu-uuuu-uuuuuuuuuuuu/kkkkkkkk-kkkk-kkkk-kkkk-kkkkkkkkkkkk/ | |
420 | public InventoryItemBase DeleteItem(InventoryItemBase item) | 420 | |
421 | { | 421 | Hashtable responsedata = new Hashtable(); |
422 | item = m_inventoryService.GetInventoryItem(item.ID); | 422 | responsedata["content_type"] = "text/plain"; |
423 | if (m_inventoryService.DeleteItem(item)) | 423 | |
424 | return item; | 424 | UUID userID; |
425 | else | 425 | string authToken = string.Empty; |
426 | { | 426 | string authority = string.Empty; |
427 | item.ID = UUID.Zero; | 427 | if (!GetParams(request, out userID, out authority, out authToken)) |
428 | return item; | 428 | { |
429 | } | 429 | m_log.InfoFormat("[HGStandaloneInvService]: Invalid parameters for InvCap message {0}", request["uri"]); |
430 | } | 430 | responsedata["int_response_code"] = 404; |
431 | 431 | responsedata["str_response_string"] = "Not found"; | |
432 | public InventoryItemBase CopyItem(InventoryItemBase olditem) | 432 | |
433 | { | 433 | return responsedata; |
434 | m_log.DebugFormat("[HGStandaloneInvService]: Copy item {0} from {1}", olditem.ID, olditem.Owner); | 434 | } |
435 | InventoryItemBase Item = m_inventoryService.GetInventoryItem(olditem.ID); // this is the old item id | 435 | |
436 | // BIG HACK here | 436 | // Next, let's parse the verb |
437 | UUID newID = olditem.AssetID; | 437 | string method = (string)request["http-method"]; |
438 | if (Item != null) | 438 | if (method.Equals("GET")) |
439 | { | 439 | { |
440 | if (olditem.Name != String.Empty) | 440 | DoInvCapPost(request, responsedata, userID, authToken); |
441 | { | 441 | return responsedata; |
442 | Item.Name = olditem.Name; | 442 | } |
443 | } | 443 | //else if (method.Equals("DELETE")) |
444 | Item.ID = newID; | 444 | //{ |
445 | Item.Folder = olditem.Folder; | 445 | // DoAgentDelete(request, responsedata, agentID, action, regionHandle); |
446 | Item.Owner = olditem.Owner; | 446 | |
447 | // There should be some tests here about the owner, etc but I'm going to ignore that | 447 | // return responsedata; |
448 | // because I'm not sure it makes any sense | 448 | //} |
449 | // Also I should probably close the asset... | 449 | else |
450 | m_inventoryService.AddItem(Item); | 450 | { |
451 | return Item; | 451 | m_log.InfoFormat("[HGStandaloneInvService]: method {0} not supported in agent message", method); |
452 | } | 452 | responsedata["int_response_code"] = 405; |
453 | else | 453 | responsedata["str_response_string"] = "Method not allowed"; |
454 | { | 454 | |
455 | m_log.Debug("[HGStandaloneInvService]: Failed to find item " + olditem.ID); | 455 | return responsedata; |
456 | olditem.ID = UUID.Zero; | 456 | } |
457 | return olditem; | 457 | |
458 | } | 458 | } |
459 | 459 | ||
460 | } | 460 | public virtual void DoInvCapPost(Hashtable request, Hashtable responsedata, UUID userID, string authToken) |
461 | 461 | { | |
462 | /// <summary> | 462 | |
463 | /// Guid to UUID wrapper for same name IInventoryServices method | 463 | // This is the meaning of POST agent |
464 | /// </summary> | 464 | |
465 | /// <param name="rawUserID"></param> | 465 | // Check Auth Token |
466 | /// <returns></returns> | 466 | if (!(m_userService is IAuthentication)) |
467 | public List<InventoryFolderBase> GetInventorySkeleton(Guid rawUserID) | 467 | { |
468 | { | 468 | m_log.Debug("[HGStandaloneInvService]: UserService is not IAuthentication. Denying access to inventory."); |
469 | UUID userID = new UUID(rawUserID); | 469 | responsedata["int_response_code"] = 501; |
470 | return ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); | 470 | responsedata["str_response_string"] = "Not implemented"; |
471 | } | 471 | return; |
472 | 472 | } | |
473 | public List<InventoryItemBase> GetActiveGestures(Guid rawUserID) | 473 | |
474 | { | 474 | bool success = ((IAuthentication)m_userService).VerifyKey(userID, authToken); |
475 | UUID userID = new UUID(rawUserID); | 475 | |
476 | 476 | if (success) | |
477 | m_log.InfoFormat("[HGStandaloneInvService]: fetching active gestures for user {0}", userID); | 477 | { |
478 | 478 | ||
479 | return ((InventoryServiceBase)m_inventoryService).GetActiveGestures(userID); | 479 | m_log.DebugFormat("[HGStandaloneInvService]: User has been authorized. Creating service handlers."); |
480 | } | 480 | |
481 | 481 | // Then establish secret service handlers | |
482 | public AssetBase GetAsset(InventoryItemBase item) | 482 | |
483 | { | 483 | Hashtable usercaps = RegisterCaps(userID, authToken); |
484 | m_log.Info("[HGStandaloneInvService]: Get asset " + item.AssetID + " for item " + item.ID); | 484 | |
485 | AssetBase asset = new AssetBase(item.AssetID, "NULL"); // send an asset with no data | 485 | responsedata["int_response_code"] = 200; |
486 | InventoryItemBase item2 = ((InventoryServiceBase)m_inventoryService).GetInventoryItem(item.ID); | 486 | //responsedata["str_response_string"] = "OK"; |
487 | if (item2 == null) | 487 | responsedata["str_response_string"] = SerializeHashtable(usercaps); |
488 | { | 488 | } |
489 | m_log.Debug("[HGStandaloneInvService]: null item"); | 489 | else |
490 | return asset; | 490 | { |
491 | } | 491 | m_log.DebugFormat("[HGStandaloneInvService]: User has is unauthorized. Denying service handlers."); |
492 | if (item2.Owner != item.Owner) | 492 | responsedata["int_response_code"] = 403; |
493 | { | 493 | responsedata["str_response_string"] = "Forbidden"; |
494 | m_log.DebugFormat("[HGStandaloneInvService]: client with uuid {0} is trying to get an item of owner {1}", item.Owner, item2.Owner); | 494 | } |
495 | return asset; | 495 | } |
496 | } | 496 | |
497 | 497 | ||
498 | // All good, get the asset | 498 | /// <summary> |
499 | AssetBase theasset = m_assetProvider.FetchAsset(item.AssetID); | 499 | /// Extract the params from a request. |
500 | m_log.Debug("[HGStandaloneInvService] Found asset " + ((theasset == null)? "NULL" : "Not Null")); | 500 | /// </summary> |
501 | if (theasset != null) | 501 | public static bool GetParams(Hashtable request, out UUID uuid, out string authority, out string authKey) |
502 | { | 502 | { |
503 | asset = theasset; | 503 | uuid = UUID.Zero; |
504 | //m_log.Debug(" >> Sending assetID " + item.AssetID); | 504 | authority = string.Empty; |
505 | } | 505 | authKey = string.Empty; |
506 | return asset; | 506 | |
507 | } | 507 | string uri = (string)request["uri"]; |
508 | 508 | uri = uri.Trim(new char[] { '/' }); | |
509 | public bool PostAsset(AssetBase asset) | 509 | string[] parts = uri.Split('/'); |
510 | { | 510 | if (parts.Length <= 1) |
511 | m_log.Info("[HGStandaloneInvService]: Post asset " + asset.FullID); | 511 | { |
512 | m_assetProvider.CreateAsset(asset); | 512 | return false; |
513 | 513 | } | |
514 | return true; | 514 | else |
515 | } | 515 | { |
516 | 516 | if (!UUID.TryParse(parts[1], out uuid)) | |
517 | /// <summary> | 517 | return false; |
518 | /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see> | 518 | |
519 | /// </summary> | 519 | if (parts.Length >= 3) |
520 | public UUID UpdateInventoryItemAsset(UUID userID, UUID itemID, byte[] data) | 520 | { |
521 | { | 521 | authKey = parts[2]; |
522 | m_log.Debug("[HGStandaloneInvService]: UpdateInventoryitemAsset for user " + userID + " item " + itemID); | 522 | return true; |
523 | InventoryItemBase item = m_inventoryService.GetInventoryItem(itemID); | 523 | } |
524 | 524 | } | |
525 | if (item != null) | 525 | |
526 | { | 526 | Uri authUri; |
527 | // We're still not dealing with permissions | 527 | Hashtable headers = (Hashtable)request["headers"]; |
528 | //if ((InventoryType)item.InvType == InventoryType.Notecard) | 528 | |
529 | //{ | 529 | // Authorization keys look like this: |
530 | // if (!Permissions.CanEditNotecard(itemID, UUID.Zero, userID)) | 530 | // http://orgrid.org:8002/<uuid> |
531 | // { | 531 | if (headers.ContainsKey("authorization")) |
532 | // //remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); | 532 | { |
533 | // return UUID.Zero; | 533 | if (Uri.TryCreate((string)headers["authorization"], UriKind.Absolute, out authUri)) |
534 | // } | 534 | { |
535 | 535 | authority = authUri.Authority; | |
536 | // //remoteClient.SendAgentAlertMessage("Notecard saved", false); | 536 | authKey = authUri.PathAndQuery.Trim('/'); |
537 | //} | 537 | m_log.DebugFormat("[HGStandaloneInvService]: Got authority {0} and key {1}", authority, authKey); |
538 | //else if ((InventoryType)item.InvType == InventoryType.LSL) | 538 | return true; |
539 | //{ | 539 | } |
540 | // if (!Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId)) | 540 | else |
541 | // { | 541 | m_log.Debug("[HGStandaloneInvService]: Wrong format for Authorization header: " + (string)headers["authorization"]); |
542 | // //remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); | 542 | } |
543 | // return UUID.Zero; | 543 | else |
544 | // } | 544 | m_log.Debug("[HGStandaloneInvService]: Authorization header not found"); |
545 | 545 | ||
546 | // //remoteClient.SendAgentAlertMessage("Script saved", false); | 546 | return false; |
547 | //} | 547 | } |
548 | 548 | ||
549 | AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data); | 549 | string SerializeHashtable(Hashtable hash) |
550 | PostAsset(asset); | 550 | { |
551 | 551 | string result = string.Empty; | |
552 | item.AssetID = asset.FullID; | 552 | foreach (object key in hash.Keys) |
553 | item.Owner = userID; | 553 | { |
554 | m_inventoryService.UpdateItem(item); | 554 | result += key.ToString() + "," + hash[key].ToString() + ";"; |
555 | 555 | } | |
556 | return (asset.FullID); | 556 | return result; |
557 | } | 557 | } |
558 | return UUID.Zero; | 558 | |
559 | } | 559 | Hashtable RegisterCaps(UUID userID, string authToken) |
560 | 560 | { | |
561 | private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data) | 561 | lock (invCaps) |
562 | { | 562 | { |
563 | AssetBase asset = new AssetBase(); | 563 | if (invCaps.ContainsKey(userID)) |
564 | asset.Name = name; | 564 | { |
565 | asset.Description = description; | 565 | // Remove the old ones |
566 | asset.Type = assetType; | 566 | DeregisterCaps(httpServer, invCaps[userID]); |
567 | asset.FullID = UUID.Random(); | 567 | invCaps.Remove(userID); |
568 | asset.Data = (data == null) ? new byte[1] : data; | 568 | } |
569 | 569 | } | |
570 | return asset; | 570 | |
571 | } | 571 | Caps caps = new Caps(null, httpServer, m_thisHostname, m_thisPort, authToken, userID, false, "Inventory"); |
572 | 572 | caps.RegisterInventoryServiceHandlers("/" + authToken + "/InventoryCap/"); | |
573 | #region Caps | 573 | caps.ItemUpdatedCall = UpdateInventoryItemAsset; |
574 | 574 | Hashtable capsHandlers = caps.CapsHandlers.CapsDetails; | |
575 | Dictionary<UUID, Hashtable> invCaps = new Dictionary<UUID, Hashtable>(); | 575 | |
576 | 576 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<Guid, InventoryCollection>( | |
577 | public Hashtable CapHandler(Hashtable request) | 577 | "POST", AddAndGetCapUrl(authToken, "GetInventory", capsHandlers), GetUserInventory, CheckAuthSession)); |
578 | { | 578 | |
579 | m_log.Debug("[CONNECTION DEBUGGING]: InvCapHandler Called"); | 579 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, InventoryCollection>( |
580 | 580 | "POST", AddAndGetCapUrl(authToken, "FetchDescendants", capsHandlers), FetchDescendants, CheckAuthSession)); | |
581 | m_log.Debug("---------------------------"); | 581 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( |
582 | m_log.Debug(" >> uri=" + request["uri"]); | 582 | "POST", AddAndGetCapUrl(authToken, "NewFolder", capsHandlers), m_inventoryService.AddFolder, CheckAuthSession)); |
583 | m_log.Debug(" >> content-type=" + request["content-type"]); | 583 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( |
584 | m_log.Debug(" >> http-method=" + request["http-method"]); | 584 | "POST", AddAndGetCapUrl(authToken, "UpdateFolder", capsHandlers), m_inventoryService.UpdateFolder, CheckAuthSession)); |
585 | m_log.Debug("---------------------------\n"); | 585 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( |
586 | 586 | "POST", AddAndGetCapUrl(authToken, "MoveFolder", capsHandlers), m_inventoryService.MoveFolder, CheckAuthSession)); | |
587 | // these are requests if the type | 587 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( |
588 | // http://inventoryserver/InvCap/uuuuuuuu-uuuu-uuuu-uuuu-uuuuuuuuuuuu/kkkkkkkk-kkkk-kkkk-kkkk-kkkkkkkkkkkk/ | 588 | "POST", AddAndGetCapUrl(authToken, "PurgeFolder", capsHandlers), m_inventoryService.PurgeFolder, CheckAuthSession)); |
589 | 589 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | |
590 | Hashtable responsedata = new Hashtable(); | 590 | "POST", AddAndGetCapUrl(authToken, "RemoveFolder", capsHandlers), RemoveFolder, CheckAuthSession)); |
591 | responsedata["content_type"] = "text/plain"; | 591 | |
592 | 592 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | |
593 | UUID userID; | 593 | "POST", AddAndGetCapUrl(authToken, "GetItem", capsHandlers), GetInventoryItem, CheckAuthSession)); |
594 | string authToken = string.Empty; | 594 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( |
595 | string authority = string.Empty; | 595 | "POST", AddAndGetCapUrl(authToken, "NewItem", capsHandlers), AddItem, CheckAuthSession)); |
596 | if (!GetParams(request, out userID, out authority, out authToken)) | 596 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( |
597 | { | 597 | "POST", AddAndGetCapUrl(authToken, "UpdateItem", capsHandlers), UpdateItem, CheckAuthSession)); |
598 | m_log.InfoFormat("[HGStandaloneInvService]: Invalid parameters for InvCap message {0}", request["uri"]); | 598 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( |
599 | responsedata["int_response_code"] = 404; | 599 | "POST", AddAndGetCapUrl(authToken, "MoveItem", capsHandlers), MoveItem, CheckAuthSession)); |
600 | responsedata["str_response_string"] = "Not found"; | 600 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( |
601 | 601 | "POST", AddAndGetCapUrl(authToken, "DeleteItem", capsHandlers), DeleteItem, CheckAuthSession)); | |
602 | return responsedata; | 602 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( |
603 | } | 603 | "POST", AddAndGetCapUrl(authToken, "CopyItem", capsHandlers), CopyItem, CheckAuthSession)); |
604 | 604 | ||
605 | // Next, let's parse the verb | 605 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, AssetBase>( |
606 | string method = (string)request["http-method"]; | 606 | "POST", AddAndGetCapUrl(authToken, "GetAsset", capsHandlers), GetAsset, CheckAuthSession)); |
607 | if (method.Equals("GET")) | 607 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<AssetBase, bool>( |
608 | { | 608 | "POST", AddAndGetCapUrl(authToken, "PostAsset", capsHandlers), PostAsset, CheckAuthSession)); |
609 | DoInvCapPost(request, responsedata, userID, authToken); | 609 | |
610 | return responsedata; | 610 | lock (invCaps) |
611 | } | 611 | invCaps.Add(userID, capsHandlers); |
612 | //else if (method.Equals("DELETE")) | 612 | |
613 | //{ | 613 | return capsHandlers; |
614 | // DoAgentDelete(request, responsedata, agentID, action, regionHandle); | 614 | } |
615 | 615 | ||
616 | // return responsedata; | 616 | string AddAndGetCapUrl(string authToken, string capType, Hashtable caps) |
617 | //} | 617 | { |
618 | else | 618 | string capUrl = "/" + authToken + "/" + capType + "/"; |
619 | { | 619 | |
620 | m_log.InfoFormat("[HGStandaloneInvService]: method {0} not supported in agent message", method); | 620 | m_log.Debug("[HGStandaloneInvService] Adding inventory cap " + capUrl); |
621 | responsedata["int_response_code"] = 405; | 621 | caps.Add(capType, capUrl); |
622 | responsedata["str_response_string"] = "Method not allowed"; | 622 | return capUrl; |
623 | 623 | } | |
624 | return responsedata; | 624 | |
625 | } | 625 | void DeregisterCaps(IHttpServer httpServer, Hashtable caps) |
626 | 626 | { | |
627 | } | 627 | foreach (string capUrl in caps.Values) |
628 | 628 | { | |
629 | public virtual void DoInvCapPost(Hashtable request, Hashtable responsedata, UUID userID, string authToken) | 629 | m_log.Debug("[HGStandaloneInvService] Removing inventory cap " + capUrl); |
630 | { | 630 | httpServer.RemoveStreamHandler("POST", capUrl); |
631 | 631 | } | |
632 | // This is the meaning of POST agent | 632 | } |
633 | 633 | ||
634 | // Check Auth Token | 634 | #endregion Caps |
635 | if (!(m_userService is IAuthentication)) | 635 | } |
636 | { | 636 | } |
637 | m_log.Debug("[HGStandaloneInvService]: UserService is not IAuthentication. Denying access to inventory."); | ||
638 | responsedata["int_response_code"] = 501; | ||
639 | responsedata["str_response_string"] = "Not implemented"; | ||
640 | return; | ||
641 | } | ||
642 | |||
643 | bool success = ((IAuthentication)m_userService).VerifyKey(userID, authToken); | ||
644 | |||
645 | if (success) | ||
646 | { | ||
647 | |||
648 | m_log.DebugFormat("[HGStandaloneInvService]: User has been authorized. Creating service handlers."); | ||
649 | |||
650 | // Then establish secret service handlers | ||
651 | |||
652 | Hashtable usercaps = RegisterCaps(userID, authToken); | ||
653 | |||
654 | responsedata["int_response_code"] = 200; | ||
655 | //responsedata["str_response_string"] = "OK"; | ||
656 | responsedata["str_response_string"] = SerializeHashtable(usercaps); | ||
657 | } | ||
658 | else | ||
659 | { | ||
660 | m_log.DebugFormat("[HGStandaloneInvService]: User has is unauthorized. Denying service handlers."); | ||
661 | responsedata["int_response_code"] = 403; | ||
662 | responsedata["str_response_string"] = "Forbidden"; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | |||
667 | /// <summary> | ||
668 | /// Extract the params from a request. | ||
669 | /// </summary> | ||
670 | public static bool GetParams(Hashtable request, out UUID uuid, out string authority, out string authKey) | ||
671 | { | ||
672 | uuid = UUID.Zero; | ||
673 | authority = string.Empty; | ||
674 | authKey = string.Empty; | ||
675 | |||
676 | string uri = (string)request["uri"]; | ||
677 | uri = uri.Trim(new char[] { '/' }); | ||
678 | string[] parts = uri.Split('/'); | ||
679 | if (parts.Length <= 1) | ||
680 | { | ||
681 | return false; | ||
682 | } | ||
683 | else | ||
684 | { | ||
685 | if (!UUID.TryParse(parts[1], out uuid)) | ||
686 | return false; | ||
687 | |||
688 | if (parts.Length >= 3) | ||
689 | { | ||
690 | authKey = parts[2]; | ||
691 | return true; | ||
692 | } | ||
693 | } | ||
694 | |||
695 | Uri authUri; | ||
696 | Hashtable headers = (Hashtable)request["headers"]; | ||
697 | |||
698 | // Authorization keys look like this: | ||
699 | // http://orgrid.org:8002/<uuid> | ||
700 | if (headers.ContainsKey("authorization")) | ||
701 | { | ||
702 | if (Uri.TryCreate((string)headers["authorization"], UriKind.Absolute, out authUri)) | ||
703 | { | ||
704 | authority = authUri.Authority; | ||
705 | authKey = authUri.PathAndQuery.Trim('/'); | ||
706 | m_log.DebugFormat("[HGStandaloneInvService]: Got authority {0} and key {1}", authority, authKey); | ||
707 | return true; | ||
708 | } | ||
709 | else | ||
710 | m_log.Debug("[HGStandaloneInvService]: Wrong format for Authorization header: " + (string)headers["authorization"]); | ||
711 | } | ||
712 | else | ||
713 | m_log.Debug("[HGStandaloneInvService]: Authorization header not found"); | ||
714 | |||
715 | return false; | ||
716 | } | ||
717 | |||
718 | string SerializeHashtable(Hashtable hash) | ||
719 | { | ||
720 | string result = string.Empty; | ||
721 | foreach (object key in hash.Keys) | ||
722 | { | ||
723 | result += key.ToString() + "," + hash[key].ToString() + ";"; | ||
724 | } | ||
725 | return result; | ||
726 | } | ||
727 | |||
728 | Hashtable RegisterCaps(UUID userID, string authToken) | ||
729 | { | ||
730 | IHttpServer httpServer = m_scene.CommsManager.HttpServer; | ||
731 | |||
732 | lock (invCaps) | ||
733 | { | ||
734 | if (invCaps.ContainsKey(userID)) | ||
735 | { | ||
736 | // Remove the old ones | ||
737 | DeregisterCaps(httpServer, invCaps[userID]); | ||
738 | invCaps.Remove(userID); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | Caps caps = new Caps(null, httpServer, m_thisHostname, m_thisPort, authToken, userID, false, "Inventory"); | ||
743 | caps.RegisterInventoryServiceHandlers("/" + authToken + "/InventoryCap/"); | ||
744 | caps.ItemUpdatedCall = UpdateInventoryItemAsset; | ||
745 | Hashtable capsHandlers = caps.CapsHandlers.CapsDetails; | ||
746 | |||
747 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<Guid, InventoryCollection>( | ||
748 | "POST", AddAndGetCapUrl(authToken, "GetInventory", capsHandlers), GetUserInventory, CheckAuthSession)); | ||
749 | |||
750 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, InventoryCollection>( | ||
751 | "POST", AddAndGetCapUrl(authToken, "FetchDescendants", capsHandlers), FetchDescendants, CheckAuthSession)); | ||
752 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | ||
753 | "POST", AddAndGetCapUrl(authToken, "NewFolder", capsHandlers), m_inventoryService.AddFolder, CheckAuthSession)); | ||
754 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | ||
755 | "POST", AddAndGetCapUrl(authToken, "UpdateFolder", capsHandlers), m_inventoryService.UpdateFolder, CheckAuthSession)); | ||
756 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | ||
757 | "POST", AddAndGetCapUrl(authToken, "MoveFolder", capsHandlers), m_inventoryService.MoveFolder, CheckAuthSession)); | ||
758 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | ||
759 | "POST", AddAndGetCapUrl(authToken, "PurgeFolder", capsHandlers), m_inventoryService.PurgeFolder, CheckAuthSession)); | ||
760 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>( | ||
761 | "POST", AddAndGetCapUrl(authToken, "RemoveFolder", capsHandlers), RemoveFolder, CheckAuthSession)); | ||
762 | |||
763 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | ||
764 | "POST", AddAndGetCapUrl(authToken, "GetItem", capsHandlers), GetInventoryItem, CheckAuthSession)); | ||
765 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | ||
766 | "POST", AddAndGetCapUrl(authToken, "NewItem", capsHandlers), AddItem, CheckAuthSession)); | ||
767 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | ||
768 | "POST", AddAndGetCapUrl(authToken, "UpdateItem", capsHandlers), UpdateItem, CheckAuthSession)); | ||
769 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | ||
770 | "POST", AddAndGetCapUrl(authToken, "MoveItem", capsHandlers), MoveItem, CheckAuthSession)); | ||
771 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | ||
772 | "POST", AddAndGetCapUrl(authToken, "DeleteItem", capsHandlers), DeleteItem, CheckAuthSession)); | ||
773 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>( | ||
774 | "POST", AddAndGetCapUrl(authToken, "CopyItem", capsHandlers), CopyItem, CheckAuthSession)); | ||
775 | |||
776 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, AssetBase>( | ||
777 | "POST", AddAndGetCapUrl(authToken, "GetAsset", capsHandlers), GetAsset, CheckAuthSession)); | ||
778 | httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<AssetBase, bool>( | ||
779 | "POST", AddAndGetCapUrl(authToken, "PostAsset", capsHandlers), PostAsset, CheckAuthSession)); | ||
780 | |||
781 | lock (invCaps) | ||
782 | invCaps.Add(userID, capsHandlers); | ||
783 | |||
784 | return capsHandlers; | ||
785 | } | ||
786 | |||
787 | string AddAndGetCapUrl(string authToken, string capType, Hashtable caps) | ||
788 | { | ||
789 | string capUrl = "/" + authToken + "/" + capType + "/"; | ||
790 | |||
791 | m_log.Debug("[HGStandaloneInvService] Adding inventory cap " + capUrl); | ||
792 | caps.Add(capType, capUrl); | ||
793 | return capUrl; | ||
794 | } | ||
795 | |||
796 | void DeregisterCaps(IHttpServer httpServer, Hashtable caps) | ||
797 | { | ||
798 | foreach (string capUrl in caps.Values) | ||
799 | { | ||
800 | m_log.Debug("[HGStandaloneInvService] Removing inventory cap " + capUrl); | ||
801 | httpServer.RemoveStreamHandler("POST", capUrl); | ||
802 | } | ||
803 | } | ||
804 | |||
805 | #endregion Caps | ||
806 | } | ||
807 | } | ||