summaryrefslogtreecommitdiff
path: root/protocols/WhatsAppWeb
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-10-04 21:19:07 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-10-04 21:19:07 +0300
commite84083c4ba1f1e68b0bc76939f2d0902d3c03c9e (patch)
tree311c9d51520a47882ae502aa173d69fe64fc73e6 /protocols/WhatsAppWeb
parentff768b032e5c96b546a0f66a98b0555845bd8217 (diff)
decoding messages - beginning
Diffstat (limited to 'protocols/WhatsAppWeb')
-rw-r--r--protocols/WhatsAppWeb/src/iq.cpp108
-rw-r--r--protocols/WhatsAppWeb/src/proto.cpp1
-rw-r--r--protocols/WhatsAppWeb/src/proto.h25
-rw-r--r--protocols/WhatsAppWeb/src/utils.cpp26
-rw-r--r--protocols/WhatsAppWeb/src/utils.h5
5 files changed, 161 insertions, 4 deletions
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 © 2019-22 George Hazan
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<WhatsAppProto>
mir_cs m_csOwnMessages;
OBJLIST<WAOwnMessage> m_arOwnMsgs;
+ OBJLIST<WADevice> m_arDevices;
+
WAUser* FindUser(const char *szId);
WAUser* AddUser(const char *szId, bool bTemporary);
@@ -214,12 +237,14 @@ class WhatsAppProto : public PROTO<WhatsAppProto>
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;
};
/////////////////////////////////////////////////////////////////////////////////////////