summaryrefslogtreecommitdiff
path: root/protocols/WhatsAppWeb/src/utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/WhatsAppWeb/src/utils.cpp')
-rw-r--r--protocols/WhatsAppWeb/src/utils.cpp373
1 files changed, 0 insertions, 373 deletions
diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp
deleted file mode 100644
index c176a894fe..0000000000
--- a/protocols/WhatsAppWeb/src/utils.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
-
-WhatsAppWeb plugin for Miranda NG
-Copyright © 2019-22 George Hazan
-
-*/
-
-#include "stdafx.h"
-
-WAJid::WAJid(const char *pszUser, const char *pszServer, int iDevice, int iAgent) :
- user(pszUser ? pszUser : ""),
- server(pszServer ? pszServer : ""),
- device(iDevice),
- agent(iAgent)
-{}
-
-WAJid::WAJid(const char *pszJid)
-{
- if (pszJid == nullptr)
- pszJid = "";
-
- auto *tmp = NEWSTR_ALLOCA(pszJid);
- auto *p = strrchr(tmp, '@');
- if (p) {
- *p = 0;
- server = p + 1;
- }
-
- if (p = strrchr(tmp, ':')) {
- *p = 0;
- device = atoi(p + 1);
- }
- else device = 0;
-
- if (p = strrchr(tmp, '_')) {
- *p = 0;
- agent = atoi(p + 1);
- }
- else agent = 0;
-
- user = tmp;
-}
-
-bool WAJid::isUser() const
-{ return server == "s.whatsapp.net";
-}
-
-bool WAJid::isGroup() const
-{ return server == "g.us";
-}
-
-bool WAJid::isBroadcast() const
-{
- return server == "broadcast";
-}
-
-bool WAJid::isStatusBroadcast() const
-{
- return isBroadcast() && user == "status";
-}
-
-CMStringA WAJid::toString() const
-{
- CMStringA ret(user);
- if (agent > 0)
- ret.AppendFormat("_%d", agent);
- if (device > 0)
- ret.AppendFormat(":%d", device);
- ret.AppendFormat("@%s", server.c_str());
- return ret;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-WAUser* WhatsAppProto::FindUser(const char *szId)
-{
- mir_cslock lck(m_csUsers);
- auto *tmp = (WAUser *)_alloca(sizeof(WAUser));
- tmp->szId = (char*)szId;
- return m_arUsers.find(tmp);
-}
-
-WAUser* WhatsAppProto::AddUser(const char *szId, bool bTemporary, bool isChat)
-{
- auto *pUser = FindUser(szId);
- if (pUser != nullptr)
- return pUser;
-
- MCONTACT hContact = db_add_contact();
- Proto_AddToContact(hContact, m_szModuleName);
-
- if (isChat) {
- setByte(hContact, "ChatRoom", 1);
- setString(hContact, "ChatRoomID", szId);
- }
- else {
- setString(hContact, DBKEY_JID, szId);
- if (m_wszDefaultGroup)
- Clist_SetGroup(hContact, m_wszDefaultGroup);
- }
-
- if (bTemporary)
- Contact::RemoveFromList(hContact);
-
- pUser = new WAUser(hContact, mir_strdup(szId));
- pUser->bIsGroupChat = isChat;
-
- mir_cslock lck(m_csUsers);
- m_arUsers.insert(pUser);
- return pUser;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-WA_PKT_HANDLER WhatsAppProto::FindPersistentHandler(const WANode &pNode)
-{
- auto *pChild = pNode.getFirstChild();
- CMStringA szChild = (pChild) ? pChild->title : "";
- CMStringA szTitle = pNode.title;
- CMStringA szType = pNode.getAttr("type");
- CMStringA szXmlns = pNode.getAttr("xmlns");
-
- for (auto &it : m_arPersistent) {
- if (it->pszTitle && szTitle != it->pszTitle)
- continue;
- if (it->pszType && szType != it->pszType)
- continue;
- if (it->pszXmlns && szXmlns != it->pszXmlns)
- continue;
- if (it->pszChild && szChild != it->pszChild)
- continue;
- return it->pHandler;
- }
-
- return nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-CMStringA WhatsAppProto::GenerateMessageId()
-{
- return CMStringA(FORMAT, "%d.%d-%d", m_wMsgPrefix[0], m_wMsgPrefix[1], m_iPacketId++);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// sends a piece of JSON to a server via a websocket, masked
-
-int WhatsAppProto::WSSend(const MessageLite &msg)
-{
- if (m_hServerConn == nullptr)
- return -1;
-
- int cbLen = msg.ByteSize();
- ptrA protoBuf((char *)mir_alloc(cbLen));
- msg.SerializeToArray(protoBuf, cbLen);
-
- Netlib_Dump(m_hServerConn, protoBuf, cbLen, true, 0);
-
- MBinBuffer payload = m_noise->encodeFrame(protoBuf, cbLen);
- WebSocket_SendBinary(m_hServerConn, payload.data(), payload.length());
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static char zeroData[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-int WhatsAppProto::WSSendNode(WANode &node, WA_PKT_HANDLER pHandler)
-{
- if (m_hServerConn == nullptr)
- return 0;
-
- if (pHandler != nullptr) {
- CMStringA id(GenerateMessageId());
- node.addAttr("id", id);
-
- mir_cslock lck(m_csPacketQueue);
- m_arPacketQueue.insert(new WARequest(id, pHandler));
- }
-
- CMStringA szText;
- node.print(szText);
- debugLogA("Sending binary node:\n%s", szText.c_str());
-
- WAWriter writer;
- writer.writeNode(&node);
-
- MBinBuffer encData = m_noise->encrypt(writer.body.data(), writer.body.length());
- MBinBuffer payload = m_noise->encodeFrame(encData.data(), encData.length());
- WebSocket_SendBinary(m_hServerConn, payload.data(), payload.length());
- return 1;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-uint32_t decodeBigEndian(const std::string &buf)
-{
- uint32_t ret = 0;
- for (auto &cc : buf) {
- ret <<= 8;
- ret += (uint8_t)cc;
- }
-
- return ret;
-}
-
-std::string encodeBigEndian(uint32_t num, size_t len)
-{
- std::string res;
- for (int i = 0; i < len; i++) {
- char c = num & 0xFF;
- res = c + res;
- num >>= 8;
- }
- return res;
-}
-
-void generateIV(uint8_t *iv, int &pVar)
-{
- auto counter = encodeBigEndian(pVar);
- memset(iv, 0, sizeof(iv));
- memcpy(iv + 8, counter.c_str(), sizeof(int));
-
- pVar++;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Popups
-
-void WhatsAppProto::InitPopups(void)
-{
- g_plugin.addPopupOption(CMStringW(FORMAT, TranslateT("%s error notifications"), m_tszUserName), m_bUsePopups);
-
- char name[256];
- mir_snprintf(name, "%s_%s", m_szModuleName, "Error");
-
- wchar_t desc[256];
- mir_snwprintf(desc, L"%s/%s", m_tszUserName, TranslateT("Errors"));
-
- POPUPCLASS ppc = {};
- ppc.flags = PCF_UNICODE;
- ppc.pszName = name;
- ppc.pszDescription.w = desc;
- ppc.hIcon = IcoLib_GetIconByHandle(m_hProtoIcon);
- ppc.colorBack = RGB(191, 0, 0); //Red
- ppc.colorText = RGB(255, 245, 225); //Yellow
- ppc.iSeconds = 60;
- m_hPopupClass = Popup_RegisterClass(&ppc);
-
- IcoLib_ReleaseIcon(ppc.hIcon);
-}
-
-void WhatsAppProto::Popup(MCONTACT hContact, const wchar_t *szMsg, const wchar_t *szTitle)
-{
- if (!m_bUsePopups)
- return;
-
- char name[256];
- mir_snprintf(name, "%s_%s", m_szModuleName, "Error");
-
- CMStringW wszTitle(szTitle);
- if (hContact == 0) {
- wszTitle.Insert(0, L": ");
- wszTitle.Insert(0, m_tszUserName);
- }
-
- POPUPDATACLASS ppd = {};
- ppd.szTitle.w = wszTitle;
- ppd.szText.w = szMsg;
- ppd.pszClassName = name;
- ppd.hContact = hContact;
- Popup_AddClass(&ppd);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MBinBuffer WhatsAppProto::unzip(const MBinBuffer &src)
-{
- z_stream strm = {};
- inflateInit(&strm);
-
- strm.avail_in = (uInt)src.length();
- strm.next_in = (Bytef *)src.data();
-
- MBinBuffer res;
- Bytef buf[2048];
-
- while (strm.avail_in > 0) {
- strm.avail_out = sizeof(buf);
- strm.next_out = buf;
-
- int ret = inflate(&strm, Z_NO_FLUSH);
- switch (ret) {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- __fallthrough;
-
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- inflateEnd(&strm);
- return res;
- }
-
- res.append(buf, sizeof(buf) - strm.avail_out);
- }
-
- inflateEnd(&strm);
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void bin2file(const MBinBuffer &buf, const wchar_t *pwszFileName)
-{
- int fileId = _wopen(pwszFileName, _O_WRONLY | _O_TRUNC | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE);
- if (fileId != -1) {
- write(fileId, buf.data(), (unsigned)buf.length());
- close(fileId);
- }
-}
-
-void string2file(const std::string &str, const wchar_t *pwszFileName)
-{
- int fileId = _wopen(pwszFileName, _O_WRONLY | _O_TRUNC | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE);
- if (fileId != -1) {
- write(fileId, str.c_str(), (unsigned)str.size());
- close(fileId);
- }
-}
-
-CMStringA directPath2url(const char *pszDirectPath)
-{
- return CMStringA("https://mmg.whatsapp.net") + pszDirectPath;
-}
-
-MBinBuffer WhatsAppProto::DownloadEncryptedFile(const char *url, const std::string &mediaKeys, const char *pszMediaType)
-{
- NETLIBHTTPHEADER headers[1] = {{"Origin", "https://web.whatsapp.com"}};
-
- NETLIBHTTPREQUEST req = {};
- req.cbSize = sizeof(req);
- req.requestType = REQUEST_GET;
- req.szUrl = (char*)url;
- req.headersCount = _countof(headers);
- req.headers = headers;
-
- MBinBuffer ret;
- auto *pResp = Netlib_HttpTransaction(m_hNetlibUser, &req);
- if (pResp) {
- if (pResp->resultCode == 200) {
- CMStringA pszHkdfString = pszMediaType;
- pszHkdfString.SetAt(_toupper(pszHkdfString[0]), 0);
- pszHkdfString = "WhatsApp " + pszHkdfString + " Keys";
-
- // 0 - 15: iv
- // 16 - 47: cipherKey
- // 48 - 111: macKey
- uint8_t out[112];
- HKDF(EVP_sha256(), (BYTE *)"", 0, (BYTE *)mediaKeys.c_str(), (int)mediaKeys.size(), (BYTE *)pszHkdfString.c_str(), pszHkdfString.GetLength(), out, sizeof(out));
-
- ret = aesDecrypt(EVP_aes_256_cbc(), out + 16, out, pResp->pData, pResp->dataLength);
- }
- }
-
- return ret;
-}
-
-CMStringW WhatsAppProto::GetTmpFileName(const char *pszClass, const char *pszAddition)
-{
- CMStringW ret(VARSW(L"%miranda_userdata%"));
- ret.AppendFormat(L"/%S/%S_%S", m_szModuleName, pszClass, pszAddition);
- return ret;
-}