clockwerk-opensim – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections; |
||
30 | using System.Collections.Generic; |
||
31 | using System.Linq; |
||
32 | using System.Net; |
||
33 | using System.Reflection; |
||
34 | using System.Text.RegularExpressions; |
||
35 | |||
36 | using log4net; |
||
37 | using Nini.Config; |
||
38 | using OpenMetaverse; |
||
39 | |||
40 | using OpenSim.Framework; |
||
41 | using OpenSim.Framework.Console; |
||
42 | using OpenSim.Server.Base; |
||
43 | using OpenSim.Services.Interfaces; |
||
44 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; |
||
45 | using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; |
||
46 | using OpenSim.Services.Connectors.Hypergrid; |
||
47 | |||
48 | namespace OpenSim.Services.LLLoginService |
||
49 | { |
||
50 | public class LLLoginService : ILoginService |
||
51 | { |
||
52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
53 | private static readonly string LogHeader = "[LLOGIN SERVICE]"; |
||
54 | |||
55 | private static bool Initialized = false; |
||
56 | |||
57 | protected IUserAccountService m_UserAccountService; |
||
58 | protected IGridUserService m_GridUserService; |
||
59 | protected IAuthenticationService m_AuthenticationService; |
||
60 | protected IInventoryService m_InventoryService; |
||
61 | protected IInventoryService m_HGInventoryService; |
||
62 | protected IGridService m_GridService; |
||
63 | protected IPresenceService m_PresenceService; |
||
64 | protected ISimulationService m_LocalSimulationService; |
||
65 | protected ISimulationService m_RemoteSimulationService; |
||
66 | protected ILibraryService m_LibraryService; |
||
67 | protected IFriendsService m_FriendsService; |
||
68 | protected IAvatarService m_AvatarService; |
||
69 | protected IUserAgentService m_UserAgentService; |
||
70 | |||
71 | protected GatekeeperServiceConnector m_GatekeeperConnector; |
||
72 | |||
73 | protected string m_DefaultRegionName; |
||
74 | protected string m_WelcomeMessage; |
||
75 | protected bool m_RequireInventory; |
||
76 | protected int m_MinLoginLevel; |
||
77 | protected string m_GatekeeperURL; |
||
78 | protected bool m_AllowRemoteSetLoginLevel; |
||
79 | protected string m_MapTileURL; |
||
80 | protected string m_SearchURL; |
||
81 | protected string m_Currency; |
||
82 | protected string m_ClassifiedFee; |
||
83 | protected string m_DestinationGuide; |
||
84 | protected string m_AvatarPicker; |
||
85 | |||
86 | protected string m_AllowedClients; |
||
87 | protected string m_DeniedClients; |
||
88 | |||
89 | protected string m_DSTZone; |
||
90 | |||
91 | IConfig m_LoginServerConfig; |
||
92 | // IConfig m_ClientsConfig; |
||
93 | |||
94 | public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService) |
||
95 | { |
||
96 | m_LoginServerConfig = config.Configs["LoginService"]; |
||
97 | if (m_LoginServerConfig == null) |
||
98 | throw new Exception(String.Format("No section LoginService in config file")); |
||
99 | |||
100 | string accountService = m_LoginServerConfig.GetString("UserAccountService", String.Empty); |
||
101 | string gridUserService = m_LoginServerConfig.GetString("GridUserService", String.Empty); |
||
102 | string agentService = m_LoginServerConfig.GetString("UserAgentService", String.Empty); |
||
103 | string authService = m_LoginServerConfig.GetString("AuthenticationService", String.Empty); |
||
104 | string invService = m_LoginServerConfig.GetString("InventoryService", String.Empty); |
||
105 | string gridService = m_LoginServerConfig.GetString("GridService", String.Empty); |
||
106 | string presenceService = m_LoginServerConfig.GetString("PresenceService", String.Empty); |
||
107 | string libService = m_LoginServerConfig.GetString("LibraryService", String.Empty); |
||
108 | string friendsService = m_LoginServerConfig.GetString("FriendsService", String.Empty); |
||
109 | string avatarService = m_LoginServerConfig.GetString("AvatarService", String.Empty); |
||
110 | string simulationService = m_LoginServerConfig.GetString("SimulationService", String.Empty); |
||
111 | |||
112 | m_DefaultRegionName = m_LoginServerConfig.GetString("DefaultRegion", String.Empty); |
||
113 | m_WelcomeMessage = m_LoginServerConfig.GetString("WelcomeMessage", "Welcome to OpenSim!"); |
||
114 | m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true); |
||
115 | m_AllowRemoteSetLoginLevel = m_LoginServerConfig.GetBoolean("AllowRemoteSetLoginLevel", false); |
||
116 | m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0); |
||
117 | m_GatekeeperURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", |
||
118 | new string[] { "Startup", "Hypergrid", "LoginService" }, String.Empty); |
||
119 | m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); |
||
120 | m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); |
||
121 | m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty); |
||
122 | m_ClassifiedFee = m_LoginServerConfig.GetString("ClassifiedFee", string.Empty); |
||
123 | m_DestinationGuide = m_LoginServerConfig.GetString ("DestinationGuide", string.Empty); |
||
124 | m_AvatarPicker = m_LoginServerConfig.GetString ("AvatarPicker", string.Empty); |
||
125 | |||
126 | m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); |
||
127 | m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); |
||
128 | |||
129 | m_DSTZone = m_LoginServerConfig.GetString("DSTZone", "America/Los_Angeles;Pacific Standard Time"); |
||
130 | |||
131 | // Clean up some of these vars |
||
132 | if (m_MapTileURL != String.Empty) |
||
133 | { |
||
134 | m_MapTileURL = m_MapTileURL.Trim(); |
||
135 | if (!m_MapTileURL.EndsWith("/")) |
||
136 | m_MapTileURL = m_MapTileURL + "/"; |
||
137 | } |
||
138 | |||
139 | // These are required; the others aren't |
||
140 | if (accountService == string.Empty || authService == string.Empty) |
||
141 | throw new Exception("LoginService is missing service specifications"); |
||
142 | |||
143 | // replace newlines in welcome message |
||
144 | m_WelcomeMessage = m_WelcomeMessage.Replace("\\n", "\n"); |
||
145 | |||
146 | Object[] args = new Object[] { config }; |
||
147 | m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); |
||
148 | m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); |
||
149 | m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args); |
||
150 | m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); |
||
151 | |||
152 | if (gridService != string.Empty) |
||
153 | m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); |
||
154 | if (presenceService != string.Empty) |
||
155 | m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); |
||
156 | if (avatarService != string.Empty) |
||
157 | m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarService, args); |
||
158 | if (friendsService != string.Empty) |
||
159 | m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args); |
||
160 | if (simulationService != string.Empty) |
||
161 | m_RemoteSimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args); |
||
162 | if (agentService != string.Empty) |
||
163 | m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(agentService, args); |
||
164 | |||
165 | // Get the Hypergrid inventory service (exists only if Hypergrid is enabled) |
||
166 | string hgInvServicePlugin = m_LoginServerConfig.GetString("HGInventoryServicePlugin", String.Empty); |
||
167 | if (hgInvServicePlugin != string.Empty) |
||
168 | { |
||
169 | string hgInvServiceArg = m_LoginServerConfig.GetString("HGInventoryServiceConstructorArg", String.Empty); |
||
170 | Object[] args2 = new Object[] { config, hgInvServiceArg }; |
||
171 | m_HGInventoryService = ServerUtils.LoadPlugin<IInventoryService>(hgInvServicePlugin, args2); |
||
172 | } |
||
173 | |||
174 | // |
||
175 | // deal with the services given as argument |
||
176 | // |
||
177 | m_LocalSimulationService = simService; |
||
178 | if (libraryService != null) |
||
179 | { |
||
180 | m_log.DebugFormat("[LLOGIN SERVICE]: Using LibraryService given as argument"); |
||
181 | m_LibraryService = libraryService; |
||
182 | } |
||
183 | else if (libService != string.Empty) |
||
184 | { |
||
185 | m_log.DebugFormat("[LLOGIN SERVICE]: Using instantiated LibraryService"); |
||
186 | m_LibraryService = ServerUtils.LoadPlugin<ILibraryService>(libService, args); |
||
187 | } |
||
188 | |||
189 | m_GatekeeperConnector = new GatekeeperServiceConnector(); |
||
190 | |||
191 | if (!Initialized) |
||
192 | { |
||
193 | Initialized = true; |
||
194 | RegisterCommands(); |
||
195 | } |
||
196 | |||
197 | m_log.DebugFormat("[LLOGIN SERVICE]: Starting..."); |
||
198 | |||
199 | } |
||
200 | |||
201 | public LLLoginService(IConfigSource config) : this(config, null, null) |
||
202 | { |
||
203 | } |
||
204 | |||
205 | public Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP) |
||
206 | { |
||
207 | Hashtable response = new Hashtable(); |
||
208 | response["success"] = "false"; |
||
209 | |||
210 | if (!m_AllowRemoteSetLoginLevel) |
||
211 | return response; |
||
212 | |||
213 | try |
||
214 | { |
||
215 | UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName); |
||
216 | if (account == null) |
||
217 | { |
||
218 | m_log.InfoFormat("[LLOGIN SERVICE]: Set Level failed, user {0} {1} not found", firstName, lastName); |
||
219 | return response; |
||
220 | } |
||
221 | |||
222 | if (account.UserLevel < 200) |
||
223 | { |
||
224 | m_log.InfoFormat("[LLOGIN SERVICE]: Set Level failed, reason: user level too low"); |
||
225 | return response; |
||
226 | } |
||
227 | |||
228 | // |
||
229 | // Authenticate this user |
||
230 | // |
||
231 | // We don't support clear passwords here |
||
232 | // |
||
233 | string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30); |
||
234 | UUID secureSession = UUID.Zero; |
||
235 | if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) |
||
236 | { |
||
237 | m_log.InfoFormat("[LLOGIN SERVICE]: SetLevel failed, reason: authentication failed"); |
||
238 | return response; |
||
239 | } |
||
240 | } |
||
241 | catch (Exception e) |
||
242 | { |
||
243 | m_log.Error("[LLOGIN SERVICE]: SetLevel failed, exception " + e.ToString()); |
||
244 | return response; |
||
245 | } |
||
246 | |||
247 | m_MinLoginLevel = level; |
||
248 | m_log.InfoFormat("[LLOGIN SERVICE]: Login level set to {0} by {1} {2}", level, firstName, lastName); |
||
249 | |||
250 | response["success"] = true; |
||
251 | return response; |
||
252 | } |
||
253 | |||
254 | public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, |
||
255 | string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP) |
||
256 | { |
||
257 | bool success = false; |
||
258 | UUID session = UUID.Random(); |
||
259 | |||
260 | m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}", |
||
261 | firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0); |
||
262 | |||
263 | try |
||
264 | { |
||
265 | // |
||
266 | // Check client |
||
267 | // |
||
268 | if (m_AllowedClients != string.Empty) |
||
269 | { |
||
270 | Regex arx = new Regex(m_AllowedClients); |
||
271 | Match am = arx.Match(clientVersion); |
||
272 | |||
273 | if (!am.Success) |
||
274 | { |
||
275 | m_log.InfoFormat( |
||
276 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: client {2} is not allowed", |
||
277 | firstName, lastName, clientVersion); |
||
278 | return LLFailedLoginResponse.LoginBlockedProblem; |
||
279 | } |
||
280 | } |
||
281 | |||
282 | if (m_DeniedClients != string.Empty) |
||
283 | { |
||
284 | Regex drx = new Regex(m_DeniedClients); |
||
285 | Match dm = drx.Match(clientVersion); |
||
286 | |||
287 | if (dm.Success) |
||
288 | { |
||
289 | m_log.InfoFormat( |
||
290 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: client {2} is denied", |
||
291 | firstName, lastName, clientVersion); |
||
292 | return LLFailedLoginResponse.LoginBlockedProblem; |
||
293 | } |
||
294 | } |
||
295 | |||
296 | // |
||
297 | // Get the account and check that it exists |
||
298 | // |
||
299 | UserAccount account = m_UserAccountService.GetUserAccount(scopeID, firstName, lastName); |
||
300 | if (account == null) |
||
301 | { |
||
302 | m_log.InfoFormat( |
||
303 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user not found", firstName, lastName); |
||
304 | return LLFailedLoginResponse.UserProblem; |
||
305 | } |
||
306 | |||
307 | if (account.UserLevel < m_MinLoginLevel) |
||
308 | { |
||
309 | m_log.InfoFormat( |
||
310 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}", |
||
311 | firstName, lastName, account.UserLevel, m_MinLoginLevel); |
||
312 | return LLFailedLoginResponse.LoginBlockedProblem; |
||
313 | } |
||
314 | |||
315 | // If a scope id is requested, check that the account is in |
||
316 | // that scope, or unscoped. |
||
317 | // |
||
318 | if (scopeID != UUID.Zero) |
||
319 | { |
||
320 | if (account.ScopeID != scopeID && account.ScopeID != UUID.Zero) |
||
321 | { |
||
322 | m_log.InfoFormat( |
||
323 | "[LLOGIN SERVICE]: Login failed, reason: user {0} {1} not found", firstName, lastName); |
||
324 | return LLFailedLoginResponse.UserProblem; |
||
325 | } |
||
326 | } |
||
327 | else |
||
328 | { |
||
329 | scopeID = account.ScopeID; |
||
330 | } |
||
331 | |||
332 | // |
||
333 | // Authenticate this user |
||
334 | // |
||
335 | if (!passwd.StartsWith("$1$")) |
||
336 | passwd = "$1$" + Util.Md5Hash(passwd); |
||
337 | passwd = passwd.Remove(0, 3); //remove $1$ |
||
338 | string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30); |
||
339 | UUID secureSession = UUID.Zero; |
||
340 | if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) |
||
341 | { |
||
342 | m_log.InfoFormat( |
||
343 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: authentication failed", |
||
344 | firstName, lastName); |
||
345 | return LLFailedLoginResponse.UserProblem; |
||
346 | } |
||
347 | |||
348 | // |
||
349 | // Get the user's inventory |
||
350 | // |
||
351 | if (m_RequireInventory && m_InventoryService == null) |
||
352 | { |
||
353 | m_log.WarnFormat( |
||
354 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: inventory service not set up", |
||
355 | firstName, lastName); |
||
356 | return LLFailedLoginResponse.InventoryProblem; |
||
357 | } |
||
358 | |||
359 | if (m_HGInventoryService != null) |
||
360 | { |
||
361 | // Give the Suitcase service a chance to create the suitcase folder. |
||
362 | // (If we're not using the Suitcase inventory service then this won't do anything.) |
||
363 | m_HGInventoryService.GetRootFolder(account.PrincipalID); |
||
364 | } |
||
365 | |||
366 | List<InventoryFolderBase> inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID); |
||
367 | if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0))) |
||
368 | { |
||
369 | m_log.InfoFormat( |
||
370 | "[LLOGIN SERVICE]: Login failed, for {0} {1}, reason: unable to retrieve user inventory", |
||
371 | firstName, lastName); |
||
372 | return LLFailedLoginResponse.InventoryProblem; |
||
373 | } |
||
374 | |||
375 | // Get active gestures |
||
376 | List<InventoryItemBase> gestures = m_InventoryService.GetActiveGestures(account.PrincipalID); |
||
377 | // m_log.DebugFormat("[LLOGIN SERVICE]: {0} active gestures", gestures.Count); |
||
378 | |||
379 | // |
||
380 | // Login the presence |
||
381 | // |
||
382 | if (m_PresenceService != null) |
||
383 | { |
||
384 | success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession); |
||
385 | |||
386 | if (!success) |
||
387 | { |
||
388 | m_log.InfoFormat( |
||
389 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: could not login presence", |
||
390 | firstName, lastName); |
||
391 | return LLFailedLoginResponse.GridProblem; |
||
392 | } |
||
393 | } |
||
394 | |||
395 | // |
||
396 | // Change Online status and get the home region |
||
397 | // |
||
398 | GridRegion home = null; |
||
399 | GridUserInfo guinfo = m_GridUserService.LoggedIn(account.PrincipalID.ToString()); |
||
400 | |||
401 | // We are only going to complain about no home if the user actually tries to login there, to avoid |
||
402 | // spamming the console. |
||
403 | if (guinfo != null) |
||
404 | { |
||
405 | if (guinfo.HomeRegionID == UUID.Zero && startLocation == "home") |
||
406 | { |
||
407 | m_log.WarnFormat( |
||
408 | "[LLOGIN SERVICE]: User {0} tried to login to a 'home' start location but they have none set", |
||
409 | account.Name); |
||
410 | } |
||
411 | else if (m_GridService != null) |
||
412 | { |
||
413 | home = m_GridService.GetRegionByUUID(scopeID, guinfo.HomeRegionID); |
||
414 | |||
415 | if (home == null && startLocation == "home") |
||
416 | { |
||
417 | m_log.WarnFormat( |
||
418 | "[LLOGIN SERVICE]: User {0} tried to login to a 'home' start location with ID {1} but this was not found.", |
||
419 | account.Name, guinfo.HomeRegionID); |
||
420 | } |
||
421 | } |
||
422 | } |
||
423 | else |
||
424 | { |
||
425 | // something went wrong, make something up, so that we don't have to test this anywhere else |
||
426 | m_log.DebugFormat("{0} Failed to fetch GridUserInfo. Creating empty GridUserInfo as home", LogHeader); |
||
427 | guinfo = new GridUserInfo(); |
||
428 | guinfo.LastPosition = guinfo.HomePosition = new Vector3(128, 128, 30); |
||
429 | } |
||
430 | |||
431 | // |
||
432 | // Find the destination region/grid |
||
433 | // |
||
434 | string where = string.Empty; |
||
435 | Vector3 position = Vector3.Zero; |
||
436 | Vector3 lookAt = Vector3.Zero; |
||
437 | GridRegion gatekeeper = null; |
||
438 | TeleportFlags flags; |
||
439 | GridRegion destination = FindDestination(account, scopeID, guinfo, session, startLocation, home, out gatekeeper, out where, out position, out lookAt, out flags); |
||
440 | if (destination == null) |
||
441 | { |
||
442 | m_PresenceService.LogoutAgent(session); |
||
443 | |||
444 | m_log.InfoFormat( |
||
445 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: destination not found", |
||
446 | firstName, lastName); |
||
447 | return LLFailedLoginResponse.GridProblem; |
||
448 | } |
||
449 | else |
||
450 | { |
||
451 | m_log.DebugFormat( |
||
452 | "[LLOGIN SERVICE]: Found destination {0}, endpoint {1} for {2} {3}", |
||
453 | destination.RegionName, destination.ExternalEndPoint, firstName, lastName); |
||
454 | } |
||
455 | |||
456 | if (account.UserLevel >= 200) |
||
457 | flags |= TeleportFlags.Godlike; |
||
458 | // |
||
459 | // Get the avatar |
||
460 | // |
||
461 | AvatarAppearance avatar = null; |
||
462 | if (m_AvatarService != null) |
||
463 | { |
||
464 | avatar = m_AvatarService.GetAppearance(account.PrincipalID); |
||
465 | } |
||
466 | |||
467 | // |
||
468 | // Instantiate/get the simulation interface and launch an agent at the destination |
||
469 | // |
||
470 | string reason = string.Empty; |
||
471 | GridRegion dest; |
||
472 | AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, |
||
473 | clientVersion, channel, mac, id0, clientIP, flags, out where, out reason, out dest); |
||
474 | destination = dest; |
||
475 | if (aCircuit == null) |
||
476 | { |
||
477 | m_PresenceService.LogoutAgent(session); |
||
478 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed for {0} {1}, reason: {2}", firstName, lastName, reason); |
||
479 | return new LLFailedLoginResponse("key", reason, "false"); |
||
480 | |||
481 | } |
||
482 | // Get Friends list |
||
483 | FriendInfo[] friendsList = new FriendInfo[0]; |
||
484 | if (m_FriendsService != null) |
||
485 | { |
||
486 | friendsList = m_FriendsService.GetFriends(account.PrincipalID); |
||
487 | // m_log.DebugFormat("[LLOGIN SERVICE]: Retrieved {0} friends", friendsList.Length); |
||
488 | } |
||
489 | |||
490 | // |
||
491 | // Finally, fill out the response and return it |
||
492 | // |
||
493 | LLLoginResponse response |
||
494 | = new LLLoginResponse( |
||
495 | account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, |
||
496 | where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, |
||
497 | m_MapTileURL, m_SearchURL, m_Currency, m_DSTZone, |
||
498 | m_DestinationGuide, m_AvatarPicker, m_ClassifiedFee); |
||
499 | |||
500 | m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); |
||
501 | |||
502 | return response; |
||
503 | } |
||
504 | catch (Exception e) |
||
505 | { |
||
506 | m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2} {3}", firstName, lastName, e.ToString(), e.StackTrace); |
||
507 | if (m_PresenceService != null) |
||
508 | m_PresenceService.LogoutAgent(session); |
||
509 | return LLFailedLoginResponse.InternalError; |
||
510 | } |
||
511 | } |
||
512 | |||
513 | protected GridRegion FindDestination( |
||
514 | UserAccount account, UUID scopeID, GridUserInfo pinfo, UUID sessionID, string startLocation, |
||
515 | GridRegion home, out GridRegion gatekeeper, |
||
516 | out string where, out Vector3 position, out Vector3 lookAt, out TeleportFlags flags) |
||
517 | { |
||
518 | flags = TeleportFlags.ViaLogin; |
||
519 | |||
520 | m_log.DebugFormat( |
||
521 | "[LLOGIN SERVICE]: Finding destination matching start location {0} for {1}", |
||
522 | startLocation, account.Name); |
||
523 | |||
524 | gatekeeper = null; |
||
525 | where = "home"; |
||
526 | position = new Vector3(128, 128, 0); |
||
527 | lookAt = new Vector3(0, 1, 0); |
||
528 | |||
529 | if (m_GridService == null) |
||
530 | return null; |
||
531 | |||
532 | if (startLocation.Equals("home")) |
||
533 | { |
||
534 | // logging into home region |
||
535 | if (pinfo == null) |
||
536 | return null; |
||
537 | |||
538 | GridRegion region = null; |
||
539 | |||
540 | bool tryDefaults = false; |
||
541 | |||
542 | if (home == null) |
||
543 | { |
||
544 | tryDefaults = true; |
||
545 | } |
||
546 | else |
||
547 | { |
||
548 | region = home; |
||
549 | |||
550 | position = pinfo.HomePosition; |
||
551 | lookAt = pinfo.HomeLookAt; |
||
552 | flags |= TeleportFlags.ViaHome; |
||
553 | } |
||
554 | |||
555 | if (tryDefaults) |
||
556 | { |
||
557 | List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); |
||
558 | if (defaults != null && defaults.Count > 0) |
||
559 | { |
||
560 | region = defaults[0]; |
||
561 | where = "safe"; |
||
562 | } |
||
563 | else |
||
564 | { |
||
565 | m_log.WarnFormat("[LLOGIN SERVICE]: User {0} {1} does not have a valid home and this grid does not have default locations. Attempting to find random region", |
||
566 | account.FirstName, account.LastName); |
||
567 | region = FindAlternativeRegion(scopeID); |
||
568 | if (region != null) |
||
569 | where = "safe"; |
||
570 | } |
||
571 | } |
||
572 | |||
573 | return region; |
||
574 | } |
||
575 | else if (startLocation.Equals("last")) |
||
576 | { |
||
577 | // logging into last visited region |
||
578 | where = "last"; |
||
579 | |||
580 | if (pinfo == null) |
||
581 | return null; |
||
582 | |||
583 | GridRegion region = null; |
||
584 | |||
585 | if (pinfo.LastRegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(scopeID, pinfo.LastRegionID)) == null) |
||
586 | { |
||
587 | List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); |
||
588 | if (defaults != null && defaults.Count > 0) |
||
589 | { |
||
590 | region = defaults[0]; |
||
591 | where = "safe"; |
||
592 | } |
||
593 | else |
||
594 | { |
||
595 | m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region"); |
||
596 | region = FindAlternativeRegion(scopeID); |
||
597 | if (region != null) |
||
598 | where = "safe"; |
||
599 | } |
||
600 | |||
601 | } |
||
602 | else |
||
603 | { |
||
604 | position = pinfo.LastPosition; |
||
605 | lookAt = pinfo.LastLookAt; |
||
606 | } |
||
607 | |||
608 | return region; |
||
609 | } |
||
610 | else |
||
611 | { |
||
612 | flags |= TeleportFlags.ViaRegionID; |
||
613 | |||
614 | // free uri form |
||
615 | // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34 |
||
616 | where = "url"; |
||
617 | GridRegion region = null; |
||
618 | Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); |
||
619 | Match uriMatch = reURI.Match(startLocation); |
||
620 | if (uriMatch == null) |
||
621 | { |
||
622 | m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, but can't process it", startLocation); |
||
623 | return null; |
||
624 | } |
||
625 | else |
||
626 | { |
||
627 | position = new Vector3(float.Parse(uriMatch.Groups["x"].Value, Culture.NumberFormatInfo), |
||
628 | float.Parse(uriMatch.Groups["y"].Value, Culture.NumberFormatInfo), |
||
629 | float.Parse(uriMatch.Groups["z"].Value, Culture.NumberFormatInfo)); |
||
630 | |||
631 | string regionName = uriMatch.Groups["region"].ToString(); |
||
632 | if (regionName != null) |
||
633 | { |
||
634 | if (!regionName.Contains("@")) |
||
635 | { |
||
636 | List<GridRegion> regions = m_GridService.GetRegionsByName(scopeID, regionName, 1); |
||
637 | if ((regions == null) || (regions != null && regions.Count == 0)) |
||
638 | { |
||
639 | m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}. Trying defaults.", startLocation, regionName); |
||
640 | regions = m_GridService.GetDefaultRegions(scopeID); |
||
641 | if (regions != null && regions.Count > 0) |
||
642 | { |
||
643 | where = "safe"; |
||
644 | return regions[0]; |
||
645 | } |
||
646 | else |
||
647 | { |
||
648 | m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region"); |
||
649 | region = FindAlternativeRegion(scopeID); |
||
650 | if (region != null) |
||
651 | { |
||
652 | where = "safe"; |
||
653 | return region; |
||
654 | } |
||
655 | else |
||
656 | { |
||
657 | m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions and no alternative found.", startLocation); |
||
658 | return null; |
||
659 | } |
||
660 | } |
||
661 | } |
||
662 | return regions[0]; |
||
663 | } |
||
664 | else |
||
665 | { |
||
666 | if (m_UserAgentService == null) |
||
667 | { |
||
668 | m_log.WarnFormat("[LLLOGIN SERVICE]: This llogin service is not running a user agent service, as such it can't lauch agents at foreign grids"); |
||
669 | return null; |
||
670 | } |
||
671 | string[] parts = regionName.Split(new char[] { '@' }); |
||
672 | if (parts.Length < 2) |
||
673 | { |
||
674 | m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}", startLocation, regionName); |
||
675 | return null; |
||
676 | } |
||
677 | // Valid specification of a remote grid |
||
678 | |||
679 | regionName = parts[0]; |
||
680 | string domainLocator = parts[1]; |
||
681 | parts = domainLocator.Split(new char[] {':'}); |
||
682 | string domainName = parts[0]; |
||
683 | uint port = 0; |
||
684 | if (parts.Length > 1) |
||
685 | UInt32.TryParse(parts[1], out port); |
||
686 | |||
687 | region = FindForeignRegion(domainName, port, regionName, account, out gatekeeper); |
||
688 | return region; |
||
689 | } |
||
690 | } |
||
691 | else |
||
692 | { |
||
693 | List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); |
||
694 | if (defaults != null && defaults.Count > 0) |
||
695 | { |
||
696 | where = "safe"; |
||
697 | return defaults[0]; |
||
698 | } |
||
699 | else |
||
700 | return null; |
||
701 | } |
||
702 | } |
||
703 | //response.LookAt = "[r0,r1,r0]"; |
||
704 | //// can be: last, home, safe, url |
||
705 | //response.StartLocation = "url"; |
||
706 | |||
707 | } |
||
708 | |||
709 | } |
||
710 | |||
711 | private GridRegion FindAlternativeRegion(UUID scopeID) |
||
712 | { |
||
713 | List<GridRegion> hyperlinks = null; |
||
714 | List<GridRegion> regions = m_GridService.GetFallbackRegions(scopeID, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000)); |
||
715 | if (regions != null && regions.Count > 0) |
||
716 | { |
||
717 | hyperlinks = m_GridService.GetHyperlinks(scopeID); |
||
718 | IEnumerable<GridRegion> availableRegions = regions.Except(hyperlinks); |
||
719 | if (availableRegions.Count() > 0) |
||
720 | return availableRegions.ElementAt(0); |
||
721 | } |
||
722 | // No fallbacks, try to find an arbitrary region that is not a hyperlink |
||
723 | // maxNumber is fixed for now; maybe use some search pattern with increasing maxSize here? |
||
724 | regions = m_GridService.GetRegionsByName(scopeID, "", 10); |
||
725 | if (regions != null && regions.Count > 0) |
||
726 | { |
||
727 | if (hyperlinks == null) |
||
728 | hyperlinks = m_GridService.GetHyperlinks(scopeID); |
||
729 | IEnumerable<GridRegion> availableRegions = regions.Except(hyperlinks); |
||
730 | if (availableRegions.Count() > 0) |
||
731 | return availableRegions.ElementAt(0); |
||
732 | } |
||
733 | return null; |
||
734 | } |
||
735 | |||
736 | private GridRegion FindForeignRegion(string domainName, uint port, string regionName, UserAccount account, out GridRegion gatekeeper) |
||
737 | { |
||
738 | m_log.Debug("[LLLOGIN SERVICE]: attempting to findforeignregion " + domainName + ":" + port.ToString() + ":" + regionName); |
||
739 | gatekeeper = new GridRegion(); |
||
740 | gatekeeper.ExternalHostName = domainName; |
||
741 | gatekeeper.HttpPort = port; |
||
742 | gatekeeper.RegionName = regionName; |
||
743 | gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); |
||
744 | |||
745 | UUID regionID; |
||
746 | ulong handle; |
||
747 | string imageURL = string.Empty, reason = string.Empty; |
||
748 | string message; |
||
749 | if (m_GatekeeperConnector.LinkRegion(gatekeeper, out regionID, out handle, out domainName, out imageURL, out reason)) |
||
750 | { |
||
751 | string homeURI = null; |
||
752 | if (account.ServiceURLs != null && account.ServiceURLs.ContainsKey("HomeURI")) |
||
753 | homeURI = (string)account.ServiceURLs["HomeURI"]; |
||
754 | |||
755 | GridRegion destination = m_GatekeeperConnector.GetHyperlinkRegion(gatekeeper, regionID, account.PrincipalID, homeURI, out message); |
||
756 | return destination; |
||
757 | } |
||
758 | |||
759 | return null; |
||
760 | } |
||
761 | |||
762 | private string hostName = string.Empty; |
||
763 | private int port = 0; |
||
764 | |||
765 | private void SetHostAndPort(string url) |
||
766 | { |
||
767 | try |
||
768 | { |
||
769 | Uri uri = new Uri(url); |
||
770 | hostName = uri.Host; |
||
771 | port = uri.Port; |
||
772 | } |
||
773 | catch |
||
774 | { |
||
775 | m_log.WarnFormat("[LLLogin SERVICE]: Unable to parse GatekeeperURL {0}", url); |
||
776 | } |
||
777 | } |
||
778 | |||
779 | protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarAppearance avatar, |
||
780 | UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, string channel, string mac, string id0, |
||
781 | IPEndPoint clientIP, TeleportFlags flags, out string where, out string reason, out GridRegion dest) |
||
782 | { |
||
783 | where = currentWhere; |
||
784 | ISimulationService simConnector = null; |
||
785 | reason = string.Empty; |
||
786 | uint circuitCode = 0; |
||
787 | AgentCircuitData aCircuit = null; |
||
788 | |||
789 | if (m_UserAgentService == null) |
||
790 | { |
||
791 | // HG standalones have both a localSimulatonDll and a remoteSimulationDll |
||
792 | // non-HG standalones have just a localSimulationDll |
||
793 | // independent login servers have just a remoteSimulationDll |
||
794 | if (m_LocalSimulationService != null) |
||
795 | simConnector = m_LocalSimulationService; |
||
796 | else if (m_RemoteSimulationService != null) |
||
797 | simConnector = m_RemoteSimulationService; |
||
798 | } |
||
799 | else // User Agent Service is on |
||
800 | { |
||
801 | if (gatekeeper == null) // login to local grid |
||
802 | { |
||
803 | if (hostName == string.Empty) |
||
804 | SetHostAndPort(m_GatekeeperURL); |
||
805 | |||
806 | gatekeeper = new GridRegion(destination); |
||
807 | gatekeeper.ExternalHostName = hostName; |
||
808 | gatekeeper.HttpPort = (uint)port; |
||
809 | gatekeeper.ServerURI = m_GatekeeperURL; |
||
810 | } |
||
811 | m_log.Debug("[LLLOGIN SERVICE]: no gatekeeper detected..... using " + m_GatekeeperURL); |
||
812 | } |
||
813 | |||
814 | bool success = false; |
||
815 | |||
816 | if (m_UserAgentService == null && simConnector != null) |
||
817 | { |
||
818 | circuitCode = (uint)Util.RandomClass.Next(); ; |
||
819 | aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, clientIP.Address.ToString(), viewer, channel, mac, id0); |
||
820 | success = LaunchAgentDirectly(simConnector, destination, aCircuit, flags, out reason); |
||
821 | if (!success && m_GridService != null) |
||
822 | { |
||
823 | // Try the fallback regions |
||
824 | List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY); |
||
825 | if (fallbacks != null) |
||
826 | { |
||
827 | foreach (GridRegion r in fallbacks) |
||
828 | { |
||
829 | success = LaunchAgentDirectly(simConnector, r, aCircuit, flags | TeleportFlags.ViaRegionID, out reason); |
||
830 | if (success) |
||
831 | { |
||
832 | where = "safe"; |
||
833 | destination = r; |
||
834 | break; |
||
835 | } |
||
836 | } |
||
837 | } |
||
838 | } |
||
839 | } |
||
840 | |||
841 | if (m_UserAgentService != null) |
||
842 | { |
||
843 | circuitCode = (uint)Util.RandomClass.Next(); ; |
||
844 | aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, clientIP.Address.ToString(), viewer, channel, mac, id0); |
||
845 | aCircuit.teleportFlags |= (uint)flags; |
||
846 | success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, clientIP, out reason); |
||
847 | if (!success && m_GridService != null) |
||
848 | { |
||
849 | // Try the fallback regions |
||
850 | List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY); |
||
851 | if (fallbacks != null) |
||
852 | { |
||
853 | foreach (GridRegion r in fallbacks) |
||
854 | { |
||
855 | success = LaunchAgentIndirectly(gatekeeper, r, aCircuit, clientIP, out reason); |
||
856 | if (success) |
||
857 | { |
||
858 | where = "safe"; |
||
859 | destination = r; |
||
860 | break; |
||
861 | } |
||
862 | } |
||
863 | } |
||
864 | } |
||
865 | } |
||
866 | dest = destination; |
||
867 | if (success) |
||
868 | return aCircuit; |
||
869 | else |
||
870 | return null; |
||
871 | } |
||
872 | |||
873 | private AgentCircuitData MakeAgent(GridRegion region, UserAccount account, |
||
874 | AvatarAppearance avatar, UUID session, UUID secureSession, uint circuit, Vector3 position, |
||
875 | string ipaddress, string viewer, string channel, string mac, string id0) |
||
876 | { |
||
877 | AgentCircuitData aCircuit = new AgentCircuitData(); |
||
878 | |||
879 | aCircuit.AgentID = account.PrincipalID; |
||
880 | if (avatar != null) |
||
881 | aCircuit.Appearance = new AvatarAppearance(avatar); |
||
882 | else |
||
883 | aCircuit.Appearance = new AvatarAppearance(); |
||
884 | |||
885 | //aCircuit.BaseFolder = irrelevant |
||
886 | aCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); |
||
887 | aCircuit.child = false; // the first login agent is root |
||
888 | aCircuit.ChildrenCapSeeds = new Dictionary<ulong, string>(); |
||
889 | aCircuit.circuitcode = circuit; |
||
890 | aCircuit.firstname = account.FirstName; |
||
891 | //aCircuit.InventoryFolder = irrelevant |
||
892 | aCircuit.lastname = account.LastName; |
||
893 | aCircuit.SecureSessionID = secureSession; |
||
894 | aCircuit.SessionID = session; |
||
895 | aCircuit.startpos = position; |
||
896 | aCircuit.IPAddress = ipaddress; |
||
897 | aCircuit.Viewer = viewer; |
||
898 | aCircuit.Channel = channel; |
||
899 | aCircuit.Mac = mac; |
||
900 | aCircuit.Id0 = id0; |
||
901 | SetServiceURLs(aCircuit, account); |
||
902 | |||
903 | return aCircuit; |
||
904 | } |
||
905 | |||
906 | private void SetServiceURLs(AgentCircuitData aCircuit, UserAccount account) |
||
907 | { |
||
908 | aCircuit.ServiceURLs = new Dictionary<string, object>(); |
||
909 | if (account.ServiceURLs == null) |
||
910 | return; |
||
911 | |||
912 | // Old style: get the service keys from the DB |
||
913 | foreach (KeyValuePair<string, object> kvp in account.ServiceURLs) |
||
914 | { |
||
915 | if (kvp.Value != null) |
||
916 | { |
||
917 | aCircuit.ServiceURLs[kvp.Key] = kvp.Value; |
||
918 | |||
919 | if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) |
||
920 | aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; |
||
921 | } |
||
922 | } |
||
923 | |||
924 | // New style: service keys start with SRV_; override the previous |
||
925 | string[] keys = m_LoginServerConfig.GetKeys(); |
||
926 | |||
927 | if (keys.Length > 0) |
||
928 | { |
||
929 | bool newUrls = false; |
||
930 | IEnumerable<string> serviceKeys = keys.Where(value => value.StartsWith("SRV_")); |
||
931 | foreach (string serviceKey in serviceKeys) |
||
932 | { |
||
933 | string keyName = serviceKey.Replace("SRV_", ""); |
||
934 | string keyValue = m_LoginServerConfig.GetString(serviceKey, string.Empty); |
||
935 | if (!keyValue.EndsWith("/")) |
||
936 | keyValue = keyValue + "/"; |
||
937 | |||
938 | if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && (string)account.ServiceURLs[keyName] != keyValue)) |
||
939 | { |
||
940 | account.ServiceURLs[keyName] = keyValue; |
||
941 | newUrls = true; |
||
942 | } |
||
943 | aCircuit.ServiceURLs[keyName] = keyValue; |
||
944 | |||
945 | m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]); |
||
946 | } |
||
947 | |||
948 | // The grid operator decided to override the defaults in the |
||
949 | // [LoginService] configuration. Let's store the correct ones. |
||
950 | if (newUrls) |
||
951 | m_UserAccountService.StoreUserAccount(account); |
||
952 | } |
||
953 | |||
954 | } |
||
955 | |||
956 | private bool LaunchAgentDirectly(ISimulationService simConnector, GridRegion region, AgentCircuitData aCircuit, TeleportFlags flags, out string reason) |
||
957 | { |
||
958 | string version; |
||
959 | |||
960 | if ( |
||
961 | !simConnector.QueryAccess( |
||
962 | region, aCircuit.AgentID, null, true, aCircuit.startpos, "SIMULATION/0.3", out version, out reason)) |
||
963 | return false; |
||
964 | |||
965 | return simConnector.CreateAgent(null, region, aCircuit, (uint)flags, out reason); |
||
966 | } |
||
967 | |||
968 | private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) |
||
969 | { |
||
970 | m_log.Debug("[LLOGIN SERVICE]: Launching agent at " + destination.RegionName); |
||
971 | |||
972 | if (m_UserAgentService.LoginAgentToGrid(null, aCircuit, gatekeeper, destination, true, out reason)) |
||
973 | return true; |
||
974 | return false; |
||
975 | } |
||
976 | |||
977 | #region Console Commands |
||
978 | private void RegisterCommands() |
||
979 | { |
||
980 | //MainConsole.Instance.Commands.AddCommand |
||
981 | MainConsole.Instance.Commands.AddCommand("Users", false, "login level", |
||
982 | "login level <level>", |
||
983 | "Set the minimum user level to log in", HandleLoginCommand); |
||
984 | |||
985 | MainConsole.Instance.Commands.AddCommand("Users", false, "login reset", |
||
986 | "login reset", |
||
987 | "Reset the login level to allow all users", |
||
988 | HandleLoginCommand); |
||
989 | |||
990 | MainConsole.Instance.Commands.AddCommand("Users", false, "login text", |
||
991 | "login text <text>", |
||
992 | "Set the text users will see on login", HandleLoginCommand); |
||
993 | |||
994 | } |
||
995 | |||
996 | private void HandleLoginCommand(string module, string[] cmd) |
||
997 | { |
||
998 | string subcommand = cmd[1]; |
||
999 | |||
1000 | switch (subcommand) |
||
1001 | { |
||
1002 | case "level": |
||
1003 | // Set the minimum level to allow login |
||
1004 | // Useful to allow grid update without worrying about users. |
||
1005 | // or fixing critical issues |
||
1006 | // |
||
1007 | if (cmd.Length > 2) |
||
1008 | { |
||
1009 | if (Int32.TryParse(cmd[2], out m_MinLoginLevel)) |
||
1010 | MainConsole.Instance.OutputFormat("Set minimum login level to {0}", m_MinLoginLevel); |
||
1011 | else |
||
1012 | MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid login level", cmd[2]); |
||
1013 | } |
||
1014 | break; |
||
1015 | |||
1016 | case "reset": |
||
1017 | m_MinLoginLevel = 0; |
||
1018 | MainConsole.Instance.OutputFormat("Reset min login level to {0}", m_MinLoginLevel); |
||
1019 | break; |
||
1020 | |||
1021 | case "text": |
||
1022 | if (cmd.Length > 2) |
||
1023 | { |
||
1024 | m_WelcomeMessage = cmd[2]; |
||
1025 | MainConsole.Instance.OutputFormat("Login welcome message set to '{0}'", m_WelcomeMessage); |
||
1026 | } |
||
1027 | break; |
||
1028 | } |
||
1029 | } |
||
1030 | } |
||
1031 | |||
1032 | #endregion |
||
1033 | } |