| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Globalization; |
| | | 4 | | using System.Text; |
| | | 5 | | |
| | | 6 | | namespace Renci.SshNet.Common |
| | | 7 | | { |
| | | 8 | | internal static class PacketDump |
| | | 9 | | { |
| | | 10 | | public static string Create(List<byte> data, int indentLevel) |
| | 39 | 11 | | { |
| | 39 | 12 | | return Create(data.ToArray(), indentLevel); |
| | 39 | 13 | | } |
| | | 14 | | |
| | | 15 | | public static string Create(byte[] data, int indentLevel) |
| | 84 | 16 | | { |
| | 84 | 17 | | if (data is null) |
| | 3 | 18 | | { |
| | 3 | 19 | | throw new ArgumentNullException(nameof(data)); |
| | | 20 | | } |
| | | 21 | | |
| | 81 | 22 | | if (indentLevel < 0) |
| | 3 | 23 | | { |
| | 3 | 24 | | throw new ArgumentOutOfRangeException(nameof(indentLevel), "Cannot be less than zero."); |
| | | 25 | | } |
| | | 26 | | |
| | | 27 | | const int lineWidth = 16; |
| | | 28 | | |
| | 78 | 29 | | var result = new StringBuilder(); |
| | 78 | 30 | | var line = new byte[lineWidth]; |
| | 78 | 31 | | var indentChars = new string(' ', indentLevel); |
| | | 32 | | |
| | 382 | 33 | | for (var pos = 0; pos < data.Length; ) |
| | 226 | 34 | | { |
| | 226 | 35 | | var linePos = 0; |
| | | 36 | | |
| | 226 | 37 | | if (result.Length > 0) |
| | 151 | 38 | | { |
| | 151 | 39 | | _ = result.Append(Environment.NewLine); |
| | 151 | 40 | | } |
| | | 41 | | |
| | 226 | 42 | | _ = result.Append(indentChars); |
| | 226 | 43 | | _ = result.Append(pos.ToString("X8")); |
| | 226 | 44 | | _ = result.Append(" "); |
| | | 45 | | |
| | 3055 | 46 | | while (true) |
| | 3055 | 47 | | { |
| | 3055 | 48 | | line[linePos++] = data[pos++]; |
| | | 49 | | |
| | 3055 | 50 | | if (linePos == lineWidth || pos == data.Length) |
| | 226 | 51 | | { |
| | 226 | 52 | | break; |
| | | 53 | | } |
| | 2829 | 54 | | } |
| | | 55 | | |
| | 226 | 56 | | _ = result.Append(AsHex(line, linePos)); |
| | 226 | 57 | | _ = result.Append(" "); |
| | 226 | 58 | | _ = result.Append(AsAscii(line, linePos)); |
| | 226 | 59 | | } |
| | | 60 | | |
| | 78 | 61 | | return result.ToString(); |
| | 78 | 62 | | } |
| | | 63 | | |
| | | 64 | | private static string AsHex(byte[] data, int length) |
| | 226 | 65 | | { |
| | 226 | 66 | | var hex = new StringBuilder(); |
| | | 67 | | |
| | 6562 | 68 | | for (var i = 0; i < length; i++) |
| | 3055 | 69 | | { |
| | 3055 | 70 | | if (i > 0) |
| | 2829 | 71 | | { |
| | 2829 | 72 | | _ = hex.Append(' '); |
| | 2829 | 73 | | } |
| | | 74 | | |
| | 3055 | 75 | | _ = hex.Append(data[i].ToString("X2", CultureInfo.InvariantCulture)); |
| | 3055 | 76 | | } |
| | | 77 | | |
| | 226 | 78 | | if (length < data.Length) |
| | 64 | 79 | | { |
| | 64 | 80 | | _ = hex.Append(new string(' ', (data.Length - length) * 3)); |
| | 64 | 81 | | } |
| | | 82 | | |
| | 226 | 83 | | return hex.ToString(); |
| | 226 | 84 | | } |
| | | 85 | | |
| | | 86 | | private static string AsAscii(byte[] data, int length) |
| | 226 | 87 | | { |
| | 226 | 88 | | var encoding = Encoding.ASCII; |
| | | 89 | | |
| | 226 | 90 | | var ascii = new StringBuilder(); |
| | | 91 | | const char dot = '.'; |
| | | 92 | | |
| | 6562 | 93 | | for (var i = 0; i < length; i++) |
| | 3055 | 94 | | { |
| | 3055 | 95 | | var b = data[i]; |
| | | 96 | | |
| | 3055 | 97 | | if (b is < 32 or >= 127) |
| | 568 | 98 | | { |
| | 568 | 99 | | _ = ascii.Append(dot); |
| | 568 | 100 | | } |
| | | 101 | | else |
| | 2487 | 102 | | { |
| | 2487 | 103 | | _ = ascii.Append(encoding.GetString(data, i, 1)); |
| | 2487 | 104 | | } |
| | 3055 | 105 | | } |
| | | 106 | | |
| | 226 | 107 | | return ascii.ToString(); |
| | 226 | 108 | | } |
| | | 109 | | } |
| | | 110 | | } |