Files
SimpleRemoter/server/2015Remote/HostJson.cpp
T
yuanyuanxianganddeepseek-flash 38cd207f5d Feature: Add host management and connection management MCP tools
Expose the online-list TLS column through list_online_hosts, search_hosts
and get_host_detail. The value comes from the flag the client reports at
login, so old clients always read false.

Add list_network_connections and kill_network_connection on top of the
connection manager sub-connection protocol. The kill path matches the
original 110-byte record instead of rebuilding addresses, supports a dry
run, refuses UDP/IPv6 targets, and verifies that the quadruple really
disappeared instead of assuming success.

Add a host_* family backed by the machine manager protocol: ten read
tools covering every tab of the host management dialog, and four
recoverable write tools for process freeze/thaw, window restore/hide/
maximize/minimize, service start/stop/pause/continue/restart, and
scheduled task run/stop. Every write re-reads the snapshot before sending
and re-checks afterwards, reporting -32009 for stale targets rather than
acting blindly. The family is gated by McpMachine, the risky subset by
McpMachineDangerous, and writes additionally require read-only mode to
be off.

Route managed sub-connections from MessageHandle and OfflineProc, keep
the single-in-flight rule by sharing the pending table with a request
kind, and move the shared JSON/lock/encoding helpers into McpInternal so
both tool families use one implementation. Settings dialog, design docs
and en_US/zh_TW/de_DE translations are updated accordingly.

Co-Authored-By: deepseek-flash
2026-10-21 20:01:41 +02:00

123 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
// 地理位置已统一按 UTF-8 存储(见 AddList),直接透传,不再 CP_ACP→UTF-8 二次转换。
CString location = ctx->GetClientData(ONLINELIST_LOCATION);
device["location"] = std::string(location.GetString());
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"
// 登录时上报的 TLS 传输标志(RES_TLS=="1" → "Y")。老客户端不上报,取值为 "N"。
// 注意这是登录凭据而不是实时探测:连接建立后若配置发生变化,需要客户端重连才会更新。
device["tls"] = (ctx->GetClientData(ONLINELIST_TLS) == "Y");
return device;
}