From e84083c4ba1f1e68b0bc76939f2d0902d3c03c9e Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 4 Oct 2022 21:19:07 +0300 Subject: decoding messages - beginning --- protocols/WhatsAppWeb/src/iq.cpp | 108 +++++++++++++++++++++++++++++++++++- protocols/WhatsAppWeb/src/proto.cpp | 1 + protocols/WhatsAppWeb/src/proto.h | 25 +++++++++ protocols/WhatsAppWeb/src/utils.cpp | 26 ++++++++- protocols/WhatsAppWeb/src/utils.h | 5 ++ 5 files changed, 161 insertions(+), 4 deletions(-) (limited to 'protocols/WhatsAppWeb') diff --git a/protocols/WhatsAppWeb/src/iq.cpp b/protocols/WhatsAppWeb/src/iq.cpp index cf55f9cfd4..9c32103016 100644 --- a/protocols/WhatsAppWeb/src/iq.cpp +++ b/protocols/WhatsAppWeb/src/iq.cpp @@ -7,6 +7,17 @@ Copyright © 2019-22 George Hazan #include "stdafx.h" +void WhatsAppProto::OnAccountSync(const WANode &node) +{ + m_arDevices.destroy(); + + for (auto &it : node.getChild("devices")->getChildren()) + if (it->title == "device") + m_arDevices.insert(new WADevice(it->getAttr("jid"), it->getAttrInt("key-index"))); +} + +///////////////////////////////////////////////////////////////////////////////////////// + void WhatsAppProto::OnIqBlockList(const WANode &node) { for (auto &it : node.getChild("list")->getChildren()) { @@ -71,6 +82,98 @@ void WhatsAppProto::OnIqDoNothing(const WANode &) ///////////////////////////////////////////////////////////////////////////////////////// +void WhatsAppProto::OnReceiveMessage(const WANode &node) +{ + auto *msgId = node.getAttr("id"); + auto *msgType = node.getAttr("type"); + auto *msgFrom = node.getAttr("from"); + auto *recepient = node.getAttr("recepient"); + auto *participant = node.getAttr("participant"); + + if (msgType == nullptr || msgFrom == nullptr || msgId == nullptr) { + debugLogA("bad message received: <%s> <%s> <%s>", msgType, msgFrom, msgId); + return; + } + + WAMSG type; + WAJid jid(msgFrom); + CMStringA szAuthor, szChatId; + + // message from one user to another + if (jid.isUser()) { + if (recepient) { + if (m_szJid != msgFrom) { + debugLogA("strange message: with recepient, but not from me"); + return; + } + szChatId = recepient; + } + else szChatId = msgFrom; + + type = WAMSG::Chat; + szAuthor = msgFrom; + } + else if (jid.isGroup()) { + if (!participant) { + debugLogA("strange message: from group, but without participant"); + return; + } + + type = WAMSG::GroupChat; + szAuthor = participant; + szChatId = msgFrom; + } + else if (jid.isBroadcast()) { + if (!participant) { + debugLogA("strange message: from group, but without participant"); + return; + } + + bool bIsMe = m_szJid == participant; + if (jid.isStatusBroadcast()) + type = (bIsMe) ? WAMSG::DirectStatus : WAMSG::OtherStatus; + else + type = (bIsMe) ? WAMSG::PeerBroadcast : WAMSG::OtherBroadcast; + szChatId = msgFrom; + szAuthor = participant; + } + else { + debugLogA("invalid message type"); + return; + } + + CMStringA szSender = (type == WAMSG::Chat) ? szAuthor : szChatId; + bool bFromMe = (m_szJid == msgFrom); + if (!bFromMe && participant) + bFromMe = m_szJid == participant; + + auto *pKey = new proto::MessageKey(); + pKey->set_participant(participant); + pKey->set_remotejid(szChatId); + pKey->set_id(msgId); + pKey->set_fromme(bFromMe); + + proto::WebMessageInfo msg; + msg.set_allocated_key(pKey); + msg.set_messagetimestamp(_atoi64(node.getAttr("t"))); + msg.set_pushname(node.getAttr("notify")); + if (bFromMe) + msg.set_status(proto::WebMessageInfo_Status_SERVER_ACK); + + if (auto *pEnc = node.getChild("enc")) { + int iVer = pEnc->getAttrInt("v"); + auto *pszType = pEnc->getAttr("type"); + if (iVer == 2 && !mir_strcmp(pszType, "pkmsg")) { + proto::Message msg; + if (msg.ParseFromArray(pEnc->content.data(), (int)pEnc->content.length())) { + int i = 0; + } + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + void WhatsAppProto::OnStreamError(const WANode &node) { m_bTerminated = true; @@ -381,8 +484,11 @@ void WhatsAppProto::InitPersistentHandlers() { m_arPersistent.insert(new WAPersistentHandler("iq", "set", "md", "pair-device", &WhatsAppProto::OnIqPairDevice)); m_arPersistent.insert(new WAPersistentHandler("iq", "set", "md", "pair-success", &WhatsAppProto::OnIqPairSuccess)); - m_arPersistent.insert(new WAPersistentHandler(0, "result", 0, 0, &WhatsAppProto::OnIqResult)); + m_arPersistent.insert(new WAPersistentHandler("message", 0, 0, 0, &WhatsAppProto::OnReceiveMessage)); + m_arPersistent.insert(new WAPersistentHandler("notification", "account_sync", 0, 0, &WhatsAppProto::OnAccountSync)); m_arPersistent.insert(new WAPersistentHandler("stream:error", 0, 0, 0, &WhatsAppProto::OnStreamError)); m_arPersistent.insert(new WAPersistentHandler("success", 0, 0, 0, &WhatsAppProto::OnSuccess)); + + m_arPersistent.insert(new WAPersistentHandler(0, "result", 0, 0, &WhatsAppProto::OnIqResult)); } diff --git a/protocols/WhatsAppWeb/src/proto.cpp b/protocols/WhatsAppWeb/src/proto.cpp index 1aa6117446..4ba2d8bf7f 100644 --- a/protocols/WhatsAppWeb/src/proto.cpp +++ b/protocols/WhatsAppWeb/src/proto.cpp @@ -33,6 +33,7 @@ WhatsAppProto::WhatsAppProto(const char *proto_name, const wchar_t *username) : m_szJid(getMStringA(DBKEY_JID)), m_tszDefaultGroup(getWStringA(DBKEY_DEF_GROUP)), m_arUsers(10, CompareUsers), + m_arDevices(1), m_arOwnMsgs(1, CompareOwnMsgs), m_arPersistent(1), m_arPacketQueue(10), diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h index 137c42e60e..2ff8731eb9 100644 --- a/protocols/WhatsAppWeb/src/proto.h +++ b/protocols/WhatsAppWeb/src/proto.h @@ -15,6 +15,16 @@ Copyright class WhatsAppProto; typedef void (WhatsAppProto:: *WA_PKT_HANDLER)(const WANode &node); +enum WAMSG +{ + Chat, + GroupChat, + DirectStatus, + OtherStatus, + PeerBroadcast, + OtherBroadcast +}; + struct WARequest { WARequest(const CMStringA &_1, WA_PKT_HANDLER _2, void *_3 = nullptr) : @@ -28,6 +38,17 @@ struct WARequest void *pUserInfo; }; +struct WADevice +{ + WADevice(const char *_1, int _2) : + jid(_1), + key_index(_2) + {} + + WAJid jid; + int key_index; +}; + struct WAPersistentHandler { WAPersistentHandler(const char *_1, const char *_2, const char *_3, const char *_4, WA_PKT_HANDLER _5) : @@ -158,6 +179,8 @@ class WhatsAppProto : public PROTO mir_cs m_csOwnMessages; OBJLIST m_arOwnMsgs; + OBJLIST m_arDevices; + WAUser* FindUser(const char *szId); WAUser* AddUser(const char *szId, bool bTemporary); @@ -214,12 +237,14 @@ class WhatsAppProto : public PROTO void OnProcessHandshake(const void *pData, int cbLen); void InitPersistentHandlers(); + void OnAccountSync(const WANode &node); void OnIqBlockList(const WANode &node); void OnIqCountPrekeys(const WANode &node); void OnIqDoNothing(const WANode &node); void OnIqPairDevice(const WANode &node); void OnIqPairSuccess(const WANode &node); void OnIqResult(const WANode &node); + void OnReceiveMessage(const WANode &node); void OnStreamError(const WANode &node); void OnSuccess(const WANode &node); diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp index 509f277f49..3f20216b13 100644 --- a/protocols/WhatsAppWeb/src/utils.cpp +++ b/protocols/WhatsAppWeb/src/utils.cpp @@ -41,6 +41,24 @@ WAJid::WAJid(const char *pszJid) 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); @@ -352,7 +370,7 @@ MBinBuffer WhatsAppProto::unzip(const MBinBuffer &src) z_stream strm = {}; inflateInit(&strm); - strm.avail_in = src.length(); + strm.avail_in = (uInt)src.length(); strm.next_in = (Bytef *)src.data(); MBinBuffer res; @@ -365,11 +383,13 @@ MBinBuffer WhatsAppProto::unzip(const MBinBuffer &src) int ret = inflate(&strm, Z_NO_FLUSH); switch (ret) { case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ + ret = Z_DATA_ERROR; + __fallthrough; + case Z_DATA_ERROR: case Z_MEM_ERROR: inflateEnd(&strm); - return ret; + return res; } res.append(buf, sizeof(buf) - strm.avail_out); diff --git a/protocols/WhatsAppWeb/src/utils.h b/protocols/WhatsAppWeb/src/utils.h index ae97df0bfe..d3adfb3dc7 100644 --- a/protocols/WhatsAppWeb/src/utils.h +++ b/protocols/WhatsAppWeb/src/utils.h @@ -157,6 +157,11 @@ struct WAJid WAJid(const char *pszUser, const char *pszServer, int device = 0, int agent = 0); CMStringA toString() const; + + bool isUser() const; + bool isGroup() const; + bool isBroadcast() const; + bool isStatusBroadcast() const; }; ///////////////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3