summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/WhatsApp')
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp6
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/FMessage.h49
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp934
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WAConnection.h20
-rw-r--r--protocols/WhatsApp/src/contacts.cpp6
-rw-r--r--protocols/WhatsApp/src/db.h3
-rw-r--r--protocols/WhatsApp/src/messages.cpp110
-rw-r--r--protocols/WhatsApp/src/proto.cpp6
-rw-r--r--protocols/WhatsApp/src/proto.h65
-rw-r--r--protocols/WhatsApp/src/utils.cpp5
10 files changed, 564 insertions, 640 deletions
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp
index 7ec854878a..e9b6377879 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp
@@ -260,6 +260,12 @@ void BinTreeNodeWriter::write(const ProtocolTreeNode &node, bool needsFlush)
this->mutex->lock();
try {
this->writeDummyHeader();
+ #ifdef _DEBUG
+ if (bSecure) {
+ string tmp = node.toString();
+ this->realOut->log(tmp.c_str());
+ }
+ #endif
writeInternal(node);
flushBuffer(needsFlush);
}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.h b/protocols/WhatsApp/src/WhatsAPI++/FMessage.h
index 3d9c8438f5..fb523d9c8e 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.h
@@ -51,29 +51,32 @@ public:
double latitude;
double longitude;
- static const unsigned char WA_TYPE_UNDEFINED = 0;
- static const unsigned char WA_TYPE_IMAGE = 1;
- static const unsigned char WA_TYPE_AUDIO = 2;
- static const unsigned char WA_TYPE_VIDEO = 3;
- static const unsigned char WA_TYPE_CONTACT = 4;
- static const unsigned char WA_TYPE_LOCATION = 5;
- static const unsigned char WA_TYPE_SYSTEM = 7;
-
- static const int STATUS_UNSENT = 0;
- static const int STATUS_UPLOADING = 1;
- static const int STATUS_UPLOADED = 2;
- static const int STATUS_SENT_BY_CLIENT = 3;
- static const int STATUS_RECEIVED_BY_SERVER = 4;
- static const int STATUS_RECEIVED_BY_TARGET = 5;
- static const int STATUS_NEVER_SEND = 6;
- static const int STATUS_SERVER_BOUNCE = 7;
-
- static const int STATUS_USER_ADDED = 191;
- static const int STATUS_USER_REMOVED = 192;
- static const int STATUS_SUBJECT_CHANGED = 193;
- static const int STATUS_PICTURE_CHANGED_SET = 194;
- static const int STATUS_PICTURE_CHANGED_DELETE = 195;
-
+ enum {
+ WA_TYPE_UNDEFINED = 0,
+ WA_TYPE_IMAGE = 1,
+ WA_TYPE_AUDIO = 2,
+ WA_TYPE_VIDEO = 3,
+ WA_TYPE_CONTACT = 4,
+ WA_TYPE_LOCATION = 5,
+ WA_TYPE_SYSTEM = 7
+ };
+
+ enum {
+ STATUS_UNSENT = 0,
+ STATUS_UPLOADING = 1,
+ STATUS_UPLOADED = 2,
+ STATUS_SENT_BY_CLIENT = 3,
+ STATUS_RECEIVED_BY_SERVER = 4,
+ STATUS_RECEIVED_BY_TARGET = 5,
+ STATUS_NEVER_SEND = 6,
+ STATUS_SERVER_BOUNCE = 7,
+
+ STATUS_USER_ADDED = 191,
+ STATUS_USER_REMOVED = 192,
+ STATUS_SUBJECT_CHANGED = 193,
+ STATUS_PICTURE_CHANGED_SET = 194,
+ STATUS_PICTURE_CHANGED_DELETE = 195
+ };
static std::string getMessage_WA_Type_StrValue(unsigned char type);
static std::string nextKeyIdNumber();
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
index d5533577bb..7ae18a30d5 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp
@@ -137,57 +137,55 @@ void WAConnection::init(IMutex *mutex, ISocketConnection *conn)
out = new BinTreeNodeWriter(this, conn, mutex);
}
-void WAConnection::setLogin(WALogin* login)
+std::string WAConnection::gidToGjid(const std::string& gid)
{
- if (login->expire_date != 0L)
- this->expire_date = login->expire_date;
+ return gid + "@g.us";
+}
- if (login->account_kind != -1)
- this->account_kind = login->account_kind;
+std::string WAConnection::makeId(const std::string& prefix)
+{
+ this->iqid++;
+ std::string id;
+ if (this->verbose)
+ id = prefix + Utilities::intToStr(this->iqid);
+ else
+ id = Utilities::itoa(this->iqid, 16);
+
+ return id;
}
-void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException)
+ProtocolTreeNode* WAConnection::getReceiptAck(const std::string& to, const std::string& id, const std::string& receiptType) throw(WAException)
{
- logData("Send message with media %s %d", message->media_name.c_str(), message->media_size);
- 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");
-
- 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);
- mediaNode = new ProtocolTreeNode("media", vcardNode);
- }
- else {
- mediaNode = new ProtocolTreeNode("media", new std::vector<unsigned char>(message->data.begin(), message->data.end()), NULL)
- << XATTR("encoding", "text");
- }
+ ProtocolTreeNode *ackNode = new ProtocolTreeNode("ack")
+ << XATTR("xmlns", "urn:xmpp:receipts") << XATTR("type", receiptType);
- mediaNode << XATTR("xmlns", "urn:xmpp:whatsapp:mms") << XATTR("type", FMessage::getMessage_WA_Type_StrValue(message->media_wa_type));
+ return new ProtocolTreeNode("message", ackNode) << XATTR("to", to) << XATTR("type", "chat") << XATTR("id", id);
+}
- if (message->media_wa_type == FMessage::WA_TYPE_LOCATION)
- mediaNode << XATTR("latitude", Utilities::doubleToStr(message->latitude)) << XATTR("longitude", Utilities::doubleToStr(message->longitude));
- else {
- 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);
- }
+bool WAConnection::supportsReceiptAcks()
+{
+ return supports_receipt_acks;
+}
- ProtocolTreeNode *n = WAConnection::getMessageNode(message, mediaNode);
- this->out->write(*n);
- delete n;
+std::string WAConnection::removeResourceFromJid(const std::string& jid)
+{
+ size_t slashidx = jid.find('/');
+ if (slashidx == std::string::npos)
+ return jid;
+
+ return jid.substr(0, slashidx + 1);
}
-void WAConnection::sendMessageWithBody(FMessage* message) throw (WAException)
+void WAConnection::setLogin(WALogin* login)
{
- ProtocolTreeNode* bodyNode = new ProtocolTreeNode("body", new std::vector<unsigned char>(message->data.begin(), message->data.end()));
- ProtocolTreeNode *n = WAConnection::getMessageNode(message, bodyNode);
- this->out->write(*n);
- delete n;
+ if (login->expire_date != 0L)
+ this->expire_date = login->expire_date;
+
+ if (login->account_kind != -1)
+ this->account_kind = login->account_kind;
}
-ProtocolTreeNode* WAConnection::getMessageNode(FMessage* message, ProtocolTreeNode* child)
+ProtocolTreeNode* WAConnection::getMessageNode(FMessage* message, ProtocolTreeNode *child)
{
std::vector<ProtocolTreeNode*>* messageChildren = new std::vector<ProtocolTreeNode*>();
messageChildren->push_back(new ProtocolTreeNode("x", new ProtocolTreeNode("server")) << XATTR("xmlns", "jabber:x:event"));
@@ -197,27 +195,14 @@ ProtocolTreeNode* WAConnection::getMessageNode(FMessage* message, ProtocolTreeNo
XATTR("to", message->key->remote_jid) << XATTR("type", "chat") << XATTR("id", message->key->id);
}
-void WAConnection::sendMessage(FMessage* message) throw(WAException)
-{
- if (message->media_wa_type != 0)
- sendMessageWithMedia(message);
- else
- sendMessageWithBody(message);
-}
-
void WAConnection::setVerboseId(bool b)
{
this->verbose = b;
}
-void WAConnection::sendAvailableForChat() throw(WAException)
-{
- this->out->write(ProtocolTreeNode("presence") << XATTR("name", this->nick));
-}
-
bool WAConnection::read() throw(WAException)
{
- ProtocolTreeNode* node;
+ ProtocolTreeNode *node;
try {
node = this->in->nextTree();
this->lastTreeRead = time(NULL);
@@ -236,281 +221,89 @@ bool WAConnection::read() throw(WAException)
}
#endif
- if (ProtocolTreeNode::tagEquals(node, "iq")) {
- const string &type = node->getAttributeValue("type");
- if (type.empty())
- throw WAException("missing 'type' attribute in iq stanza", WAException::CORRUPT_STREAM_EX, 0);
-
- const string &id = node->getAttributeValue("id");
- const string &from = node->getAttributeValue("from");
-
- if (type == "result") {
- if (id.empty())
- throw WAException("missing 'id' attribute in iq stanza", WAException::CORRUPT_STREAM_EX, 0);
-
- std::map<string, IqResultHandler*>::iterator it = this->pending_server_requests.find(id);
- if (it != this->pending_server_requests.end()) {
- it->second->parse(node, from);
- delete it->second;
- this->pending_server_requests.erase(id);
- }
- 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");
- if (kind == "paid")
- this->account_kind = 1;
- else if (kind == "free")
- this->account_kind = 0;
- else
- this->account_kind = -1;
-
- const string &expiration = accountNode->getAttributeValue("expiration");
- if (expiration.empty())
- throw WAException("no expiration");
-
- this->expire_date = atol(expiration.c_str());
- if (this->expire_date == 0)
- throw WAException("invalid expire date: " + expiration);
- if (this->event_handler != NULL)
- this->event_handler->onAccountChange(this->account_kind, this->expire_date);
- }
- }
- else if (type == "error") {
- std::map<string, IqResultHandler*>::iterator it = this->pending_server_requests.find(id);
- if (it != this->pending_server_requests.end()) {
- it->second->error(node);
- delete it->second;
- this->pending_server_requests.erase(id);
- }
- }
- else if (type == "get") {
- ProtocolTreeNode* childNode = node->getChild(0);
- if (ProtocolTreeNode::tagEquals(childNode, "ping")) {
- if (this->event_handler != NULL)
- this->event_handler->onPing(id);
- }
- else if ((ProtocolTreeNode::tagEquals(childNode, "query") && !from.empty()) ? false : (ProtocolTreeNode::tagEquals(childNode, "relay")) && !from.empty()) {
- const string &pin = childNode->getAttributeValue("pin");
- if (!pin.empty() && this->event_handler != NULL) {
- int timeoutSeconds = atoi(childNode->getAttributeValue("timeout").c_str());
- this->event_handler->onRelayRequest(pin, timeoutSeconds, id);
- }
- }
- }
- else if (type == "set") {
- ProtocolTreeNode* childNode = node->getChild(0);
- if (ProtocolTreeNode::tagEquals(childNode, "query")) {
- const string &xmlns = childNode->getAttributeValue("xmlns");
- if (xmlns == "jabber:iq:roster") {
- std::vector<ProtocolTreeNode*> itemNodes(childNode->getAllChildren("item"));
- for (size_t i = 0; i < itemNodes.size(); i++) {
- ProtocolTreeNode* itemNode = itemNodes[i];
- const string &jid = itemNode->getAttributeValue("jid");
- const string &subscription = itemNode->getAttributeValue("subscription");
- // ask = itemNode->getAttributeValue("ask");
- }
- }
- }
- }
- else throw WAException("unknown iq type attribute: " + type, WAException::CORRUPT_STREAM_EX, 0);
- }
- else if (ProtocolTreeNode::tagEquals(node, "presence")) {
- const string &xmlns = node->getAttributeValue("xmlns");
- const string &from = node->getAttributeValue("from");
- if (xmlns == "urn:xmpp" && !from.empty()) {
- const string &type = node->getAttributeValue("type");
- if (type == "unavailable") {
- if (this->event_handler != NULL)
- this->event_handler->onAvailable(from, false);
- }
- else if (type == "available") {
- if (this->event_handler != NULL)
- this->event_handler->onAvailable(from, true);
- }
- }
- else if (xmlns == "w" && !from.empty()) {
- const string &add = node->getAttributeValue("add");
- const string &remove = node->getAttributeValue("remove");
- const string &status = node->getAttributeValue("status");
- if (!add.empty()) {
- if (this->group_event_handler != NULL)
- this->group_event_handler->onGroupAddUser(from, add);
- }
- else if (!remove.empty()) {
- if (this->group_event_handler != NULL)
- this->group_event_handler->onGroupRemoveUser(from, remove);
- }
- else if (status == "dirty") {
- std::map<string, string>* categories = parseCategories(node);
- if (this->event_handler != NULL)
- this->event_handler->onDirty(*categories);
- delete categories;
- }
- }
- }
- else if (ProtocolTreeNode::tagEquals(node, "message")) {
- parseMessageInitialTagAlreadyChecked(node);
- }
+ if (ProtocolTreeNode::tagEquals(node, "iq"))
+ parseIq(node);
+ else if (ProtocolTreeNode::tagEquals(node, "presence"))
+ parsePresense(node);
+ else if (ProtocolTreeNode::tagEquals(node, "message"))
+ parseMessage(node);
+ else if (ProtocolTreeNode::tagEquals(node, "ack"))
+ parseAck(node);
+ else if (ProtocolTreeNode::tagEquals(node, "chatstates"))
+ parseChatStates(node);
delete node;
return true;
}
-void WAConnection::sendPing() throw(WAException)
-{
- std::string id = makeId("ping_");
- this->pending_server_requests[id] = new IqResultPingHandler(this);
-
- 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)
-{
- this->out->write(ProtocolTreeNode("iq")
- << XATTR("type", "result") << XATTR("to", this->domain) << XATTR("id", id));
-}
-
-void WAConnection::sendComposing(const std::string& to) throw(WAException)
-{
- ProtocolTreeNode* composingNode = new ProtocolTreeNode("composing")
- << XATTR("xmlns", "http://jabber.org/protocol/chatstates");
-
- this->out->write(ProtocolTreeNode("message", composingNode)
- << XATTR("to", to) << XATTR("type", "chat"));
-}
-
-void WAConnection::sendActive() throw(WAException)
-{
- this->out->write(ProtocolTreeNode("presence") << XATTR("type", "active"));
-}
-
-void WAConnection::sendInactive() throw(WAException)
-{
- this->out->write(ProtocolTreeNode("presence") << XATTR("type", "inactive"));
-}
-
-void WAConnection::sendPaused(const std::string& to) throw(WAException)
-{
- ProtocolTreeNode* pausedNode = new ProtocolTreeNode("paused");
- *pausedNode << XATTR("xmlns", "http://jabber.org/protocol/chatstates");
-
- 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)
-{
- ProtocolTreeNode* receivedNode = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts");
-
- this->out->write(ProtocolTreeNode("message", receivedNode)
- << XATTR("to", to) << XATTR("type", "subject") << XATTR("id", id));
-}
-
-void WAConnection::sendMessageReceived(FMessage* message) throw(WAException)
+void WAConnection::readGroupList(ProtocolTreeNode *node, std::vector<std::string>& groups) throw (WAException)
{
- ProtocolTreeNode* receivedNode = new ProtocolTreeNode("received")
- << XATTR("xmlns", "urn:xmpp:receipts");
-
- 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 *n = getReceiptAck(to, id, "delivered");
- this->out->write(*n);
- delete n;
-}
-
-void WAConnection::sendVisibleReceiptAck(const std::string& to, const std::string& id) throw (WAException)
-{
- ProtocolTreeNode *n = getReceiptAck(to, id, "visible");
- this->out->write(*n);
- delete n;
-}
-
-void WAConnection::sendPresenceSubscriptionRequest(const std::string& to) throw(WAException)
-{
- 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)
-{
- 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);
-
- this->out->write(ProtocolTreeNode("iq", configNode)
- << 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)
-{
- 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");
-
- std::string id = makeId("config_");
- this->out->write(ProtocolTreeNode("iq", configNode) << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->domain));
+ std::vector<ProtocolTreeNode*> nodes(node->getAllChildren("group"));
+ for (size_t i = 0; i < nodes.size(); i++) {
+ ProtocolTreeNode *groupNode = nodes[i];
+ const string &gid = groupNode->getAttributeValue("id");
+ string gjid = gidToGjid(gid);
+ const string &owner = groupNode->getAttributeValue("owner");
+ const string &subject = groupNode->getAttributeValue("subject");
+ const string &subject_t = groupNode->getAttributeValue("s_t");
+ const string &subject_owner = groupNode->getAttributeValue("s_o");
+ const string &creation = groupNode->getAttributeValue("creation");
+ if (this->group_event_handler != NULL)
+ this->group_event_handler->onGroupInfoFromList(gjid, owner, subject, subject_owner, atoi(subject_t.c_str()), atoi(creation.c_str()));
+ groups.push_back(gjid);
+ }
}
-std::vector<ProtocolTreeNode*>* WAConnection::processGroupSettings(const std::vector<GroupSetting>& groups)
+std::map<string, string> WAConnection::parseCategories(ProtocolTreeNode *dirtyNode) throw (WAException)
{
- std::vector<ProtocolTreeNode*>* result = new std::vector<ProtocolTreeNode*>(groups.size());
- if (!groups.empty()) {
- time_t now = time(NULL);
- for (size_t i = 0; i < groups.size(); i++) {
- (*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);
+ std::map<string, string> categories;
+ if (dirtyNode->children != NULL) {
+ for (size_t i = 0; i < dirtyNode->children->size(); i++) {
+ ProtocolTreeNode *childNode = (*dirtyNode->children)[i];
+ if (ProtocolTreeNode::tagEquals(childNode, "category")) {
+ const string &categoryName = childNode->getAttributeValue("name");
+ const string &timestamp = childNode->getAttributeValue("timestamp");
+ categories[categoryName] = timestamp;
+ }
}
}
- return result;
+ return categories;
}
-std::string WAConnection::makeId(const std::string& prefix)
+void WAConnection::parseAck(ProtocolTreeNode *node) throw(WAException)
{
- this->iqid++;
- std::string id;
- if (this->verbose)
- id = prefix + Utilities::intToStr(this->iqid);
- else
- id = Utilities::itoa(this->iqid, 16);
+ const string &from = node->getAttributeValue("from");
+ const string &cls = node->getAttributeValue("class");
+ const string &id = node->getAttributeValue("id");
+ const string &ts = node->getAttributeValue("t");
- return id;
+ if (this->event_handler != NULL) {
+ FMessage msg(new Key(from, true, id));
+ msg.status = FMessage::STATUS_RECEIVED_BY_SERVER;
+ this->event_handler->onMessageStatusUpdate(&msg);
+ }
}
-ProtocolTreeNode* WAConnection::getReceiptAck(const std::string& to, const std::string& id, const std::string& receiptType) throw(WAException)
+void WAConnection::parseChatStates(ProtocolTreeNode *node) throw (WAException)
{
- ProtocolTreeNode* ackNode = new ProtocolTreeNode("ack")
- << XATTR("xmlns", "urn:xmpp:receipts") << XATTR("type", receiptType);
+ const string &from = node->getAttributeValue("from");
- return new ProtocolTreeNode("message", ackNode) << XATTR("to", to) << XATTR("type", "chat") << XATTR("id", id);
-}
-
-std::map<string, string>* WAConnection::parseCategories(ProtocolTreeNode* dirtyNode) throw (WAException)
-{
- std::map<string, string>* categories = new std::map<string, string>();
- if (dirtyNode->children != NULL) {
- for (size_t i = 0; i < dirtyNode->children->size(); i++) {
- ProtocolTreeNode* childNode = (*dirtyNode->children)[i];
- if (ProtocolTreeNode::tagEquals(childNode, "category")) {
- const string &categoryName = childNode->getAttributeValue("name");
- const string &timestamp = childNode->getAttributeValue("timestamp");
- (*categories)[categoryName] = timestamp;
- }
+ std::vector<ProtocolTreeNode*> messageChildren(node->getAllChildren());
+ for (size_t i = 0; i < messageChildren.size(); i++) {
+ ProtocolTreeNode *childNode = messageChildren[i];
+ if (ProtocolTreeNode::tagEquals(childNode, "composing")) {
+ if (this->event_handler != NULL)
+ this->event_handler->onIsTyping(from, true);
+ }
+ else if (ProtocolTreeNode::tagEquals(childNode, "paused")) {
+ if (this->event_handler != NULL)
+ this->event_handler->onIsTyping(from, false);
}
}
-
- return categories;
}
-void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messageNode) throw (WAException)
+void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAException)
{
const string &id = messageNode->getAttributeValue("id");
const string &attribute_t = messageNode->getAttributeValue("t");
@@ -546,7 +339,7 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
receiptRequested = true;
}
- ProtocolTreeNode* bodyNode = messageNode->getChild("body");
+ ProtocolTreeNode *bodyNode = messageNode->getChild("body");
if (bodyNode != NULL&& this->group_event_handler != NULL)
this->group_event_handler->onGroupNewSubject(from, author, bodyNode->getDataAsString(), atoi(attribute_t.c_str()));
@@ -560,16 +353,8 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
std::vector<ProtocolTreeNode*> messageChildren(messageNode->getAllChildren());
for (size_t i = 0; i < messageChildren.size(); i++) {
- ProtocolTreeNode* childNode = messageChildren[i];
- if (ProtocolTreeNode::tagEquals(childNode, "composing")) {
- if (this->event_handler != NULL)
- this->event_handler->onIsTyping(from, true);
- }
- else if (ProtocolTreeNode::tagEquals(childNode, "paused")) {
- if (this->event_handler != NULL)
- this->event_handler->onIsTyping(from, false);
- }
- else if (ProtocolTreeNode::tagEquals(childNode, "body")) {
+ ProtocolTreeNode *childNode = messageChildren[i];
+ if (ProtocolTreeNode::tagEquals(childNode, "body")) {
Key* key = new Key(from, false, id);
fmessage->key = key;
fmessage->remote_resource = author;
@@ -596,7 +381,7 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
}
if (fmessage->media_wa_type == FMessage::WA_TYPE_CONTACT) {
- ProtocolTreeNode* contactChildNode = childNode->getChild(0);
+ ProtocolTreeNode *contactChildNode = childNode->getChild(0);
if (contactChildNode != NULL) {
fmessage->media_name = contactChildNode->getAttributeValue("name");
fmessage->data = contactChildNode->getDataAsString();
@@ -616,45 +401,6 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
fmessage->key = key;
fmessage->remote_resource = author;
}
- else if (!ProtocolTreeNode::tagEquals(childNode, "active")) {
- if (ProtocolTreeNode::tagEquals(childNode, "request")) {
- fmessage->wants_receipt = true;
- }
- else if (ProtocolTreeNode::tagEquals(childNode, "notify")) {
- fmessage->notifyname = childNode->getAttributeValue("name");
- }
- else if (ProtocolTreeNode::tagEquals(childNode, "x")) {
- const string &xmlns = childNode->getAttributeValue("xmlns");
- if (xmlns == "jabber:x:event" && !id.empty()) {
- Key* key = new Key(from, true, id);
- FMessage* message = new FMessage(key);
- message->status = FMessage::STATUS_RECEIVED_BY_SERVER;
- if (this->event_handler != NULL)
- this->event_handler->onMessageStatusUpdate(message);
- delete message;
- }
- }
- else if (ProtocolTreeNode::tagEquals(childNode, "received")) {
- Key* key = new Key(from, true, id);
- FMessage* message = new FMessage(key);
- message->status = FMessage::STATUS_RECEIVED_BY_TARGET;
- if (this->event_handler != NULL)
- this->event_handler->onMessageStatusUpdate(message);
- delete message;
- if (this->supportsReceiptAcks()) {
- const string &receipt_type = childNode->getAttributeValue("type");
- if (receipt_type == "delivered")
- sendDeliveredReceiptAck(from, id);
- else if (receipt_type == "visible")
- sendVisibleReceiptAck(from, id);
- }
- }
- else if (ProtocolTreeNode::tagEquals(childNode, "offline")) {
- if (!attribute_t.empty())
- fmessage->timestamp = atoi(attribute_t.c_str());
- fmessage->offline = true;
- }
- }
}
if (fmessage->timestamp == 0) {
@@ -672,13 +418,13 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
bool flag = false;
std::vector<ProtocolTreeNode*> children(messageNode->getAllChildren());
for (size_t i = 0; i < children.size(); i++) {
- ProtocolTreeNode* child = children[i];
+ ProtocolTreeNode *child = children[i];
if (ProtocolTreeNode::tagEquals(child, "notification")) {
const string &type = child->getAttributeValue("type");
if (type == "picture" && this->event_handler != NULL) {
std::vector<ProtocolTreeNode*> children2(child->getAllChildren());
for (unsigned j = 0; j < children2.size(); j++) {
- ProtocolTreeNode* child2 = children2[j];
+ ProtocolTreeNode *child2 = children2[j];
if (ProtocolTreeNode::tagEquals(child2, "set")) {
const string &id = child2->getAttributeValue("id");
const string &author = child2->getAttributeValue("author");
@@ -700,17 +446,174 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag
}
}
-bool WAConnection::supportsReceiptAcks()
+void WAConnection::parseIq(ProtocolTreeNode *node) throw(WAException)
{
- return supports_receipt_acks;
+ const string &type = node->getAttributeValue("type");
+ if (type.empty())
+ throw WAException("missing 'type' attribute in iq stanza", WAException::CORRUPT_STREAM_EX, 0);
+
+ const string &id = node->getAttributeValue("id");
+ const string &from = node->getAttributeValue("from");
+
+ if (type == "result") {
+ if (id.empty())
+ throw WAException("missing 'id' attribute in iq stanza", WAException::CORRUPT_STREAM_EX, 0);
+
+ std::map<string, IqResultHandler*>::iterator it = this->pending_server_requests.find(id);
+ if (it != this->pending_server_requests.end()) {
+ it->second->parse(node, from);
+ delete it->second;
+ this->pending_server_requests.erase(id);
+ }
+ 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");
+ if (kind == "paid")
+ this->account_kind = 1;
+ else if (kind == "free")
+ this->account_kind = 0;
+ else
+ this->account_kind = -1;
+
+ const string &expiration = accountNode->getAttributeValue("expiration");
+ if (expiration.empty())
+ throw WAException("no expiration");
+
+ this->expire_date = atol(expiration.c_str());
+ if (this->expire_date == 0)
+ throw WAException("invalid expire date: " + expiration);
+ if (this->event_handler != NULL)
+ this->event_handler->onAccountChange(this->account_kind, this->expire_date);
+ }
+ }
+ else if (type == "error") {
+ std::map<string, IqResultHandler*>::iterator it = this->pending_server_requests.find(id);
+ if (it != this->pending_server_requests.end()) {
+ it->second->error(node);
+ delete it->second;
+ this->pending_server_requests.erase(id);
+ }
+ }
+ else if (type == "get") {
+ ProtocolTreeNode *childNode = node->getChild(0);
+ if (ProtocolTreeNode::tagEquals(childNode, "ping")) {
+ if (this->event_handler != NULL)
+ this->event_handler->onPing(id);
+ }
+ else if ((ProtocolTreeNode::tagEquals(childNode, "query") && !from.empty()) ? false : (ProtocolTreeNode::tagEquals(childNode, "relay")) && !from.empty()) {
+ const string &pin = childNode->getAttributeValue("pin");
+ if (!pin.empty() && this->event_handler != NULL) {
+ int timeoutSeconds = atoi(childNode->getAttributeValue("timeout").c_str());
+ this->event_handler->onRelayRequest(pin, timeoutSeconds, id);
+ }
+ }
+ }
+ else if (type == "set") {
+ ProtocolTreeNode *childNode = node->getChild(0);
+ if (ProtocolTreeNode::tagEquals(childNode, "query")) {
+ const string &xmlns = childNode->getAttributeValue("xmlns");
+ if (xmlns == "jabber:iq:roster") {
+ std::vector<ProtocolTreeNode*> itemNodes(childNode->getAllChildren("item"));
+ for (size_t i = 0; i < itemNodes.size(); i++) {
+ ProtocolTreeNode *itemNode = itemNodes[i];
+ const string &jid = itemNode->getAttributeValue("jid");
+ const string &subscription = itemNode->getAttributeValue("subscription");
+ // ask = itemNode->getAttributeValue("ask");
+ }
+ }
+ }
+ }
+ else throw WAException("unknown iq type attribute: " + type, WAException::CORRUPT_STREAM_EX, 0);
}
-void WAConnection::sendNotificationReceived(const std::string& jid, const std::string& id) throw(WAException)
+void WAConnection::parsePresense(ProtocolTreeNode *node) throw(WAException)
{
- ProtocolTreeNode* child = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts");
+ const string &xmlns = node->getAttributeValue("xmlns");
+ const string &from = node->getAttributeValue("from");
+ if (from.empty())
+ return;
- this->out->write(ProtocolTreeNode("message", child)
- << XATTR("id", id) << XATTR("type", "notification") << XATTR("to", jid));
+ if (xmlns == "w" && !from.empty()) {
+ const string &add = node->getAttributeValue("add");
+ const string &remove = node->getAttributeValue("remove");
+ const string &status = node->getAttributeValue("status");
+ if (!add.empty()) {
+ if (this->group_event_handler != NULL)
+ this->group_event_handler->onGroupAddUser(from, add);
+ }
+ else if (!remove.empty()) {
+ if (this->group_event_handler != NULL)
+ this->group_event_handler->onGroupRemoveUser(from, remove);
+ }
+ else if (status == "dirty") {
+ std::map<string, string> categories = parseCategories(node);
+ if (this->event_handler != NULL)
+ this->event_handler->onDirty(categories);
+ }
+ return;
+ }
+
+ const string &type = node->getAttributeValue("type");
+ if (type == "unavailable") {
+ if (this->event_handler != NULL)
+ this->event_handler->onAvailable(from, false);
+ }
+ else if (type == "available" || type == "") {
+ if (this->event_handler != NULL)
+ this->event_handler->onAvailable(from, true);
+ }
+}
+
+std::vector<ProtocolTreeNode*>* WAConnection::processGroupSettings(const std::vector<GroupSetting>& groups)
+{
+ std::vector<ProtocolTreeNode*>* result = new std::vector<ProtocolTreeNode*>(groups.size());
+ if (!groups.empty()) {
+ time_t now = time(NULL);
+ for (size_t i = 0; i < groups.size(); i++) {
+ (*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);
+ }
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Send* functions
+
+void WAConnection::sendActive() throw(WAException)
+{
+ this->out->write(ProtocolTreeNode("presence") << XATTR("type", "active"));
+}
+
+void WAConnection::sendAvailableForChat() throw(WAException)
+{
+ this->out->write(ProtocolTreeNode("presence") << XATTR("name", this->nick));
+}
+
+void WAConnection::sendClientConfig(const std::string& sound, const std::string& pushID, bool preview, const std::string& platform) throw(WAException)
+{
+ 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);
+
+ this->out->write(ProtocolTreeNode("iq", configNode)
+ << 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)
+{
+ 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");
+
+ std::string id = makeId("config_");
+ this->out->write(ProtocolTreeNode("iq", configNode) << XATTR("id", id) << XATTR("type", "set") << XATTR("to", this->domain));
}
void WAConnection::sendClose() throw(WAException)
@@ -719,26 +622,19 @@ void WAConnection::sendClose() throw(WAException)
this->out->streamEnd();
}
-void WAConnection::sendGetPrivacyList() throw (WAException)
+void WAConnection::sendComposing(const std::string& to) throw(WAException)
{
- std::string id = makeId("privacylist_");
- this->pending_server_requests[id] = new IqResultPrivayListHandler(this);
-
- 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"));
+ this->out->write(ProtocolTreeNode("chatstate", new ProtocolTreeNode("composing")) << XATTR("to", to));
}
-void WAConnection::sendGetServerProperties() throw (WAException)
+void WAConnection::sendDeleteAccount() 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::string id = makeId("del_acct_");
+ this->pending_server_requests[id] = new IqResultSendDeleteAccount(this);
- this->out->write(ProtocolTreeNode("iq", listNode)
- << XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us"));
+ 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"));
}
void WAConnection::sendGetGroups() throw (WAException)
@@ -751,6 +647,15 @@ void WAConnection::sendGetGroups() throw (WAException)
this->mutex->unlock();
}
+void WAConnection::sendGetGroups(const std::string& id, const std::string& type) throw (WAException)
+{
+ 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::sendGetOwningGroups() throw (WAException)
{
this->mutex->lock();
@@ -761,36 +666,149 @@ void WAConnection::sendGetOwningGroups() throw (WAException)
this->mutex->unlock();
}
-void WAConnection::sendGetGroups(const std::string& id, const std::string& type) throw (WAException)
+void WAConnection::sendGetPicture(const std::string& jid, const std::string& type, const std::string& oldId, const std::string& newId) throw (WAException)
{
- ProtocolTreeNode* listNode = new ProtocolTreeNode("list")
- << XATTR("xmlns", "w:g") << XATTR("type", type);
+ std::string id = makeId("get_picture_");
+ this->pending_server_requests[id] = new IqResultGetPhotoHandler(this, jid, oldId, newId);
+
+ ProtocolTreeNode *listNode = new ProtocolTreeNode("picture")
+ << XATTR("xmlns", "w:profile:picture") << XATTR("type", type);
+
+ this->out->write(ProtocolTreeNode("iq", listNode)
+ << XATTR("id", id) << XATTR("to", jid) << XATTR("type", "get"));
+}
+
+void WAConnection::sendGetPictureIds(const std::vector<std::string>& jids) throw (WAException)
+{
+ std::string id = makeId("get_picture_ids_");
+ this->pending_server_requests[id] = new IqResultGetPictureIdsHandler(this);
+
+ std::vector<ProtocolTreeNode*>* children = new std::vector<ProtocolTreeNode*>();
+ for (size_t i = 0; i < jids.size(); i++) {
+ ProtocolTreeNode *child = new ProtocolTreeNode("user") << XATTR("jid", jids[i]);
+ children->push_back(child);
+ }
+
+ 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::sendGetPrivacyList() throw (WAException)
+{
+ std::string id = makeId("privacylist_");
+ this->pending_server_requests[id] = new IqResultPrivayListHandler(this);
+
+ 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");
this->out->write(ProtocolTreeNode("iq", listNode)
<< XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us"));
}
-void WAConnection::readGroupList(ProtocolTreeNode* node, std::vector<std::string>& groups) throw (WAException)
+void WAConnection::sendInactive() throw(WAException)
{
- std::vector<ProtocolTreeNode*> nodes(node->getAllChildren("group"));
- for (size_t i = 0; i < nodes.size(); i++) {
- ProtocolTreeNode* groupNode = nodes[i];
- const string &gid = groupNode->getAttributeValue("id");
- string gjid = gidToGjid(gid);
- const string &owner = groupNode->getAttributeValue("owner");
- const string &subject = groupNode->getAttributeValue("subject");
- const string &subject_t = groupNode->getAttributeValue("s_t");
- const string &subject_owner = groupNode->getAttributeValue("s_o");
- const string &creation = groupNode->getAttributeValue("creation");
- if (this->group_event_handler != NULL)
- this->group_event_handler->onGroupInfoFromList(gjid, owner, subject, subject_owner, atoi(subject_t.c_str()), atoi(creation.c_str()));
- groups.push_back(gjid);
+ this->out->write(ProtocolTreeNode("presence") << XATTR("type", "inactive"));
+}
+
+void WAConnection::sendMessage(FMessage* message) throw(WAException)
+{
+ if (message->media_wa_type != 0)
+ sendMessageWithMedia(message);
+ else
+ sendMessageWithBody(message);
+}
+
+void WAConnection::sendMessageWithMedia(FMessage* message) throw (WAException)
+{
+ logData("Send message with media %s %d", message->media_name.c_str(), message->media_size);
+ 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");
+
+ 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);
+ mediaNode = new ProtocolTreeNode("media", vcardNode);
}
+ else {
+ mediaNode = new ProtocolTreeNode("media", new std::vector<unsigned char>(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)
+ mediaNode << XATTR("latitude", Utilities::doubleToStr(message->latitude)) << XATTR("longitude", Utilities::doubleToStr(message->longitude));
+ else {
+ 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);
+ }
+
+ ProtocolTreeNode *n = WAConnection::getMessageNode(message, mediaNode);
+ this->out->write(*n);
+ delete n;
}
-std::string WAConnection::gidToGjid(const std::string& gid)
+void WAConnection::sendMessageWithBody(FMessage* message) throw (WAException)
{
- return gid + "@g.us";
+ ProtocolTreeNode *bodyNode = new ProtocolTreeNode("body", new std::vector<unsigned char>(message->data.begin(), message->data.end()));
+ ProtocolTreeNode *n = WAConnection::getMessageNode(message, bodyNode);
+ this->out->write(*n);
+ delete n;
+}
+
+void WAConnection::sendMessageReceived(FMessage* message) throw(WAException)
+{
+ ProtocolTreeNode *receivedNode = new ProtocolTreeNode("received")
+ << XATTR("xmlns", "urn:xmpp:receipts");
+
+ this->out->write(ProtocolTreeNode("message", receivedNode)
+ << XATTR("to", message->key->remote_jid) << XATTR("type", "chat") << XATTR("id", message->key->id));
+}
+
+void WAConnection::sendNotificationReceived(const std::string& jid, const std::string& id) throw(WAException)
+{
+ ProtocolTreeNode *child = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts");
+
+ this->out->write(ProtocolTreeNode("message", child)
+ << XATTR("id", id) << XATTR("type", "notification") << XATTR("to", jid));
+}
+
+void WAConnection::sendPaused(const std::string& to) throw(WAException)
+{
+ this->out->write(ProtocolTreeNode("chatstate", new ProtocolTreeNode("paused")) << XATTR("to", to));
+}
+
+void WAConnection::sendPing() throw(WAException)
+{
+ std::string id = makeId("ping_");
+ this->pending_server_requests[id] = new IqResultPingHandler(this);
+
+ 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)
+{
+ this->out->write(ProtocolTreeNode("iq")
+ << XATTR("type", "result") << XATTR("to", this->domain) << XATTR("id", id));
+}
+
+void WAConnection::sendPresenceSubscriptionRequest(const std::string& to) throw(WAException)
+{
+ this->out->write(ProtocolTreeNode("presence") << XATTR("type", "subscribe") << XATTR("to", to));
}
void WAConnection::sendQueryLastOnline(const std::string& jid) throw (WAException)
@@ -798,17 +816,49 @@ void WAConnection::sendQueryLastOnline(const std::string& jid) throw (WAExceptio
std::string id = makeId("last_");
this->pending_server_requests[id] = new IqResultQueryLastOnlineHandler(this);
- ProtocolTreeNode* queryNode = new ProtocolTreeNode("query") << XATTR("xmlns", "jabber:iq:last");
+ 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::sendSetPicture(const std::string& jid, std::vector<unsigned char>* data) throw (WAException)
+{
+ std::string id = this->makeId("set_photo_");
+ this->pending_server_requests[id] = new IqResultSetPhotoHandler(this, jid);
+
+ 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::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", new std::vector<unsigned char>(status.begin(), status.end()), NULL);
+ ProtocolTreeNode *n = getMessageNode(message, body);
+ this->out->write(*n);
+ delete n;
+ delete message;
+}
+
+void WAConnection::sendSubjectReceived(const std::string& to, const std::string& id)throw(WAException)
+{
+ ProtocolTreeNode *receivedNode = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts");
+
+ this->out->write(ProtocolTreeNode("message", receivedNode)
+ << XATTR("to", to) << XATTR("type", "subject") << XATTR("id", id));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Group chats
+
void WAConnection::sendGetGroupInfo(const std::string& gjid) throw (WAException)
{
std::string id = makeId("get_g_info_");
this->pending_server_requests[id] = new IqResultGetGroupInfoHandler(this);
- ProtocolTreeNode* queryNode = new ProtocolTreeNode("query") << XATTR("xmlns", "w:g");
+ ProtocolTreeNode *queryNode = new ProtocolTreeNode("query") << XATTR("xmlns", "w:g");
this->out->write(ProtocolTreeNode("iq", queryNode)
<< XATTR("id", id) << XATTR("type", "get") << XATTR("to", gjid));
}
@@ -818,16 +868,16 @@ void WAConnection::sendGetParticipants(const std::string& gjid) throw (WAExcepti
std::string id = makeId("get_participants_");
this->pending_server_requests[id] = new IqResultGetGroupParticipantsHandler(this);
- ProtocolTreeNode* listNode = new ProtocolTreeNode("list") << XATTR("xmlns", "w:g");
+ 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<std::string>& vector, const std::string& tag, const std::string& attribute) throw (WAException)
+void WAConnection::readAttributeList(ProtocolTreeNode *node, std::vector<std::string>& vector, const std::string& tag, const std::string& attribute) throw (WAException)
{
std::vector<ProtocolTreeNode*> nodes(node->getAllChildren(tag));
for (size_t i = 0; i < nodes.size(); i++) {
- ProtocolTreeNode* tagNode = nodes[i];
+ ProtocolTreeNode *tagNode = nodes[i];
vector.push_back(tagNode->getAttributeValue(attribute));
}
}
@@ -838,7 +888,7 @@ void WAConnection::sendCreateGroupChat(const std::string& subject) throw (WAExce
std::string id = makeId("create_group_");
this->pending_server_requests[id] = new IqResultCreateGroupChatHandler(this);
- ProtocolTreeNode* groupNode = new ProtocolTreeNode("group")
+ ProtocolTreeNode *groupNode = new ProtocolTreeNode("group")
<< XATTR("xmlns", "w:g") << XATTR("action", "create") << XATTR("subject", subject);
this->out->write(ProtocolTreeNode("iq", groupNode)
@@ -849,7 +899,7 @@ void WAConnection::sendEndGroupChat(const std::string& gjid) throw (WAException)
{
std::string id = makeId("remove_group_");
- ProtocolTreeNode* groupNode = new ProtocolTreeNode("group") << XATTR("xmlns", "w:g") << XATTR("action", "delete");
+ 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));
}
@@ -859,8 +909,8 @@ void WAConnection::sendClearDirty(const std::string& category) throw (WAExceptio
std::string id = makeId("clean_dirty_");
this->pending_server_requests[id] = new IqResultClearDirtyHandler(this);
- ProtocolTreeNode* categoryNode = new ProtocolTreeNode("category") << XATTR("name", category);
- ProtocolTreeNode* cleanNode = new ProtocolTreeNode("clean", categoryNode) << XATTR("xmlns", "urn:xmpp:whatsapp:dirty");
+ 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"));
}
@@ -869,8 +919,8 @@ void WAConnection::sendLeaveGroup(const std::string& gjid) throw (WAException)
{
std::string id = makeId("leave_group_");
- ProtocolTreeNode* groupNode = new ProtocolTreeNode("group") << XATTR("id", gjid);
- ProtocolTreeNode* leaveNode = new ProtocolTreeNode("leave", groupNode) << XATTR("xmlns", "w:g");
+ 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"));
}
@@ -894,7 +944,7 @@ void WAConnection::sendVerbParticipants(const std::string& gjid, const std::vect
for (size_t i = 0; i < size; i++)
(*children)[i] = new ProtocolTreeNode("participant") << XATTR("jid", participants[i]);
- ProtocolTreeNode* innerNode = new ProtocolTreeNode(inner_tag, NULL, children)
+ ProtocolTreeNode *innerNode = new ProtocolTreeNode(inner_tag, NULL, children)
<< XATTR("xmlns", "w:g");
this->out->write(ProtocolTreeNode("iq", innerNode)
@@ -905,76 +955,10 @@ void WAConnection::sendSetNewSubject(const std::string& gjid, const std::string&
{
std::string id = this->makeId("set_group_subject_");
- ProtocolTreeNode* subjectNode = new ProtocolTreeNode("subject")
+ ProtocolTreeNode *subjectNode = new ProtocolTreeNode("subject")
<< XATTR("xmlns", "w:g") << XATTR("value", subject);
this->out->write(ProtocolTreeNode("iq", subjectNode)
<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid));
}
-std::string WAConnection::removeResourceFromJid(const std::string& jid)
-{
- size_t slashidx = jid.find('/');
- if (slashidx == std::string::npos)
- return jid;
-
- return jid.substr(0, slashidx + 1);
-}
-
-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", new std::vector<unsigned char>(status.begin(), status.end()), NULL);
- ProtocolTreeNode *n = getMessageNode(message, body);
- this->out->write(*n);
- delete n;
- delete message;
-}
-
-void WAConnection::sendSetPicture(const std::string& jid, std::vector<unsigned char>* data) throw (WAException)
-{
- std::string id = this->makeId("set_photo_");
- this->pending_server_requests[id] = new IqResultSetPhotoHandler(this, jid);
-
- 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)
-{
- std::string id = makeId("get_picture_");
- this->pending_server_requests[id] = new IqResultGetPhotoHandler(this, jid, oldId, newId);
-
- ProtocolTreeNode* listNode = new ProtocolTreeNode("picture")
- << XATTR("xmlns", "w:profile:picture") << XATTR("type", type);
-
- this->out->write(ProtocolTreeNode("iq", listNode)
- << XATTR("id", id) << XATTR("to", jid) << XATTR("type", "get"));
-}
-
-void WAConnection::sendGetPictureIds(const std::vector<std::string>& jids) throw (WAException)
-{
- std::string id = makeId("get_picture_ids_");
- this->pending_server_requests[id] = new IqResultGetPictureIdsHandler(this);
-
- std::vector<ProtocolTreeNode*>* children = new std::vector<ProtocolTreeNode*>();
- for (size_t i = 0; i < jids.size(); i++) {
- ProtocolTreeNode* child = new ProtocolTreeNode("user") << XATTR("jid", jids[i]);
- children->push_back(child);
- }
-
- 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)
-{
- std::string id = makeId("del_acct_");
- this->pending_server_requests[id] = new IqResultSendDeleteAccount(this);
-
- 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 91164a824f..bbdad6c0e6 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
+++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h
@@ -365,10 +365,15 @@ private:
std::map<string, IqResultHandler*> pending_server_requests;
IMutex *mutex;
+ void parseAck(ProtocolTreeNode *node) throw (WAException);
+ void parseChatStates(ProtocolTreeNode *node) throw (WAException);
+ void parseIq(ProtocolTreeNode *node) throw(WAException);
+ void parseMessage(ProtocolTreeNode* node) throw(WAException);
+ void parsePresense(ProtocolTreeNode*) throw(WAException);
+ std::map<string, string> parseCategories(ProtocolTreeNode* node) throw(WAException);
+
void sendMessageWithMedia(FMessage* message) throw(WAException);
void sendMessageWithBody(FMessage* message) throw(WAException);
- std::map<string, string>* 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);
std::string makeId(const std::string& prefix);
void sendGetGroups(const std::string& id, const std::string& type) throw (WAException);
@@ -391,6 +396,8 @@ public:
std::string jid;
std::string nick;
+ KeyStream inputKey, outputKey;
+
int msg_id;
bool retry;
bool supports_receipt_acks;
@@ -403,16 +410,15 @@ public:
void logData(const char *format, ...);
- static MessageStore* message_store;
- KeyStream inputKey, outputKey;
-
static std::string removeResourceFromJid(const std::string& jid);
- void setLogin(WALogin* login);
+ void setLogin(WALogin *login);
void setVerboseId(bool b);
void sendMessage(FMessage* message) throw(WAException);
void sendAvailableForChat() throw(WAException);
+
bool read() throw(WAException);
+
void sendPing() throw(WAException);
void sendQueryLastOnline(const std::string& jid) throw (WAException);
void sendPong(const std::string& id) throw(WAException);
@@ -422,8 +428,6 @@ public:
void sendPaused(const std::string& to) throw(WAException);
void sendSubjectReceived(const std::string& to, const std::string& id) throw(WAException);
void sendMessageReceived(FMessage* message) throw(WAException);
- void sendDeliveredReceiptAck(const std::string& to, const std::string& id) throw(WAException);
- void sendVisibleReceiptAck(const std::string& to, const std::string& id) throw (WAException);
void sendPresenceSubscriptionRequest(const std::string& to) throw (WAException);
void sendClientConfig(const std::string& sound, const std::string& pushID, bool preview, const std::string& platform) throw(WAException);
void sendClientConfig(const std::string& pushID, bool preview, const std::string& platform, bool defaultSettings, bool groupSettings, const std::vector<GroupSetting>& groups) throw(WAException);
diff --git a/protocols/WhatsApp/src/contacts.cpp b/protocols/WhatsApp/src/contacts.cpp
index 271c038622..39b7c48849 100644
--- a/protocols/WhatsApp/src/contacts.cpp
+++ b/protocols/WhatsApp/src/contacts.cpp
@@ -191,12 +191,6 @@ void WhatsAppProto::UpdateStatusMsg(MCONTACT hContact)
ss << stzLastSeen;
}
- int state = getDword(hContact, WHATSAPP_KEY_LAST_MSG_STATE, 2);
- if (state < 2 && lastSeen != -1)
- ss << _T(" - ");
- for (; state < 2; ++state)
- ss << _T("\u2713");
-
db_set_ws(hContact, "CList", "StatusMsg", ss.str().c_str());
}
diff --git a/protocols/WhatsApp/src/db.h b/protocols/WhatsApp/src/db.h
index 615d0d8608..228a25bde2 100644
--- a/protocols/WhatsApp/src/db.h
+++ b/protocols/WhatsApp/src/db.h
@@ -10,9 +10,6 @@
#define WHATSAPP_KEY_NAME "RealName"
#define WHATSAPP_KEY_PUSH_NAME "Nick"
#define WHATSAPP_KEY_LAST_SEEN "LastSeen"
-#define WHATSAPP_KEY_LAST_MSG_ID_HEADER "LastMsgIdHeader"
-#define WHATSAPP_KEY_LAST_MSG_ID "LastMsgId"
-#define WHATSAPP_KEY_LAST_MSG_STATE "LastMsgState"
#define WHATSAPP_KEY_AVATAR_ID "AvatarId"
#define WHATSAPP_KEY_SYSTRAY_NOTIFY "UseSystrayNotify"
#define WHATSAPP_KEY_DEF_GROUP "DefaultGroup"
diff --git a/protocols/WhatsApp/src/messages.cpp b/protocols/WhatsApp/src/messages.cpp
index d86f5c017d..9fe33b121c 100644
--- a/protocols/WhatsApp/src/messages.cpp
+++ b/protocols/WhatsApp/src/messages.cpp
@@ -40,72 +40,39 @@ void WhatsAppProto::onMessageForMe(FMessage* paramFMessage, bool paramBoolean)
int WhatsAppProto::SendMsg(MCONTACT hContact, int flags, const char *msg)
{
- int msgId = ++(this->msgId);
+ ptrA jid(getStringA(hContact, "ID"));
+ if (jid == NULL)
+ return 0;
- ForkThread(&WhatsAppProto::SendMsgWorker, new send_direct(hContact, msg, (HANDLE)msgId, flags & IS_CHAT));
- return this->msgIdHeader + msgId;
-}
-
-void WhatsAppProto::SendMsgWorker(void* p)
-{
- if (p == NULL)
- return;
-
- DBVARIANT dbv;
- send_direct *data = static_cast<send_direct*>(p);
+ if (m_pConnection != NULL) {
+ debugLogA("No connection");
+ return 0;
+ }
- if (getByte(data->hContact, "SimpleChatRoom", 0) > 0 && getByte(data->hContact, "IsGroupMember", 0) == 0) {
+ if (getByte(hContact, "SimpleChatRoom", 0) > 0 && getByte(hContact, "IsGroupMember", 0) == 0) {
debugLogA("not a group member");
- ProtoBroadcastAck(data->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED,
- (HANDLE)(this->msgIdHeader + this->msgId), (LPARAM) "You cannot send messages to groups if you are not a member.");
+ return 0;
}
- else if (!getString(data->hContact, "ID", &dbv) && m_pConnection != NULL) {
- try {
- setDword(data->hContact, WHATSAPP_KEY_LAST_MSG_STATE, 2);
- setDword(data->hContact, WHATSAPP_KEY_LAST_MSG_ID_HEADER, this->msgIdHeader);
- setDword(data->hContact, WHATSAPP_KEY_LAST_MSG_ID, this->msgId);
-
- std::stringstream ss;
- ss << this->msgIdHeader << "-" << this->msgId;
- Key* key = new Key(Key(dbv.pszVal, true, ss.str())); // deleted by FMessage
- FMessage fmsg(key);
- fmsg.data = data->msg;
- fmsg.timestamp = time(NULL);
-
- db_free(&dbv);
-
- m_pConnection->sendMessage(&fmsg);
- }
- catch (exception &e) {
- debugLogA("exception: %s", e.what());
- ProtoBroadcastAck(data->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED,
- (HANDLE)(this->msgIdHeader + this->msgId), (LPARAM)e.what());
- }
- catch (...) {
- debugLogA("unknown exception");
- ProtoBroadcastAck(data->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED,
- (HANDLE)(this->msgIdHeader + this->msgId), (LPARAM) "Failed sending message");
- }
+
+ int msgId = this->m_pConnection->msg_id++;
+ try {
+ std::string id = "msg" + Utilities::intToStr(msgId);
+ FMessage fmsg(new Key((const char*)jid, true, id));
+ fmsg.data = msg;
+ fmsg.timestamp = time(NULL);
+
+ m_pConnection->sendMessage(&fmsg);
}
- else {
- debugLogA("No connection");
- ProtoBroadcastAck(data->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED,
- (HANDLE)(this->msgIdHeader + this->msgId), (LPARAM) "You cannot send messages when you are offline.");
+ catch (exception &e) {
+ debugLogA("exception: %s", e.what());
+ ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)msgId, (LPARAM)e.what());
+ }
+ catch (...) {
+ debugLogA("unknown exception");
+ ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)msgId, (LPARAM)"Failed sending message");
}
- delete data;
-}
-
-void WhatsAppProto::RecvMsgWorker(void *p)
-{
- if (p == NULL)
- return;
-
- //WAConnection.cpp l1225 - message will be deleted. We cannot send the ack inside a thread!
- //FMessage *fmsg = static_cast<FMessage*>(p);
- //m_pConnection->sendMessageReceived(fmsg);
-
- //delete fmsg;
+ return msgId;
}
void WhatsAppProto::onIsTyping(const std::string& paramString, bool paramBoolean)
@@ -153,27 +120,8 @@ void WhatsAppProto::onMessageStatusUpdate(FMessage* fmsg)
if (hContact == 0)
return;
- int state = 5 - fmsg->status;
- if (state != 0 && state != 1)
- return;
-
- int header;
- int id;
- size_t delimPos = fmsg->key->id.find("-");
-
- std::stringstream ss;
- ss << fmsg->key->id.substr(0, delimPos);
- ss >> header;
-
- ss.clear();
- ss << fmsg->key->id.substr(delimPos + 1);
- ss >> id;
-
- if (state == 1)
- ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)(header + id), 0);
-
- if (getDword(hContact, WHATSAPP_KEY_LAST_MSG_ID_HEADER, 0) == header && getDword(hContact, WHATSAPP_KEY_LAST_MSG_ID, -1) == id) {
- setDword(hContact, WHATSAPP_KEY_LAST_MSG_STATE, state);
- this->UpdateStatusMsg(hContact);
+ if (fmsg->status == FMessage::STATUS_RECEIVED_BY_SERVER) {
+ int msgId = atoi(fmsg->key->id.substr(3).c_str());
+ ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)msgId, 0);
}
}
diff --git a/protocols/WhatsApp/src/proto.cpp b/protocols/WhatsApp/src/proto.cpp
index 10b933b955..bf54fa6e5f 100644
--- a/protocols/WhatsApp/src/proto.cpp
+++ b/protocols/WhatsApp/src/proto.cpp
@@ -16,9 +16,7 @@ WhatsAppProto::WhatsAppProto(const char* proto_name, const TCHAR* username) :
PROTO<WhatsAppProto>(proto_name, username)
{
this->challenge = new std::vector < unsigned char > ;
- this->msgId = 0;
- this->msgIdHeader = time(NULL);
-
+
update_loop_lock_ = CreateEvent(NULL, false, false, NULL);
FMessage::generating_lock = new Mutex();
@@ -211,7 +209,7 @@ HANDLE WhatsAppProto::SearchBasic(const PROTOCHAR* id)
return 0;
// fake - we always accept search
- SearchParam *param = new SearchParam(id, GetSerial());
+ SearchParam *param = new SearchParam(id, m_pConnection->msg_id++);
ForkThread(&WhatsAppProto::SearchAckThread, param);
return (HANDLE)param->id;
}
diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h
index 44dde4958b..7293245831 100644
--- a/protocols/WhatsApp/src/proto.h
+++ b/protocols/WhatsApp/src/proto.h
@@ -104,7 +104,6 @@ public:
// Worker Threads
void __cdecl SendMsgWorker(void*);
- void __cdecl RecvMsgWorker(void*);
void __cdecl SendTypingWorker(void*);
void __cdecl SendGetGroupInfoWorker(void*);
void __cdecl SendSetGroupNameWorker(void*);
@@ -115,6 +114,7 @@ public:
MCONTACT AddToContactList(const std::string &jid, BYTE type = 0, bool dont_check = false,
const char *new_name = NULL, bool isChatRoom = false, bool isHidden = false);
+
bool IsMyContact(MCONTACT hContact, bool include_chat = false);
MCONTACT ContactIDToHContact(const std::string&);
void SetAllContactStatuses(int status, bool reset_client = false);
@@ -134,12 +134,13 @@ public:
bool Register(int state, const string &cc, const string &number, const string &code, string &password);
+private:
+
//////////////////////////////////////////////////////////////////////////////////////
// Helpers
std::tstring GetAvatarFolder();
void ToggleStatusMenuItems(BOOL bEnable);
- LONG GetSerial(void);
//////////////////////////////////////////////////////////////////////////////////////
// Handles, Locks
@@ -153,61 +154,55 @@ public:
std::tstring def_avatar_folder_;
- WASocketConnection* conn;
- WAConnection* m_pConnection;
+ WASocketConnection *conn;
+ WAConnection *m_pConnection;
Mutex connMutex;
int lastPongTime;
- std::vector<unsigned char>* challenge;
- int msgId;
- int msgIdHeader;
+ std::vector<unsigned char> *challenge;
string phoneNumber;
- string jid;
- string nick;
+ string jid, nick;
std::map<string, MCONTACT> hContactByJid;
map<MCONTACT, map<MCONTACT, bool>> isMemberByGroupContact;
-private:
- LONG m_serial;
-
//////////////////////////////////////////////////////////////////////////////////////
// WhatsApp Events
protected:
- virtual void onMessageForMe(FMessage* paramFMessage, bool paramBoolean);
- virtual void onMessageStatusUpdate(FMessage* paramFMessage);
- virtual void onMessageError(FMessage* message, int paramInt) { ; }
- virtual void onPing(const std::string& id) throw (WAException);
+ virtual void onMessageForMe(FMessage *paramFMessage, bool paramBoolean);
+ virtual void onMessageStatusUpdate(FMessage *paramFMessage);
+ virtual void onMessageError(FMessage *message, int paramInt) { ; }
+ virtual void onPing(const std::string &id) throw (WAException);
virtual void onPingResponseReceived() { }
- virtual void onAvailable(const std::string& paramString, bool paramBoolean);
- virtual void onClientConfigReceived(const std::string& paramString) { }
- virtual void onLastSeen(const std::string& paramString1, int paramInt, const std::string& paramString2);
- virtual void onIsTyping(const std::string& paramString, bool paramBoolean);
+ virtual void onAvailable(const std::string &paramString, bool paramBoolean);
+ virtual void onClientConfigReceived(const std::string &paramString) { }
+ virtual void onLastSeen(const std::string &paramString1, int paramInt, const std::string &paramString2);
+ virtual void onIsTyping(const std::string &paramString, bool paramBoolean);
virtual void onAccountChange(int paramInt, time_t expire_date) { }
- virtual void onPrivacyBlockListAdd(const std::string& paramString) { }
+ virtual void onPrivacyBlockListAdd(const std::string &paramString) { }
virtual void onPrivacyBlockListClear() { }
virtual void onDirty(const std::map<string, string>& paramHashtable) { }
virtual void onDirtyResponse(int paramHashtable) { }
- virtual void onRelayRequest(const std::string& paramString1, int paramInt, const std::string& paramString2) { }
+ virtual void onRelayRequest(const std::string &paramString1, int paramInt, const std::string &paramString2) { }
virtual void onSendGetPictureIds(std::map<string, string>* ids);
- virtual void onSendGetPicture(const std::string& jid, const std::vector<unsigned char>& data, const std::string& oldId, const std::string& newId);
- virtual void onPictureChanged(const std::string& from, const std::string& author, bool set);
+ virtual void onSendGetPicture(const std::string &jid, const std::vector<unsigned char>& data, const std::string &oldId, const std::string &newId);
+ virtual void onPictureChanged(const std::string &from, const std::string &author, bool set);
virtual void onDeleteAccount(bool result) { }
- virtual void onGroupAddUser(const std::string& paramString1, const std::string& paramString2);
- virtual void onGroupRemoveUser(const std::string& paramString1, const std::string& paramString2);
- virtual void onGroupNewSubject(const std::string& from, const std::string& author, const std::string& newSubject, int paramInt);
+ virtual void onGroupAddUser(const std::string &paramString1, const std::string &paramString2);
+ virtual void onGroupRemoveUser(const std::string &paramString1, const std::string &paramString2);
+ virtual void onGroupNewSubject(const std::string &from, const std::string &author, const std::string &newSubject, int paramInt);
virtual void onServerProperties(std::map<std::string, std::string>* nameValueMap) { }
- virtual void onGroupCreated(const std::string& paramString1, const std::string& paramString2);
- virtual void onGroupInfo(const std::string& paramString1, const std::string& paramString2, const std::string& paramString3, const std::string& paramString4, int paramInt1, int paramInt2);
- virtual void onGroupInfoFromList(const std::string& paramString1, const std::string& paramString2, const std::string& paramString3, const std::string& paramString4, int paramInt1, int paramInt2);
+ virtual void onGroupCreated(const std::string &paramString1, const std::string &paramString2);
+ virtual void onGroupInfo(const std::string &paramString1, const std::string &paramString2, const std::string &paramString3, const std::string &paramString4, int paramInt1, int paramInt2);
+ virtual void onGroupInfoFromList(const std::string &paramString1, const std::string &paramString2, const std::string &paramString3, const std::string &paramString4, int paramInt1, int paramInt2);
virtual void onOwningGroups(const std::vector<string>& paramVector);
- virtual void onSetSubject(const std::string& paramString) { }
- virtual void onAddGroupParticipants(const std::string& paramString, const std::vector<string>& paramVector, int paramHashtable) { }
- virtual void onRemoveGroupParticipants(const std::string& paramString, const std::vector<string>& paramVector, int paramHashtable) { }
- virtual void onGetParticipants(const std::string& gjid, const std::vector<string>& participants);
+ virtual void onSetSubject(const std::string &paramString) { }
+ virtual void onAddGroupParticipants(const std::string &paramString, const std::vector<string>& paramVector, int paramHashtable) { }
+ virtual void onRemoveGroupParticipants(const std::string &paramString, const std::vector<string>& paramVector, int paramHashtable) { }
+ virtual void onGetParticipants(const std::string &gjid, const std::vector<string>& participants);
virtual void onParticipatingGroups(const std::vector<string>& paramVector);
- virtual void onLeaveGroup(const std::string& paramString);
+ virtual void onLeaveGroup(const std::string &paramString);
//////////////////////////////////////////////////////////////////////////////////////
// Information providing
diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp
index 0155ba2206..0aa95f1a16 100644
--- a/protocols/WhatsApp/src/utils.cpp
+++ b/protocols/WhatsApp/src/utils.cpp
@@ -1,10 +1,5 @@
#include "common.h"
-LONG WhatsAppProto::GetSerial(void)
-{
- return ::InterlockedIncrement(&m_serial);
-}
-
std::string getLastErrorMsg()
{
// Retrieve the system error message for the last-error code