summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2015-01-25 19:54:43 +0000
committerGeorge Hazan <george.hazan@gmail.com>2015-01-25 19:54:43 +0000
commit58ac4567a402d383c3edb0749b9f2fb88b8422d6 (patch)
tree224f909ab2abea950795d88b15b8b8a9e486551b /protocols/WhatsApp
parentdac1f42ef81ac1119430fd294a6b35b0b8cd6837 (diff)
less pointers, less memory problems
git-svn-id: http://svn.miranda-ng.org/main/trunk@11906 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/WhatsApp')
-rw-r--r--protocols/WhatsApp/src/WASocketConnection.cpp4
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp73
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.h8
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp26
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h7
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp19
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp64
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WAConnection.h25
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp40
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WALogin.h14
-rw-r--r--protocols/WhatsApp/src/connection.cpp28
11 files changed, 135 insertions, 173 deletions
diff --git a/protocols/WhatsApp/src/WASocketConnection.cpp b/protocols/WhatsApp/src/WASocketConnection.cpp
index 41d0b78663..c688492e4e 100644
--- a/protocols/WhatsApp/src/WASocketConnection.cpp
+++ b/protocols/WhatsApp/src/WASocketConnection.cpp
@@ -20,9 +20,8 @@ WASocketConnection::WASocketConnection(const std::string& dir, int port) throw (
noc.flags = NLOCF_V2; // | NLOCF_SSL;
this->hConn = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, reinterpret_cast<WPARAM>(this->hNetlibUser),
reinterpret_cast<LPARAM>(&noc));
- if (this->hConn == NULL) {
+ if (this->hConn == NULL)
throw WAException(getLastErrorMsg(), WAException::SOCKET_EX, WAException::SOCKET_EX_OPEN);
- }
this->connected = true;
}
@@ -45,7 +44,6 @@ void WASocketConnection::write(int i)
void WASocketConnection::makeNonBlock()
{
- //if (fcntl(socket->channel, F_SETFL, O_NONBLOCK) == -1) // #TODO !?
throw WAException("Error setting socket nonblocking!", WAException::SOCKET_EX, WAException::SOCKET_EX_OPEN);
}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp
index 16e9238a4f..492dde1027 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp
@@ -12,45 +12,17 @@
#include "ProtocolTreeNode.h"
#include "utilities.h"
-static const char *secondary_dict[] = {
- "mpeg4", "wmv", "audio/3gpp", "audio/aac", "audio/amr", "audio/mp4", "audio/mpeg", "audio/ogg", "audio/qcelp", "audio/wav",
- "audio/webm", "audio/x-caf", "audio/x-ms-wma", "image/gif", "image/jpeg", "image/png", "video/3gpp", "video/avi", "video/mp4",
- "video/mpeg", "video/quicktime", "video/x-flv", "video/x-ms-asf", "302", "400", "401", "402", "403", "404", "405", "406", "407",
- "409", "410", "500", "501", "503", "504", "abitrate", "acodec", "app_uptime", "asampfmt", "asampfreq", "audio", "clear", "conflict",
- "conn_no_nna", "cost", "currency", "duration", "extend", "file", "fps", "g_notify", "g_sound", "gcm", "gone", "google_play", "hash",
- "height", "invalid", "jid-malformed", "latitude", "lc", "lg", "live", "location", "log", "longitude", "max_groups", "max_participants",
- "max_subject", "mimetype", "mode", "napi_version", "normalize", "orighash", "origin", "passive", "password", "played",
- "policy-violation", "pop_mean_time", "pop_plus_minus", "price", "pricing", "redeem", "Replaced by new connection", "resume",
- "signature", "size", "sound", "source", "system-shutdown", "username", "vbitrate", "vcard", "vcodec", "video", "width",
- "xml-not-well-formed", "checkmarks", "image_max_edge", "image_max_kbytes", "image_quality", "ka", "ka_grow", "ka_shrink", "newmedia",
- "library", "caption", "forward", "c0", "c1", "c2", "c3", "clock_skew", "cts", "k0", "k1", "login_rtt", "m_id", "nna_msg_rtt",
- "nna_no_off_count", "nna_offline_ratio", "nna_push_rtt", "no_nna_con_count", "off_msg_rtt", "on_msg_rtt", "stat_name", "sts",
- "suspect_conn", "lists", "self", "qr", "web", "w:b", "recipient", "w:stats", "forbidden", "aurora.m4r", "bamboo.m4r", "chord.m4r",
- "circles.m4r", "complete.m4r", "hello.m4r", "input.m4r", "keys.m4r", "note.m4r", "popcorn.m4r", "pulse.m4r", "synth.m4r", "filehash",
- "max_list_recipients", "en-AU", "en-GB", "es-MX", "pt-PT", "zh-Hans", "zh-Hant", "relayelection", "relaylatency", "interruption",
- "Apex.m4r", "Beacon.m4r", "Bulletin.m4r", "By The Seaside.m4r", "Chimes.m4r", "Circuit.m4r", "Constellation.m4r", "Cosmic.m4r",
- "Crystals.m4r", "Hillside.m4r", "Illuminate.m4r", "Night Owl.m4r", "Opening.m4r", "Playtime.m4r", "Presto.m4r", "Radar.m4r",
- "Radiate.m4r", "Ripples.m4r", "Sencha.m4r", "Signal.m4r", "Silk.m4r", "Slow Rise.m4r", "Stargaze.m4r", "Summit.m4r", "Twinkle.m4r",
- "Uplift.m4r", "Waves.m4r", "voip", "eligible", "upgrade", "planned", "current", "future", "disable", "expire", "start", "stop",
- "accuracy", "speed", "bearing", "recording", "encrypt", "key", "identity", "w:gp2", "admin", "locked", "unlocked", "new", "battery",
- "archive", "adm", "plaintext_size", "compressed_size", "delivered", "msg", "pkmsg", "everyone", "v", "transport", "call-id"
-};
-
-BinTreeNodeReader::BinTreeNodeReader(WAConnection* conn, ISocketConnection* connection, const char** dictionary, const int dictionarysize)
+BinTreeNodeReader::BinTreeNodeReader(WAConnection *conn, ISocketConnection *connection) :
+ buf(BUFFER_SIZE)
{
this->conn = conn;
this->rawIn = connection;
- this->tokenMap = dictionary;
- this->tokenmapsize = dictionarysize;
this->readSize = 1;
this->in = NULL;
- this->buf = new std::vector<unsigned char>(BUFFER_SIZE);
}
BinTreeNodeReader::~BinTreeNodeReader()
{
- if (this->buf != NULL)
- delete this->buf;
if (this->in != NULL)
delete this->in;
}
@@ -88,9 +60,7 @@ ProtocolTreeNode* BinTreeNodeReader::nextTreeInternal()
data = new std::vector<unsigned char>(s->begin(), s->end());
delete s;
}
- else {
- data = (std::vector<unsigned char>*) obj->data;
- }
+ else data = (std::vector<unsigned char>*) obj->data;
ProtocolTreeNode* ret = new ProtocolTreeNode(*tag, data); ret->attributes = attribs;
delete obj;
@@ -105,20 +75,21 @@ bool BinTreeNodeReader::isListTag(int b)
void BinTreeNodeReader::decodeStream(int flags, int offset, int length)
{
+ unsigned char *pData = (unsigned char*)&buf[0];
+
if ((flags & 8) != 0) {
if (length < 4)
throw WAException("invalid length" + length, WAException::CORRUPT_STREAM_EX, 0);
length -= 4;
- unsigned char *pData = (unsigned char*)&(*this->buf)[0];
- this->conn->inputKey->decodeMessage(pData, offset + length, 0, length);
- this->rawIn->dump(pData + offset, length);
+ this->conn->inputKey.decodeMessage(pData, offset + length, 0, length);
}
+ this->rawIn->dump(pData + offset, length);
if (this->in != NULL)
delete this->in;
- this->in = new ByteArrayInputStream(this->buf, offset, length);
+ this->in = new ByteArrayInputStream(&this->buf, offset, length);
}
std::map<string, string>* BinTreeNodeReader::readAttributes(int attribCount)
@@ -172,17 +143,17 @@ ReadData* BinTreeNodeReader::readString(int token)
throw WAException("-1 token in readString", WAException::CORRUPT_STREAM_EX, -1);
int bSize;
- ReadData* ret = new ReadData();
+ ReadData *ret = new ReadData();
- if (token > 2 && token <= this->tokenmapsize) {
- if (token != this->tokenmapsize)
- ret->data = new std::string(this->tokenMap[token]);
+ if (token > 2 && token <= WAConnection::DICTIONARY_LEN) {
+ if (token != WAConnection::DICTIONARY_LEN)
+ ret->data = new std::string(WAConnection::dictionary[token]);
else {
token = readInt8(this->in);
- if (token >= 0 && token < _countof(secondary_dict))
- ret->data = new std::string(secondary_dict[token]);
- else
+ if (token >= WAConnection::EXTDICTIONARY_LEN)
throw WAException("invalid token/length in getToken", WAException::CORRUPT_STREAM_EX, 0);
+
+ ret->data = new std::string(WAConnection::extended_dict[token]);
}
ret->type = STRING;
@@ -305,12 +276,11 @@ void BinTreeNodeReader::getTopLevelStream()
int flags = (stanzaSize >> 20);
stanzaSize &= 0x0FFFFF;
- if (this->buf->size() < (size_t)stanzaSize) {
- int newsize = max((int)(this->buf->size() * 3 / 2), stanzaSize);
- delete this->buf;
- this->buf = new std::vector<unsigned char>(newsize);
+ if (this->buf.size() < (size_t)stanzaSize) {
+ int newsize = max((int)(this->buf.size() * 3 / 2), stanzaSize);
+ this->buf.resize(newsize);
}
- fillArray(*this->buf, stanzaSize, this->rawIn);
+ fillArray(this->buf, stanzaSize, this->rawIn);
this->decodeStream(flags, 0, stanzaSize);
}
@@ -351,11 +321,10 @@ void BinTreeNodeReader::streamStart()
int tag = this->in->read();
int size = readListSize(tag);
tag = this->in->read();
- if (tag != 1) {
+ if (tag != 1)
throw WAException("expecting STREAM_START in streamStart", WAException::CORRUPT_STREAM_EX, 0);
- }
- int attribCount = (size - 2 + size % 2) / 2;
+ int attribCount = (size - 2 + size % 2) / 2;
std::map<string, string>* attributes = readAttributes(attribCount);
delete attributes;
}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.h b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.h
index 4288c671f3..29fdf4ec0a 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.h
@@ -32,13 +32,11 @@ public:
class BinTreeNodeReader {
private:
- const char** tokenMap;
- int tokenmapsize;
ISocketConnection *rawIn;
ByteArrayInputStream* in;
- std::vector<unsigned char>* buf;
+ std::vector<unsigned char> buf;
int readSize;
- WAConnection* conn;
+ WAConnection *conn;
ProtocolTreeNode* nextTreeInternal();
bool isListTag(int b);
@@ -64,7 +62,7 @@ private:
public:
- BinTreeNodeReader(WAConnection* conn, ISocketConnection* connection, const char** dictionary, const int dictionarysize);
+ BinTreeNodeReader(WAConnection* conn, ISocketConnection* connection);
virtual ~BinTreeNodeReader();
ProtocolTreeNode* nextTree();
void streamStart();
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp
index d4387278e1..a4f79baf17 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp
@@ -10,15 +10,15 @@
#include "BinTreeNodeWriter.h"
#include "utilities.h"
-BinTreeNodeWriter::BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection,
- const char** dictionary, const int dictionarysize, IMutex* mutex)
+BinTreeNodeWriter::BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection, IMutex* mutex)
{
+ this->bLoggedIn = false;
this->mutex = mutex;
this->conn = conn;
this->out = new ByteArrayOutputStream(2048);
this->realOut = connection;
- for (int i = 0; i < dictionarysize; i++) {
- std::string token(dictionary[i]);
+ for (int i = 0; i < WAConnection::DICTIONARY_LEN; i++) {
+ std::string token(WAConnection::dictionary[i]);
if (token.compare("") != 0)
this->tokenMap[token] = i;
}
@@ -34,26 +34,23 @@ void BinTreeNodeWriter::writeDummyHeader()
this->out->setPosition(num2);
}
-
void BinTreeNodeWriter::processBuffer()
{
- bool flag = this->conn->outputKey != NULL;
unsigned int num = 0u;
- if (flag) {
+ if (bLoggedIn) {
long num2 = (long)this->out->getLength() + 4L;
this->out->setLength(num2);
this->out->setPosition(num2);
num |= 1u;
}
long num3 = (long)this->out->getLength() - 3L - (long) this->dataBegin;
- if (num3 >= 1048576L) {
+ if (num3 >= 1048576L)
throw WAException("Buffer too large: " + num3, WAException::CORRUPT_STREAM_EX, 0);
- }
std::vector<unsigned char>* buffer = this->out->getBuffer();
- if (flag) {
+ if (bLoggedIn) {
int num4 = (int)num3 - 4;
- this->conn->outputKey->encodeMessage(buffer->data(), this->dataBegin + 3 + num4, this->dataBegin + 3, num4);
+ this->conn->outputKey.encodeMessage(buffer->data(), this->dataBegin + 3 + num4, this->dataBegin + 3, num4);
}
(*buffer)[this->dataBegin] = (unsigned char)((unsigned long)((unsigned long)num << 4) | (unsigned long)((num3 & 16711680L) >> 16));
(*buffer)[this->dataBegin + 1] = (unsigned char)((num3 & 65280L) >> 8);
@@ -156,12 +153,11 @@ void BinTreeNodeWriter::writeString(const std::string& tag)
void BinTreeNodeWriter::writeJid(std::string* user, const std::string& server)
{
this->out->write(250);
- if (user != NULL && !user->empty()) {
+ if (user != NULL && !user->empty())
writeString(*user);
- }
- else {
+ else
writeToken(0);
- }
+
writeString(server);
}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h
index c87b58f32b..e4a771f231 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h
@@ -40,6 +40,7 @@ private:
ByteArrayOutputStream *out;
IMutex* mutex;
int dataBegin;
+ bool bLoggedIn;
void writeListStart(int i);
void writeInt8(int v);
@@ -57,7 +58,9 @@ private:
void processBuffer();
public:
- BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection, const char** dictionary, const int dictionarysize, IMutex* mutex);
+ BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection, IMutex* mutex);
+ virtual ~BinTreeNodeWriter();
+
void streamStart(std::string domain, std::string resource);
void flushBuffer(bool flushNetwork);
void flushBuffer(bool flushNetwork, int startingOffset);
@@ -65,7 +68,7 @@ public:
void write(const ProtocolTreeNode &node);
void write(const ProtocolTreeNode &node, bool needsFlush);
- virtual ~BinTreeNodeWriter();
+ void setLoggedIn() { bLoggedIn = true; }
};
#endif /* BINTREENODEWRITER_H_ */
diff --git a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp
index f4741729a7..d027cb9c86 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp
@@ -14,9 +14,19 @@
using namespace Utilities;
-KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) :
+KeyStream::KeyStream() :
seq(0)
{
+ HMAC_CTX_init(&hmac);
+}
+
+KeyStream::~KeyStream()
+{
+ HMAC_CTX_cleanup(&hmac);
+}
+
+void KeyStream::init(unsigned char* _key, unsigned char* _keyMac)
+{
memcpy(key, _key, 20);
memcpy(keyMac, _keyMac, 20);
@@ -24,13 +34,6 @@ KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) :
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<unsigned char>& nonce, unsigned char *out)
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
index 83310b4ac2..48300ad530 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
@@ -36,6 +36,34 @@ const char* WAConnection::dictionary[] = {
const int WAConnection::DICTIONARY_LEN = _countof(WAConnection::dictionary);
+const char* WAConnection::extended_dict[] = {
+ "mpeg4", "wmv", "audio/3gpp", "audio/aac", "audio/amr", "audio/mp4", "audio/mpeg", "audio/ogg", "audio/qcelp", "audio/wav",
+ "audio/webm", "audio/x-caf", "audio/x-ms-wma", "image/gif", "image/jpeg", "image/png", "video/3gpp", "video/avi", "video/mp4",
+ "video/mpeg", "video/quicktime", "video/x-flv", "video/x-ms-asf", "302", "400", "401", "402", "403", "404", "405", "406", "407",
+ "409", "410", "500", "501", "503", "504", "abitrate", "acodec", "app_uptime", "asampfmt", "asampfreq", "audio", "clear", "conflict",
+ "conn_no_nna", "cost", "currency", "duration", "extend", "file", "fps", "g_notify", "g_sound", "gcm", "gone", "google_play", "hash",
+ "height", "invalid", "jid-malformed", "latitude", "lc", "lg", "live", "location", "log", "longitude", "max_groups", "max_participants",
+ "max_subject", "mimetype", "mode", "napi_version", "normalize", "orighash", "origin", "passive", "password", "played",
+ "policy-violation", "pop_mean_time", "pop_plus_minus", "price", "pricing", "redeem", "Replaced by new connection", "resume",
+ "signature", "size", "sound", "source", "system-shutdown", "username", "vbitrate", "vcard", "vcodec", "video", "width",
+ "xml-not-well-formed", "checkmarks", "image_max_edge", "image_max_kbytes", "image_quality", "ka", "ka_grow", "ka_shrink", "newmedia",
+ "library", "caption", "forward", "c0", "c1", "c2", "c3", "clock_skew", "cts", "k0", "k1", "login_rtt", "m_id", "nna_msg_rtt",
+ "nna_no_off_count", "nna_offline_ratio", "nna_push_rtt", "no_nna_con_count", "off_msg_rtt", "on_msg_rtt", "stat_name", "sts",
+ "suspect_conn", "lists", "self", "qr", "web", "w:b", "recipient", "w:stats", "forbidden", "aurora.m4r", "bamboo.m4r", "chord.m4r",
+ "circles.m4r", "complete.m4r", "hello.m4r", "input.m4r", "keys.m4r", "note.m4r", "popcorn.m4r", "pulse.m4r", "synth.m4r", "filehash",
+ "max_list_recipients", "en-AU", "en-GB", "es-MX", "pt-PT", "zh-Hans", "zh-Hant", "relayelection", "relaylatency", "interruption",
+ "Apex.m4r", "Beacon.m4r", "Bulletin.m4r", "By The Seaside.m4r", "Chimes.m4r", "Circuit.m4r", "Constellation.m4r", "Cosmic.m4r",
+ "Crystals.m4r", "Hillside.m4r", "Illuminate.m4r", "Night Owl.m4r", "Opening.m4r", "Playtime.m4r", "Presto.m4r", "Radar.m4r",
+ "Radiate.m4r", "Ripples.m4r", "Sencha.m4r", "Signal.m4r", "Silk.m4r", "Slow Rise.m4r", "Stargaze.m4r", "Summit.m4r", "Twinkle.m4r",
+ "Uplift.m4r", "Waves.m4r", "voip", "eligible", "upgrade", "planned", "current", "future", "disable", "expire", "start", "stop",
+ "accuracy", "speed", "bearing", "recording", "encrypt", "key", "identity", "w:gp2", "admin", "locked", "unlocked", "new", "battery",
+ "archive", "adm", "plaintext_size", "compressed_size", "delivered", "msg", "pkmsg", "everyone", "v", "transport", "call-id"
+};
+
+const int WAConnection::EXTDICTIONARY_LEN = _countof(WAConnection::extended_dict);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
WAConnection::WAConnection(IMutex* mutex, WAListener* event_handler, WAGroupListener* group_event_handler)
{
this->init(event_handler, group_event_handler, mutex);
@@ -43,8 +71,6 @@ WAConnection::WAConnection(IMutex* mutex, WAListener* event_handler, WAGroupList
WAConnection::~WAConnection()
{
- delete this->inputKey;
- delete this->outputKey;
delete this->in;
delete this->out;
std::map<string, IqResultHandler*>::iterator it;
@@ -54,18 +80,15 @@ WAConnection::~WAConnection()
void WAConnection::init(WAListener* event_handler, WAGroupListener* group_event_handler, IMutex* mutex)
{
- this->login = NULL;
this->event_handler = event_handler;
this->group_event_handler = group_event_handler;
- this->inputKey = NULL;
- this->outputKey = NULL;
this->in = NULL;
this->out = NULL;
this->msg_id = 0;
- this->state = 0; // 0 disconnected 1 connecting 2 connected
this->retry = true;
+ this->supports_receipt_acks = false;
this->iqid = 0;
this->verbose = true;
this->lastTreeRead = 0;
@@ -76,27 +99,18 @@ void WAConnection::init(WAListener* event_handler, WAGroupListener* group_event_
void WAConnection::setLogin(WALogin* login)
{
- this->login = login;
-
- if (login->expire_date != 0L) {
+ if (login->expire_date != 0L)
this->expire_date = login->expire_date;
- }
- if (login->account_kind != -1) {
+
+ if (login->account_kind != -1)
this->account_kind = login->account_kind;
- }
- this->jid = this->login->user + "@" + this->login->domain;
- this->fromm = this->login->user + "@" + this->login->domain + "/" + this->login->resource;
+ this->jid = user + "@" + domain;
this->in = login->getTreeNodeReader();
this->out = login->getTreeNodeWriter();
}
-WALogin* WAConnection::getLogin()
-{
- return this->login;
-}
-
void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException)
{
_LOGDATA("Send message with media %s %d", message->media_name.c_str(), message->media_size);
@@ -177,7 +191,7 @@ void WAConnection::setVerboseId(bool b)
void WAConnection::sendAvailableForChat() throw(WAException)
{
- this->out->write(ProtocolTreeNode("presence") << XATTR("name", this->login->push_name));
+ this->out->write(ProtocolTreeNode("presence") << XATTR("name", this->nick));
}
bool WAConnection::read() throw(WAException)
@@ -213,7 +227,7 @@ bool WAConnection::read() throw(WAException)
delete it->second;
this->pending_server_requests.erase(id);
}
- else if (id.compare(0, this->login->user.size(), this->login->user) == 0) {
+ else if (id.compare(0, this->user.size(), this->user) == 0) {
ProtocolTreeNode* accountNode = node->getChild(0);
ProtocolTreeNode::require(accountNode, "account");
const string &kind = accountNode->getAttributeValue("kind");
@@ -328,7 +342,7 @@ void WAConnection::sendPing() throw(WAException)
void WAConnection::sendPong(const std::string& id) throw(WAException)
{
this->out->write(ProtocolTreeNode("iq")
- << XATTR("type", "result") << XATTR("to", this->login->domain) << XATTR("id", id));
+ << XATTR("type", "result") << XATTR("to", this->domain) << XATTR("id", id));
}
void WAConnection::sendComposing(const std::string& to) throw(WAException)
@@ -400,7 +414,7 @@ void WAConnection::sendClientConfig(const std::string& sound, const std::string&
this->pending_server_requests[id] = new IqSendClientConfigHandler(this);
this->out->write(ProtocolTreeNode("iq", configNode)
- << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->login->domain));
+ << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->domain));
}
void WAConnection::sendClientConfig(const std::string& pushID, bool preview, const std::string& platform, bool defaultSettings, bool groupSettings, const std::vector<GroupSetting>& groups) throw(WAException)
@@ -411,7 +425,7 @@ void WAConnection::sendClientConfig(const std::string& pushID, bool preview, con
<< XATTR("default", defaultSettings ? "1" : "0") << XATTR("groups", groupSettings ? "1" : "0");
std::string id = makeId("config_");
- this->out->write(ProtocolTreeNode("iq", configNode) << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->login->domain));
+ this->out->write(ProtocolTreeNode("iq", configNode) << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->domain));
}
std::vector<ProtocolTreeNode*>* WAConnection::processGroupSettings(const std::vector<GroupSetting>& groups)
@@ -658,7 +672,7 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
bool WAConnection::supportsReceiptAcks()
{
- return (this->login != NULL) && (this->login->supports_receipt_acks);
+ return supports_receipt_acks;
}
void WAConnection::sendNotificationReceived(const std::string& jid, const std::string& id) throw(WAException)
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
index 0271e8dc66..983cb4e4bc 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
@@ -352,8 +352,7 @@ class WAConnection {
};
- private:
- WALogin* login;
+private:
BinTreeNodeReader* in;
BinTreeNodeWriter* out;
WAListener* event_handler;
@@ -363,8 +362,6 @@ class WAConnection {
std::map<string, IqResultHandler*> pending_server_requests;
IMutex* mutex;
- // std::<string, FMessage* > message_store;
-
void init(WAListener* event_handler, WAGroupListener* group_event_handler, IMutex* mutex);
void sendMessageWithMedia(FMessage* message) throw(WAException);
void sendMessageWithBody(FMessage* message) throw(WAException);
@@ -381,26 +378,34 @@ class WAConnection {
static ProtocolTreeNode getMessageNode(FMessage* message, ProtocolTreeNode* node);
std::vector<ProtocolTreeNode*>* processGroupSettings(const std::vector<GroupSetting>& gruops);
- public:
+public:
WAConnection(IMutex* mutex, WAListener* event_handler = NULL, WAGroupListener* group_event_handler = NULL);
virtual ~WAConnection();
+
+ std::string user;
+ std::string domain;
+ std::string resource;
std::string jid;
- std::string fromm;
+ std::string nick;
+
int msg_id;
- int state;
bool retry;
+ bool supports_receipt_acks;
time_t expire_date;
int account_kind;
time_t lastTreeRead;
+
static const int DICTIONARY_LEN;
static const char* dictionary[];
+
+ static const int EXTDICTIONARY_LEN;
+ static const char* extended_dict[];
+
static MessageStore* message_store;
- KeyStream* inputKey;
- KeyStream* outputKey;
+ KeyStream inputKey, outputKey;
static std::string removeResourceFromJid(const std::string& jid);
- WALogin* getLogin();
void setLogin(WALogin* login);
void setVerboseId(bool b);
void sendMessage(FMessage* message) throw(WAException);
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
index 0e0ebc22d7..c833d30ffe 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
@@ -20,25 +20,19 @@ 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& password)
{
this->connection = connection;
+ this->password = password;
this->inn = reader;
this->out = writer;
- this->domain = domain;
- this->user = user;
- this->resource = resource;
- this->password = password;
- this->push_name = push_name;
- this->supports_receipt_acks = false;
this->account_kind = -1;
this->expire_date = 0L;
- this->outputKey = NULL;
}
std::vector<unsigned char>* WALogin::login(const std::vector<unsigned char>& authBlob)
{
- this->out->streamStart(this->domain, this->resource);
+ this->out->streamStart(connection->domain, connection->resource);
_LOGDATA("sent stream start");
@@ -92,7 +86,7 @@ void WALogin::sendAuth(const std::vector<unsigned char>& existingChallenge)
data = this->getAuthBlob(existingChallenge);
this->out->write(ProtocolTreeNode("auth", data) <<
- XATTR("mechanism", "WAUTH-2") << XATTR("user", this->user), true);
+ XATTR("mechanism", "WAUTH-2") << XATTR("user", connection->user), true);
}
std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char>& nonce)
@@ -100,31 +94,25 @@ std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char
unsigned char out[4*20];
KeyStream::keyFromPasswordAndNonce(this->password, nonce, out);
- if (this->connection->inputKey != NULL)
- delete this->connection->inputKey;
- this->connection->inputKey = new KeyStream(out + 40, out + 60);
-
- if (this->outputKey != NULL)
- delete this->outputKey;
- this->outputKey = new KeyStream(out, out + 20);
+ this->connection->inputKey.init(out + 40, out + 60);
+ this->connection->outputKey.init(out, out + 20);
std::vector<unsigned char>* list = new std::vector<unsigned char>(0);
for (int i = 0; i < 4; i++)
list->push_back(0);
- list->insert(list->end(), this->user.begin(), this->user.end());
+ list->insert(list->end(), connection->user.begin(), connection->user.end());
list->insert(list->end(), nonce.begin(), nonce.end());
- this->outputKey->encodeMessage(&((*list)[0]), 0, 4, (int)list->size() - 4);
+ this->connection->outputKey.encodeMessage(&((*list)[0]), 0, 4, (int)list->size() - 4);
return list;
}
std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess()
{
- ProtocolTreeNode* root;
- while ((root = this->inn->nextTree()) != NULL) {
+ while (ProtocolTreeNode *root = this->inn->nextTree()) {
if (ProtocolTreeNode::tagEquals(root, "stream:features")) {
- this->supports_receipt_acks = root->getChild("receipt_acks") != NULL;
+ connection->supports_receipt_acks = root->getChild("receipt_acks") != NULL;
delete root;
continue;
}
@@ -166,15 +154,11 @@ void WALogin::parseSuccessNode(ProtocolTreeNode* node)
this->account_kind = 0;
else
this->account_kind = -1;
-
- if (this->connection->outputKey != NULL)
- delete this->connection->outputKey;
- this->connection->outputKey = this->outputKey;
}
std::vector<unsigned char> WALogin::readSuccess()
{
- ProtocolTreeNode* node = this->inn->nextTree();
+ ProtocolTreeNode *node = this->inn->nextTree();
if (ProtocolTreeNode::tagEquals(node, "failure")) {
delete node;
@@ -197,6 +181,8 @@ std::vector<unsigned char> WALogin::readSuccess()
}
else this->account_kind = -1;
+ this->out->setLoggedIn();
+
std::vector<unsigned char> data = *node->data;
delete node;
return data;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h
index 3e08bdbe8e..ab1e13472b 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h
@@ -30,9 +30,11 @@ private:
void hmacsha1(unsigned char* text, int textLength, unsigned char *out);
public:
- KeyStream(unsigned char* _key, unsigned char* _keyMac);
+ KeyStream();
~KeyStream();
+ void init(unsigned char *_key, unsigned char *_keyMac);
+
static void keyFromPasswordAndNonce(const std::string& pass, const std::vector<unsigned char>& nonce, unsigned char *out);
void decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length);
void encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length);
@@ -42,7 +44,6 @@ public:
class WALogin {
private:
static const std::string NONCE_KEY;
- KeyStream* outputKey;
WAConnection* connection;
BinTreeNodeReader* inn;
BinTreeNodeWriter* out;
@@ -56,16 +57,11 @@ private:
std::vector<unsigned char> readSuccess();
public:
- std::string user;
- std::string domain;
- std::string password;
- std::string resource;
- std::string push_name;
- bool supports_receipt_acks;
time_t expire_date;
int account_kind;
+ std::string password;
- 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(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNodeWriter *writer, const std::string& password);
~WALogin();
std::vector<unsigned char>* login(const std::vector<unsigned char>& blobLength);
diff --git a/protocols/WhatsApp/src/connection.cpp b/protocols/WhatsApp/src/connection.cpp
index b970db7d96..ee4609fc75 100644
--- a/protocols/WhatsApp/src/connection.cpp
+++ b/protocols/WhatsApp/src/connection.cpp
@@ -77,7 +77,6 @@ void WhatsAppProto::stayConnectedLoop(void*)
// -----------------------------
Mutex writerMutex;
- WALogin* login = NULL;
int desiredStatus;
bool error = false;
@@ -85,10 +84,6 @@ void WhatsAppProto::stayConnectedLoop(void*)
while (true) {
if (connection != NULL) {
- if (connection->getLogin() == NULL && login != NULL) {
- delete login;
- login = NULL;
- }
delete connection;
connection = NULL;
}
@@ -123,20 +118,19 @@ void WhatsAppProto::stayConnectedLoop(void*)
portNumber = 5222, resource += "-5222";
this->conn = new WASocketConnection("c.whatsapp.net", portNumber);
-
- connection = new WAConnection(&this->connMutex, this, this);
- login = new WALogin(connection, new BinTreeNodeReader(connection, conn, WAConnection::dictionary, WAConnection::DICTIONARY_LEN),
- new BinTreeNodeWriter(connection, conn, WAConnection::dictionary, WAConnection::DICTIONARY_LEN, &writerMutex),
- "s.whatsapp.net", this->phoneNumber, resource, password, nick);
-
- std::vector<unsigned char>* nextChallenge = login->login(*this->challenge);
- delete this->challenge;
- this->challenge = nextChallenge;
- connection->setLogin(login);
+ this->connection = new WAConnection(&this->connMutex, this, this);
+ {
+ WALogin login(connection, new BinTreeNodeReader(connection, conn), new BinTreeNodeWriter(connection, conn, &writerMutex), password);
+
+ std::vector<unsigned char>* nextChallenge = login.login(*this->challenge);
+ delete this->challenge;
+ this->challenge = nextChallenge;
+ connection->setLogin(&login);
+ }
+ connection->nick = this->nick;
connection->setVerboseId(true); // ?
- if (desiredStatus != ID_STATUS_INVISIBLE) {
+ if (desiredStatus != ID_STATUS_INVISIBLE)
connection->sendAvailableForChat();
- }
debugLogA("Set status to online");
this->m_iStatus = desiredStatus;