From 1979fd80424d16b2e489f9b57d01d9c7811d25a2 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Mon, 2 Jan 2023 21:10:29 +0300 Subject: Update copyrights --- protocols/MinecraftDynmap/src/chat.cpp | 368 +++++----- protocols/MinecraftDynmap/src/communication.cpp | 884 ++++++++++++------------ protocols/MinecraftDynmap/src/constants.h | 92 +-- protocols/MinecraftDynmap/src/dialogs.cpp | 196 +++--- protocols/MinecraftDynmap/src/dialogs.h | 54 +- protocols/MinecraftDynmap/src/main.cpp | 180 ++--- protocols/MinecraftDynmap/src/proto.cpp | 360 +++++----- protocols/MinecraftDynmap/src/proto.h | 272 ++++---- protocols/MinecraftDynmap/src/stdafx.cxx | 34 +- protocols/MinecraftDynmap/src/stdafx.h | 140 ++-- protocols/MinecraftDynmap/src/utils.h | 126 ++-- protocols/MinecraftDynmap/src/version.h | 2 +- 12 files changed, 1354 insertions(+), 1354 deletions(-) (limited to 'protocols/MinecraftDynmap/src') diff --git a/protocols/MinecraftDynmap/src/chat.cpp b/protocols/MinecraftDynmap/src/chat.cpp index a6f15cc115..c0c1f80542 100644 --- a/protocols/MinecraftDynmap/src/chat.cpp +++ b/protocols/MinecraftDynmap/src/chat.cpp @@ -1,185 +1,185 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "stdafx.h" - -void MinecraftDynmapProto::UpdateChat(const char *name, const char *message, const time_t timestamp, bool addtolog) -{ - // replace % to %% to not interfere with chat color codes - CMStringA szMessage(message); - szMessage.Replace("%", "%%"); - - GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_MESSAGE }; - gce.dwFlags = GCEF_UTF8; - gce.time = timestamp; - gce.pszText.a = szMessage.c_str(); - - if (name == NULL) { - gce.iType = GC_EVENT_INFORMATION; - name = TranslateU("Server"); - gce.bIsMe = false; - } - else gce.bIsMe = (m_nick == name); - - if (addtolog) - gce.dwFlags |= GCEF_ADDTOLOG; - - gce.pszUID.a = gce.pszNick.a = name; - Chat_Event(&gce); -} - -int MinecraftDynmapProto::OnChatEvent(WPARAM, LPARAM lParam) -{ - GCHOOK *hook = reinterpret_cast(lParam); - if(strcmp(hook->si->pszModule,m_szModuleName)) - return 0; - - switch(hook->iType) { - case GC_USER_MESSAGE: - { - CMStringA szText(ptrA(mir_utf8encodeW(hook->ptszText))); - szText.Replace("%%", "%"); - if (szText.IsEmpty()) - break; - - // Outgoing message - debugLogA("**Chat - Outgoing message: %s", szText.c_str()); - ForkThread(&MinecraftDynmapProto::SendMsgWorker, new std::string(szText)); - } - break; - - case GC_SESSION_TERMINATE: - m_nick.clear(); - SetStatus(ID_STATUS_OFFLINE); - break; - } - - return 0; -} - -void MinecraftDynmapProto::AddChatContact(const char *name) -{ - GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_JOIN }; - gce.time = uint32_t(time(0)); - gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG; - gce.pszUID.a = gce.pszNick.a = name; - gce.bIsMe = (m_nick == name); - - if (gce.bIsMe) - gce.pszStatus.a = "Admin"; - else - gce.pszStatus.a = "Normal"; - - Chat_Event(&gce); -} - -void MinecraftDynmapProto::DeleteChatContact(const char *name) -{ - GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_PART }; - gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG; - gce.pszUID.a = gce.pszNick.a = name; - gce.time = uint32_t(time(0)); - gce.bIsMe = (m_nick == name); - Chat_Event(&gce); -} - -INT_PTR MinecraftDynmapProto::OnJoinChat(WPARAM,LPARAM suppress) -{ - ptrW tszTitle(mir_a2u_cp(m_title.c_str(), CP_UTF8)); - - // Create the group chat session - SESSION_INFO *si = Chat_NewSession(GCW_PRIVMESS, m_szModuleName, m_tszUserName, tszTitle); - if (!si || m_iStatus == ID_STATUS_OFFLINE) - return 0; - - // Create a group - Chat_AddGroup(si, TranslateT("Admin")); - Chat_AddGroup(si, TranslateT("Normal")); - - // Note: Initialization will finish up in SetChatStatus, called separately - if (!suppress) - SetChatStatus(m_iStatus); - - return 0; -} - -void MinecraftDynmapProto::SetTopic(const char *topic) -{ - GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_TOPIC }; - gce.dwFlags = GCEF_UTF8; - gce.time = ::time(0); - gce.pszText.a = topic; - Chat_Event( &gce); -} - -INT_PTR MinecraftDynmapProto::OnLeaveChat(WPARAM,LPARAM) -{ - Chat_Control(m_szModuleName, m_tszUserName, SESSION_OFFLINE); - Chat_Terminate(m_szModuleName, m_tszUserName); - return 0; -} - -void MinecraftDynmapProto::SetChatStatus(int status) -{ - if (status == ID_STATUS_ONLINE) - { - // Load actual name from database - ptrA nick(db_get_sa(0, m_szModuleName, MINECRAFTDYNMAP_KEY_NAME, Translate("You"))); - m_nick = nick; - - // Add self contact - AddChatContact(m_nick.c_str()); - - Chat_Control(m_szModuleName, m_tszUserName, SESSION_INITDONE); - Chat_Control(m_szModuleName, m_tszUserName, SESSION_ONLINE); - } - else Chat_Control(m_szModuleName, m_tszUserName, SESSION_OFFLINE); -} - -void MinecraftDynmapProto::ClearChat() -{ - Chat_Control(m_szModuleName, m_tszUserName, WINDOW_CLEARLOG); -} - -// TODO: Could this be done better? -MCONTACT MinecraftDynmapProto::GetChatHandle() -{ - /*if (chatHandle_ != NULL) - return chatHandle_; - - for (auto &hContact : AccContacts()) { - if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) > 0) { - ptrA id = db_get_sa(hContact, m_szModuleName, "ChatRoomId"); - if (id != NULL && !strcmp(id, m_szModuleName)) - return hContact; - } - } - - return NULL;*/ - - GC_INFO gci = {0}; - gci.Flags = GCF_HCONTACT; - gci.pszModule = m_szModuleName; - gci.pszID = m_tszUserName; - Chat_GetInfo(&gci); - - return gci.hContact; +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" + +void MinecraftDynmapProto::UpdateChat(const char *name, const char *message, const time_t timestamp, bool addtolog) +{ + // replace % to %% to not interfere with chat color codes + CMStringA szMessage(message); + szMessage.Replace("%", "%%"); + + GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_MESSAGE }; + gce.dwFlags = GCEF_UTF8; + gce.time = timestamp; + gce.pszText.a = szMessage.c_str(); + + if (name == NULL) { + gce.iType = GC_EVENT_INFORMATION; + name = TranslateU("Server"); + gce.bIsMe = false; + } + else gce.bIsMe = (m_nick == name); + + if (addtolog) + gce.dwFlags |= GCEF_ADDTOLOG; + + gce.pszUID.a = gce.pszNick.a = name; + Chat_Event(&gce); +} + +int MinecraftDynmapProto::OnChatEvent(WPARAM, LPARAM lParam) +{ + GCHOOK *hook = reinterpret_cast(lParam); + if(strcmp(hook->si->pszModule,m_szModuleName)) + return 0; + + switch(hook->iType) { + case GC_USER_MESSAGE: + { + CMStringA szText(ptrA(mir_utf8encodeW(hook->ptszText))); + szText.Replace("%%", "%"); + if (szText.IsEmpty()) + break; + + // Outgoing message + debugLogA("**Chat - Outgoing message: %s", szText.c_str()); + ForkThread(&MinecraftDynmapProto::SendMsgWorker, new std::string(szText)); + } + break; + + case GC_SESSION_TERMINATE: + m_nick.clear(); + SetStatus(ID_STATUS_OFFLINE); + break; + } + + return 0; +} + +void MinecraftDynmapProto::AddChatContact(const char *name) +{ + GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_JOIN }; + gce.time = uint32_t(time(0)); + gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG; + gce.pszUID.a = gce.pszNick.a = name; + gce.bIsMe = (m_nick == name); + + if (gce.bIsMe) + gce.pszStatus.a = "Admin"; + else + gce.pszStatus.a = "Normal"; + + Chat_Event(&gce); +} + +void MinecraftDynmapProto::DeleteChatContact(const char *name) +{ + GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_PART }; + gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG; + gce.pszUID.a = gce.pszNick.a = name; + gce.time = uint32_t(time(0)); + gce.bIsMe = (m_nick == name); + Chat_Event(&gce); +} + +INT_PTR MinecraftDynmapProto::OnJoinChat(WPARAM,LPARAM suppress) +{ + ptrW tszTitle(mir_a2u_cp(m_title.c_str(), CP_UTF8)); + + // Create the group chat session + SESSION_INFO *si = Chat_NewSession(GCW_PRIVMESS, m_szModuleName, m_tszUserName, tszTitle); + if (!si || m_iStatus == ID_STATUS_OFFLINE) + return 0; + + // Create a group + Chat_AddGroup(si, TranslateT("Admin")); + Chat_AddGroup(si, TranslateT("Normal")); + + // Note: Initialization will finish up in SetChatStatus, called separately + if (!suppress) + SetChatStatus(m_iStatus); + + return 0; +} + +void MinecraftDynmapProto::SetTopic(const char *topic) +{ + GCEVENT gce = { m_szModuleName, szRoomName, GC_EVENT_TOPIC }; + gce.dwFlags = GCEF_UTF8; + gce.time = ::time(0); + gce.pszText.a = topic; + Chat_Event( &gce); +} + +INT_PTR MinecraftDynmapProto::OnLeaveChat(WPARAM,LPARAM) +{ + Chat_Control(m_szModuleName, m_tszUserName, SESSION_OFFLINE); + Chat_Terminate(m_szModuleName, m_tszUserName); + return 0; +} + +void MinecraftDynmapProto::SetChatStatus(int status) +{ + if (status == ID_STATUS_ONLINE) + { + // Load actual name from database + ptrA nick(db_get_sa(0, m_szModuleName, MINECRAFTDYNMAP_KEY_NAME, Translate("You"))); + m_nick = nick; + + // Add self contact + AddChatContact(m_nick.c_str()); + + Chat_Control(m_szModuleName, m_tszUserName, SESSION_INITDONE); + Chat_Control(m_szModuleName, m_tszUserName, SESSION_ONLINE); + } + else Chat_Control(m_szModuleName, m_tszUserName, SESSION_OFFLINE); +} + +void MinecraftDynmapProto::ClearChat() +{ + Chat_Control(m_szModuleName, m_tszUserName, WINDOW_CLEARLOG); +} + +// TODO: Could this be done better? +MCONTACT MinecraftDynmapProto::GetChatHandle() +{ + /*if (chatHandle_ != NULL) + return chatHandle_; + + for (auto &hContact : AccContacts()) { + if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) > 0) { + ptrA id = db_get_sa(hContact, m_szModuleName, "ChatRoomId"); + if (id != NULL && !strcmp(id, m_szModuleName)) + return hContact; + } + } + + return NULL;*/ + + GC_INFO gci = {0}; + gci.Flags = GCF_HCONTACT; + gci.pszModule = m_szModuleName; + gci.pszID = m_tszUserName; + Chat_GetInfo(&gci); + + return gci.hContact; } \ No newline at end of file diff --git a/protocols/MinecraftDynmap/src/communication.cpp b/protocols/MinecraftDynmap/src/communication.cpp index 7ca5f0a732..47e6ec4480 100644 --- a/protocols/MinecraftDynmap/src/communication.cpp +++ b/protocols/MinecraftDynmap/src/communication.cpp @@ -1,442 +1,442 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "stdafx.h" - -http::response MinecraftDynmapProto::sendRequest(const int request_type, std::string *post_data, std::string *get_data) -{ - http::response resp; - - // Prepare the request - NETLIBHTTPREQUEST nlhr = { sizeof(NETLIBHTTPREQUEST) }; - - // FIXME: get server - - // Set request URL - std::string url = m_server + chooseAction(request_type, get_data); - nlhr.szUrl = (char*)url.c_str(); - - // Set timeout (bigger for channel request) - nlhr.timeout = 1000 * ((request_type == MINECRAFTDYNMAP_REQUEST_EVENTS) ? 65 : 20); - - // Set request type (GET/POST) and eventually also POST data - if (post_data != nullptr) { - nlhr.requestType = REQUEST_POST; - nlhr.pData = (char*)(*post_data).c_str(); - nlhr.dataLength = (int)post_data->length(); - } - else { - nlhr.requestType = REQUEST_GET; - } - - // Set headers - it depends on requestType so it must be after setting that - nlhr.headers = get_request_headers(nlhr.requestType, &nlhr.headersCount); - - // Set flags - nlhr.flags = NLHRF_HTTP11; - -#ifdef _DEBUG - nlhr.flags |= NLHRF_DUMPASTEXT; -#else - nlhr.flags |= NLHRF_NODUMP; -#endif - - // Set persistent connection (or not) - switch (request_type) - { - case MINECRAFTDYNMAP_REQUEST_HOME: - nlhr.nlc = nullptr; - break; - - case MINECRAFTDYNMAP_REQUEST_EVENTS: - nlhr.nlc = hEventsConnection; - nlhr.flags |= NLHRF_PERSISTENT; - break; - - default: - WaitForSingleObject(connection_lock_, INFINITE); - nlhr.nlc = hConnection; - nlhr.flags |= NLHRF_PERSISTENT; - break; - } - - debugLogA("@@@@@ Sending request to '%s'", nlhr.szUrl); - - // Send the request - NLHR_PTR pnlhr(Netlib_HttpTransaction(m_hNetlibUser, &nlhr)); - - mir_free(nlhr.headers); - - // Remember the persistent connection handle (or not) - switch (request_type) { - case MINECRAFTDYNMAP_REQUEST_HOME: - break; - - case MINECRAFTDYNMAP_REQUEST_EVENTS: - hEventsConnection = pnlhr ? pnlhr->nlc : nullptr; - break; - - default: - ReleaseMutex(connection_lock_); - hConnection = pnlhr ? pnlhr->nlc : nullptr; - break; - } - - // Check and copy response data - if (pnlhr != nullptr) - { - debugLogA("@@@@@ Got response with code %d", pnlhr->resultCode); - store_headers(&resp, pnlhr->headers, pnlhr->headersCount); - resp.code = pnlhr->resultCode; - resp.data = pnlhr->pData ? pnlhr->pData : ""; - - // debugLogA("&&&&& Got response: %s", resp.data.c_str()); - } else { - debugLogA("!!!!! No response from server (time-out)"); - resp.code = HTTP_CODE_FAKE_DISCONNECTED; - // Better to have something set explicitely as this value is compaired in all communication requests - } - - return resp; -} - -////////////////////////////////////////////////////////////////////////////// - -std::string MinecraftDynmapProto::chooseAction(int request_type, std::string *get_data) -{ - switch (request_type) { - case MINECRAFTDYNMAP_REQUEST_MESSAGE: - return "/up/sendmessage"; - - case MINECRAFTDYNMAP_REQUEST_CONFIGURATION: - return "/up/configuration"; - - case MINECRAFTDYNMAP_REQUEST_EVENTS: - return std::string("/up/world/world/") + (!m_timestamp.empty() ? m_timestamp : "0"); - - //case MINECRAFTDYNMAP_REQUEST_HOME: - default: - return "/" + *get_data; - } -} - - -NETLIBHTTPHEADER* MinecraftDynmapProto::get_request_headers(int request_type, int* headers_count) -{ - if (request_type == REQUEST_POST) - *headers_count = 5; - else - *headers_count = 4; - - NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(*headers_count)); - - if (request_type == REQUEST_POST) { - headers[4].szName = "Content-Type"; - headers[4].szValue = "application/json; charset=utf-8"; - } - - headers[3].szName = "Cookie"; - headers[3].szValue = (char *)m_cookie.c_str(); - headers[2].szName = "User-Agent"; - headers[2].szValue = (char *)g_strUserAgent.c_str(); - headers[1].szName = "Accept"; - headers[1].szValue = "*/*"; - headers[0].szName = "Accept-Language"; - headers[0].szValue = "en,en-US;q=0.9"; - - return headers; -} - -void MinecraftDynmapProto::store_headers(http::response* resp, NETLIBHTTPHEADER* headers, int headersCount) -{ - for (size_t i = 0; i < (size_t)headersCount; i++) { - std::string header_name = headers[i].szName; - std::string header_value = headers[i].szValue; - - resp->headers[header_name] = header_value; - } -} - -////////////////////////////////////////////////////////////////////////////// - -bool MinecraftDynmapProto::doSignOn() -{ - handleEntry(__FUNCTION__); - - http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_CONFIGURATION); - - if (resp.code != HTTP_CODE_OK) { - return handleError(__FUNCTION__, "Can't load configuration", true); - } - - JSONNode root = JSONNode::parse(resp.data.c_str()); - if (!root) - return false; - - /* - const JSONNode &allowchat_ = root["allowchat"]; // boolean - const JSONNode &allowwebchat_ = root["allowwebchat"]; // boolean - const JSONNode &loggedin_ = root["loggedin"]; // boolean - const JSONNode &loginEnabled_ = root["login-enabled"]; // boolean - const JSONNode &loginRequired_ = root["webchat-requires-login"]; // boolean - */ - - const JSONNode &title_ = root["title"]; // name of server - const JSONNode &interval_ = root["webchat-interval"]; // limit in seconds for sending messages - const JSONNode &rate_ = root["updaterate"]; // probably update rate for events request - - if (!title_ || !interval_ || !rate_) { - return handleError(__FUNCTION__, "No title, interval or rate in configuration", true); - } - - m_title = title_.as_string(); - m_interval = interval_.as_int(); - m_updateRate = rate_.as_int(); - m_cookie.clear(); - - if (resp.headers.find("Set-Cookie") != resp.headers.end()) { - // Load Session identifier - std::string cookies = resp.headers["Set-Cookie"]; - - const char *findStr = "JSESSIONID="; - std::string::size_type start = cookies.find(findStr); - - if (start != std::string::npos) { - m_cookie = cookies.substr(start, cookies.find(";") - start); - } - } - - if (m_cookie.empty()) { - return handleError(__FUNCTION__, "Empty session id", true); - } - - return handleSuccess(__FUNCTION__); -} - -bool MinecraftDynmapProto::doEvents() -{ - handleEntry(__FUNCTION__); - - // Get update - http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_EVENTS); - - if (resp.code != HTTP_CODE_OK) - return handleError(__FUNCTION__, "Response is not code 200"); - - JSONNode root = JSONNode::parse(resp.data.c_str()); - if (!root) - return handleError(__FUNCTION__, "Invalid JSON response"); - - const JSONNode ×tamp_ = root["timestamp"]; - if (!timestamp_) - return handleError(__FUNCTION__, "Received no timestamp node"); - - m_timestamp = timestamp_.as_string(); - - const JSONNode &updates_ = root["updates"]; - if (!updates_) - return handleError(__FUNCTION__, "Received no updates node"); - - for (auto it = updates_.begin(); it != updates_.end(); ++it) { - const JSONNode &type_ = (*it)["type"]; - if (type_ && type_.as_string() == "chat") { - const JSONNode &time_ = (*it)["timestamp"]; - // const JSONNode &source_ = (*it)["source"]; // e.g. "web" - const JSONNode &playerName_ = (*it)["playerName"]; - const JSONNode &message_ = (*it)["message"]; - // TODO: there are also "channel" and "account" elements - - if (!time_ || !playerName_ || !message_) { - debugLogW(L"Error: No player name, time or text for message"); - continue; - } - - time_t timestamp = atoi(time_.as_string().c_str()); - std::string name = playerName_.as_string(); - std::string message = message_.as_string(); - - debugLogW(L"Received message: [%d] %s -> %s", timestamp, name.c_str(), message.c_str()); - UpdateChat(name.c_str(), message.c_str(), timestamp); - } - } - - return handleSuccess(__FUNCTION__); -} - -bool MinecraftDynmapProto::doSendMessage(const std::string &message_text) -{ - handleEntry(__FUNCTION__); - - JSONNode json(JSON_NODE); - json.push_back(JSONNode("name", m_nick.c_str())); - json.push_back(JSONNode("message", message_text.c_str())); - std::string data = json.write(); - - http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_MESSAGE, &data); - - if (resp.code == HTTP_CODE_OK) { - JSONNode root = JSONNode::parse(resp.data.c_str()); - if (root) { - const JSONNode &error_ = root["error"]; - if (error_) { - std::string error = error_.as_string(); - if (error == "none") { - return handleSuccess(__FUNCTION__); - } - else if (error == "not-allowed") { - UpdateChat(nullptr, Translate("Message was not sent. Probably you are sending them too fast or chat is disabled completely.")); - } - } - } - } - - return handleError(__FUNCTION__); -} - -std::string MinecraftDynmapProto::doGetPage(const int request_type) -{ - handleEntry(__FUNCTION__); - - http::response resp = sendRequest(request_type); - - if (resp.code == HTTP_CODE_OK) { - handleSuccess(__FUNCTION__); - } else { - handleError(__FUNCTION__); - } - - return resp.data; -} - -void MinecraftDynmapProto::SignOnWorker(void*) -{ - SYSTEMTIME t; - GetLocalTime(&t); - debugLogA("[%d.%d.%d] Using Omegle Protocol %s", t.wDay, t.wMonth, t.wYear, __VERSION_STRING_DOTS); - - ScopedLock s(signon_lock_); - - int old_status = m_iStatus; - - // Load server from database - ptrA str(db_get_sa(0, m_szModuleName, MINECRAFTDYNMAP_KEY_SERVER)); - if (!str || !str[0]) { - MessageBox(nullptr, TranslateT("Set server address to connect."), m_tszUserName, MB_OK); - SetStatus(ID_STATUS_OFFLINE); - return; - } - m_server = str; - - // Fix format of given server - if (m_server.substr(0, 7) != "http://" && m_server.substr(0, 8) != "https://") - m_server = "http://" + m_server; - if (m_server.substr(m_server.length() - 1, 1) == "/") - m_server = m_server.substr(0, m_server.length() -1); - - if (doSignOn()) { - // Signed in, switch to online, create chatroom and start events loop - m_iStatus = m_iDesiredStatus; - ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); - - setDword("LogonTS", (uint32_t)time(0)); - ClearChat(); - OnJoinChat(0, false); - - ResetEvent(events_loop_event_); - - ForkThread(&MinecraftDynmapProto::EventsLoop, this); - } - else { - // Some error - ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_FAILED, (HANDLE)old_status, m_iStatus); - } - -} - -void MinecraftDynmapProto::SignOffWorker(void*) -{ - ScopedLock s(signon_lock_); - - SetEvent(events_loop_event_); - - m_cookie.clear(); - m_title.clear(); - m_server.clear(); - m_timestamp.clear(); - - int old_status = m_iStatus; - m_iStatus = ID_STATUS_OFFLINE; - - Netlib_Shutdown(hEventsConnection); - - OnLeaveChat(NULL, NULL); - - delSetting("LogonTS"); - - ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); - - if (hConnection) - Netlib_CloseHandle(hConnection); - hConnection = nullptr; - - if (hEventsConnection) - Netlib_CloseHandle(hEventsConnection); - hEventsConnection = nullptr; -} - -void MinecraftDynmapProto::EventsLoop(void *) -{ - ScopedLock s(events_loop_lock_); - - time_t tim = ::time(0); - debugLogA(">>>>> Entering %s[%d]", __FUNCTION__, tim); - - while (doEvents()) - { - if (!isOnline()) - break; - - if (WaitForSingleObjectEx(events_loop_event_, m_updateRate, true) != WAIT_TIMEOUT) // FIXME: correct timeout - break; - - debugLogA("***** %s[%d] refreshing...", __FUNCTION__, tim); - } - - ResetEvent(events_loop_event_); - ResetEvent(events_loop_lock_); - debugLogA("<<<<< Exiting %s[%d]", __FUNCTION__, tim); -} - -void MinecraftDynmapProto::SendMsgWorker(void *p) -{ - if (p == nullptr) - return; - - ScopedLock s(send_message_lock_); - - CMStringA data = ((std::string*)p)->c_str(); - delete (std::string*)p; - - data.TrimRight(); - - if (isOnline() && data.GetLength()) - doSendMessage(data.c_str()); -} +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" + +http::response MinecraftDynmapProto::sendRequest(const int request_type, std::string *post_data, std::string *get_data) +{ + http::response resp; + + // Prepare the request + NETLIBHTTPREQUEST nlhr = { sizeof(NETLIBHTTPREQUEST) }; + + // FIXME: get server + + // Set request URL + std::string url = m_server + chooseAction(request_type, get_data); + nlhr.szUrl = (char*)url.c_str(); + + // Set timeout (bigger for channel request) + nlhr.timeout = 1000 * ((request_type == MINECRAFTDYNMAP_REQUEST_EVENTS) ? 65 : 20); + + // Set request type (GET/POST) and eventually also POST data + if (post_data != nullptr) { + nlhr.requestType = REQUEST_POST; + nlhr.pData = (char*)(*post_data).c_str(); + nlhr.dataLength = (int)post_data->length(); + } + else { + nlhr.requestType = REQUEST_GET; + } + + // Set headers - it depends on requestType so it must be after setting that + nlhr.headers = get_request_headers(nlhr.requestType, &nlhr.headersCount); + + // Set flags + nlhr.flags = NLHRF_HTTP11; + +#ifdef _DEBUG + nlhr.flags |= NLHRF_DUMPASTEXT; +#else + nlhr.flags |= NLHRF_NODUMP; +#endif + + // Set persistent connection (or not) + switch (request_type) + { + case MINECRAFTDYNMAP_REQUEST_HOME: + nlhr.nlc = nullptr; + break; + + case MINECRAFTDYNMAP_REQUEST_EVENTS: + nlhr.nlc = hEventsConnection; + nlhr.flags |= NLHRF_PERSISTENT; + break; + + default: + WaitForSingleObject(connection_lock_, INFINITE); + nlhr.nlc = hConnection; + nlhr.flags |= NLHRF_PERSISTENT; + break; + } + + debugLogA("@@@@@ Sending request to '%s'", nlhr.szUrl); + + // Send the request + NLHR_PTR pnlhr(Netlib_HttpTransaction(m_hNetlibUser, &nlhr)); + + mir_free(nlhr.headers); + + // Remember the persistent connection handle (or not) + switch (request_type) { + case MINECRAFTDYNMAP_REQUEST_HOME: + break; + + case MINECRAFTDYNMAP_REQUEST_EVENTS: + hEventsConnection = pnlhr ? pnlhr->nlc : nullptr; + break; + + default: + ReleaseMutex(connection_lock_); + hConnection = pnlhr ? pnlhr->nlc : nullptr; + break; + } + + // Check and copy response data + if (pnlhr != nullptr) + { + debugLogA("@@@@@ Got response with code %d", pnlhr->resultCode); + store_headers(&resp, pnlhr->headers, pnlhr->headersCount); + resp.code = pnlhr->resultCode; + resp.data = pnlhr->pData ? pnlhr->pData : ""; + + // debugLogA("&&&&& Got response: %s", resp.data.c_str()); + } else { + debugLogA("!!!!! No response from server (time-out)"); + resp.code = HTTP_CODE_FAKE_DISCONNECTED; + // Better to have something set explicitely as this value is compaired in all communication requests + } + + return resp; +} + +////////////////////////////////////////////////////////////////////////////// + +std::string MinecraftDynmapProto::chooseAction(int request_type, std::string *get_data) +{ + switch (request_type) { + case MINECRAFTDYNMAP_REQUEST_MESSAGE: + return "/up/sendmessage"; + + case MINECRAFTDYNMAP_REQUEST_CONFIGURATION: + return "/up/configuration"; + + case MINECRAFTDYNMAP_REQUEST_EVENTS: + return std::string("/up/world/world/") + (!m_timestamp.empty() ? m_timestamp : "0"); + + //case MINECRAFTDYNMAP_REQUEST_HOME: + default: + return "/" + *get_data; + } +} + + +NETLIBHTTPHEADER* MinecraftDynmapProto::get_request_headers(int request_type, int* headers_count) +{ + if (request_type == REQUEST_POST) + *headers_count = 5; + else + *headers_count = 4; + + NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(*headers_count)); + + if (request_type == REQUEST_POST) { + headers[4].szName = "Content-Type"; + headers[4].szValue = "application/json; charset=utf-8"; + } + + headers[3].szName = "Cookie"; + headers[3].szValue = (char *)m_cookie.c_str(); + headers[2].szName = "User-Agent"; + headers[2].szValue = (char *)g_strUserAgent.c_str(); + headers[1].szName = "Accept"; + headers[1].szValue = "*/*"; + headers[0].szName = "Accept-Language"; + headers[0].szValue = "en,en-US;q=0.9"; + + return headers; +} + +void MinecraftDynmapProto::store_headers(http::response* resp, NETLIBHTTPHEADER* headers, int headersCount) +{ + for (size_t i = 0; i < (size_t)headersCount; i++) { + std::string header_name = headers[i].szName; + std::string header_value = headers[i].szValue; + + resp->headers[header_name] = header_value; + } +} + +////////////////////////////////////////////////////////////////////////////// + +bool MinecraftDynmapProto::doSignOn() +{ + handleEntry(__FUNCTION__); + + http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_CONFIGURATION); + + if (resp.code != HTTP_CODE_OK) { + return handleError(__FUNCTION__, "Can't load configuration", true); + } + + JSONNode root = JSONNode::parse(resp.data.c_str()); + if (!root) + return false; + + /* + const JSONNode &allowchat_ = root["allowchat"]; // boolean + const JSONNode &allowwebchat_ = root["allowwebchat"]; // boolean + const JSONNode &loggedin_ = root["loggedin"]; // boolean + const JSONNode &loginEnabled_ = root["login-enabled"]; // boolean + const JSONNode &loginRequired_ = root["webchat-requires-login"]; // boolean + */ + + const JSONNode &title_ = root["title"]; // name of server + const JSONNode &interval_ = root["webchat-interval"]; // limit in seconds for sending messages + const JSONNode &rate_ = root["updaterate"]; // probably update rate for events request + + if (!title_ || !interval_ || !rate_) { + return handleError(__FUNCTION__, "No title, interval or rate in configuration", true); + } + + m_title = title_.as_string(); + m_interval = interval_.as_int(); + m_updateRate = rate_.as_int(); + m_cookie.clear(); + + if (resp.headers.find("Set-Cookie") != resp.headers.end()) { + // Load Session identifier + std::string cookies = resp.headers["Set-Cookie"]; + + const char *findStr = "JSESSIONID="; + std::string::size_type start = cookies.find(findStr); + + if (start != std::string::npos) { + m_cookie = cookies.substr(start, cookies.find(";") - start); + } + } + + if (m_cookie.empty()) { + return handleError(__FUNCTION__, "Empty session id", true); + } + + return handleSuccess(__FUNCTION__); +} + +bool MinecraftDynmapProto::doEvents() +{ + handleEntry(__FUNCTION__); + + // Get update + http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_EVENTS); + + if (resp.code != HTTP_CODE_OK) + return handleError(__FUNCTION__, "Response is not code 200"); + + JSONNode root = JSONNode::parse(resp.data.c_str()); + if (!root) + return handleError(__FUNCTION__, "Invalid JSON response"); + + const JSONNode ×tamp_ = root["timestamp"]; + if (!timestamp_) + return handleError(__FUNCTION__, "Received no timestamp node"); + + m_timestamp = timestamp_.as_string(); + + const JSONNode &updates_ = root["updates"]; + if (!updates_) + return handleError(__FUNCTION__, "Received no updates node"); + + for (auto it = updates_.begin(); it != updates_.end(); ++it) { + const JSONNode &type_ = (*it)["type"]; + if (type_ && type_.as_string() == "chat") { + const JSONNode &time_ = (*it)["timestamp"]; + // const JSONNode &source_ = (*it)["source"]; // e.g. "web" + const JSONNode &playerName_ = (*it)["playerName"]; + const JSONNode &message_ = (*it)["message"]; + // TODO: there are also "channel" and "account" elements + + if (!time_ || !playerName_ || !message_) { + debugLogW(L"Error: No player name, time or text for message"); + continue; + } + + time_t timestamp = atoi(time_.as_string().c_str()); + std::string name = playerName_.as_string(); + std::string message = message_.as_string(); + + debugLogW(L"Received message: [%d] %s -> %s", timestamp, name.c_str(), message.c_str()); + UpdateChat(name.c_str(), message.c_str(), timestamp); + } + } + + return handleSuccess(__FUNCTION__); +} + +bool MinecraftDynmapProto::doSendMessage(const std::string &message_text) +{ + handleEntry(__FUNCTION__); + + JSONNode json(JSON_NODE); + json.push_back(JSONNode("name", m_nick.c_str())); + json.push_back(JSONNode("message", message_text.c_str())); + std::string data = json.write(); + + http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_MESSAGE, &data); + + if (resp.code == HTTP_CODE_OK) { + JSONNode root = JSONNode::parse(resp.data.c_str()); + if (root) { + const JSONNode &error_ = root["error"]; + if (error_) { + std::string error = error_.as_string(); + if (error == "none") { + return handleSuccess(__FUNCTION__); + } + else if (error == "not-allowed") { + UpdateChat(nullptr, Translate("Message was not sent. Probably you are sending them too fast or chat is disabled completely.")); + } + } + } + } + + return handleError(__FUNCTION__); +} + +std::string MinecraftDynmapProto::doGetPage(const int request_type) +{ + handleEntry(__FUNCTION__); + + http::response resp = sendRequest(request_type); + + if (resp.code == HTTP_CODE_OK) { + handleSuccess(__FUNCTION__); + } else { + handleError(__FUNCTION__); + } + + return resp.data; +} + +void MinecraftDynmapProto::SignOnWorker(void*) +{ + SYSTEMTIME t; + GetLocalTime(&t); + debugLogA("[%d.%d.%d] Using Omegle Protocol %s", t.wDay, t.wMonth, t.wYear, __VERSION_STRING_DOTS); + + ScopedLock s(signon_lock_); + + int old_status = m_iStatus; + + // Load server from database + ptrA str(db_get_sa(0, m_szModuleName, MINECRAFTDYNMAP_KEY_SERVER)); + if (!str || !str[0]) { + MessageBox(nullptr, TranslateT("Set server address to connect."), m_tszUserName, MB_OK); + SetStatus(ID_STATUS_OFFLINE); + return; + } + m_server = str; + + // Fix format of given server + if (m_server.substr(0, 7) != "http://" && m_server.substr(0, 8) != "https://") + m_server = "http://" + m_server; + if (m_server.substr(m_server.length() - 1, 1) == "/") + m_server = m_server.substr(0, m_server.length() -1); + + if (doSignOn()) { + // Signed in, switch to online, create chatroom and start events loop + m_iStatus = m_iDesiredStatus; + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); + + setDword("LogonTS", (uint32_t)time(0)); + ClearChat(); + OnJoinChat(0, false); + + ResetEvent(events_loop_event_); + + ForkThread(&MinecraftDynmapProto::EventsLoop, this); + } + else { + // Some error + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_FAILED, (HANDLE)old_status, m_iStatus); + } + +} + +void MinecraftDynmapProto::SignOffWorker(void*) +{ + ScopedLock s(signon_lock_); + + SetEvent(events_loop_event_); + + m_cookie.clear(); + m_title.clear(); + m_server.clear(); + m_timestamp.clear(); + + int old_status = m_iStatus; + m_iStatus = ID_STATUS_OFFLINE; + + Netlib_Shutdown(hEventsConnection); + + OnLeaveChat(NULL, NULL); + + delSetting("LogonTS"); + + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); + + if (hConnection) + Netlib_CloseHandle(hConnection); + hConnection = nullptr; + + if (hEventsConnection) + Netlib_CloseHandle(hEventsConnection); + hEventsConnection = nullptr; +} + +void MinecraftDynmapProto::EventsLoop(void *) +{ + ScopedLock s(events_loop_lock_); + + time_t tim = ::time(0); + debugLogA(">>>>> Entering %s[%d]", __FUNCTION__, tim); + + while (doEvents()) + { + if (!isOnline()) + break; + + if (WaitForSingleObjectEx(events_loop_event_, m_updateRate, true) != WAIT_TIMEOUT) // FIXME: correct timeout + break; + + debugLogA("***** %s[%d] refreshing...", __FUNCTION__, tim); + } + + ResetEvent(events_loop_event_); + ResetEvent(events_loop_lock_); + debugLogA("<<<<< Exiting %s[%d]", __FUNCTION__, tim); +} + +void MinecraftDynmapProto::SendMsgWorker(void *p) +{ + if (p == nullptr) + return; + + ScopedLock s(send_message_lock_); + + CMStringA data = ((std::string*)p)->c_str(); + delete (std::string*)p; + + data.TrimRight(); + + if (isOnline() && data.GetLength()) + doSendMessage(data.c_str()); +} diff --git a/protocols/MinecraftDynmap/src/constants.h b/protocols/MinecraftDynmap/src/constants.h index 42d1d2c33c..b8f454fe0f 100644 --- a/protocols/MinecraftDynmap/src/constants.h +++ b/protocols/MinecraftDynmap/src/constants.h @@ -1,46 +1,46 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#pragma once - -// Product management -#define MINECRAFTDYNMAP_NAME "Minecraft Dynmap" - -// Limits -#define MINECRAFTDYNMAP_TIMEOUTS_LIMIT 6 -// This is just guessed some wise limit -#define MINECRAFTDYNMAP_MESSAGE_LIMIT 256 -#define MINECRAFTDYNMAP_MESSAGE_LIMIT_TEXT "256" - -#define MINECRAFTDYNMAP_QUESTION_MIN_LENGTH 10 - -// Request types -#define MINECRAFTDYNMAP_REQUEST_HOME 100 // getting server homepage -#define MINECRAFTDYNMAP_REQUEST_CONFIGURATION 101 // getting server configuration -#define MINECRAFTDYNMAP_REQUEST_EVENTS 102 // receiving events -#define MINECRAFTDYNMAP_REQUEST_MESSAGE 103 // sending messages - -// DB settings -#define MINECRAFTDYNMAP_KEY_TIMEOUTS_LIMIT "TimeoutsLimit" // [HIDDEN] - -#define MINECRAFTDYNMAP_KEY_NAME "Nick" -#define MINECRAFTDYNMAP_KEY_SERVER "Server" +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#pragma once + +// Product management +#define MINECRAFTDYNMAP_NAME "Minecraft Dynmap" + +// Limits +#define MINECRAFTDYNMAP_TIMEOUTS_LIMIT 6 +// This is just guessed some wise limit +#define MINECRAFTDYNMAP_MESSAGE_LIMIT 256 +#define MINECRAFTDYNMAP_MESSAGE_LIMIT_TEXT "256" + +#define MINECRAFTDYNMAP_QUESTION_MIN_LENGTH 10 + +// Request types +#define MINECRAFTDYNMAP_REQUEST_HOME 100 // getting server homepage +#define MINECRAFTDYNMAP_REQUEST_CONFIGURATION 101 // getting server configuration +#define MINECRAFTDYNMAP_REQUEST_EVENTS 102 // receiving events +#define MINECRAFTDYNMAP_REQUEST_MESSAGE 103 // sending messages + +// DB settings +#define MINECRAFTDYNMAP_KEY_TIMEOUTS_LIMIT "TimeoutsLimit" // [HIDDEN] + +#define MINECRAFTDYNMAP_KEY_NAME "Nick" +#define MINECRAFTDYNMAP_KEY_SERVER "Server" diff --git a/protocols/MinecraftDynmap/src/dialogs.cpp b/protocols/MinecraftDynmap/src/dialogs.cpp index 54ea975fae..38707c6870 100644 --- a/protocols/MinecraftDynmap/src/dialogs.cpp +++ b/protocols/MinecraftDynmap/src/dialogs.cpp @@ -1,98 +1,98 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#include "stdafx.h" - -// Icons - -static IconItem iconList[] = -{ - { "proto", LPGEN("Protocol icon"), IDI_PROTO }, -}; - -static HANDLE hIconLibItem[_countof(iconList)]; - -void InitIcons(void) -{ - g_plugin.registerIcon("Protocols/MinecraftDynmap", iconList, "MinecraftDynmap"); -} - -// Dialogs - -static void LoadDBText(MinecraftDynmapProto* ppro, HWND hwnd, int idCtrl, const char* szSetting) -{ - ptrW tstr(db_get_wsa(0, ppro->m_szModuleName, szSetting)); - if (tstr) - SetDlgItemText(hwnd, idCtrl, tstr); -} - -static void StoreDBText(MinecraftDynmapProto* ppro, HWND hwnd, int idCtrl, const char* szSetting) -{ - wchar_t tstr[250 + 1]; - - GetDlgItemText(hwnd, idCtrl, tstr, _countof(tstr)); - if (tstr[0] != '\0') - db_set_ws(0, ppro->m_szModuleName, szSetting, tstr); - else - db_unset(0, ppro->m_szModuleName, szSetting); -} - - -INT_PTR CALLBACK MinecraftDynmapAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) -{ - MinecraftDynmapProto *proto; - - switch (message) { - case WM_INITDIALOG: - TranslateDialogDefault(hwnd); - - proto = reinterpret_cast(lparam); - SetWindowLongPtr(hwnd, GWLP_USERDATA, lparam); - - LoadDBText(proto, hwnd, IDC_SERVER, MINECRAFTDYNMAP_KEY_SERVER); - LoadDBText(proto, hwnd, IDC_NAME, MINECRAFTDYNMAP_KEY_NAME); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wparam)) { - case IDC_NAME: - if (HIWORD(wparam) != EN_CHANGE || (HWND)lparam != GetFocus()) - return TRUE; - - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - break; - } - break; - - case WM_NOTIFY: - if (reinterpret_cast(lparam)->code == PSN_APPLY) { - proto = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - - StoreDBText(proto, hwnd, IDC_SERVER, MINECRAFTDYNMAP_KEY_SERVER); - StoreDBText(proto, hwnd, IDC_NAME, MINECRAFTDYNMAP_KEY_NAME); - - return TRUE; - } - break; - } - return FALSE; -} +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "stdafx.h" + +// Icons + +static IconItem iconList[] = +{ + { "proto", LPGEN("Protocol icon"), IDI_PROTO }, +}; + +static HANDLE hIconLibItem[_countof(iconList)]; + +void InitIcons(void) +{ + g_plugin.registerIcon("Protocols/MinecraftDynmap", iconList, "MinecraftDynmap"); +} + +// Dialogs + +static void LoadDBText(MinecraftDynmapProto* ppro, HWND hwnd, int idCtrl, const char* szSetting) +{ + ptrW tstr(db_get_wsa(0, ppro->m_szModuleName, szSetting)); + if (tstr) + SetDlgItemText(hwnd, idCtrl, tstr); +} + +static void StoreDBText(MinecraftDynmapProto* ppro, HWND hwnd, int idCtrl, const char* szSetting) +{ + wchar_t tstr[250 + 1]; + + GetDlgItemText(hwnd, idCtrl, tstr, _countof(tstr)); + if (tstr[0] != '\0') + db_set_ws(0, ppro->m_szModuleName, szSetting, tstr); + else + db_unset(0, ppro->m_szModuleName, szSetting); +} + + +INT_PTR CALLBACK MinecraftDynmapAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + MinecraftDynmapProto *proto; + + switch (message) { + case WM_INITDIALOG: + TranslateDialogDefault(hwnd); + + proto = reinterpret_cast(lparam); + SetWindowLongPtr(hwnd, GWLP_USERDATA, lparam); + + LoadDBText(proto, hwnd, IDC_SERVER, MINECRAFTDYNMAP_KEY_SERVER); + LoadDBText(proto, hwnd, IDC_NAME, MINECRAFTDYNMAP_KEY_NAME); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDC_NAME: + if (HIWORD(wparam) != EN_CHANGE || (HWND)lparam != GetFocus()) + return TRUE; + + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + break; + + case WM_NOTIFY: + if (reinterpret_cast(lparam)->code == PSN_APPLY) { + proto = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + + StoreDBText(proto, hwnd, IDC_SERVER, MINECRAFTDYNMAP_KEY_SERVER); + StoreDBText(proto, hwnd, IDC_NAME, MINECRAFTDYNMAP_KEY_NAME); + + return TRUE; + } + break; + } + return FALSE; +} diff --git a/protocols/MinecraftDynmap/src/dialogs.h b/protocols/MinecraftDynmap/src/dialogs.h index 0af8617bae..f9d4586590 100644 --- a/protocols/MinecraftDynmap/src/dialogs.h +++ b/protocols/MinecraftDynmap/src/dialogs.h @@ -1,27 +1,27 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#pragma once - -void InitIcons(void); - -INT_PTR CALLBACK MinecraftDynmapAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#pragma once + +void InitIcons(void); + +INT_PTR CALLBACK MinecraftDynmapAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); diff --git a/protocols/MinecraftDynmap/src/main.cpp b/protocols/MinecraftDynmap/src/main.cpp index 5aa5c93460..a108fc6244 100644 --- a/protocols/MinecraftDynmap/src/main.cpp +++ b/protocols/MinecraftDynmap/src/main.cpp @@ -1,90 +1,90 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#include "stdafx.h" - -CMPlugin g_plugin; - -std::string g_strUserAgent; - -PLUGININFOEX pluginInfoEx = { - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), - __DESCRIPTION, - __AUTHOR, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - // {40DA5EBD-4F2D-4BEA-841C-EAB77BEE6F4F} - { 0x40da5ebd, 0x4f2d, 0x4bea, 0x84, 0x1c, 0xea, 0xb7, 0x7b, 0xee, 0x6f, 0x4f } -}; - -CMPlugin::CMPlugin() : - ACCPROTOPLUGIN("MinecraftDynmap", pluginInfoEx) -{ - SetUniqueId("Nick"); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Interface information - -extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST}; - -///////////////////////////////////////////////////////////////////////////////////////// -// Load - -static HANDLE g_hEvents[1]; - -int CMPlugin::Load() -{ - InitIcons(); - - // Init native User-Agent - { - MFileVersion w; - Miranda_GetFileVersion(&w); - std::stringstream agent; - agent << "Miranda NG/" << w[0] << "." << w[1] << "." << w[2] << "." << w[3]; - #ifdef _WIN64 - agent << " Minecraft Dynmap Protocol x64/"; - #else - agent << " Minecraft Dynmap Protocol/"; - #endif - agent << __VERSION_STRING_DOTS; - g_strUserAgent = agent.str(); - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Unload - -int CMPlugin::Unload() -{ - for (size_t i=0; i < _countof(g_hEvents); i++) - UnhookEvent(g_hEvents[i]); - - return 0; -} - +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "stdafx.h" + +CMPlugin g_plugin; + +std::string g_strUserAgent; + +PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {40DA5EBD-4F2D-4BEA-841C-EAB77BEE6F4F} + { 0x40da5ebd, 0x4f2d, 0x4bea, 0x84, 0x1c, 0xea, 0xb7, 0x7b, 0xee, 0x6f, 0x4f } +}; + +CMPlugin::CMPlugin() : + ACCPROTOPLUGIN("MinecraftDynmap", pluginInfoEx) +{ + SetUniqueId("Nick"); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Interface information + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST}; + +///////////////////////////////////////////////////////////////////////////////////////// +// Load + +static HANDLE g_hEvents[1]; + +int CMPlugin::Load() +{ + InitIcons(); + + // Init native User-Agent + { + MFileVersion w; + Miranda_GetFileVersion(&w); + std::stringstream agent; + agent << "Miranda NG/" << w[0] << "." << w[1] << "." << w[2] << "." << w[3]; + #ifdef _WIN64 + agent << " Minecraft Dynmap Protocol x64/"; + #else + agent << " Minecraft Dynmap Protocol/"; + #endif + agent << __VERSION_STRING_DOTS; + g_strUserAgent = agent.str(); + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Unload + +int CMPlugin::Unload() +{ + for (size_t i=0; i < _countof(g_hEvents); i++) + UnhookEvent(g_hEvents[i]); + + return 0; +} + diff --git a/protocols/MinecraftDynmap/src/proto.cpp b/protocols/MinecraftDynmap/src/proto.cpp index e787b831da..47c05d5105 100644 --- a/protocols/MinecraftDynmap/src/proto.cpp +++ b/protocols/MinecraftDynmap/src/proto.cpp @@ -1,180 +1,180 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#include "stdafx.h" - -MinecraftDynmapProto::MinecraftDynmapProto(const char* proto_name, const wchar_t* username) : - PROTO(proto_name, username), m_interval(0), hConnection(nullptr), hEventsConnection(nullptr), - m_updateRate(5000), m_nick("") -{ - this->signon_lock_ = CreateMutex(nullptr, FALSE, nullptr); - this->send_message_lock_ = CreateMutex(nullptr, FALSE, nullptr); - this->connection_lock_ = CreateMutex(nullptr, FALSE, nullptr); - this->events_loop_lock_ = CreateMutex(nullptr, FALSE, nullptr); - this->events_loop_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); - - // Group chats - CreateProtoService(PS_JOINCHAT, &MinecraftDynmapProto::OnJoinChat); - CreateProtoService(PS_LEAVECHAT, &MinecraftDynmapProto::OnLeaveChat); - - CreateProtoService(PS_CREATEACCMGRUI, &MinecraftDynmapProto::SvcCreateAccMgrUI); - - HookProtoEvent(ME_GC_EVENT, &MinecraftDynmapProto::OnChatEvent); - - // Create standard network connection - NETLIBUSER nlu = {}; - nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE; - nlu.szSettingsModule = m_szModuleName; - nlu.szDescriptiveName.w = m_tszUserName; - m_hNetlibUser = Netlib_RegisterUser(&nlu); - if (m_hNetlibUser == nullptr) { - wchar_t error[200]; - mir_snwprintf(error, TranslateT("Unable to initialize Netlib for %s."), m_tszUserName); - MessageBox(nullptr, error, L"Miranda NG", MB_OK | MB_ICONERROR); - } - - // Register group chat - GCREGISTER gcr = {}; - gcr.pszModule = m_szModuleName; - gcr.ptszDispName = m_tszUserName; - gcr.iMaxText = MINECRAFTDYNMAP_MESSAGE_LIMIT; - Chat_Register(&gcr); - - // Client instantiation - this->error_count_ = 0; - this->chatHandle_ = nullptr; - this->szRoomName = mir_utf8encodeW(username); -} - -MinecraftDynmapProto::~MinecraftDynmapProto() -{ - Netlib_CloseHandle(m_hNetlibUser); - - WaitForSingleObject(this->signon_lock_, IGNORE); - WaitForSingleObject(this->send_message_lock_, IGNORE); - WaitForSingleObject(this->connection_lock_, IGNORE); - WaitForSingleObject(this->events_loop_lock_, IGNORE); - - CloseHandle(this->signon_lock_); - CloseHandle(this->send_message_lock_); - CloseHandle(this->connection_lock_); - CloseHandle(this->events_loop_lock_); - CloseHandle(this->events_loop_event_); -} - -////////////////////////////////////////////////////////////////////////////// - -INT_PTR MinecraftDynmapProto::GetCaps(int type, MCONTACT) -{ - switch(type) { - case PFLAGNUM_1: - return PF1_CHAT; - case PFLAGNUM_2: - return PF2_ONLINE; - case PFLAG_MAXLENOFMESSAGE: - return MINECRAFTDYNMAP_MESSAGE_LIMIT; - case PFLAG_UNIQUEIDTEXT: - return (INT_PTR) TranslateT("Visible name"); - } - return 0; -} - -////////////////////////////////////////////////////////////////////////////// - -int MinecraftDynmapProto::SetStatus(int new_status) -{ - // Routing not supported statuses - switch (new_status) { - case ID_STATUS_OFFLINE: - case ID_STATUS_CONNECTING: - new_status = ID_STATUS_OFFLINE; - break; - default: - new_status = ID_STATUS_ONLINE; - break; - } - - m_iDesiredStatus = new_status; - - if (new_status == m_iStatus) { - return 0; - } - - if (m_iStatus == ID_STATUS_CONNECTING && new_status != ID_STATUS_OFFLINE) { - return 0; - } - - if (new_status == ID_STATUS_OFFLINE) { - ForkThread(&MinecraftDynmapProto::SignOffWorker, this); - } else { - ForkThread(&MinecraftDynmapProto::SignOnWorker, this); - } - return 0; -} - -////////////////////////////////////////////////////////////////////////////// -// EVENTS - -INT_PTR MinecraftDynmapProto::SvcCreateAccMgrUI(WPARAM, LPARAM lParam) -{ - return (INT_PTR)CreateDialogParam(g_plugin.getInst(),MAKEINTRESOURCE(IDD_MinecraftDynmapACCOUNT), (HWND)lParam, MinecraftDynmapAccountProc, (LPARAM)this); -} - -void MinecraftDynmapProto::OnShutdown() -{ - SetStatus(ID_STATUS_OFFLINE); -} - -void MinecraftDynmapProto::OnContactDeleted(MCONTACT) -{ - OnLeaveChat(NULL, NULL); -} - -////////////////////////////////////////////////////////////////////////////// -// HELPERS - -bool MinecraftDynmapProto::handleEntry(const std::string &method) -{ - debugLogA(" >> Entering %s()", method.c_str()); - return true; -} - -bool MinecraftDynmapProto::handleSuccess(const std::string &method) -{ - debugLogA(" << Quitting %s()", method.c_str()); - reset_error(); - return true; -} - -bool MinecraftDynmapProto::handleError(const std::string &method, const std::string &error, bool force_disconnect) -{ - increment_error(); - debugLogA("!!!!! Quitting %s() with error: %s", method.c_str(), !error.empty() ? error.c_str() : "Something went wrong"); - - if (!force_disconnect && error_count_ <= (UINT)db_get_b(0, m_szModuleName, MINECRAFTDYNMAP_KEY_TIMEOUTS_LIMIT, MINECRAFTDYNMAP_TIMEOUTS_LIMIT)) { - return true; - } - - reset_error(); - SetStatus(ID_STATUS_OFFLINE); - return false; -} +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "stdafx.h" + +MinecraftDynmapProto::MinecraftDynmapProto(const char* proto_name, const wchar_t* username) : + PROTO(proto_name, username), m_interval(0), hConnection(nullptr), hEventsConnection(nullptr), + m_updateRate(5000), m_nick("") +{ + this->signon_lock_ = CreateMutex(nullptr, FALSE, nullptr); + this->send_message_lock_ = CreateMutex(nullptr, FALSE, nullptr); + this->connection_lock_ = CreateMutex(nullptr, FALSE, nullptr); + this->events_loop_lock_ = CreateMutex(nullptr, FALSE, nullptr); + this->events_loop_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + // Group chats + CreateProtoService(PS_JOINCHAT, &MinecraftDynmapProto::OnJoinChat); + CreateProtoService(PS_LEAVECHAT, &MinecraftDynmapProto::OnLeaveChat); + + CreateProtoService(PS_CREATEACCMGRUI, &MinecraftDynmapProto::SvcCreateAccMgrUI); + + HookProtoEvent(ME_GC_EVENT, &MinecraftDynmapProto::OnChatEvent); + + // Create standard network connection + NETLIBUSER nlu = {}; + nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE; + nlu.szSettingsModule = m_szModuleName; + nlu.szDescriptiveName.w = m_tszUserName; + m_hNetlibUser = Netlib_RegisterUser(&nlu); + if (m_hNetlibUser == nullptr) { + wchar_t error[200]; + mir_snwprintf(error, TranslateT("Unable to initialize Netlib for %s."), m_tszUserName); + MessageBox(nullptr, error, L"Miranda NG", MB_OK | MB_ICONERROR); + } + + // Register group chat + GCREGISTER gcr = {}; + gcr.pszModule = m_szModuleName; + gcr.ptszDispName = m_tszUserName; + gcr.iMaxText = MINECRAFTDYNMAP_MESSAGE_LIMIT; + Chat_Register(&gcr); + + // Client instantiation + this->error_count_ = 0; + this->chatHandle_ = nullptr; + this->szRoomName = mir_utf8encodeW(username); +} + +MinecraftDynmapProto::~MinecraftDynmapProto() +{ + Netlib_CloseHandle(m_hNetlibUser); + + WaitForSingleObject(this->signon_lock_, IGNORE); + WaitForSingleObject(this->send_message_lock_, IGNORE); + WaitForSingleObject(this->connection_lock_, IGNORE); + WaitForSingleObject(this->events_loop_lock_, IGNORE); + + CloseHandle(this->signon_lock_); + CloseHandle(this->send_message_lock_); + CloseHandle(this->connection_lock_); + CloseHandle(this->events_loop_lock_); + CloseHandle(this->events_loop_event_); +} + +////////////////////////////////////////////////////////////////////////////// + +INT_PTR MinecraftDynmapProto::GetCaps(int type, MCONTACT) +{ + switch(type) { + case PFLAGNUM_1: + return PF1_CHAT; + case PFLAGNUM_2: + return PF2_ONLINE; + case PFLAG_MAXLENOFMESSAGE: + return MINECRAFTDYNMAP_MESSAGE_LIMIT; + case PFLAG_UNIQUEIDTEXT: + return (INT_PTR) TranslateT("Visible name"); + } + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +int MinecraftDynmapProto::SetStatus(int new_status) +{ + // Routing not supported statuses + switch (new_status) { + case ID_STATUS_OFFLINE: + case ID_STATUS_CONNECTING: + new_status = ID_STATUS_OFFLINE; + break; + default: + new_status = ID_STATUS_ONLINE; + break; + } + + m_iDesiredStatus = new_status; + + if (new_status == m_iStatus) { + return 0; + } + + if (m_iStatus == ID_STATUS_CONNECTING && new_status != ID_STATUS_OFFLINE) { + return 0; + } + + if (new_status == ID_STATUS_OFFLINE) { + ForkThread(&MinecraftDynmapProto::SignOffWorker, this); + } else { + ForkThread(&MinecraftDynmapProto::SignOnWorker, this); + } + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +// EVENTS + +INT_PTR MinecraftDynmapProto::SvcCreateAccMgrUI(WPARAM, LPARAM lParam) +{ + return (INT_PTR)CreateDialogParam(g_plugin.getInst(),MAKEINTRESOURCE(IDD_MinecraftDynmapACCOUNT), (HWND)lParam, MinecraftDynmapAccountProc, (LPARAM)this); +} + +void MinecraftDynmapProto::OnShutdown() +{ + SetStatus(ID_STATUS_OFFLINE); +} + +void MinecraftDynmapProto::OnContactDeleted(MCONTACT) +{ + OnLeaveChat(NULL, NULL); +} + +////////////////////////////////////////////////////////////////////////////// +// HELPERS + +bool MinecraftDynmapProto::handleEntry(const std::string &method) +{ + debugLogA(" >> Entering %s()", method.c_str()); + return true; +} + +bool MinecraftDynmapProto::handleSuccess(const std::string &method) +{ + debugLogA(" << Quitting %s()", method.c_str()); + reset_error(); + return true; +} + +bool MinecraftDynmapProto::handleError(const std::string &method, const std::string &error, bool force_disconnect) +{ + increment_error(); + debugLogA("!!!!! Quitting %s() with error: %s", method.c_str(), !error.empty() ? error.c_str() : "Something went wrong"); + + if (!force_disconnect && error_count_ <= (UINT)db_get_b(0, m_szModuleName, MINECRAFTDYNMAP_KEY_TIMEOUTS_LIMIT, MINECRAFTDYNMAP_TIMEOUTS_LIMIT)) { + return true; + } + + reset_error(); + SetStatus(ID_STATUS_OFFLINE); + return false; +} diff --git a/protocols/MinecraftDynmap/src/proto.h b/protocols/MinecraftDynmap/src/proto.h index b863b2547c..852edaef74 100644 --- a/protocols/MinecraftDynmap/src/proto.h +++ b/protocols/MinecraftDynmap/src/proto.h @@ -1,136 +1,136 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#pragma once - -class MinecraftDynmapProto : public PROTO -{ - ptrA szRoomName; - -public: - MinecraftDynmapProto(const char *proto_name, const wchar_t *username); - ~MinecraftDynmapProto(); - - inline const char* ModuleName() const { - return m_szModuleName; - } - - inline bool isOnline() { - return (m_iStatus != ID_STATUS_OFFLINE && m_iStatus != ID_STATUS_CONNECTING); - } - - inline bool isOffline() { - return (m_iStatus == ID_STATUS_OFFLINE); - } - - // PROTO_INTERFACE - INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override; - int SetStatus(int iNewStatus) override; - - void OnContactDeleted(MCONTACT) override; - void OnShutdown() override; - - // Services - INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM); - - // Chat handling - int __cdecl OnChatEvent(WPARAM,LPARAM); - INT_PTR __cdecl OnJoinChat(WPARAM,LPARAM); - INT_PTR __cdecl OnLeaveChat(WPARAM,LPARAM); - - // Loops - void __cdecl EventsLoop(void*); - - // Worker threads - void __cdecl SignOnWorker(void*); - void __cdecl SignOffWorker(void*); - void __cdecl SendMsgWorker(void*); - - // Chat handling - void UpdateChat(const char *name, const char *message, const time_t timestamp = time(0), bool addtochat = true); - void AddChatContact(const char *nick); - void DeleteChatContact(const char *name); - void SetChatStatus(int); - void ClearChat(); - void SetTopic(const char *topic); - MCONTACT GetChatHandle(); - - // Locks - HANDLE signon_lock_; - HANDLE connection_lock_; - HANDLE send_message_lock_; - HANDLE events_loop_lock_; - - HANDLE events_loop_event_; - - // Handles - HNETLIBCONN hConnection; - HNETLIBCONN hEventsConnection; - HANDLE chatHandle_; - - // Data storage - void store_headers(http::response *resp, NETLIBHTTPHEADER *headers, int headers_count); - - std::string get_server(bool not_last = false); - std::string get_language(); - - // Connection handling - unsigned int error_count_; - - // Helpers - bool handleEntry(const std::string &method); - bool handleSuccess(const std::string &method); - bool handleError(const std::string &method, const std::string &error = "", bool force_disconnect = false); - - void __inline increment_error() { error_count_++; } - void __inline decrement_error() { if (error_count_ > 0) error_count_--; } - void __inline reset_error() { error_count_ = 0; } - - // HTTP communication - http::response sendRequest(const int request_type, std::string *post_data = nullptr, std::string *get_data = nullptr); - std::string chooseAction(int, std::string *get_data = nullptr); - NETLIBHTTPHEADER *get_request_headers(int request_type, int *headers_count); - - // Requests and processing - bool doSignOn(); - bool doEvents(); - bool doSendMessage(const std::string &message_text); - - std::string doGetPage(int); - - // Configuration - std::string m_nick; - std::string m_cookie; - std::string m_server; - std::string m_title; - std::string m_timestamp; - int m_interval; - int m_updateRate; -}; - -struct CMPlugin : public ACCPROTOPLUGIN -{ - CMPlugin(); - - int Load() override; - int Unload() override; -}; +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#pragma once + +class MinecraftDynmapProto : public PROTO +{ + ptrA szRoomName; + +public: + MinecraftDynmapProto(const char *proto_name, const wchar_t *username); + ~MinecraftDynmapProto(); + + inline const char* ModuleName() const { + return m_szModuleName; + } + + inline bool isOnline() { + return (m_iStatus != ID_STATUS_OFFLINE && m_iStatus != ID_STATUS_CONNECTING); + } + + inline bool isOffline() { + return (m_iStatus == ID_STATUS_OFFLINE); + } + + // PROTO_INTERFACE + INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override; + int SetStatus(int iNewStatus) override; + + void OnContactDeleted(MCONTACT) override; + void OnShutdown() override; + + // Services + INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM); + + // Chat handling + int __cdecl OnChatEvent(WPARAM,LPARAM); + INT_PTR __cdecl OnJoinChat(WPARAM,LPARAM); + INT_PTR __cdecl OnLeaveChat(WPARAM,LPARAM); + + // Loops + void __cdecl EventsLoop(void*); + + // Worker threads + void __cdecl SignOnWorker(void*); + void __cdecl SignOffWorker(void*); + void __cdecl SendMsgWorker(void*); + + // Chat handling + void UpdateChat(const char *name, const char *message, const time_t timestamp = time(0), bool addtochat = true); + void AddChatContact(const char *nick); + void DeleteChatContact(const char *name); + void SetChatStatus(int); + void ClearChat(); + void SetTopic(const char *topic); + MCONTACT GetChatHandle(); + + // Locks + HANDLE signon_lock_; + HANDLE connection_lock_; + HANDLE send_message_lock_; + HANDLE events_loop_lock_; + + HANDLE events_loop_event_; + + // Handles + HNETLIBCONN hConnection; + HNETLIBCONN hEventsConnection; + HANDLE chatHandle_; + + // Data storage + void store_headers(http::response *resp, NETLIBHTTPHEADER *headers, int headers_count); + + std::string get_server(bool not_last = false); + std::string get_language(); + + // Connection handling + unsigned int error_count_; + + // Helpers + bool handleEntry(const std::string &method); + bool handleSuccess(const std::string &method); + bool handleError(const std::string &method, const std::string &error = "", bool force_disconnect = false); + + void __inline increment_error() { error_count_++; } + void __inline decrement_error() { if (error_count_ > 0) error_count_--; } + void __inline reset_error() { error_count_ = 0; } + + // HTTP communication + http::response sendRequest(const int request_type, std::string *post_data = nullptr, std::string *get_data = nullptr); + std::string chooseAction(int, std::string *get_data = nullptr); + NETLIBHTTPHEADER *get_request_headers(int request_type, int *headers_count); + + // Requests and processing + bool doSignOn(); + bool doEvents(); + bool doSendMessage(const std::string &message_text); + + std::string doGetPage(int); + + // Configuration + std::string m_nick; + std::string m_cookie; + std::string m_server; + std::string m_title; + std::string m_timestamp; + int m_interval; + int m_updateRate; +}; + +struct CMPlugin : public ACCPROTOPLUGIN +{ + CMPlugin(); + + int Load() override; + int Unload() override; +}; diff --git a/protocols/MinecraftDynmap/src/stdafx.cxx b/protocols/MinecraftDynmap/src/stdafx.cxx index 1ab0efee94..ebbde0ade1 100644 --- a/protocols/MinecraftDynmap/src/stdafx.cxx +++ b/protocols/MinecraftDynmap/src/stdafx.cxx @@ -1,18 +1,18 @@ -/* -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - +/* +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + #include "stdafx.h" \ No newline at end of file diff --git a/protocols/MinecraftDynmap/src/stdafx.h b/protocols/MinecraftDynmap/src/stdafx.h index 929267ae60..f5cc740bca 100644 --- a/protocols/MinecraftDynmap/src/stdafx.h +++ b/protocols/MinecraftDynmap/src/stdafx.h @@ -1,70 +1,70 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#pragma once - -#pragma warning(disable:4996) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "version.h" - -class MinecraftDynmapProto; - -#include "utils.h" -#include "proto.h" -#include "constants.h" -#include "dialogs.h" -#include "resource.h" - -extern std::string g_strUserAgent; +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#pragma once + +#pragma warning(disable:4996) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "version.h" + +class MinecraftDynmapProto; + +#include "utils.h" +#include "proto.h" +#include "constants.h" +#include "dialogs.h" +#include "resource.h" + +extern std::string g_strUserAgent; diff --git a/protocols/MinecraftDynmap/src/utils.h b/protocols/MinecraftDynmap/src/utils.h index e4f3d3ff37..c42fb86d9e 100644 --- a/protocols/MinecraftDynmap/src/utils.h +++ b/protocols/MinecraftDynmap/src/utils.h @@ -1,63 +1,63 @@ -/* - -Minecraft Dynmap plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2015-17 Robert Pösel, 2017-22 Miranda NG team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#pragma once - -// DB macros -#define getU8String(setting, dest) db_get_utf(NULL, m_szModuleName, setting, dest) -#define setU8String(setting, value) db_set_utf(NULL, m_szModuleName, setting, value) - -// HTTP constants and object -#define HTTP_CODE_FAKE_DISCONNECTED 0 -#define HTTP_CODE_FAKE_ERROR 1 - -namespace http -{ - struct response - { - response() : code(0) {} - int code; - std::map< std::string, std::string > headers; - std::string data; - }; -} - -class ScopedLock -{ -public: - ScopedLock(HANDLE h) : handle_(h) - { - WaitForSingleObject(handle_,INFINITE); - } - ~ScopedLock() - { - if (handle_) - ReleaseMutex(handle_); - } - void Unlock() - { - ReleaseMutex(handle_); - handle_ = nullptr; - } -private: - HANDLE handle_; -}; +/* + +Minecraft Dynmap plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2015-17 Robert Pösel, 2017-23 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#pragma once + +// DB macros +#define getU8String(setting, dest) db_get_utf(NULL, m_szModuleName, setting, dest) +#define setU8String(setting, value) db_set_utf(NULL, m_szModuleName, setting, value) + +// HTTP constants and object +#define HTTP_CODE_FAKE_DISCONNECTED 0 +#define HTTP_CODE_FAKE_ERROR 1 + +namespace http +{ + struct response + { + response() : code(0) {} + int code; + std::map< std::string, std::string > headers; + std::string data; + }; +} + +class ScopedLock +{ +public: + ScopedLock(HANDLE h) : handle_(h) + { + WaitForSingleObject(handle_,INFINITE); + } + ~ScopedLock() + { + if (handle_) + ReleaseMutex(handle_); + } + void Unlock() + { + ReleaseMutex(handle_); + handle_ = nullptr; + } +private: + HANDLE handle_; +}; diff --git a/protocols/MinecraftDynmap/src/version.h b/protocols/MinecraftDynmap/src/version.h index fa021b8cae..1e71a749da 100644 --- a/protocols/MinecraftDynmap/src/version.h +++ b/protocols/MinecraftDynmap/src/version.h @@ -10,4 +10,4 @@ #define __DESCRIPTION "Minecraft Dynmap support for Miranda NG." #define __AUTHOR "Robert Pösel" #define __AUTHORWEB "https://miranda-ng.org/p/MinecraftDynmap" -#define __COPYRIGHT "© 2015-17 Robert Pösel, 2017-22 Miranda NG team" +#define __COPYRIGHT "© 2015-17 Robert Pösel, 2017-23 Miranda NG team" -- cgit v1.2.3