Feature: Add "Unban IP" to log message context menu in main dialog

- 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
This commit is contained in:
yuanyuanxiang
2026-08-07 11:45:18 +02:00
parent 7bbc47a0ee
commit c8973282cb
5 changed files with 82 additions and 2 deletions

View File

@@ -944,6 +944,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_MSGLOG_SEARCH, &CMy2015RemoteDlg::OnMsglogSearch)
ON_COMMAND(ID_MSGLOG_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnMsglogLoginNotify)
ON_COMMAND(ID_MSGLOG_BAN_IP, &CMy2015RemoteDlg::OnMsglogBanIP)
ON_COMMAND(ID_MSGLOG_UNBAN_IP, &CMy2015RemoteDlg::OnMsglogUnbanIP)
ON_COMMAND(ID_ONLINE_ADD_WATCH, &CMy2015RemoteDlg::OnOnlineAddWatch)
ON_COMMAND(ID_ONLINE_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnOnlineLoginNotify)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline)
@@ -9308,13 +9309,15 @@ void CMy2015RemoteDlg::OnRClickMessage(NMHDR* pNMHDR, LRESULT* pResult)
menu.AppendMenu(MF_SEPARATOR);
menu.AppendMenu(MF_STRING, ID_MSGLOG_LOGIN_NOTIFY, _TR("上线提醒"));
menu.AppendMenu(MF_STRING, ID_MSGLOG_BAN_IP, _TR("封禁IP"));
menu.AppendMenu(MF_STRING, ID_MSGLOG_UNBAN_IP, _TR("解除封禁"));
// 没有选中项时禁用"删除选中"、"复制选中"、"上线提醒""封禁IP"
// 没有选中项时禁用"删除选中"、"复制选中"、"上线提醒""封禁IP"和"解除封禁"
if (m_CList_Message.GetSelectedCount() == 0) {
menu.EnableMenuItem(ID_MSGLOG_DELETE, MF_GRAYED);
menu.EnableMenuItem(ID_MSGLOG_COPY, MF_GRAYED);
menu.EnableMenuItem(ID_MSGLOG_LOGIN_NOTIFY, MF_GRAYED);
menu.EnableMenuItem(ID_MSGLOG_BAN_IP, MF_GRAYED);
menu.EnableMenuItem(ID_MSGLOG_UNBAN_IP, MF_GRAYED);
}
// PowerShell不可用时禁用"上线提醒"
if (!GetNotifyManager().IsPowerShellAvailable()) {
@@ -9623,6 +9626,73 @@ void CMy2015RemoteDlg::OnMsglogBanIP()
MessageBoxL(details, _TR("封禁IP"), MB_ICONINFORMATION);
}
void CMy2015RemoteDlg::OnMsglogUnbanIP()
{
// Get selected log messages and extract IP addresses from them
std::vector<std::string> ipsToProcess;
POSITION pos = m_CList_Message.GetFirstSelectedItemPosition();
while (pos) {
int row = m_CList_Message.GetNextSelectedItem(pos);
CString msgText = m_CList_Message.GetItemText(row, 2);
CString extractedIP;
if (ExtractFirstIPFromMessage(msgText, extractedIP)) {
std::string ipUtf8 = CT2A(extractedIP, CP_UTF8);
ipsToProcess.push_back(ipUtf8);
}
}
if (ipsToProcess.empty()) {
MessageBoxL("所选日志消息中未检测到有效的 IP 地址", "提示", MB_ICONINFORMATION);
return;
}
int unblacklistedCount = 0;
int clientRestoredCount = 0;
for (const auto& ip : ipsToProcess) {
// 1. Remove from IP blacklist
if (IPBlacklist::getInstance().IsBlacklisted(ip)) {
IPBlacklist::getInstance().RemoveIP(ip);
unblacklistedCount++;
}
// 2. Find all clients matching this IP and restore AUTH_FORBIDDEN to UNAUTHORIZED
for (const auto& kv : m_ClientMap->GetAll()) {
if (strcmp(kv.second.IP, ip.c_str()) == 0
&& kv.second.Authorized == AUTH_FORBIDDEN) {
m_ClientMap->SetClientMapInteger(kv.first, MAP_AUTH, UNAUTHORIZED);
clientRestoredCount++;
}
}
}
// Persist
if (unblacklistedCount > 0) {
std::string blacklistStr = IPBlacklist::getInstance().Export();
THIS_CFG.SetStr("settings", "IPBlacklist", blacklistStr.c_str());
}
if (clientRestoredCount > 0) {
m_ClientMap->SaveToFile(GetDbPath());
}
// Build result message
CString details;
if (unblacklistedCount > 0) {
details.AppendFormat(_TR("已将 %d 个 IP 从黑名单移除"), unblacklistedCount);
}
if (clientRestoredCount > 0) {
if (!details.IsEmpty()) details += _T("\n");
details.AppendFormat(_TR("已恢复 %d 个客户端的授权状态"), clientRestoredCount);
}
if (unblacklistedCount == 0 && clientRestoredCount == 0) {
details = _TR("未找到需要解除封禁的 IP");
}
MessageBoxL(details, _TR("解除封禁"), MB_ICONINFORMATION);
}
void CMy2015RemoteDlg::OnOnlineAddWatch()
{
EnterCriticalSection(&m_cs);