aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Console/RemoteConsole.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Console/RemoteConsole.cs')
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs400
1 files changed, 200 insertions, 200 deletions
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index 9049b4b..f59c902 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -46,93 +46,93 @@ namespace OpenSim.Framework.Console
46 // 46 //
47 public class RemoteConsole : CommandConsole 47 public class RemoteConsole : CommandConsole
48 { 48 {
49 // Connection specific data, indexed by a session ID 49 // Connection specific data, indexed by a session ID
50 // we create when a client connects. 50 // we create when a client connects.
51 protected class ConsoleConnection 51 protected class ConsoleConnection
52 { 52 {
53 // Last activity from the client 53 // Last activity from the client
54 public int last; 54 public int last;
55 55
56 // Last line of scrollback posted to this client 56 // Last line of scrollback posted to this client
57 public long lastLineSeen; 57 public long lastLineSeen;
58 58
59 // True if this is a new connection, e.g. has never 59 // True if this is a new connection, e.g. has never
60 // displayed a prompt to the user. 60 // displayed a prompt to the user.
61 public bool newConnection = true; 61 public bool newConnection = true;
62 } 62 }
63 63
64 // A line in the scrollback buffer. 64 // A line in the scrollback buffer.
65 protected class ScrollbackEntry 65 protected class ScrollbackEntry
66 { 66 {
67 // The line number of this entry 67 // The line number of this entry
68 public long lineNumber; 68 public long lineNumber;
69 69
70 // The text to send to the client 70 // The text to send to the client
71 public string text; 71 public string text;
72 72
73 // The level this should be logged as. Omitted for 73 // The level this should be logged as. Omitted for
74 // prompts and input echo. 74 // prompts and input echo.
75 public string level; 75 public string level;
76 76
77 // True if the text above is a prompt, e.g. the 77 // True if the text above is a prompt, e.g. the
78 // client should turn on the cursor / accept input 78 // client should turn on the cursor / accept input
79 public bool isPrompt; 79 public bool isPrompt;
80 80
81 // True if the requested input is a command. A 81 // True if the requested input is a command. A
82 // client may offer help or validate input if 82 // client may offer help or validate input if
83 // this is set. If false, input should be sent 83 // this is set. If false, input should be sent
84 // as typed. 84 // as typed.
85 public bool isCommand; 85 public bool isCommand;
86 86
87 // True if this text represents a line of text that 87 // True if this text represents a line of text that
88 // was input in response to a prompt. A client should 88 // was input in response to a prompt. A client should
89 // turn off the cursor and refrain from sending commands 89 // turn off the cursor and refrain from sending commands
90 // until a new prompt is received. 90 // until a new prompt is received.
91 public bool isInput; 91 public bool isInput;
92 } 92 }
93 93
94 // Data that is relevant to all connections 94 // Data that is relevant to all connections
95 95
96 // The scrollback buffer 96 // The scrollback buffer
97 protected List<ScrollbackEntry> m_Scrollback = new List<ScrollbackEntry>(); 97 protected List<ScrollbackEntry> m_Scrollback = new List<ScrollbackEntry>();
98 98
99 // Monotonously incrementing line number. This may eventually 99 // Monotonously incrementing line number. This may eventually
100 // wrap. No provision is made for that case because 64 bits 100 // wrap. No provision is made for that case because 64 bits
101 // is a long, long time. 101 // is a long, long time.
102 protected long m_lineNumber = 0; 102 protected long m_lineNumber = 0;
103 103
104 // These two variables allow us to send the correct 104 // These two variables allow us to send the correct
105 // information about the prompt status to the client, 105 // information about the prompt status to the client,
106 // irrespective of what may have run off the top of the 106 // irrespective of what may have run off the top of the
107 // scrollback buffer; 107 // scrollback buffer;
108 protected bool m_expectingInput = false; 108 protected bool m_expectingInput = false;
109 protected bool m_expectingCommand = true; 109 protected bool m_expectingCommand = true;
110 protected string m_lastPromptUsed; 110 protected string m_lastPromptUsed;
111 111
112 // This is the list of things received from clients. 112 // This is the list of things received from clients.
113 // Note: Race conditions can happen. If a client sends 113 // Note: Race conditions can happen. If a client sends
114 // something while nothing is expected, it will be 114 // something while nothing is expected, it will be
115 // intepreted as input to the next prompt. For 115 // intepreted as input to the next prompt. For
116 // commands this is largely correct. For other prompts, 116 // commands this is largely correct. For other prompts,
117 // YMMV. 117 // YMMV.
118 // TODO: Find a better way to fix this 118 // TODO: Find a better way to fix this
119 protected List<string> m_InputData = new List<string>(); 119 protected List<string> m_InputData = new List<string>();
120 120
121 // Event to allow ReadLine to wait synchronously even though 121 // Event to allow ReadLine to wait synchronously even though
122 // everthing else is asynchronous here. 122 // everthing else is asynchronous here.
123 protected ManualResetEvent m_DataEvent = new ManualResetEvent(false); 123 protected ManualResetEvent m_DataEvent = new ManualResetEvent(false);
124 124
125 // The list of sessions we maintain. Unlike other console types, 125 // The list of sessions we maintain. Unlike other console types,
126 // multiple users on the same console are explicitly allowed. 126 // multiple users on the same console are explicitly allowed.
127 protected Dictionary<UUID, ConsoleConnection> m_Connections = 127 protected Dictionary<UUID, ConsoleConnection> m_Connections =
128 new Dictionary<UUID, ConsoleConnection>(); 128 new Dictionary<UUID, ConsoleConnection>();
129 129
130 // Timer to control expiration of sessions that have been 130 // Timer to control expiration of sessions that have been
131 // disconnected. 131 // disconnected.
132 protected System.Timers.Timer m_expireTimer = new System.Timers.Timer(5000); 132 protected System.Timers.Timer m_expireTimer = new System.Timers.Timer(5000);
133 133
134 // The less interesting stuff that makes the actual server 134 // The less interesting stuff that makes the actual server
135 // work. 135 // work.
136 protected IHttpServer m_Server = null; 136 protected IHttpServer m_Server = null;
137 protected IConfigSource m_Config = null; 137 protected IConfigSource m_Config = null;
138 138
@@ -143,130 +143,130 @@ namespace OpenSim.Framework.Console
143 143
144 public RemoteConsole(string defaultPrompt) : base(defaultPrompt) 144 public RemoteConsole(string defaultPrompt) : base(defaultPrompt)
145 { 145 {
146 // There is something wrong with this architecture. 146 // There is something wrong with this architecture.
147 // A prompt is sent on every single input, so why have this? 147 // A prompt is sent on every single input, so why have this?
148 // TODO: Investigate and fix. 148 // TODO: Investigate and fix.
149 m_lastPromptUsed = defaultPrompt; 149 m_lastPromptUsed = defaultPrompt;
150 150
151 // Start expiration of sesssions. 151 // Start expiration of sesssions.
152 m_expireTimer.Elapsed += DoExpire; 152 m_expireTimer.Elapsed += DoExpire;
153 m_expireTimer.Start(); 153 m_expireTimer.Start();
154 } 154 }
155 155
156 public void ReadConfig(IConfigSource config) 156 public void ReadConfig(IConfigSource config)
157 { 157 {
158 m_Config = config; 158 m_Config = config;
159 159
160 // We're pulling this from the 'Network' section for legacy 160 // We're pulling this from the 'Network' section for legacy
161 // compatibility. However, this is so essentially insecure 161 // compatibility. However, this is so essentially insecure
162 // that TLS and client certs should be used instead of 162 // that TLS and client certs should be used instead of
163 // a username / password. 163 // a username / password.
164 IConfig netConfig = m_Config.Configs["Network"]; 164 IConfig netConfig = m_Config.Configs["Network"];
165 165
166 if (netConfig == null) 166 if (netConfig == null)
167 return; 167 return;
168 168
169 // Get the username and password. 169 // Get the username and password.
170 m_UserName = netConfig.GetString("ConsoleUser", String.Empty); 170 m_UserName = netConfig.GetString("ConsoleUser", String.Empty);
171 m_Password = netConfig.GetString("ConsolePass", String.Empty); 171 m_Password = netConfig.GetString("ConsolePass", String.Empty);
172 172
173 // Woefully underdocumented, this is what makes javascript 173 // Woefully underdocumented, this is what makes javascript
174 // console clients work. Set to "*" for anywhere or (better) 174 // console clients work. Set to "*" for anywhere or (better)
175 // to specific addresses. 175 // to specific addresses.
176 m_AllowedOrigin = netConfig.GetString("ConsoleAllowedOrigin", String.Empty); 176 m_AllowedOrigin = netConfig.GetString("ConsoleAllowedOrigin", String.Empty);
177 } 177 }
178 178
179 public void SetServer(IHttpServer server) 179 public void SetServer(IHttpServer server)
180 { 180 {
181 // This is called by the framework to give us the server 181 // This is called by the framework to give us the server
182 // instance (means: port) to work with. 182 // instance (means: port) to work with.
183 m_Server = server; 183 m_Server = server;
184 184
185 // Add our handlers 185 // Add our handlers
186 m_Server.AddHTTPHandler("/StartSession/", HandleHttpStartSession); 186 m_Server.AddHTTPHandler("/StartSession/", HandleHttpStartSession);
187 m_Server.AddHTTPHandler("/CloseSession/", HandleHttpCloseSession); 187 m_Server.AddHTTPHandler("/CloseSession/", HandleHttpCloseSession);
188 m_Server.AddHTTPHandler("/SessionCommand/", HandleHttpSessionCommand); 188 m_Server.AddHTTPHandler("/SessionCommand/", HandleHttpSessionCommand);
189 } 189 }
190 190
191 public override void Output(string text, string level) 191 public override void Output(string text, string level)
192 { 192 {
193 Output(text, level, false, false, false); 193 Output(text, level, false, false, false);
194 } 194 }
195 195
196 protected void Output(string text, string level, bool isPrompt, bool isCommand, bool isInput) 196 protected void Output(string text, string level, bool isPrompt, bool isCommand, bool isInput)
197 { 197 {
198 // Increment the line number. It was 0 and they start at 1 198 // Increment the line number. It was 0 and they start at 1
199 // so we need to pre-increment. 199 // so we need to pre-increment.
200 m_lineNumber++; 200 m_lineNumber++;
201 201
202 // Create and populate the new entry. 202 // Create and populate the new entry.
203 ScrollbackEntry newEntry = new ScrollbackEntry(); 203 ScrollbackEntry newEntry = new ScrollbackEntry();
204 204
205 newEntry.lineNumber = m_lineNumber; 205 newEntry.lineNumber = m_lineNumber;
206 newEntry.text = text; 206 newEntry.text = text;
207 newEntry.level = level; 207 newEntry.level = level;
208 newEntry.isPrompt = isPrompt; 208 newEntry.isPrompt = isPrompt;
209 newEntry.isCommand = isCommand; 209 newEntry.isCommand = isCommand;
210 newEntry.isInput = isInput; 210 newEntry.isInput = isInput;
211 211
212 // Add a line to the scrollback. In some cases, that may not 212 // Add a line to the scrollback. In some cases, that may not
213 // actually be a line of text. 213 // actually be a line of text.
214 lock (m_Scrollback) 214 lock (m_Scrollback)
215 { 215 {
216 // Prune the scrollback to the length se send as connect 216 // Prune the scrollback to the length se send as connect
217 // burst to give the user some context. 217 // burst to give the user some context.
218 while (m_Scrollback.Count >= 1000) 218 while (m_Scrollback.Count >= 1000)
219 m_Scrollback.RemoveAt(0); 219 m_Scrollback.RemoveAt(0);
220 220
221 m_Scrollback.Add(newEntry); 221 m_Scrollback.Add(newEntry);
222 } 222 }
223 223
224 // Let the rest of the system know we have output something. 224 // Let the rest of the system know we have output something.
225 FireOnOutput(text.Trim()); 225 FireOnOutput(text.Trim());
226 226
227 // Also display it for debugging. 227 // Also display it for debugging.
228 System.Console.WriteLine(text.Trim()); 228 System.Console.WriteLine(text.Trim());
229 } 229 }
230 230
231 public override void Output(string text) 231 public override void Output(string text)
232 { 232 {
233 // Output plain (non-logging style) text. 233 // Output plain (non-logging style) text.
234 Output(text, String.Empty, false, false, false); 234 Output(text, String.Empty, false, false, false);
235 } 235 }
236 236
237 public override string ReadLine(string p, bool isCommand, bool e) 237 public override string ReadLine(string p, bool isCommand, bool e)
238 { 238 {
239 // Output the prompt an prepare to wait. This 239 // Output the prompt an prepare to wait. This
240 // is called on a dedicated console thread and 240 // is called on a dedicated console thread and
241 // needs to be synchronous. Old architecture but 241 // needs to be synchronous. Old architecture but
242 // not worth upgrading. 242 // not worth upgrading.
243 if (isCommand) 243 if (isCommand)
244 { 244 {
245 m_expectingInput = true; 245 m_expectingInput = true;
246 m_expectingCommand = true; 246 m_expectingCommand = true;
247 Output(p, String.Empty, true, true, false); 247 Output(p, String.Empty, true, true, false);
248 m_lastPromptUsed = p; 248 m_lastPromptUsed = p;
249 } 249 }
250 else 250 else
251 { 251 {
252 m_expectingInput = true; 252 m_expectingInput = true;
253 Output(p, String.Empty, true, false, false); 253 Output(p, String.Empty, true, false, false);
254 } 254 }
255 255
256 256
257 // Here is where we wait for the user to input something. 257 // Here is where we wait for the user to input something.
258 m_DataEvent.WaitOne(); 258 m_DataEvent.WaitOne();
259 259
260 string cmdinput; 260 string cmdinput;
261 261
262 // Check for empty input. Read input if not empty. 262 // Check for empty input. Read input if not empty.
263 lock (m_InputData) 263 lock (m_InputData)
264 { 264 {
265 if (m_InputData.Count == 0) 265 if (m_InputData.Count == 0)
266 { 266 {
267 m_DataEvent.Reset(); 267 m_DataEvent.Reset();
268 m_expectingInput = false; 268 m_expectingInput = false;
269 m_expectingCommand = false; 269 m_expectingCommand = false;
270 270
271 return ""; 271 return "";
272 } 272 }
@@ -278,19 +278,19 @@ namespace OpenSim.Framework.Console
278 278
279 } 279 }
280 280
281 m_expectingInput = false; 281 m_expectingInput = false;
282 m_expectingCommand = false; 282 m_expectingCommand = false;
283 283
284 // Echo to all the other users what we have done. This 284 // Echo to all the other users what we have done. This
285 // will also go to ourselves. 285 // will also go to ourselves.
286 Output (cmdinput, String.Empty, false, false, true); 286 Output (cmdinput, String.Empty, false, false, true);
287 287
288 // If this is a command, we need to resolve and execute it. 288 // If this is a command, we need to resolve and execute it.
289 if (isCommand) 289 if (isCommand)
290 { 290 {
291 // This call will actually execute the command and create 291 // This call will actually execute the command and create
292 // any output associated with it. The core just gets an 292 // any output associated with it. The core just gets an
293 // empty string so it will call again immediately. 293 // empty string so it will call again immediately.
294 string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); 294 string[] cmd = Commands.Resolve(Parser.Parse(cmdinput));
295 295
296 if (cmd.Length != 0) 296 if (cmd.Length != 0)
@@ -306,11 +306,11 @@ namespace OpenSim.Framework.Console
306 } 306 }
307 } 307 }
308 308
309 // Return the raw input string if not a command. 309 // Return the raw input string if not a command.
310 return cmdinput; 310 return cmdinput;
311 } 311 }
312 312
313 // Very simplistic static access control header. 313 // Very simplistic static access control header.
314 protected Hashtable CheckOrigin(Hashtable result) 314 protected Hashtable CheckOrigin(Hashtable result)
315 { 315 {
316 if (!string.IsNullOrEmpty(m_AllowedOrigin)) 316 if (!string.IsNullOrEmpty(m_AllowedOrigin))
@@ -338,21 +338,21 @@ namespace OpenSim.Framework.Console
338 338
339 protected void DoExpire(Object sender, ElapsedEventArgs e) 339 protected void DoExpire(Object sender, ElapsedEventArgs e)
340 { 340 {
341 // Iterate the list of console connections and find those we 341 // Iterate the list of console connections and find those we
342 // haven't heard from for longer then the longpoll interval. 342 // haven't heard from for longer then the longpoll interval.
343 // Remove them. 343 // Remove them.
344 List<UUID> expired = new List<UUID>(); 344 List<UUID> expired = new List<UUID>();
345 345
346 lock (m_Connections) 346 lock (m_Connections)
347 { 347 {
348 // Mark the expired ones 348 // Mark the expired ones
349 foreach (KeyValuePair<UUID, ConsoleConnection> kvp in m_Connections) 349 foreach (KeyValuePair<UUID, ConsoleConnection> kvp in m_Connections)
350 { 350 {
351 if (System.Environment.TickCount - kvp.Value.last > 500000) 351 if (System.Environment.TickCount - kvp.Value.last > 500000)
352 expired.Add(kvp.Key); 352 expired.Add(kvp.Key);
353 } 353 }
354 354
355 // Delete them 355 // Delete them
356 foreach (UUID id in expired) 356 foreach (UUID id in expired)
357 { 357 {
358 m_Connections.Remove(id); 358 m_Connections.Remove(id);
@@ -361,10 +361,10 @@ namespace OpenSim.Framework.Console
361 } 361 }
362 } 362 }
363 363
364 // Start a new session. 364 // Start a new session.
365 protected Hashtable HandleHttpStartSession(Hashtable request) 365 protected Hashtable HandleHttpStartSession(Hashtable request)
366 { 366 {
367 // The login is in the form of a http form post 367 // The login is in the form of a http form post
368 Hashtable post = DecodePostString(request["body"].ToString()); 368 Hashtable post = DecodePostString(request["body"].ToString());
369 Hashtable reply = new Hashtable(); 369 Hashtable reply = new Hashtable();
370 370
@@ -372,7 +372,7 @@ namespace OpenSim.Framework.Console
372 reply["int_response_code"] = 401; 372 reply["int_response_code"] = 401;
373 reply["content_type"] = "text/plain"; 373 reply["content_type"] = "text/plain";
374 374
375 // Check user name and password 375 // Check user name and password
376 if (m_UserName == String.Empty) 376 if (m_UserName == String.Empty)
377 return reply; 377 return reply;
378 378
@@ -385,28 +385,28 @@ namespace OpenSim.Framework.Console
385 return reply; 385 return reply;
386 } 386 }
387 387
388 // Set up the new console connection record 388 // Set up the new console connection record
389 ConsoleConnection c = new ConsoleConnection(); 389 ConsoleConnection c = new ConsoleConnection();
390 c.last = System.Environment.TickCount; 390 c.last = System.Environment.TickCount;
391 c.lastLineSeen = 0; 391 c.lastLineSeen = 0;
392 392
393 // Assign session ID 393 // Assign session ID
394 UUID sessionID = UUID.Random(); 394 UUID sessionID = UUID.Random();
395 395
396 // Add connection to list. 396 // Add connection to list.
397 lock (m_Connections) 397 lock (m_Connections)
398 { 398 {
399 m_Connections[sessionID] = c; 399 m_Connections[sessionID] = c;
400 } 400 }
401 401
402 // This call is a CAP. The URL is the authentication. 402 // This call is a CAP. The URL is the authentication.
403 string uri = "/ReadResponses/" + sessionID.ToString() + "/"; 403 string uri = "/ReadResponses/" + sessionID.ToString() + "/";
404 404
405 m_Server.AddPollServiceHTTPHandler( 405 m_Server.AddPollServiceHTTPHandler(
406 uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout 406 uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
407 407
408 // Our reply is an XML document. 408 // Our reply is an XML document.
409 // TODO: Change this to Linq.Xml 409 // TODO: Change this to Linq.Xml
410 XmlDocument xmldoc = new XmlDocument(); 410 XmlDocument xmldoc = new XmlDocument();
411 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 411 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
412 "", ""); 412 "", "");
@@ -429,7 +429,7 @@ namespace OpenSim.Framework.Console
429 429
430 rootElement.AppendChild(MainConsole.Instance.Commands.GetXml(xmldoc)); 430 rootElement.AppendChild(MainConsole.Instance.Commands.GetXml(xmldoc));
431 431
432 // Set up the response and check origin 432 // Set up the response and check origin
433 reply["str_response_string"] = xmldoc.InnerXml; 433 reply["str_response_string"] = xmldoc.InnerXml;
434 reply["int_response_code"] = 200; 434 reply["int_response_code"] = 200;
435 reply["content_type"] = "text/xml"; 435 reply["content_type"] = "text/xml";
@@ -438,7 +438,7 @@ namespace OpenSim.Framework.Console
438 return reply; 438 return reply;
439 } 439 }
440 440
441 // Client closes session. Clean up. 441 // Client closes session. Clean up.
442 protected Hashtable HandleHttpCloseSession(Hashtable request) 442 protected Hashtable HandleHttpCloseSession(Hashtable request)
443 { 443 {
444 Hashtable post = DecodePostString(request["body"].ToString()); 444 Hashtable post = DecodePostString(request["body"].ToString());
@@ -487,7 +487,7 @@ namespace OpenSim.Framework.Console
487 return reply; 487 return reply;
488 } 488 }
489 489
490 // Command received from the client. 490 // Command received from the client.
491 protected Hashtable HandleHttpSessionCommand(Hashtable request) 491 protected Hashtable HandleHttpSessionCommand(Hashtable request)
492 { 492 {
493 Hashtable post = DecodePostString(request["body"].ToString()); 493 Hashtable post = DecodePostString(request["body"].ToString());
@@ -497,7 +497,7 @@ namespace OpenSim.Framework.Console
497 reply["int_response_code"] = 404; 497 reply["int_response_code"] = 404;
498 reply["content_type"] = "text/plain"; 498 reply["content_type"] = "text/plain";
499 499
500 // Check the ID 500 // Check the ID
501 if (post["ID"] == null) 501 if (post["ID"] == null)
502 return reply; 502 return reply;
503 503
@@ -505,25 +505,25 @@ namespace OpenSim.Framework.Console
505 if (!UUID.TryParse(post["ID"].ToString(), out id)) 505 if (!UUID.TryParse(post["ID"].ToString(), out id))
506 return reply; 506 return reply;
507 507
508 // Find the connection for that ID. 508 // Find the connection for that ID.
509 lock (m_Connections) 509 lock (m_Connections)
510 { 510 {
511 if (!m_Connections.ContainsKey(id)) 511 if (!m_Connections.ContainsKey(id))
512 return reply; 512 return reply;
513 } 513 }
514 514
515 // Empty post. Just error out. 515 // Empty post. Just error out.
516 if (post["COMMAND"] == null) 516 if (post["COMMAND"] == null)
517 return reply; 517 return reply;
518 518
519 // Place the input data in the buffer. 519 // Place the input data in the buffer.
520 lock (m_InputData) 520 lock (m_InputData)
521 { 521 {
522 m_DataEvent.Set(); 522 m_DataEvent.Set();
523 m_InputData.Add(post["COMMAND"].ToString()); 523 m_InputData.Add(post["COMMAND"].ToString());
524 } 524 }
525 525
526 // Create the XML reply document. 526 // Create the XML reply document.
527 XmlDocument xmldoc = new XmlDocument(); 527 XmlDocument xmldoc = new XmlDocument();
528 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 528 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
529 "", ""); 529 "", "");
@@ -547,7 +547,7 @@ namespace OpenSim.Framework.Console
547 return reply; 547 return reply;
548 } 548 }
549 549
550 // Decode a HTTP form post to a Hashtable 550 // Decode a HTTP form post to a Hashtable
551 protected Hashtable DecodePostString(string data) 551 protected Hashtable DecodePostString(string data)
552 { 552 {
553 Hashtable result = new Hashtable(); 553 Hashtable result = new Hashtable();
@@ -565,14 +565,14 @@ namespace OpenSim.Framework.Console
565 565
566 if (elems.Length > 1) 566 if (elems.Length > 1)
567 value = System.Web.HttpUtility.UrlDecode(elems[1]); 567 value = System.Web.HttpUtility.UrlDecode(elems[1]);
568 568
569 result[name] = value; 569 result[name] = value;
570 } 570 }
571 571
572 return result; 572 return result;
573 } 573 }
574 574
575 // Close the CAP receiver for the responses for a given client. 575 // Close the CAP receiver for the responses for a given client.
576 public void CloseConnection(UUID id) 576 public void CloseConnection(UUID id)
577 { 577 {
578 try 578 try
@@ -586,8 +586,8 @@ namespace OpenSim.Framework.Console
586 } 586 }
587 } 587 }
588 588
589 // Check if there is anything to send. Return true if this client has 589 // Check if there is anything to send. Return true if this client has
590 // lines pending. 590 // lines pending.
591 protected bool HasEvents(UUID RequestID, UUID sessionID) 591 protected bool HasEvents(UUID RequestID, UUID sessionID)
592 { 592 {
593 ConsoleConnection c = null; 593 ConsoleConnection c = null;
@@ -604,10 +604,10 @@ namespace OpenSim.Framework.Console
604 return false; 604 return false;
605 } 605 }
606 606
607 // Send all pending output to the client. 607 // Send all pending output to the client.
608 protected Hashtable GetEvents(UUID RequestID, UUID sessionID) 608 protected Hashtable GetEvents(UUID RequestID, UUID sessionID)
609 { 609 {
610 // Find the connection that goes with this client. 610 // Find the connection that goes with this client.
611 ConsoleConnection c = null; 611 ConsoleConnection c = null;
612 612
613 lock (m_Connections) 613 lock (m_Connections)
@@ -617,14 +617,14 @@ namespace OpenSim.Framework.Console
617 c = m_Connections[sessionID]; 617 c = m_Connections[sessionID];
618 } 618 }
619 619
620 // If we have nothing to send, send the no events response. 620 // If we have nothing to send, send the no events response.
621 c.last = System.Environment.TickCount; 621 c.last = System.Environment.TickCount;
622 if (c.lastLineSeen >= m_lineNumber) 622 if (c.lastLineSeen >= m_lineNumber)
623 return NoEvents(RequestID, UUID.Zero); 623 return NoEvents(RequestID, UUID.Zero);
624 624
625 Hashtable result = new Hashtable(); 625 Hashtable result = new Hashtable();
626 626
627 // Create the response document. 627 // Create the response document.
628 XmlDocument xmldoc = new XmlDocument(); 628 XmlDocument xmldoc = new XmlDocument();
629 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 629 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
630 "", ""); 630 "", "");
@@ -648,29 +648,29 @@ namespace OpenSim.Framework.Console
648 648
649 for (long i = sendStart ; i < m_lineNumber ; i++) 649 for (long i = sendStart ; i < m_lineNumber ; i++)
650 { 650 {
651 ScrollbackEntry e = m_Scrollback[(int)(i - startLine)]; 651 ScrollbackEntry e = m_Scrollback[(int)(i - startLine)];
652 652
653 XmlElement res = xmldoc.CreateElement("", "Line", ""); 653 XmlElement res = xmldoc.CreateElement("", "Line", "");
654 res.SetAttribute("Number", e.lineNumber.ToString()); 654 res.SetAttribute("Number", e.lineNumber.ToString());
655 res.SetAttribute("Level", e.level); 655 res.SetAttribute("Level", e.level);
656 // Don't include these for the scrollback, we'll send the 656 // Don't include these for the scrollback, we'll send the
657 // real state later. 657 // real state later.
658 if (!c.newConnection) 658 if (!c.newConnection)
659 { 659 {
660 res.SetAttribute("Prompt", e.isPrompt ? "true" : "false"); 660 res.SetAttribute("Prompt", e.isPrompt ? "true" : "false");
661 res.SetAttribute("Command", e.isCommand ? "true" : "false"); 661 res.SetAttribute("Command", e.isCommand ? "true" : "false");
662 res.SetAttribute("Input", e.isInput ? "true" : "false"); 662 res.SetAttribute("Input", e.isInput ? "true" : "false");
663 } 663 }
664 else if (i == m_lineNumber - 1) // Last line for a new connection 664 else if (i == m_lineNumber - 1) // Last line for a new connection
665 { 665 {
666 res.SetAttribute("Prompt", m_expectingInput ? "true" : "false"); 666 res.SetAttribute("Prompt", m_expectingInput ? "true" : "false");
667 res.SetAttribute("Command", m_expectingCommand ? "true" : "false"); 667 res.SetAttribute("Command", m_expectingCommand ? "true" : "false");
668 res.SetAttribute("Input", (!m_expectingInput) ? "true" : "false"); 668 res.SetAttribute("Input", (!m_expectingInput) ? "true" : "false");
669 } 669 }
670 else 670 else
671 { 671 {
672 res.SetAttribute("Input", e.isInput ? "true" : "false"); 672 res.SetAttribute("Input", e.isInput ? "true" : "false");
673 } 673 }
674 674
675 res.AppendChild(xmldoc.CreateTextNode(e.text)); 675 res.AppendChild(xmldoc.CreateTextNode(e.text));
676 676
@@ -679,7 +679,7 @@ namespace OpenSim.Framework.Console
679 } 679 }
680 680
681 c.lastLineSeen = m_lineNumber; 681 c.lastLineSeen = m_lineNumber;
682 c.newConnection = false; 682 c.newConnection = false;
683 683
684 xmldoc.AppendChild(rootElement); 684 xmldoc.AppendChild(rootElement);
685 685
@@ -693,8 +693,8 @@ namespace OpenSim.Framework.Console
693 return result; 693 return result;
694 } 694 }
695 695
696 // This is really just a no-op. It generates what is sent 696 // This is really just a no-op. It generates what is sent
697 // to the client if the poll times out without any events. 697 // to the client if the poll times out without any events.
698 protected Hashtable NoEvents(UUID RequestID, UUID id) 698 protected Hashtable NoEvents(UUID RequestID, UUID id)
699 { 699 {
700 Hashtable result = new Hashtable(); 700 Hashtable result = new Hashtable();