From 1979fd80424d16b2e489f9b57d01d9c7811d25a2 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Mon, 2 Jan 2023 21:10:29 +0300 Subject: Update copyrights --- protocols/SkypeWeb/src/main.cpp | 2 +- protocols/SkypeWeb/src/request_queue.cpp | 2 +- protocols/SkypeWeb/src/requests/avatars.h | 2 +- protocols/SkypeWeb/src/requests/capabilities.h | 2 +- protocols/SkypeWeb/src/requests/chatrooms.h | 2 +- protocols/SkypeWeb/src/requests/contacts.h | 2 +- protocols/SkypeWeb/src/requests/endpoint.h | 2 +- protocols/SkypeWeb/src/requests/history.h | 2 +- protocols/SkypeWeb/src/requests/login.h | 2 +- protocols/SkypeWeb/src/requests/messages.h | 2 +- protocols/SkypeWeb/src/requests/oauth.h | 148 +-- protocols/SkypeWeb/src/requests/poll.h | 2 +- protocols/SkypeWeb/src/requests/profile.h | 2 +- protocols/SkypeWeb/src/requests/search.h | 2 +- protocols/SkypeWeb/src/requests/status.h | 2 +- protocols/SkypeWeb/src/requests/subscriptions.h | 2 +- protocols/SkypeWeb/src/skype_avatars.cpp | 2 +- protocols/SkypeWeb/src/skype_chatrooms.cpp | 2 +- protocols/SkypeWeb/src/skype_contacts.cpp | 2 +- protocols/SkypeWeb/src/skype_db.cpp | 238 ++-- protocols/SkypeWeb/src/skype_db.h | 2 +- protocols/SkypeWeb/src/skype_events.cpp | 2 +- protocols/SkypeWeb/src/skype_history_sync.cpp | 2 +- protocols/SkypeWeb/src/skype_icons.cpp | 2 +- protocols/SkypeWeb/src/skype_login.cpp | 2 +- protocols/SkypeWeb/src/skype_menus.cpp | 2 +- protocols/SkypeWeb/src/skype_menus.h | 2 +- protocols/SkypeWeb/src/skype_messages.cpp | 2 +- protocols/SkypeWeb/src/skype_oauth.cpp | 330 +++--- protocols/SkypeWeb/src/skype_options.cpp | 2 +- protocols/SkypeWeb/src/skype_polling.cpp | 2 +- protocols/SkypeWeb/src/skype_profile.cpp | 2 +- protocols/SkypeWeb/src/skype_proto.cpp | 686 ++++++------ protocols/SkypeWeb/src/skype_proto.h | 2 +- protocols/SkypeWeb/src/skype_search.cpp | 2 +- protocols/SkypeWeb/src/skype_trouter.cpp | 2 +- protocols/SkypeWeb/src/skype_utils.cpp | 1358 +++++++++++------------ protocols/SkypeWeb/src/skype_utils.h | 2 +- protocols/SkypeWeb/src/stdafx.cxx | 2 +- protocols/SkypeWeb/src/stdafx.h | 2 +- protocols/SkypeWeb/src/version.h | 2 +- 41 files changed, 1416 insertions(+), 1416 deletions(-) (limited to 'protocols/SkypeWeb') diff --git a/protocols/SkypeWeb/src/main.cpp b/protocols/SkypeWeb/src/main.cpp index 3e3c36210b..b1e3ddfb5b 100644 --- a/protocols/SkypeWeb/src/main.cpp +++ b/protocols/SkypeWeb/src/main.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/request_queue.cpp b/protocols/SkypeWeb/src/request_queue.cpp index c7ab39d344..d6240e7cee 100644 --- a/protocols/SkypeWeb/src/request_queue.cpp +++ b/protocols/SkypeWeb/src/request_queue.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/avatars.h b/protocols/SkypeWeb/src/requests/avatars.h index fd015e1bed..cdf5ac7b6e 100644 --- a/protocols/SkypeWeb/src/requests/avatars.h +++ b/protocols/SkypeWeb/src/requests/avatars.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/capabilities.h b/protocols/SkypeWeb/src/requests/capabilities.h index 17b823a575..3170ca6d66 100644 --- a/protocols/SkypeWeb/src/requests/capabilities.h +++ b/protocols/SkypeWeb/src/requests/capabilities.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/chatrooms.h b/protocols/SkypeWeb/src/requests/chatrooms.h index 2e12729862..2fc4e435ff 100644 --- a/protocols/SkypeWeb/src/requests/chatrooms.h +++ b/protocols/SkypeWeb/src/requests/chatrooms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/contacts.h b/protocols/SkypeWeb/src/requests/contacts.h index 4a62c67441..f9a3c13fa0 100644 --- a/protocols/SkypeWeb/src/requests/contacts.h +++ b/protocols/SkypeWeb/src/requests/contacts.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/endpoint.h b/protocols/SkypeWeb/src/requests/endpoint.h index 8c351144c8..c0abe99a43 100644 --- a/protocols/SkypeWeb/src/requests/endpoint.h +++ b/protocols/SkypeWeb/src/requests/endpoint.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/history.h b/protocols/SkypeWeb/src/requests/history.h index 75b7dc93d4..4438288479 100644 --- a/protocols/SkypeWeb/src/requests/history.h +++ b/protocols/SkypeWeb/src/requests/history.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/login.h b/protocols/SkypeWeb/src/requests/login.h index e06cb28d40..e0053745d4 100644 --- a/protocols/SkypeWeb/src/requests/login.h +++ b/protocols/SkypeWeb/src/requests/login.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/messages.h b/protocols/SkypeWeb/src/requests/messages.h index 4a71b79445..4e41e38dd4 100644 --- a/protocols/SkypeWeb/src/requests/messages.h +++ b/protocols/SkypeWeb/src/requests/messages.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/oauth.h b/protocols/SkypeWeb/src/requests/oauth.h index 5d26982a8d..cc9842a0d2 100644 --- a/protocols/SkypeWeb/src/requests/oauth.h +++ b/protocols/SkypeWeb/src/requests/oauth.h @@ -1,74 +1,74 @@ -/* -Copyright (c) 2015-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 . -*/ - -#ifndef _SKYPE_REQUEST_OAUTH_H_ -#define _SKYPE_REQUEST_OAUTH_H_ - -struct OAuthRequest : public AsyncHttpRequest -{ - OAuthRequest() : - AsyncHttpRequest(REQUEST_GET, HOST_OTHER, "https://login.live.com/login.srf", &CSkypeProto::OnOAuthStart) - { - flags |= NLHRF_REDIRECT; - - this << CHAR_PARAM("wa", "wsignin1.0") << CHAR_PARAM("wp", "MBI_SSL") - << CHAR_PARAM("wreply", "https://lw.skype.com/login/oauth/proxy?site_name=lw.skype.com") - << CHAR_PARAM("cobrandid", "90010"); - } - - OAuthRequest(const char *login, const char *password, const char *cookies, const char *ppft) : - AsyncHttpRequest(REQUEST_POST, HOST_OTHER, "https://login.live.com/ppsecure/post.srf", &CSkypeProto::OnOAuthConfirm) - { - this << CHAR_PARAM("wa", "wsignin1.0") << CHAR_PARAM("wp", "MBI_SSL") - << CHAR_PARAM("wreply", "https://lw.skype.com/login/oauth/proxy?site_name=lw.skype.com") - << CHAR_PARAM("cobrandid", "90010"); - m_szUrl.AppendFormat("?%s", m_szParam.c_str()); - m_szParam.Empty(); - - AddHeader("Cookie", cookies); - - if (auto *delim = strchr(login, ':')) - login = delim + 1; - - this << CHAR_PARAM("login", login) << CHAR_PARAM("passwd", password) << CHAR_PARAM("PPFT", ppft); - } - - OAuthRequest(const char *cookies, const char* ppft, const char* opid) : - AsyncHttpRequest(REQUEST_POST, HOST_OTHER, "https://login.live.com/ppsecure/post.srf", &CSkypeProto::OnOAuthAuthorize) - { - this << CHAR_PARAM("wa", "wsignin1.0") << CHAR_PARAM("wp", "MBI_SSL") - << CHAR_PARAM("wreply", "https://lw.skype.com/login/oauth/proxy?site_name=lw.skype.com") - << CHAR_PARAM("cobrandid", "90010") - << CHAR_PARAM("id", "293290") - << CHAR_PARAM("opid", opid); - - m_szUrl.AppendFormat("?%s", m_szParam.c_str()); - m_szParam.Empty(); - - AddHeader("Cookie", cookies); - - this << CHAR_PARAM("type", "28") << CHAR_PARAM("PPFT", ppft); - } - - OAuthRequest(const char *t) : - AsyncHttpRequest(REQUEST_POST, HOST_LOGIN, "/login/microsoft", &CSkypeProto::OnOAuthEnd) - { - this << CHAR_PARAM ("t", t) << CHAR_PARAM("site_name", "lw.skype.com") << INT_PARAM ("oauthPartner", 999); - } -}; - -#endif //_SKYPE_REQUEST_OAUTH_H_ +/* +Copyright (c) 2015-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 . +*/ + +#ifndef _SKYPE_REQUEST_OAUTH_H_ +#define _SKYPE_REQUEST_OAUTH_H_ + +struct OAuthRequest : public AsyncHttpRequest +{ + OAuthRequest() : + AsyncHttpRequest(REQUEST_GET, HOST_OTHER, "https://login.live.com/login.srf", &CSkypeProto::OnOAuthStart) + { + flags |= NLHRF_REDIRECT; + + this << CHAR_PARAM("wa", "wsignin1.0") << CHAR_PARAM("wp", "MBI_SSL") + << CHAR_PARAM("wreply", "https://lw.skype.com/login/oauth/proxy?site_name=lw.skype.com") + << CHAR_PARAM("cobrandid", "90010"); + } + + OAuthRequest(const char *login, const char *password, const char *cookies, const char *ppft) : + AsyncHttpRequest(REQUEST_POST, HOST_OTHER, "https://login.live.com/ppsecure/post.srf", &CSkypeProto::OnOAuthConfirm) + { + this << CHAR_PARAM("wa", "wsignin1.0") << CHAR_PARAM("wp", "MBI_SSL") + << CHAR_PARAM("wreply", "https://lw.skype.com/login/oauth/proxy?site_name=lw.skype.com") + << CHAR_PARAM("cobrandid", "90010"); + m_szUrl.AppendFormat("?%s", m_szParam.c_str()); + m_szParam.Empty(); + + AddHeader("Cookie", cookies); + + if (auto *delim = strchr(login, ':')) + login = delim + 1; + + this << CHAR_PARAM("login", login) << CHAR_PARAM("passwd", password) << CHAR_PARAM("PPFT", ppft); + } + + OAuthRequest(const char *cookies, const char* ppft, const char* opid) : + AsyncHttpRequest(REQUEST_POST, HOST_OTHER, "https://login.live.com/ppsecure/post.srf", &CSkypeProto::OnOAuthAuthorize) + { + this << CHAR_PARAM("wa", "wsignin1.0") << CHAR_PARAM("wp", "MBI_SSL") + << CHAR_PARAM("wreply", "https://lw.skype.com/login/oauth/proxy?site_name=lw.skype.com") + << CHAR_PARAM("cobrandid", "90010") + << CHAR_PARAM("id", "293290") + << CHAR_PARAM("opid", opid); + + m_szUrl.AppendFormat("?%s", m_szParam.c_str()); + m_szParam.Empty(); + + AddHeader("Cookie", cookies); + + this << CHAR_PARAM("type", "28") << CHAR_PARAM("PPFT", ppft); + } + + OAuthRequest(const char *t) : + AsyncHttpRequest(REQUEST_POST, HOST_LOGIN, "/login/microsoft", &CSkypeProto::OnOAuthEnd) + { + this << CHAR_PARAM ("t", t) << CHAR_PARAM("site_name", "lw.skype.com") << INT_PARAM ("oauthPartner", 999); + } +}; + +#endif //_SKYPE_REQUEST_OAUTH_H_ diff --git a/protocols/SkypeWeb/src/requests/poll.h b/protocols/SkypeWeb/src/requests/poll.h index ce4b32cb4c..4475ec041e 100644 --- a/protocols/SkypeWeb/src/requests/poll.h +++ b/protocols/SkypeWeb/src/requests/poll.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/profile.h b/protocols/SkypeWeb/src/requests/profile.h index 426087a63a..c255f9166b 100644 --- a/protocols/SkypeWeb/src/requests/profile.h +++ b/protocols/SkypeWeb/src/requests/profile.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/search.h b/protocols/SkypeWeb/src/requests/search.h index d47562ff9c..357ad470bc 100644 --- a/protocols/SkypeWeb/src/requests/search.h +++ b/protocols/SkypeWeb/src/requests/search.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/status.h b/protocols/SkypeWeb/src/requests/status.h index 58ebd23dcd..74e35960cd 100644 --- a/protocols/SkypeWeb/src/requests/status.h +++ b/protocols/SkypeWeb/src/requests/status.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/requests/subscriptions.h b/protocols/SkypeWeb/src/requests/subscriptions.h index b0f71046e8..b1ddc03a6e 100644 --- a/protocols/SkypeWeb/src/requests/subscriptions.h +++ b/protocols/SkypeWeb/src/requests/subscriptions.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_avatars.cpp b/protocols/SkypeWeb/src/skype_avatars.cpp index 934180e929..1ac07d6d33 100644 --- a/protocols/SkypeWeb/src/skype_avatars.cpp +++ b/protocols/SkypeWeb/src/skype_avatars.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_chatrooms.cpp b/protocols/SkypeWeb/src/skype_chatrooms.cpp index 3087321ea2..4f27b13c5c 100644 --- a/protocols/SkypeWeb/src/skype_chatrooms.cpp +++ b/protocols/SkypeWeb/src/skype_chatrooms.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_contacts.cpp b/protocols/SkypeWeb/src/skype_contacts.cpp index cd1a2a13a1..75827daaf6 100644 --- a/protocols/SkypeWeb/src/skype_contacts.cpp +++ b/protocols/SkypeWeb/src/skype_contacts.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_db.cpp b/protocols/SkypeWeb/src/skype_db.cpp index 3417b15c01..8d815088d1 100644 --- a/protocols/SkypeWeb/src/skype_db.cpp +++ b/protocols/SkypeWeb/src/skype_db.cpp @@ -1,119 +1,119 @@ -/* -Copyright (c) 2015-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 . -*/ - -#include "stdafx.h" - -struct { int type; char *name; uint32_t flags; } g_SkypeDBTypes[] = -{ - { SKYPE_DB_EVENT_TYPE_INCOMING_CALL, LPGEN("Incoming call"), DETF_NONOTIFY }, - { SKYPE_DB_EVENT_TYPE_EDITED_MESSAGE, LPGEN("Edited message"), 0 }, - { SKYPE_DB_EVENT_TYPE_ACTION, LPGEN("Action"), 0 }, - { SKYPE_DB_EVENT_TYPE_CALL_INFO, LPGEN("Call information"), 0 }, - { SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, LPGEN("File transfer information"), 0 }, - { SKYPE_DB_EVENT_TYPE_URIOBJ, LPGEN("URI object"), 0 }, - { SKYPE_DB_EVENT_TYPE_MOJI, LPGEN("Moji"), 0 }, - { SKYPE_DB_EVENT_TYPE_FILE, LPGEN("File"), 0 }, - { SKYPE_DB_EVENT_TYPE_UNKNOWN, LPGEN("Unknown event"), 0 }, -}; - -MEVENT CSkypeProto::GetMessageFromDb(const char *messageId) -{ - if (messageId == nullptr) - return NULL; - - return db_event_getById(m_szModuleName, messageId); -} - -MEVENT CSkypeProto::AddDbEvent(uint16_t type, MCONTACT hContact, uint32_t timestamp, uint32_t flags, const CMStringW &content, const CMStringA &msgId) -{ - if (MEVENT hDbEvent = GetMessageFromDb(msgId)) - return hDbEvent; - - T2Utf szMsg(content); - DBEVENTINFO dbei = {}; - dbei.szModule = m_szModuleName; - dbei.timestamp = timestamp; - dbei.eventType = type; - dbei.cbBlob = (uint32_t)mir_strlen(szMsg) + 1; - dbei.pBlob = (uint8_t *)szMsg; - dbei.flags = flags; - dbei.szId = msgId; - return db_event_add(hContact, &dbei); -} - -void CSkypeProto::EditEvent(MCONTACT hContact, MEVENT hEvent, const CMStringW &szContent, time_t edit_time) -{ - mir_cslock lck(m_AppendMessageLock); - - DB::EventInfo dbei; - dbei.cbBlob = -1; - if (db_event_get(hEvent, &dbei)) - return; - - JSONNode jMsg = JSONNode::parse((char*)dbei.pBlob); - if (jMsg) { - JSONNode &jEdits = jMsg["edits"]; - if (jEdits) { - for (auto &it : jEdits) - if (it["time"].as_int() == edit_time) - return; - - JSONNode jEdit; - jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent); - jEdits << jEdit; - } - } - else { - JSONNode jOriginalMsg; jOriginalMsg.set_name("original_message"); - jOriginalMsg << INT_PARAM("time", (long)dbei.timestamp) << CHAR_PARAM("text", (char *)dbei.pBlob); - - jMsg = JSONNode(); - jMsg << jOriginalMsg; - - JSONNode jEdit; - jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent); - - JSONNode jEdits(JSON_ARRAY); jEdits.set_name("edits"); - jEdits << jEdit; - jMsg << jEdits; - } - - std::string newMsg = jMsg.write().c_str(); - dbei.cbBlob = int(newMsg.size() + 1); - dbei.pBlob = (uint8_t*)newMsg.c_str(); - db_event_edit(hContact, hEvent, &dbei); -} - -void CSkypeProto::InitDBEvents() -{ - // custom event - DBEVENTTYPEDESCR dbEventType = {}; - dbEventType.module = m_szModuleName; - dbEventType.flags = DETF_HISTORY | DETF_MSGWINDOW; - dbEventType.iconService = MODULE "/GetEventIcon"; - dbEventType.textService = MODULE "/GetEventText"; - - for (auto &cur : g_SkypeDBTypes) { - dbEventType.eventType = cur.type; - dbEventType.descr = Translate(cur.name); - dbEventType.flags |= cur.flags; - - DbEvent_RegisterType(&dbEventType); - - dbEventType.flags &= (~cur.flags); - } -} +/* +Copyright (c) 2015-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" + +struct { int type; char *name; uint32_t flags; } g_SkypeDBTypes[] = +{ + { SKYPE_DB_EVENT_TYPE_INCOMING_CALL, LPGEN("Incoming call"), DETF_NONOTIFY }, + { SKYPE_DB_EVENT_TYPE_EDITED_MESSAGE, LPGEN("Edited message"), 0 }, + { SKYPE_DB_EVENT_TYPE_ACTION, LPGEN("Action"), 0 }, + { SKYPE_DB_EVENT_TYPE_CALL_INFO, LPGEN("Call information"), 0 }, + { SKYPE_DB_EVENT_TYPE_FILETRANSFER_INFO, LPGEN("File transfer information"), 0 }, + { SKYPE_DB_EVENT_TYPE_URIOBJ, LPGEN("URI object"), 0 }, + { SKYPE_DB_EVENT_TYPE_MOJI, LPGEN("Moji"), 0 }, + { SKYPE_DB_EVENT_TYPE_FILE, LPGEN("File"), 0 }, + { SKYPE_DB_EVENT_TYPE_UNKNOWN, LPGEN("Unknown event"), 0 }, +}; + +MEVENT CSkypeProto::GetMessageFromDb(const char *messageId) +{ + if (messageId == nullptr) + return NULL; + + return db_event_getById(m_szModuleName, messageId); +} + +MEVENT CSkypeProto::AddDbEvent(uint16_t type, MCONTACT hContact, uint32_t timestamp, uint32_t flags, const CMStringW &content, const CMStringA &msgId) +{ + if (MEVENT hDbEvent = GetMessageFromDb(msgId)) + return hDbEvent; + + T2Utf szMsg(content); + DBEVENTINFO dbei = {}; + dbei.szModule = m_szModuleName; + dbei.timestamp = timestamp; + dbei.eventType = type; + dbei.cbBlob = (uint32_t)mir_strlen(szMsg) + 1; + dbei.pBlob = (uint8_t *)szMsg; + dbei.flags = flags; + dbei.szId = msgId; + return db_event_add(hContact, &dbei); +} + +void CSkypeProto::EditEvent(MCONTACT hContact, MEVENT hEvent, const CMStringW &szContent, time_t edit_time) +{ + mir_cslock lck(m_AppendMessageLock); + + DB::EventInfo dbei; + dbei.cbBlob = -1; + if (db_event_get(hEvent, &dbei)) + return; + + JSONNode jMsg = JSONNode::parse((char*)dbei.pBlob); + if (jMsg) { + JSONNode &jEdits = jMsg["edits"]; + if (jEdits) { + for (auto &it : jEdits) + if (it["time"].as_int() == edit_time) + return; + + JSONNode jEdit; + jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent); + jEdits << jEdit; + } + } + else { + JSONNode jOriginalMsg; jOriginalMsg.set_name("original_message"); + jOriginalMsg << INT_PARAM("time", (long)dbei.timestamp) << CHAR_PARAM("text", (char *)dbei.pBlob); + + jMsg = JSONNode(); + jMsg << jOriginalMsg; + + JSONNode jEdit; + jEdit << INT_PARAM("time", (long)edit_time) << WCHAR_PARAM("text", szContent); + + JSONNode jEdits(JSON_ARRAY); jEdits.set_name("edits"); + jEdits << jEdit; + jMsg << jEdits; + } + + std::string newMsg = jMsg.write().c_str(); + dbei.cbBlob = int(newMsg.size() + 1); + dbei.pBlob = (uint8_t*)newMsg.c_str(); + db_event_edit(hContact, hEvent, &dbei); +} + +void CSkypeProto::InitDBEvents() +{ + // custom event + DBEVENTTYPEDESCR dbEventType = {}; + dbEventType.module = m_szModuleName; + dbEventType.flags = DETF_HISTORY | DETF_MSGWINDOW; + dbEventType.iconService = MODULE "/GetEventIcon"; + dbEventType.textService = MODULE "/GetEventText"; + + for (auto &cur : g_SkypeDBTypes) { + dbEventType.eventType = cur.type; + dbEventType.descr = Translate(cur.name); + dbEventType.flags |= cur.flags; + + DbEvent_RegisterType(&dbEventType); + + dbEventType.flags &= (~cur.flags); + } +} diff --git a/protocols/SkypeWeb/src/skype_db.h b/protocols/SkypeWeb/src/skype_db.h index 8a0d58a049..ad9a7e2ff7 100644 --- a/protocols/SkypeWeb/src/skype_db.h +++ b/protocols/SkypeWeb/src/skype_db.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_events.cpp b/protocols/SkypeWeb/src/skype_events.cpp index a2f13e8187..49a93a53a0 100644 --- a/protocols/SkypeWeb/src/skype_events.cpp +++ b/protocols/SkypeWeb/src/skype_events.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp index a034722bbd..ae72cdb920 100644 --- a/protocols/SkypeWeb/src/skype_history_sync.cpp +++ b/protocols/SkypeWeb/src/skype_history_sync.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_icons.cpp b/protocols/SkypeWeb/src/skype_icons.cpp index 8bd77f324a..15934a3d23 100644 --- a/protocols/SkypeWeb/src/skype_icons.cpp +++ b/protocols/SkypeWeb/src/skype_icons.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_login.cpp b/protocols/SkypeWeb/src/skype_login.cpp index d003c4ee71..94faff30d8 100644 --- a/protocols/SkypeWeb/src/skype_login.cpp +++ b/protocols/SkypeWeb/src/skype_login.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_menus.cpp b/protocols/SkypeWeb/src/skype_menus.cpp index 2d52b1a790..faf99da486 100644 --- a/protocols/SkypeWeb/src/skype_menus.cpp +++ b/protocols/SkypeWeb/src/skype_menus.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_menus.h b/protocols/SkypeWeb/src/skype_menus.h index 3e8c380d6f..b4e74aa6a3 100644 --- a/protocols/SkypeWeb/src/skype_menus.h +++ b/protocols/SkypeWeb/src/skype_menus.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index c6974a071c..01a0235caa 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_oauth.cpp b/protocols/SkypeWeb/src/skype_oauth.cpp index dee5e92387..0a1f8908d3 100644 --- a/protocols/SkypeWeb/src/skype_oauth.cpp +++ b/protocols/SkypeWeb/src/skype_oauth.cpp @@ -1,165 +1,165 @@ -/* -Copyright (c) 2015-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 . -*/ - -#include "stdafx.h" - -static std::string sub(const std::string &str, const char *start, const char *end) -{ - size_t i1 = str.find(start); - if (i1 == -1) - return ""; - - i1 += strlen(start); - size_t i2 = str.find(end, i1); - return (i2 == -1) ? "" : str.substr(i1, i2 - i1); -} - -void CSkypeProto::OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) -{ - if (response == nullptr || response->pData == nullptr) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - std::regex regex; - std::smatch match; - std::string content = response->pData; - - regex = ""; - - if (!std::regex_search(content, match, regex)) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - std::string PPFT = match[1]; - - std::map scookies; - regex = "^(.+?)=(.*?);"; - - for (int i = 0; i < response->headersCount; i++) { - if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) - continue; - - content = response->headers[i].szValue; - if (std::regex_search(content, match, regex)) - scookies[match[1]] = match[2]; - } - - ptrA login(getStringA(SKYPE_SETTINGS_ID)); - ptrA password(getStringA(SKYPE_SETTINGS_PASSWORD)); - CMStringA mscookies(FORMAT, "MSPRequ=%s;MSPOK=%s;CkTst=G%lld;", scookies["MSPRequ"].c_str(), scookies["MSPOK"].c_str(), time(NULL)); - - cookies["MSPRequ"] = scookies["MSPRequ"]; - - PushRequest(new OAuthRequest(login, password, mscookies.c_str(), PPFT.c_str())); -} - -bool CSkypeProto::CheckOauth(const char *szResponse) -{ - std::string content = szResponse; - std::smatch match; - if (!std::regex_search(content, match, std::regex(""))) - if (!std::regex_search(content, match, std::regex(""))) - return false; - - std::string t = match[1]; - PushRequest(new OAuthRequest(t.c_str())); - return true; -} - -void CSkypeProto::OnOAuthConfirm(NETLIBHTTPREQUEST *response, AsyncHttpRequest *) -{ - if (response == nullptr || response->pData == nullptr) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - if (CheckOauth(response->pData)) - return; - - std::string content = response->pData; - std::string PPFT = sub(content, "sFT:'", "'"); - std::string opid = sub(content, "opid=", "&"); - if (PPFT.empty() || opid.empty()) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - std::regex regex("^(.+?=.*?;)"); - std::smatch match; - CMStringA mscookies; - - for (int i = 0; i < response->headersCount; i++) { - if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) - continue; - - content = response->headers[i].szValue; - if (std::regex_search(content, match, regex)) - mscookies.Append(match[1].str().c_str()); - } - - PushRequest(new OAuthRequest(mscookies.c_str(), PPFT.c_str(), opid.c_str())); -} - -void CSkypeProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) -{ - if (response == nullptr || response->pData == nullptr) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - if (!CheckOauth(response->pData)) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - } -} - -void CSkypeProto::OnOAuthEnd(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) -{ - if (response == nullptr || response->pData == nullptr) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - std::regex regex; - std::smatch match; - std::string content = response->pData; - - regex = ""; - if (!std::regex_search(content, match, regex)) { - ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); - SetStatus(ID_STATUS_OFFLINE); - return; - } - std::string token = match[1]; - setString("TokenSecret", token.c_str()); - regex = ""; - - if (std::regex_search(content, match, regex)) { - std::string expiresIn = match[1]; - int seconds = atoi(expiresIn.c_str()); - setDword("TokenExpiresIn", time(NULL) + seconds); - } - - OnLoginSuccess(); -} +/* +Copyright (c) 2015-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" + +static std::string sub(const std::string &str, const char *start, const char *end) +{ + size_t i1 = str.find(start); + if (i1 == -1) + return ""; + + i1 += strlen(start); + size_t i2 = str.find(end, i1); + return (i2 == -1) ? "" : str.substr(i1, i2 - i1); +} + +void CSkypeProto::OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +{ + if (response == nullptr || response->pData == nullptr) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + std::string content = response->pData; + + regex = ""; + + if (!std::regex_search(content, match, regex)) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string PPFT = match[1]; + + std::map scookies; + regex = "^(.+?)=(.*?);"; + + for (int i = 0; i < response->headersCount; i++) { + if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) + continue; + + content = response->headers[i].szValue; + if (std::regex_search(content, match, regex)) + scookies[match[1]] = match[2]; + } + + ptrA login(getStringA(SKYPE_SETTINGS_ID)); + ptrA password(getStringA(SKYPE_SETTINGS_PASSWORD)); + CMStringA mscookies(FORMAT, "MSPRequ=%s;MSPOK=%s;CkTst=G%lld;", scookies["MSPRequ"].c_str(), scookies["MSPOK"].c_str(), time(NULL)); + + cookies["MSPRequ"] = scookies["MSPRequ"]; + + PushRequest(new OAuthRequest(login, password, mscookies.c_str(), PPFT.c_str())); +} + +bool CSkypeProto::CheckOauth(const char *szResponse) +{ + std::string content = szResponse; + std::smatch match; + if (!std::regex_search(content, match, std::regex(""))) + if (!std::regex_search(content, match, std::regex(""))) + return false; + + std::string t = match[1]; + PushRequest(new OAuthRequest(t.c_str())); + return true; +} + +void CSkypeProto::OnOAuthConfirm(NETLIBHTTPREQUEST *response, AsyncHttpRequest *) +{ + if (response == nullptr || response->pData == nullptr) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + if (CheckOauth(response->pData)) + return; + + std::string content = response->pData; + std::string PPFT = sub(content, "sFT:'", "'"); + std::string opid = sub(content, "opid=", "&"); + if (PPFT.empty() || opid.empty()) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex("^(.+?=.*?;)"); + std::smatch match; + CMStringA mscookies; + + for (int i = 0; i < response->headersCount; i++) { + if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) + continue; + + content = response->headers[i].szValue; + if (std::regex_search(content, match, regex)) + mscookies.Append(match[1].str().c_str()); + } + + PushRequest(new OAuthRequest(mscookies.c_str(), PPFT.c_str(), opid.c_str())); +} + +void CSkypeProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +{ + if (response == nullptr || response->pData == nullptr) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + if (!CheckOauth(response->pData)) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + } +} + +void CSkypeProto::OnOAuthEnd(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +{ + if (response == nullptr || response->pData == nullptr) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + std::string content = response->pData; + + regex = ""; + if (!std::regex_search(content, match, regex)) { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string token = match[1]; + setString("TokenSecret", token.c_str()); + regex = ""; + + if (std::regex_search(content, match, regex)) { + std::string expiresIn = match[1]; + int seconds = atoi(expiresIn.c_str()); + setDword("TokenExpiresIn", time(NULL) + seconds); + } + + OnLoginSuccess(); +} diff --git a/protocols/SkypeWeb/src/skype_options.cpp b/protocols/SkypeWeb/src/skype_options.cpp index baaff8b7ab..07f15c215a 100644 --- a/protocols/SkypeWeb/src/skype_options.cpp +++ b/protocols/SkypeWeb/src/skype_options.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index b868e18bcd..0000de3b20 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_profile.cpp b/protocols/SkypeWeb/src/skype_profile.cpp index 5612dc9619..f8fbaa2fbe 100644 --- a/protocols/SkypeWeb/src/skype_profile.cpp +++ b/protocols/SkypeWeb/src/skype_profile.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index d99fe64b61..5eb23d11ca 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -1,343 +1,343 @@ -/* -Copyright (c) 2015-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 . -*/ - -#include "stdafx.h" - -CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) : - PROTO(protoName, userName), - m_PopupClasses(1), - m_OutMessages(3, PtrKeySortT), - m_bThreadsTerminated(false), - m_impl(*this), - m_requests(1), - bAutoHistorySync(this, "AutoSync", true), - bMarkAllAsUnread(this, "MarkMesUnread", true), - bUseHostnameAsPlace(this, "UseHostName", true), - bUseBBCodes(this, "UseBBCodes", true), - bUseServerTime(this, "UseServerTime", false), - wstrCListGroup(this, SKYPE_SETTINGS_GROUP, L"Skype"), - wstrPlace(this, "Place", L"") -{ - NETLIBUSER nlu = {}; - nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_UNICODE; - nlu.szDescriptiveName.w = m_tszUserName; - nlu.szSettingsModule = m_szModuleName; - m_hNetlibUser = Netlib_RegisterUser(&nlu); - - CreateProtoService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit); - CreateProtoService(PS_GETAVATARINFO, &CSkypeProto::SvcGetAvatarInfo); - CreateProtoService(PS_GETAVATARCAPS, &CSkypeProto::SvcGetAvatarCaps); - CreateProtoService(PS_GETMYAVATAR, &CSkypeProto::SvcGetMyAvatar); - CreateProtoService(PS_SETMYAVATAR, &CSkypeProto::SvcSetMyAvatar); - - CreateProtoService(PS_MENU_REQAUTH, &CSkypeProto::OnRequestAuth); - CreateProtoService(PS_MENU_GRANTAUTH, &CSkypeProto::OnGrantAuth); - CreateProtoService(PS_MENU_LOADHISTORY, &CSkypeProto::GetContactHistory); - - HookProtoEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit); - HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CSkypeProto::OnDbEventRead); - - m_tszAvatarFolder = std::wstring(VARSW(L"%miranda_avatarcache%")) + L"\\" + m_tszUserName; - CreateDirectoryTreeW(m_tszAvatarFolder.c_str()); - - //sounds - g_plugin.addSound("skype_inc_call", L"SkypeWeb", LPGENW("Incoming call")); - g_plugin.addSound("skype_call_canceled", L"SkypeWeb", LPGENW("Incoming call canceled")); - - m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, NULL, NULL); - - m_szSkypename = getMStringA(SKYPE_SETTINGS_ID); - if (m_szSkypename.IsEmpty()) { - m_szSkypename = getMStringA(SKYPE_SETTINGS_LOGIN); - if (!m_szSkypename.IsEmpty()) { // old settings format, need to update all settings - m_szSkypename.Insert(0, "8:"); - setString(SKYPE_SETTINGS_ID, m_szSkypename); - - for (auto &hContact : AccContacts()) { - CMStringA id(ptrA(getUStringA(hContact, "Skypename"))); - if (!id.IsEmpty()) - setString(hContact, SKYPE_SETTINGS_ID, (isChatRoom(hContact)) ? "19:"+id : "8:"+id); - - ptrW wszNick(getWStringA(hContact, "Nick")); - if (wszNick == nullptr) - setUString(hContact, "Nick", id); - - delSetting(hContact, "Skypename"); - } - } - } - - InitGroupChatModule(); -} - -CSkypeProto::~CSkypeProto() -{ - StopQueue(); - if (m_hRequestQueueThread) { - WaitForSingleObject(m_hRequestQueueThread, INFINITE); - m_hRequestQueueThread = nullptr; - } - - UninitPopups(); - - if (m_hPollingThread) { - WaitForSingleObject(m_hPollingThread, INFINITE); - m_hPollingThread = nullptr; - } -} - -void CSkypeProto::OnModulesLoaded() -{ - setAllContactStatuses(ID_STATUS_OFFLINE, false); - - HookProtoEvent(ME_MSG_PRECREATEEVENT, &CSkypeProto::OnPreCreateMessage); - - InitDBEvents(); - InitPopups(); -} - -void CSkypeProto::OnShutdown() -{ - debugLogA(__FUNCTION__); - - StopQueue(); - - m_bThreadsTerminated = true; - - m_hPollingEvent.Set(); - m_hTrouterEvent.Set(); -} - -INT_PTR CSkypeProto::GetCaps(int type, MCONTACT) -{ - switch (type) { - case PFLAGNUM_1: - return PF1_IM | PF1_AUTHREQ | PF1_CHAT | PF1_BASICSEARCH | PF1_MODEMSG | PF1_FILE; - case PFLAGNUM_2: - return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND; - case PFLAGNUM_3: - return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND; - case PFLAGNUM_4: - return PF4_NOAUTHDENYREASON | PF4_SUPPORTTYPING | PF4_AVATARS | PF4_IMSENDOFFLINE | PF4_OFFLINEFILES | PF4_SERVERMSGID; - case PFLAG_UNIQUEIDTEXT: - return (INT_PTR)TranslateT("Skypename"); - } - return 0; -} - -int CSkypeProto::SetAwayMsg(int, const wchar_t *msg) -{ - if (IsOnline()) - PushRequest(new SetStatusMsgRequest(msg ? T2Utf(msg) : "")); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void CSkypeProto::OnReceiveAwayMsg(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) -{ - JsonReply reply(response); - if (reply.error()) - return; - - MCONTACT hContact = DWORD_PTR(pRequest->pUserInfo); - auto &root = reply.data(); - if (JSONNode &mood = root["mood"]) { - CMStringW str = mood.as_mstring(); - ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)str.c_str()); - } - else { - ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, 0); - } -} - -HANDLE CSkypeProto::GetAwayMsg(MCONTACT hContact) -{ - auto *pReq = new GetProfileRequest(this, hContact); - pReq->m_pFunc = &CSkypeProto::OnReceiveAwayMsg; - return (HANDLE)1; -} - -MCONTACT CSkypeProto::AddToList(int, PROTOSEARCHRESULT *psr) -{ - debugLogA(__FUNCTION__); - - if (psr->id.a == nullptr) - return NULL; - - MCONTACT hContact; - if (psr->flags & PSR_UNICODE) - hContact = AddContact(T2Utf(psr->id.w), T2Utf(psr->nick.w)); - else - hContact = AddContact(psr->id.a, psr->nick.a); - - return hContact; -} - -MCONTACT CSkypeProto::AddToListByEvent(int, int, MEVENT hDbEvent) -{ - debugLogA(__FUNCTION__); - - DB::EventInfo dbei; - dbei.cbBlob = -1; - if (db_event_get(hDbEvent, &dbei)) - return NULL; - if (mir_strcmp(dbei.szModule, m_szModuleName)) - return NULL; - if (dbei.eventType != EVENTTYPE_AUTHREQUEST) - return NULL; - - DB::AUTH_BLOB blob(dbei.pBlob); - return AddContact(blob.get_email(), blob.get_nick()); -} - -int CSkypeProto::Authorize(MEVENT hDbEvent) -{ - MCONTACT hContact = GetContactFromAuthEvent(hDbEvent); - if (hContact == INVALID_CONTACT_ID) - return 1; - - PushRequest(new AuthAcceptRequest(getId(hContact))); - return 0; -} - -int CSkypeProto::AuthDeny(MEVENT hDbEvent, const wchar_t*) -{ - MCONTACT hContact = GetContactFromAuthEvent(hDbEvent); - if (hContact == INVALID_CONTACT_ID) - return 1; - - PushRequest(new AuthDeclineRequest(getId(hContact))); - return 0; -} - -int CSkypeProto::AuthRecv(MCONTACT, PROTORECVEVENT* pre) -{ - return Proto_AuthRecv(m_szModuleName, pre); -} - -int CSkypeProto::AuthRequest(MCONTACT hContact, const wchar_t *szMessage) -{ - if (hContact == INVALID_CONTACT_ID) - return 1; - - PushRequest(new AddContactRequest(getId(hContact), T2Utf(szMessage))); - return 0; -} - -int CSkypeProto::GetInfo(MCONTACT hContact, int) -{ - if (isChatRoom(hContact)) - return 1; - - PushRequest(new GetProfileRequest(this, hContact)); - return 0; -} - -int CSkypeProto::SendMsg(MCONTACT hContact, int flags, const char *msg) -{ - return OnSendMessage(hContact, flags, msg); -} - -int CSkypeProto::SetStatus(int iNewStatus) -{ - if (iNewStatus == m_iDesiredStatus) - return 0; - - switch (iNewStatus) { - case ID_STATUS_FREECHAT: iNewStatus = ID_STATUS_ONLINE; break; - case ID_STATUS_NA: iNewStatus = ID_STATUS_AWAY; break; - case ID_STATUS_OCCUPIED: iNewStatus = ID_STATUS_DND; break; - } - - debugLogA(__FUNCTION__ ": changing status from %i to %i", m_iStatus, iNewStatus); - - int old_status = m_iStatus; - m_iDesiredStatus = iNewStatus; - - if (iNewStatus == ID_STATUS_OFFLINE) { - if (m_iStatus > ID_STATUS_CONNECTING + 1 && m_szId) - PushRequest(new DeleteEndpointRequest(this)); - - m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; - // logout - StopQueue(); - - ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, ID_STATUS_OFFLINE); - - m_impl.m_heartBeat.StopSafe(); - - if (!Miranda_IsTerminated()) - setAllContactStatuses(ID_STATUS_OFFLINE, false); - return 0; - } - else { - if (old_status == ID_STATUS_CONNECTING) - return 0; - - if (old_status == ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE) - Login(); - else - PushRequest(new SetStatusRequest(MirandaToSkypeStatus(m_iDesiredStatus))); - } - - ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); - return 0; -} - -int CSkypeProto::UserIsTyping(MCONTACT hContact, int type) -{ - PushRequest(new SendTypingRequest(getId(hContact), type)); - return 0; -} - -int CSkypeProto::RecvContacts(MCONTACT hContact, PROTORECVEVENT* pre) -{ - PROTOSEARCHRESULT **isrList = (PROTOSEARCHRESULT**)pre->szMessage; - - int nCount = *((LPARAM*)pre->lParam); - char* szMessageId = ((char*)pre->lParam + sizeof(LPARAM)); - - //if (GetMessageFromDb(hContact, szMessageId, pre->timestamp)) return 0; - - uint32_t cbBlob = 0; - for (int i = 0; i < nCount; i++) - cbBlob += int(/*mir_wstrlen(isrList[i]->nick.w)*/0 + 2 + mir_wstrlen(isrList[i]->id.w) + mir_strlen(szMessageId)); - - uint8_t *pBlob = (uint8_t*)mir_calloc(cbBlob); - uint8_t *pCurBlob = pBlob; - - for (int i = 0; i < nCount; i++) { - //mir_strcpy((char*)pCurBlob, _T2A(isrList[i]->nick.w)); - pCurBlob += mir_strlen((PCHAR)pCurBlob) + 1; - - mir_strcpy((char*)pCurBlob, _T2A(isrList[i]->id.w)); - pCurBlob += mir_strlen((char*)pCurBlob) + 1; - } - - DBEVENTINFO dbei = {}; - dbei.szModule = m_szModuleName; - dbei.timestamp = pre->timestamp; - dbei.eventType = EVENTTYPE_CONTACTS; - dbei.cbBlob = cbBlob; - dbei.pBlob = pBlob; - dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0; - db_event_add(hContact, &dbei); - - mir_free(pBlob); - return 0; -} +/* +Copyright (c) 2015-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" + +CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) : + PROTO(protoName, userName), + m_PopupClasses(1), + m_OutMessages(3, PtrKeySortT), + m_bThreadsTerminated(false), + m_impl(*this), + m_requests(1), + bAutoHistorySync(this, "AutoSync", true), + bMarkAllAsUnread(this, "MarkMesUnread", true), + bUseHostnameAsPlace(this, "UseHostName", true), + bUseBBCodes(this, "UseBBCodes", true), + bUseServerTime(this, "UseServerTime", false), + wstrCListGroup(this, SKYPE_SETTINGS_GROUP, L"Skype"), + wstrPlace(this, "Place", L"") +{ + NETLIBUSER nlu = {}; + nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_UNICODE; + nlu.szDescriptiveName.w = m_tszUserName; + nlu.szSettingsModule = m_szModuleName; + m_hNetlibUser = Netlib_RegisterUser(&nlu); + + CreateProtoService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit); + CreateProtoService(PS_GETAVATARINFO, &CSkypeProto::SvcGetAvatarInfo); + CreateProtoService(PS_GETAVATARCAPS, &CSkypeProto::SvcGetAvatarCaps); + CreateProtoService(PS_GETMYAVATAR, &CSkypeProto::SvcGetMyAvatar); + CreateProtoService(PS_SETMYAVATAR, &CSkypeProto::SvcSetMyAvatar); + + CreateProtoService(PS_MENU_REQAUTH, &CSkypeProto::OnRequestAuth); + CreateProtoService(PS_MENU_GRANTAUTH, &CSkypeProto::OnGrantAuth); + CreateProtoService(PS_MENU_LOADHISTORY, &CSkypeProto::GetContactHistory); + + HookProtoEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit); + HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CSkypeProto::OnDbEventRead); + + m_tszAvatarFolder = std::wstring(VARSW(L"%miranda_avatarcache%")) + L"\\" + m_tszUserName; + CreateDirectoryTreeW(m_tszAvatarFolder.c_str()); + + //sounds + g_plugin.addSound("skype_inc_call", L"SkypeWeb", LPGENW("Incoming call")); + g_plugin.addSound("skype_call_canceled", L"SkypeWeb", LPGENW("Incoming call canceled")); + + m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, NULL, NULL); + + m_szSkypename = getMStringA(SKYPE_SETTINGS_ID); + if (m_szSkypename.IsEmpty()) { + m_szSkypename = getMStringA(SKYPE_SETTINGS_LOGIN); + if (!m_szSkypename.IsEmpty()) { // old settings format, need to update all settings + m_szSkypename.Insert(0, "8:"); + setString(SKYPE_SETTINGS_ID, m_szSkypename); + + for (auto &hContact : AccContacts()) { + CMStringA id(ptrA(getUStringA(hContact, "Skypename"))); + if (!id.IsEmpty()) + setString(hContact, SKYPE_SETTINGS_ID, (isChatRoom(hContact)) ? "19:"+id : "8:"+id); + + ptrW wszNick(getWStringA(hContact, "Nick")); + if (wszNick == nullptr) + setUString(hContact, "Nick", id); + + delSetting(hContact, "Skypename"); + } + } + } + + InitGroupChatModule(); +} + +CSkypeProto::~CSkypeProto() +{ + StopQueue(); + if (m_hRequestQueueThread) { + WaitForSingleObject(m_hRequestQueueThread, INFINITE); + m_hRequestQueueThread = nullptr; + } + + UninitPopups(); + + if (m_hPollingThread) { + WaitForSingleObject(m_hPollingThread, INFINITE); + m_hPollingThread = nullptr; + } +} + +void CSkypeProto::OnModulesLoaded() +{ + setAllContactStatuses(ID_STATUS_OFFLINE, false); + + HookProtoEvent(ME_MSG_PRECREATEEVENT, &CSkypeProto::OnPreCreateMessage); + + InitDBEvents(); + InitPopups(); +} + +void CSkypeProto::OnShutdown() +{ + debugLogA(__FUNCTION__); + + StopQueue(); + + m_bThreadsTerminated = true; + + m_hPollingEvent.Set(); + m_hTrouterEvent.Set(); +} + +INT_PTR CSkypeProto::GetCaps(int type, MCONTACT) +{ + switch (type) { + case PFLAGNUM_1: + return PF1_IM | PF1_AUTHREQ | PF1_CHAT | PF1_BASICSEARCH | PF1_MODEMSG | PF1_FILE; + case PFLAGNUM_2: + return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND; + case PFLAGNUM_3: + return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND; + case PFLAGNUM_4: + return PF4_NOAUTHDENYREASON | PF4_SUPPORTTYPING | PF4_AVATARS | PF4_IMSENDOFFLINE | PF4_OFFLINEFILES | PF4_SERVERMSGID; + case PFLAG_UNIQUEIDTEXT: + return (INT_PTR)TranslateT("Skypename"); + } + return 0; +} + +int CSkypeProto::SetAwayMsg(int, const wchar_t *msg) +{ + if (IsOnline()) + PushRequest(new SetStatusMsgRequest(msg ? T2Utf(msg) : "")); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSkypeProto::OnReceiveAwayMsg(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +{ + JsonReply reply(response); + if (reply.error()) + return; + + MCONTACT hContact = DWORD_PTR(pRequest->pUserInfo); + auto &root = reply.data(); + if (JSONNode &mood = root["mood"]) { + CMStringW str = mood.as_mstring(); + ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)str.c_str()); + } + else { + ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, 0); + } +} + +HANDLE CSkypeProto::GetAwayMsg(MCONTACT hContact) +{ + auto *pReq = new GetProfileRequest(this, hContact); + pReq->m_pFunc = &CSkypeProto::OnReceiveAwayMsg; + return (HANDLE)1; +} + +MCONTACT CSkypeProto::AddToList(int, PROTOSEARCHRESULT *psr) +{ + debugLogA(__FUNCTION__); + + if (psr->id.a == nullptr) + return NULL; + + MCONTACT hContact; + if (psr->flags & PSR_UNICODE) + hContact = AddContact(T2Utf(psr->id.w), T2Utf(psr->nick.w)); + else + hContact = AddContact(psr->id.a, psr->nick.a); + + return hContact; +} + +MCONTACT CSkypeProto::AddToListByEvent(int, int, MEVENT hDbEvent) +{ + debugLogA(__FUNCTION__); + + DB::EventInfo dbei; + dbei.cbBlob = -1; + if (db_event_get(hDbEvent, &dbei)) + return NULL; + if (mir_strcmp(dbei.szModule, m_szModuleName)) + return NULL; + if (dbei.eventType != EVENTTYPE_AUTHREQUEST) + return NULL; + + DB::AUTH_BLOB blob(dbei.pBlob); + return AddContact(blob.get_email(), blob.get_nick()); +} + +int CSkypeProto::Authorize(MEVENT hDbEvent) +{ + MCONTACT hContact = GetContactFromAuthEvent(hDbEvent); + if (hContact == INVALID_CONTACT_ID) + return 1; + + PushRequest(new AuthAcceptRequest(getId(hContact))); + return 0; +} + +int CSkypeProto::AuthDeny(MEVENT hDbEvent, const wchar_t*) +{ + MCONTACT hContact = GetContactFromAuthEvent(hDbEvent); + if (hContact == INVALID_CONTACT_ID) + return 1; + + PushRequest(new AuthDeclineRequest(getId(hContact))); + return 0; +} + +int CSkypeProto::AuthRecv(MCONTACT, PROTORECVEVENT* pre) +{ + return Proto_AuthRecv(m_szModuleName, pre); +} + +int CSkypeProto::AuthRequest(MCONTACT hContact, const wchar_t *szMessage) +{ + if (hContact == INVALID_CONTACT_ID) + return 1; + + PushRequest(new AddContactRequest(getId(hContact), T2Utf(szMessage))); + return 0; +} + +int CSkypeProto::GetInfo(MCONTACT hContact, int) +{ + if (isChatRoom(hContact)) + return 1; + + PushRequest(new GetProfileRequest(this, hContact)); + return 0; +} + +int CSkypeProto::SendMsg(MCONTACT hContact, int flags, const char *msg) +{ + return OnSendMessage(hContact, flags, msg); +} + +int CSkypeProto::SetStatus(int iNewStatus) +{ + if (iNewStatus == m_iDesiredStatus) + return 0; + + switch (iNewStatus) { + case ID_STATUS_FREECHAT: iNewStatus = ID_STATUS_ONLINE; break; + case ID_STATUS_NA: iNewStatus = ID_STATUS_AWAY; break; + case ID_STATUS_OCCUPIED: iNewStatus = ID_STATUS_DND; break; + } + + debugLogA(__FUNCTION__ ": changing status from %i to %i", m_iStatus, iNewStatus); + + int old_status = m_iStatus; + m_iDesiredStatus = iNewStatus; + + if (iNewStatus == ID_STATUS_OFFLINE) { + if (m_iStatus > ID_STATUS_CONNECTING + 1 && m_szId) + PushRequest(new DeleteEndpointRequest(this)); + + m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; + // logout + StopQueue(); + + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, ID_STATUS_OFFLINE); + + m_impl.m_heartBeat.StopSafe(); + + if (!Miranda_IsTerminated()) + setAllContactStatuses(ID_STATUS_OFFLINE, false); + return 0; + } + else { + if (old_status == ID_STATUS_CONNECTING) + return 0; + + if (old_status == ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE) + Login(); + else + PushRequest(new SetStatusRequest(MirandaToSkypeStatus(m_iDesiredStatus))); + } + + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); + return 0; +} + +int CSkypeProto::UserIsTyping(MCONTACT hContact, int type) +{ + PushRequest(new SendTypingRequest(getId(hContact), type)); + return 0; +} + +int CSkypeProto::RecvContacts(MCONTACT hContact, PROTORECVEVENT* pre) +{ + PROTOSEARCHRESULT **isrList = (PROTOSEARCHRESULT**)pre->szMessage; + + int nCount = *((LPARAM*)pre->lParam); + char* szMessageId = ((char*)pre->lParam + sizeof(LPARAM)); + + //if (GetMessageFromDb(hContact, szMessageId, pre->timestamp)) return 0; + + uint32_t cbBlob = 0; + for (int i = 0; i < nCount; i++) + cbBlob += int(/*mir_wstrlen(isrList[i]->nick.w)*/0 + 2 + mir_wstrlen(isrList[i]->id.w) + mir_strlen(szMessageId)); + + uint8_t *pBlob = (uint8_t*)mir_calloc(cbBlob); + uint8_t *pCurBlob = pBlob; + + for (int i = 0; i < nCount; i++) { + //mir_strcpy((char*)pCurBlob, _T2A(isrList[i]->nick.w)); + pCurBlob += mir_strlen((PCHAR)pCurBlob) + 1; + + mir_strcpy((char*)pCurBlob, _T2A(isrList[i]->id.w)); + pCurBlob += mir_strlen((char*)pCurBlob) + 1; + } + + DBEVENTINFO dbei = {}; + dbei.szModule = m_szModuleName; + dbei.timestamp = pre->timestamp; + dbei.eventType = EVENTTYPE_CONTACTS; + dbei.cbBlob = cbBlob; + dbei.pBlob = pBlob; + dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0; + db_event_add(hContact, &dbei); + + mir_free(pBlob); + return 0; +} diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 4630cde68f..3517ae742a 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_search.cpp b/protocols/SkypeWeb/src/skype_search.cpp index e47eba7243..51a4952021 100644 --- a/protocols/SkypeWeb/src/skype_search.cpp +++ b/protocols/SkypeWeb/src/skype_search.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_trouter.cpp b/protocols/SkypeWeb/src/skype_trouter.cpp index bb8a74385b..65e38d4d41 100644 --- a/protocols/SkypeWeb/src/skype_trouter.cpp +++ b/protocols/SkypeWeb/src/skype_trouter.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index 903309054b..fc7a4bb6b1 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -1,679 +1,679 @@ -/* -Copyright (c) 2015-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 . -*/ - -#include "stdafx.h" - -#pragma warning(disable:4566) - -time_t CSkypeProto::IsoToUnixTime(const std::string &stamp) -{ - char date[9]; - int i, y; - - if (stamp.empty()) - return 0; - - char *p = NEWSTR_ALLOCA(stamp.c_str()); - - // skip '-' chars - int si = 0, sj = 0; - while (true) { - if (p[si] == '-') - si++; - else if (!(p[sj++] = p[si++])) - break; - } - - // Get the date part - for (i = 0; *p != '\0' && i < 8 && isdigit(*p); p++, i++) - date[i] = *p; - - // Parse year - if (i == 6) { - // 2-digit year (1970-2069) - y = (date[0] - '0') * 10 + (date[1] - '0'); - if (y < 70) y += 100; - } - else if (i == 8) { - // 4-digit year - y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + date[3] - '0'; - y -= 1900; - } - else return 0; - - struct tm timestamp; - timestamp.tm_year = y; - - // Parse month - timestamp.tm_mon = (date[i - 4] - '0') * 10 + date[i - 3] - '0' - 1; - - // Parse date - timestamp.tm_mday = (date[i - 2] - '0') * 10 + date[i - 1] - '0'; - - // Skip any date/time delimiter - for (; *p != '\0' && !isdigit(*p); p++); - - // Parse time - if (sscanf(p, "%d:%d:%d", ×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec) != 3) - return (time_t)0; - - timestamp.tm_isdst = 0; // DST is already present in _timezone below - time_t t = mktime(×tamp); - - _tzset(); - t -= _timezone; - return (t >= 0) ? t : 0; -} - -struct HtmlEntity -{ - const char *entity; - const char *symbol; -}; - -const HtmlEntity htmlEntities[] = -{ - { "AElig", "\u00C6" }, - { "Aacute", "\u00C1" }, - { "Acirc", "\u00C2" }, - { "Agrave", "\u00C0" }, - { "Alpha", "\u0391" }, - { "Aring", "\u00C5" }, - { "Atilde", "\u00C3" }, - { "Auml", "\u00C4" }, - { "Beta", "\u0392" }, - { "Ccedil", "\u00C7" }, - { "Chi", "\u03A7" }, - { "Dagger", "‡" }, - { "Delta", "\u0394" }, - { "ETH", "\u00D0" }, - { "Eacute", "\u00C9" }, - { "Ecirc", "\u00CA" }, - { "Egrave", "\u00C8" }, - { "Epsilon", "\u0395" }, - { "Eta", "\u0397" }, - { "Euml", "\u00CB" }, - { "Gamma", "\u0393" }, - { "Iacute", "\u00CD" }, - { "Icirc", "\u00CE" }, - { "Igrave", "\u00CC" }, - { "Iota", "\u0399" }, - { "Iuml", "\u00CF" }, - { "Kappa", "\u039A" }, - { "Lambda", "\u039B" }, - { "Mu", "\u039C" }, - { "Ntilde", "\u00D1" }, - { "Nu", "\u039D" }, - { "OElig", "\u0152" }, - { "Oacute", "\u00D3" }, - { "Ocirc", "\u00D4" }, - { "Ograve", "\u00D2" }, - { "Omega", "\u03A9" }, - { "Omicron", "\u039F" }, - { "Oslash", "\u00D8" }, - { "Otilde", "\u00D5" }, - { "Ouml", "\u00D6" }, - { "Phi", "\u03A6" }, - { "Pi", "\u03A0" }, - { "Prime", "\u2033" }, - { "Psi", "\u03A8" }, - { "Rho", "\u03A1" }, - { "Scaron", "Š" }, - { "Sigma", "Σ" }, - { "THORN", "Þ" }, - { "Tau", "Τ" }, - { "Theta", "Θ" }, - { "Uacute", "Ú" }, - { "Ucirc", "Û" }, - { "Ugrave", "Ù" }, - { "Upsilon", "Υ" }, - { "Uuml", "Ü" }, - { "Xi", "Ξ" }, - { "Yacute", "Ý" }, - { "Yuml", "Ÿ" }, - { "Zeta", "Ζ" }, - { "aacute", "á" }, - { "acirc", "â" }, - { "acute", "´" }, - { "aelig", "æ" }, - { "agrave", "à" }, - { "alefsym", "ℵ" }, - { "alpha", "α" }, - { "amp", "&" }, - { "and", "∧" }, - { "ang", "∠" }, - { "apos", "'" }, - { "aring", "å" }, - { "asymp", "≈" }, - { "atilde", "ã" }, - { "auml", "ä" }, - { "bdquo", "„" }, - { "beta", "β" }, - { "brvbar", "¦" }, - { "bull", "•" }, - { "cap", "∩" }, - { "ccedil", "ç" }, - { "cedil", "¸" }, - { "cent", "¢" }, - { "chi", "χ" }, - { "circ", "ˆ" }, - { "clubs", "♣" }, - { "cong", "≅" }, - { "copy", "©" }, - { "crarr", "↵" }, - { "cup", "∪" }, - { "curren", "¤" }, - { "dArr", "⇓" }, - { "dagger", "†" }, - { "darr", "↓" }, - { "deg", "°" }, - { "delta", "δ" }, - { "diams", "♦" }, - { "divide", "÷" }, - { "eacute", "é" }, - { "ecirc", "ê" }, - { "egrave", "è" }, - { "empty", "∅" }, - { "emsp", " " }, - { "ensp", " " }, - { "epsilon", "ε" }, - { "equiv", "≡" }, - { "eta", "η" }, - { "eth", "ð" }, - { "euml", "ë" }, - { "euro", "€" }, - { "exist", "∃" }, - { "fnof", "ƒ" }, - { "forall", "∀" }, - { "frac12", "½" }, - { "frac14", "¼" }, - { "frac34", "¾" }, - { "frasl", "⁄" }, - { "gamma", "γ" }, - { "ge", "≥" }, - { "gt", ">" }, - { "hArr", "⇔" }, - { "harr", "↔" }, - { "hearts", "♥" }, - { "hellip", "…" }, - { "iacute", "í" }, - { "icirc", "î" }, - { "iexcl", "¡" }, - { "igrave", "ì" }, - { "image", "ℑ" }, - { "infin", "∞" }, - { "int", "∫" }, - { "iota", "ι" }, - { "iquest", "¿" }, - { "isin", "∈" }, - { "iuml", "ï" }, - { "kappa", "κ" }, - { "lArr", "⇐" }, - { "lambda", "λ" }, - { "lang", "〈" }, - { "laquo", "«" }, - { "larr", "←" }, - { "lceil", "⌈" }, - { "ldquo", "“" }, - { "le", "≤" }, - { "lfloor", "⌊" }, - { "lowast", "∗" }, - { "loz", "◊" }, - { "lrm", "\xE2\x80\x8E" }, - { "lsaquo", "‹" }, - { "lsquo", "‘" }, - { "lt", "<" }, - { "macr", "¯" }, - { "mdash", "—" }, - { "micro", "µ" }, - { "middot", "·" }, - { "minus", "−" }, - { "mu", "μ" }, - { "nabla", "∇" }, - { "nbsp", " " }, - { "ndash", "–" }, - { "ne", "≠" }, - { "ni", "∋" }, - { "not", "¬" }, - { "notin", "∉" }, - { "nsub", "⊄" }, - { "ntilde", "ñ" }, - { "nu", "ν" }, - { "oacute", "ó" }, - { "ocirc", "ô" }, - { "oelig", "œ" }, - { "ograve", "ò" }, - { "oline", "‾" }, - { "omega", "ω" }, - { "omicron", "ο" }, - { "oplus", "⊕" }, - { "or", "∨" }, - { "ordf", "ª" }, - { "ordm", "º" }, - { "oslash", "ø" }, - { "otilde", "õ" }, - { "otimes", "⊗" }, - { "ouml", "ö" }, - { "para", "¶" }, - { "part", "∂" }, - { "permil", "‰" }, - { "perp", "⊥" }, - { "phi", "φ" }, - { "pi", "π" }, - { "piv", "ϖ" }, - { "plusmn", "±" }, - { "pound", "£" }, - { "prime", "′" }, - { "prod", "∏" }, - { "prop", "∝" }, - { "psi", "ψ" }, - { "quot", "\"" }, - { "rArr", "⇒" }, - { "radic", "√" }, - { "rang", "〉" }, - { "raquo", "»" }, - { "rarr", "→" }, - { "rceil", "⌉" }, - { "rdquo", "”" }, - { "real", "ℜ" }, - { "reg", "®" }, - { "rfloor", "⌋" }, - { "rho", "ρ" }, - { "rlm", "\xE2\x80\x8F" }, - { "rsaquo", "›" }, - { "rsquo", "’" }, - { "sbquo", "‚" }, - { "scaron", "š" }, - { "sdot", "⋅" }, - { "sect", "§" }, - { "shy", "\xC2\xAD" }, - { "sigma", "σ" }, - { "sigmaf", "ς" }, - { "sim", "∼" }, - { "spades", "♠" }, - { "sub", "⊂" }, - { "sube", "⊆" }, - { "sum", "∑" }, - { "sup", "⊃" }, - { "sup1", "¹" }, - { "sup2", "²" }, - { "sup3", "³" }, - { "supe", "⊇" }, - { "szlig", "ß" }, - { "tau", "τ" }, - { "there4", "∴" }, - { "theta", "θ" }, - { "thetasym", "ϑ" }, - { "thinsp", " " }, - { "thorn", "þ" }, - { "tilde", "˜" }, - { "times", "×" }, - { "trade", "™" }, - { "uArr", "⇑" }, - { "uacute", "ú" }, - { "uarr", "↑" }, - { "ucirc", "û" }, - { "ugrave", "ù" }, - { "uml", "¨" }, - { "upsih", "ϒ" }, - { "upsilon", "υ" }, - { "uuml", "ü" }, - { "weierp", "℘" }, - { "xi", "ξ" }, - { "yacute", "ý" }, - { "yen", "¥" }, - { "yuml", "ÿ" }, - { "zeta", "ζ" }, - { "zwj", "\xE2\x80\x8D" }, - { "zwnj", "\xE2\x80\x8C" } -}; - -CMStringW RemoveHtml(const CMStringW &data) -{ - CMStringW new_string; - - for (int i = 0; i < data.GetLength(); i++) { - wchar_t c = data[i]; - if (c == '<') { - i = data.Find('>', i); - if (i == -1) - break; - - continue; - } - - // special character - if (c == '&') { - int begin = i; - i = data.Find(';', i); - if (i == -1) - i = begin; - else { - CMStringW entity = data.Mid(begin + 1, i - begin - 1); - - bool found = false; - if (entity.GetLength() > 1 && entity[0] == '#') { - // Numeric replacement - bool hex = false; - if (entity[1] == 'x') { - hex = true; - entity.Delete(0, 2); - } - else entity.Delete(0, 1); - - if (!entity.IsEmpty()) { - found = true; - errno = 0; - unsigned long value = wcstoul(entity, nullptr, hex ? 16 : 10); - if (errno != 0) { // error with conversion in strtoul, ignore the result - found = false; - } - else if (value <= 127) { // U+0000 .. U+007F - new_string += (char)value; - } - else if (value >= 128 && value <= 2047) { // U+0080 .. U+07FF - new_string += (char)(192 + (value / 64)); - new_string += (char)(128 + (value % 64)); - } - else if (value >= 2048 && value <= 65535) { // U+0800 .. U+FFFF - new_string += (char)(224 + (value / 4096)); - new_string += (char)(128 + ((value / 64) % 64)); - new_string += (char)(128 + (value % 64)); - } - else { - new_string += (char)((value >> 24) & 0xFF); - new_string += (char)((value >> 16) & 0xFF); - new_string += (char)((value >> 8) & 0xFF); - new_string += (char)((value) & 0xFF); - } - } - } - else { - // Keyword replacement - CMStringA tmp = entity; - for (auto &it : htmlEntities) { - if (!mir_strcmpi(tmp, it.entity)) { - new_string += it.symbol; - found = true; - break; - } - } - } - - if (found) - continue; - else - i = begin; - } - } - - new_string.AppendChar(c); - } - - return new_string; -} - -const char* CSkypeProto::MirandaToSkypeStatus(int status) -{ - switch (status) { - case ID_STATUS_AWAY: - return "Away"; - - case ID_STATUS_DND: - return "Busy"; - - case ID_STATUS_IDLE: - return "Idle"; - - case ID_STATUS_INVISIBLE: - return "Hidden"; - } - return "Online"; -} - -int CSkypeProto::SkypeToMirandaStatus(const char *status) -{ - if (!mir_strcmpi(status, "Online")) - return ID_STATUS_ONLINE; - else if (!mir_strcmpi(status, "Hidden")) - return ID_STATUS_INVISIBLE; - else if (!mir_strcmpi(status, "Away")) - return ID_STATUS_AWAY; - else if (!mir_strcmpi(status, "Idle")) - return ID_STATUS_AWAY; - else if (!mir_strcmpi(status, "Busy")) - return ID_STATUS_DND; - else - return ID_STATUS_OFFLINE; -} - -bool CSkypeProto::IsFileExists(std::wstring path) -{ - return _waccess(path.c_str(), 0) == 0; -} - -const char* GetSkypeNick(const char *szSkypeId) -{ - if (auto *p = strchr(szSkypeId, ':')) - return p + 1; - return szSkypeId; -} - -const wchar_t* GetSkypeNick(const wchar_t *szSkypeId) -{ - if (auto *p = wcsrchr(szSkypeId, ':')) - return p + 1; - return szSkypeId; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// url parsing - -CMStringA ParseUrl(const char *url, const char *token) -{ - if (url == nullptr) - return CMStringA(); - - auto *start = strstr(url, token); - if (start == nullptr) - return CMStringA(); - - auto *end = strchr(++start, '/'); - if (end == nullptr) - return CMStringA(start); - return CMStringA(start, end - start); -} - -CMStringW ParseUrl(const wchar_t *url, const wchar_t *token) -{ - if (url == nullptr) - return CMStringW(); - - auto *start = wcsstr(url, token); - if (start == nullptr) - return CMStringW(); - - auto *end = wcschr(++start, '/'); - if (end == nullptr) - return CMStringW(start); - return CMStringW(start, end - start); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static int possibleTypes[] = { 1, 2, 8, 19 }; - -CMStringA UrlToSkypeId(const char *url, int *pUserType) -{ - int userType = -1; - CMStringA szResult; - - if (url != nullptr) { - for (auto &it : possibleTypes) { - char tmp[10]; - sprintf_s(tmp, "/%d:", it); - if (strstr(url, tmp)) { - userType = it; - szResult = ParseUrl(url, tmp); - break; - } - } - } - - if (pUserType) - *pUserType = userType; - - return szResult; -} - -CMStringW UrlToSkypeId(const wchar_t *url, int *pUserType) -{ - int userType = -1; - CMStringW szResult; - - if (url != nullptr) { - for (auto &it : possibleTypes) { - wchar_t tmp[10]; - swprintf_s(tmp, L"/%d:", it); - if (wcsstr(url, tmp)) { - userType = it; - szResult = ParseUrl(url, tmp); - break; - } - } - } - - if (pUserType) - *pUserType = userType; - - return szResult; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -INT_PTR CSkypeProto::ParseSkypeUriService(WPARAM, LPARAM lParam) -{ - wchar_t *arg = (wchar_t *)lParam; - if (arg == nullptr) - return 1; - - // skip leading prefix - wchar_t szUri[1024]; - wcsncpy_s(szUri, arg, _TRUNCATE); - wchar_t *szJid = wcschr(szUri, ':'); - if (szJid == nullptr) - return 1; - - // empty jid? - if (!*szJid) - return 1; - - // command code - wchar_t *szCommand = szJid; - szCommand = wcschr(szCommand, '?'); - if (szCommand) - *(szCommand++) = 0; - - // parameters - wchar_t *szSecondParam = szCommand ? wcschr(szCommand, '&') : nullptr; - if (szSecondParam) - *(szSecondParam++) = 0; - - // no command or message command - if (!szCommand || !mir_wstrcmpi(szCommand, L"chat")) { - if (szSecondParam) { - wchar_t *szChatId = wcsstr(szSecondParam, L"id="); - if (szChatId) { - szChatId += 5; - StartChatRoom(szChatId, szChatId); - return 0; - } - } - MCONTACT hContact = AddContact(_T2A(szJid), nullptr, true); - CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, NULL); - return 0; - } - - if (!mir_wstrcmpi(szCommand, L"call")) { - MCONTACT hContact = AddContact(_T2A(szJid), nullptr, true); - NotifyEventHooks(g_hCallEvent, (WPARAM)hContact, (LPARAM)0); - return 0; - } - - if (!mir_wstrcmpi(szCommand, L"userinfo")) - return 0; - - if (!mir_wstrcmpi(szCommand, L"add")) { - MCONTACT hContact = FindContact(_T2A(szJid)); - if (hContact == NULL) { - PROTOSEARCHRESULT psr = { 0 }; - psr.cbSize = sizeof(psr); - psr.id.w = mir_wstrdup(szJid); - psr.nick.w = mir_wstrdup(szJid); - psr.flags = PSR_UNICODE; - Contact::AddBySearch(m_szModuleName, &psr); - } - return 0; - } - - if (!mir_wstrcmpi(szCommand, L"sendfile")) { - MCONTACT hContact = AddContact(_T2A(szJid), nullptr, true); - CallService(MS_FILE_SENDFILE, hContact, NULL); - return 1; - } - - if (!mir_wstrcmpi(szCommand, L"voicemail")) - return 1; - - return 1; -} - -INT_PTR CSkypeProto::GlobalParseSkypeUriService(WPARAM wParam, LPARAM lParam) -{ - for (auto &it : CMPlugin::g_arInstances) - if (it->IsOnline()) - return it->ParseSkypeUriService(wParam, lParam); - - return 1; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) -{ - if (pReply == nullptr) { - m_errorCode = 500; - return; - } - - m_errorCode = pReply->resultCode; - if (m_errorCode != 200) - return; - - m_root = json_parse(pReply->pData); - if (m_root == nullptr) { - m_errorCode = 500; - return; - } - - m_errorCode = (*m_root)["status"]["code"].as_int(); -} - -JsonReply::~JsonReply() -{ - json_delete(m_root); -} +/* +Copyright (c) 2015-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" + +#pragma warning(disable:4566) + +time_t CSkypeProto::IsoToUnixTime(const std::string &stamp) +{ + char date[9]; + int i, y; + + if (stamp.empty()) + return 0; + + char *p = NEWSTR_ALLOCA(stamp.c_str()); + + // skip '-' chars + int si = 0, sj = 0; + while (true) { + if (p[si] == '-') + si++; + else if (!(p[sj++] = p[si++])) + break; + } + + // Get the date part + for (i = 0; *p != '\0' && i < 8 && isdigit(*p); p++, i++) + date[i] = *p; + + // Parse year + if (i == 6) { + // 2-digit year (1970-2069) + y = (date[0] - '0') * 10 + (date[1] - '0'); + if (y < 70) y += 100; + } + else if (i == 8) { + // 4-digit year + y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + date[3] - '0'; + y -= 1900; + } + else return 0; + + struct tm timestamp; + timestamp.tm_year = y; + + // Parse month + timestamp.tm_mon = (date[i - 4] - '0') * 10 + date[i - 3] - '0' - 1; + + // Parse date + timestamp.tm_mday = (date[i - 2] - '0') * 10 + date[i - 1] - '0'; + + // Skip any date/time delimiter + for (; *p != '\0' && !isdigit(*p); p++); + + // Parse time + if (sscanf(p, "%d:%d:%d", ×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec) != 3) + return (time_t)0; + + timestamp.tm_isdst = 0; // DST is already present in _timezone below + time_t t = mktime(×tamp); + + _tzset(); + t -= _timezone; + return (t >= 0) ? t : 0; +} + +struct HtmlEntity +{ + const char *entity; + const char *symbol; +}; + +const HtmlEntity htmlEntities[] = +{ + { "AElig", "\u00C6" }, + { "Aacute", "\u00C1" }, + { "Acirc", "\u00C2" }, + { "Agrave", "\u00C0" }, + { "Alpha", "\u0391" }, + { "Aring", "\u00C5" }, + { "Atilde", "\u00C3" }, + { "Auml", "\u00C4" }, + { "Beta", "\u0392" }, + { "Ccedil", "\u00C7" }, + { "Chi", "\u03A7" }, + { "Dagger", "‡" }, + { "Delta", "\u0394" }, + { "ETH", "\u00D0" }, + { "Eacute", "\u00C9" }, + { "Ecirc", "\u00CA" }, + { "Egrave", "\u00C8" }, + { "Epsilon", "\u0395" }, + { "Eta", "\u0397" }, + { "Euml", "\u00CB" }, + { "Gamma", "\u0393" }, + { "Iacute", "\u00CD" }, + { "Icirc", "\u00CE" }, + { "Igrave", "\u00CC" }, + { "Iota", "\u0399" }, + { "Iuml", "\u00CF" }, + { "Kappa", "\u039A" }, + { "Lambda", "\u039B" }, + { "Mu", "\u039C" }, + { "Ntilde", "\u00D1" }, + { "Nu", "\u039D" }, + { "OElig", "\u0152" }, + { "Oacute", "\u00D3" }, + { "Ocirc", "\u00D4" }, + { "Ograve", "\u00D2" }, + { "Omega", "\u03A9" }, + { "Omicron", "\u039F" }, + { "Oslash", "\u00D8" }, + { "Otilde", "\u00D5" }, + { "Ouml", "\u00D6" }, + { "Phi", "\u03A6" }, + { "Pi", "\u03A0" }, + { "Prime", "\u2033" }, + { "Psi", "\u03A8" }, + { "Rho", "\u03A1" }, + { "Scaron", "Š" }, + { "Sigma", "Σ" }, + { "THORN", "Þ" }, + { "Tau", "Τ" }, + { "Theta", "Θ" }, + { "Uacute", "Ú" }, + { "Ucirc", "Û" }, + { "Ugrave", "Ù" }, + { "Upsilon", "Υ" }, + { "Uuml", "Ü" }, + { "Xi", "Ξ" }, + { "Yacute", "Ý" }, + { "Yuml", "Ÿ" }, + { "Zeta", "Ζ" }, + { "aacute", "á" }, + { "acirc", "â" }, + { "acute", "´" }, + { "aelig", "æ" }, + { "agrave", "à" }, + { "alefsym", "ℵ" }, + { "alpha", "α" }, + { "amp", "&" }, + { "and", "∧" }, + { "ang", "∠" }, + { "apos", "'" }, + { "aring", "å" }, + { "asymp", "≈" }, + { "atilde", "ã" }, + { "auml", "ä" }, + { "bdquo", "„" }, + { "beta", "β" }, + { "brvbar", "¦" }, + { "bull", "•" }, + { "cap", "∩" }, + { "ccedil", "ç" }, + { "cedil", "¸" }, + { "cent", "¢" }, + { "chi", "χ" }, + { "circ", "ˆ" }, + { "clubs", "♣" }, + { "cong", "≅" }, + { "copy", "©" }, + { "crarr", "↵" }, + { "cup", "∪" }, + { "curren", "¤" }, + { "dArr", "⇓" }, + { "dagger", "†" }, + { "darr", "↓" }, + { "deg", "°" }, + { "delta", "δ" }, + { "diams", "♦" }, + { "divide", "÷" }, + { "eacute", "é" }, + { "ecirc", "ê" }, + { "egrave", "è" }, + { "empty", "∅" }, + { "emsp", " " }, + { "ensp", " " }, + { "epsilon", "ε" }, + { "equiv", "≡" }, + { "eta", "η" }, + { "eth", "ð" }, + { "euml", "ë" }, + { "euro", "€" }, + { "exist", "∃" }, + { "fnof", "ƒ" }, + { "forall", "∀" }, + { "frac12", "½" }, + { "frac14", "¼" }, + { "frac34", "¾" }, + { "frasl", "⁄" }, + { "gamma", "γ" }, + { "ge", "≥" }, + { "gt", ">" }, + { "hArr", "⇔" }, + { "harr", "↔" }, + { "hearts", "♥" }, + { "hellip", "…" }, + { "iacute", "í" }, + { "icirc", "î" }, + { "iexcl", "¡" }, + { "igrave", "ì" }, + { "image", "ℑ" }, + { "infin", "∞" }, + { "int", "∫" }, + { "iota", "ι" }, + { "iquest", "¿" }, + { "isin", "∈" }, + { "iuml", "ï" }, + { "kappa", "κ" }, + { "lArr", "⇐" }, + { "lambda", "λ" }, + { "lang", "〈" }, + { "laquo", "«" }, + { "larr", "←" }, + { "lceil", "⌈" }, + { "ldquo", "“" }, + { "le", "≤" }, + { "lfloor", "⌊" }, + { "lowast", "∗" }, + { "loz", "◊" }, + { "lrm", "\xE2\x80\x8E" }, + { "lsaquo", "‹" }, + { "lsquo", "‘" }, + { "lt", "<" }, + { "macr", "¯" }, + { "mdash", "—" }, + { "micro", "µ" }, + { "middot", "·" }, + { "minus", "−" }, + { "mu", "μ" }, + { "nabla", "∇" }, + { "nbsp", " " }, + { "ndash", "–" }, + { "ne", "≠" }, + { "ni", "∋" }, + { "not", "¬" }, + { "notin", "∉" }, + { "nsub", "⊄" }, + { "ntilde", "ñ" }, + { "nu", "ν" }, + { "oacute", "ó" }, + { "ocirc", "ô" }, + { "oelig", "œ" }, + { "ograve", "ò" }, + { "oline", "‾" }, + { "omega", "ω" }, + { "omicron", "ο" }, + { "oplus", "⊕" }, + { "or", "∨" }, + { "ordf", "ª" }, + { "ordm", "º" }, + { "oslash", "ø" }, + { "otilde", "õ" }, + { "otimes", "⊗" }, + { "ouml", "ö" }, + { "para", "¶" }, + { "part", "∂" }, + { "permil", "‰" }, + { "perp", "⊥" }, + { "phi", "φ" }, + { "pi", "π" }, + { "piv", "ϖ" }, + { "plusmn", "±" }, + { "pound", "£" }, + { "prime", "′" }, + { "prod", "∏" }, + { "prop", "∝" }, + { "psi", "ψ" }, + { "quot", "\"" }, + { "rArr", "⇒" }, + { "radic", "√" }, + { "rang", "〉" }, + { "raquo", "»" }, + { "rarr", "→" }, + { "rceil", "⌉" }, + { "rdquo", "”" }, + { "real", "ℜ" }, + { "reg", "®" }, + { "rfloor", "⌋" }, + { "rho", "ρ" }, + { "rlm", "\xE2\x80\x8F" }, + { "rsaquo", "›" }, + { "rsquo", "’" }, + { "sbquo", "‚" }, + { "scaron", "š" }, + { "sdot", "⋅" }, + { "sect", "§" }, + { "shy", "\xC2\xAD" }, + { "sigma", "σ" }, + { "sigmaf", "ς" }, + { "sim", "∼" }, + { "spades", "♠" }, + { "sub", "⊂" }, + { "sube", "⊆" }, + { "sum", "∑" }, + { "sup", "⊃" }, + { "sup1", "¹" }, + { "sup2", "²" }, + { "sup3", "³" }, + { "supe", "⊇" }, + { "szlig", "ß" }, + { "tau", "τ" }, + { "there4", "∴" }, + { "theta", "θ" }, + { "thetasym", "ϑ" }, + { "thinsp", " " }, + { "thorn", "þ" }, + { "tilde", "˜" }, + { "times", "×" }, + { "trade", "™" }, + { "uArr", "⇑" }, + { "uacute", "ú" }, + { "uarr", "↑" }, + { "ucirc", "û" }, + { "ugrave", "ù" }, + { "uml", "¨" }, + { "upsih", "ϒ" }, + { "upsilon", "υ" }, + { "uuml", "ü" }, + { "weierp", "℘" }, + { "xi", "ξ" }, + { "yacute", "ý" }, + { "yen", "¥" }, + { "yuml", "ÿ" }, + { "zeta", "ζ" }, + { "zwj", "\xE2\x80\x8D" }, + { "zwnj", "\xE2\x80\x8C" } +}; + +CMStringW RemoveHtml(const CMStringW &data) +{ + CMStringW new_string; + + for (int i = 0; i < data.GetLength(); i++) { + wchar_t c = data[i]; + if (c == '<') { + i = data.Find('>', i); + if (i == -1) + break; + + continue; + } + + // special character + if (c == '&') { + int begin = i; + i = data.Find(';', i); + if (i == -1) + i = begin; + else { + CMStringW entity = data.Mid(begin + 1, i - begin - 1); + + bool found = false; + if (entity.GetLength() > 1 && entity[0] == '#') { + // Numeric replacement + bool hex = false; + if (entity[1] == 'x') { + hex = true; + entity.Delete(0, 2); + } + else entity.Delete(0, 1); + + if (!entity.IsEmpty()) { + found = true; + errno = 0; + unsigned long value = wcstoul(entity, nullptr, hex ? 16 : 10); + if (errno != 0) { // error with conversion in strtoul, ignore the result + found = false; + } + else if (value <= 127) { // U+0000 .. U+007F + new_string += (char)value; + } + else if (value >= 128 && value <= 2047) { // U+0080 .. U+07FF + new_string += (char)(192 + (value / 64)); + new_string += (char)(128 + (value % 64)); + } + else if (value >= 2048 && value <= 65535) { // U+0800 .. U+FFFF + new_string += (char)(224 + (value / 4096)); + new_string += (char)(128 + ((value / 64) % 64)); + new_string += (char)(128 + (value % 64)); + } + else { + new_string += (char)((value >> 24) & 0xFF); + new_string += (char)((value >> 16) & 0xFF); + new_string += (char)((value >> 8) & 0xFF); + new_string += (char)((value) & 0xFF); + } + } + } + else { + // Keyword replacement + CMStringA tmp = entity; + for (auto &it : htmlEntities) { + if (!mir_strcmpi(tmp, it.entity)) { + new_string += it.symbol; + found = true; + break; + } + } + } + + if (found) + continue; + else + i = begin; + } + } + + new_string.AppendChar(c); + } + + return new_string; +} + +const char* CSkypeProto::MirandaToSkypeStatus(int status) +{ + switch (status) { + case ID_STATUS_AWAY: + return "Away"; + + case ID_STATUS_DND: + return "Busy"; + + case ID_STATUS_IDLE: + return "Idle"; + + case ID_STATUS_INVISIBLE: + return "Hidden"; + } + return "Online"; +} + +int CSkypeProto::SkypeToMirandaStatus(const char *status) +{ + if (!mir_strcmpi(status, "Online")) + return ID_STATUS_ONLINE; + else if (!mir_strcmpi(status, "Hidden")) + return ID_STATUS_INVISIBLE; + else if (!mir_strcmpi(status, "Away")) + return ID_STATUS_AWAY; + else if (!mir_strcmpi(status, "Idle")) + return ID_STATUS_AWAY; + else if (!mir_strcmpi(status, "Busy")) + return ID_STATUS_DND; + else + return ID_STATUS_OFFLINE; +} + +bool CSkypeProto::IsFileExists(std::wstring path) +{ + return _waccess(path.c_str(), 0) == 0; +} + +const char* GetSkypeNick(const char *szSkypeId) +{ + if (auto *p = strchr(szSkypeId, ':')) + return p + 1; + return szSkypeId; +} + +const wchar_t* GetSkypeNick(const wchar_t *szSkypeId) +{ + if (auto *p = wcsrchr(szSkypeId, ':')) + return p + 1; + return szSkypeId; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// url parsing + +CMStringA ParseUrl(const char *url, const char *token) +{ + if (url == nullptr) + return CMStringA(); + + auto *start = strstr(url, token); + if (start == nullptr) + return CMStringA(); + + auto *end = strchr(++start, '/'); + if (end == nullptr) + return CMStringA(start); + return CMStringA(start, end - start); +} + +CMStringW ParseUrl(const wchar_t *url, const wchar_t *token) +{ + if (url == nullptr) + return CMStringW(); + + auto *start = wcsstr(url, token); + if (start == nullptr) + return CMStringW(); + + auto *end = wcschr(++start, '/'); + if (end == nullptr) + return CMStringW(start); + return CMStringW(start, end - start); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int possibleTypes[] = { 1, 2, 8, 19 }; + +CMStringA UrlToSkypeId(const char *url, int *pUserType) +{ + int userType = -1; + CMStringA szResult; + + if (url != nullptr) { + for (auto &it : possibleTypes) { + char tmp[10]; + sprintf_s(tmp, "/%d:", it); + if (strstr(url, tmp)) { + userType = it; + szResult = ParseUrl(url, tmp); + break; + } + } + } + + if (pUserType) + *pUserType = userType; + + return szResult; +} + +CMStringW UrlToSkypeId(const wchar_t *url, int *pUserType) +{ + int userType = -1; + CMStringW szResult; + + if (url != nullptr) { + for (auto &it : possibleTypes) { + wchar_t tmp[10]; + swprintf_s(tmp, L"/%d:", it); + if (wcsstr(url, tmp)) { + userType = it; + szResult = ParseUrl(url, tmp); + break; + } + } + } + + if (pUserType) + *pUserType = userType; + + return szResult; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR CSkypeProto::ParseSkypeUriService(WPARAM, LPARAM lParam) +{ + wchar_t *arg = (wchar_t *)lParam; + if (arg == nullptr) + return 1; + + // skip leading prefix + wchar_t szUri[1024]; + wcsncpy_s(szUri, arg, _TRUNCATE); + wchar_t *szJid = wcschr(szUri, ':'); + if (szJid == nullptr) + return 1; + + // empty jid? + if (!*szJid) + return 1; + + // command code + wchar_t *szCommand = szJid; + szCommand = wcschr(szCommand, '?'); + if (szCommand) + *(szCommand++) = 0; + + // parameters + wchar_t *szSecondParam = szCommand ? wcschr(szCommand, '&') : nullptr; + if (szSecondParam) + *(szSecondParam++) = 0; + + // no command or message command + if (!szCommand || !mir_wstrcmpi(szCommand, L"chat")) { + if (szSecondParam) { + wchar_t *szChatId = wcsstr(szSecondParam, L"id="); + if (szChatId) { + szChatId += 5; + StartChatRoom(szChatId, szChatId); + return 0; + } + } + MCONTACT hContact = AddContact(_T2A(szJid), nullptr, true); + CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, NULL); + return 0; + } + + if (!mir_wstrcmpi(szCommand, L"call")) { + MCONTACT hContact = AddContact(_T2A(szJid), nullptr, true); + NotifyEventHooks(g_hCallEvent, (WPARAM)hContact, (LPARAM)0); + return 0; + } + + if (!mir_wstrcmpi(szCommand, L"userinfo")) + return 0; + + if (!mir_wstrcmpi(szCommand, L"add")) { + MCONTACT hContact = FindContact(_T2A(szJid)); + if (hContact == NULL) { + PROTOSEARCHRESULT psr = { 0 }; + psr.cbSize = sizeof(psr); + psr.id.w = mir_wstrdup(szJid); + psr.nick.w = mir_wstrdup(szJid); + psr.flags = PSR_UNICODE; + Contact::AddBySearch(m_szModuleName, &psr); + } + return 0; + } + + if (!mir_wstrcmpi(szCommand, L"sendfile")) { + MCONTACT hContact = AddContact(_T2A(szJid), nullptr, true); + CallService(MS_FILE_SENDFILE, hContact, NULL); + return 1; + } + + if (!mir_wstrcmpi(szCommand, L"voicemail")) + return 1; + + return 1; +} + +INT_PTR CSkypeProto::GlobalParseSkypeUriService(WPARAM wParam, LPARAM lParam) +{ + for (auto &it : CMPlugin::g_arInstances) + if (it->IsOnline()) + return it->ParseSkypeUriService(wParam, lParam); + + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) +{ + if (pReply == nullptr) { + m_errorCode = 500; + return; + } + + m_errorCode = pReply->resultCode; + if (m_errorCode != 200) + return; + + m_root = json_parse(pReply->pData); + if (m_root == nullptr) { + m_errorCode = 500; + return; + } + + m_errorCode = (*m_root)["status"]["code"].as_int(); +} + +JsonReply::~JsonReply() +{ + json_delete(m_root); +} diff --git a/protocols/SkypeWeb/src/skype_utils.h b/protocols/SkypeWeb/src/skype_utils.h index 6234abf8b6..e8a1f05836 100644 --- a/protocols/SkypeWeb/src/skype_utils.h +++ b/protocols/SkypeWeb/src/skype_utils.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/stdafx.cxx b/protocols/SkypeWeb/src/stdafx.cxx index f64d25234b..ebbde0ade1 100644 --- a/protocols/SkypeWeb/src/stdafx.cxx +++ b/protocols/SkypeWeb/src/stdafx.cxx @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +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 diff --git a/protocols/SkypeWeb/src/stdafx.h b/protocols/SkypeWeb/src/stdafx.h index 059d5cb9d6..6dbb1da1c3 100644 --- a/protocols/SkypeWeb/src/stdafx.h +++ b/protocols/SkypeWeb/src/stdafx.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-22 Miranda NG team (https://miranda-ng.org) +Copyright (c) 2015-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 diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h index b41d65df1e..991de1af6d 100644 --- a/protocols/SkypeWeb/src/version.h +++ b/protocols/SkypeWeb/src/version.h @@ -10,4 +10,4 @@ #define __DESCRIPTION "Skype protocol support for Miranda NG. Based on new Skype for Web." #define __AUTHOR "Miranda NG team" #define __AUTHORWEB "https://miranda-ng.org/p/SkypeWeb" -#define __COPYRIGHT "© 2015-22 Miranda NG team" +#define __COPYRIGHT "© 2015-23 Miranda NG team" -- cgit v1.2.3