aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Grid/UserServer/UserServerCommandModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Grid/UserServer/UserServerCommandModule.cs')
-rw-r--r--OpenSim/Grid/UserServer/UserServerCommandModule.cs732
1 files changed, 366 insertions, 366 deletions
diff --git a/OpenSim/Grid/UserServer/UserServerCommandModule.cs b/OpenSim/Grid/UserServer/UserServerCommandModule.cs
index 41a7eed..f35cfec 100644
--- a/OpenSim/Grid/UserServer/UserServerCommandModule.cs
+++ b/OpenSim/Grid/UserServer/UserServerCommandModule.cs
@@ -1,366 +1,366 @@
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.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using log4net.Config; 33using log4net.Config;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Data; 35using OpenSim.Data;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
38using OpenSim.Framework.Communications.Cache; 38using OpenSim.Framework.Communications.Cache;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Statistics; 41using OpenSim.Framework.Statistics;
42using OpenSim.Grid.Communications.OGS1; 42using OpenSim.Grid.Communications.OGS1;
43using OpenSim.Grid.Framework; 43using OpenSim.Grid.Framework;
44using OpenSim.Grid.UserServer.Modules; 44using OpenSim.Grid.UserServer.Modules;
45 45
46namespace OpenSim.Grid.UserServer 46namespace OpenSim.Grid.UserServer
47{ 47{
48 public class UserServerCommandModule 48 public class UserServerCommandModule
49 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 protected ConsoleBase m_console; 52 protected ConsoleBase m_console;
53 protected UserConfig m_cfg; 53 protected UserConfig m_cfg;
54 54
55 protected UserDataBaseService m_userDataBaseService; 55 protected UserDataBaseService m_userDataBaseService;
56 protected UserLoginService m_loginService; 56 protected UserLoginService m_loginService;
57 57
58 protected UUID m_lastCreatedUser = UUID.Random(); 58 protected UUID m_lastCreatedUser = UUID.Random();
59 59
60 protected IUGAIMCore m_core; 60 protected IUGAIMCore m_core;
61 61
62 public UserServerCommandModule( UserLoginService loginService) 62 public UserServerCommandModule( UserLoginService loginService)
63 { 63 {
64 m_loginService = loginService; 64 m_loginService = loginService;
65 } 65 }
66 66
67 public void Initialise(IUGAIMCore core) 67 public void Initialise(IUGAIMCore core)
68 { 68 {
69 m_core = core; 69 m_core = core;
70 } 70 }
71 71
72 public void PostInitialise() 72 public void PostInitialise()
73 { 73 {
74 UserConfig cfg; 74 UserConfig cfg;
75 if (m_core.TryGet<UserConfig>(out cfg)) 75 if (m_core.TryGet<UserConfig>(out cfg))
76 { 76 {
77 m_cfg = cfg; 77 m_cfg = cfg;
78 } 78 }
79 79
80 UserDataBaseService userDBservice; 80 UserDataBaseService userDBservice;
81 if (m_core.TryGet<UserDataBaseService>(out userDBservice)) 81 if (m_core.TryGet<UserDataBaseService>(out userDBservice))
82 { 82 {
83 m_userDataBaseService = userDBservice; 83 m_userDataBaseService = userDBservice;
84 } 84 }
85 85
86 ConsoleBase console; 86 ConsoleBase console;
87 if ((m_core.TryGet<ConsoleBase>(out console)) && (m_cfg != null) && (m_userDataBaseService != null)) 87 if ((m_core.TryGet<ConsoleBase>(out console)) && (m_cfg != null) && (m_userDataBaseService != null))
88 { 88 {
89 RegisterConsoleCommands(console); 89 RegisterConsoleCommands(console);
90 } 90 }
91 } 91 }
92 92
93 public void RegisterHandlers(BaseHttpServer httpServer) 93 public void RegisterHandlers(BaseHttpServer httpServer)
94 { 94 {
95 95
96 } 96 }
97 97
98 private void RegisterConsoleCommands(ConsoleBase console) 98 private void RegisterConsoleCommands(ConsoleBase console)
99 { 99 {
100 m_console = console; 100 m_console = console;
101 m_console.Commands.AddCommand("userserver", false, "create user", 101 m_console.Commands.AddCommand("userserver", false, "create user",
102 "create user [<first> [<last> [<x> <y> [email]]]]", 102 "create user [<first> [<last> [<x> <y> [email]]]]",
103 "Create a new user account", RunCommand); 103 "Create a new user account", RunCommand);
104 104
105 m_console.Commands.AddCommand("userserver", false, "reset user password", 105 m_console.Commands.AddCommand("userserver", false, "reset user password",
106 "reset user password [<first> [<last> [<new password>]]]", 106 "reset user password [<first> [<last> [<new password>]]]",
107 "Reset a user's password", RunCommand); 107 "Reset a user's password", RunCommand);
108 108
109 m_console.Commands.AddCommand("userserver", false, "login level", 109 m_console.Commands.AddCommand("userserver", false, "login level",
110 "login level <level>", 110 "login level <level>",
111 "Set the minimum user level to log in", HandleLoginCommand); 111 "Set the minimum user level to log in", HandleLoginCommand);
112 112
113 m_console.Commands.AddCommand("userserver", false, "login reset", 113 m_console.Commands.AddCommand("userserver", false, "login reset",
114 "login reset", 114 "login reset",
115 "Reset the login level to allow all users", 115 "Reset the login level to allow all users",
116 HandleLoginCommand); 116 HandleLoginCommand);
117 117
118 m_console.Commands.AddCommand("userserver", false, "login text", 118 m_console.Commands.AddCommand("userserver", false, "login text",
119 "login text <text>", 119 "login text <text>",
120 "Set the text users will see on login", HandleLoginCommand); 120 "Set the text users will see on login", HandleLoginCommand);
121 121
122 m_console.Commands.AddCommand("userserver", false, "test-inventory", 122 m_console.Commands.AddCommand("userserver", false, "test-inventory",
123 "test-inventory", 123 "test-inventory",
124 "Perform a test inventory transaction", RunCommand); 124 "Perform a test inventory transaction", RunCommand);
125 125
126 m_console.Commands.AddCommand("userserver", false, "logoff-user", 126 m_console.Commands.AddCommand("userserver", false, "logoff-user",
127 "logoff-user <first> <last> <message>", 127 "logoff-user <first> <last> <message>",
128 "Log off a named user", RunCommand); 128 "Log off a named user", RunCommand);
129 } 129 }
130 130
131 #region Console Command Handlers 131 #region Console Command Handlers
132 public void do_create(string[] args) 132 public void do_create(string[] args)
133 { 133 {
134 switch (args[0]) 134 switch (args[0])
135 { 135 {
136 case "user": 136 case "user":
137 CreateUser(args); 137 CreateUser(args);
138 break; 138 break;
139 } 139 }
140 } 140 }
141 141
142 /// <summary> 142 /// <summary>
143 /// Execute switch for some of the reset commands 143 /// Execute switch for some of the reset commands
144 /// </summary> 144 /// </summary>
145 /// <param name="args"></param> 145 /// <param name="args"></param>
146 protected void Reset(string[] args) 146 protected void Reset(string[] args)
147 { 147 {
148 if (args.Length == 0) 148 if (args.Length == 0)
149 return; 149 return;
150 150
151 switch (args[0]) 151 switch (args[0])
152 { 152 {
153 case "user": 153 case "user":
154 154
155 switch (args[1]) 155 switch (args[1])
156 { 156 {
157 case "password": 157 case "password":
158 ResetUserPassword(args); 158 ResetUserPassword(args);
159 break; 159 break;
160 } 160 }
161 161
162 break; 162 break;
163 } 163 }
164 } 164 }
165 165
166 /// <summary> 166 /// <summary>
167 /// Create a new user 167 /// Create a new user
168 /// </summary> 168 /// </summary>
169 /// <param name="cmdparams">string array with parameters: firstname, lastname, password, locationX, locationY, email</param> 169 /// <param name="cmdparams">string array with parameters: firstname, lastname, password, locationX, locationY, email</param>
170 protected void CreateUser(string[] cmdparams) 170 protected void CreateUser(string[] cmdparams)
171 { 171 {
172 string firstName; 172 string firstName;
173 string lastName; 173 string lastName;
174 string password; 174 string password;
175 string email; 175 string email;
176 uint regX = 1000; 176 uint regX = 1000;
177 uint regY = 1000; 177 uint regY = 1000;
178 178
179 if (cmdparams.Length < 2) 179 if (cmdparams.Length < 2)
180 firstName = MainConsole.Instance.CmdPrompt("First name", "Default"); 180 firstName = MainConsole.Instance.CmdPrompt("First name", "Default");
181 else firstName = cmdparams[1]; 181 else firstName = cmdparams[1];
182 182
183 if (cmdparams.Length < 3) 183 if (cmdparams.Length < 3)
184 lastName = MainConsole.Instance.CmdPrompt("Last name", "User"); 184 lastName = MainConsole.Instance.CmdPrompt("Last name", "User");
185 else lastName = cmdparams[2]; 185 else lastName = cmdparams[2];
186 186
187 if (cmdparams.Length < 4) 187 if (cmdparams.Length < 4)
188 password = MainConsole.Instance.PasswdPrompt("Password"); 188 password = MainConsole.Instance.PasswdPrompt("Password");
189 else password = cmdparams[3]; 189 else password = cmdparams[3];
190 190
191 if (cmdparams.Length < 5) 191 if (cmdparams.Length < 5)
192 regX = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region X", regX.ToString())); 192 regX = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region X", regX.ToString()));
193 else regX = Convert.ToUInt32(cmdparams[4]); 193 else regX = Convert.ToUInt32(cmdparams[4]);
194 194
195 if (cmdparams.Length < 6) 195 if (cmdparams.Length < 6)
196 regY = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region Y", regY.ToString())); 196 regY = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region Y", regY.ToString()));
197 else regY = Convert.ToUInt32(cmdparams[5]); 197 else regY = Convert.ToUInt32(cmdparams[5]);
198 198
199 if (cmdparams.Length < 7) 199 if (cmdparams.Length < 7)
200 email = MainConsole.Instance.CmdPrompt("Email", ""); 200 email = MainConsole.Instance.CmdPrompt("Email", "");
201 else email = cmdparams[6]; 201 else email = cmdparams[6];
202 202
203 if (null == m_userDataBaseService.GetUserProfile(firstName, lastName)) 203 if (null == m_userDataBaseService.GetUserProfile(firstName, lastName))
204 { 204 {
205 m_lastCreatedUser = m_userDataBaseService.AddUser(firstName, lastName, password, email, regX, regY); 205 m_lastCreatedUser = m_userDataBaseService.AddUser(firstName, lastName, password, email, regX, regY);
206 } 206 }
207 else 207 else
208 { 208 {
209 m_log.ErrorFormat("[USERS]: A user with the name {0} {1} already exists!", firstName, lastName); 209 m_log.ErrorFormat("[USERS]: A user with the name {0} {1} already exists!", firstName, lastName);
210 } 210 }
211 } 211 }
212 212
213 /// <summary> 213 /// <summary>
214 /// Reset a user password. 214 /// Reset a user password.
215 /// </summary> 215 /// </summary>
216 /// <param name="cmdparams"></param> 216 /// <param name="cmdparams"></param>
217 private void ResetUserPassword(string[] cmdparams) 217 private void ResetUserPassword(string[] cmdparams)
218 { 218 {
219 string firstName; 219 string firstName;
220 string lastName; 220 string lastName;
221 string newPassword; 221 string newPassword;
222 222
223 if (cmdparams.Length < 3) 223 if (cmdparams.Length < 3)
224 firstName = MainConsole.Instance.CmdPrompt("First name"); 224 firstName = MainConsole.Instance.CmdPrompt("First name");
225 else firstName = cmdparams[2]; 225 else firstName = cmdparams[2];
226 226
227 if (cmdparams.Length < 4) 227 if (cmdparams.Length < 4)
228 lastName = MainConsole.Instance.CmdPrompt("Last name"); 228 lastName = MainConsole.Instance.CmdPrompt("Last name");
229 else lastName = cmdparams[3]; 229 else lastName = cmdparams[3];
230 230
231 if (cmdparams.Length < 5) 231 if (cmdparams.Length < 5)
232 newPassword = MainConsole.Instance.PasswdPrompt("New password"); 232 newPassword = MainConsole.Instance.PasswdPrompt("New password");
233 else newPassword = cmdparams[4]; 233 else newPassword = cmdparams[4];
234 234
235 m_userDataBaseService.ResetUserPassword(firstName, lastName, newPassword); 235 m_userDataBaseService.ResetUserPassword(firstName, lastName, newPassword);
236 } 236 }
237 237
238 private void HandleTestCommand(string module, string[] cmd) 238 private void HandleTestCommand(string module, string[] cmd)
239 { 239 {
240 m_log.Info("test command received"); 240 m_log.Info("test command received");
241 } 241 }
242 242
243 private void HandleLoginCommand(string module, string[] cmd) 243 private void HandleLoginCommand(string module, string[] cmd)
244 { 244 {
245 string subcommand = cmd[1]; 245 string subcommand = cmd[1];
246 246
247 switch (subcommand) 247 switch (subcommand)
248 { 248 {
249 case "level": 249 case "level":
250 // Set the minimal level to allow login 250 // Set the minimal level to allow login
251 // Useful to allow grid update without worrying about users. 251 // Useful to allow grid update without worrying about users.
252 // or fixing critical issues 252 // or fixing critical issues
253 // 253 //
254 if (cmd.Length > 2) 254 if (cmd.Length > 2)
255 { 255 {
256 int level = Convert.ToInt32(cmd[2]); 256 int level = Convert.ToInt32(cmd[2]);
257 m_loginService.setloginlevel(level); 257 m_loginService.setloginlevel(level);
258 } 258 }
259 break; 259 break;
260 case "reset": 260 case "reset":
261 m_loginService.setloginlevel(0); 261 m_loginService.setloginlevel(0);
262 break; 262 break;
263 case "text": 263 case "text":
264 if (cmd.Length > 2) 264 if (cmd.Length > 2)
265 { 265 {
266 m_loginService.setwelcometext(cmd[2]); 266 m_loginService.setwelcometext(cmd[2]);
267 } 267 }
268 break; 268 break;
269 } 269 }
270 } 270 }
271 271
272 public void RunCommand(string module, string[] cmd) 272 public void RunCommand(string module, string[] cmd)
273 { 273 {
274 List<string> args = new List<string>(cmd); 274 List<string> args = new List<string>(cmd);
275 string command = cmd[0]; 275 string command = cmd[0];
276 276
277 args.RemoveAt(0); 277 args.RemoveAt(0);
278 278
279 string[] cmdparams = args.ToArray(); 279 string[] cmdparams = args.ToArray();
280 280
281 switch (command) 281 switch (command)
282 { 282 {
283 case "create": 283 case "create":
284 do_create(cmdparams); 284 do_create(cmdparams);
285 break; 285 break;
286 286
287 case "reset": 287 case "reset":
288 Reset(cmdparams); 288 Reset(cmdparams);
289 break; 289 break;
290 290
291 291
292 case "test-inventory": 292 case "test-inventory":
293 // RestObjectPosterResponse<List<InventoryFolderBase>> requester = new RestObjectPosterResponse<List<InventoryFolderBase>>(); 293 // RestObjectPosterResponse<List<InventoryFolderBase>> requester = new RestObjectPosterResponse<List<InventoryFolderBase>>();
294 // requester.ReturnResponseVal = TestResponse; 294 // requester.ReturnResponseVal = TestResponse;
295 // requester.BeginPostObject<UUID>(m_userManager._config.InventoryUrl + "RootFolders/", m_lastCreatedUser); 295 // requester.BeginPostObject<UUID>(m_userManager._config.InventoryUrl + "RootFolders/", m_lastCreatedUser);
296 SynchronousRestObjectPoster.BeginPostObject<UUID, List<InventoryFolderBase>>( 296 SynchronousRestObjectPoster.BeginPostObject<UUID, List<InventoryFolderBase>>(
297 "POST", m_cfg.InventoryUrl + "RootFolders/", m_lastCreatedUser); 297 "POST", m_cfg.InventoryUrl + "RootFolders/", m_lastCreatedUser);
298 break; 298 break;
299 299
300 case "logoff-user": 300 case "logoff-user":
301 if (cmdparams.Length >= 3) 301 if (cmdparams.Length >= 3)
302 { 302 {
303 string firstname = cmdparams[0]; 303 string firstname = cmdparams[0];
304 string lastname = cmdparams[1]; 304 string lastname = cmdparams[1];
305 string message = ""; 305 string message = "";
306 306
307 for (int i = 2; i < cmdparams.Length; i++) 307 for (int i = 2; i < cmdparams.Length; i++)
308 message += " " + cmdparams[i]; 308 message += " " + cmdparams[i];
309 309
310 UserProfileData theUser = null; 310 UserProfileData theUser = null;
311 try 311 try
312 { 312 {
313 theUser = m_loginService.GetTheUser(firstname, lastname); 313 theUser = m_loginService.GetTheUser(firstname, lastname);
314 } 314 }
315 catch (Exception) 315 catch (Exception)
316 { 316 {
317 m_log.Error("[LOGOFF]: Error getting user data from the database."); 317 m_log.Error("[LOGOFF]: Error getting user data from the database.");
318 } 318 }
319 319
320 if (theUser != null) 320 if (theUser != null)
321 { 321 {
322 if (theUser.CurrentAgent != null) 322 if (theUser.CurrentAgent != null)
323 { 323 {
324 if (theUser.CurrentAgent.AgentOnline) 324 if (theUser.CurrentAgent.AgentOnline)
325 { 325 {
326 m_log.Info("[LOGOFF]: Logging off requested user!"); 326 m_log.Info("[LOGOFF]: Logging off requested user!");
327 m_loginService.LogOffUser(theUser, message); 327 m_loginService.LogOffUser(theUser, message);
328 328
329 theUser.CurrentAgent.AgentOnline = false; 329 theUser.CurrentAgent.AgentOnline = false;
330 330
331 m_loginService.CommitAgent(ref theUser); 331 m_loginService.CommitAgent(ref theUser);
332 } 332 }
333 else 333 else
334 { 334 {
335 m_log.Info( 335 m_log.Info(
336 "[LOGOFF]: User Doesn't appear to be online, sending the logoff message anyway."); 336 "[LOGOFF]: User Doesn't appear to be online, sending the logoff message anyway.");
337 m_loginService.LogOffUser(theUser, message); 337 m_loginService.LogOffUser(theUser, message);
338 338
339 theUser.CurrentAgent.AgentOnline = false; 339 theUser.CurrentAgent.AgentOnline = false;
340 340
341 m_loginService.CommitAgent(ref theUser); 341 m_loginService.CommitAgent(ref theUser);
342 } 342 }
343 } 343 }
344 else 344 else
345 { 345 {
346 m_log.Error( 346 m_log.Error(
347 "[LOGOFF]: Unable to logoff-user. User doesn't have an agent record so I can't find the simulator to notify"); 347 "[LOGOFF]: Unable to logoff-user. User doesn't have an agent record so I can't find the simulator to notify");
348 } 348 }
349 } 349 }
350 else 350 else
351 { 351 {
352 m_log.Info("[LOGOFF]: User doesn't exist in the database"); 352 m_log.Info("[LOGOFF]: User doesn't exist in the database");
353 } 353 }
354 } 354 }
355 else 355 else
356 { 356 {
357 m_log.Error( 357 m_log.Error(
358 "[LOGOFF]: Invalid amount of parameters. logoff-user takes at least three. Firstname, Lastname, and message"); 358 "[LOGOFF]: Invalid amount of parameters. logoff-user takes at least three. Firstname, Lastname, and message");
359 } 359 }
360 360
361 break; 361 break;
362 } 362 }
363 } 363 }
364 } 364 }
365 #endregion 365 #endregion
366} 366}