diff options
Diffstat (limited to 'protocols/WhatsApp')
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp | 13 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp | 20 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h | 1 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp | 82 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WAConnection.h | 23 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp | 35 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WALogin.h | 10 | ||||
-rw-r--r-- | protocols/WhatsApp/src/connection.cpp | 9 |
8 files changed, 90 insertions, 103 deletions
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp index 492dde1027..99c186f126 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp @@ -12,6 +12,8 @@ #include "ProtocolTreeNode.h"
#include "utilities.h"
+extern const char *dictionary[], *extended_dict[];
+
BinTreeNodeReader::BinTreeNodeReader(WAConnection *conn, ISocketConnection *connection) :
buf(BUFFER_SIZE)
{
@@ -145,15 +147,12 @@ ReadData* BinTreeNodeReader::readString(int token) int bSize;
ReadData *ret = new ReadData();
- if (token > 2 && token <= WAConnection::DICTIONARY_LEN) {
- if (token != WAConnection::DICTIONARY_LEN)
- ret->data = new std::string(WAConnection::dictionary[token]);
+ if (token > 2 && token <= 236) {
+ if (token != 236)
+ ret->data = new std::string(dictionary[token]);
else {
token = readInt8(this->in);
- 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->data = new std::string(extended_dict[token]);
}
ret->type = STRING;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp index a4f79baf17..227857a522 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp @@ -17,11 +17,6 @@ BinTreeNodeWriter::BinTreeNodeWriter(WAConnection* conn, ISocketConnection* conn this->conn = conn;
this->out = new ByteArrayOutputStream(2048);
this->realOut = connection;
- for (int i = 0; i < WAConnection::DICTIONARY_LEN; i++) {
- std::string token(WAConnection::dictionary[i]);
- if (token.compare("") != 0)
- this->tokenMap[token] = i;
- }
this->dataBegin = 0;
}
@@ -135,9 +130,9 @@ void BinTreeNodeWriter::writeAttributes(std::map<string, string>* attributes) void BinTreeNodeWriter::writeString(const std::string& tag)
{
- std::map<string, int>::iterator it = this->tokenMap.find(tag);
- if (it != this->tokenMap.end())
- writeToken(it->second);
+ int token = WAConnection::tokenLookup(tag);
+ if (token != -1)
+ writeToken(token);
else {
size_t atIndex = tag.find('@');
if (atIndex == 0 || atIndex == string::npos)
@@ -164,12 +159,11 @@ void BinTreeNodeWriter::writeJid(std::string* user, const std::string& server) void BinTreeNodeWriter::writeToken(int intValue)
{
- if (intValue < 245)
- this->out->write(intValue);
- else if (intValue <= 500) {
- this->out->write(254);
- this->out->write(intValue - 245);
+ if (intValue & 0x100) {
+ this->out->write(236);
+ this->out->write(intValue & 0xFF);
}
+ else this->out->write(intValue);
}
void BinTreeNodeWriter::writeBytes(unsigned char* bytes, int length)
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h index e4a771f231..66d9cbb991 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h @@ -35,7 +35,6 @@ class WAConnection; class BinTreeNodeWriter {
private:
WAConnection* conn;
- map<string, int> tokenMap;
ISocketConnection *realOut;
ByteArrayOutputStream *out;
IMutex* mutex;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp index 48300ad530..270c329085 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp @@ -10,7 +10,7 @@ #include "ProtocolTreeNode.h"
#include "utilities.h"
-const char* WAConnection::dictionary[] = {
+const char* dictionary[] = {
"", "", "", "account", "ack", "action", "active", "add", "after", "all", "allow", "apple", "auth", "author", "available", "bad-protocol", "bad-request", "before", "body", "broadcast", "cancel", "category", "challenge", "chat", "clean", "code", "composing", "config", "contacts", "count", "create", "creation", "debug", "default", "delete", "delivery", "delta", "deny", @@ -34,9 +34,7 @@ const char* WAConnection::dictionary[] = { "adpcm", "amrnb", "amrwb", "mp3", "pcm", "qcelp", "wma", "h263", "h264", "jpeg" };
-const int WAConnection::DICTIONARY_LEN = _countof(WAConnection::dictionary);
-
-const char* WAConnection::extended_dict[] = { +const char* 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", @@ -60,41 +58,71 @@ const char* WAConnection::extended_dict[] = { "archive", "adm", "plaintext_size", "compressed_size", "delivered", "msg", "pkmsg", "everyone", "v", "transport", "call-id" }; -const int WAConnection::EXTDICTIONARY_LEN = _countof(WAConnection::extended_dict);
-
-/////////////////////////////////////////////////////////////////////////////////////////
+static map<string, int> tokenMap1, tokenMap2;
-WAConnection::WAConnection(IMutex* mutex, WAListener* event_handler, WAGroupListener* group_event_handler)
+void WAConnection::globalInit()
{
- this->init(event_handler, group_event_handler, mutex);
+ for (int i = 0; i < _countof(dictionary); i++)
+ if (*dictionary[i] != 0)
+ tokenMap1[dictionary[i]] = i;
+
+ for (int i = 0; i < _countof(extended_dict); i++)
+ tokenMap2[extended_dict[i]] = i;
}
-WAConnection::~WAConnection()
+int WAConnection::tokenLookup(const std::string &str)
{
- delete this->in;
- delete this->out;
- std::map<string, IqResultHandler*>::iterator it;
- for (it = this->pending_server_requests.begin(); it != this->pending_server_requests.end(); it++)
- delete it->second;
+ std::map<string, int>::iterator it = tokenMap1.find(str);
+ if (it != tokenMap1.end())
+ return it->second;
+
+ it = tokenMap2.find(str);
+ if (it != tokenMap2.end())
+ return it->second + 0x100;
+
+ return -1;
}
-void WAConnection::init(WAListener* event_handler, WAGroupListener* group_event_handler, IMutex* mutex)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+WAConnection::WAConnection(const std::string &user, const std::string &resource, IMutex *mutex, WAListener *event_handler, WAGroupListener *group_event_handler)
{
+ this->mutex = mutex;
this->event_handler = event_handler;
this->group_event_handler = group_event_handler;
+
this->in = NULL;
this->out = NULL;
this->msg_id = 0;
this->retry = true;
+ this->user = user;
+ this->resource = resource;
+ this->domain = "s.whatsapp.net";
+ this->jid = user + "@" + domain;
+
this->supports_receipt_acks = false;
this->iqid = 0;
this->verbose = true;
this->lastTreeRead = 0;
this->expire_date = 0L;
this->account_kind = -1;
- this->mutex = mutex;
+}
+
+WAConnection::~WAConnection()
+{
+ delete this->in;
+ delete this->out;
+ std::map<string, IqResultHandler*>::iterator it;
+ for (it = this->pending_server_requests.begin(); it != this->pending_server_requests.end(); it++)
+ delete it->second;
+}
+
+void WAConnection::init(IMutex *mutex, WASocketConnection *conn)
+{
+ in = new BinTreeNodeReader(this, conn);
+ out = new BinTreeNodeWriter(this, conn, mutex);
}
void WAConnection::setLogin(WALogin* login)
@@ -104,11 +132,6 @@ void WAConnection::setLogin(WALogin* login) if (login->account_kind != -1)
this->account_kind = login->account_kind;
-
- this->jid = user + "@" + domain;
-
- this->in = login->getTreeNodeReader();
- this->out = login->getTreeNodeWriter();
}
void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException)
@@ -118,7 +141,7 @@ void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException) if (message->media_wa_type == FMessage::WA_TYPE_SYSTEM)
throw new WAException("Cannot send system message over the network");
- ProtocolTreeNode* mediaNode;
+ ProtocolTreeNode *mediaNode;
if (message->media_wa_type == FMessage::WA_TYPE_CONTACT && !message->media_name.empty()) {
ProtocolTreeNode* vcardNode = new ProtocolTreeNode("vcard", new std::vector<unsigned char>(message->data.begin(), message->data.end()))
<< XATTR("name", message->media_name);
@@ -131,17 +154,12 @@ void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException) 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) {
+ if (message->media_wa_type == FMessage::WA_TYPE_LOCATION)
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) {
- mediaNode << XATTR("file", message->media_name) << XATTRI("size", message->media_size) << XATTR("url", message->media_url);
- }
- else {
- mediaNode << XATTR("file", message->media_name) << XATTRI("size", message->media_size)
- << XATTR("url", message->media_url) << XATTRI("seconds", message->media_duration_seconds);
- }
+ mediaNode << XATTR("file", message->media_name) << XATTRI("size", message->media_size) << XATTR("url", message->media_url);
+ if (message->media_wa_type == FMessage::WA_TYPE_CONTACT || message->media_name.empty() || message->media_url.empty() || message->media_size <= 0)
+ mediaNode << XATTRI("seconds", message->media_duration_seconds);
}
this->out->write(WAConnection::getMessageNode(message, mediaNode));
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h index 983cb4e4bc..697542e32c 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h @@ -24,6 +24,7 @@ #pragma warning(disable : 4290)
class WALogin;
+class WASocketConnection;
class KeyStream;
class BinTreeNodeReader;
@@ -351,18 +352,18 @@ class WAConnection { }
};
+ friend class WALogin;
private:
- BinTreeNodeReader* in;
- BinTreeNodeWriter* out;
- WAListener* event_handler;
- WAGroupListener* group_event_handler;
+ BinTreeNodeReader *in;
+ BinTreeNodeWriter *out;
+ WAListener *event_handler;
+ WAGroupListener *group_event_handler;
bool verbose;
int iqid;
std::map<string, IqResultHandler*> pending_server_requests;
- IMutex* mutex;
+ IMutex *mutex;
- void init(WAListener* event_handler, WAGroupListener* group_event_handler, IMutex* mutex);
void sendMessageWithMedia(FMessage* message) throw(WAException);
void sendMessageWithBody(FMessage* message) throw(WAException);
std::map<string, string>* parseCategories(ProtocolTreeNode* node) throw(WAException);
@@ -379,8 +380,9 @@ private: std::vector<ProtocolTreeNode*>* processGroupSettings(const std::vector<GroupSetting>& gruops);
public:
- WAConnection(IMutex* mutex, WAListener* event_handler = NULL, WAGroupListener* group_event_handler = NULL);
+ WAConnection(const std::string& user, const std::string& resource, IMutex* mutex, WAListener* event_handler, WAGroupListener* group_event_handler);
virtual ~WAConnection();
+ void init(IMutex* mutex, WASocketConnection*);
std::string user;
std::string domain;
@@ -395,11 +397,8 @@ public: 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 void globalInit(void);
+ static int tokenLookup(const std::string&);
static MessageStore* message_store;
KeyStream inputKey, outputKey;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp index c833d30ffe..e009968b59 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp @@ -20,19 +20,17 @@ using namespace Utilities; const std::string WALogin::NONCE_KEY = "nonce=\"";
-WALogin::WALogin(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNodeWriter *writer, const std::string& password)
+WALogin::WALogin(WAConnection* connection, const std::string& password)
{
this->connection = connection;
this->password = password;
- this->inn = reader;
- this->out = writer;
this->account_kind = -1;
this->expire_date = 0L;
}
std::vector<unsigned char>* WALogin::login(const std::vector<unsigned char>& authBlob)
{
- this->out->streamStart(connection->domain, connection->resource);
+ connection->out->streamStart(connection->domain, connection->resource);
_LOGDATA("sent stream start");
@@ -44,27 +42,17 @@ std::vector<unsigned char>* WALogin::login(const std::vector<unsigned char>& aut _LOGDATA("send auth, auth blob size %d", authBlob.size());
- this->inn->streamStart();
+ connection->in->streamStart();
_LOGDATA("read stream start");
return this->readFeaturesUntilChallengeOrSuccess();
}
-BinTreeNodeReader* WALogin::getTreeNodeReader()
-{
- return this->inn;
-}
-
-BinTreeNodeWriter* WALogin::getTreeNodeWriter()
-{
- return this->out;
-}
-
void WALogin::sendResponse(const std::vector<unsigned char>& challengeData)
{
std::vector<unsigned char>* authBlob = this->getAuthBlob(challengeData);
- this->out->write(ProtocolTreeNode("response", authBlob));
+ connection->out->write(ProtocolTreeNode("response", authBlob));
}
void WALogin::sendFeatures()
@@ -76,7 +64,7 @@ void WALogin::sendFeatures() ProtocolTreeNode* pictureChild = new ProtocolTreeNode("w:profile:picture") << XATTR("type", "all");
children->push_back(pictureChild);
- this->out->write(ProtocolTreeNode("stream:features", NULL, children), true);
+ connection->out->write(ProtocolTreeNode("stream:features", NULL, children), true);
}
void WALogin::sendAuth(const std::vector<unsigned char>& existingChallenge)
@@ -85,7 +73,7 @@ void WALogin::sendAuth(const std::vector<unsigned char>& existingChallenge) if (!existingChallenge.empty())
data = this->getAuthBlob(existingChallenge);
- this->out->write(ProtocolTreeNode("auth", data) <<
+ connection->out->write(ProtocolTreeNode("auth", data) <<
XATTR("mechanism", "WAUTH-2") << XATTR("user", connection->user), true);
}
@@ -110,15 +98,13 @@ std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess()
{
- while (ProtocolTreeNode *root = this->inn->nextTree()) {
+ while (ProtocolTreeNode *root = connection->in->nextTree()) {
if (ProtocolTreeNode::tagEquals(root, "stream:features")) {
connection->supports_receipt_acks = root->getChild("receipt_acks") != NULL;
delete root;
continue;
}
if (ProtocolTreeNode::tagEquals(root, "challenge")) {
- // base64_decode(*root->data);
- // _LOGDATA("Challenge data %s (%d)", root->data->c_str(), root->data->length());
std::vector<unsigned char> challengedata(root->data->begin(), root->data->end());
delete root;
this->sendResponse(challengedata);
@@ -128,7 +114,6 @@ std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess() return new std::vector<unsigned char>(data.begin(), data.end());
}
if (ProtocolTreeNode::tagEquals(root, "success")) {
- // base64_decode(*root->data);
std::vector<unsigned char>* ret = new std::vector<unsigned char>(root->data->begin(), root->data->end());
this->parseSuccessNode(root);
delete root;
@@ -140,6 +125,8 @@ std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess() void WALogin::parseSuccessNode(ProtocolTreeNode* node)
{
+ connection->out->setLoggedIn();
+
const string &expiration = node->getAttributeValue("expiration");
if (!expiration.empty()) {
this->expire_date = atol(expiration.c_str());
@@ -158,7 +145,7 @@ void WALogin::parseSuccessNode(ProtocolTreeNode* node) std::vector<unsigned char> WALogin::readSuccess()
{
- ProtocolTreeNode *node = this->inn->nextTree();
+ ProtocolTreeNode *node = connection->in->nextTree();
if (ProtocolTreeNode::tagEquals(node, "failure")) {
delete node;
@@ -181,8 +168,6 @@ 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 ab1e13472b..440f34f71b 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h @@ -44,16 +44,14 @@ public: class WALogin {
private:
static const std::string NONCE_KEY;
- WAConnection* connection;
- BinTreeNodeReader* inn;
- BinTreeNodeWriter* out;
+ WAConnection *connection;
std::vector<unsigned char>* getAuthBlob(const std::vector<unsigned char>& nonce);
void sendResponse(const std::vector<unsigned char>& challengeData);
void sendFeatures();
void sendAuth(const std::vector<unsigned char>& nonce);
std::vector<unsigned char>* readFeaturesUntilChallengeOrSuccess();
- void parseSuccessNode(ProtocolTreeNode* node);
+ void parseSuccessNode(ProtocolTreeNode *node);
std::vector<unsigned char> readSuccess();
public:
@@ -61,12 +59,10 @@ public: int account_kind;
std::string password;
- WALogin(WAConnection* connection, BinTreeNodeReader *reader, BinTreeNodeWriter *writer, const std::string& password);
+ WALogin(WAConnection* connection, const std::string& password);
~WALogin();
std::vector<unsigned char>* login(const std::vector<unsigned char>& blobLength);
- BinTreeNodeReader *getTreeNodeReader();
- BinTreeNodeWriter *getTreeNodeWriter();
};
#endif /* WALOGIN_H_ */
diff --git a/protocols/WhatsApp/src/connection.cpp b/protocols/WhatsApp/src/connection.cpp index 2acc8a89fa..8c1f16c456 100644 --- a/protocols/WhatsApp/src/connection.cpp +++ b/protocols/WhatsApp/src/connection.cpp @@ -118,13 +118,10 @@ void WhatsAppProto::stayConnectedLoop(void*) portNumber = 5222, resource += "-5222";
this->conn = new WASocketConnection("c.whatsapp.net", portNumber);
- this->connection = new WAConnection(&this->connMutex, this, this);
-
- this->connection->domain = "s.whatsapp.net";
- this->connection->user = this->phoneNumber;
- this->connection->resource = resource;
+ this->connection = new WAConnection(this->phoneNumber, resource, &this->connMutex, this, this);
+ this->connection->init(&writerMutex, this->conn);
{
- WALogin login(connection, new BinTreeNodeReader(connection, conn), new BinTreeNodeWriter(connection, conn, &writerMutex), password);
+ WALogin login(connection, password);
std::vector<unsigned char>* nextChallenge = login.login(*this->challenge);
delete this->challenge;
|