diff options
Diffstat (limited to 'protocols/WhatsAppWeb/src/iq.cpp')
-rw-r--r-- | protocols/WhatsAppWeb/src/iq.cpp | 709 |
1 files changed, 0 insertions, 709 deletions
diff --git a/protocols/WhatsAppWeb/src/iq.cpp b/protocols/WhatsAppWeb/src/iq.cpp deleted file mode 100644 index 4f74567f0c..0000000000 --- a/protocols/WhatsAppWeb/src/iq.cpp +++ /dev/null @@ -1,709 +0,0 @@ -/* - -WhatsAppWeb plugin for Miranda NG -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()) { - auto *pUser = AddUser(it->getAttr("jid"), false); - Contact::Hide(pUser->hContact); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnIqCountPrekeys(const WANode &node) -{ - int iCount = node.getChild("count")->getAttrInt("value"); - if (iCount < 5) - UploadMorePrekeys(); -} - -void WhatsAppProto::UploadMorePrekeys() -{ - WANodeIq iq(IQ::SET, "encrypt"); - - auto regId = encodeBigEndian(getDword(DBKEY_REG_ID)); - iq.addChild("registration")->content.append(regId.c_str(), regId.size()); - - iq.addChild("type")->content.append(KEY_BUNDLE_TYPE, 1); - iq.addChild("identity")->content.append(m_signalStore.signedIdentity.pub); - - const int PORTION = 10; - m_signalStore.generatePrekeys(PORTION); - - int iStart = getDword(DBKEY_PREKEY_UPLOAD_ID, 1); - auto *n = iq.addChild("list"); - for (int i = 0; i < PORTION; i++) { - auto *nKey = n->addChild("key"); - - int keyId = iStart + i; - auto encId = encodeBigEndian(keyId, 3); - nKey->addChild("id")->content.append(encId.c_str(), encId.size()); - nKey->addChild("value")->content.append(getBlob(CMStringA(FORMAT, "PreKey%dPublic", keyId))); - } - setDword(DBKEY_PREKEY_UPLOAD_ID, iStart + PORTION); - - auto *skey = iq.addChild("skey"); - - auto encId = encodeBigEndian(m_signalStore.preKey.keyid, 3); - skey->addChild("id")->content.append(encId.c_str(), encId.size()); - skey->addChild("value")->content.append(m_signalStore.preKey.pub); - skey->addChild("signature")->content.append(m_signalStore.preKey.signature); - - WSSendNode(iq, &WhatsAppProto::OnIqDoNothing); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnIqDoNothing(const WANode &) -{ -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnNotifyEncrypt(const WANode &node) -{ - auto *pszFrom = node.getAttr("from"); - if (!mir_strcmp(pszFrom, S_WHATSAPP_NET)) { - - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnReceiveInfo(const WANode &node) -{ - if (auto *pChild = node.getFirstChild()) { - if (pChild->title == "offline") - debugLogA("Processed %d offline events", pChild->getAttrInt("count")); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnReceiveMessage(const WANode &node) -{ - auto *msgId = node.getAttr("id"); - auto *msgType = node.getAttr("type"); - auto *msgFrom = node.getAttr("from"); - auto *category = node.getAttr("category"); - auto *recipient = node.getAttr("recipient"); - 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; - - if (node.getAttr("offline")) - type.bOffline = true; - - // message from one user to another - if (jid.isUser()) { - if (recipient) { - if (m_szJid != msgFrom) { - debugLogA("strange message: with recipient, but not from me"); - return; - } - szChatId = recipient; - } - else szChatId = msgFrom; - - type.bPrivateChat = true; - szAuthor = msgFrom; - } - else if (jid.isGroup()) { - if (!participant) { - debugLogA("strange message: from group, but without participant"); - return; - } - - type.bGroupChat = true; - 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()) { - if (bIsMe) - type.bDirectStatus = true; - else - type.bOtherStatus = true; - } - else { - if (bIsMe) - type.bPeerBroadcast = true; - else - type.bOtherBroadcast = true; - } - szChatId = msgFrom; - szAuthor = participant; - } - else { - debugLogA("invalid message type"); - return; - } - - CMStringA szSender = (type.bPrivateChat) ? szAuthor : szChatId; - bool bFromMe = (m_szJid == msgFrom); - if (!bFromMe && participant) - bFromMe = m_szJid == participant; - - auto *pKey = new proto::MessageKey(); - pKey->set_remotejid(szChatId); - pKey->set_id(msgId); - pKey->set_fromme(bFromMe); - if (participant) - pKey->set_participant(participant); - - 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); - - int iDecryptable = 0; - - for (auto &it: node.getChildren()) { - if (it->title == "verified_name") { - proto::VerifiedNameCertificate cert; - cert << it->content; - - proto::VerifiedNameCertificate::Details details; - details.ParseFromString(cert.details()); - - msg.set_verifiedbizname(details.verifiedname()); - continue; - } - - if (it->title != "enc" || it->content.length() == 0) - continue; - - SignalBuffer msgBody; - auto *pszType = it->getAttr("type"); - try { - if (!mir_strcmp(pszType, "pkmsg") || !mir_strcmp(pszType, "msg")) { - CMStringA szUser = (WAJid(szSender).isUser()) ? szSender : szAuthor; - msgBody = m_signalStore.decryptSignalProto(szUser, pszType, it->content); - } - else if (!mir_strcmp(pszType, "skmsg")) { - msgBody = m_signalStore.decryptGroupSignalProto(szSender, szAuthor, it->content); - } - else throw "Invalid e2e type"; - - if (!msgBody) - throw "Invalid e2e message"; - - iDecryptable++; - - // remove message padding - if (size_t len = msgBody.len()) { - size_t c = msgBody.data()[len - 1]; - if (c < len) - msgBody.reset(len - c); - } - - proto::Message encMsg; - encMsg.ParseFromArray(msgBody.data(), msgBody.len()); - if (encMsg.devicesentmessage().has_message()) - msg.set_allocated_message(new proto::Message(encMsg.devicesentmessage().message())); - else - msg.set_allocated_message(new proto::Message(encMsg)); - - if (encMsg.has_senderkeydistributionmessage()) - m_signalStore.processSenderKeyMessage(encMsg.senderkeydistributionmessage()); - - ProcessMessage(type, msg); - msg.clear_message(); - - // send receipt - const char *pszReceiptType = nullptr, *pszReceiptTo = participant; - if (!mir_strcmp(category, "peer")) - pszReceiptType = "peer_msg"; - else if (bFromMe) { - // message was sent by me from a different device - pszReceiptType = "sender"; - if (WAJid(szChatId).isUser()) - pszReceiptTo = szAuthor; - } - else if (!m_hServerConn) - pszReceiptType = "inactive"; - - SendReceipt(szChatId, pszReceiptTo, msgId, pszReceiptType); - } - catch (const char *pszError) { - debugLogA("Message cannot be parsed: %s", pszError); - } - - if (!iDecryptable) { - debugLogA("Nothing to decrypt"); - return; - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnStreamError(const WANode &node) -{ - m_bTerminated = true; - - if (auto *pszCode = node.getAttr("code")) { - switch (atoi(pszCode)) { - case 401: - debugLogA("Connection logged out from another device, exiting"); - break; - - case 408: - debugLogA("Connection lost, exiting"); - break; - - case 411: - debugLogA("Conflict between two devices, exiting"); - break; - - case 428: - debugLogA("Connection forcibly closed by the server, exiting"); - break; - - case 440: - debugLogA("Connection replaced from another device, exiting"); - break; - - case 515: - debugLogA("Server required to restart immediately, leaving thread"); - m_bRespawn = true; - break; - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnIqResult(const WANode &node) -{ - if (auto *pszId = node.getAttr("id")) - for (auto &it: m_arPacketQueue) - if (it->szPacketId == pszId) - (this->*it->pHandler)(node); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnIqPairDevice(const WANode &node) -{ - WSSendNode(WANodeIq(IQ::RESULT) << CHAR_PARAM("id", node.getAttr("id"))); - - if (auto *pRef = node.getChild("pair-device")->getChild("ref")) { - ShowQrCode(pRef->getBody()); - } - else { - debugLogA("OnIqPairDevice: got reply without ref, exiting"); - ShutdownSession(); - } -} - -void WhatsAppProto::OnIqPairSuccess(const WANode &node) -{ - CloseQrDialog(); - - auto *pRoot = node.getChild("pair-success"); - - try { - if (auto *pPlatform = pRoot->getChild("platform")) - debugLogA("Got response from platform: %s", pPlatform->getBody().c_str()); - - if (auto *pBiz = pRoot->getChild("biz")) - if (auto *pszName = pBiz->getAttr("name")) - setUString("Nick", pszName); - - if (auto *pDevice = pRoot->getChild("device")) { - if (auto *pszJid = pDevice->getAttr("jid")) { - WAJid jid(pszJid); - m_szJid = jid.user + "@" + jid.server; - setUString(DBKEY_JID, m_szJid); - setDword(DBKEY_DEVICE_ID, jid.device); - } - } - else throw "OnIqPairSuccess: got reply without device info, exiting"; - - if (auto *pIdentity = pRoot->getChild("device-identity")) { - proto::ADVSignedDeviceIdentityHMAC payload; - if (!payload.ParseFromArray(pIdentity->content.data(), (int)pIdentity->content.length())) - throw "OnIqPairSuccess: got reply with invalid identity, exiting"; - - auto &hmac = payload.hmac(); - auto &details = payload.details(); - { - // check details signature using HMAC - uint8_t signature[32]; - unsigned int out_len = sizeof(signature); - MBinBuffer secret(getBlob(DBKEY_SECRET_KEY)); - HMAC(EVP_sha256(), secret.data(), (int)secret.length(), (BYTE *)details.c_str(), (int)details.size(), signature, &out_len); - if (memcmp(hmac.c_str(), signature, sizeof(signature))) - throw "OnIqPairSuccess: got reply with invalid details signature, exiting"; - } - - proto::ADVSignedDeviceIdentity account; - if (!account.ParseFromString(details)) - throw "OnIqPairSuccess: got reply with invalid account, exiting"; - - auto &deviceDetails = account.details(); - auto &accountSignature = account.accountsignature(); - auto &accountSignatureKey = account.accountsignaturekey(); - { - MBinBuffer buf; - buf.append("\x06\x00", 2); - buf.append(deviceDetails.c_str(), deviceDetails.size()); - buf.append(m_signalStore.signedIdentity.pub); - - ec_public_key key = {}; - memcpy(key.data, accountSignatureKey.c_str(), sizeof(key.data)); - if (1 != curve_verify_signature(&key, (BYTE *)buf.data(), buf.length(), (BYTE *)accountSignature.c_str(), accountSignature.size())) - throw "OnIqPairSuccess: got reply with invalid account signature, exiting"; - } - debugLogA("Received valid account signature"); - { - MBinBuffer buf; - buf.append("\x06\x01", 2); - buf.append(deviceDetails.c_str(), deviceDetails.size()); - buf.append(m_signalStore.signedIdentity.pub); - buf.append(accountSignatureKey.c_str(), accountSignatureKey.size()); - - signal_buffer *result; - ec_private_key key = {}; - memcpy(key.data, m_signalStore.signedIdentity.priv.data(), m_signalStore.signedIdentity.priv.length()); - if (curve_calculate_signature(m_signalStore.CTX(), &result, &key, (BYTE *)buf.data(), buf.length()) != 0) - throw "OnIqPairSuccess: cannot calculate account signature, exiting"; - - account.set_devicesignature(result->data, result->len); - signal_buffer_free(result); - } - - setDword("SignalDeviceId", 0); - { - MBinBuffer key; - if (accountSignatureKey.size() == 32) - key.append(KEY_BUNDLE_TYPE, 1); - key.append(accountSignatureKey.c_str(), accountSignatureKey.size()); - db_set_blob(0, m_szModuleName, "SignalIdentifierKey", key.data(), (int)key.length()); - } - - account.clear_accountsignaturekey(); - - MBinBuffer accountEnc(account.ByteSize()); - account.SerializeToArray(accountEnc.data(), (int)accountEnc.length()); - db_set_blob(0, m_szModuleName, "WAAccount", accountEnc.data(), (int)accountEnc.length()); - - proto::ADVDeviceIdentity deviceIdentity; - deviceIdentity.ParseFromString(deviceDetails); - - WANodeIq reply(IQ::RESULT); reply << CHAR_PARAM("id", node.getAttr("id")); - - WANode *nodePair = reply.addChild("pair-device-sign"); - - WANode *nodeDeviceIdentity = nodePair->addChild("device-identity"); - nodeDeviceIdentity->addAttr("key-index", deviceIdentity.keyindex()); - nodeDeviceIdentity->content.append(accountEnc.data(), accountEnc.length()); - WSSendNode(reply); - } - else throw "OnIqPairSuccess: got reply without identity, exiting"; - } - catch (const char *pErrMsg) { - debugLogA(pErrMsg); - ShutdownSession(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnProcessHandshake(const void *pData, int cbLen) -{ - proto::HandshakeMessage msg; - if (!msg.ParseFromArray(pData, cbLen)) { - debugLogA("Error parsing data, exiting"); - -LBL_Error: - ShutdownSession(); - return; - } - - auto &static_ = msg.serverhello().static_(); - auto &payload_ = msg.serverhello().payload(); - auto &ephemeral_ = msg.serverhello().ephemeral(); - - m_noise->updateHash(ephemeral_.c_str(), ephemeral_.size()); - m_noise->mixIntoKey(m_noise->ephemeral.priv.data(), ephemeral_.c_str()); - - MBinBuffer decryptedStatic = m_noise->decrypt(static_.c_str(), static_.size()); - m_noise->mixIntoKey(m_noise->ephemeral.priv.data(), decryptedStatic.data()); - - MBinBuffer decryptedCert = m_noise->decrypt(payload_.c_str(), payload_.size()); - - proto::CertChain cert; cert.ParseFromArray(decryptedCert.data(), (int)decryptedCert.length()); - proto::CertChain::NoiseCertificate::Details details; details.ParseFromString(cert.intermediate().details()); - if (details.issuerserial() != 0) { - debugLogA("Invalid certificate serial number, exiting"); - goto LBL_Error; - } - - MBinBuffer encryptedPub = m_noise->encrypt(m_noise->noiseKeys.pub.data(), m_noise->noiseKeys.pub.length()); - m_noise->mixIntoKey(m_noise->noiseKeys.priv.data(), ephemeral_.c_str()); - - // create reply - proto::ClientPayload node; - - MFileVersion v; - Miranda_GetFileVersion(&v); - - // not received our jid from server? generate registration packet then - if (m_szJid.IsEmpty()) { - uint8_t appVersion[16]; - mir_md5_hash((BYTE *)APP_VERSION, sizeof(APP_VERSION) - 1, appVersion); - - auto *pAppVersion = new proto::DeviceProps_AppVersion(); - pAppVersion->set_primary(v[0]); - pAppVersion->set_secondary(v[1]); - pAppVersion->set_tertiary(v[2]); - pAppVersion->set_quaternary(v[3]); - - proto::DeviceProps pCompanion; - pCompanion.set_os("Miranda"); - pCompanion.set_allocated_version(pAppVersion); - pCompanion.set_platformtype(proto::DeviceProps_PlatformType_DESKTOP); - pCompanion.set_requirefullsync(false); - - MBinBuffer buf(pCompanion.ByteSize()); - pCompanion.SerializeToArray(buf.data(), (int)buf.length()); - - auto *pPairingData = new proto::ClientPayload_DevicePairingRegistrationData(); - pPairingData->set_deviceprops(buf.data(), buf.length()); - pPairingData->set_buildhash(appVersion, sizeof(appVersion)); - pPairingData->set_eregid(encodeBigEndian(getDword(DBKEY_REG_ID))); - pPairingData->set_ekeytype(KEY_BUNDLE_TYPE); - pPairingData->set_eident(m_signalStore.signedIdentity.pub.data(), m_signalStore.signedIdentity.pub.length()); - pPairingData->set_eskeyid(encodeBigEndian(m_signalStore.preKey.keyid)); - pPairingData->set_eskeyval(m_signalStore.preKey.pub.data(), m_signalStore.preKey.pub.length()); - pPairingData->set_eskeysig(m_signalStore.preKey.signature.data(), m_signalStore.preKey.signature.length()); - node.set_allocated_devicepairingdata(pPairingData); - - node.set_passive(false); - } - // generate login packet - else { - WAJid jid(m_szJid); - node.set_username(_atoi64(jid.user)); - node.set_device(getDword(DBKEY_DEVICE_ID)); - node.set_passive(true); - } - - auto *pUserVersion = new proto::ClientPayload_UserAgent_AppVersion(); - pUserVersion->set_primary(2); - pUserVersion->set_secondary(2230); - pUserVersion->set_tertiary(15); - - auto *pUserAgent = new proto::ClientPayload_UserAgent(); - pUserAgent->set_allocated_appversion(pUserVersion); - pUserAgent->set_platform(proto::ClientPayload_UserAgent_Platform_WEB); - pUserAgent->set_releasechannel(proto::ClientPayload_UserAgent_ReleaseChannel_RELEASE); - pUserAgent->set_mcc("000"); - pUserAgent->set_mnc("000"); - pUserAgent->set_osversion("0.1"); - pUserAgent->set_osbuildnumber("0.1"); - pUserAgent->set_manufacturer(""); - pUserAgent->set_device("Desktop"); - pUserAgent->set_localelanguageiso6391("en"); - pUserAgent->set_localecountryiso31661alpha2("US"); - - auto *pWebInfo = new proto::ClientPayload_WebInfo(); - pWebInfo->set_websubplatform(proto::ClientPayload_WebInfo_WebSubPlatform_WEB_BROWSER); - - node.set_connecttype(proto::ClientPayload_ConnectType_WIFI_UNKNOWN); - node.set_connectreason(proto::ClientPayload_ConnectReason_USER_ACTIVATED); - node.set_allocated_useragent(pUserAgent); - node.set_allocated_webinfo(pWebInfo); - - MBinBuffer payload(node.ByteSize()); - node.SerializeToArray(payload.data(), (int)payload.length()); - - MBinBuffer payloadEnc = m_noise->encrypt(payload.data(), payload.length()); - - auto *pFinish = new proto::HandshakeMessage_ClientFinish(); - pFinish->set_payload(payloadEnc.data(), payloadEnc.length()); - pFinish->set_static_(encryptedPub.data(), encryptedPub.length()); - - proto::HandshakeMessage handshake; - handshake.set_allocated_clientfinish(pFinish); - WSSend(handshake); - - m_noise->finish(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnServerSync(const WANode &node) -{ - OBJLIST<WACollection> task(1); - - for (auto &it : node.getChildren()) - if (it->title == "collection") - task.insert(new WACollection(it->getAttr("name"), it->getAttrInt("version"))); - - ResyncServer(task); -} - -void WhatsAppProto::ResyncServer(const OBJLIST<WACollection> &task) -{ - WANodeIq iq(IQ::SET, "w:sync:app:state"); - - auto *pList = iq.addChild("sync"); - for (auto &it : task) { - auto *pCollection = m_arCollections.find(it); - if (pCollection == nullptr) - m_arCollections.insert(pCollection = new WACollection(it->szName, 0)); - - if (pCollection->version < it->version) { - auto *pNode = pList->addChild("collection"); - *pNode << CHAR_PARAM("name", it->szName) << INT_PARAM("version", pCollection->version) - << CHAR_PARAM("return_snapshot", (!pCollection->version) ? "true" : "false"); - } - } - - if (pList->getFirstChild() != nullptr) - WSSendNode(iq, &WhatsAppProto::OnIqServerSync); -} - -void WhatsAppProto::OnIqServerSync(const WANode &node) -{ - for (auto &coll : node.getChild("sync")->getChildren()) { - if (coll->title != "collection") - continue; - - auto *pszName = coll->getAttr("name"); - - auto *pCollection = FindCollection(pszName); - if (pCollection == nullptr) { - pCollection = new WACollection(pszName, 0); - m_arCollections.insert(pCollection); - } - - int dwVersion = 0; - - CMStringW wszSnapshotPath(GetTmpFileName("collection", pszName)); - if (auto *pSnapshot = coll->getChild("snapshot")) { - proto::ExternalBlobReference body; - body << pSnapshot->content; - if (!body.has_directpath() || !body.has_mediakey()) { - debugLogA("Invalid snapshot data, skipping"); - continue; - } - - MBinBuffer buf = DownloadEncryptedFile(directPath2url(body.directpath().c_str()), body.mediakey(), "App State"); - if (!buf.data()) { - debugLogA("Invalid downloaded snapshot data, skipping"); - continue; - } - - proto::SyncdSnapshot snapshot; - snapshot << buf; - - dwVersion = snapshot.version().version(); - if (dwVersion > pCollection->version) { - auto &hash = snapshot.mac(); - pCollection->hash.assign(hash.c_str(), hash.size()); - - for (auto &it : snapshot.records()) - pCollection->parseRecord(it, true); - } - } - - if (auto *pPatchList = coll->getChild("patches")) { - for (auto &it : pPatchList->getChildren()) { - proto::SyncdPatch patch; - patch << it->content; - - dwVersion = patch.version().version(); - if (dwVersion > pCollection->version) - for (auto &jt : patch.mutations()) - pCollection->parseRecord(jt.record(), jt.operation() == proto::SyncdMutation_SyncdOperation::SyncdMutation_SyncdOperation_SET); - } - } - - CMStringA szSetting(FORMAT, "Collection_%s", pszName); - // setDword(szSetting, dwVersion); - - JSONNode jsonRoot, jsonMap; - for (auto &it : pCollection->indexValueMap) - jsonMap << CHAR_PARAM(ptrA(mir_base64_encode(it.first.c_str(), it.first.size())), ptrA(mir_base64_encode(it.second.c_str(), it.second.size()))); - jsonRoot << INT_PARAM("version", dwVersion) << JSON_PARAM("indexValueMap", jsonMap); - - // string2file(jsonRoot.write(), GetTmpFileName("collection", CMStringA(pszName) + ".json")); - } -} - -void WACollection::parseRecord(const ::proto::SyncdRecord &rec, bool bSet) -{ - // auto &id = rec.keyid().id(); - auto &index = rec.index().blob(); - auto &value = rec.value().blob(); - - if (bSet) { - indexValueMap[index] = value.substr(0, value.size() - 32); - } - else indexValueMap.erase(index); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void WhatsAppProto::OnSuccess(const WANode &) -{ - OnLoggedIn(); - - WSSendNode(WANodeIq(IQ::SET, "passive") << XCHILD("active"), &WhatsAppProto::OnIqDoNothing); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -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("notification", "encrypt", 0, 0, &WhatsAppProto::OnNotifyEncrypt)); - m_arPersistent.insert(new WAPersistentHandler("notification", "account_sync", 0, 0, &WhatsAppProto::OnAccountSync)); - m_arPersistent.insert(new WAPersistentHandler("notification", "server_sync", 0, 0, &WhatsAppProto::OnServerSync)); - - m_arPersistent.insert(new WAPersistentHandler("ib", 0, 0, 0, &WhatsAppProto::OnReceiveInfo)); - m_arPersistent.insert(new WAPersistentHandler("message", 0, 0, 0, &WhatsAppProto::OnReceiveMessage)); - 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)); -} |