aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/LoginService.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Communications/Services/LoginService.cs (renamed from OpenSim/Framework/Communications/LoginService.cs)2186
1 files changed, 1093 insertions, 1093 deletions
diff --git a/OpenSim/Framework/Communications/LoginService.cs b/OpenSim/Framework/Communications/Services/LoginService.cs
index 99b5df7..51158c9 100644
--- a/OpenSim/Framework/Communications/LoginService.cs
+++ b/OpenSim/Framework/Communications/Services/LoginService.cs
@@ -1,1093 +1,1093 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
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 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Text.RegularExpressions; 33using System.Text.RegularExpressions;
34using System.Threading; 34using System.Threading;
35using System.Web; 35using System.Web;
36using log4net; 36using log4net;
37using Nwc.XmlRpc; 37using Nwc.XmlRpc;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenMetaverse.StructuredData; 39using OpenMetaverse.StructuredData;
40using OpenSim.Framework.Communications.Cache; 40using OpenSim.Framework.Communications.Cache;
41using OpenSim.Framework.Statistics; 41using OpenSim.Framework.Statistics;
42 42
43namespace OpenSim.Framework.Communications 43namespace OpenSim.Framework.Communications.Services
44{ 44{
45 public abstract class LoginService 45 public abstract class LoginService
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 protected string m_welcomeMessage = "Welcome to OpenSim"; 49 protected string m_welcomeMessage = "Welcome to OpenSim";
50 protected int m_minLoginLevel = 0; 50 protected int m_minLoginLevel = 0;
51 protected UserManagerBase m_userManager = null; 51 protected UserManagerBase m_userManager = null;
52 protected Mutex m_loginMutex = new Mutex(false); 52 protected Mutex m_loginMutex = new Mutex(false);
53 53
54 /// <summary> 54 /// <summary>
55 /// Used during login to send the skeleton of the OpenSim Library to the client. 55 /// Used during login to send the skeleton of the OpenSim Library to the client.
56 /// </summary> 56 /// </summary>
57 protected LibraryRootFolder m_libraryRootFolder; 57 protected LibraryRootFolder m_libraryRootFolder;
58 58
59 protected uint m_defaultHomeX; 59 protected uint m_defaultHomeX;
60 protected uint m_defaultHomeY; 60 protected uint m_defaultHomeY;
61 61
62 /// <summary> 62 /// <summary>
63 /// Used by the login service to make requests to the inventory service. 63 /// Used by the login service to make requests to the inventory service.
64 /// </summary> 64 /// </summary>
65 protected IInterServiceInventoryServices m_inventoryService; 65 protected IInterServiceInventoryServices m_inventoryService;
66 66
67 /// <summary> 67 /// <summary>
68 /// Constructor 68 /// Constructor
69 /// </summary> 69 /// </summary>
70 /// <param name="userManager"></param> 70 /// <param name="userManager"></param>
71 /// <param name="libraryRootFolder"></param> 71 /// <param name="libraryRootFolder"></param>
72 /// <param name="welcomeMess"></param> 72 /// <param name="welcomeMess"></param>
73 public LoginService(UserManagerBase userManager, LibraryRootFolder libraryRootFolder, 73 public LoginService(UserManagerBase userManager, LibraryRootFolder libraryRootFolder,
74 string welcomeMess) 74 string welcomeMess)
75 { 75 {
76 m_userManager = userManager; 76 m_userManager = userManager;
77 m_libraryRootFolder = libraryRootFolder; 77 m_libraryRootFolder = libraryRootFolder;
78 78
79 if (welcomeMess != String.Empty) 79 if (welcomeMess != String.Empty)
80 { 80 {
81 m_welcomeMessage = welcomeMess; 81 m_welcomeMessage = welcomeMess;
82 } 82 }
83 } 83 }
84 84
85 /// <summary> 85 /// <summary>
86 /// If the user is already logged in, try to notify the region that the user they've got is dead. 86 /// If the user is already logged in, try to notify the region that the user they've got is dead.
87 /// </summary> 87 /// </summary>
88 /// <param name="theUser"></param> 88 /// <param name="theUser"></param>
89 public virtual void LogOffUser(UserProfileData theUser, string message) 89 public virtual void LogOffUser(UserProfileData theUser, string message)
90 { 90 {
91 } 91 }
92 92
93 93
94 /// <summary> 94 /// <summary>
95 /// Called when we receive the client's initial XMLRPC login_to_simulator request message 95 /// Called when we receive the client's initial XMLRPC login_to_simulator request message
96 /// </summary> 96 /// </summary>
97 /// <param name="request">The XMLRPC request</param> 97 /// <param name="request">The XMLRPC request</param>
98 /// <returns>The response to send</returns> 98 /// <returns>The response to send</returns>
99 public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request) 99 public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request)
100 { 100 {
101 // Temporary fix 101 // Temporary fix
102 m_loginMutex.WaitOne(); 102 m_loginMutex.WaitOne();
103 103
104 try 104 try
105 { 105 {
106 //CFK: CustomizeResponse contains sufficient strings to alleviate the need for this. 106 //CFK: CustomizeResponse contains sufficient strings to alleviate the need for this.
107 //CKF: m_log.Info("[LOGIN]: Attempting login now..."); 107 //CKF: m_log.Info("[LOGIN]: Attempting login now...");
108 XmlRpcResponse response = new XmlRpcResponse(); 108 XmlRpcResponse response = new XmlRpcResponse();
109 Hashtable requestData = (Hashtable)request.Params[0]; 109 Hashtable requestData = (Hashtable)request.Params[0];
110 110
111 SniffLoginKey((Uri)request.Params[2], requestData); 111 SniffLoginKey((Uri)request.Params[2], requestData);
112 112
113 bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") && 113 bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") &&
114 (requestData.Contains("passwd") || requestData.Contains("web_login_key"))); 114 (requestData.Contains("passwd") || requestData.Contains("web_login_key")));
115 115
116 string startLocationRequest = "last"; 116 string startLocationRequest = "last";
117 117
118 UserProfileData userProfile; 118 UserProfileData userProfile;
119 LoginResponse logResponse = new LoginResponse(); 119 LoginResponse logResponse = new LoginResponse();
120 120
121 string firstname; 121 string firstname;
122 string lastname; 122 string lastname;
123 123
124 if (GoodXML) 124 if (GoodXML)
125 { 125 {
126 if (requestData.Contains("start")) 126 if (requestData.Contains("start"))
127 { 127 {
128 startLocationRequest = (string)requestData["start"]; 128 startLocationRequest = (string)requestData["start"];
129 } 129 }
130 130
131 firstname = (string)requestData["first"]; 131 firstname = (string)requestData["first"];
132 lastname = (string)requestData["last"]; 132 lastname = (string)requestData["last"];
133 133
134 m_log.InfoFormat( 134 m_log.InfoFormat(
135 "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'", 135 "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'",
136 firstname, lastname); 136 firstname, lastname);
137 137
138 string clientVersion = "Unknown"; 138 string clientVersion = "Unknown";
139 139
140 if (requestData.Contains("version")) 140 if (requestData.Contains("version"))
141 { 141 {
142 clientVersion = (string)requestData["version"]; 142 clientVersion = (string)requestData["version"];
143 } 143 }
144 144
145 m_log.DebugFormat( 145 m_log.DebugFormat(
146 "[LOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest); 146 "[LOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest);
147 147
148 if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile)) 148 if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile))
149 { 149 {
150 return logResponse.CreateLoginFailedResponse(); 150 return logResponse.CreateLoginFailedResponse();
151 } 151 }
152 } 152 }
153 else 153 else
154 { 154 {
155 m_log.Info( 155 m_log.Info(
156 "[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data"); 156 "[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data");
157 157
158 return logResponse.CreateGridErrorResponse(); 158 return logResponse.CreateGridErrorResponse();
159 } 159 }
160 160
161 if (userProfile.GodLevel < m_minLoginLevel) 161 if (userProfile.GodLevel < m_minLoginLevel)
162 { 162 {
163 return logResponse.CreateLoginBlockedResponse(); 163 return logResponse.CreateLoginBlockedResponse();
164 } 164 }
165 else 165 else
166 { 166 {
167 // If we already have a session... 167 // If we already have a session...
168 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline) 168 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline)
169 { 169 {
170 //TODO: The following statements can cause trouble: 170 //TODO: The following statements can cause trouble:
171 // If agentOnline could not turn from true back to false normally 171 // If agentOnline could not turn from true back to false normally
172 // because of some problem, for instance, the crashment of server or client, 172 // because of some problem, for instance, the crashment of server or client,
173 // the user cannot log in any longer. 173 // the user cannot log in any longer.
174 userProfile.CurrentAgent.AgentOnline = false; 174 userProfile.CurrentAgent.AgentOnline = false;
175 175
176 m_userManager.CommitAgent(ref userProfile); 176 m_userManager.CommitAgent(ref userProfile);
177 177
178 // try to tell the region that their user is dead. 178 // try to tell the region that their user is dead.
179 LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location"); 179 LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location");
180 180
181 // Reject the login 181 // Reject the login
182 182
183 m_log.InfoFormat( 183 m_log.InfoFormat(
184 "[LOGIN END]: XMLRPC Notifying user {0} {1} that they are already logged in", 184 "[LOGIN END]: XMLRPC Notifying user {0} {1} that they are already logged in",
185 firstname, lastname); 185 firstname, lastname);
186 186
187 return logResponse.CreateAlreadyLoggedInResponse(); 187 return logResponse.CreateAlreadyLoggedInResponse();
188 } 188 }
189 189
190 // Otherwise... 190 // Otherwise...
191 // Create a new agent session 191 // Create a new agent session
192 192
193 m_userManager.ResetAttachments(userProfile.ID); 193 m_userManager.ResetAttachments(userProfile.ID);
194 194
195 CreateAgent(userProfile, request); 195 CreateAgent(userProfile, request);
196 196
197 try 197 try
198 { 198 {
199 UUID agentID = userProfile.ID; 199 UUID agentID = userProfile.ID;
200 InventoryData inventData; 200 InventoryData inventData;
201 201
202 try 202 try
203 { 203 {
204 inventData = GetInventorySkeleton(agentID); 204 inventData = GetInventorySkeleton(agentID);
205 } 205 }
206 catch (Exception e) 206 catch (Exception e)
207 { 207 {
208 m_log.ErrorFormat( 208 m_log.ErrorFormat(
209 "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}", 209 "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}",
210 agentID, e); 210 agentID, e);
211 211
212 return logResponse.CreateLoginInventoryFailedResponse(); 212 return logResponse.CreateLoginInventoryFailedResponse();
213 } 213 }
214 214
215 ArrayList AgentInventoryArray = inventData.InventoryArray; 215 ArrayList AgentInventoryArray = inventData.InventoryArray;
216 216
217 Hashtable InventoryRootHash = new Hashtable(); 217 Hashtable InventoryRootHash = new Hashtable();
218 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); 218 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
219 ArrayList InventoryRoot = new ArrayList(); 219 ArrayList InventoryRoot = new ArrayList();
220 InventoryRoot.Add(InventoryRootHash); 220 InventoryRoot.Add(InventoryRootHash);
221 userProfile.RootInventoryFolderID = inventData.RootFolderID; 221 userProfile.RootInventoryFolderID = inventData.RootFolderID;
222 222
223 // Inventory Library Section 223 // Inventory Library Section
224 Hashtable InventoryLibRootHash = new Hashtable(); 224 Hashtable InventoryLibRootHash = new Hashtable();
225 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; 225 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
226 ArrayList InventoryLibRoot = new ArrayList(); 226 ArrayList InventoryLibRoot = new ArrayList();
227 InventoryLibRoot.Add(InventoryLibRootHash); 227 InventoryLibRoot.Add(InventoryLibRootHash);
228 228
229 logResponse.InventoryLibRoot = InventoryLibRoot; 229 logResponse.InventoryLibRoot = InventoryLibRoot;
230 logResponse.InventoryLibraryOwner = GetLibraryOwner(); 230 logResponse.InventoryLibraryOwner = GetLibraryOwner();
231 logResponse.InventoryRoot = InventoryRoot; 231 logResponse.InventoryRoot = InventoryRoot;
232 logResponse.InventorySkeleton = AgentInventoryArray; 232 logResponse.InventorySkeleton = AgentInventoryArray;
233 logResponse.InventoryLibrary = GetInventoryLibrary(); 233 logResponse.InventoryLibrary = GetInventoryLibrary();
234 234
235 logResponse.CircuitCode = Util.RandomClass.Next(); 235 logResponse.CircuitCode = Util.RandomClass.Next();
236 logResponse.Lastname = userProfile.SurName; 236 logResponse.Lastname = userProfile.SurName;
237 logResponse.Firstname = userProfile.FirstName; 237 logResponse.Firstname = userProfile.FirstName;
238 logResponse.AgentID = agentID; 238 logResponse.AgentID = agentID;
239 logResponse.SessionID = userProfile.CurrentAgent.SessionID; 239 logResponse.SessionID = userProfile.CurrentAgent.SessionID;
240 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID; 240 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
241 logResponse.Message = GetMessage(); 241 logResponse.Message = GetMessage();
242 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); 242 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
243 logResponse.StartLocation = startLocationRequest; 243 logResponse.StartLocation = startLocationRequest;
244 244
245 if (CustomiseResponse(logResponse, userProfile, startLocationRequest)) 245 if (CustomiseResponse(logResponse, userProfile, startLocationRequest))
246 { 246 {
247 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime; 247 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
248 CommitAgent(ref userProfile); 248 CommitAgent(ref userProfile);
249 249
250 // If we reach this point, then the login has successfully logged onto the grid 250 // If we reach this point, then the login has successfully logged onto the grid
251 if (StatsManager.UserStats != null) 251 if (StatsManager.UserStats != null)
252 StatsManager.UserStats.AddSuccessfulLogin(); 252 StatsManager.UserStats.AddSuccessfulLogin();
253 253
254 m_log.DebugFormat( 254 m_log.DebugFormat(
255 "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.", 255 "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.",
256 firstname, lastname); 256 firstname, lastname);
257 257
258 return logResponse.ToXmlRpcResponse(); 258 return logResponse.ToXmlRpcResponse();
259 } 259 }
260 else 260 else
261 { 261 {
262 m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname); 262 m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname);
263 return logResponse.CreateDeadRegionResponse(); 263 return logResponse.CreateDeadRegionResponse();
264 } 264 }
265 } 265 }
266 catch (Exception e) 266 catch (Exception e)
267 { 267 {
268 m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e); 268 m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e);
269 m_log.Error(e.StackTrace); 269 m_log.Error(e.StackTrace);
270 } 270 }
271 } 271 }
272 272
273 m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response"); 273 m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response");
274 return response; 274 return response;
275 } 275 }
276 finally 276 finally
277 { 277 {
278 m_loginMutex.ReleaseMutex(); 278 m_loginMutex.ReleaseMutex();
279 } 279 }
280 } 280 }
281 281
282 protected virtual bool TryAuthenticateXmlRpcLogin(XmlRpcRequest request, string firstname, string lastname, out UserProfileData userProfile) 282 protected virtual bool TryAuthenticateXmlRpcLogin(XmlRpcRequest request, string firstname, string lastname, out UserProfileData userProfile)
283 { 283 {
284 Hashtable requestData = (Hashtable)request.Params[0]; 284 Hashtable requestData = (Hashtable)request.Params[0];
285 285
286 bool GoodLogin = false; 286 bool GoodLogin = false;
287 287
288 userProfile = GetTheUser(firstname, lastname); 288 userProfile = GetTheUser(firstname, lastname);
289 if (userProfile == null) 289 if (userProfile == null)
290 { 290 {
291 m_log.Info("[LOGIN END]: XMLRPC Could not find a profile for " + firstname + " " + lastname); 291 m_log.Info("[LOGIN END]: XMLRPC Could not find a profile for " + firstname + " " + lastname);
292 } 292 }
293 else 293 else
294 { 294 {
295 if (requestData.Contains("passwd")) 295 if (requestData.Contains("passwd"))
296 { 296 {
297 string passwd = (string)requestData["passwd"]; 297 string passwd = (string)requestData["passwd"];
298 GoodLogin = AuthenticateUser(userProfile, passwd); 298 GoodLogin = AuthenticateUser(userProfile, passwd);
299 } 299 }
300 if (!GoodLogin && (requestData.Contains("web_login_key"))) 300 if (!GoodLogin && (requestData.Contains("web_login_key")))
301 { 301 {
302 try 302 try
303 { 303 {
304 UUID webloginkey = new UUID((string)requestData["web_login_key"]); 304 UUID webloginkey = new UUID((string)requestData["web_login_key"]);
305 GoodLogin = AuthenticateUser(userProfile, webloginkey); 305 GoodLogin = AuthenticateUser(userProfile, webloginkey);
306 } 306 }
307 catch (Exception e) 307 catch (Exception e)
308 { 308 {
309 m_log.InfoFormat( 309 m_log.InfoFormat(
310 "[LOGIN END]: XMLRPC Bad web_login_key: {0} for user {1} {2}, exception {3}", 310 "[LOGIN END]: XMLRPC Bad web_login_key: {0} for user {1} {2}, exception {3}",
311 requestData["web_login_key"], firstname, lastname, e); 311 requestData["web_login_key"], firstname, lastname, e);
312 } 312 }
313 } 313 }
314 } 314 }
315 315
316 return GoodLogin; 316 return GoodLogin;
317 } 317 }
318 318
319 protected virtual bool TryAuthenticateLLSDLogin(string firstname, string lastname, string passwd, out UserProfileData userProfile) 319 protected virtual bool TryAuthenticateLLSDLogin(string firstname, string lastname, string passwd, out UserProfileData userProfile)
320 { 320 {
321 bool GoodLogin = false; 321 bool GoodLogin = false;
322 userProfile = GetTheUser(firstname, lastname); 322 userProfile = GetTheUser(firstname, lastname);
323 if (userProfile == null) 323 if (userProfile == null)
324 { 324 {
325 m_log.Info("[LOGIN]: LLSD Could not find a profile for " + firstname + " " + lastname); 325 m_log.Info("[LOGIN]: LLSD Could not find a profile for " + firstname + " " + lastname);
326 326
327 return false; 327 return false;
328 } 328 }
329 329
330 GoodLogin = AuthenticateUser(userProfile, passwd); 330 GoodLogin = AuthenticateUser(userProfile, passwd);
331 return GoodLogin; 331 return GoodLogin;
332 } 332 }
333 333
334 /// <summary> 334 /// <summary>
335 /// Called when we receive the client's initial LLSD login_to_simulator request message 335 /// Called when we receive the client's initial LLSD login_to_simulator request message
336 /// </summary> 336 /// </summary>
337 /// <param name="request">The LLSD request</param> 337 /// <param name="request">The LLSD request</param>
338 /// <returns>The response to send</returns> 338 /// <returns>The response to send</returns>
339 public OSD LLSDLoginMethod(OSD request) 339 public OSD LLSDLoginMethod(OSD request)
340 { 340 {
341 // Temporary fix 341 // Temporary fix
342 m_loginMutex.WaitOne(); 342 m_loginMutex.WaitOne();
343 343
344 try 344 try
345 { 345 {
346 // bool GoodLogin = false; 346 // bool GoodLogin = false;
347 347
348 string startLocationRequest = "last"; 348 string startLocationRequest = "last";
349 349
350 UserProfileData userProfile = null; 350 UserProfileData userProfile = null;
351 LoginResponse logResponse = new LoginResponse(); 351 LoginResponse logResponse = new LoginResponse();
352 352
353 if (request.Type == OSDType.Map) 353 if (request.Type == OSDType.Map)
354 { 354 {
355 OSDMap map = (OSDMap)request; 355 OSDMap map = (OSDMap)request;
356 356
357 if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd")) 357 if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd"))
358 { 358 {
359 string firstname = map["first"].AsString(); 359 string firstname = map["first"].AsString();
360 string lastname = map["last"].AsString(); 360 string lastname = map["last"].AsString();
361 string passwd = map["passwd"].AsString(); 361 string passwd = map["passwd"].AsString();
362 362
363 if (map.ContainsKey("start")) 363 if (map.ContainsKey("start"))
364 { 364 {
365 m_log.Info("[LOGIN]: LLSD StartLocation Requested: " + map["start"].AsString()); 365 m_log.Info("[LOGIN]: LLSD StartLocation Requested: " + map["start"].AsString());
366 startLocationRequest = map["start"].AsString(); 366 startLocationRequest = map["start"].AsString();
367 } 367 }
368 m_log.Info("[LOGIN]: LLSD Login Requested for: '" + firstname + "' '" + lastname + "' / " + passwd); 368 m_log.Info("[LOGIN]: LLSD Login Requested for: '" + firstname + "' '" + lastname + "' / " + passwd);
369 369
370 if (!TryAuthenticateLLSDLogin(firstname, lastname, passwd, out userProfile)) 370 if (!TryAuthenticateLLSDLogin(firstname, lastname, passwd, out userProfile))
371 { 371 {
372 return logResponse.CreateLoginFailedResponseLLSD(); 372 return logResponse.CreateLoginFailedResponseLLSD();
373 } 373 }
374 } 374 }
375 else 375 else
376 return logResponse.CreateLoginFailedResponseLLSD(); 376 return logResponse.CreateLoginFailedResponseLLSD();
377 } 377 }
378 else 378 else
379 return logResponse.CreateLoginFailedResponseLLSD(); 379 return logResponse.CreateLoginFailedResponseLLSD();
380 380
381 381
382 if (userProfile.GodLevel < m_minLoginLevel) 382 if (userProfile.GodLevel < m_minLoginLevel)
383 { 383 {
384 return logResponse.CreateLoginBlockedResponseLLSD(); 384 return logResponse.CreateLoginBlockedResponseLLSD();
385 } 385 }
386 else 386 else
387 { 387 {
388 // If we already have a session... 388 // If we already have a session...
389 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline) 389 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline)
390 { 390 {
391 userProfile.CurrentAgent.AgentOnline = false; 391 userProfile.CurrentAgent.AgentOnline = false;
392 392
393 m_userManager.CommitAgent(ref userProfile); 393 m_userManager.CommitAgent(ref userProfile);
394 // try to tell the region that their user is dead. 394 // try to tell the region that their user is dead.
395 LogOffUser(userProfile, " LLSD You were logged off because you logged in from another location"); 395 LogOffUser(userProfile, " LLSD You were logged off because you logged in from another location");
396 396
397 // Reject the login 397 // Reject the login
398 398
399 m_log.InfoFormat( 399 m_log.InfoFormat(
400 "[LOGIN END]: LLSD Notifying user {0} {1} that they are already logged in", 400 "[LOGIN END]: LLSD Notifying user {0} {1} that they are already logged in",
401 userProfile.FirstName, userProfile.SurName); 401 userProfile.FirstName, userProfile.SurName);
402 402
403 userProfile.CurrentAgent = null; 403 userProfile.CurrentAgent = null;
404 return logResponse.CreateAlreadyLoggedInResponseLLSD(); 404 return logResponse.CreateAlreadyLoggedInResponseLLSD();
405 } 405 }
406 406
407 // Otherwise... 407 // Otherwise...
408 // Create a new agent session 408 // Create a new agent session
409 409
410 m_userManager.ResetAttachments(userProfile.ID); 410 m_userManager.ResetAttachments(userProfile.ID);
411 411
412 CreateAgent(userProfile, request); 412 CreateAgent(userProfile, request);
413 413
414 try 414 try
415 { 415 {
416 UUID agentID = userProfile.ID; 416 UUID agentID = userProfile.ID;
417 417
418 //InventoryData inventData = GetInventorySkeleton(agentID); 418 //InventoryData inventData = GetInventorySkeleton(agentID);
419 InventoryData inventData = null; 419 InventoryData inventData = null;
420 420
421 try 421 try
422 { 422 {
423 inventData = GetInventorySkeleton(agentID); 423 inventData = GetInventorySkeleton(agentID);
424 } 424 }
425 catch (Exception e) 425 catch (Exception e)
426 { 426 {
427 m_log.ErrorFormat( 427 m_log.ErrorFormat(
428 "[LOGIN END]: LLSD Error retrieving inventory skeleton of agent {0}, {1} - {2}", 428 "[LOGIN END]: LLSD Error retrieving inventory skeleton of agent {0}, {1} - {2}",
429 agentID, e.GetType(), e.Message); 429 agentID, e.GetType(), e.Message);
430 430
431 return logResponse.CreateLoginFailedResponseLLSD();// .CreateLoginInventoryFailedResponseLLSD (); 431 return logResponse.CreateLoginFailedResponseLLSD();// .CreateLoginInventoryFailedResponseLLSD ();
432 } 432 }
433 433
434 434
435 ArrayList AgentInventoryArray = inventData.InventoryArray; 435 ArrayList AgentInventoryArray = inventData.InventoryArray;
436 436
437 Hashtable InventoryRootHash = new Hashtable(); 437 Hashtable InventoryRootHash = new Hashtable();
438 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); 438 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
439 ArrayList InventoryRoot = new ArrayList(); 439 ArrayList InventoryRoot = new ArrayList();
440 InventoryRoot.Add(InventoryRootHash); 440 InventoryRoot.Add(InventoryRootHash);
441 userProfile.RootInventoryFolderID = inventData.RootFolderID; 441 userProfile.RootInventoryFolderID = inventData.RootFolderID;
442 442
443 443
444 // Inventory Library Section 444 // Inventory Library Section
445 Hashtable InventoryLibRootHash = new Hashtable(); 445 Hashtable InventoryLibRootHash = new Hashtable();
446 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; 446 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
447 ArrayList InventoryLibRoot = new ArrayList(); 447 ArrayList InventoryLibRoot = new ArrayList();
448 InventoryLibRoot.Add(InventoryLibRootHash); 448 InventoryLibRoot.Add(InventoryLibRootHash);
449 449
450 logResponse.InventoryLibRoot = InventoryLibRoot; 450 logResponse.InventoryLibRoot = InventoryLibRoot;
451 logResponse.InventoryLibraryOwner = GetLibraryOwner(); 451 logResponse.InventoryLibraryOwner = GetLibraryOwner();
452 logResponse.InventoryRoot = InventoryRoot; 452 logResponse.InventoryRoot = InventoryRoot;
453 logResponse.InventorySkeleton = AgentInventoryArray; 453 logResponse.InventorySkeleton = AgentInventoryArray;
454 logResponse.InventoryLibrary = GetInventoryLibrary(); 454 logResponse.InventoryLibrary = GetInventoryLibrary();
455 455
456 logResponse.CircuitCode = (Int32)Util.RandomClass.Next(); 456 logResponse.CircuitCode = (Int32)Util.RandomClass.Next();
457 logResponse.Lastname = userProfile.SurName; 457 logResponse.Lastname = userProfile.SurName;
458 logResponse.Firstname = userProfile.FirstName; 458 logResponse.Firstname = userProfile.FirstName;
459 logResponse.AgentID = agentID; 459 logResponse.AgentID = agentID;
460 logResponse.SessionID = userProfile.CurrentAgent.SessionID; 460 logResponse.SessionID = userProfile.CurrentAgent.SessionID;
461 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID; 461 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
462 logResponse.Message = GetMessage(); 462 logResponse.Message = GetMessage();
463 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); 463 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
464 logResponse.StartLocation = startLocationRequest; 464 logResponse.StartLocation = startLocationRequest;
465 465
466 try 466 try
467 { 467 {
468 CustomiseResponse(logResponse, userProfile, startLocationRequest); 468 CustomiseResponse(logResponse, userProfile, startLocationRequest);
469 } 469 }
470 catch (Exception ex) 470 catch (Exception ex)
471 { 471 {
472 m_log.Info("[LOGIN]: LLSD " + ex.ToString()); 472 m_log.Info("[LOGIN]: LLSD " + ex.ToString());
473 return logResponse.CreateDeadRegionResponseLLSD(); 473 return logResponse.CreateDeadRegionResponseLLSD();
474 } 474 }
475 475
476 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime; 476 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
477 CommitAgent(ref userProfile); 477 CommitAgent(ref userProfile);
478 478
479 // If we reach this point, then the login has successfully logged onto the grid 479 // If we reach this point, then the login has successfully logged onto the grid
480 if (StatsManager.UserStats != null) 480 if (StatsManager.UserStats != null)
481 StatsManager.UserStats.AddSuccessfulLogin(); 481 StatsManager.UserStats.AddSuccessfulLogin();
482 482
483 m_log.DebugFormat( 483 m_log.DebugFormat(
484 "[LOGIN END]: LLSD Authentication of user {0} {1} successful. Sending response to client.", 484 "[LOGIN END]: LLSD Authentication of user {0} {1} successful. Sending response to client.",
485 userProfile.FirstName, userProfile.SurName); 485 userProfile.FirstName, userProfile.SurName);
486 486
487 return logResponse.ToLLSDResponse(); 487 return logResponse.ToLLSDResponse();
488 } 488 }
489 catch (Exception ex) 489 catch (Exception ex)
490 { 490 {
491 m_log.Info("[LOGIN]: LLSD " + ex.ToString()); 491 m_log.Info("[LOGIN]: LLSD " + ex.ToString());
492 return logResponse.CreateFailedResponseLLSD(); 492 return logResponse.CreateFailedResponseLLSD();
493 } 493 }
494 } 494 }
495 } 495 }
496 finally 496 finally
497 { 497 {
498 m_loginMutex.ReleaseMutex(); 498 m_loginMutex.ReleaseMutex();
499 } 499 }
500 } 500 }
501 501
502 public Hashtable ProcessHTMLLogin(Hashtable keysvals) 502 public Hashtable ProcessHTMLLogin(Hashtable keysvals)
503 { 503 {
504 // Matches all unspecified characters 504 // Matches all unspecified characters
505 // Currently specified,; lowercase letters, upper case letters, numbers, underline 505 // Currently specified,; lowercase letters, upper case letters, numbers, underline
506 // period, space, parens, and dash. 506 // period, space, parens, and dash.
507 507
508 Regex wfcut = new Regex("[^a-zA-Z0-9_\\.\\$ \\(\\)\\-]"); 508 Regex wfcut = new Regex("[^a-zA-Z0-9_\\.\\$ \\(\\)\\-]");
509 509
510 Hashtable returnactions = new Hashtable(); 510 Hashtable returnactions = new Hashtable();
511 int statuscode = 200; 511 int statuscode = 200;
512 512
513 string firstname = String.Empty; 513 string firstname = String.Empty;
514 string lastname = String.Empty; 514 string lastname = String.Empty;
515 string location = String.Empty; 515 string location = String.Empty;
516 string region = String.Empty; 516 string region = String.Empty;
517 string grid = String.Empty; 517 string grid = String.Empty;
518 string channel = String.Empty; 518 string channel = String.Empty;
519 string version = String.Empty; 519 string version = String.Empty;
520 string lang = String.Empty; 520 string lang = String.Empty;
521 string password = String.Empty; 521 string password = String.Empty;
522 string errormessages = String.Empty; 522 string errormessages = String.Empty;
523 523
524 // the client requires the HTML form field be named 'username' 524 // the client requires the HTML form field be named 'username'
525 // however, the data it sends when it loads the first time is 'firstname' 525 // however, the data it sends when it loads the first time is 'firstname'
526 // another one of those little nuances. 526 // another one of those little nuances.
527 527
528 if (keysvals.Contains("firstname")) 528 if (keysvals.Contains("firstname"))
529 firstname = wfcut.Replace((string)keysvals["firstname"], String.Empty, 99999); 529 firstname = wfcut.Replace((string)keysvals["firstname"], String.Empty, 99999);
530 530
531 if (keysvals.Contains("username")) 531 if (keysvals.Contains("username"))
532 firstname = wfcut.Replace((string)keysvals["username"], String.Empty, 99999); 532 firstname = wfcut.Replace((string)keysvals["username"], String.Empty, 99999);
533 533
534 if (keysvals.Contains("lastname")) 534 if (keysvals.Contains("lastname"))
535 lastname = wfcut.Replace((string)keysvals["lastname"], String.Empty, 99999); 535 lastname = wfcut.Replace((string)keysvals["lastname"], String.Empty, 99999);
536 536
537 if (keysvals.Contains("location")) 537 if (keysvals.Contains("location"))
538 location = wfcut.Replace((string)keysvals["location"], String.Empty, 99999); 538 location = wfcut.Replace((string)keysvals["location"], String.Empty, 99999);
539 539
540 if (keysvals.Contains("region")) 540 if (keysvals.Contains("region"))
541 region = wfcut.Replace((string)keysvals["region"], String.Empty, 99999); 541 region = wfcut.Replace((string)keysvals["region"], String.Empty, 99999);
542 542
543 if (keysvals.Contains("grid")) 543 if (keysvals.Contains("grid"))
544 grid = wfcut.Replace((string)keysvals["grid"], String.Empty, 99999); 544 grid = wfcut.Replace((string)keysvals["grid"], String.Empty, 99999);
545 545
546 if (keysvals.Contains("channel")) 546 if (keysvals.Contains("channel"))
547 channel = wfcut.Replace((string)keysvals["channel"], String.Empty, 99999); 547 channel = wfcut.Replace((string)keysvals["channel"], String.Empty, 99999);
548 548
549 if (keysvals.Contains("version")) 549 if (keysvals.Contains("version"))
550 version = wfcut.Replace((string)keysvals["version"], String.Empty, 99999); 550 version = wfcut.Replace((string)keysvals["version"], String.Empty, 99999);
551 551
552 if (keysvals.Contains("lang")) 552 if (keysvals.Contains("lang"))
553 lang = wfcut.Replace((string)keysvals["lang"], String.Empty, 99999); 553 lang = wfcut.Replace((string)keysvals["lang"], String.Empty, 99999);
554 554
555 if (keysvals.Contains("password")) 555 if (keysvals.Contains("password"))
556 password = wfcut.Replace((string)keysvals["password"], String.Empty, 99999); 556 password = wfcut.Replace((string)keysvals["password"], String.Empty, 99999);
557 557
558 // load our login form. 558 // load our login form.
559 string loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages); 559 string loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
560 560
561 if (keysvals.ContainsKey("show_login_form")) 561 if (keysvals.ContainsKey("show_login_form"))
562 { 562 {
563 UserProfileData user = GetTheUser(firstname, lastname); 563 UserProfileData user = GetTheUser(firstname, lastname);
564 bool goodweblogin = false; 564 bool goodweblogin = false;
565 565
566 if (user != null) 566 if (user != null)
567 goodweblogin = AuthenticateUser(user, password); 567 goodweblogin = AuthenticateUser(user, password);
568 568
569 if (goodweblogin) 569 if (goodweblogin)
570 { 570 {
571 UUID webloginkey = UUID.Random(); 571 UUID webloginkey = UUID.Random();
572 m_userManager.StoreWebLoginKey(user.ID, webloginkey); 572 m_userManager.StoreWebLoginKey(user.ID, webloginkey);
573 //statuscode = 301; 573 //statuscode = 301;
574 574
575 // string redirectURL = "about:blank?redirect-http-hack=" + 575 // string redirectURL = "about:blank?redirect-http-hack=" +
576 // HttpUtility.UrlEncode("secondlife:///app/login?first_name=" + firstname + "&last_name=" + 576 // HttpUtility.UrlEncode("secondlife:///app/login?first_name=" + firstname + "&last_name=" +
577 // lastname + 577 // lastname +
578 // "&location=" + location + "&grid=Other&web_login_key=" + webloginkey.ToString()); 578 // "&location=" + location + "&grid=Other&web_login_key=" + webloginkey.ToString());
579 //m_log.Info("[WEB]: R:" + redirectURL); 579 //m_log.Info("[WEB]: R:" + redirectURL);
580 returnactions["int_response_code"] = statuscode; 580 returnactions["int_response_code"] = statuscode;
581 //returnactions["str_redirect_location"] = redirectURL; 581 //returnactions["str_redirect_location"] = redirectURL;
582 //returnactions["str_response_string"] = "<HTML><BODY>GoodLogin</BODY></HTML>"; 582 //returnactions["str_response_string"] = "<HTML><BODY>GoodLogin</BODY></HTML>";
583 returnactions["str_response_string"] = webloginkey.ToString(); 583 returnactions["str_response_string"] = webloginkey.ToString();
584 } 584 }
585 else 585 else
586 { 586 {
587 errormessages = "The Username and password supplied did not match our records. Check your caps lock and try again"; 587 errormessages = "The Username and password supplied did not match our records. Check your caps lock and try again";
588 588
589 loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages); 589 loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
590 returnactions["int_response_code"] = statuscode; 590 returnactions["int_response_code"] = statuscode;
591 returnactions["str_response_string"] = loginform; 591 returnactions["str_response_string"] = loginform;
592 } 592 }
593 } 593 }
594 else 594 else
595 { 595 {
596 returnactions["int_response_code"] = statuscode; 596 returnactions["int_response_code"] = statuscode;
597 returnactions["str_response_string"] = loginform; 597 returnactions["str_response_string"] = loginform;
598 } 598 }
599 return returnactions; 599 return returnactions;
600 } 600 }
601 601
602 public string GetLoginForm(string firstname, string lastname, string location, string region, 602 public string GetLoginForm(string firstname, string lastname, string location, string region,
603 string grid, string channel, string version, string lang, 603 string grid, string channel, string version, string lang,
604 string password, string errormessages) 604 string password, string errormessages)
605 { 605 {
606 // inject our values in the form at the markers 606 // inject our values in the form at the markers
607 607
608 string loginform = String.Empty; 608 string loginform = String.Empty;
609 string file = Path.Combine(Util.configDir(), "http_loginform.html"); 609 string file = Path.Combine(Util.configDir(), "http_loginform.html");
610 if (!File.Exists(file)) 610 if (!File.Exists(file))
611 { 611 {
612 loginform = GetDefaultLoginForm(); 612 loginform = GetDefaultLoginForm();
613 } 613 }
614 else 614 else
615 { 615 {
616 StreamReader sr = File.OpenText(file); 616 StreamReader sr = File.OpenText(file);
617 loginform = sr.ReadToEnd(); 617 loginform = sr.ReadToEnd();
618 sr.Close(); 618 sr.Close();
619 } 619 }
620 620
621 loginform = loginform.Replace("[$firstname]", firstname); 621 loginform = loginform.Replace("[$firstname]", firstname);
622 loginform = loginform.Replace("[$lastname]", lastname); 622 loginform = loginform.Replace("[$lastname]", lastname);
623 loginform = loginform.Replace("[$location]", location); 623 loginform = loginform.Replace("[$location]", location);
624 loginform = loginform.Replace("[$region]", region); 624 loginform = loginform.Replace("[$region]", region);
625 loginform = loginform.Replace("[$grid]", grid); 625 loginform = loginform.Replace("[$grid]", grid);
626 loginform = loginform.Replace("[$channel]", channel); 626 loginform = loginform.Replace("[$channel]", channel);
627 loginform = loginform.Replace("[$version]", version); 627 loginform = loginform.Replace("[$version]", version);
628 loginform = loginform.Replace("[$lang]", lang); 628 loginform = loginform.Replace("[$lang]", lang);
629 loginform = loginform.Replace("[$password]", password); 629 loginform = loginform.Replace("[$password]", password);
630 loginform = loginform.Replace("[$errors]", errormessages); 630 loginform = loginform.Replace("[$errors]", errormessages);
631 631
632 return loginform; 632 return loginform;
633 } 633 }
634 634
635 public string GetDefaultLoginForm() 635 public string GetDefaultLoginForm()
636 { 636 {
637 string responseString = 637 string responseString =
638 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"; 638 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
639 responseString += "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; 639 responseString += "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
640 responseString += "<head>"; 640 responseString += "<head>";
641 responseString += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"; 641 responseString += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";
642 responseString += "<meta http-equiv=\"cache-control\" content=\"no-cache\">"; 642 responseString += "<meta http-equiv=\"cache-control\" content=\"no-cache\">";
643 responseString += "<meta http-equiv=\"Pragma\" content=\"no-cache\">"; 643 responseString += "<meta http-equiv=\"Pragma\" content=\"no-cache\">";
644 responseString += "<title>OpenSim Login</title>"; 644 responseString += "<title>OpenSim Login</title>";
645 responseString += "<body><br />"; 645 responseString += "<body><br />";
646 responseString += "<div id=\"login_box\">"; 646 responseString += "<div id=\"login_box\">";
647 647
648 responseString += "<form action=\"/go.cgi\" method=\"GET\" id=\"login-form\">"; 648 responseString += "<form action=\"/go.cgi\" method=\"GET\" id=\"login-form\">";
649 649
650 responseString += "<div id=\"message\">[$errors]</div>"; 650 responseString += "<div id=\"message\">[$errors]</div>";
651 responseString += "<fieldset id=\"firstname\">"; 651 responseString += "<fieldset id=\"firstname\">";
652 responseString += "<legend>First Name:</legend>"; 652 responseString += "<legend>First Name:</legend>";
653 responseString += "<input type=\"text\" id=\"firstname_input\" size=\"15\" maxlength=\"100\" name=\"username\" value=\"[$firstname]\" />"; 653 responseString += "<input type=\"text\" id=\"firstname_input\" size=\"15\" maxlength=\"100\" name=\"username\" value=\"[$firstname]\" />";
654 responseString += "</fieldset>"; 654 responseString += "</fieldset>";
655 responseString += "<fieldset id=\"lastname\">"; 655 responseString += "<fieldset id=\"lastname\">";
656 responseString += "<legend>Last Name:</legend>"; 656 responseString += "<legend>Last Name:</legend>";
657 responseString += "<input type=\"text\" size=\"15\" maxlength=\"100\" name=\"lastname\" value=\"[$lastname]\" />"; 657 responseString += "<input type=\"text\" size=\"15\" maxlength=\"100\" name=\"lastname\" value=\"[$lastname]\" />";
658 responseString += "</fieldset>"; 658 responseString += "</fieldset>";
659 responseString += "<fieldset id=\"password\">"; 659 responseString += "<fieldset id=\"password\">";
660 responseString += "<legend>Password:</legend>"; 660 responseString += "<legend>Password:</legend>";
661 responseString += "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">"; 661 responseString += "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">";
662 responseString += "<tr>"; 662 responseString += "<tr>";
663 responseString += "<td colspan=\"2\"><input type=\"password\" size=\"15\" maxlength=\"100\" name=\"password\" value=\"[$password]\" /></td>"; 663 responseString += "<td colspan=\"2\"><input type=\"password\" size=\"15\" maxlength=\"100\" name=\"password\" value=\"[$password]\" /></td>";
664 responseString += "</tr>"; 664 responseString += "</tr>";
665 responseString += "<tr>"; 665 responseString += "<tr>";
666 responseString += "<td valign=\"middle\"><input type=\"checkbox\" name=\"remember_password\" id=\"remember_password\" [$remember_password] style=\"margin-left:0px;\"/></td>"; 666 responseString += "<td valign=\"middle\"><input type=\"checkbox\" name=\"remember_password\" id=\"remember_password\" [$remember_password] style=\"margin-left:0px;\"/></td>";
667 responseString += "<td><label for=\"remember_password\">Remember password</label></td>"; 667 responseString += "<td><label for=\"remember_password\">Remember password</label></td>";
668 responseString += "</tr>"; 668 responseString += "</tr>";
669 responseString += "</table>"; 669 responseString += "</table>";
670 responseString += "</fieldset>"; 670 responseString += "</fieldset>";
671 responseString += "<input type=\"hidden\" name=\"show_login_form\" value=\"FALSE\" />"; 671 responseString += "<input type=\"hidden\" name=\"show_login_form\" value=\"FALSE\" />";
672 responseString += "<input type=\"hidden\" name=\"method\" value=\"login\" />"; 672 responseString += "<input type=\"hidden\" name=\"method\" value=\"login\" />";
673 responseString += "<input type=\"hidden\" id=\"grid\" name=\"grid\" value=\"[$grid]\" />"; 673 responseString += "<input type=\"hidden\" id=\"grid\" name=\"grid\" value=\"[$grid]\" />";
674 responseString += "<input type=\"hidden\" id=\"region\" name=\"region\" value=\"[$region]\" />"; 674 responseString += "<input type=\"hidden\" id=\"region\" name=\"region\" value=\"[$region]\" />";
675 responseString += "<input type=\"hidden\" id=\"location\" name=\"location\" value=\"[$location]\" />"; 675 responseString += "<input type=\"hidden\" id=\"location\" name=\"location\" value=\"[$location]\" />";
676 responseString += "<input type=\"hidden\" id=\"channel\" name=\"channel\" value=\"[$channel]\" />"; 676 responseString += "<input type=\"hidden\" id=\"channel\" name=\"channel\" value=\"[$channel]\" />";
677 responseString += "<input type=\"hidden\" id=\"version\" name=\"version\" value=\"[$version]\" />"; 677 responseString += "<input type=\"hidden\" id=\"version\" name=\"version\" value=\"[$version]\" />";
678 responseString += "<input type=\"hidden\" id=\"lang\" name=\"lang\" value=\"[$lang]\" />"; 678 responseString += "<input type=\"hidden\" id=\"lang\" name=\"lang\" value=\"[$lang]\" />";
679 responseString += "<div id=\"submitbtn\">"; 679 responseString += "<div id=\"submitbtn\">";
680 responseString += "<input class=\"input_over\" type=\"submit\" value=\"Connect\" />"; 680 responseString += "<input class=\"input_over\" type=\"submit\" value=\"Connect\" />";
681 responseString += "</div>"; 681 responseString += "</div>";
682 responseString += "<div id=\"connecting\" style=\"visibility:hidden\"> Connecting...</div>"; 682 responseString += "<div id=\"connecting\" style=\"visibility:hidden\"> Connecting...</div>";
683 683
684 responseString += "<div id=\"helplinks\"><!---"; 684 responseString += "<div id=\"helplinks\"><!---";
685 responseString += "<a href=\"#join now link\" target=\"_blank\"></a> | "; 685 responseString += "<a href=\"#join now link\" target=\"_blank\"></a> | ";
686 responseString += "<a href=\"#forgot password link\" target=\"_blank\"></a>"; 686 responseString += "<a href=\"#forgot password link\" target=\"_blank\"></a>";
687 responseString += "---></div>"; 687 responseString += "---></div>";
688 688
689 responseString += "<div id=\"channelinfo\"> [$channel] | [$version]=[$lang]</div>"; 689 responseString += "<div id=\"channelinfo\"> [$channel] | [$version]=[$lang]</div>";
690 responseString += "</form>"; 690 responseString += "</form>";
691 responseString += "<script language=\"JavaScript\">"; 691 responseString += "<script language=\"JavaScript\">";
692 responseString += "document.getElementById('firstname_input').focus();"; 692 responseString += "document.getElementById('firstname_input').focus();";
693 responseString += "</script>"; 693 responseString += "</script>";
694 responseString += "</div>"; 694 responseString += "</div>";
695 responseString += "</div>"; 695 responseString += "</div>";
696 responseString += "</body>"; 696 responseString += "</body>";
697 responseString += "</html>"; 697 responseString += "</html>";
698 698
699 return responseString; 699 return responseString;
700 } 700 }
701 701
702 /// <summary> 702 /// <summary>
703 /// Saves a target agent to the database 703 /// Saves a target agent to the database
704 /// </summary> 704 /// </summary>
705 /// <param name="profile">The users profile</param> 705 /// <param name="profile">The users profile</param>
706 /// <returns>Successful?</returns> 706 /// <returns>Successful?</returns>
707 public bool CommitAgent(ref UserProfileData profile) 707 public bool CommitAgent(ref UserProfileData profile)
708 { 708 {
709 return m_userManager.CommitAgent(ref profile); 709 return m_userManager.CommitAgent(ref profile);
710 } 710 }
711 711
712 /// <summary> 712 /// <summary>
713 /// Checks a user against it's password hash 713 /// Checks a user against it's password hash
714 /// </summary> 714 /// </summary>
715 /// <param name="profile">The users profile</param> 715 /// <param name="profile">The users profile</param>
716 /// <param name="password">The supplied password</param> 716 /// <param name="password">The supplied password</param>
717 /// <returns>Authenticated?</returns> 717 /// <returns>Authenticated?</returns>
718 public virtual bool AuthenticateUser(UserProfileData profile, string password) 718 public virtual bool AuthenticateUser(UserProfileData profile, string password)
719 { 719 {
720 bool passwordSuccess = false; 720 bool passwordSuccess = false;
721 //m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID); 721 //m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID);
722 722
723 // Web Login method seems to also occasionally send the hashed password itself 723 // Web Login method seems to also occasionally send the hashed password itself
724 724
725 // we do this to get our hash in a form that the server password code can consume 725 // we do this to get our hash in a form that the server password code can consume
726 // when the web-login-form submits the password in the clear (supposed to be over SSL!) 726 // when the web-login-form submits the password in the clear (supposed to be over SSL!)
727 if (!password.StartsWith("$1$")) 727 if (!password.StartsWith("$1$"))
728 password = "$1$" + Util.Md5Hash(password); 728 password = "$1$" + Util.Md5Hash(password);
729 729
730 password = password.Remove(0, 3); //remove $1$ 730 password = password.Remove(0, 3); //remove $1$
731 731
732 string s = Util.Md5Hash(password + ":" + profile.PasswordSalt); 732 string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
733 // Testing... 733 // Testing...
734 //m_log.Info("[LOGIN]: SubHash:" + s + " userprofile:" + profile.passwordHash); 734 //m_log.Info("[LOGIN]: SubHash:" + s + " userprofile:" + profile.passwordHash);
735 //m_log.Info("[LOGIN]: userprofile:" + profile.passwordHash + " SubCT:" + password); 735 //m_log.Info("[LOGIN]: userprofile:" + profile.passwordHash + " SubCT:" + password);
736 736
737 passwordSuccess = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase) 737 passwordSuccess = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
738 || profile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase)); 738 || profile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
739 739
740 return passwordSuccess; 740 return passwordSuccess;
741 } 741 }
742 742
743 public virtual bool AuthenticateUser(UserProfileData profile, UUID webloginkey) 743 public virtual bool AuthenticateUser(UserProfileData profile, UUID webloginkey)
744 { 744 {
745 bool passwordSuccess = false; 745 bool passwordSuccess = false;
746 m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID); 746 m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID);
747 747
748 // Match web login key unless it's the default weblogin key UUID.Zero 748 // Match web login key unless it's the default weblogin key UUID.Zero
749 passwordSuccess = ((profile.WebLoginKey == webloginkey) && profile.WebLoginKey != UUID.Zero); 749 passwordSuccess = ((profile.WebLoginKey == webloginkey) && profile.WebLoginKey != UUID.Zero);
750 750
751 return passwordSuccess; 751 return passwordSuccess;
752 } 752 }
753 753
754 /// <summary> 754 /// <summary>
755 /// 755 ///
756 /// </summary> 756 /// </summary>
757 /// <param name="profile"></param> 757 /// <param name="profile"></param>
758 /// <param name="request"></param> 758 /// <param name="request"></param>
759 public void CreateAgent(UserProfileData profile, XmlRpcRequest request) 759 public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
760 { 760 {
761 m_userManager.CreateAgent(profile, request); 761 m_userManager.CreateAgent(profile, request);
762 } 762 }
763 763
764 public void CreateAgent(UserProfileData profile, OSD request) 764 public void CreateAgent(UserProfileData profile, OSD request)
765 { 765 {
766 m_userManager.CreateAgent(profile, request); 766 m_userManager.CreateAgent(profile, request);
767 } 767 }
768 768
769 /// <summary> 769 /// <summary>
770 /// 770 ///
771 /// </summary> 771 /// </summary>
772 /// <param name="firstname"></param> 772 /// <param name="firstname"></param>
773 /// <param name="lastname"></param> 773 /// <param name="lastname"></param>
774 /// <returns></returns> 774 /// <returns></returns>
775 public virtual UserProfileData GetTheUser(string firstname, string lastname) 775 public virtual UserProfileData GetTheUser(string firstname, string lastname)
776 { 776 {
777 return m_userManager.GetUserProfile(firstname, lastname); 777 return m_userManager.GetUserProfile(firstname, lastname);
778 } 778 }
779 779
780 /// <summary> 780 /// <summary>
781 /// 781 ///
782 /// </summary> 782 /// </summary>
783 /// <returns></returns> 783 /// <returns></returns>
784 public virtual string GetMessage() 784 public virtual string GetMessage()
785 { 785 {
786 return m_welcomeMessage; 786 return m_welcomeMessage;
787 } 787 }
788 788
789 private static LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL) 789 private static LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL)
790 { 790 {
791 LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList(); 791 LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList();
792 foreach (FriendListItem fl in LFL) 792 foreach (FriendListItem fl in LFL)
793 { 793 {
794 LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend); 794 LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend);
795 buddyitem.BuddyID = fl.Friend; 795 buddyitem.BuddyID = fl.Friend;
796 buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms; 796 buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms;
797 buddyitem.BuddyRightsGiven = (int)fl.FriendPerms; 797 buddyitem.BuddyRightsGiven = (int)fl.FriendPerms;
798 buddylistreturn.AddNewBuddy(buddyitem); 798 buddylistreturn.AddNewBuddy(buddyitem);
799 } 799 }
800 return buddylistreturn; 800 return buddylistreturn;
801 } 801 }
802 802
803 /// <summary> 803 /// <summary>
804 /// Converts the inventory library skeleton into the form required by the rpc request. 804 /// Converts the inventory library skeleton into the form required by the rpc request.
805 /// </summary> 805 /// </summary>
806 /// <returns></returns> 806 /// <returns></returns>
807 protected virtual ArrayList GetInventoryLibrary() 807 protected virtual ArrayList GetInventoryLibrary()
808 { 808 {
809 Dictionary<UUID, InventoryFolderImpl> rootFolders 809 Dictionary<UUID, InventoryFolderImpl> rootFolders
810 = m_libraryRootFolder.RequestSelfAndDescendentFolders(); 810 = m_libraryRootFolder.RequestSelfAndDescendentFolders();
811 ArrayList folderHashes = new ArrayList(); 811 ArrayList folderHashes = new ArrayList();
812 812
813 foreach (InventoryFolderBase folder in rootFolders.Values) 813 foreach (InventoryFolderBase folder in rootFolders.Values)
814 { 814 {
815 Hashtable TempHash = new Hashtable(); 815 Hashtable TempHash = new Hashtable();
816 TempHash["name"] = folder.Name; 816 TempHash["name"] = folder.Name;
817 TempHash["parent_id"] = folder.ParentID.ToString(); 817 TempHash["parent_id"] = folder.ParentID.ToString();
818 TempHash["version"] = (Int32)folder.Version; 818 TempHash["version"] = (Int32)folder.Version;
819 TempHash["type_default"] = (Int32)folder.Type; 819 TempHash["type_default"] = (Int32)folder.Type;
820 TempHash["folder_id"] = folder.ID.ToString(); 820 TempHash["folder_id"] = folder.ID.ToString();
821 folderHashes.Add(TempHash); 821 folderHashes.Add(TempHash);
822 } 822 }
823 823
824 return folderHashes; 824 return folderHashes;
825 } 825 }
826 826
827 /// <summary> 827 /// <summary>
828 /// 828 ///
829 /// </summary> 829 /// </summary>
830 /// <returns></returns> 830 /// <returns></returns>
831 protected virtual ArrayList GetLibraryOwner() 831 protected virtual ArrayList GetLibraryOwner()
832 { 832 {
833 //for now create random inventory library owner 833 //for now create random inventory library owner
834 Hashtable TempHash = new Hashtable(); 834 Hashtable TempHash = new Hashtable();
835 TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000"; 835 TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000";
836 ArrayList inventoryLibOwner = new ArrayList(); 836 ArrayList inventoryLibOwner = new ArrayList();
837 inventoryLibOwner.Add(TempHash); 837 inventoryLibOwner.Add(TempHash);
838 return inventoryLibOwner; 838 return inventoryLibOwner;
839 } 839 }
840 840
841 public class InventoryData 841 public class InventoryData
842 { 842 {
843 public ArrayList InventoryArray = null; 843 public ArrayList InventoryArray = null;
844 public UUID RootFolderID = UUID.Zero; 844 public UUID RootFolderID = UUID.Zero;
845 845
846 public InventoryData(ArrayList invList, UUID rootID) 846 public InventoryData(ArrayList invList, UUID rootID)
847 { 847 {
848 InventoryArray = invList; 848 InventoryArray = invList;
849 RootFolderID = rootID; 849 RootFolderID = rootID;
850 } 850 }
851 } 851 }
852 852
853 protected void SniffLoginKey(Uri uri, Hashtable requestData) 853 protected void SniffLoginKey(Uri uri, Hashtable requestData)
854 { 854 {
855 string uri_str = uri.ToString(); 855 string uri_str = uri.ToString();
856 string[] parts = uri_str.Split(new char[] { '=' }); 856 string[] parts = uri_str.Split(new char[] { '=' });
857 if (parts.Length > 1) 857 if (parts.Length > 1)
858 { 858 {
859 string web_login_key = parts[1]; 859 string web_login_key = parts[1];
860 requestData.Add("web_login_key", web_login_key); 860 requestData.Add("web_login_key", web_login_key);
861 m_log.InfoFormat("[LOGIN]: Login with web_login_key {0}", web_login_key); 861 m_log.InfoFormat("[LOGIN]: Login with web_login_key {0}", web_login_key);
862 } 862 }
863 } 863 }
864 864
865 /// <summary> 865 /// <summary>
866 /// Customises the login response and fills in missing values. This method also tells the login region to 866 /// Customises the login response and fills in missing values. This method also tells the login region to
867 /// expect a client connection. 867 /// expect a client connection.
868 /// </summary> 868 /// </summary>
869 /// <param name="response">The existing response</param> 869 /// <param name="response">The existing response</param>
870 /// <param name="theUser">The user profile</param> 870 /// <param name="theUser">The user profile</param>
871 /// <param name="startLocationRequest">The requested start location</param> 871 /// <param name="startLocationRequest">The requested start location</param>
872 /// <returns>true on success, false if the region was not successfully told to expect a user connection</returns> 872 /// <returns>true on success, false if the region was not successfully told to expect a user connection</returns>
873 public bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest) 873 public bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest)
874 { 874 {
875 // add active gestures to login-response 875 // add active gestures to login-response
876 AddActiveGestures(response, theUser); 876 AddActiveGestures(response, theUser);
877 877
878 // HomeLocation 878 // HomeLocation
879 RegionInfo homeInfo = null; 879 RegionInfo homeInfo = null;
880 880
881 // use the homeRegionID if it is stored already. If not, use the regionHandle as before 881 // use the homeRegionID if it is stored already. If not, use the regionHandle as before
882 UUID homeRegionId = theUser.HomeRegionID; 882 UUID homeRegionId = theUser.HomeRegionID;
883 ulong homeRegionHandle = theUser.HomeRegion; 883 ulong homeRegionHandle = theUser.HomeRegion;
884 if (homeRegionId != UUID.Zero) 884 if (homeRegionId != UUID.Zero)
885 { 885 {
886 homeInfo = GetRegionInfo(homeRegionId); 886 homeInfo = GetRegionInfo(homeRegionId);
887 } 887 }
888 else 888 else
889 { 889 {
890 homeInfo = GetRegionInfo(homeRegionHandle); 890 homeInfo = GetRegionInfo(homeRegionHandle);
891 } 891 }
892 892
893 if (homeInfo != null) 893 if (homeInfo != null)
894 { 894 {
895 response.Home = 895 response.Home =
896 string.Format( 896 string.Format(
897 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", 897 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
898 (homeInfo.RegionLocX * Constants.RegionSize), 898 (homeInfo.RegionLocX * Constants.RegionSize),
899 (homeInfo.RegionLocY * Constants.RegionSize), 899 (homeInfo.RegionLocY * Constants.RegionSize),
900 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, 900 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z,
901 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); 901 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z);
902 } 902 }
903 else 903 else
904 { 904 {
905 m_log.InfoFormat("not found the region at {0} {1}", theUser.HomeRegionX, theUser.HomeRegionY); 905 m_log.InfoFormat("not found the region at {0} {1}", theUser.HomeRegionX, theUser.HomeRegionY);
906 // Emergency mode: Home-region isn't available, so we can't request the region info. 906 // Emergency mode: Home-region isn't available, so we can't request the region info.
907 // Use the stored home regionHandle instead. 907 // Use the stored home regionHandle instead.
908 // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again 908 // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again
909 ulong regionX = homeRegionHandle >> 32; 909 ulong regionX = homeRegionHandle >> 32;
910 ulong regionY = homeRegionHandle & 0xffffffff; 910 ulong regionY = homeRegionHandle & 0xffffffff;
911 response.Home = 911 response.Home =
912 string.Format( 912 string.Format(
913 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", 913 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
914 regionX, regionY, 914 regionX, regionY,
915 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, 915 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z,
916 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); 916 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z);
917 917
918 m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}", 918 m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}",
919 theUser.FirstName, theUser.SurName, 919 theUser.FirstName, theUser.SurName,
920 regionX, regionY); 920 regionX, regionY);
921 } 921 }
922 922
923 // StartLocation 923 // StartLocation
924 RegionInfo regionInfo = null; 924 RegionInfo regionInfo = null;
925 if (startLocationRequest == "home") 925 if (startLocationRequest == "home")
926 { 926 {
927 regionInfo = homeInfo; 927 regionInfo = homeInfo;
928 theUser.CurrentAgent.Position = theUser.HomeLocation; 928 theUser.CurrentAgent.Position = theUser.HomeLocation;
929 response.LookAt = "[r" + theUser.HomeLookAt.X.ToString() + ",r" + theUser.HomeLookAt.Y.ToString() + ",r" + theUser.HomeLookAt.Z.ToString() + "]"; 929 response.LookAt = "[r" + theUser.HomeLookAt.X.ToString() + ",r" + theUser.HomeLookAt.Y.ToString() + ",r" + theUser.HomeLookAt.Z.ToString() + "]";
930 } 930 }
931 else if (startLocationRequest == "last") 931 else if (startLocationRequest == "last")
932 { 932 {
933 UUID lastRegion = theUser.CurrentAgent.Region; 933 UUID lastRegion = theUser.CurrentAgent.Region;
934 regionInfo = GetRegionInfo(lastRegion); 934 regionInfo = GetRegionInfo(lastRegion);
935 response.LookAt = "[r" + theUser.CurrentAgent.LookAt.X.ToString() + ",r" + theUser.CurrentAgent.LookAt.Y.ToString() + ",r" + theUser.CurrentAgent.LookAt.Z.ToString() + "]"; 935 response.LookAt = "[r" + theUser.CurrentAgent.LookAt.X.ToString() + ",r" + theUser.CurrentAgent.LookAt.Y.ToString() + ",r" + theUser.CurrentAgent.LookAt.Z.ToString() + "]";
936 } 936 }
937 else 937 else
938 { 938 {
939 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); 939 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
940 Match uriMatch = reURI.Match(startLocationRequest); 940 Match uriMatch = reURI.Match(startLocationRequest);
941 if (uriMatch == null) 941 if (uriMatch == null)
942 { 942 {
943 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest); 943 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest);
944 } 944 }
945 else 945 else
946 { 946 {
947 string region = uriMatch.Groups["region"].ToString(); 947 string region = uriMatch.Groups["region"].ToString();
948 regionInfo = RequestClosestRegion(region); 948 regionInfo = RequestClosestRegion(region);
949 if (regionInfo == null) 949 if (regionInfo == null)
950 { 950 {
951 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region); 951 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region);
952 } 952 }
953 else 953 else
954 { 954 {
955 theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value), 955 theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value),
956 float.Parse(uriMatch.Groups["y"].Value), float.Parse(uriMatch.Groups["z"].Value)); 956 float.Parse(uriMatch.Groups["y"].Value), float.Parse(uriMatch.Groups["z"].Value));
957 } 957 }
958 } 958 }
959 response.LookAt = "[r0,r1,r0]"; 959 response.LookAt = "[r0,r1,r0]";
960 // can be: last, home, safe, url 960 // can be: last, home, safe, url
961 response.StartLocation = "url"; 961 response.StartLocation = "url";
962 } 962 }
963 963
964 if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response))) 964 if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response)))
965 { 965 {
966 return true; 966 return true;
967 } 967 }
968 968
969 // StartLocation not available, send him to a nearby region instead 969 // StartLocation not available, send him to a nearby region instead
970 // regionInfo = m_gridService.RequestClosestRegion(""); 970 // regionInfo = m_gridService.RequestClosestRegion("");
971 //m_log.InfoFormat("[LOGIN]: StartLocation not available sending to region {0}", regionInfo.regionName); 971 //m_log.InfoFormat("[LOGIN]: StartLocation not available sending to region {0}", regionInfo.regionName);
972 972
973 // Send him to default region instead 973 // Send him to default region instead
974 ulong defaultHandle = (((ulong)m_defaultHomeX * Constants.RegionSize) << 32) | 974 ulong defaultHandle = (((ulong)m_defaultHomeX * Constants.RegionSize) << 32) |
975 ((ulong)m_defaultHomeY * Constants.RegionSize); 975 ((ulong)m_defaultHomeY * Constants.RegionSize);
976 976
977 if ((regionInfo != null) && (defaultHandle == regionInfo.RegionHandle)) 977 if ((regionInfo != null) && (defaultHandle == regionInfo.RegionHandle))
978 { 978 {
979 m_log.ErrorFormat("[LOGIN]: Not trying the default region since this is the same as the selected region"); 979 m_log.ErrorFormat("[LOGIN]: Not trying the default region since this is the same as the selected region");
980 return false; 980 return false;
981 } 981 }
982 982
983 m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead"); 983 m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead");
984 regionInfo = GetRegionInfo(defaultHandle); 984 regionInfo = GetRegionInfo(defaultHandle);
985 985
986 if (regionInfo == null) 986 if (regionInfo == null)
987 { 987 {
988 m_log.ErrorFormat("[LOGIN]: No default region available. Aborting."); 988 m_log.ErrorFormat("[LOGIN]: No default region available. Aborting.");
989 return false; 989 return false;
990 } 990 }
991 991
992 theUser.CurrentAgent.Position = new Vector3(128, 128, 0); 992 theUser.CurrentAgent.Position = new Vector3(128, 128, 0);
993 response.StartLocation = "safe"; 993 response.StartLocation = "safe";
994 994
995 return PrepareLoginToRegion(regionInfo, theUser, response); 995 return PrepareLoginToRegion(regionInfo, theUser, response);
996 } 996 }
997 997
998 protected abstract RegionInfo RequestClosestRegion(string region); 998 protected abstract RegionInfo RequestClosestRegion(string region);
999 protected abstract RegionInfo GetRegionInfo(ulong homeRegionHandle); 999 protected abstract RegionInfo GetRegionInfo(ulong homeRegionHandle);
1000 protected abstract RegionInfo GetRegionInfo(UUID homeRegionId); 1000 protected abstract RegionInfo GetRegionInfo(UUID homeRegionId);
1001 protected abstract bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response); 1001 protected abstract bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response);
1002 1002
1003 /// <summary> 1003 /// <summary>
1004 /// Add active gestures of the user to the login response. 1004 /// Add active gestures of the user to the login response.
1005 /// </summary> 1005 /// </summary>
1006 /// <param name="response"> 1006 /// <param name="response">
1007 /// A <see cref="LoginResponse"/> 1007 /// A <see cref="LoginResponse"/>
1008 /// </param> 1008 /// </param>
1009 /// <param name="theUser"> 1009 /// <param name="theUser">
1010 /// A <see cref="UserProfileData"/> 1010 /// A <see cref="UserProfileData"/>
1011 /// </param> 1011 /// </param>
1012 protected void AddActiveGestures(LoginResponse response, UserProfileData theUser) 1012 protected void AddActiveGestures(LoginResponse response, UserProfileData theUser)
1013 { 1013 {
1014 List<InventoryItemBase> gestures = m_inventoryService.GetActiveGestures(theUser.ID); 1014 List<InventoryItemBase> gestures = m_inventoryService.GetActiveGestures(theUser.ID);
1015 //m_log.DebugFormat("[LOGIN]: AddActiveGestures, found {0}", gestures == null ? 0 : gestures.Count); 1015 //m_log.DebugFormat("[LOGIN]: AddActiveGestures, found {0}", gestures == null ? 0 : gestures.Count);
1016 ArrayList list = new ArrayList(); 1016 ArrayList list = new ArrayList();
1017 if (gestures != null) 1017 if (gestures != null)
1018 { 1018 {
1019 foreach (InventoryItemBase gesture in gestures) 1019 foreach (InventoryItemBase gesture in gestures)
1020 { 1020 {
1021 Hashtable item = new Hashtable(); 1021 Hashtable item = new Hashtable();
1022 item["item_id"] = gesture.ID.ToString(); 1022 item["item_id"] = gesture.ID.ToString();
1023 item["asset_id"] = gesture.AssetID.ToString(); 1023 item["asset_id"] = gesture.AssetID.ToString();
1024 list.Add(item); 1024 list.Add(item);
1025 } 1025 }
1026 } 1026 }
1027 response.ActiveGestures = list; 1027 response.ActiveGestures = list;
1028 } 1028 }
1029 1029
1030 /// <summary> 1030 /// <summary>
1031 /// Get the initial login inventory skeleton (in other words, the folder structure) for the given user. 1031 /// Get the initial login inventory skeleton (in other words, the folder structure) for the given user.
1032 /// </summary> 1032 /// </summary>
1033 /// <param name="userID"></param> 1033 /// <param name="userID"></param>
1034 /// <returns></returns> 1034 /// <returns></returns>
1035 /// <exception cref='System.Exception'>This will be thrown if there is a problem with the inventory service</exception> 1035 /// <exception cref='System.Exception'>This will be thrown if there is a problem with the inventory service</exception>
1036 protected InventoryData GetInventorySkeleton(UUID userID) 1036 protected InventoryData GetInventorySkeleton(UUID userID)
1037 { 1037 {
1038 List<InventoryFolderBase> folders = m_inventoryService.GetInventorySkeleton(userID); 1038 List<InventoryFolderBase> folders = m_inventoryService.GetInventorySkeleton(userID);
1039 1039
1040 // If we have user auth but no inventory folders for some reason, create a new set of folders. 1040 // If we have user auth but no inventory folders for some reason, create a new set of folders.
1041 if (folders == null || folders.Count == 0) 1041 if (folders == null || folders.Count == 0)
1042 { 1042 {
1043 m_log.InfoFormat( 1043 m_log.InfoFormat(
1044 "[LOGIN]: A root inventory folder for user {0} was not found. Requesting creation.", userID); 1044 "[LOGIN]: A root inventory folder for user {0} was not found. Requesting creation.", userID);
1045 1045
1046 // Although the create user function creates a new agent inventory along with a new user profile, some 1046 // Although the create user function creates a new agent inventory along with a new user profile, some
1047 // tools are creating the user profile directly in the database without creating the inventory. At 1047 // tools are creating the user profile directly in the database without creating the inventory. At
1048 // this time we'll accomodate them by lazily creating the user inventory now if it doesn't already 1048 // this time we'll accomodate them by lazily creating the user inventory now if it doesn't already
1049 // exist. 1049 // exist.
1050 if (!m_inventoryService.CreateNewUserInventory(userID)) 1050 if (!m_inventoryService.CreateNewUserInventory(userID))
1051 { 1051 {
1052 throw new Exception( 1052 throw new Exception(
1053 String.Format( 1053 String.Format(
1054 "The inventory creation request for user {0} did not succeed." 1054 "The inventory creation request for user {0} did not succeed."
1055 + " Please contact your inventory service provider for more information.", 1055 + " Please contact your inventory service provider for more information.",
1056 userID)); 1056 userID));
1057 } 1057 }
1058 1058
1059 m_log.InfoFormat("[LOGIN]: A new inventory skeleton was successfully created for user {0}", userID); 1059 m_log.InfoFormat("[LOGIN]: A new inventory skeleton was successfully created for user {0}", userID);
1060 1060
1061 folders = m_inventoryService.GetInventorySkeleton(userID); 1061 folders = m_inventoryService.GetInventorySkeleton(userID);
1062 1062
1063 if (folders == null || folders.Count == 0) 1063 if (folders == null || folders.Count == 0)
1064 { 1064 {
1065 throw new Exception( 1065 throw new Exception(
1066 String.Format( 1066 String.Format(
1067 "A root inventory folder for user {0} could not be retrieved from the inventory service", 1067 "A root inventory folder for user {0} could not be retrieved from the inventory service",
1068 userID)); 1068 userID));
1069 } 1069 }
1070 } 1070 }
1071 1071
1072 UUID rootID = UUID.Zero; 1072 UUID rootID = UUID.Zero;
1073 ArrayList AgentInventoryArray = new ArrayList(); 1073 ArrayList AgentInventoryArray = new ArrayList();
1074 Hashtable TempHash; 1074 Hashtable TempHash;
1075 foreach (InventoryFolderBase InvFolder in folders) 1075 foreach (InventoryFolderBase InvFolder in folders)
1076 { 1076 {
1077 if (InvFolder.ParentID == UUID.Zero) 1077 if (InvFolder.ParentID == UUID.Zero)
1078 { 1078 {
1079 rootID = InvFolder.ID; 1079 rootID = InvFolder.ID;
1080 } 1080 }
1081 TempHash = new Hashtable(); 1081 TempHash = new Hashtable();
1082 TempHash["name"] = InvFolder.Name; 1082 TempHash["name"] = InvFolder.Name;
1083 TempHash["parent_id"] = InvFolder.ParentID.ToString(); 1083 TempHash["parent_id"] = InvFolder.ParentID.ToString();
1084 TempHash["version"] = (Int32)InvFolder.Version; 1084 TempHash["version"] = (Int32)InvFolder.Version;
1085 TempHash["type_default"] = (Int32)InvFolder.Type; 1085 TempHash["type_default"] = (Int32)InvFolder.Type;
1086 TempHash["folder_id"] = InvFolder.ID.ToString(); 1086 TempHash["folder_id"] = InvFolder.ID.ToString();
1087 AgentInventoryArray.Add(TempHash); 1087 AgentInventoryArray.Add(TempHash);
1088 } 1088 }
1089 1089
1090 return new InventoryData(AgentInventoryArray, rootID); 1090 return new InventoryData(AgentInventoryArray, rootID);
1091 } 1091 }
1092 } 1092 }
1093} 1093}