diff options
Diffstat (limited to 'protocols/WhatsAppWeb/src/utils.cpp')
-rw-r--r-- | protocols/WhatsAppWeb/src/utils.cpp | 449 |
1 files changed, 2 insertions, 447 deletions
diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp index 99393d65fc..9d62432a10 100644 --- a/protocols/WhatsAppWeb/src/utils.cpp +++ b/protocols/WhatsAppWeb/src/utils.cpp @@ -183,451 +183,6 @@ void WANode::print(CMStringA &dest, int level) const } ///////////////////////////////////////////////////////////////////////////////////////// -// WAReader class members - -bool WAReader::readAttributes(WANode *pNode, int count) -{ - if (count == 0) - return true; - - for (int i = 0; i < count; i++) { - CMStringA name = readString(readInt8()); - if (name.IsEmpty()) - return false; - - CMStringA value = readString(readInt8()); - if (value.IsEmpty()) - return false; - - pNode->addAttr(name, value); - } - return true; -} - -uint32_t WAReader::readInt20() -{ - if (m_limit - m_buf < 3) - return 0; - - int ret = (int(m_buf[0] & 0x0F) << 16) + (int(m_buf[1]) << 8) + int(m_buf[2]); - m_buf += 3; - return ret; -} - -uint32_t WAReader::readIntN(int n) -{ - if (m_limit - m_buf < n) - return 0; - - uint32_t res = 0; - for (int i = 0; i < n; i++, m_buf++) - res = (res <<= 8) + *m_buf; - return res; -} - -bool WAReader::readList(WANode *pParent, int tag) -{ - int size = readListSize(tag); - if (size == -1) - return false; - - for (int i = 0; i < size; i++) { - WANode *pNew = readNode(); - if (pNew == nullptr) - return false; - pParent->children.push_back(pNew); - } - - return true; -} - -int WAReader::readListSize(int tag) -{ - switch (tag) { - case LIST_EMPTY: - return 0; - case LIST_8: - return readInt8(); - case LIST_16: - return readInt16(); - } - return -1; -} - -WANode* WAReader::readNode() -{ - int listSize = readListSize(readInt8()); - if (listSize == -1) - return nullptr; - - int descrTag = readInt8(); - if (descrTag == STREAM_END) - return nullptr; - - CMStringA name = readString(descrTag); - if (name.IsEmpty()) - return nullptr; - - std::unique_ptr<WANode> ret(new WANode()); - ret->title = name.c_str(); - - if (!readAttributes(ret.get(), (listSize-1)>>1)) - return nullptr; - - if ((listSize % 2) == 1) - return ret.release(); - - int size, tag = readInt8(); - switch (tag) { - case LIST_EMPTY: case LIST_8: case LIST_16: - readList(ret.get(), tag); - break; - - case BINARY_8: - size = readInt8(); - -LBL_Binary: - if (m_limit - m_buf < size) - return false; - - ret->content.assign((void*)m_buf, size); - m_buf += size; - break; - - case BINARY_20: - size = readInt20(); - goto LBL_Binary; - - case BINARY_32: - size = readInt32(); - goto LBL_Binary; - - default: - CMStringA str = readString(tag); - ret->content.assign(str.GetBuffer(), str.GetLength() + 1); - } - - return ret.release(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static int unpackHex(int val) -{ - if (val < 0 || val > 15) - return -1; - - return (val < 10) ? val + '0' : val - 10 + 'A'; -} - -static int unpackNibble(int val) -{ - if (val < 0 || val > 15) - return -1; - - switch (val) { - case 10: return '-'; - case 11: return '.'; - case 15: return 0; - default: return '0' + val; - } -} - -CMStringA WAReader::readPacked(int tag) -{ - int startByte = readInt8(); - bool bTrim = false; - if (startByte & 0x80) { - startByte &= ~0x80; - bTrim = true; - } - - CMStringA ret; - for (int i = 0; i < startByte; i++) { - BYTE b = readInt8(); - int lower = (tag == NIBBLE_8) ? unpackNibble(b >> 4) : unpackHex(b >> 4); - if (lower == -1) - return ""; - - int higher = (tag == NIBBLE_8) ? unpackNibble(b & 0x0F) : unpackHex(b & 0x0F); - if (higher == -1) - return ""; - - ret.AppendChar(lower); - ret.AppendChar(higher); - } - - if (bTrim && !ret.IsEmpty()) - ret.Truncate(ret.GetLength() - 1); - return ret; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static char *SingleByteTokens[] = { - "", "", "", "200", "400", "404", "500", "501", "502", "action", "add", - "after", "archive", "author", "available", "battery", "before", "body", - "broadcast", "chat", "clear", "code", "composing", "contacts", "count", - "create", "debug", "delete", "demote", "duplicate", "encoding", "error", - "false", "filehash", "from", "g.us", "group", "groups_v2", "height", "id", - "image", "in", "index", "invis", "item", "jid", "kind", "last", "leave", - "live", "log", "media", "message", "mimetype", "missing", "modify", "name", - "notification", "notify", "out", "owner", "participant", "paused", - "picture", "played", "presence", "preview", "promote", "query", "raw", - "read", "receipt", "received", "recipient", "recording", "relay", - "remove", "response", "resume", "retry", "s.whatsapp.net", "seconds", - "set", "size", "status", "subject", "subscribe", "t", "text", "to", "true", - "type", "unarchive", "unavailable", "url", "user", "value", "web", "width", - "mute", "read_only", "admin", "creator", "short", "update", "powersave", - "checksum", "epoch", "block", "previous", "409", "replaced", "reason", - "spam", "modify_tag", "message_info", "delivery", "emoji", "title", - "description", "canonical-url", "matched-text", "star", "unstar", - "media_key", "filename", "identity", "unread", "page", "page_count", - "search", "media_message", "security", "call_log", "profile", "ciphertext", - "invite", "gif", "vcard", "frequent", "privacy", "blacklist", "whitelist", - "verify", "location", "document", "elapsed", "revoke_invite", "expiration", - "unsubscribe", "disable", "vname", "old_jid", "new_jid", "announcement", - "locked", "prop", "label", "color", "call", "offer", "call-id", - "quick_reply", "sticker", "pay_t", "accept", "reject", "sticker_pack", - "invalid", "canceled", "missed", "connected", "result", "audio", - "video", "recent" }; - -CMStringA WAReader::readString(int tag) -{ - if (tag >= 3 && tag < _countof(SingleByteTokens)) { - CMStringA ret = SingleByteTokens[tag]; - if (ret == "s.whatsapp.net") - return "c.us"; - return ret; - } - - switch (tag) { -// case DICTIONARY_0: return dict0[readInt8()]; -// case DICTIONARY_1: return dict1[readInt8()]; -// case DICTIONARY_2: return dict2[readInt8()]; -// case DICTIONARY_3: return dict3[readInt8()]; - case LIST_EMPTY: - return ""; - - case BINARY_8: - return readStringFromChars(readInt8()); - - case BINARY_20: - return readStringFromChars(readInt20()); - - case BINARY_32: - return readStringFromChars(readInt32()); - - case NIBBLE_8: - case HEX_8: - return readPacked(tag); - - case JID_PAIR: - CMStringA s1 = readString(readInt8()); - if (s1.IsEmpty()) - break; - - CMStringA s2 = readString(readInt8()); - if (s2.IsEmpty()) - break; - - return CMStringA(FORMAT, "%s@%s", s1.c_str(), s2.c_str()); - } - - // error - return ""; -} - -CMStringA WAReader::readStringFromChars(int size) -{ - if (m_limit - m_buf < size) - return ""; - - CMStringA ret((char*)m_buf, size); - m_buf += size; - return ret; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// WAWriter class members - -void WAWriter::writeByte(uint8_t b) -{ - body.append(&b, 1); -} - -void WAWriter::writeIntN(int value, int n) -{ - for (int i = n - 1; i >= 0; i--) - writeByte((value >> i * 8) & 0xFF); -} - -void WAWriter::writeInt20(int value) -{ - writeByte((value >> 16) & 0xFF); - writeByte((value >> 8) & 0xFF); - writeByte(value & 0xFF); -} - -void WAWriter::writeLength(int value) -{ - if (value >= (1 << 20)) { - writeByte(BINARY_32); - writeInt32(value); - } - else if (value >= 256) { - writeByte(BINARY_20); - writeInt20(value); - } - else { - writeByte(BINARY_8); - writeInt8(value); - } -} - -void WAWriter::writeListSize(int length) -{ - if (length == 0) - writeByte(LIST_EMPTY); - else if (length < 256) { - writeByte(LIST_8); - writeInt8(length); - } - else { - writeByte(LIST_16); - writeInt16(length); - } -} - -void WAWriter::writeNode(const WANode *pNode) -{ - int numAttrs = (int)pNode->attrs.size(); - int hasContent = pNode->content.length() != 0; - writeListSize(2*numAttrs + 1 + hasContent); - - writeString(pNode->title.c_str()); - - // write attributes - for (auto &it : pNode->attrs) { - if (it->value.IsEmpty()) - continue; - - writeString(it->name.c_str()); - writeString(it->value.c_str()); - } - - // write contents - if (pNode->content.length()) { - writeLength((int)pNode->content.length()); - body.append(pNode->content.data(), pNode->content.length()); - } - - // write children - if (pNode->children.size()) { - writeListSize((int)pNode->children.size()); - for (auto &it : pNode->children) - writeNode(it); - } -} - -void WAWriter::writeString(const char *str, bool bRaw) -{ - if (!bRaw && !mir_strcmp(str, "c.us")) { - writeToken("s.whatsapp.net"); - return; - } - - if (writeToken(str)) - return; - - auto *pszDelimiter = strchr(str, '@'); - if (pszDelimiter) { - writeByte(JID_PAIR); - - if (pszDelimiter == str) // empty jid - writeByte(LIST_EMPTY); - else - writePacked(CMStringA(str, int(pszDelimiter - str))); - } - else { - int len = (int)strlen(str); - writeLength(len); - body.append(str, len); - } -} - -bool WAWriter::writeToken(const char *str) -{ - for (auto &it : SingleByteTokens) - if (!strcmp(str, it)) { - writeByte(int(&it - SingleByteTokens)); - return true; - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static BYTE packNibble(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - - switch (c) { - case '-': return 10; - case '.': return 11; - case 0: return 15; - } - - return -1; -} - -static BYTE packHex(char c) -{ - if (c == 0) - return 15; - - if (c >= '0' && c <= '9') - return c - '0'; - - if (c >= 'A' && c <= 'F') - return c - 'A'; - - if (c >= 'a' && c <= 'f') - return c - 'a'; - - return -1; -} - -static BYTE packPair(int type, char c1, char c2) -{ - BYTE b1 = (type == NIBBLE_8) ? packNibble(c1) : packHex(c1); - BYTE b2 = (type == NIBBLE_8) ? packNibble(c2) : packHex(c2); - return (b1 << 4) + b2; -} - -void WAWriter::writePacked(const CMStringA &str) -{ - if (str.GetLength() > 254) - return; - - // all symbols of str can be a nibble? - int type = (strspn(str, "0123456789-.") == str.GetLength()) ? NIBBLE_8 : HEX_8; - - int len = str.GetLength() / 2; - BYTE firstByte = (len % 2) == 0 ? 0 : 0x80; - writeByte(firstByte | len); - - const char *p = str; - for (int i = 0; i < len; i++, p += 2) - writeByte(packPair(type, p[0], p[1])); - - if (firstByte != 0) - writeByte(packPair(type, p[0], 0)); -} - -///////////////////////////////////////////////////////////////////////////////////////// std::string encodeBigEndian(uint32_t num, size_t len) { @@ -658,7 +213,7 @@ static unsigned char *HKDF_Extract(const EVP_MD *evp_md, { unsigned int tmp_len; - if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len)) + if (!HMAC(evp_md, salt, (int)salt_len, key, (int)key_len, prk, &tmp_len)) return NULL; *prk_len = tmp_len; @@ -689,7 +244,7 @@ static unsigned char *HKDF_Expand(const EVP_MD *evp_md, if ((hmac = HMAC_CTX_new()) == NULL) return NULL; - if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL)) + if (!HMAC_Init_ex(hmac, prk, (int)prk_len, evp_md, NULL)) goto err; for (i = 1; i <= n; i++) { |