diff options
author | dartraiden <wowemuh@gmail.com> | 2023-01-02 21:10:29 +0300 |
---|---|---|
committer | dartraiden <wowemuh@gmail.com> | 2023-01-02 21:10:29 +0300 |
commit | 1979fd80424d16b2e489f9b57d01d9c7811d25a2 (patch) | |
tree | 960d42c5fe4a51f0fe2850bea91256e226bce221 /protocols/MinecraftDynmap/src | |
parent | adfbbb217d4f4a05acf198755f219a5223d31c27 (diff) |
Update copyrights
Diffstat (limited to 'protocols/MinecraftDynmap/src')
-rw-r--r-- | protocols/MinecraftDynmap/src/chat.cpp | 368 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/communication.cpp | 884 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/constants.h | 92 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/dialogs.cpp | 196 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/dialogs.h | 54 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/main.cpp | 180 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/proto.cpp | 360 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/proto.h | 272 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/stdafx.cxx | 34 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/stdafx.h | 140 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/utils.h | 126 | ||||
-rw-r--r-- | protocols/MinecraftDynmap/src/version.h | 2 |
12 files changed, 1354 insertions, 1354 deletions
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 <http://www.gnu.org/licenses/>. -*/ - -#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<GCHOOK*>(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 <http://www.gnu.org/licenses/>.
+*/
+
+#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<GCHOOK*>(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 <http://www.gnu.org/licenses/>. -*/ - -#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 <http://www.gnu.org/licenses/>.
+*/
+
+#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 <http://www.gnu.org/licenses/>. - -*/ - -#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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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 <http://www.gnu.org/licenses/>. - -*/ - -#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<MinecraftDynmapProto*>(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<NMHDR*>(lparam)->code == PSN_APPLY) { - proto = reinterpret_cast<MinecraftDynmapProto*>(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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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<MinecraftDynmapProto*>(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<NMHDR*>(lparam)->code == PSN_APPLY) {
+ proto = reinterpret_cast<MinecraftDynmapProto*>(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 <http://www.gnu.org/licenses/>. - -*/ - -#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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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 <http://www.gnu.org/licenses/>. - -*/ - -#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<MinecraftDynmapProto>("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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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<MinecraftDynmapProto>("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 <http://www.gnu.org/licenses/>. - -*/ - -#include "stdafx.h" - -MinecraftDynmapProto::MinecraftDynmapProto(const char* proto_name, const wchar_t* username) : - PROTO<MinecraftDynmapProto>(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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "stdafx.h"
+
+MinecraftDynmapProto::MinecraftDynmapProto(const char* proto_name, const wchar_t* username) :
+ PROTO<MinecraftDynmapProto>(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 <http://www.gnu.org/licenses/>. - -*/ - -#pragma once - -class MinecraftDynmapProto : public PROTO<MinecraftDynmapProto> -{ - 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<MinecraftDynmapProto> -{ - 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#pragma once
+
+class MinecraftDynmapProto : public PROTO<MinecraftDynmapProto>
+{
+ 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<MinecraftDynmapProto>
+{
+ 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 <http://www.gnu.org/licenses/>. -*/ - +/*
+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 <http://www.gnu.org/licenses/>.
+*/
+
#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 <http://www.gnu.org/licenses/>. - -*/ - -#pragma once - -#pragma warning(disable:4996) - -#include <string> -#include <cstring> -#include <sstream> -#include <fstream> -#include <map> -#include <stdarg.h> -#include <time.h> -#include <assert.h> -#include <io.h> - -#include <windows.h> -#include <commctrl.h> - -#include <newpluginapi.h> -#include <m_system.h> -#include <m_chat_int.h> -#include <m_clistint.h> -#include <m_langpack.h> -#include <m_netlib.h> -#include <m_options.h> -#include <m_popup.h> -#include <m_protocols.h> -#include <m_protosvc.h> -#include <m_protoint.h> -#include <m_skin.h> -#include <statusmodes.h> -#include <m_icolib.h> -#include <m_utils.h> -#include <m_hotkeys.h> -#include <m_message.h> -#include <m_json.h> -#include <m_http.h> - -#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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#pragma once
+
+#pragma warning(disable:4996)
+
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <fstream>
+#include <map>
+#include <stdarg.h>
+#include <time.h>
+#include <assert.h>
+#include <io.h>
+
+#include <windows.h>
+#include <commctrl.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_chat_int.h>
+#include <m_clistint.h>
+#include <m_langpack.h>
+#include <m_netlib.h>
+#include <m_options.h>
+#include <m_popup.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_protoint.h>
+#include <m_skin.h>
+#include <statusmodes.h>
+#include <m_icolib.h>
+#include <m_utils.h>
+#include <m_hotkeys.h>
+#include <m_message.h>
+#include <m_json.h>
+#include <m_http.h>
+
+#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 <http://www.gnu.org/licenses/>. - -*/ - -#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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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"
|