diff --git a/Base64.cs b/Base64.cs
new file mode 100644
index 0000000..4f7f9b0
--- /dev/null
+++ b/Base64.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Text;
+
+namespace CMLeonOS
+{
+ ///
+ /// Cosmos裸机专属Base64编码/解码工具类
+ /// 无.NET原生Convert依赖,纯手写实现,适配Cosmos System2
+ ///
+ public static class Base64Helper
+ {
+ // Base64标准编码表(0-63对应),裸机环境直接硬编码,无需动态生成
+ private const string Base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ ///
+ /// Base64编码(加密):将字符串转为Base64编码串(默认UTF8编码)
+ ///
+ /// 原始字符串
+ /// Base64编码后的字符串
+ public static string Encode(string input)
+ {
+ // 空值校验,裸机环境需严格判空
+ if (string.IsNullOrEmpty(input))
+ return string.Empty;
+
+ // 将字符串转为UTF8字节数组(Cosmos支持基础UTF8/ASCII)
+ byte[] inputBytes = Encoding.UTF8.GetBytes(input);
+ // 调用字节数组的编码核心方法
+ return EncodeBytes(inputBytes);
+ }
+
+ ///
+ /// Base64编码(核心):将二进制字节数组转为Base64编码串
+ /// 适配任意二进制数据(文件、网络流、字符串字节)
+ ///
+ /// 原始二进制字节数组
+ /// Base64编码后的字符串
+ public static string EncodeBytes(byte[] inputBytes)
+ {
+ if (inputBytes == null || inputBytes.Length == 0)
+ return string.Empty;
+
+ // 构建结果字符串,裸机用StringBuilder更高效
+ StringBuilder result = new StringBuilder();
+ int inputLength = inputBytes.Length;
+ // 按3字节为一组遍历,处理所有完整组
+ for (int i = 0; i < inputLength; i += 3)
+ {
+ // 取3个字节,不足的补0(位运算用,不修改原数组)
+ byte b1 = i < inputLength ? inputBytes[i] : (byte)0;
+ byte b2 = i + 1 < inputLength ? inputBytes[i + 1] : (byte)0;
+ byte b3 = i + 2 < inputLength ? inputBytes[i + 2] : (byte)0;
+
+ // 核心位运算:3字节(24位)拆分为4个6位
+ // 第一个6位:b1的高6位(右移2位,与0x3F过滤低2位)
+ int idx1 = (b1 >> 2) & 0x3F;
+ // 第二个6位:b1的低2位 + b2的高4位(左移4位 + b2右移4位,与0x3F过滤)
+ int idx2 = ((b1 & 0x03) << 4) | ((b2 >> 4) & 0x0F);
+ // 第三个6位:b2的低4位 + b3的高2位(左移2位 + b3右移6位,与0x3F过滤)
+ int idx3 = ((b2 & 0x0F) << 2) | ((b3 >> 6) & 0x03);
+ // 第四个6位:b3的低6位(与0x3F过滤高2位)
+ int idx4 = b3 & 0x3F;
+
+ // 根据索引取Base64字符,添加到结果
+ result.Append(Base64Table[idx1]);
+ result.Append(Base64Table[idx2]);
+
+ // 补位处理:不足3字节时,用=替代
+ result.Append(i + 1 < inputLength ? Base64Table[idx3] : '=');
+ result.Append(i + 2 < inputLength ? Base64Table[idx4] : '=');
+ }
+
+ return result.ToString();
+ }
+
+ ///
+ /// Base64解码(解密):将Base64编码串转回原始字符串(默认UTF8编码)
+ ///
+ /// Base64编码串
+ /// 解码后的原始字符串
+ /// Base64格式错误时抛出
+ public static string Decode(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return string.Empty;
+
+ // 解码为字节数组,再转为UTF8字符串
+ byte[] outputBytes = DecodeToBytes(input);
+ return Encoding.UTF8.GetString(outputBytes);
+ }
+
+ ///
+ /// Base64解码(核心):将Base64编码串转回原始二进制字节数组
+ /// 适配任意Base64编码的二进制数据
+ ///
+ /// Base64编码串
+ /// 解码后的二进制字节数组
+ /// Base64格式错误时抛出
+ public static byte[] DecodeToBytes(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return Array.Empty();
+
+ // 预处理:过滤所有非Base64有效字符(仅保留编码表字符和=)
+ StringBuilder cleanInput = new StringBuilder();
+ foreach (char c in input)
+ {
+ if (Base64Table.Contains(c) || c == '=')
+ cleanInput.Append(c);
+ }
+ string base64 = cleanInput.ToString();
+ int inputLength = base64.Length;
+
+ // 基础格式校验:Base64长度必须是4的倍数
+ if (inputLength % 4 != 0)
+ throw new ArgumentException("Invalid Base64 string: Length is not a multiple of 4");
+
+ // 计算补位符数量(=的个数,只能是0/1/2)
+ int padCount = 0;
+ if (base64[inputLength - 1] == '=') padCount++;
+ if (base64[inputLength - 2] == '=') padCount++;
+
+ // 计算解码后的字节数:(4*分组数 - 补位符数) / 3
+ int outputLength = (inputLength * 6) / 8 - padCount;
+ byte[] outputBytes = new byte[outputLength];
+ int outputIndex = 0;
+
+ // 按4个字符为一组遍历,处理所有组
+ for (int i = 0; i < inputLength; i += 4)
+ {
+ // 取4个Base64字符,转换为对应的6位索引(0-63)
+ int idx1 = Base64Table.IndexOf(base64[i]);
+ int idx2 = Base64Table.IndexOf(base64[i + 1]);
+ // 补位的=索引为-1,转为0处理
+ int idx3 = i + 2 < inputLength ? Base64Table.IndexOf(base64[i + 2]) : 0;
+ int idx4 = i + 3 < inputLength ? Base64Table.IndexOf(base64[i + 3]) : 0;
+
+ // 基础校验:无效字符(索引为-1且非=)
+ if (idx1 == -1 || idx2 == -1 || (idx3 == -1 && base64[i+2] != '=') || (idx4 == -1 && base64[i+3] != '='))
+ throw new ArgumentException("Invalid Base64 string: Contains invalid characters");
+
+ // 核心位运算:4个6位拼接为24位,拆分为3个字节
+ uint combined = (uint)((idx1 << 18) | (idx2 << 12) | (idx3 << 6) | idx4);
+ // 第一个字节:24位的高8位
+ byte b1 = (byte)((combined >> 16) & 0xFF);
+ // 第二个字节:24位的中间8位
+ byte b2 = (byte)((combined >> 8) & 0xFF);
+ // 第三个字节:24位的低8位
+ byte b3 = (byte)(combined & 0xFF);
+
+ // 将字节写入结果数组,根据补位符数量跳过多余字节
+ if (outputIndex < outputLength)
+ outputBytes[outputIndex++] = b1;
+ if (outputIndex < outputLength)
+ outputBytes[outputIndex++] = b2;
+ if (outputIndex < outputLength)
+ outputBytes[outputIndex++] = b3;
+ }
+
+ return outputBytes;
+ }
+ }
+}
diff --git a/CMLeonOS.csproj b/CMLeonOS.csproj
index cd7da58..bfb4d5c 100644
--- a/CMLeonOS.csproj
+++ b/CMLeonOS.csproj
@@ -42,7 +42,8 @@
-
+
+
diff --git a/Shell.cs b/Shell.cs
index 879b7da..30ef5f7 100644
--- a/Shell.cs
+++ b/Shell.cs
@@ -10,6 +10,7 @@ using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
+using CosmosHttp.Client;
using Cosmos.Core;
using Cosmos.Core.Memory;
using Cosmos.HAL;
@@ -194,6 +195,10 @@ namespace CMLeonOS
" ping - Ping IP address (5 times)",
" tcpserver - Start TCP server on specified port",
" tcpclient - Connect to TCP server",
+ " wget - Download file from URL",
+ " whoami - Show current username",
+ " base64 encrypt - Encode text to Base64",
+ " base64 decrypt - Decode Base64 to text",
" version - Show OS version",
" about - Show about information",
" help - Show help page (1-3)",
@@ -451,6 +456,15 @@ namespace CMLeonOS
case "tcpclient":
ConnectTcpClient(args);
break;
+ case "wget":
+ DownloadFile(args);
+ break;
+ case "whoami":
+ ShowCurrentUsername();
+ break;
+ case "base64":
+ ProcessBase64Command(args);
+ break;
default:
ShowError($"Unknown command: {command}");
break;
@@ -1888,5 +1902,186 @@ namespace CMLeonOS
ShowError($"TCP client error: {ex.Message}");
}
}
+
+ private void DownloadFile(string args)
+ {
+ string[] parts = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (parts.Length == 0)
+ {
+ ShowError("Error: Please specify URL");
+ ShowError("Usage: wget [output]");
+ return;
+ }
+
+ string url = parts[0];
+ string outputPath = parts.Length > 1 ? parts[1] : "";
+
+ Console.WriteLine("====================================");
+ Console.WriteLine(" WGET - File Downloader");
+ Console.WriteLine("====================================");
+ Console.WriteLine();
+ Console.WriteLine($"Downloading from: {url}");
+
+ try
+ {
+ HttpRequest request = new HttpRequest();
+
+ string domain = "";
+ string path = "/";
+
+ if (url.StartsWith("http://"))
+ {
+ url = url.Substring(7);
+ }
+ if (url.StartsWith("https://"))
+ {
+ url = url.Substring(8);
+ }
+
+ int slashIndex = url.IndexOf('/');
+ if (slashIndex == -1)
+ {
+ domain = url;
+ }
+ else
+ {
+ domain = url.Substring(0, slashIndex);
+ path = url.Substring(slashIndex);
+ }
+
+ if (string.IsNullOrWhiteSpace(domain))
+ {
+ ShowError("Error: Invalid URL format");
+ return;
+ }
+
+ Console.WriteLine($"Domain: {domain}");
+ Console.WriteLine($"Path: {path}");
+ Console.WriteLine();
+
+ request.Domain = domain;
+ request.Path = path;
+ request.Method = "GET";
+
+ Console.WriteLine("Sending request...");
+ request.Send();
+
+ if (request.Response == null)
+ {
+ ShowError("Error: No response received");
+ return;
+ }
+
+ byte[] content = Encoding.ASCII.GetBytes(request.Response.Content);
+
+ if (content == null || content.Length == 0)
+ {
+ ShowError("Error: No content received");
+ return;
+ }
+
+ Console.WriteLine($"Downloaded {content.Length} bytes");
+ Console.WriteLine();
+
+ if (string.IsNullOrWhiteSpace(outputPath))
+ {
+ int lastSlash = path.LastIndexOf('/');
+ if (lastSlash >= 0 && lastSlash < path.Length - 1)
+ {
+ outputPath = path.Substring(lastSlash + 1);
+ }
+ else
+ {
+ outputPath = "downloaded_file";
+ }
+ }
+
+ if (!outputPath.StartsWith("0:\\") && !outputPath.StartsWith("0:/"))
+ {
+ outputPath = Path.Combine(prompt, outputPath);
+ }
+
+ Console.WriteLine($"Saving to: {outputPath}");
+
+ File.WriteAllBytes(outputPath, content);
+
+ ShowSuccess($"File saved successfully: {outputPath}");
+ }
+ catch (Exception ex)
+ {
+ ShowError($"Download error: {ex.Message}");
+ }
+ }
+
+ private void ShowCurrentUsername()
+ {
+ Console.WriteLine("====================================");
+ Console.WriteLine(" Current User");
+ Console.WriteLine("====================================");
+ Console.WriteLine();
+ Console.WriteLine($"Username: {userSystem.CurrentUsername}");
+ Console.WriteLine();
+ }
+
+ private void ProcessBase64Command(string args)
+ {
+ string[] parts = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (parts.Length == 0)
+ {
+ ShowError("Error: Please specify subcommand");
+ ShowError("Usage: base64 encrypt | base64 decrypt ");
+ return;
+ }
+
+ string subcommand = parts[0].ToLower();
+
+ if (subcommand != "encrypt" && subcommand != "decrypt")
+ {
+ ShowError("Error: Invalid subcommand");
+ ShowError("Usage: base64 encrypt | base64 decrypt ");
+ return;
+ }
+
+ if (parts.Length < 2)
+ {
+ ShowError("Error: Please specify text to process");
+ ShowError($"Usage: base64 {subcommand} ");
+ return;
+ }
+
+ string text = string.Join(" ", parts, 1, parts.Length - 1);
+
+ Console.WriteLine("====================================");
+ Console.WriteLine(" Base64");
+ Console.WriteLine("====================================");
+ Console.WriteLine();
+
+ try
+ {
+ if (subcommand == "encrypt")
+ {
+ string encoded = Base64Helper.Encode(text);
+ Console.WriteLine($"Original: {text}");
+ Console.WriteLine();
+ Console.WriteLine($"Encoded: {encoded}");
+ }
+ if (subcommand == "decrypt")
+ {
+ string decoded = Base64Helper.Decode(text);
+ Console.WriteLine($"Encoded: {text}");
+ Console.WriteLine();
+ Console.WriteLine($"Decoded: {decoded}");
+ }
+
+ Console.WriteLine();
+ ShowSuccess("Base64 operation completed");
+ }
+ catch (Exception ex)
+ {
+ ShowError($"Base64 error: {ex.Message}");
+ }
+ }
}
}
\ No newline at end of file
diff --git a/UserSystem.cs b/UserSystem.cs
index 91b8df3..88c3e3e 100644
--- a/UserSystem.cs
+++ b/UserSystem.cs
@@ -159,6 +159,18 @@ namespace CMLeonOS
}
}
+ public string CurrentUsername
+ {
+ get
+ {
+ if (currentLoggedInUser != null)
+ {
+ return currentLoggedInUser.Username;
+ }
+ return "Not logged in";
+ }
+ }
+
public void FirstTimeSetup()
{
Console.WriteLine("====================================");