From 7be002f7a2eff2ec51557d4b44180413cf7a5a48 Mon Sep 17 00:00:00 2001 From: LuChao Date: Sun, 2 Jun 2024 01:42:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/wxhelper/src/http_server.cc | 324 +++++++++++++++++----------- app/wxhelper/src/misc_controller.cc | 300 +++++++++++++++----------- app/wxhelper/src/sync_msg_hook.cc | 89 +++++--- app/wxhelper/src/wxutils.cc | 74 ++++++- 4 files changed, 501 insertions(+), 286 deletions(-) diff --git a/app/wxhelper/src/http_server.cc b/app/wxhelper/src/http_server.cc index be20543..1e934bd 100644 --- a/app/wxhelper/src/http_server.cc +++ b/app/wxhelper/src/http_server.cc @@ -1,141 +1,207 @@ -#include "http_server.h" +#include "http_server.h" // 引入 http_server.h 文件,包含了 HttpServer 类的定义 -#include "http_router.h" -#include "nlohmann/json.hpp" -#include "spdlog/spdlog.h" -#include "utils.h" +#include "http_router.h" // 引入 http_router.h 文件,包含了 HttpRouter 类的定义 +#include "nlohmann/json.hpp" // 引入 nlohmann/json.hpp 文件,用于 JSON 处理 +#include "spdlog/spdlog.h" // 引入 spdlog/spdlog.h 文件,用于日志记录 +#include "utils.h" // 引入 utils.h 文件,包含了一些辅助函数 +#include "wxutils.h" // 引入 wxutils.h 文件,包含了一些与 wxWidgets 相关的辅助函数 -namespace http { +namespace http // 定义命名空间 http,用于组织代码 +{ -HttpServer::~HttpServer() { - if (thread_ != nullptr) { - CloseHandle(thread_); - } - mg_mgr_free(&mgr_); -} - -void HttpServer::init(std::string &&host, int port) { - if (port < 1 || port > 65535) { - throw std::invalid_argument("Port number is out of range."); - } - mg_mgr_init(&mgr_); - host_ = std::move(host); - port_ = port; - SPDLOG_INFO("http init :host={},port={}",host_,port_); -} - -bool HttpServer::Start() { - if (running_) { - SPDLOG_INFO("http server is already running"); - return true; - } -#ifdef _DEBUG - base::utils::CreateConsole(); -#endif - running_.store(true); - thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LaunchServer, this, - NULL, 0); - SPDLOG_INFO("CreateThread for http server ,the result is {}",thread_ != NULL); - return thread_ != NULL; -} - -bool HttpServer::Stop() { - if (!running_) { - return true; - } -#ifdef _DEBUG - base::utils::CloseConsole(); -#endif - running_ = false; - if (thread_) { - WaitForSingleObject(thread_, -1); - CloseHandle(thread_); - thread_ = NULL; - } - return true; -} - -void HttpServer::LaunchServer(HttpServer *server) { - int port = server->GetPort(); - std::string host = server->GetHost(); - const mg_mgr * mgr = server->GetMgr(); - std::string listen_addr = host +":"+ std::to_string(port); - if (mg_http_listen(const_cast(mgr), listen_addr.c_str(), - EventHandler, NULL) == NULL) { - SPDLOG_ERROR("http server listen fail.port:{}", port); - return; - } - for (;;) { - mg_mgr_poll(const_cast(mgr), 100); - } -} - -void HttpServer::EventHandler(struct mg_connection *c, int ev, void *ev_data, - void *fn_data) { - if (ev == MG_EV_OPEN) { - } else if (ev == MG_EV_HTTP_MSG) { - struct mg_http_message *hm = (struct mg_http_message *)ev_data; - if (mg_http_match_uri(hm, "/websocket/*")) { - mg_ws_upgrade(c, hm, NULL); - } else if (mg_http_match_uri(hm, "/api/*")) { - HandleHttpRequest(c, hm, fn_data); - } else { - nlohmann::json res = {{"code", 400}, - {"msg", "invalid url, please check url"}, - {"data", NULL}}; - std::string ret = res.dump(); - mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", - ret.c_str()); + HttpServer::~HttpServer() // HttpServer 类的析构函数 + { + if (thread_ != nullptr) // 如果线程指针 thread_ 不为空 + { + // wxhelper::wxutils::print_utf8_to_console("Destroying thread"); // 打印到控制台,告知正在销毁线程 + CloseHandle(thread_); // 关闭线程句柄 } - } else if (ev == MG_EV_WS_MSG) { - HandleWebsocketRequest(c, ev_data, fn_data); + mg_mgr_free(&mgr_); // 释放 CivetWeb 管理器 } -} -void HttpServer::HandleHttpRequest(struct mg_connection *c, void *ev_data, - void *fn_data) { - struct mg_http_message *hm = (struct mg_http_message *)ev_data; - std::string ret = R"({"code":200,"msg":"success"})"; - try { - if (mg_vcasecmp(&hm->method, "GET") == 0) { - nlohmann::json ret_data = { - {"code", 200}, - {"data", {}}, - {"msg", "the get method is not supported.please use post method."}}; - ret = ret_data.dump(); - } else if (mg_vcasecmp(&hm->method, "POST") == 0) { - std::string url(hm->uri.ptr, hm->uri.len); - std::string p = "{}"; - if (hm->body.len > 0){ - nlohmann::json params = - nlohmann::json::parse(hm->body.ptr, hm->body.ptr + hm->body.len); - p = params.dump(); + void HttpServer::init(std::string &&host, int port) // HttpServer 类的初始化函数 + { + if (port < 1 || port > 65535) // 如果端口号不在有效范围内 + { + throw std::invalid_argument("Port number is out of range."); // 抛出异常 + } + mg_mgr_init(&mgr_); // 初始化 CivetWeb 管理器 + host_ = std::move(host); // 使用移动构造函数将 host 参数赋值给成员变量 host_ + port_ = port; // 将端口号赋值给成员变量 port_ + // wxhelper::wxutils::print_utf8_to_console("http init :"); + // wxhelper::wxutils::print_utf8_to_console(host_); // 打印初始化信息到控制台 + // wxhelper::wxutils::print_utf8_to_console(std::to_string(port_)); + SPDLOG_INFO("http init :host={},port={}", host_, port_); // 记录日志 + } + + bool HttpServer::Start() // HttpServer 类的启动函数 + { + if (running_) // 如果服务器已经在运行 + { + wxhelper::wxutils::print_utf8_to_console("http server is already running"); + SPDLOG_INFO("http server is already running"); // 记录日志 + return true; // 返回 true + } +#ifdef _DEBUG // 如果定义了 _DEBUG 宏 + base::utils::CreateConsole(); // 创建控制台窗口 +#endif + running_.store(true); // 将 running_ 原子变量设置为 true + thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LaunchServer, this, + NULL, 0); // 创建线程运行 LaunchServer 函数 + wxhelper::wxutils::print_utf8_to_console("CreateThread for http server ,the result is..."); + SPDLOG_INFO("CreateThread for http server ,the result is {}", thread_ != NULL); + return thread_ != NULL; // 返回线程创建是否成功 + } + + bool HttpServer::Stop() // HttpServer 类的停止函数 + { + if (!running_) // 如果服务器不在运行状态 + { + wxhelper::wxutils::print_utf8_to_console("http server is not running"); + return true; // 直接返回 true + } +#ifdef _DEBUG + base::utils::CloseConsole(); // 关闭控制台窗口 +#endif + running_ = false; // 将 running_ 设置为 false + if (thread_) // 如果线程句柄不为空 + { + WaitForSingleObject(thread_, -1); // 等待线程结束 + CloseHandle(thread_); // 关闭线程句柄 + thread_ = NULL; // 将线程句柄设置为 NULL + } + return true; // 返回 true + } + + void HttpServer::LaunchServer(HttpServer *server) // HttpServer 类的服务器启动函数 + { + int port = server->GetPort(); // 获取端口号 + std::string host = server->GetHost(); // 获取主机名 + const mg_mgr *mgr = server->GetMgr(); // 获取 CivetWeb 管理器 + std::string listen_addr = host + ":" + std::to_string(port); // 构建监听地址 + if (mg_http_listen(const_cast(mgr), listen_addr.c_str(), + EventHandler, NULL) == NULL) // 如果监听失败 + { + // wxhelper::wxutils::print_utf8_to_console("http server listen fail.port:{}"); + // wxhelper::wxutils::print_utf8_to_console(std::to_string(port)); // 打印错误信息到控制台 + SPDLOG_ERROR("http server listen fail.port:{}", port); // 记录错误日志 + return; // 返回 + } + // wxhelper::wxutils::print_utf8_to_console("Listening on port: {}"); + // wxhelper::wxutils::print_utf8_to_console(std::to_string(port)); // 打印监听信息到控制台 + for (;;) + { + mg_mgr_poll(const_cast(mgr), 100); // 轮询 CivetWeb 管理器 + } + } + + void HttpServer::EventHandler(struct mg_connection *c, int ev, void *ev_data, + void *fn_data) // HttpServer 类的事件处理函数 + { + if (ev == MG_EV_OPEN) // 如果事件类型是连接打开 + { + // wxhelper::wxutils::print_utf8_to_console("Connection opened"); // 打印信息到控制台 + } + else if (ev == MG_EV_HTTP_MSG) // 如果事件类型是 HTTP 消息 + { + struct mg_http_message *hm = (struct mg_http_message *)ev_data; // 转换事件数据为 mg_http_message 类型 + if (mg_http_match_uri(hm, "/websocket/*")) // 如果匹配到 WebSocket 路由 + { + mg_ws_upgrade(c, hm, NULL); // 升级为 WebSocket 连接 + } + else if (mg_http_match_uri(hm, "/api/*")) // 如果匹配到 API 路由 + { + HandleHttpRequest(c, hm, fn_data); // 处理 HTTP 请求 + } + else // 如果不匹配任何路由 + { + nlohmann::json res = {{"code", 400}, + {"msg", "invalid url, please check url"}, + {"data", NULL}}; + std::string ret = res.dump(); // 将 JSON 对象转换为字符串 + mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", + ret.c_str()); // 发送 HTTP 响应 } - ret = HttpRouter::GetInstance().HandleHttpRequest(url, p); } - } catch (nlohmann::json::exception &e) { - nlohmann::json res = {{"code", "500"}, {"msg", e.what()}, {"data", NULL}}; - ret = res.dump(); + else if (ev == MG_EV_WS_MSG) // 如果事件类型是 WebSocket 消息 + { + HandleWebsocketRequest(c, ev_data, fn_data); // 处理 WebSocket 请求 + } } - mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", - ret.c_str()); -} -void HttpServer::HandleWebsocketRequest(struct mg_connection *c, void *ev_data, - void *fn_data) { - struct mg_ws_message *wm = (struct mg_ws_message *)ev_data; - std::string ret = R"({"code":200,"msg":"success"})"; - try { - nlohmann::json params = - nlohmann::json::parse(wm->data.ptr, wm->data.ptr + wm->data.len); - std::string cmd = params["cmd"]; - std::string p = params.dump(); - ret = HttpRouter::GetInstance().HandleHttpRequest(cmd, p); - } catch (nlohmann::json::exception &e) { - nlohmann::json res = {{"code", "500"}, {"msg", e.what()}, {"data", NULL}}; - ret = res.dump(); + void HttpServer::HandleHttpRequest(struct mg_connection *c, void *ev_data, + void *fn_data) // HttpServer 类的 HTTP 请求处理函数 + { + struct mg_http_message *hm = (struct mg_http_message *)ev_data; // 转换事件数据为 mg_http_message 类型 + wxhelper::wxutils::print_utf8_to_console("Handling HTTP request..."); // 打印信息到控制台 + std::string ret = R"({"code":200,"msg":"success"})"; // 初始化 HTTP 响应 + try + { + if (mg_vcasecmp(&hm->method, "GET") == 0) // 如果请求方法是 GET + { + nlohmann::json ret_data = { + {"code", 200}, + {"data", {}}, + {"msg", "the get method is not supported.please use post method."}}; + ret = ret_data.dump(); // 将 JSON 对象转换为字符串 + } + else if (mg_vcasecmp(&hm->method, "POST") == 0) // 如果请求方法是 POST + { + std::string url(hm->uri.ptr, hm->uri.len); // 获取请求的 URL + wxhelper::wxutils::print_utf8_to_console("Parsed HTTP url: " + url); + std::string p = "{}"; // 初始化 POST 参数字符串 + if (hm->body.len > 0) // 如果请求体长度大于 0 + { + nlohmann::json params = nlohmann::json::parse(hm->body.ptr, hm->body.ptr + hm->body.len); // 解析 POST 参数 + p = params.dump(); // 将 JSON 对象转换为字符串 + } + wxhelper::wxutils::print_utf8_to_console("Parsed HTTP parameters: " + p); + ret = HttpRouter::GetInstance().HandleHttpRequest(url, p); // 调用 HttpRouter 处理请求 + } + } + catch (nlohmann::json::exception &e) // 如果解析 JSON 时发生异常 + { + nlohmann::json res = {{"code", "500"}, {"msg", e.what()}, {"data", NULL}}; + ret = res.dump(); // 设置错误响应 + } + + try + { + wxhelper::wxutils::print_utf8_to_console("Sending HTTP response... "); + + // wxhelper::wxutils::print_utf8_to_console("Sending HTTP response: "); + // wxhelper::wxutils::print_utf8_to_console(std::string(ret)); + } + catch (const std::exception &e) + { + wxhelper::wxutils::print_utf8_to_console("Sending HTTP response error: " + std::string(e.what())); + } + + mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", + ret.c_str()); // 发送 HTTP 响应 } - mg_ws_send(c, ret.c_str(), ret.size(), WEBSOCKET_OP_TEXT); -} -} // namespace http \ No newline at end of file + void HttpServer::HandleWebsocketRequest(struct mg_connection *c, void *ev_data, + void *fn_data) // HttpServer 类的 WebSocket 请求处理函数 + { + struct mg_ws_message *wm = (struct mg_ws_message *)ev_data; // 转换事件数据为 mg_ws_message 类型 + wxhelper::wxutils::print_utf8_to_console("Handling WebSocket request"); // 打印信息到控制台 + std::string ret = R"({"code":200,"msg":"success"})"; // 初始化 WebSocket 响应 + try + { + nlohmann::json params = nlohmann::json::parse(wm->data.ptr, wm->data.ptr + wm->data.len); // 解析 WebSocket 参数 + std::string cmd = params["cmd"]; // 获取命令 + std::string p = params.dump(); // 将 JSON 对象转换为字符串 + wxhelper::wxutils::print_utf8_to_console("Parsed WebSocket parameters: " + p); + ret = HttpRouter::GetInstance().HandleHttpRequest(cmd, p); // 调用 HttpRouter 处理请求 + } + catch (nlohmann::json::exception &e) // 如果解析 JSON 时发生异常 + { + nlohmann::json res = {{"code", "500"}, {"msg", e.what()}, {"data", NULL}}; + ret = res.dump(); // 设置错误响应 + } + wxhelper::wxutils::print_utf8_to_console("Sending WebSocket response: {}" + ret); + mg_ws_send(c, ret.c_str(), ret.size(), WEBSOCKET_OP_TEXT); // 发送 WebSocket 响应 + } + +} // namespace http \ No newline at end of file diff --git a/app/wxhelper/src/misc_controller.cc b/app/wxhelper/src/misc_controller.cc index 9150d90..d7fb7b1 100644 --- a/app/wxhelper/src/misc_controller.cc +++ b/app/wxhelper/src/misc_controller.cc @@ -5,128 +5,184 @@ #include "spdlog/spdlog.h" #include "wechat_interface.h" #include "wechat_service.h" +#include "wxutils.h" namespace jsonutils = wxhelper::jsonutils; -namespace wxhelper { -std::string MiscController::CheckLogin(std::string params) { - int64_t success = wechat::WeChatService::GetInstance().CheckLogin(); - nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; - return ret.dump(); -} -std::string MiscController::GetUserInfo(std::string params) { - wechat::SelfInfoInner out; - int64_t success = wechat::WeChatService::GetInstance().GetSelfInfo(out); - nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; - nlohmann::json j_info = { - {"name", out.name}, - {"city", out.city}, - {"province", out.province}, - {"country", out.country}, - {"account", out.account}, - {"wxid", out.wxid}, - {"mobile", out.mobile}, - {"headImage", out.head_img}, - {"signature", out.signature}, - {"dataSavePath", out.data_save_path}, - {"currentDataPath", out.current_data_path}, - {"dbKey", out.db_key}, - {"publicKey", out.public_key}, - {"privateKey", out.private_key}, - }; - ret["data"] = j_info; - return ret.dump(); -} -std::string MiscController::GetSNSFirstPage(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::GetSNSNextPage(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::AddFavFromMsg(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::AddFavFromImage(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::DecodeImage(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::GetVoiceByMsgId(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::DoOcrTask(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::LockWeChat(std::string params) { - int64_t success = wechat::WeChatService::GetInstance().LockWeChat(); - nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; - return ret.dump(); -} -std::string MiscController::UnlockWeChat(std::string params) { - int64_t success = wechat::WeChatService::GetInstance().UnlockWeChat(); - nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; - return ret.dump(); -} -std::string MiscController::ClickEnterWeChat(std::string params) { - int64_t success = wechat::WeChatService::GetInstance().EnterWeChat(); - nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; - return ret.dump(); -} -std::string MiscController::GetLoginUrl(std::string params) { - std::string login_url = wechat::WeChatService::GetInstance().GetLoginUrl(); - nlohmann::json ret = { - {"code", 1}, {"data", {"loginUrl", login_url}}, {"msg", "success"}}; - return ret.dump(); -} -std::string MiscController::TranslateVoice(std::string params) { - nlohmann::json jp = nlohmann::json::parse(params); - int64_t msg_id = jsonutils::GetInt64Param(jp, "msgId"); - int64_t success = wechat::WeChatService::GetInstance().TranslateVoice(msg_id); - nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; - return ret.dump(); -} -std::string MiscController::GetTranslateVoiceText(std::string params) { - nlohmann::json jp = nlohmann::json::parse(params); - int64_t msg_id = jsonutils::GetInt64Param(jp, "msgId"); - std::string content = - wechat::WeChatService::GetInstance().GetTranslateVoiceText(msg_id); - nlohmann::json ret_data = { - {"code", 1}, {"msg", "success"}, {"data", {{"transtext", content}}}}; - return ret_data.dump(); -} -std::string MiscController::OpenUrlByWeChat(std::string params) { - nlohmann::json jp = nlohmann::json::parse(params); - std::wstring url = jsonutils::GetWStringParam(jp, "url"); - int flag = jsonutils::GetIntParam(jp, "flag"); - int64_t success = - wechat::WeChatService::GetInstance().OpenUrlByWeChatBrowser(url, flag); - nlohmann::json ret = { - {"code", success}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::ConfirmReceipt(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -std::string MiscController::DownloadAttach(std::string params) { - nlohmann::json ret = { - {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; - return ret.dump(); -} -} // namespace wxhelper +namespace wxhelper +{ + std::string MiscController::CheckLogin(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("CheckLogin called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + int64_t success = wechat::WeChatService::GetInstance().CheckLogin(); + nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; + return ret.dump(); + } + std::string MiscController::GetUserInfo(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("GetUserInfo called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + wechat::SelfInfoInner out; + int64_t success = wechat::WeChatService::GetInstance().GetSelfInfo(out); + nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; + nlohmann::json j_info = { + {"name", out.name}, + {"city", out.city}, + {"province", out.province}, + {"country", out.country}, + {"account", out.account}, + {"wxid", out.wxid}, + {"mobile", out.mobile}, + {"headImage", out.head_img}, + {"signature", out.signature}, + {"dataSavePath", out.data_save_path}, + {"currentDataPath", out.current_data_path}, + {"dbKey", out.db_key}, + {"publicKey", out.public_key}, + {"privateKey", out.private_key}, + }; + ret["data"] = j_info; + return ret.dump(); + } + std::string MiscController::GetSNSFirstPage(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("GetSNSFirstPage called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::GetSNSNextPage(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("GetSNSNextPage called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::AddFavFromMsg(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("AddFavFromMsg called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::AddFavFromImage(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("AddFavFromImage called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::DecodeImage(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("DecodeImage called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::GetVoiceByMsgId(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("GetVoiceByMsgId called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::DoOcrTask(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("DoOcrTask called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::LockWeChat(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("LockWeChat called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + int64_t success = wechat::WeChatService::GetInstance().LockWeChat(); + nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; + return ret.dump(); + } + std::string MiscController::UnlockWeChat(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("UnlockWeChat called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + int64_t success = wechat::WeChatService::GetInstance().UnlockWeChat(); + nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; + return ret.dump(); + } + std::string MiscController::ClickEnterWeChat(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("ClickEnterWeChat called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + int64_t success = wechat::WeChatService::GetInstance().EnterWeChat(); + nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; + return ret.dump(); + } + std::string MiscController::GetLoginUrl(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("GetLoginUrl called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + std::string login_url = wechat::WeChatService::GetInstance().GetLoginUrl(); + nlohmann::json ret = { + {"code", 1}, {"data", {"loginUrl", login_url}}, {"msg", "success"}}; + return ret.dump(); + } + std::string MiscController::TranslateVoice(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("TranslateVoice called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json jp = nlohmann::json::parse(params); + int64_t msg_id = jsonutils::GetInt64Param(jp, "msgId"); + int64_t success = wechat::WeChatService::GetInstance().TranslateVoice(msg_id); + nlohmann::json ret = {{"code", success}, {"data", {}}, {"msg", "success"}}; + return ret.dump(); + } + std::string MiscController::GetTranslateVoiceText(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("GetTranslateVoiceText called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json jp = nlohmann::json::parse(params); + int64_t msg_id = jsonutils::GetInt64Param(jp, "msgId"); + std::string content = + wechat::WeChatService::GetInstance().GetTranslateVoiceText(msg_id); + nlohmann::json ret_data = { + {"code", 1}, {"msg", "success"}, {"data", {{"transtext", content}}}}; + return ret_data.dump(); + } + std::string MiscController::OpenUrlByWeChat(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("OpenUrlByWeChat called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json jp = nlohmann::json::parse(params); + std::wstring url = jsonutils::GetWStringParam(jp, "url"); + int flag = jsonutils::GetIntParam(jp, "flag"); + int64_t success = + wechat::WeChatService::GetInstance().OpenUrlByWeChatBrowser(url, flag); + nlohmann::json ret = { + {"code", success}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::ConfirmReceipt(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("ConfirmReceipt called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } + std::string MiscController::DownloadAttach(std::string params) + { + // wxhelper::wxutils::print_utf8_to_console("DownloadAttach called with params: "); + // wxhelper::wxutils::print_utf8_to_console(params); + nlohmann::json ret = { + {"code", 200}, {"data", {}}, {"msg", "Not Implemented"}}; + return ret.dump(); + } +} // namespace wxhelper diff --git a/app/wxhelper/src/sync_msg_hook.cc b/app/wxhelper/src/sync_msg_hook.cc index 2d0553b..df3a40b 100644 --- a/app/wxhelper/src/sync_msg_hook.cc +++ b/app/wxhelper/src/sync_msg_hook.cc @@ -1,73 +1,98 @@ -#include "sync_msg_hook.h" +#include "sync_msg_hook.h" // 引入同步消息钩子头文件 -#include "base64.h" -#include "config.h" -#include "nlohmann/json.hpp" -#include "offset.h" -#include "spdlog/spdlog.h" -#include "thread_pool.h" -#include "utils.h" +#include "base64.h" // 引入Base64编码库 +#include "config.h" // 引入配置文件处理库 +#include "nlohmann/json.hpp" // 引入nlohmann JSON库 +#include "offset.h" // 引入偏移量定义文件 +#include "spdlog/spdlog.h" // 引入日志库 +#include "thread_pool.h" // 引入线程池库 +#include "utils.h" // 引入工具函数库 -#include "wxutils.h" +#include "wxutils.h" // 引入微信工具函数库 namespace wxhelper { - + + // wxhelper命名空间下的SyncMsgHook类的初始化函数 void SyncMsgHook::Init() { + // 获取微信窗口的基础地址加上偏移量kDoAddMsg int64_t addr = wxutils::GetWeChatWinBase() + wechat::offset::kDoAddMsg; + // 将获取到的地址转换为__DoAddMsg类型的函数指针 kDoAddMsg = (wechat::function::__DoAddMsg)addr; + // 保存原始的函数指针 origin_ = &kDoAddMsg; + // 设置新的函数指针,用于拦截 detour_ = &HandleSyncMsg; + // 初始化钩子标志为未激活 hook_flag_ = false; } + // 处理同步消息的函数,用于拦截微信消息并进行处理 void SyncMsgHook::HandleSyncMsg(int64_t param1, int64_t param2, int64_t param3) { + // 输出调试信息到控制台 + wxhelper::wxutils::print_utf8_to_console("HandleSyncMsg called"); + // 输出参数param2的值到控制台 + wxhelper::wxutils::print_utf8_to_console("param2:" + std::to_string(param2)); + + // 创建JSON对象用于存储消息内容 nlohmann::json msg; - msg["pid"] = GetCurrentProcessId(); - msg["fromUser"] = wxutils::ReadSKBuiltinString(*(int64_t *)(param2 + 0x18)); - msg["toUser"] = wxutils::ReadSKBuiltinString(*(int64_t *)(param2 + 0x28)); - msg["content"] = wxutils::ReadSKBuiltinString(*(int64_t *)(param2 + 0x30)); - msg["signature"] = wxutils::ReadWeChatStr(*(int64_t *)(param2 + 0x48)); - msg["msgId"] = *(int64_t *)(param2 + 0x60); - msg["msgSequence"] = *(DWORD *)(param2 + 0x5C); - msg["createTime"] = *(DWORD *)(param2 + 0x58); - msg["displayFullContent"] = wxutils::ReadWeChatStr(*(int64_t *)(param2 + 0x50)); - DWORD type = *(DWORD *)(param2 + 0x24); - msg["type"] = type; + // 填充消息内容到JSON对象 + msg["pid"] = GetCurrentProcessId(); // 当前进程ID + msg["fromUser"] = wxutils::ReadSKBuiltinString(*(int64_t *)(param2 + 0x18)); // 发送者 + msg["toUser"] = wxutils::ReadSKBuiltinString(*(int64_t *)(param2 + 0x28)); // 接收者 + msg["content"] = wxutils::ReadSKBuiltinString(*(int64_t *)(param2 + 0x30)); // 消息内容 + msg["signature"] = wxutils::ReadWeChatStr(*(int64_t *)(param2 + 0x48)); // 消息签名 + msg["msgId"] = *(int64_t *)(param2 + 0x60); // 消息ID + msg["msgSequence"] = *(DWORD *)(param2 + 0x5C); // 消息序列号 + msg["createTime"] = *(DWORD *)(param2 + 0x58); // 创建时间 + msg["displayFullContent"] = wxutils::ReadWeChatStr(*(int64_t *)(param2 + 0x50)); // 是否展示完整内容 + DWORD type = *(DWORD *)(param2 + 0x24); // 消息类型 + msg["type"] = type; // 将消息类型添加到JSON对象 + + // 根据消息类型处理图片消息 if (type == 3) { - std::string img = wxutils::ReadSKBuiltinBuffer(*(int64_t *)(param2 + 0x40)); - SPDLOG_INFO("encode size:{}", img.size()); - msg["base64Img"] = base64_encode(img); + std::string img = wxutils::ReadSKBuiltinBuffer(*(int64_t *)(param2 + 0x40)); // 读取图片数据 + SPDLOG_INFO("encode size:{}", img.size()); // 输出图片编码大小的日志 + msg["base64Img"] = base64_encode(img); // 将图片数据编码为Base64字符串 } + + // 将JSON对象转换为字符串,并添加换行符 std::string jstr = msg.dump() + '\n'; + // 创建InnerMessageStruct结构体用于存储消息 hook::InnerMessageStruct *inner_msg = new hook::InnerMessageStruct; + // 分配内存并复制JSON字符串到buffer中 inner_msg->buffer = new char[jstr.size() + 1]; memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1); + // 设置消息长度 inner_msg->length = jstr.size(); - std::string mode = Config::GetInstance().GetRecvMessageMode(); + + // 根据配置的接收消息模式,选择不同的回调函数加入线程池 + std::string mode = Config::GetInstance().GetRecvMessageMode(); // 获取接收消息模式 if (mode == "http") { bool add = base::ThreadPool::GetInstance().AddWork( - hook::SendHttpMsgCallback, inner_msg); - SPDLOG_INFO("add http msg work:{}", add); + hook::SendHttpMsgCallback, inner_msg); // 添加HTTP消息发送任务 + SPDLOG_INFO("add http msg work:{}", add); // 输出HTTP消息任务添加结果的日志 } else if (mode == "tcp") { bool add = base::ThreadPool::GetInstance().AddWork(hook::SendTcpMsgCallback, - inner_msg); - wxhelper::wxutils::print_utf8_to_console("add tcp msg work:" + std::to_string(add)); - - SPDLOG_INFO("add tcp msg work:{}", add); + inner_msg); // 添加TCP消息发送任务 + wxhelper::wxutils::print_utf8_to_console("add tcp msg work:" + std::to_string(add)); // 输出TCP消息任务添加结果到控制台 + SPDLOG_INFO("add tcp msg work:{}", add); // 输出TCP消息任务添加结果的日志 } + + // 确保原始的DoAddMsg函数指针不为空 if (kDoAddMsg == nullptr) { int64_t addr = wxutils::GetWeChatWinBase() + wechat::offset::kDoAddMsg; - kDoAddMsg = (wechat::function::__DoAddMsg)addr; + kDoAddMsg = (wechat::function::__DoAddMsg)addr; // 重新获取原始函数指针 } + // 调用原始的DoAddMsg函数,完成消息的添加 kDoAddMsg(param1, param2, param3); } } // namespace wxhelper \ No newline at end of file diff --git a/app/wxhelper/src/wxutils.cc b/app/wxhelper/src/wxutils.cc index d9faa15..a8dee43 100644 --- a/app/wxhelper/src/wxutils.cc +++ b/app/wxhelper/src/wxutils.cc @@ -1,150 +1,218 @@ -#include "wxutils.h" +// 引入wxutils.h文件,该文件可能包含与wxWidgets相关的工具函数 +#include "wxutils.h" +// 引入utils.h文件,该文件可能包含一些通用的工具函数 #include "utils.h" + +// 定义缓冲区大小为1024字节 #define BUFSIZE 1024 + +// 定义JPEG文件的魔术数字 #define JPEG0 0xFF #define JPEG1 0xD8 #define JPEG2 0xFF + +// 定义PNG文件的魔术数字 #define PNG0 0x89 #define PNG1 0x50 #define PNG2 0x4E + +// 定义BMP文件的魔术数字 #define BMP0 0x42 #define BMP1 0x4D + +// 定义GIF文件的魔术数字 #define GIF0 0x47 #define GIF1 0x49 #define GIF2 0x46 +// 引入标准输入输出库 #include +// 引入本地化设置库 #include +// 引入codecvt库,用于字符编码转换 #include +// 引入字符串库 #include -#include +// 引入时间库,用于时间函数 #include +// 引入iomanip库,用于控制输入输出格式 #include +// 引入字符串流库 #include +// 引入__msvc_chrono.hpp库,用于MSVC特有的时间函数 #include <__msvc_chrono.hpp> +// 定义wxhelper命名空间,用于封装wxWidgets相关的辅助功能 namespace wxhelper { + // 定义wxutils命名空间,用于封装微信相关的工具函数 namespace wxutils { + // 根据操作系统平台定义GetWeChatWinBase函数的返回类型 #ifdef _WIN64 + // 在64位Windows平台上,返回类型为int64_t int64_t GetWeChatWinBase() { + // 使用GetModuleHandleA函数获取WeChatWin.dll的模块句柄 return (int64_t)GetModuleHandleA("WeChatWin.dll"); } #else + // 在32位Windows平台上,返回类型为int32_t int32_t GetWeChatWinBase() { + // 使用GetModuleHandleA函数获取WeChatWin.dll的模块句柄 return (int32_t)GetModuleHandleA("WeChatWin.dll"); } #endif + // 定义ReadSKBuiltinString函数,用于读取内置字符串 std::string ReadSKBuiltinString(INT64 addr) { + // 读取地址偏移0x8处的内部字符串地址 INT64 inner_string = *(INT64 *)(addr + 0x8); + // 如果内部字符串地址为0,则返回空字符串 if (inner_string == 0) { return std::string(); } + // 否则,调用ReadWeChatStr函数读取字符串 return ReadWeChatStr(inner_string); } + // 定义ReadSKBuiltinBuffer函数,用于读取内置缓冲区 std::string ReadSKBuiltinBuffer(INT64 addr) { + // 读取地址偏移0x10处的长度 INT64 len = *(INT64 *)(addr + 0x10); + // 如果长度为0,则返回空字符串 if (len == 0) { return std::string(); } + // 读取地址偏移0x8处的内部字符串地址 INT64 inner_string = *(INT64 *)(addr + 0x8); + // 如果内部字符串地址为0,则返回空字符串 if (inner_string == 0) { return std::string(); } + // 否则,调用ReadWeChatStr函数读取字符串 return ReadWeChatStr(inner_string); } + // 定义ReadWeChatStr函数,用于读取微信字符串 std::string ReadWeChatStr(INT64 addr) { + // 读取地址偏移0x10处的长度 INT64 len = *(INT64 *)(addr + 0x10); + // 如果长度为0,则返回空字符串 if (len == 0) { return std::string(); } + // 读取地址偏移0x18处的最大长度 INT64 max_len = *(INT64 *)(addr + 0x18); + // 如果最大长度的低4位为0xF,则直接从地址处读取字符串 if ((max_len | 0xF) == 0xF) { return std::string((char *)addr, len); } + // 否则,读取地址处指向的字符指针,并从该指针处读取字符串 char *char_from_user = *(char **)(addr); return std::string(char_from_user, len); } + // 定义ImageXor函数,用于对图像数据进行异或解密 std::string ImageXor(std::string buf) { + // 获取原始数据的C风格字符串表示 const char *origin = buf.c_str(); short key = 0; + // 尝试使用JPEG的魔术数字进行解密 if ((*origin ^ JPEG0) == (*(origin + 1) ^ JPEG1)) { key = *origin ^ JPEG0; } + // 尝试使用PNG的魔术数字进行解密 else if ((*origin ^ PNG1) == (*(origin + 1) ^ PNG2)) { key = *origin ^ PNG1; } + // 尝试使用GIF的魔术数字进行解密 else if ((*origin ^ GIF0) == (*(origin + 1) ^ GIF1)) { key = *origin ^ GIF0; } + // 尝试使用BMP的魔术数字进行解密 else if ((*origin ^ BMP0) == (*(origin + 1) ^ BMP1)) { key = *origin ^ BMP0; } + // 如果无法解密,则返回空字符串 else { key = -1; } + // 如果找到了解密密钥,则进行解密 if (key > 0) { + // 分配内存用于存放解密后的图像数据 char *img_buf = new char[buf.size()]; + // 对图像数据进行异或操作进行解密 for (unsigned int i = 0; i < buf.size(); i++) { img_buf[i] = *(origin + i) ^ key; } + // 创建解密后的字符串并返回 std::string str(img_buf); + // 释放分配的内存 delete[] img_buf; img_buf = NULL; return str; } + // 如果没有找到解密密钥,则返回空字符串 return std::string(); } + // 定义ReadWstring函数,用于读取宽字符字符串 std::wstring ReadWstring(INT64 addr) { + // 读取地址偏移0x8处的长度 DWORD len = *(DWORD *)(addr + 0x8); + // 如果长度为0,则返回空宽字符串 if (len == 0) { return std::wstring(); } + // 读取地址处指向的宽字符指针 wchar_t *str = *(wchar_t **)(addr); + // 如果宽字符指针为空,则返回空宽字符串 if (str == NULL) { return std::wstring(); } + // 否则,从宽字符指针处读取宽字符串 return std::wstring(str, len); } + + // 定义ReadWstringThenConvert函数,用于读取宽字符串并转换为UTF-8字符串 std::string ReadWstringThenConvert(INT64 addr) { + // 调用ReadWstring函数读取宽字符串 std::wstring wstr = ReadWstring(addr); + // 调用WstringToUtf8函数将宽字符串转换为UTF-8字符串 return base::utils::WstringToUtf8(wstr); } + // 定义DecodeImage函数,用于解码图像数据 int DecodeImage(const wchar_t *file_path, const wchar_t *save_dir) { + // 该函数目前尚未实现,返回-1表示失败 return -1; } + // 定义print_utf8_to_console函数,用于将UTF-8字符串打印到控制台 void print_utf8_to_console(const std::string &utf8_str) { // 获取当前时间 @@ -170,4 +238,4 @@ namespace wxhelper } } // namespace wxutils -} // namespace wxhelper +} // namespace wxhelper \ No newline at end of file