#include "stdafx.h" #include "HostJson.h" #include "HostInfo.h" // _ClientList / MAP_NOTE #include "context.h" // context 接口 + ONLINELIST_* 枚举 #include "2015RemoteDlg.h" // GetClientEncoding 辅助函数(UTF-8 能力位判断) #ifndef _WIN64 #ifdef _DEBUG #pragma comment(lib, "jsoncpp/jsoncppd.lib") #else #pragma comment(lib, "jsoncpp/jsoncpp.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "jsoncpp/jsoncpp_x64d.lib") #else #pragma comment(lib, "jsoncpp/jsoncpp_x64.lib") #endif #endif // Helper: Convert ANSI (GBK) string to UTF-8 // (自 WebService.cpp 抽出,供 BuildDeviceListJson 与 BuildHostJson 共用) static std::string AnsiToUtf8(const CString& str) { if (str.IsEmpty()) return ""; #ifdef _UNICODE // Unicode build: CString is already UTF-16, convert to UTF-8 int len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); if (len <= 0) return ""; std::string result(len - 1, '\0'); WideCharToMultiByte(CP_UTF8, 0, str, -1, &result[0], len, NULL, NULL); return result; #else // MBCS build: CString is ANSI (GBK), need to convert to UTF-16 first, then to UTF-8 int wlen = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); if (wlen <= 0) return ""; std::wstring wstr(wlen - 1, L'\0'); MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], wlen); int u8len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL); if (u8len <= 0) return ""; std::string result(u8len - 1, '\0'); WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &result[0], u8len, NULL, NULL); return result; #endif } Json::Value BuildHostJson(context* ctx, _ClientList* clientMap) { Json::Value device; if (!ctx) return device; // 空 context → 返回 null Json::Value // Use string for ID to avoid JavaScript number precision loss device["id"] = std::to_string(ctx->GetClientID()); CString name = ctx->GetClientData(ONLINELIST_COMPUTER_NAME); device["name"] = AnsiToUtf8(name); // 用户在 MFC 端给这台主机起的备注(菜单"修改备注"写入 MAP_NOTE) if (clientMap) { CString remark = clientMap->GetClientMapData(ctx->GetClientID(), MAP_NOTE); if (!remark.IsEmpty()) { device["remark"] = AnsiToUtf8(remark); } } CString ip = ctx->GetClientData(ONLINELIST_IP); device["ip"] = AnsiToUtf8(ip); CString os = ctx->GetClientData(ONLINELIST_OS); device["os"] = AnsiToUtf8(os); CString location = ctx->GetClientData(ONLINELIST_LOCATION); device["location"] = AnsiToUtf8(location); CString rtt = ctx->GetClientData(ONLINELIST_PING); device["rtt"] = AnsiToUtf8(rtt); CString version = ctx->GetClientData(ONLINELIST_VERSION); device["version"] = AnsiToUtf8(version); // 活动窗口编码由客户端能力位决定:新客户端是 UTF-8,老客户端是 CP_ACP(默认 936)。 // 不能像其它字段那样无脑 AnsiToUtf8——会把新客户端的 UTF-8 字节再当 GBK 双重编码。 CString activeWindow = ctx->GetClientData(ONLINELIST_LOGINTIME); std::string activeWindowU8; if (!activeWindow.IsEmpty()) { UINT cp = GetClientEncoding(ctx); int wlen = MultiByteToWideChar(cp, 0, activeWindow, -1, NULL, 0); if (wlen > 1) { std::wstring w(wlen - 1, L'\0'); MultiByteToWideChar(cp, 0, activeWindow, -1, &w[0], wlen); int u8len = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, NULL, 0, NULL, NULL); if (u8len > 1) { activeWindowU8.resize(u8len - 1); WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, &activeWindowU8[0], u8len, NULL, NULL); } } } device["activeWindow"] = activeWindowU8; device["online"] = true; // Add device group to response std::string deviceGroup = ctx->GetGroupName(); if (deviceGroup.empty()) deviceGroup = "default"; device["group"] = deviceGroup; // Get screen info from client's reported resolution // Format: "n:MxN" where n=monitor count, M=width, N=height CString resolution = ctx->GetAdditionalData(RES_RESOLUTION); if (!resolution.IsEmpty()) { device["screen"] = AnsiToUtf8(resolution); // e.g. "2:3840x1080" } CString clientType = ctx->GetAdditionalData(RES_CLIENT_TYPE); device["clientType"] = AnsiToUtf8(clientType); // e.g. "MAC", "LNX", "EXE" return device; }