2 Commits

Author SHA1 Message Date
Leonmmcoset
ec7e0978d3 增加设置项MaxLoginAttempts(默认3) 2026-02-28 19:39:48 +08:00
Leonmmcoset
c5fc081977 hex命令 2026-02-28 19:24:02 +08:00
12 changed files with 440 additions and 6 deletions

View File

@@ -1 +1 @@
2026-02-28 16:28:03
2026-02-28 19:35:58

View File

@@ -1 +1 @@
02ff829
c5fc081

View File

@@ -11,7 +11,8 @@ namespace CMLeonOS.Settings
private static Dictionary<string, string> defaultSettings = new Dictionary<string, string>
{
{ "LoggerEnabled", "true" }
{ "LoggerEnabled", "true" },
{ "MaxLoginAttempts", "3" }
};
public static bool LoggerEnabled
@@ -31,6 +32,26 @@ namespace CMLeonOS.Settings
}
}
public static int MaxLoginAttempts
{
get
{
if (settings.TryGetValue("MaxLoginAttempts", out string value))
{
if (int.TryParse(value, out int result))
{
return result;
}
}
return 3;
}
set
{
settings["MaxLoginAttempts"] = value.ToString();
SaveSettings();
}
}
public static void LoadSettings()
{
settings.Clear();

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Sys = Cosmos.System;

View File

@@ -6,6 +6,7 @@ using System.Text;
using System.Threading;
using Sys = Cosmos.System;
using CMLeonOS.Logger;
using CMLeonOS.Settings;
namespace CMLeonOS
{
@@ -25,6 +26,7 @@ namespace CMLeonOS
public bool fixmode = Kernel.FixMode;
private User currentLoggedInUser;
private static CMLeonOS.Logger.Logger _logger = CMLeonOS.Logger.Logger.Instance;
private Dictionary<string, int> loginAttempts = new Dictionary<string, int>();
public User CurrentLoggedInUser
{
@@ -593,13 +595,37 @@ namespace CMLeonOS
if (foundUser.Password != hashedInputPassword)
{
string usernameLower = username.ToLower();
if (!loginAttempts.ContainsKey(usernameLower))
{
loginAttempts[usernameLower] = 0;
}
loginAttempts[usernameLower]++;
int attempts = loginAttempts[usernameLower];
int maxAttempts = Settings.SettingsManager.MaxLoginAttempts;
if (attempts >= maxAttempts)
{
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.Red, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(17, 24);
global::System.Console.Write($"Maximum login attempts ({maxAttempts}) reached. ");
global::System.Console.SetCursorPosition(17, 25);
global::System.Console.Write("Please restart to enter password again. ");
global::System.Threading.Thread.Sleep(3000);
Sys.Power.Reboot();
}
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.Red, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(17, 24);
global::System.Console.Write("Invalid password. ");
global::System.Console.Write($"Invalid password. Attempts: {attempts}/{maxAttempts} ");
global::System.Threading.Thread.Sleep(1000);
return false;
}
loginAttempts.Remove(username.ToLower());
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.Green, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(17, 24);
global::System.Console.Write("Login successful! ");

View File

@@ -329,6 +329,60 @@ nano <file>
nano myfile.txt
```
### hex
使用16进制编辑器编辑二进制文件。
**用法:**
```bash
hex <filename>
```
**示例:**
```bash
hex test.bin
hex kernel.sys
```
**控制键:**
- `↑ ↓ ← →` - 移动光标
- `Page Up / Page Down` - 滚动视图
- `0-9, A-F` - 编辑字节值
- `S` - 保存文件
- `Q` - 退出编辑器
**说明:**
- 显示文件的16进制字节值和对应的ASCII字符
- 每行显示16个字节分为8个字节一组
- 显示每行的偏移地址8位16进制
- 光标位置用白色背景高亮显示
- 文件修改后显示 [MODIFIED] 标记
- 支持查看和编辑任意大小的二进制文件
- 按 S 键保存修改到文件
- 按 Q 键退出编辑器(不保存修改)
**界面示例:**
```
====================================
Hex Editor
====================================
File: test.bin
Size: 256 bytes [MODIFIED]
00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 21 00 00 00 00 |Hello World.....|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Cursor: 0x00000000 (0)
Value: 0x48
Controls:
Arrow Keys - Move cursor
Page Up/Down - Scroll view
0-9, A-F - Edit byte
S - Save file
Q - Quit
```
## 用户管理命令
### user

View File

@@ -214,6 +214,9 @@ namespace CMLeonOS.shell
case "snake":
shell.PlaySnake();
break;
case "hex":
shell.EditHexFile(args);
break;
case "alias":
shell.ProcessAlias(args);
break;

View File

@@ -296,6 +296,12 @@ namespace CMLeonOS.Commands
Description = "Search text in file"
},
new CommandInfo
{
Command = "hex",
Parameters = "<filename>",
Description = "Hexadecimal file editor"
},
new CommandInfo
{
Command = "ping",
Parameters = "<ip>",

View File

@@ -58,6 +58,18 @@ namespace CMLeonOS.Commands
Console.WriteLine("Error: LoggerEnabled must be 'true' or 'false'");
}
}
else if (key.ToLower() == "maxloginattempts")
{
if (int.TryParse(value, out int attempts) && attempts > 0)
{
SettingsManager.MaxLoginAttempts = attempts;
Console.WriteLine($"MaxLoginAttempts set to {attempts}");
}
else
{
Console.WriteLine("Error: MaxLoginAttempts must be a positive integer");
}
}
else
{
SettingsManager.SetSetting(key, value);

View File

@@ -0,0 +1,49 @@
using System;
using System.IO;
namespace CMLeonOS.Commands.Utility
{
public static class HexCommand
{
public static void EditHexFile(string args)
{
try
{
if (string.IsNullOrWhiteSpace(args))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Usage: hex <filename>");
Console.WriteLine("Example: hex test.bin");
Console.WriteLine();
Console.WriteLine("Controls:");
Console.WriteLine(" Arrow Keys - Move cursor");
Console.WriteLine(" Page Up/Down - Scroll view");
Console.WriteLine(" 0-9, A-F - Edit byte");
Console.WriteLine(" S - Save file");
Console.WriteLine(" Q - Quit");
Console.ResetColor();
return;
}
string filePath = args.Trim();
if (!File.Exists(filePath))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"File not found: {filePath}");
Console.ResetColor();
return;
}
var editor = new HexEditor(filePath);
editor.Run();
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Error opening hex editor: {ex.Message}");
Console.ResetColor();
}
}
}
}

View File

@@ -0,0 +1,258 @@
using System;
using System.IO;
namespace CMLeonOS.Commands.Utility
{
public class HexEditor
{
private byte[] data;
private int cursorPosition;
private int viewOffset;
private int bytesPerLine = 16;
private int bytesPerGroup = 2;
private string filePath;
private bool modified;
private bool running;
public HexEditor(string path)
{
filePath = path;
if (File.Exists(path))
{
data = File.ReadAllBytes(path);
}
else
{
data = new byte[256];
}
cursorPosition = 0;
viewOffset = 0;
modified = false;
running = true;
}
public void Run()
{
Console.Clear();
Console.WriteLine("====================================");
Console.WriteLine(" Hex Editor");
Console.WriteLine("====================================");
Console.WriteLine();
Console.WriteLine("File: " + filePath);
Console.WriteLine("Size: " + data.Length + " bytes");
Console.WriteLine();
Console.WriteLine("Controls:");
Console.WriteLine(" Arrow Keys - Move cursor");
Console.WriteLine(" Page Up/Down - Scroll view");
Console.WriteLine(" 0-9, A-F - Edit byte");
Console.WriteLine(" S - Save file");
Console.WriteLine(" Q - Quit");
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
while (running)
{
Display();
HandleInput();
}
}
private void Display()
{
Console.Clear();
Console.WriteLine("====================================");
Console.WriteLine(" Hex Editor");
Console.WriteLine("====================================");
Console.WriteLine();
Console.WriteLine("File: " + filePath);
Console.WriteLine("Size: " + data.Length + " bytes");
if (modified)
{
Console.Write(" [MODIFIED]");
}
Console.WriteLine();
Console.WriteLine();
int lines = (int)Math.Ceiling((double)data.Length / bytesPerLine);
int startLine = viewOffset / bytesPerLine;
int endLine = Math.Min(startLine + 20, lines);
for (int line = startLine; line < endLine; line++)
{
int offset = line * bytesPerLine;
if (offset >= data.Length) break;
Console.Write(offset.ToString("X8") + " ");
for (int i = 0; i < bytesPerLine; i++)
{
int byteOffset = offset + i;
if (byteOffset >= data.Length)
{
Console.Write(" ");
}
else
{
byte b = data[byteOffset];
bool isCursor = (byteOffset == cursorPosition);
if (isCursor)
{
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
}
Console.Write(b.ToString("X2") + " ");
if (isCursor)
{
Console.ResetColor();
}
if ((i + 1) % bytesPerGroup == 0)
{
Console.Write(" ");
}
}
}
Console.Write(" |");
for (int i = 0; i < bytesPerLine; i++)
{
int byteOffset = offset + i;
if (byteOffset >= data.Length)
{
Console.Write(" ");
}
else
{
byte b = data[byteOffset];
bool isCursor = (byteOffset == cursorPosition);
if (isCursor)
{
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
}
char c = (b >= 32 && b <= 126) ? (char)b : '.';
Console.Write(c);
if (isCursor)
{
Console.ResetColor();
}
}
}
Console.WriteLine("|");
}
Console.WriteLine();
Console.WriteLine("Cursor: 0x" + cursorPosition.ToString("X8") + " (" + cursorPosition + ")");
Console.WriteLine("Value: 0x" + data[cursorPosition].ToString("X2"));
Console.WriteLine();
Console.WriteLine("Controls:");
Console.WriteLine(" Arrow Keys - Move cursor");
Console.WriteLine(" Page Up/Down - Scroll view");
Console.WriteLine(" 0-9, A-F - Edit byte");
Console.WriteLine(" S - Save file");
Console.WriteLine(" Q - Quit");
}
private void HandleInput()
{
var key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.UpArrow:
cursorPosition = Math.Max(0, cursorPosition - bytesPerLine);
break;
case ConsoleKey.DownArrow:
cursorPosition = Math.Min(data.Length - 1, cursorPosition + bytesPerLine);
break;
case ConsoleKey.LeftArrow:
cursorPosition = Math.Max(0, cursorPosition - 1);
break;
case ConsoleKey.RightArrow:
cursorPosition = Math.Min(data.Length - 1, cursorPosition + 1);
break;
case ConsoleKey.PageUp:
viewOffset = Math.Max(0, viewOffset - (bytesPerLine * 20));
break;
case ConsoleKey.PageDown:
viewOffset = Math.Min(data.Length - 1, viewOffset + (bytesPerLine * 20));
break;
case ConsoleKey.D0:
case ConsoleKey.D1:
case ConsoleKey.D2:
case ConsoleKey.D3:
case ConsoleKey.D4:
case ConsoleKey.D5:
case ConsoleKey.D6:
case ConsoleKey.D7:
case ConsoleKey.D8:
case ConsoleKey.D9:
int digit = key.KeyChar - '0';
EditByte(digit);
break;
case ConsoleKey.A:
EditByte(10);
break;
case ConsoleKey.B:
EditByte(11);
break;
case ConsoleKey.C:
EditByte(12);
break;
case ConsoleKey.D:
EditByte(13);
break;
case ConsoleKey.E:
EditByte(14);
break;
case ConsoleKey.F:
EditByte(15);
break;
case ConsoleKey.S:
SaveFile();
break;
case ConsoleKey.Q:
running = false;
break;
}
}
private void EditByte(int value)
{
if (cursorPosition >= 0 && cursorPosition < data.Length)
{
data[cursorPosition] = (byte)value;
modified = true;
}
}
private void SaveFile()
{
try
{
File.WriteAllBytes(filePath, data);
modified = false;
Console.WriteLine();
Console.WriteLine("File saved successfully!");
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("Error saving file: " + ex.Message);
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
}
}
}

View File

@@ -409,7 +409,7 @@ namespace CMLeonOS
"cpass", "hostname", "ipconfig", "setdns", "setgateway", "nslookup",
"ping", "wget", "ftp", "tcpserver", "tcpclient", "lua", "lua2cla", "cla",
"branswe", "beep", "env", "whoami", "uptime", "alias",
"unalias", "base64", "testgui", "ps", "kill"
"unalias", "base64", "testgui", "ps", "kill", "hex"
};
}
@@ -1066,6 +1066,11 @@ namespace CMLeonOS
Commands.System.KillCommand.KillProcess(args, ShowError, ShowWarning);
}
public void EditHexFile(string args)
{
Commands.Utility.HexCommand.EditHexFile(args);
}
public void CreateFTP()
{
Console.WriteLine("====================================");