From dac1f42ef81ac1119430fd294a6b35b0b8cd6837 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 25 Jan 2015 17:45:10 +0000 Subject: - class KeyStream extracted to the separate module; - xml attributes redesigned to produce efficient code; - many small improvements git-svn-id: http://svn.miranda-ng.org/main/trunk@11905 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/WhatsApp/WhatsApp_10.vcxproj | 90 ++++ protocols/WhatsApp/WhatsApp_10.vcxproj.filters | 3 + protocols/WhatsApp/WhatsApp_12.vcxproj | 86 +++ protocols/WhatsApp/WhatsApp_12.vcxproj.filters | 3 + .../WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp | 9 +- .../WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp | 40 +- .../WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h | 12 +- protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp | 107 ++-- protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp | 37 +- protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp | 89 ++++ protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp | 3 +- .../WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp | 74 ++- .../WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h | 41 +- protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp | 580 +++++---------------- protocols/WhatsApp/src/WhatsAPI++/WAConnection.h | 6 +- protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp | 112 +--- protocols/WhatsApp/src/WhatsAPI++/WALogin.h | 3 +- protocols/WhatsApp/src/WhatsAPI++/utilities.cpp | 12 +- protocols/WhatsApp/src/common.h | 1 + 19 files changed, 643 insertions(+), 665 deletions(-) create mode 100644 protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp (limited to 'protocols/WhatsApp') diff --git a/protocols/WhatsApp/WhatsApp_10.vcxproj b/protocols/WhatsApp/WhatsApp_10.vcxproj index f1d2e34272..0d1f57f208 100644 --- a/protocols/WhatsApp/WhatsApp_10.vcxproj +++ b/protocols/WhatsApp/WhatsApp_10.vcxproj @@ -214,33 +214,123 @@ NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h + + + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h diff --git a/protocols/WhatsApp/WhatsApp_10.vcxproj.filters b/protocols/WhatsApp/WhatsApp_10.vcxproj.filters index e1f2cb38a2..7ab73c9b4c 100644 --- a/protocols/WhatsApp/WhatsApp_10.vcxproj.filters +++ b/protocols/WhatsApp/WhatsApp_10.vcxproj.filters @@ -119,6 +119,9 @@ WhatsAPI++\Source Files + + WhatsAPI++\Source Files + diff --git a/protocols/WhatsApp/WhatsApp_12.vcxproj b/protocols/WhatsApp/WhatsApp_12.vcxproj index 77b0532482..5cb112c3a1 100644 --- a/protocols/WhatsApp/WhatsApp_12.vcxproj +++ b/protocols/WhatsApp/WhatsApp_12.vcxproj @@ -213,33 +213,119 @@ NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h + + + ../common.h + ../common.h + ../common.h + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h NotUsing + Use + ../common.h + Use + ../common.h + Use + ../common.h + Use + ../common.h diff --git a/protocols/WhatsApp/WhatsApp_12.vcxproj.filters b/protocols/WhatsApp/WhatsApp_12.vcxproj.filters index 4ab7a2cfa7..9dd21638c1 100644 --- a/protocols/WhatsApp/WhatsApp_12.vcxproj.filters +++ b/protocols/WhatsApp/WhatsApp_12.vcxproj.filters @@ -122,6 +122,9 @@ WhatsAPI++\Source Files + + WhatsAPI++\Source Files + diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp index 573afb4680..16e9238a4f 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp @@ -5,7 +5,8 @@ * Author: Antonio */ -#include +#include "../common.h" // #TODO Remove Miranda-dependency + #include "BinTreeNodeReader.h" #include "WAException.h" #include "ProtocolTreeNode.h" @@ -69,13 +70,13 @@ ProtocolTreeNode* BinTreeNodeReader::nextTreeInternal() int attribCount = (size - 2 + size % 2) / 2; std::map* attribs = readAttributes(attribCount); if (size % 2 == 1) { - ProtocolTreeNode* ret = new ProtocolTreeNode(*tag, attribs); + ProtocolTreeNode* ret = new ProtocolTreeNode(*tag); ret->attributes = attribs; delete tag; return ret; } b = this->in->read(); if (isListTag(b)) { - ProtocolTreeNode* ret = new ProtocolTreeNode(*tag, attribs, NULL, readList(b)); + ProtocolTreeNode* ret = new ProtocolTreeNode(*tag, NULL, readList(b)); ret->attributes = attribs; delete tag; return ret; } @@ -91,7 +92,7 @@ ProtocolTreeNode* BinTreeNodeReader::nextTreeInternal() data = (std::vector*) obj->data; } - ProtocolTreeNode* ret = new ProtocolTreeNode(*tag, attribs, data); + ProtocolTreeNode* ret = new ProtocolTreeNode(*tag, data); ret->attributes = attribs; delete obj; delete tag; return ret; diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp index b79bdcfd09..d4387278e1 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp @@ -5,8 +5,9 @@ * Author: Antonio */ +#include "../common.h" // #TODO Remove Miranda-dependency + #include "BinTreeNodeWriter.h" -#include #include "utilities.h" BinTreeNodeWriter::BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection, @@ -195,22 +196,21 @@ void BinTreeNodeWriter::writeInt24(int v) this->out->write(v & 0xFF); } -void BinTreeNodeWriter::writeInternal(ProtocolTreeNode* node) +void BinTreeNodeWriter::writeInternal(const ProtocolTreeNode &node) { writeListStart( - 1 + (node->attributes == NULL ? 0 : (int)node->attributes->size() * 2) - + (node->children == NULL ? 0 : 1) - + (node->data == NULL ? 0 : 1)); - writeString(node->tag); - writeAttributes(node->attributes); - if (node->data != NULL) { - writeBytes((unsigned char*)node->data->data(), (int)node->data->size()); - } - if (node->children != NULL && !node->children->empty()) { - writeListStart((int)node->children->size()); - for (size_t a = 0; a < node->children->size(); a++) { - writeInternal((*node->children)[a]); - } + 1 + (node.attributes == NULL ? 0 : (int)node.attributes->size() * 2) + + (node.children == NULL ? 0 : 1) + + (node.data == NULL ? 0 : 1)); + writeString(node.tag); + writeAttributes(node.attributes); + if (node.data != NULL) + writeBytes((unsigned char*)node.data->data(), (int)node.data->size()); + + if (node.children != NULL && !node.children->empty()) { + writeListStart((int)node.children->size()); + for (size_t a = 0; a < node.children->size(); a++) + writeInternal(*(*node.children)[a]); } } @@ -258,21 +258,17 @@ void BinTreeNodeWriter::streamEnd() this->mutex->unlock(); } -void BinTreeNodeWriter::write(ProtocolTreeNode* node) +void BinTreeNodeWriter::write(const ProtocolTreeNode& node) { write(node, true); } -void BinTreeNodeWriter::write(ProtocolTreeNode* node, bool needsFlush) +void BinTreeNodeWriter::write(const ProtocolTreeNode &node, bool needsFlush) { this->mutex->lock(); try { this->writeDummyHeader(); - if (node == NULL) - this->out->write(0); - else { - writeInternal(node); - } + writeInternal(node); flushBuffer(needsFlush); } catch (exception& ex) { diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h index 20faaea4e8..c87b58f32b 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h @@ -35,7 +35,7 @@ class WAConnection; class BinTreeNodeWriter { private: WAConnection* conn; - map tokenMap; + map tokenMap; ISocketConnection *realOut; ByteArrayOutputStream *out; IMutex* mutex; @@ -52,9 +52,9 @@ private: void writeToken(int intValue); void writeBytes(unsigned char* bytes, int length); void writeInt24(int v); - void writeInternal(ProtocolTreeNode* node); - void writeDummyHeader(); - void processBuffer(); + void writeInternal(const ProtocolTreeNode &node); + void writeDummyHeader(); + void processBuffer(); public: BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection, const char** dictionary, const int dictionarysize, IMutex* mutex); @@ -62,8 +62,8 @@ public: void flushBuffer(bool flushNetwork); void flushBuffer(bool flushNetwork, int startingOffset); void streamEnd(); - void write(ProtocolTreeNode* node); - void write(ProtocolTreeNode* node, bool needsFlush); + void write(const ProtocolTreeNode &node); + void write(const ProtocolTreeNode &node, bool needsFlush); virtual ~BinTreeNodeWriter(); }; diff --git a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp index d52b10c549..579dd58516 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp @@ -5,59 +5,69 @@ * Author: Antonio */ +#include "../common.h" // #TODO Remove Miranda-dependency + #include "ByteArray.h" #include "WAException.h" -#include -#include #include "utilities.h" -ByteArrayOutputStream::ByteArrayOutputStream(int size) { +ByteArrayOutputStream::ByteArrayOutputStream(int size) +{ this->buf = new std::vector(); this->buf->reserve(size); this->position = 0; } -void ByteArrayOutputStream::setLength(size_t length) { +void ByteArrayOutputStream::setLength(size_t length) +{ this->buf->resize(length); } -size_t ByteArrayOutputStream::getLength() { +size_t ByteArrayOutputStream::getLength() +{ return this->buf->size(); } -size_t ByteArrayOutputStream::getCapacity() { +size_t ByteArrayOutputStream::getCapacity() +{ return this->buf->capacity(); } -size_t ByteArrayOutputStream::getPosition() { +size_t ByteArrayOutputStream::getPosition() +{ return this->position; } -void ByteArrayOutputStream::setPosition(size_t count) { +void ByteArrayOutputStream::setPosition(size_t count) +{ this->position = count; } -std::vector* ByteArrayOutputStream::toByteArray() { +std::vector* ByteArrayOutputStream::toByteArray() +{ std::vector* array = new std::vector(this->buf->size()); for (size_t i = 0; i < this->buf->size(); i++) (*array)[i] = (*this->buf)[i]; return array; } -std::vector* ByteArrayOutputStream::getBuffer() { +std::vector* ByteArrayOutputStream::getBuffer() +{ return this->buf; } -void ByteArrayOutputStream::write(int i) { +void ByteArrayOutputStream::write(int i) +{ if (this->position == this->buf->size()) - this->buf->push_back((unsigned char) i); + this->buf->push_back((unsigned char)i); else - (*this->buf)[this->position] = (unsigned char) i; + (*this->buf)[this->position] = (unsigned char)i; this->position = this->position + 1; } -void ByteArrayOutputStream::write(unsigned char* b, size_t len) { +void ByteArrayOutputStream::write(unsigned char* b, size_t len) +{ if (len == 0) return; @@ -65,85 +75,94 @@ void ByteArrayOutputStream::write(unsigned char* b, size_t len) { write(b[i]); } -void ByteArrayOutputStream::write(const std::string& s) { +void ByteArrayOutputStream::write(const std::string& s) +{ for (size_t i = 0; i < s.size(); i++) - write((unsigned char) s[i]); + write((unsigned char)s[i]); } -ByteArrayOutputStream::~ByteArrayOutputStream() { +ByteArrayOutputStream::~ByteArrayOutputStream() +{ delete this->buf; } -ByteArrayInputStream::ByteArrayInputStream(std::vector* buf, size_t off, size_t length ) { +ByteArrayInputStream::ByteArrayInputStream(std::vector* buf, size_t off, size_t length) +{ this->buf = buf; this->pos = off; this->count = min(off + length, buf->size()); } -ByteArrayInputStream::ByteArrayInputStream(std::vector* buf) { +ByteArrayInputStream::ByteArrayInputStream(std::vector* buf) +{ this->buf = buf; this->pos = 0; this->count = buf->size(); } -int ByteArrayInputStream::read() { +int ByteArrayInputStream::read() +{ return (pos < count) ? ((*this->buf)[pos++]) : -1; } -int ByteArrayInputStream::read(std::vector& b, size_t off, size_t len) { - if (len > (b.size() - off)) { +int ByteArrayInputStream::read(std::vector& b, size_t off, size_t len) +{ + if (len > (b.size() - off)) throw new WAException("Index out of bounds"); - } else if (len == 0) { + + if (len == 0) return 0; - } int c = read(); - if (c == -1) { + if (c == -1) return -1; - } - b[off] = (unsigned char) c; + + b[off] = (unsigned char)c; size_t i = 1; try { - for (; i < len ; i++) { + for (; i < len; i++) { c = read(); - if (c == -1) { + if (c == -1) break; - } - b[off + i] = (unsigned char) c; + + b[off + i] = (unsigned char)c; } - } catch (std::exception& ) { + } + catch (std::exception&) { } return (int)i; } -ByteArrayInputStream::~ByteArrayInputStream() { -} +ByteArrayInputStream::~ByteArrayInputStream() +{} -void ByteArrayInputStream::print() { +void ByteArrayInputStream::print() +{ std::cout << "["; - for (size_t i = 0; i < this->count; i++) { + for (size_t i = 0; i < this->count; i++) std::cout << (*this->buf)[i] << " "; - } + std::cout << std::endl; - for (size_t i = 0; i < this->count; i++) { - std::cout << (int) ((signed char) (*this->buf)[i]) << " "; - } + for (size_t i = 0; i < this->count; i++) + std::cout << (int)((signed char)(*this->buf)[i]) << " "; + std::cout << "]" << std::endl; } -void ByteArrayOutputStream::print() { +void ByteArrayOutputStream::print() +{ _LOGDATA("["); std::string chars(this->buf->begin(), this->buf->end()); _LOGDATA("%s ", chars.c_str()); std::string numbers = ""; - for (size_t i = 0; i < this->buf->size(); i++) { - numbers += Utilities::intToStr((int) ((signed char) (*this->buf)[i])) + " "; - } + for (size_t i = 0; i < this->buf->size(); i++) + numbers += Utilities::intToStr((int)((signed char)(*this->buf)[i])) + " "; + _LOGDATA("%s", numbers.c_str()); _LOGDATA("]"); } diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp index c80e44c657..a684d1e3e3 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp @@ -5,10 +5,8 @@ * Author: Antonio */ -#include -#include -#include -#include "FMessage.h" +#include "../common.h" // #TODO Remove Miranda-dependency + #include "utilities.h" //SDL_mutex* FMessage::generating_lock = SDL_CreateMutex(); @@ -17,7 +15,8 @@ int FMessage::generating_id = 0; std::string FMessage::generating_header = Utilities::intToStr(static_cast (time(NULL))).append("-"); -FMessage::FMessage() { +FMessage::FMessage() +{ this->key = NULL; this->timestamp = 0; this->media_wa_type = 0; @@ -30,7 +29,8 @@ FMessage::FMessage() { this->data = ""; } -FMessage::FMessage(const std::string& remote_jid, bool from_me, const std::string& data) { +FMessage::FMessage(const std::string& remote_jid, bool from_me, const std::string& data) +{ Key* local_key; FMessage::generating_lock->lock(); FMessage::generating_id++; @@ -48,7 +48,8 @@ FMessage::FMessage(const std::string& remote_jid, bool from_me, const std::strin this->media_url = ""; } -std::string FMessage::nextKeyIdNumber() { +std::string FMessage::nextKeyIdNumber() +{ int id = 0; FMessage::generating_lock->lock(); id = (FMessage::generating_id++); @@ -56,7 +57,8 @@ std::string FMessage::nextKeyIdNumber() { return generating_header + (Utilities::intToStr(id)); } -FMessage::FMessage(Key* key) { +FMessage::FMessage(Key* key) +{ this->key = key; this->timestamp = 0; this->media_wa_type = 0; @@ -68,7 +70,8 @@ FMessage::FMessage(Key* key) { this->media_url = ""; } -std::string FMessage::getMessage_WA_Type_StrValue(unsigned char type) { +std::string FMessage::getMessage_WA_Type_StrValue(unsigned char type) +{ switch (type) { case FMessage::WA_TYPE_UNDEFINED: return ""; @@ -89,26 +92,30 @@ std::string FMessage::getMessage_WA_Type_StrValue(unsigned char type) { return ""; } -FMessage::~FMessage() { +FMessage::~FMessage() +{ if (this->key != NULL) delete key; } -Key::Key(const std::string& remote_jid, bool from_me, const std::string& id) { +Key::Key(const std::string& remote_jid, bool from_me, const std::string& id) +{ this->remote_jid = remote_jid; this->from_me = from_me; this->id = id; } -std::string Key::toString() { - return "Key[id=" + id + ", from_me=" + (from_me ? "true":"false") + ", remote_jid=" + remote_jid + "]"; +std::string Key::toString() +{ + return "Key[id=" + id + ", from_me=" + (from_me ? "true" : "false") + ", remote_jid=" + remote_jid + "]"; } -unsigned char FMessage::getMessage_WA_Type(const std::string& type) { +unsigned char FMessage::getMessage_WA_Type(const std::string& type) +{ if (type.empty()) return WA_TYPE_UNDEFINED; - + std::string typeLower = type; std::transform(typeLower.begin(), typeLower.end(), typeLower.begin(), ::tolower); if (typeLower.compare("system") == 0) diff --git a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp new file mode 100644 index 0000000000..f4741729a7 --- /dev/null +++ b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp @@ -0,0 +1,89 @@ +/* + * WALogin.cpp + * + * Created on: 26/06/2012 + * Author: Antonio + */ + +#include "../common.h" // #TODO Remove Miranda-dependency + +#include "WALogin.h" +#include "ByteArray.h" +#include "ProtocolTreeNode.h" +#include "WAException.h" + +using namespace Utilities; + +KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) : + seq(0) +{ + memcpy(key, _key, 20); + memcpy(keyMac, _keyMac, 20); + + RC4_set_key(&this->rc4, 20, this->key); + + unsigned char drop[768]; + RC4(&this->rc4, sizeof(drop), drop, drop); + + HMAC_CTX_init(&hmac); +} + +KeyStream::~KeyStream() +{ + HMAC_CTX_cleanup(&hmac); +} + +void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector& nonce, unsigned char *out) +{ + size_t cbSize = nonce.size(); + + uint8_t *pNonce = (uint8_t*)_alloca(cbSize + 1); + memcpy(pNonce, nonce.data(), cbSize); + + for (int i = 0; i < 4; i++) { + pNonce[cbSize] = i + 1; + PKCS5_PBKDF2_HMAC_SHA1(pass.data(), (int)pass.size(), pNonce, (int)cbSize+1, 2, 20, out + i*20); + } +} + +void KeyStream::decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) +{ + unsigned char digest[20]; + this->hmacsha1(buffer + offset, length, digest); + + if (memcmp(&buffer[macOffset], digest, 4)) + throw WAException("invalid MAC", WAException::CORRUPT_STREAM_EX, 0); + + unsigned char* out = (unsigned char*)_alloca(length); + RC4(&this->rc4, length, buffer + offset, out); + memcpy(buffer + offset, out, length); +} + +void KeyStream::encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) +{ + unsigned char* out = (unsigned char*)_alloca(length); + RC4(&this->rc4, length, buffer + offset, out); + memcpy(buffer + offset, out, length); + + unsigned char digest[20]; + this->hmacsha1(buffer + offset, length, digest); + memcpy(buffer + macOffset, digest, 4); +} + +void KeyStream::hmacsha1(unsigned char* text, int textLength, unsigned char *out) +{ + HMAC_Init(&hmac, this->keyMac, 20, EVP_sha1()); + HMAC_Update(&hmac, text, textLength); + + unsigned char hmacInt[4]; + hmacInt[0] = (this->seq >> 24); + hmacInt[1] = (this->seq >> 16); + hmacInt[2] = (this->seq >> 8); + hmacInt[3] = (this->seq); + HMAC_Update(&hmac, hmacInt, sizeof(hmacInt)); + + unsigned int mdLength; + HMAC_Final(&hmac, out, &mdLength); + + this->seq++; +} diff --git a/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp b/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp index 8171094d5c..966e7cd28c 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp @@ -3,8 +3,9 @@ * */ +#include "../common.h" // #TODO Remove Miranda-dependency + #include "PhoneNumber.h" -#include "WAException.h" struct CountryDescr { diff --git a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp index 5ca7bd7f0e..5929d43b20 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp @@ -5,27 +5,32 @@ * Author: Antonio */ +#include "../common.h" // #TODO Remove Miranda-dependency + #include "WAException.h" #include "ProtocolTreeNode.h" static std::string nilstr; -ProtocolTreeNode::ProtocolTreeNode(const string& tag, map *attributes, vector* data, vector *children) { +ProtocolTreeNode::ProtocolTreeNode(const string& tag, vector* data, vector *children) +{ this->tag = tag; this->data = data; - this->attributes = attributes; + this->attributes = NULL; this->children = children; } -ProtocolTreeNode::ProtocolTreeNode(const string& tag, map *attributes, ProtocolTreeNode* child) { +ProtocolTreeNode::ProtocolTreeNode(const string& tag, ProtocolTreeNode* child) +{ this->tag = tag; this->data = NULL; - this->attributes = attributes; + this->attributes = NULL; this->children = new std::vector(1); (*this->children)[0] = child; } -ProtocolTreeNode::~ProtocolTreeNode() { +ProtocolTreeNode::~ProtocolTreeNode() +{ if (this->attributes != NULL) delete this->attributes; if (this->children != NULL) { @@ -39,11 +44,12 @@ ProtocolTreeNode::~ProtocolTreeNode() { } -string ProtocolTreeNode::toString() { +string ProtocolTreeNode::toString() +{ string out; out += "<" + this->tag; if (this->attributes != NULL) { - map::iterator ii; + map::iterator ii; for (ii = attributes->begin(); ii != attributes->end(); ii++) out += "" + ii->first + "=\"" + ii->second + "\""; } @@ -61,7 +67,8 @@ string ProtocolTreeNode::toString() { return out; } -ProtocolTreeNode* ProtocolTreeNode::getChild(const string& id) { +ProtocolTreeNode* ProtocolTreeNode::getChild(const string& id) +{ if (this->children == NULL || this->children->size() == 0) return NULL; @@ -72,7 +79,8 @@ ProtocolTreeNode* ProtocolTreeNode::getChild(const string& id) { return NULL; } -ProtocolTreeNode* ProtocolTreeNode::getChild(size_t id) { +ProtocolTreeNode* ProtocolTreeNode::getChild(size_t id) +{ if (this->children == NULL || this->children->size() == 0) return NULL; @@ -87,7 +95,7 @@ const string& ProtocolTreeNode::getAttributeValue(const string& attribute) if (this->attributes == NULL) return nilstr; - map::iterator it = attributes->find(attribute); + map::iterator it = attributes->find(attribute); if (it == attributes->end()) return nilstr; @@ -128,6 +136,48 @@ bool ProtocolTreeNode::tagEquals(ProtocolTreeNode *node, const string& tag) void ProtocolTreeNode::require(ProtocolTreeNode *node, const string& tag) { - if (!tagEquals(node, tag)) - throw WAException("failed require. node:" + node->toString() + "tag: " + tag, WAException::CORRUPT_STREAM_EX, 0); + if (!tagEquals(node, tag)) + throw WAException("failed require. node:" + node->toString() + "tag: " + tag, WAException::CORRUPT_STREAM_EX, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +ProtocolTreeNode& operator<<(ProtocolTreeNode &node, const XATTR &attr) +{ + if (node.attributes == NULL) + node.attributes = new map; + + (*node.attributes)[attr.name] = attr.value; + return node; +} + +ProtocolTreeNode* operator<<(ProtocolTreeNode *node, const XATTR &attr) +{ + if (node->attributes == NULL) + node->attributes = new map; + + (*node->attributes)[attr.name] = attr.value; + return node; +} + +ProtocolTreeNode& operator<<(ProtocolTreeNode &node, const XATTRI &attr) +{ + if (node.attributes == NULL) + node.attributes = new map; + + char szValue[100]; + _itoa_s(attr.value, szValue, 10); + (*node.attributes)[attr.name] = szValue; + return node; +} + +ProtocolTreeNode* operator<<(ProtocolTreeNode *node, const XATTRI &attr) +{ + if (node->attributes == NULL) + node->attributes = new map; + + char szValue[100]; + _itoa_s(attr.value, szValue, 10); + (*node->attributes)[attr.name] = szValue; + return node; } diff --git a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h index d810852314..0731d97ab1 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h +++ b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h @@ -14,6 +14,37 @@ using namespace std; +struct XATTR +{ + __forceinline XATTR(const char *_name, const char *_value) : + name(_name), value(_value) + {} + + __forceinline XATTR(const char *_name, const std::string &_value) : + name(_name), value(_value.c_str()) + {} + + __forceinline XATTR(const std::string &_name, const std::string &_value) : + name(_name.c_str()), value(_value.c_str()) + {} + + const char *name, *value; +}; + +struct XATTRI +{ + __forceinline XATTRI(const char *_name, int _value) : + name(_name), value(_value) + {} + + __forceinline XATTRI(const std::string &_name, int _value) : + name(_name.c_str()), value(_value) + {} + + const char *name; + int value; +}; + class ProtocolTreeNode { public: vector* data; @@ -21,8 +52,8 @@ public: map *attributes; vector *children; - ProtocolTreeNode(const string& tag, map *attributes, ProtocolTreeNode* child); - ProtocolTreeNode(const string& tag, map *attributes, vector* data = NULL, vector *children = NULL); + ProtocolTreeNode(const string& tag, ProtocolTreeNode* child); + ProtocolTreeNode(const string& tag, vector* data = NULL, vector *children = NULL); string toString(); ProtocolTreeNode* getChild(const string& id); ProtocolTreeNode* getChild(size_t id); @@ -38,4 +69,10 @@ public: virtual ~ProtocolTreeNode(); }; +ProtocolTreeNode& operator<<(ProtocolTreeNode&, const XATTR&); +ProtocolTreeNode* operator<<(ProtocolTreeNode*, const XATTR&); + +ProtocolTreeNode& operator<<(ProtocolTreeNode&, const XATTRI&); +ProtocolTreeNode* operator<<(ProtocolTreeNode*, const XATTRI&); + #endif /* PROTOCOLNODE_H_ */ \ No newline at end of file diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp index 352d49b07d..83310b4ac2 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp @@ -5,10 +5,9 @@ * Author: Antonio */ -#include "WAConnection.h" +#include "../common.h" // #TODO Remove Miranda-dependency + #include "ProtocolTreeNode.h" -#include -#include #include "utilities.h" const char* WAConnection::dictionary[] = { @@ -104,62 +103,49 @@ void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException) _LOGDATA("media-url:%s", message->media_url.c_str()); if (message->media_wa_type == FMessage::WA_TYPE_SYSTEM) throw new WAException("Cannot send system message over the network"); - std::map* attribs = new std::map(); - (*attribs)["xmlns"] = "urn:xmpp:whatsapp:mms"; - (*attribs)["type"] = FMessage::getMessage_WA_Type_StrValue(message->media_wa_type); + + ProtocolTreeNode* mediaNode; + if (message->media_wa_type == FMessage::WA_TYPE_CONTACT && !message->media_name.empty()) { + ProtocolTreeNode* vcardNode = new ProtocolTreeNode("vcard", new std::vector(message->data.begin(), message->data.end())) + << XATTR("name", message->media_name); + mediaNode = new ProtocolTreeNode("media", vcardNode); + } + else { + mediaNode = new ProtocolTreeNode("media", new std::vector(message->data.begin(), message->data.end()), NULL) + << XATTR("encoding", "text"); + } + + mediaNode << XATTR("xmlns", "urn:xmpp:whatsapp:mms") << XATTR("type", FMessage::getMessage_WA_Type_StrValue(message->media_wa_type)); if (message->media_wa_type == FMessage::WA_TYPE_LOCATION) { - (*attribs)["latitude"] = Utilities::doubleToStr(message->latitude); - (*attribs)["longitude"] = Utilities::doubleToStr(message->longitude); + mediaNode << XATTR("latitude", Utilities::doubleToStr(message->latitude)) << XATTR("longitude", Utilities::doubleToStr(message->longitude)); } else { if (message->media_wa_type != FMessage::WA_TYPE_CONTACT && !message->media_name.empty() && !message->media_url.empty() && message->media_size > 0L) { - (*attribs)["file"] = message->media_name; - (*attribs)["size"] = Utilities::intToStr((int)message->media_size); - (*attribs)["url"] = message->media_url; + mediaNode << XATTR("file", message->media_name) << XATTRI("size", message->media_size) << XATTR("url", message->media_url); } else { - (*attribs)["file"] = message->media_name; - (*attribs)["size"] = Utilities::intToStr((int)message->media_size); - (*attribs)["url"] = message->media_url; - (*attribs)["seconds"] = Utilities::intToStr(message->media_duration_seconds); + mediaNode << XATTR("file", message->media_name) << XATTRI("size", message->media_size) + << XATTR("url", message->media_url) << XATTRI("seconds", message->media_duration_seconds); } } - ProtocolTreeNode* mediaNode; - if (message->media_wa_type == FMessage::WA_TYPE_CONTACT && !message->media_name.empty()) { - std::map* attribs2 = new std::map(); - (*attribs2)["name"] = message->media_name; - ProtocolTreeNode* vcardNode = new ProtocolTreeNode("vcard", attribs2, new std::vector(message->data.begin(), message->data.end())); - mediaNode = new ProtocolTreeNode("media", attribs, vcardNode); - } - else { - (*attribs)["encoding"] = "text"; - mediaNode = new ProtocolTreeNode("media", attribs, new std::vector(message->data.begin(), message->data.end()), NULL); - } - - ProtocolTreeNode* root = WAConnection::getMessageNode(message, mediaNode); - this->out->write(root); - delete root; + this->out->write(WAConnection::getMessageNode(message, mediaNode)); } void WAConnection::sendMessageWithBody(FMessage* message) throw (WAException) { - ProtocolTreeNode* bodyNode = new ProtocolTreeNode("body", NULL, new std::vector(message->data.begin(), message->data.end())); - ProtocolTreeNode* root = WAConnection::getMessageNode(message, bodyNode); - this->out->write(root); - delete root; + ProtocolTreeNode* bodyNode = new ProtocolTreeNode("body", new std::vector(message->data.begin(), message->data.end())); + this->out->write(WAConnection::getMessageNode(message, bodyNode)); } -ProtocolTreeNode* WAConnection::getMessageNode(FMessage* message, ProtocolTreeNode* child) +ProtocolTreeNode WAConnection::getMessageNode(FMessage* message, ProtocolTreeNode* child) { ProtocolTreeNode* requestNode = NULL; - ProtocolTreeNode* serverNode = new ProtocolTreeNode("server", NULL); - std::map* attrib = new std::map(); - (*attrib)["xmlns"] = "jabber:x:event"; + ProtocolTreeNode* serverNode = new ProtocolTreeNode("server"); std::vector* children = new std::vector(1); (*children)[0] = serverNode; - ProtocolTreeNode* xNode = new ProtocolTreeNode("x", attrib, NULL, children); + ProtocolTreeNode* xNode = new ProtocolTreeNode("x", NULL, children) << XATTR("xmlns", "jabber:x:event"); int childCount = (requestNode == NULL ? 0 : 1) + 2; std::vector* messageChildren = new std::vector(childCount); int i = 0; @@ -172,12 +158,8 @@ ProtocolTreeNode* WAConnection::getMessageNode(FMessage* message, ProtocolTreeNo (*messageChildren)[i] = child; i++; - std::map* attrib2 = new std::map(); - (*attrib2)["to"] = message->key->remote_jid; - (*attrib2)["type"] = "chat"; - (*attrib2)["id"] = message->key->id; - - return new ProtocolTreeNode("message", attrib2, NULL, messageChildren); + return ProtocolTreeNode("message", NULL, messageChildren) << + XATTR("to", message->key->remote_jid) << XATTR("type", "chat") << XATTR("id", message->key->id); } void WAConnection::sendMessage(FMessage* message) throw(WAException) @@ -195,11 +177,7 @@ void WAConnection::setVerboseId(bool b) void WAConnection::sendAvailableForChat() throw(WAException) { - std::map* attribs = new std::map(); - (*attribs)["name"] = this->login->push_name; - ProtocolTreeNode *presenceNode = new ProtocolTreeNode("presence", attribs); - this->out->write(presenceNode); - delete presenceNode; + this->out->write(ProtocolTreeNode("presence") << XATTR("name", this->login->push_name)); } bool WAConnection::read() throw(WAException) @@ -338,210 +316,102 @@ bool WAConnection::read() throw(WAException) return true; } -void WAConnection::sendNop() throw(WAException) -{ - this->out->write(NULL); -} - void WAConnection::sendPing() throw(WAException) { std::string id = makeId("ping_"); this->pending_server_requests[id] = new IqResultPingHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:p"; - ProtocolTreeNode* pingNode = new ProtocolTreeNode("ping", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, pingNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* pingNode = new ProtocolTreeNode("ping") << XATTR("xmlns", "w:p"); + this->out->write(ProtocolTreeNode("iq", pingNode) << XATTR("id", id) << XATTR("type", "get")); } void WAConnection::sendPong(const std::string& id) throw(WAException) { - std::map* attribs = new std::map(); - (*attribs)["type"] = "result"; - (*attribs)["to"] = this->login->domain; - (*attribs)["id"] = id; - ProtocolTreeNode *iqNode = new ProtocolTreeNode("iq", attribs); - this->out->write(iqNode); - delete iqNode; + this->out->write(ProtocolTreeNode("iq") + << XATTR("type", "result") << XATTR("to", this->login->domain) << XATTR("id", id)); } void WAConnection::sendComposing(const std::string& to) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "http://jabber.org/protocol/chatstates"; - ProtocolTreeNode* composingNode = new ProtocolTreeNode("composing", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["to"] = to; - (*attribs2)["type"] = "chat"; - ProtocolTreeNode* messageNode = new ProtocolTreeNode("message", attribs2, composingNode); + ProtocolTreeNode* composingNode = new ProtocolTreeNode("composing") + << XATTR("xmlns", "http://jabber.org/protocol/chatstates"); - this->out->write(messageNode); - - delete messageNode; + this->out->write(ProtocolTreeNode("message", composingNode) + << XATTR("to", to) << XATTR("type", "chat")); } - void WAConnection::sendActive() throw(WAException) { - std::map* attribs = new std::map(); - (*attribs)["type"] = "active"; - ProtocolTreeNode* presenceNode = new ProtocolTreeNode("presence", attribs); - - this->out->write(presenceNode); - - delete presenceNode; + this->out->write(ProtocolTreeNode("presence") << XATTR("type", "active")); } void WAConnection::sendInactive() throw(WAException) { - std::map* attribs = new std::map(); - (*attribs)["type"] = "inactive"; - ProtocolTreeNode* presenceNode = new ProtocolTreeNode("presence", attribs); - - this->out->write(presenceNode); - - delete presenceNode; + this->out->write(ProtocolTreeNode("presence") << XATTR("type", "inactive")); } void WAConnection::sendPaused(const std::string& to) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "http://jabber.org/protocol/chatstates"; - ProtocolTreeNode* pausedNode = new ProtocolTreeNode("paused", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["to"] = to; - (*attribs2)["type"] = "chat"; - ProtocolTreeNode* messageNode = new ProtocolTreeNode("message", attribs2, pausedNode); - - this->out->write(messageNode); + ProtocolTreeNode* pausedNode = new ProtocolTreeNode("paused"); + *pausedNode << XATTR("xmlns", "http://jabber.org/protocol/chatstates"); - delete messageNode; + this->out->write(ProtocolTreeNode("message", pausedNode) << XATTR("to", to) << XATTR("type", "chat")); } void WAConnection::sendSubjectReceived(const std::string& to, const std::string& id)throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:receipts"; - ProtocolTreeNode* receivedNode = new ProtocolTreeNode("received", attribs1); - - ProtocolTreeNode* messageNode = getSubjectMessage(to, id, receivedNode); - - this->out->write(messageNode); + ProtocolTreeNode* receivedNode = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts"); - delete messageNode; -} - -ProtocolTreeNode* WAConnection::getSubjectMessage(const std::string& to, const std::string& id, ProtocolTreeNode* child) throw (WAException) -{ - std::map* attribs1 = new std::map(); - (*attribs1)["to"] = to; - (*attribs1)["type"] = "subject"; - (*attribs1)["id"] = id; - ProtocolTreeNode* messageNode = new ProtocolTreeNode("message", attribs1, child); - - return messageNode; + this->out->write(ProtocolTreeNode("message", receivedNode) + << XATTR("to", to) << XATTR("type", "subject") << XATTR("id", id)); } void WAConnection::sendMessageReceived(FMessage* message) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:receipts"; - ProtocolTreeNode* receivedNode = new ProtocolTreeNode("received", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["to"] = message->key->remote_jid; - (*attribs2)["type"] = "chat"; - (*attribs2)["id"] = message->key->id; + ProtocolTreeNode* receivedNode = new ProtocolTreeNode("received") + << XATTR("xmlns", "urn:xmpp:receipts"); - ProtocolTreeNode* messageNode = new ProtocolTreeNode("message", attribs2, receivedNode); - - this->out->write(messageNode); - delete messageNode; + this->out->write(ProtocolTreeNode("message", receivedNode) + << XATTR("to", message->key->remote_jid) << XATTR("type", "chat") << XATTR("id", message->key->id)); } void WAConnection::sendDeliveredReceiptAck(const std::string& to, const std::string& id) throw(WAException) { - ProtocolTreeNode *root = getReceiptAck(to, id, "delivered"); - this->out->write(root); - delete root; + this->out->write(getReceiptAck(to, id, "delivered")); } void WAConnection::sendVisibleReceiptAck(const std::string& to, const std::string& id) throw (WAException) { - ProtocolTreeNode *root = getReceiptAck(to, id, "visible"); - this->out->write(root); - delete root; + this->out->write(getReceiptAck(to, id, "visible")); } void WAConnection::sendPresenceSubscriptionRequest(const std::string& to) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["type"] = "subscribe"; - (*attribs1)["to"] = to; - ProtocolTreeNode* presenceNode = new ProtocolTreeNode("presence", attribs1); - this->out->write(presenceNode); - delete presenceNode; + this->out->write(ProtocolTreeNode("presence") << XATTR("type", "subscribe") << XATTR("to", to)); } void WAConnection::sendClientConfig(const std::string& sound, const std::string& pushID, bool preview, const std::string& platform) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:whatsapp:push"; - (*attribs1)["sound"] = sound; - (*attribs1)["id"] = pushID; - (*attribs1)["preview"] = preview ? "1" : "0"; - (*attribs1)["platform"] = platform; - ProtocolTreeNode* configNode = new ProtocolTreeNode("config", attribs1); + ProtocolTreeNode* configNode = new ProtocolTreeNode("config") + << XATTR("xmlns", "urn:xmpp:whatsapp:push") << XATTR("sound", sound) << XATTR("id", pushID) << XATTR("preview", preview ? "1" : "0") << XATTR("platform", platform); std::string id = makeId("config_"); - this->pending_server_requests[id] = new IqSendClientConfigHandler(this); - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "set"; - (*attribs2)["to"] = this->login->domain; - - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, configNode); - - this->out->write(iqNode); - delete iqNode; - + this->out->write(ProtocolTreeNode("iq", configNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->login->domain)); } void WAConnection::sendClientConfig(const std::string& pushID, bool preview, const std::string& platform, bool defaultSettings, bool groupSettings, const std::vector& groups) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:whatsapp:push"; - (*attribs1)["id"] = pushID; - (*attribs1)["lg"] = "en"; - (*attribs1)["lc"] = "US"; - (*attribs1)["clear"] = "0"; - (*attribs1)["preview"] = preview ? "1" : "0"; - (*attribs1)["platform"] = platform; - (*attribs1)["default"] = defaultSettings ? "1" : "0"; - (*attribs1)["groups"] = groupSettings ? "1" : "0"; - ProtocolTreeNode* configNode = new ProtocolTreeNode("config", attribs1, NULL, this->processGroupSettings(groups)); - std::string id = makeId("config_"); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "set"; - (*attribs2)["to"] = this->login->domain; + ProtocolTreeNode* configNode = new ProtocolTreeNode("config", NULL, this->processGroupSettings(groups)) + << XATTR("xmlns", "urn:xmpp:whatsapp:push") << XATTR("id", pushID) << XATTR("lg", "en") << XATTR("lc", "US") << XATTR("clear", "0") + << XATTR("preview", preview ? "1" : "0") << XATTR("platform", platform) + << XATTR("default", defaultSettings ? "1" : "0") << XATTR("groups", groupSettings ? "1" : "0"); - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, configNode); - this->out->write(iqNode); - delete iqNode; + std::string id = makeId("config_"); + this->out->write(ProtocolTreeNode("iq", configNode) << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->login->domain)); } std::vector* WAConnection::processGroupSettings(const std::vector& groups) @@ -550,13 +420,9 @@ std::vector* WAConnection::processGroupSettings(const std::ve if (!groups.empty()) { time_t now = time(NULL); for (size_t i = 0; i < groups.size(); i++) { - std::map* attribs = new std::map(); - (*attribs)["jid"] = groups[i].jid; - (*attribs)["notify"] = (groups[i].enabled ? "1" : "0"); - (*attribs)["mute"] = Utilities::intToStr(int(groups[i].muteExpiry > now ? (groups[i].muteExpiry - now) : 0)); - _LOGDATA("mute group %s, %s", (*attribs)["jid"].c_str(), (*attribs)["mute"].c_str()); - - (*result)[i] = new ProtocolTreeNode("item", attribs); + (*result)[i] = new ProtocolTreeNode("item") + << XATTR("jid", groups[i].jid) << XATTR("notify", (groups[i].enabled ? "1" : "0")) + << XATTRI("mute", (groups[i].muteExpiry > now) ? groups[i].muteExpiry - now : 0); } } @@ -575,20 +441,12 @@ std::string WAConnection::makeId(const std::string& prefix) return id; } -ProtocolTreeNode* WAConnection::getReceiptAck(const std::string& to, const std::string& id, const std::string& receiptType) throw(WAException) +ProtocolTreeNode WAConnection::getReceiptAck(const std::string& to, const std::string& id, const std::string& receiptType) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:receipts"; - (*attribs1)["type"] = receiptType; - ProtocolTreeNode* ackNode = new ProtocolTreeNode("ack", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["to"] = to; - (*attribs2)["type"] = "chat"; - (*attribs2)["id"] = id; - ProtocolTreeNode* messageNode = new ProtocolTreeNode("message", attribs2, ackNode); - - return messageNode; + ProtocolTreeNode* ackNode = new ProtocolTreeNode("ack") + << XATTR("xmlns", "urn:xmpp:receipts") << XATTR("type", receiptType); + + return ProtocolTreeNode("message", ackNode) << XATTR("to", to) << XATTR("type", "chat") << XATTR("id", id); } std::map* WAConnection::parseCategories(ProtocolTreeNode* dirtyNode) throw (WAException) @@ -805,27 +663,15 @@ bool WAConnection::supportsReceiptAcks() void WAConnection::sendNotificationReceived(const std::string& jid, const std::string& id) throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:receipts"; - ProtocolTreeNode* child = new ProtocolTreeNode("received", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "notification"; - (*attribs2)["to"] = jid; - ProtocolTreeNode* node = new ProtocolTreeNode("message", attribs2, child); + ProtocolTreeNode* child = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts"); - this->out->write(node); - delete node; + this->out->write(ProtocolTreeNode("message", child) + << XATTR("id", id) << XATTR("type", "notification") << XATTR("to", jid)); } void WAConnection::sendClose() throw(WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["type"] = "unavailable"; - ProtocolTreeNode* presenceNode = new ProtocolTreeNode("presence", attribs1); - this->out->write(presenceNode); - delete presenceNode; + this->out->write(ProtocolTreeNode("presence") << XATTR("type", "unavailable")); this->out->streamEnd(); } @@ -834,41 +680,21 @@ void WAConnection::sendGetPrivacyList() throw (WAException) std::string id = makeId("privacylist_"); this->pending_server_requests[id] = new IqResultPrivayListHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["name"] = "default"; - ProtocolTreeNode* listNode = new ProtocolTreeNode("list", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["xmlns"] = "jabber:iq:privacy"; - ProtocolTreeNode* queryNode = new ProtocolTreeNode("query", attribs2, listNode); - - std::map* attribs3 = new std::map(); - (*attribs3)["id"] = id; - (*attribs3)["type"] = "get"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs3, queryNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* listNode = new ProtocolTreeNode("list") << XATTR("name", "default"); + ProtocolTreeNode* queryNode = new ProtocolTreeNode("query", listNode) << XATTR("xmlns", "jabber:iq:privacy"); + this->out->write(ProtocolTreeNode("iq", queryNode) << XATTR("id", id) << XATTR("type", "get")); } void WAConnection::sendGetServerProperties() throw (WAException) { std::string id = makeId("get_server_properties_"); this->pending_server_requests[id] = new IqResultServerPropertiesHandler(this); + + ProtocolTreeNode* listNode = new ProtocolTreeNode("list") + << XATTR("xmlns", "w:g") << XATTR("type", "props"); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - (*attribs1)["type"] = "props"; - ProtocolTreeNode* listNode = new ProtocolTreeNode("list", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - (*attribs2)["to"] = "g.us"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, listNode); - - this->out->write(iqNode); - delete iqNode; + this->out->write(ProtocolTreeNode("iq", listNode) + << XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us")); } void WAConnection::sendGetGroups() throw (WAException) @@ -893,19 +719,11 @@ void WAConnection::sendGetOwningGroups() throw (WAException) void WAConnection::sendGetGroups(const std::string& id, const std::string& type) throw (WAException) { - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - (*attribs1)["type"] = type; - ProtocolTreeNode* listNode = new ProtocolTreeNode("list", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - (*attribs2)["to"] = "g.us"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, listNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* listNode = new ProtocolTreeNode("list") + << XATTR("xmlns", "w:g") << XATTR("type", type); + + this->out->write(ProtocolTreeNode("iq", listNode) + << XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us")); } void WAConnection::readGroupList(ProtocolTreeNode* node, std::vector& groups) throw (WAException) @@ -936,18 +754,9 @@ void WAConnection::sendQueryLastOnline(const std::string& jid) throw (WAExceptio std::string id = makeId("last_"); this->pending_server_requests[id] = new IqResultQueryLastOnlineHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "jabber:iq:last"; - ProtocolTreeNode* queryNode = new ProtocolTreeNode("query", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - (*attribs2)["to"] = jid; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, queryNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* queryNode = new ProtocolTreeNode("query") << XATTR("xmlns", "jabber:iq:last"); + this->out->write(ProtocolTreeNode("iq", queryNode) + << XATTR("id", id) << XATTR("type", "get") << XATTR("to", jid)); } void WAConnection::sendGetGroupInfo(const std::string& gjid) throw (WAException) @@ -955,18 +764,9 @@ void WAConnection::sendGetGroupInfo(const std::string& gjid) throw (WAException) std::string id = makeId("get_g_info_"); this->pending_server_requests[id] = new IqResultGetGroupInfoHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - ProtocolTreeNode* queryNode = new ProtocolTreeNode("query", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - (*attribs2)["to"] = gjid; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, queryNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* queryNode = new ProtocolTreeNode("query") << XATTR("xmlns", "w:g"); + this->out->write(ProtocolTreeNode("iq", queryNode) + << XATTR("id", id) << XATTR("type", "get") << XATTR("to", gjid)); } void WAConnection::sendGetParticipants(const std::string& gjid) throw (WAException) @@ -974,18 +774,9 @@ void WAConnection::sendGetParticipants(const std::string& gjid) throw (WAExcepti std::string id = makeId("get_participants_"); this->pending_server_requests[id] = new IqResultGetGroupParticipantsHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - ProtocolTreeNode* listNode = new ProtocolTreeNode("list", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - (*attribs2)["to"] = gjid; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, listNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* listNode = new ProtocolTreeNode("list") << XATTR("xmlns", "w:g"); + this->out->write(ProtocolTreeNode("iq", listNode) + << XATTR("id", id) << XATTR("type", "get") << XATTR("to", gjid)); } void WAConnection::readAttributeList(ProtocolTreeNode* node, std::vector& vector, const std::string& tag, const std::string& attribute) throw (WAException) @@ -1003,39 +794,20 @@ void WAConnection::sendCreateGroupChat(const std::string& subject) throw (WAExce std::string id = makeId("create_group_"); this->pending_server_requests[id] = new IqResultCreateGroupChatHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - (*attribs1)["action"] = "create"; - (*attribs1)["subject"] = subject; - ProtocolTreeNode* groupNode = new ProtocolTreeNode("group", attribs1); + ProtocolTreeNode* groupNode = new ProtocolTreeNode("group") + << XATTR("xmlns", "w:g") << XATTR("action", "create") << XATTR("subject", subject); - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "set"; - (*attribs2)["to"] = "g.us"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, groupNode); - - this->out->write(iqNode); - delete iqNode; + this->out->write(ProtocolTreeNode("iq", groupNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", "g.us")); } void WAConnection::sendEndGroupChat(const std::string& gjid) throw (WAException) { std::string id = makeId("remove_group_"); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - (*attribs1)["action"] = "delete"; - ProtocolTreeNode* groupNode = new ProtocolTreeNode("group", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "set"; - (*attribs2)["to"] = gjid; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, groupNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* groupNode = new ProtocolTreeNode("group") << XATTR("xmlns", "w:g") << XATTR("action", "delete"); + this->out->write(ProtocolTreeNode("iq", groupNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid)); } void WAConnection::sendClearDirty(const std::string& category) throw (WAException) @@ -1043,44 +815,20 @@ void WAConnection::sendClearDirty(const std::string& category) throw (WAExceptio std::string id = makeId("clean_dirty_"); this->pending_server_requests[id] = new IqResultClearDirtyHandler(this); - std::map* attribs1 = new std::map(); - (*attribs1)["name"] = category; - ProtocolTreeNode* categoryNode = new ProtocolTreeNode("category", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["xmlns"] = "urn:xmpp:whatsapp:dirty"; - ProtocolTreeNode* cleanNode = new ProtocolTreeNode("clean", attribs2, categoryNode); - - std::map* attribs3 = new std::map(); - (*attribs3)["id"] = id; - (*attribs3)["type"] = "set"; - (*attribs3)["to"] = "s.whatsapp.net"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs3, cleanNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* categoryNode = new ProtocolTreeNode("category") << XATTR("name", category); + ProtocolTreeNode* cleanNode = new ProtocolTreeNode("clean", categoryNode) << XATTR("xmlns", "urn:xmpp:whatsapp:dirty"); + this->out->write(ProtocolTreeNode("iq", cleanNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", "s.whatsapp.net")); } void WAConnection::sendLeaveGroup(const std::string& gjid) throw (WAException) { std::string id = makeId("leave_group_"); - std::map* attribs1 = new std::map(); - (*attribs1)["id"] = gjid; - ProtocolTreeNode* groupNode = new ProtocolTreeNode("group", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["xmlns"] = "w:g"; - ProtocolTreeNode* leaveNode = new ProtocolTreeNode("leave", attribs2, groupNode); - - std::map* attribs3 = new std::map(); - (*attribs3)["id"] = id; - (*attribs3)["type"] = "set"; - (*attribs3)["to"] = "g.us"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs3, leaveNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* groupNode = new ProtocolTreeNode("group") << XATTR("id", gjid); + ProtocolTreeNode* leaveNode = new ProtocolTreeNode("leave", groupNode) << XATTR("xmlns", "w:g"); + this->out->write(ProtocolTreeNode("iq", leaveNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", "g.us")); } void WAConnection::sendAddParticipants(const std::string& gjid, const std::vector& participants) throw (WAException) @@ -1099,43 +847,25 @@ void WAConnection::sendVerbParticipants(const std::string& gjid, const std::vect { size_t size = participants.size(); std::vector* children = new std::vector(size); - for (size_t i = 0; i < size; i++) { - std::map* attribs1 = new std::map(); - (*attribs1)["jid"] = participants[i]; - (*children)[i] = new ProtocolTreeNode("participant", attribs1); - } + for (size_t i = 0; i < size; i++) + (*children)[i] = new ProtocolTreeNode("participant") << XATTR("jid", participants[i]); - std::map* attribs2 = new std::map(); - (*attribs2)["xmlns"] = "w:g"; - ProtocolTreeNode* innerNode = new ProtocolTreeNode(inner_tag, attribs2, NULL, children); + ProtocolTreeNode* innerNode = new ProtocolTreeNode(inner_tag, NULL, children) + << XATTR("xmlns", "w:g"); - std::map* attribs3 = new std::map(); - (*attribs3)["id"] = id; - (*attribs3)["type"] = "set"; - (*attribs3)["to"] = gjid; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs3, innerNode); - - this->out->write(iqNode); - delete iqNode; + this->out->write(ProtocolTreeNode("iq", innerNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid)); } void WAConnection::sendSetNewSubject(const std::string& gjid, const std::string& subject) throw (WAException) { std::string id = this->makeId("set_group_subject_"); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:g"; - (*attribs1)["value"] = subject; - ProtocolTreeNode* subjectNode = new ProtocolTreeNode("subject", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "set"; - (*attribs2)["to"] = gjid; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, subjectNode); + ProtocolTreeNode* subjectNode = new ProtocolTreeNode("subject") + << XATTR("xmlns", "w:g") << XATTR("value", subject); - this->out->write(iqNode); - delete iqNode; + this->out->write(ProtocolTreeNode("iq", subjectNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid)); } std::string WAConnection::removeResourceFromJid(const std::string& jid) @@ -1151,10 +881,8 @@ void WAConnection::sendStatusUpdate(std::string& status) throw (WAException) { std::string id = this->makeId(Utilities::intToStr((int)time(NULL))); FMessage* message = new FMessage(new Key("s.us", true, id)); - ProtocolTreeNode* body = new ProtocolTreeNode("body", NULL, new std::vector(status.begin(), status.end()), NULL); - ProtocolTreeNode* messageNode = getMessageNode(message, body); - this->out->write(messageNode); - delete messageNode; + ProtocolTreeNode* body = new ProtocolTreeNode("body", new std::vector(status.begin(), status.end()), NULL); + this->out->write(getMessageNode(message, body)); delete message; } @@ -1163,19 +891,9 @@ void WAConnection::sendSetPicture(const std::string& jid, std::vectormakeId("set_photo_"); this->pending_server_requests[id] = new IqResultSetPhotoHandler(this, jid); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:profile:picture"; - // (*attribs1)["type"] = "image"; - ProtocolTreeNode* listNode = new ProtocolTreeNode("picture", attribs1, data, NULL); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "set"; - (*attribs2)["to"] = jid; - - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, listNode); - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* listNode = new ProtocolTreeNode("picture", data, NULL) << XATTR("xmlns", "w:profile:picture"); + this->out->write(ProtocolTreeNode("iq", listNode) + << XATTR("id", id) << XATTR("type", "set") << XATTR("to", jid)); } void WAConnection::sendGetPicture(const std::string& jid, const std::string& type, const std::string& oldId, const std::string& newId) throw (WAException) @@ -1183,19 +901,11 @@ void WAConnection::sendGetPicture(const std::string& jid, const std::string& typ std::string id = makeId("get_picture_"); this->pending_server_requests[id] = new IqResultGetPhotoHandler(this, jid, oldId, newId); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:profile:picture"; - (*attribs1)["type"] = type; - ProtocolTreeNode* listNode = new ProtocolTreeNode("picture", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["to"] = jid; - (*attribs2)["type"] = "get"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, listNode); + ProtocolTreeNode* listNode = new ProtocolTreeNode("picture") + << XATTR("xmlns", "w:profile:picture") << XATTR("type", type); - this->out->write(iqNode); - delete iqNode; + this->out->write(ProtocolTreeNode("iq", listNode) + << XATTR("id", id) << XATTR("to", jid) << XATTR("type", "get")); } void WAConnection::sendGetPictureIds(const std::vector& jids) throw (WAException) @@ -1205,23 +915,12 @@ void WAConnection::sendGetPictureIds(const std::vector& jids) throw std::vector* children = new std::vector(); for (size_t i = 0; i < jids.size(); i++) { - std::map* attribs = new std::map(); - (*attribs)["jid"] = jids[i]; - ProtocolTreeNode* child = new ProtocolTreeNode("user", attribs); + ProtocolTreeNode* child = new ProtocolTreeNode("user") << XATTR("jid", jids[i]); children->push_back(child); } - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "w:profile:picture"; - ProtocolTreeNode* queryNode = new ProtocolTreeNode("list", attribs1, NULL, children); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - ProtocolTreeNode* iqNode = new ProtocolTreeNode("iq", attribs2, queryNode); - - this->out->write(iqNode); - delete iqNode; + ProtocolTreeNode* queryNode = new ProtocolTreeNode("list", NULL, children) << XATTR("xmlns", "w:profile:picture"); + this->out->write(ProtocolTreeNode("iq", queryNode) << XATTR("id", id) << XATTR("type", "get")); } void WAConnection::sendDeleteAccount() throw (WAException) @@ -1229,16 +928,7 @@ void WAConnection::sendDeleteAccount() throw (WAException) std::string id = makeId("del_acct_"); this->pending_server_requests[id] = new IqResultSendDeleteAccount(this); - std::map* attribs1 = new std::map(); - (*attribs1)["xmlns"] = "urn:xmpp:whatsapp:account"; - ProtocolTreeNode* node1 = new ProtocolTreeNode("remove", attribs1); - - std::map* attribs2 = new std::map(); - (*attribs2)["id"] = id; - (*attribs2)["type"] = "get"; - (*attribs2)["to"] = "s.whatsapp.net"; - - ProtocolTreeNode* node2 = new ProtocolTreeNode("iq", attribs2, node1); - this->out->write(node2); - delete node2; + ProtocolTreeNode* node1 = new ProtocolTreeNode("remove") << XATTR("xmlns", "urn:xmpp:whatsapp:account"); + this->out->write(ProtocolTreeNode("iq", node1) + << XATTR("id", id) << XATTR("type", "get") << XATTR("to", "s.whatsapp.net")); } diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h index 92a8b82e4c..0271e8dc66 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h @@ -370,7 +370,7 @@ class WAConnection { void sendMessageWithBody(FMessage* message) throw(WAException); std::map* parseCategories(ProtocolTreeNode* node) throw(WAException); void parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* node) throw(WAException); - ProtocolTreeNode* getReceiptAck(const std::string& to, const std::string& id, const std::string& receiptType) throw(WAException); + ProtocolTreeNode getReceiptAck(const std::string& to, const std::string& id, const std::string& receiptType) throw(WAException); std::string makeId(const std::string& prefix); void sendGetGroups(const std::string& id, const std::string& type) throw (WAException); void readGroupList(ProtocolTreeNode* node, std::vector& groups) throw (WAException); @@ -378,8 +378,7 @@ class WAConnection { void readAttributeList(ProtocolTreeNode* node, std::vector& vector, const std::string& tag, const std::string& attribute) throw (WAException); void sendVerbParticipants(const std::string& gjid, const std::vector& participants, const std::string& id, const std::string& inner_tag) throw (WAException); bool supportsReceiptAcks(); - static ProtocolTreeNode* getMessageNode(FMessage* message, ProtocolTreeNode* node); - static ProtocolTreeNode* getSubjectMessage(const std::string& to, const std::string& id, ProtocolTreeNode* child) throw (WAException); + static ProtocolTreeNode getMessageNode(FMessage* message, ProtocolTreeNode* node); std::vector* processGroupSettings(const std::vector& gruops); public: @@ -407,7 +406,6 @@ class WAConnection { void sendMessage(FMessage* message) throw(WAException); void sendAvailableForChat() throw(WAException); bool read() throw(WAException); - void sendNop() throw(WAException); void sendPing() throw(WAException); void sendQueryLastOnline(const std::string& jid) throw (WAException); void sendPong(const std::string& id) throw(WAException); diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp index 459cc7efe9..0e0ebc22d7 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp @@ -20,7 +20,8 @@ using namespace Utilities; const std::string WALogin::NONCE_KEY = "nonce=\""; -WALogin::WALogin(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNodeWriter *writer, const std::string& domain, const std::string& user, const std::string& resource, const std::string& password, const std::string& push_name) { +WALogin::WALogin(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNodeWriter *writer, const std::string& domain, const std::string& user, const std::string& resource, const std::string& password, const std::string& push_name) +{ this->connection = connection; this->inn = reader; this->out = writer; @@ -35,7 +36,8 @@ WALogin::WALogin(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNod this->outputKey = NULL; } -std::vector* WALogin::login(const std::vector& authBlob) { +std::vector* WALogin::login(const std::vector& authBlob) +{ this->out->streamStart(this->domain, this->resource); _LOGDATA("sent stream start"); @@ -65,44 +67,32 @@ BinTreeNodeWriter* WALogin::getTreeNodeWriter() return this->out; } -void WALogin::sendResponse(const std::vector& challengeData) { +void WALogin::sendResponse(const std::vector& challengeData) +{ std::vector* authBlob = this->getAuthBlob(challengeData); - - ProtocolTreeNode node("response", NULL, authBlob); - - this->out->write(&node); + this->out->write(ProtocolTreeNode("response", authBlob)); } void WALogin::sendFeatures() { - ProtocolTreeNode* child = new ProtocolTreeNode("receipt_acks", NULL); + ProtocolTreeNode* child = new ProtocolTreeNode("receipt_acks"); std::vector* children = new std::vector(); children->push_back(child); - std::map* attributes = new std::map(); - (*attributes)["type"] = "all"; - ProtocolTreeNode* pictureChild = new ProtocolTreeNode("w:profile:picture", attributes); - children->push_back(pictureChild); + ProtocolTreeNode* pictureChild = new ProtocolTreeNode("w:profile:picture") << XATTR("type", "all"); + children->push_back(pictureChild); - // children->push_back(new ProtocolTreeNode("status", NULL)); - - ProtocolTreeNode node("stream:features", NULL, NULL, children); - this->out->write(&node, true); + this->out->write(ProtocolTreeNode("stream:features", NULL, children), true); } void WALogin::sendAuth(const std::vector& existingChallenge) { std::vector* data = NULL; - if (!existingChallenge.empty()) { + if (!existingChallenge.empty()) data = this->getAuthBlob(existingChallenge); - } - std::map* attributes = new std::map(); - (*attributes)["mechanism"] = "WAUTH-2"; - (*attributes)["user"] = this->user; - - ProtocolTreeNode node("auth", attributes, data, NULL); - this->out->write(&node, true); + this->out->write(ProtocolTreeNode("auth", data) << + XATTR("mechanism", "WAUTH-2") << XATTR("user", this->user), true); } std::vector* WALogin::getAuthBlob(const std::vector& nonce) @@ -214,77 +204,3 @@ std::vector WALogin::readSuccess() WALogin::~WALogin() {} - -KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) : - seq(0) -{ - memcpy(key, _key, 20); - memcpy(keyMac, _keyMac, 20); - - RC4_set_key(&this->rc4, 20, this->key); - - unsigned char drop[768]; - RC4(&this->rc4, sizeof(drop), drop, drop); - - HMAC_CTX_init(&hmac); -} - -KeyStream::~KeyStream() -{ - HMAC_CTX_cleanup(&hmac); -} - -void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector& nonce, unsigned char *out) -{ - size_t cbSize = nonce.size(); - - uint8_t *pNonce = (uint8_t*)_alloca(cbSize + 1); - memcpy(pNonce, nonce.data(), cbSize); - - for (int i = 0; i < 4; i++) { - pNonce[cbSize] = i + 1; - PKCS5_PBKDF2_HMAC_SHA1(pass.data(), (int)pass.size(), pNonce, (int)cbSize+1, 2, 20, out + i*20); - } -} - -void KeyStream::decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) -{ - unsigned char digest[20]; - this->hmacsha1(buffer + offset, length, digest); - - if (memcmp(&buffer[macOffset], digest, 4)) - throw WAException("invalid MAC", WAException::CORRUPT_STREAM_EX, 0); - - unsigned char* out = (unsigned char*)_alloca(length); - RC4(&this->rc4, length, buffer + offset, out); - memcpy(buffer + offset, out, length); -} - -void KeyStream::encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) -{ - unsigned char* out = (unsigned char*)_alloca(length); - RC4(&this->rc4, length, buffer + offset, out); - memcpy(buffer + offset, out, length); - - unsigned char digest[20]; - this->hmacsha1(buffer + offset, length, digest); - memcpy(buffer + macOffset, digest, 4); -} - -void KeyStream::hmacsha1(unsigned char* text, int textLength, unsigned char *out) -{ - HMAC_Init(&hmac, this->keyMac, 20, EVP_sha1()); - HMAC_Update(&hmac, text, textLength); - - unsigned char hmacInt[4]; - hmacInt[0] = (this->seq >> 24); - hmacInt[1] = (this->seq >> 16); - hmacInt[2] = (this->seq >> 8); - hmacInt[3] = (this->seq); - HMAC_Update(&hmac, hmacInt, sizeof(hmacInt)); - - unsigned int mdLength; - HMAC_Final(&hmac, out, &mdLength); - - this->seq++; -} diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h index 2949213e53..3e08bdbe8e 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h @@ -66,10 +66,11 @@ public: int account_kind; WALogin(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNodeWriter *writer, const std::string& domain, const std::string& user, const std::string& resource, const std::string& password, const std::string& push_name); + ~WALogin(); + std::vector* login(const std::vector& blobLength); BinTreeNodeReader *getTreeNodeReader(); BinTreeNodeWriter *getTreeNodeWriter(); - virtual ~WALogin(); }; #endif /* WALOGIN_H_ */ diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp index dc28b86c69..491a39e3e4 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp @@ -1,17 +1,7 @@ -#define _CRT_SECURE_NO_WARNINGS +#include "../common.h" // #TODO Remove Miranda-dependency #include "utilities.h" -#include -#include -#include -#include -#include -#include #include "WAException.h" -#include -#include -#include -#include namespace Utilities { diff --git a/protocols/WhatsApp/src/common.h b/protocols/WhatsApp/src/common.h index ea2af49172..e6bff0462a 100644 --- a/protocols/WhatsApp/src/common.h +++ b/protocols/WhatsApp/src/common.h @@ -68,6 +68,7 @@ Copyright #include #include #include + #include "WhatsAPI++/WAConnection.h" class WhatsAppProto; -- cgit v1.2.3