/// <summary> /// Runs the data through our presentation handlers /// </summary> /// <param name="data">The data to format</param> /// <param name="connection">The connection object this data is going to be sent to</param> /// <param name="sendAllData">Indicates if all data should be sent.</param> /// <returns>A formatted string of data</returns> internal static string FormatData(string data, Connection connection, bool sendAllData) { if (connection.Terminal.UseWordWrap && connection.Terminal.Width > 0) { data = WordWrapHandler.Parse(data, connection.Terminal.Width); } if (connection.Terminal.UseBuffer && !sendAllData) { connection.OutputBuffer.Clear(); string[] temp = BufferHandler.Parse(data); string[] output; bool appendOverflow = false; if (temp.Length > connection.PagingRowLimit) { appendOverflow = true; connection.OutputBuffer.Append(temp); output = connection.OutputBuffer.GetRows(BufferDirection.Forward, connection.PagingRowLimit); } else { output = temp; } data = BufferHandler.Format( output, false, appendOverflow, connection.OutputBuffer.CurrentLocation, connection.OutputBuffer.Length); } if (connection.Terminal.UseANSI) { data = AnsiHandler.Parse(data); } else { // TODO: Remove regex into separate parser. var options = RegexOptions.None; var regex = new Regex(@"<%?\w+[^>]*%>", options); string input = data; string replacement = string.Empty; data = regex.Replace(input, replacement); } if (!connection.Terminal.UseMXP) { // TODO: Remove regex into separate parser. var options = RegexOptions.None; var regex = new Regex(@"</?\w+[^>]*>", options); string input = data; string replacement = string.Empty; data = regex.Replace(input, replacement); } return data; }
/// <summary> /// Checks the data passed to it to see if the connection now has /// a command ready. /// </summary> /// <param name="sender">The connection sending the data</param> /// <param name="data">The data received</param> public void OnDataReceived(Connection sender, Byte[] data) { //we can be sure that the data is text because the telnet server has dealt with any nasties string input = Encoding.ASCII.GetString(data); //Append the data to our text buffer. sender.Buffer.Append(input); //get the whole of our buffer input = sender.Buffer.ToString(); input = StripDodgyTerminator(sender, input); //if we have nothing left to process then bail out if (input.Length == 0) { return; } SetLastTerminator(sender, input); //replace any \r\n or \n\r or \n with just \r so that we can just deal with one line marker input = input.Replace("\n", _newLineMarker); input = input.Replace("\r\r", _newLineMarker); //our new line will only be a \r as we removed all \n above. if (input.Contains(_newLineMarker)) { //we have received a newline char in our stream, this means that //we need to raise a command. However we might receive multiple commands //in the same stream as our network connection might be slow. //we have a special case which is not captured by below. //that of just a carriage return being entered in the client. //we should pass that up as a valid command. if (input == _newLineMarker) { RaiseInputReceived(new ConnectionArgs(sender), ""); } //does our input "end" with \r if so then we have a series of full commands. //if it doesnt then we have a partial command at the end which needs to wait for more data. bool fullCommand = input.EndsWith(_newLineMarker); //split on our \r string[] commands = input.Split(new string[] { _newLineMarker }, StringSplitOptions.RemoveEmptyEntries); string action = string.Empty; for (int i = 0; i < commands.Length; i++) { action = commands[i].Trim(); //if its a full command. if ((i < commands.Length - 1) || (i == commands.Length - 1 && fullCommand)) { //fill the last input buffer sender.LastInput = action; //raise the input recevied event RaiseInputReceived(new ConnectionArgs(sender), action); } } //clear the buffer sender.Buffer.Length = 0; if (!fullCommand) { //if the last command wasnt a full command, //we need to append that action back to the buffer sender.Buffer.Append(action); } } }
/// <summary> /// Because of the variation in line terminators between clients we have to choose one /// and strip out the others. This leaves a funny situation when we have determined that /// a command has come in because of \r so we process it but the next string we receive /// begins with \n because the client actually send command\r\n. /// This function checks the last terminator we received and if the opposite one is /// received at the start of the next set of data it removes it. /// </summary> /// <param name="sender">The connection we received the input on</param> /// <param name="input">The input we are checking</param> /// <returns></returns> private static string StripDodgyTerminator(Connection sender, String input) { if ((sender.LastInputTerminator == "\r") && input.StartsWith("\n")) { input = input.Replace("\n", ""); } else if ((sender.LastInputTerminator == "\n") && input.StartsWith("\r")) { input = input.Replace("\r", ""); } return input; }
/// <summary> /// Sets the last input terminator to the termination char(s) we have /// just received (if any) /// </summary> /// <param name="sender">The connection we received input on</param> /// <param name="input">The input we are checking</param> private static void SetLastTerminator(Connection sender, String input) { if (input.Contains("\r") & input.Contains("\n")) { sender.LastInputTerminator = "\r\n"; } else if (input.Contains("\r")) { sender.LastInputTerminator = "\r"; } else if (input.Contains("\n")) { sender.LastInputTerminator = "\n"; } }