Add three read-only P2b MCP tools over the existing protocol. list_processes and list_windows trigger the client via COMMAND_SYSTEM / COMMAND_WSLIST on the main connection and receive TOKEN_PSLIST / TOKEN_WSLIST on a one-shot sub-link; get_activity_history uses the main-connection RPC COMMAND_QUERY_ACTIVITY -> TOKEN_REPORT_ACTIVITY. A per-host single-flight pending registry (m_Pending) with a 20s timeout correlates each response to its request and rejects a concurrent request for the same host with -32003. Parsers stop on the first empty record to ignore the client's LocalSize trailing zero padding, and window titles are decoded per the client UTF-8 capability bit. MessageHandle only adds if-guarded branches, so the MFC dialogs are untouched. Sync Mcp_Phase2_Design.md with the mode A'/A architecture, the verification notes, and the registry-backed config location.
Co-Authored-By: deepseek-v4-pro
Add two pure in-memory MCP tools over the online host list. search_hosts filters by name/remark, IP, group and OS (all optional, AND-combined, ASCII case-insensitive substring match); get_host_detail returns one online host by id and answers -32602 for a missing/non-numeric id and -32002 for an unknown or offline id. Sync Mcp_Phase2_Design.md with the second-review corrections and the P2a implementation.
Co-Authored-By: deepseek-v4-pro
Add an optional MCP server (JSON-RPC 2.0 over Streamable HTTP) exposing
an online-host listing tool, protected by a Bearer token. Disabled by
default; configured via a new "Extensions > MCP Settings" dialog.
- McpServer: httplib + JSON-RPC 2.0 dispatch (initialize/ping/tools/list/tools/call)
- McpSettingsDlg: runtime-created dialog for enable/port/bind/token
- HostJson: extract single-host JSON serialization shared with WebService
- FRP: expose MCP port (union with listening/Web ports) when bound to 0.0.0.0
- i18n: en_US / zh_TW translations
Co-Authored-By: deepseek-v4-pro
Add 16x16 icons for the three context-menu items that previously had
none: "Activity History" (Client Management), "Browse Window" (Remote
Control), and "Proxy Port - Auto Start" (Client Proxy). Register three
new bitmap resources and extend the main dialog's bitmap array from 63
to 66 entries so each menu item renders an intuitive glyph.
Co-Authored-By: deepseek-v4-pro
Record the client's active-window history (start time, window title, and
dwell duration), newest first, skipping dwellings under 5 seconds and
breaking the timing on idle, capped at 500 entries. Add an "Activity
History" item inside the host's Client Management submenu that requests
the snapshot over the main connection and shows it in a new dialog. The
dialog rebuilds its edit control as a Unicode window so UTF-8 titles
render correctly instead of degrading to "?" through the MBCS ANSI
boundary. The menu item and dialog title go through _TR and are
localized in en_US and zh_TW.
Co-Authored-By: deepseek-v4-pro
Persist the sort column and direction chosen via the online host list
header (list\OnlineListSort registry key) so the next launch defaults to
the same sort. Re-apply the sort when hosts come online/offline so newly
connected hosts land in their sorted position instead of appending at the
end.
Co-Authored-By: deepseek-v4-pro
Persist the sort column and direction chosen via the list header so the
next time the process or window management dialog opens it defaults to
the same sort. Process and window lists are remembered separately
(list\ProcessListSort and list\WindowListSort registry keys) since their
columns have different meanings.
Co-Authored-By: deepseek-v4-pro
The process list stored the architecture string only in ItemData::Arch,
leaving Data[3] (the architecture column) empty. Sorting by the
architecture column therefore compared empty strings and did nothing.
Populate Data[3] with the architecture value so the sort works.
Co-Authored-By: deepseek-v4-pro
- Add "Unban IP" menu item to the log message list (m_CList_Message)
right-click context menu, performing two actions on the extracted IP:
1. Remove the IP from the IPBlacklist singleton and persist to config
2. Scan the entire history host list (m_ClientMap->GetAll()) for all
clients matching the IP with AUTH_FORBIDDEN status, and restore
them to UNAUTHORIZED (0) — requiring re-authorization for safety
- Reuses ExtractFirstIPFromMessage() for dependency-free IPv4 parsing
- Handles the case where an IP is not in the blacklist and has no
matching forbidden clients with a clear "no action needed" message
- Menu item is grayed out when no log entry is selected
- Sync en_US / zh_TW language files with new translation strings
Co-Authored-By: DeepSeek V4 Pro
- Add "Ban IP" menu item to the log message list (m_CList_Message)
right-click context menu, allowing users to extract IPv4 addresses from
selected log entries and add them directly to the IP blacklist
- Reuses ExtractFirstIPFromMessage() from the previous commit for
dependency-free IPv4 parsing with per-segment 0-255 validation
- Checks against whitelist before banning (whitelisted IPs cannot be
banned) and skips IPs already in blacklist with clear feedback
- Immediately persists via THIS_CFG.SetStr to the config ini file;
IPBlacklist singleton takes effect instantly — subsequent connections
from banned IPs are rejected in IOCPServer::OnAccept() which already
calls IsIPBlacklisted() on every new connection
- Menu item is grayed out when no log entry is selected
- Sync en_US / zh_TW language files with new translation strings
Co-Authored-By: DeepSeek V4 Pro
- Add "Online Notify" menu item to the log message list (m_CList_Message)
right-click context menu, allowing users to extract IPv4 addresses from
selected log entries and add them to notification keywords
- Implement ExtractFirstIPFromMessage() for dependency-free IPv4 parsing
with per-segment 0-255 validation, handling diverse log message formats
- Extend NotifyManager::ShouldNotify with IP column (ONLINELIST_IP)
fallback check, ensuring IP keywords match regardless of the user's
configured ColumnIndex setting
- OnMsglogLoginNotify only appends keywords and enables the rule without
overwriting the user's existing ColumnIndex or TriggerType settings
- Menu item is automatically grayed out when PowerShell is unavailable
or no log entry is selected
- Sync en_US / zh_TW language files with new translation strings
Co-Authored-By: DeepSeek V4 Pro
Commit 6d0b1bb (Feat: Add privilege column) inserted ONLINELIST_PRIVILEGE
at enum value 9, shifting INSTALLTIME from 9→10 and PATH from 12→13.
However, FileUpload_Lib (SimplePlugins) is compiled against a separate
copy of context.h that still uses the old enum values. Since
HostInfo.cpp's SaveClientMapData uses OLD enum values to read
sClientInfo[], it was reading privilegeStr for InstallTime and client
type for ProgramPath — corrupting the history host database.
Fix: move ONLINELIST_PRIVILEGE to value 16 (just before MAX), restoring
all original enum values (INSTALLTIME=9, PATH=12, etc.) so the
pre-built library can continue reading correct data without recompilation.
The 'permission' column now appears as the rightmost column in the
online host list instead of between 'version' and 'install time'.
Co-Authored-By: DeepSeek V4 Pro
- Add LicenseLimit field to LicenseInfo struct (0 = not set, unlimited)
- Add GetLicenseLimit/SetLicenseLimit: read/write LicenseLimit key in licenses.ini
- Append |lic:N to reserved field in TOKEN_AUTH response only when
LicenseLimit > 0; absent |lic: means no limit (client defaults to 9999),
so super admin authenticating to its own server is never falsely terminated
- Add "Sub-license limit" item in CLicenseDlg right-click menu (1-9999,
empty = clear limit); menu label shows current value in real time
- Limit change takes effect when sub-client re-authenticates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TOKEN_AUTH: when the server has a V2 private key, signs "SN|valid(0/1)"
with ECDSA P-256 and places "sig:<base64>" in the response reserved field.
Clients can verify server identity without changing the request format.
TOKEN_SERVER_VERIFY (251): added constant to commands.h; handler already
present in 2015RemoteDlg.cpp for the challenge-response server identity check.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two changes to reduce unnecessary CScreenSpy restarts when connecting:
1. Client (ScreenManager.cpp): Initialize CScreenSpy with bitrate from
the locally-saved quality profile, so CMD_QUALITY_LEVEL arriving from
the server (same bitrate as default) hits SetBitRate(3000)==3000 and
skips the restart instead of comparing against the hard-coded 0.
Also fixes QualityLevel init to use the already-computed `quality`
variable (which honours the QUALITY_DISABLED override when algo!=NUL)
rather than re-reading the cfg key a second time.
2. Server (ScreenSpyDlg.cpp): Only send CMD_SCREEN_SIZE strategy=2 when
the session is in QUALITY_ADAPTIVE mode and a cached maxWidth exists.
Fixed quality levels already carry resolution via CMD_QUALITY_PROFILES,
so unconditionally sending CMD_SCREEN_SIZE caused a second restart when
the screen spy was still rebuilding from the first one.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>