diff options
author | George Hazan <george.hazan@gmail.com> | 2015-02-06 23:36:02 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2015-02-06 23:36:02 +0000 |
commit | b2f86045d3b3dc2a454f127f186429b60e493072 (patch) | |
tree | f56c5696ef3ebf62b1a97e4abbfcbc332adbbd28 /protocols/WhatsApp | |
parent | 8c6ce1ceb218db86d059372e18277c16b1ab20cb (diff) |
merge from branch
git-svn-id: http://svn.miranda-ng.org/main/trunk@12029 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/WhatsApp')
40 files changed, 1109 insertions, 1179 deletions
diff --git a/protocols/WhatsApp/WhatsApp_10.vcxproj b/protocols/WhatsApp/WhatsApp_10.vcxproj index fcace9e0a4..1025f8a435 100644 --- a/protocols/WhatsApp/WhatsApp_10.vcxproj +++ b/protocols/WhatsApp/WhatsApp_10.vcxproj @@ -370,10 +370,6 @@ </ItemGroup>
<ItemGroup>
<None Include="res\add-group.ico" />
- <None Include="res\add-user-to-group.ico" />
- <None Include="res\change-group-subject.ico" />
- <None Include="res\leave-group.ico" />
- <None Include="res\remove-user-from-group.ico" />
<None Include="res\whatsapp.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/protocols/WhatsApp/WhatsApp_10.vcxproj.filters b/protocols/WhatsApp/WhatsApp_10.vcxproj.filters index eb0a64d9d5..e59297c958 100644 --- a/protocols/WhatsApp/WhatsApp_10.vcxproj.filters +++ b/protocols/WhatsApp/WhatsApp_10.vcxproj.filters @@ -227,17 +227,5 @@ <None Include="res\add-group.ico">
<Filter>Resources</Filter>
</None>
- <None Include="res\add-user-to-group.ico">
- <Filter>Resources</Filter>
- </None>
- <None Include="res\change-group-subject.ico">
- <Filter>Resources</Filter>
- </None>
- <None Include="res\leave-group.ico">
- <Filter>Resources</Filter>
- </None>
- <None Include="res\remove-user-from-group.ico">
- <Filter>Resources</Filter>
- </None>
</ItemGroup>
</Project>
\ No newline at end of file diff --git a/protocols/WhatsApp/WhatsApp_12.vcxproj b/protocols/WhatsApp/WhatsApp_12.vcxproj index c38387e23a..f369f65cde 100644 --- a/protocols/WhatsApp/WhatsApp_12.vcxproj +++ b/protocols/WhatsApp/WhatsApp_12.vcxproj @@ -364,10 +364,6 @@ </ItemGroup>
<ItemGroup>
<Image Include="res\add-group.ico" />
- <Image Include="res\add-user-to-group.ico" />
- <Image Include="res\change-group-subject.ico" />
- <Image Include="res\leave-group.ico" />
- <Image Include="res\remove-user-from-group.ico" />
<Image Include="res\whatsapp.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/protocols/WhatsApp/WhatsApp_12.vcxproj.filters b/protocols/WhatsApp/WhatsApp_12.vcxproj.filters index 7511e22832..851eaa9000 100644 --- a/protocols/WhatsApp/WhatsApp_12.vcxproj.filters +++ b/protocols/WhatsApp/WhatsApp_12.vcxproj.filters @@ -224,18 +224,6 @@ <Image Include="res\add-group.ico">
<Filter>Resources\Icons</Filter>
</Image>
- <Image Include="res\add-user-to-group.ico">
- <Filter>Resources\Icons</Filter>
- </Image>
- <Image Include="res\change-group-subject.ico">
- <Filter>Resources\Icons</Filter>
- </Image>
- <Image Include="res\leave-group.ico">
- <Filter>Resources\Icons</Filter>
- </Image>
- <Image Include="res\remove-user-from-group.ico">
- <Filter>Resources\Icons</Filter>
- </Image>
<Image Include="res\whatsapp.ico">
<Filter>Resources\Icons</Filter>
</Image>
diff --git a/protocols/WhatsApp/res/add-user-to-group.ico b/protocols/WhatsApp/res/add-user-to-group.ico Binary files differdeleted file mode 100644 index d99febc5a5..0000000000 --- a/protocols/WhatsApp/res/add-user-to-group.ico +++ /dev/null diff --git a/protocols/WhatsApp/res/change-group-subject.ico b/protocols/WhatsApp/res/change-group-subject.ico Binary files differdeleted file mode 100644 index 6a50c7581e..0000000000 --- a/protocols/WhatsApp/res/change-group-subject.ico +++ /dev/null diff --git a/protocols/WhatsApp/res/leave-group.ico b/protocols/WhatsApp/res/leave-group.ico Binary files differdeleted file mode 100644 index 1e7ea0d9db..0000000000 --- a/protocols/WhatsApp/res/leave-group.ico +++ /dev/null diff --git a/protocols/WhatsApp/res/remove-user-from-group.ico b/protocols/WhatsApp/res/remove-user-from-group.ico Binary files differdeleted file mode 100644 index d9a30dbda1..0000000000 --- a/protocols/WhatsApp/res/remove-user-from-group.ico +++ /dev/null diff --git a/protocols/WhatsApp/res/whatsapp.rc b/protocols/WhatsApp/res/whatsapp.rc index 3099411ab0..102202ff70 100644 --- a/protocols/WhatsApp/res/whatsapp.rc +++ b/protocols/WhatsApp/res/whatsapp.rc @@ -96,19 +96,19 @@ BEGIN CTEXT "-",IDC_STATIC,82,62,8,8
END
-IDD_INPUTBOX DIALOGEX 0, 0, 300, 66
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "WhatsApp"
-FONT 8, "MS Shell Dlg", 400, 0, 0x0
+IDD_GROUPCHAT_INVITE DIALOGEX 0, 0, 215, 170
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Invite Users"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- LTEXT "",IDC_TEXT,12,11,288,8
- EDITTEXT IDC_VALUE,12,24,282,12,ES_AUTOHSCROLL
- PUSHBUTTON "Cancel",IDC_CANCEL,164,45,60,14
- PUSHBUTTON "OK",IDC_OK,228,45,66,14
+ GROUPBOX "Choose an user",IDC_STATIC,4,2,208,130
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x1,12,12,192,112,WS_EX_CLIENTEDGE
+ LTEXT "Other user:",IDC_STATIC,4,138,55,8
+ EDITTEXT IDC_NEWJID,60,136,152,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Invite",IDOK,108,152,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,162,152,50,14
END
-
/////////////////////////////////////////////////////////////////////////////
//
// Icon
@@ -118,10 +118,7 @@ END // remains consistent on all systems.
IDI_WHATSAPP ICON "whatsapp.ico"
IDI_ADD_GROUP ICON "add-group.ico"
-IDI_ADD_USER_TO_GROUP ICON "add-user-to-group.ico"
-IDI_CHANGE_GROUP_SUBJECT ICON "change-group-subject.ico"
-IDI_LEAVE_GROUP ICON "leave-group.ico"
-IDI_REMOVE_USER_FROM_GROUP ICON "remove-user-from-group.ico"
+
#endif // German (Germany) resources
/////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/WhatsApp/src/WASocketConnection.cpp b/protocols/WhatsApp/src/WASocketConnection.cpp index 2ff362b9bf..6852fb92dd 100644 --- a/protocols/WhatsApp/src/WASocketConnection.cpp +++ b/protocols/WhatsApp/src/WASocketConnection.cpp @@ -12,7 +12,7 @@ void WASocketConnection::quitNetwork() {
}
-WASocketConnection::WASocketConnection(const std::string& dir, int port) throw (WAException)
+WASocketConnection::WASocketConnection(const std::string &dir, int port) throw (WAException)
{
NETLIBOPENCONNECTION noc = { sizeof(noc) };
noc.szHost = dir.c_str();
diff --git a/protocols/WhatsApp/src/WASocketConnection.h b/protocols/WhatsApp/src/WASocketConnection.h index 1f0034471b..e6dcc472a6 100644 --- a/protocols/WhatsApp/src/WASocketConnection.h +++ b/protocols/WhatsApp/src/WASocketConnection.h @@ -1,12 +1,8 @@ #if !defined(WASOCKETCONNECTION_H)
#define WASOCKETCONNECTION_H
-#include "common.h"
#include "WhatsAPI++/ISocketConnection.h"
-#include <iostream>
#include "WhatsAPI++/WAException.h"
-#include "WhatsAPI++/WALogin.h"
-#include <windows.h>
class WASocketConnection : public ISocketConnection
{
@@ -21,7 +17,7 @@ private: HANDLE hConn;
public:
- WASocketConnection(const std::string& dir, int port) throw (WAException);
+ WASocketConnection(const std::string &dir, int port) throw (WAException);
virtual ~WASocketConnection();
void write(int i);
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp index 035a3c9d39..00909b6855 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp @@ -134,7 +134,7 @@ void BinTreeNodeWriter::writeAttributes(std::map<string, string>* attributes) }
}
-void BinTreeNodeWriter::writeString(const std::string& tag)
+void BinTreeNodeWriter::writeString(const std::string &tag)
{
int token = WAConnection::tokenLookup(tag);
if (token != -1)
@@ -151,7 +151,7 @@ void BinTreeNodeWriter::writeString(const std::string& tag) }
}
-void BinTreeNodeWriter::writeJid(std::string* user, const std::string& server)
+void BinTreeNodeWriter::writeJid(std::string* user, const std::string &server)
{
out->write(250);
if (user != NULL && !user->empty())
@@ -265,12 +265,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
+
if (node.tag.empty())
out->write(0);
else
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h index 5a43d660b1..9b59f26f03 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h @@ -47,8 +47,8 @@ private: void writeInt16(int v, ByteArrayOutputStream* out);
void writeInt16(int v);
void writeAttributes(std::map<string, string>* attributes);
- void writeString(const std::string& tag);
- void writeJid(std::string* user, const std::string& server);
+ void writeString(const std::string &tag);
+ void writeJid(std::string* user, const std::string &server);
void writeToken(int intValue);
void writeBytes(unsigned char* bytes, int length);
void writeInt24(int v);
diff --git a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp index 7e98847cff..5df55f97ab 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp @@ -51,7 +51,7 @@ void ByteArrayOutputStream::write(unsigned char* b, size_t len) write(b[i]);
}
-void ByteArrayOutputStream::write(const std::string& s)
+void ByteArrayOutputStream::write(const std::string &s)
{
for (size_t i = 0; i < s.size(); i++)
write((unsigned char)s[i]);
diff --git a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h index 5a3f90d221..d3375d1f3b 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h +++ b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h @@ -26,7 +26,7 @@ public: void setPosition(size_t count);
void write(int i);
void write(unsigned char* c, size_t length);
- void write(const std::string& s);
+ void write(const std::string &s);
void setLength(size_t length);
__forceinline size_t getCapacity() const { return buf.capacity(); }
diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp index 23461b30fc..8f5fd2dcc9 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp @@ -57,7 +57,7 @@ FMessage::~FMessage() {
}
-Key::Key(const std::string& remote_jid, bool from_me, const std::string& id)
+Key::Key(const std::string &remote_jid, bool from_me, const std::string &id)
{
this->remote_jid = remote_jid;
this->from_me = from_me;
@@ -70,7 +70,7 @@ std::string Key::toString() }
-unsigned char FMessage::getMessage_WA_Type(const std::string& type)
+unsigned char FMessage::getMessage_WA_Type(const std::string &type)
{
if (type.empty())
return WA_TYPE_UNDEFINED;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.h b/protocols/WhatsApp/src/WhatsAPI++/FMessage.h index 9b6a29b038..0d55aa6804 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.h +++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.h @@ -21,7 +21,7 @@ struct Key bool from_me;
std::string id;
- Key(const std::string& remote_jid, bool from_me, const std::string& id);
+ Key(const std::string &remote_jid, bool from_me, const std::string &id);
std::string toString();
};
diff --git a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp index d027cb9c86..c50e4cbbd1 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp @@ -36,7 +36,7 @@ void KeyStream::init(unsigned char* _key, unsigned char* _keyMac) RC4(&this->rc4, sizeof(drop), drop, drop);
}
-void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector<unsigned char>& nonce, unsigned char *out)
+void KeyStream::keyFromPasswordAndNonce(const std::string &pass, const std::vector<unsigned char>& nonce, unsigned char *out)
{
size_t cbSize = nonce.size();
diff --git a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h index aeb1b6e18e..50e0f4033d 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h +++ b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h @@ -55,21 +55,21 @@ public: map<string, string> *attributes;
vector<ProtocolTreeNode*> *children;
- ProtocolTreeNode(const string& tag, ProtocolTreeNode* child);
- ProtocolTreeNode(const string& tag, vector<unsigned char>* data = NULL, vector<ProtocolTreeNode*> *children = NULL);
+ ProtocolTreeNode(const string &tag, ProtocolTreeNode *child);
+ ProtocolTreeNode(const string &tag, vector<unsigned char> *data = NULL, vector<ProtocolTreeNode*> *children = NULL);
~ProtocolTreeNode();
string toString() const;
- ProtocolTreeNode* getChild(const string& id);
+ ProtocolTreeNode* getChild(const string &id);
ProtocolTreeNode* getChild(size_t id);
- const string& getAttributeValue(const string& attribute);
+ const string& getAttributeValue(const string &attribute);
vector<ProtocolTreeNode*> getAllChildren();
- vector<ProtocolTreeNode*> getAllChildren(const string& tag);
+ vector<ProtocolTreeNode*> getAllChildren(const string &tag);
std::string getDataAsString() const;
- static bool tagEquals(ProtocolTreeNode *node, const string& tag);
- static void require(ProtocolTreeNode *node, const string& tag);
+ static bool tagEquals(ProtocolTreeNode *node, const string &tag);
+ static void require(ProtocolTreeNode *node, const string &tag);
};
ProtocolTreeNode& operator<<(ProtocolTreeNode&, const XATTR&);
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp index f1e671a4de..be44413c52 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp @@ -204,6 +204,8 @@ bool WAConnection::read() throw(WAException) parsePresense(node);
else if (ProtocolTreeNode::tagEquals(node, "message"))
parseMessage(node);
+ else if (ProtocolTreeNode::tagEquals(node, "notification"))
+ parseNotification(node);
else if (ProtocolTreeNode::tagEquals(node, "ack"))
parseAck(node);
else if (ProtocolTreeNode::tagEquals(node, "receipt"))
@@ -228,7 +230,7 @@ void WAConnection::readGroupList(ProtocolTreeNode *node, std::vector<std::string const string &subject_owner = groupNode->getAttributeValue("s_o");
const string &creation = groupNode->getAttributeValue("creation");
if (m_pGroupEventHandler != NULL)
- m_pGroupEventHandler->onGroupInfoFromList(gjid, owner, subject, subject_owner, atoi(subject_t.c_str()), atoi(creation.c_str()));
+ m_pGroupEventHandler->onGroupInfo(gjid, owner, subject, subject_owner, atoi(subject_t.c_str()), atoi(creation.c_str()));
groups.push_back(gjid);
}
}
@@ -260,26 +262,10 @@ void WAConnection::parseAck(ProtocolTreeNode *node) throw(WAException) if (cls == "message" && m_pEventHandler != NULL) {
FMessage msg(from, true, id);
msg.status = FMessage::STATUS_RECEIVED_BY_SERVER;
- m_pEventHandler->onMessageStatusUpdate(&msg);
+ m_pEventHandler->onMessageStatusUpdate(msg);
}
}
-void WAConnection::parseReceipt(ProtocolTreeNode *node) throw(WAException)
-{
- const string &from = node->getAttributeValue("from");
- const string &id = node->getAttributeValue("id");
- const string &ts = node->getAttributeValue("t");
-
- if (m_pEventHandler != NULL) {
- FMessage msg(from, false, id);
- msg.status = FMessage::STATUS_RECEIVED_BY_TARGET;
- m_pEventHandler->onMessageStatusUpdate(&msg);
- }
-
- out.write(ProtocolTreeNode("ack")
- << XATTR("to", from) << XATTR("id", id) << XATTR("type", "read") << XATTRI("t", time(0)));
-}
-
void WAConnection::parseChatStates(ProtocolTreeNode *node) throw (WAException)
{
const string &from = node->getAttributeValue("from");
@@ -298,6 +284,99 @@ void WAConnection::parseChatStates(ProtocolTreeNode *node) throw (WAException) }
}
+void WAConnection::parseIq(ProtocolTreeNode *node) throw(WAException)
+{
+ 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 (m_pEventHandler != NULL)
+ m_pEventHandler->onAccountChange(this->account_kind, this->expire_date);
+ }
+ else {
+ ProtocolTreeNode *childNode = node->getChild(0);
+ if (ProtocolTreeNode::tagEquals(childNode, "leave")) {
+ std::vector<ProtocolTreeNode*> nodes(childNode->getAllChildren("group"));
+ for (size_t i = 0; i < nodes.size(); i++) {
+ ProtocolTreeNode *groupNode = nodes[i];
+ const string &gjid = groupNode->getAttributeValue("id");
+ if (m_pGroupEventHandler != NULL)
+ m_pGroupEventHandler->onLeaveGroup(gjid);
+ }
+ }
+ }
+ }
+ 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 (m_pEventHandler != NULL)
+ m_pEventHandler->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() && m_pEventHandler != NULL) {
+ int timeoutSeconds = atoi(childNode->getAttributeValue("timeout").c_str());
+ m_pEventHandler->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::parseMessage(ProtocolTreeNode *messageNode) throw (WAException)
{
const string &id = messageNode->getAttributeValue("id");
@@ -321,23 +400,7 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio message.status = FMessage::STATUS_SERVER_BOUNCE;
if (m_pEventHandler != NULL)
- m_pEventHandler->onMessageError(&message, errorCode);
- }
- else if (typeAttribute == "subject") {
- bool receiptRequested = false;
- std::vector<ProtocolTreeNode*> requestNodes(messageNode->getAllChildren("request"));
- for (size_t i = 0; i < requestNodes.size(); i++) {
- ProtocolTreeNode *requestNode = requestNodes[i];
- if (requestNode->getAttributeValue("xmlns") == "urn:xmpp:receipts")
- receiptRequested = true;
- }
-
- ProtocolTreeNode *bodyNode = messageNode->getChild("body");
- if (bodyNode != NULL&& m_pGroupEventHandler != NULL)
- m_pGroupEventHandler->onGroupNewSubject(from, author, bodyNode->getDataAsString(), atoi(attribute_t.c_str()));
-
- if (receiptRequested)
- sendSubjectReceived(from, id);
+ m_pEventHandler->onMessageError(message, errorCode);
}
else if (typeAttribute == "text") {
ProtocolTreeNode *body = messageNode->getChild("body");
@@ -347,6 +410,7 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio FMessage fmessage(from, false, id);
fmessage.wants_receipt = false;
fmessage.timestamp = atoi(attribute_t.c_str());
+ fmessage.remote_resource = messageNode->getAttributeValue("participant");
fmessage.notifyname = messageNode->getAttributeValue("notify");
fmessage.data = body->getDataAsString();
fmessage.status = FMessage::STATUS_UNSENT;
@@ -354,8 +418,13 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio fmessage.timestamp = time(NULL);
fmessage.offline = false;
}
- if (m_pEventHandler != NULL)
- m_pEventHandler->onMessageForMe(&fmessage, false);
+
+ if (fmessage.remote_resource.empty()) {
+ if (m_pEventHandler != NULL)
+ m_pEventHandler->onMessageForMe(fmessage);
+ }
+ else if (m_pGroupEventHandler != NULL)
+ m_pGroupEventHandler->onGroupMessage(fmessage);
}
else if (typeAttribute == "media") {
if (from.empty() || id.empty())
@@ -421,120 +490,87 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio }
if (m_pEventHandler != NULL)
- m_pEventHandler->onMessageForMe(&fmessage, false);
- }
- else if (typeAttribute == "notification") {
- logData("Notification node %s", messageNode->toString().c_str());
- bool flag = false;
- std::vector<ProtocolTreeNode*> children(messageNode->getAllChildren());
- for (size_t i = 0; i < children.size(); i++) {
- ProtocolTreeNode *child = children[i];
- if (ProtocolTreeNode::tagEquals(child, "notification")) {
- const string &type = child->getAttributeValue("type");
- if (type == "picture" && m_pEventHandler != NULL) {
- std::vector<ProtocolTreeNode*> children2(child->getAllChildren());
- for (unsigned j = 0; j < children2.size(); j++) {
- ProtocolTreeNode *child2 = children2[j];
- if (ProtocolTreeNode::tagEquals(child2, "set")) {
- const string &id = child2->getAttributeValue("id");
- const string &author = child2->getAttributeValue("author");
- if (!id.empty())
- m_pEventHandler->onPictureChanged(from, author, true);
- }
- else if (ProtocolTreeNode::tagEquals(child2, "delete")) {
- const string &author = child2->getAttributeValue("author");
- m_pEventHandler->onPictureChanged(from, author, false);
- }
- }
- }
- }
- else if (ProtocolTreeNode::tagEquals(child, "request"))
- flag = true;
- }
- if (flag)
- this->sendNotificationReceived(from, id);
+ m_pEventHandler->onMessageForMe(fmessage);
}
}
-void WAConnection::parseIq(ProtocolTreeNode *node) throw(WAException)
+void WAConnection::parseNotification(ProtocolTreeNode *node) throw(WAException)
{
- 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");
+ const string &type = node->getAttributeValue("type");
+ if (type.empty() || from.empty() || m_pEventHandler == NULL)
+ return;
- if (type == "result") {
- if (id.empty())
- throw WAException("missing 'id' attribute in iq stanza", WAException::CORRUPT_STREAM_EX, 0);
+ const string &participant = node->getAttributeValue("participant");
+ int ts = atoi(node->getAttributeValue("t").c_str());
- 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;
+ if (type == "contacts") {
+ std::vector<ProtocolTreeNode*> children(node->getAllChildren());
+ for (size_t i = 0; i < children.size(); i++) {
+ ProtocolTreeNode *child = children[i];
- const string &expiration = accountNode->getAttributeValue("expiration");
- if (expiration.empty())
- throw WAException("no expiration");
+ const string &jid = node->getAttributeValue("jid");
+ if (jid.empty()) continue;
- this->expire_date = atol(expiration.c_str());
- if (this->expire_date == 0)
- throw WAException("invalid expire date: " + expiration);
- if (m_pEventHandler != NULL)
- m_pEventHandler->onAccountChange(this->account_kind, this->expire_date);
+ bool bAdded;
+ if (ProtocolTreeNode::tagEquals(child, "add"))
+ bAdded = true;
+ else if (ProtocolTreeNode::tagEquals(child, "delete"))
+ bAdded = false;
+ else
+ continue;
+
+ m_pEventHandler->onContactChanged(jid, bAdded);
}
}
- 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 == "picture") {
+ std::vector<ProtocolTreeNode*> children2(node->getAllChildren());
+ for (unsigned j = 0; j < children2.size(); j++) {
+ ProtocolTreeNode *child2 = children2[j];
+ if (ProtocolTreeNode::tagEquals(child2, "set")) {
+ const string &id = child2->getAttributeValue("id");
+ const string &jid = child2->getAttributeValue("jid");
+ if (!id.empty())
+ m_pEventHandler->onPictureChanged(jid, id, true);
+ }
+ else if (ProtocolTreeNode::tagEquals(child2, "delete")) {
+ const string &jid = child2->getAttributeValue("jid");
+ m_pEventHandler->onPictureChanged(jid, id, false);
+ }
}
}
- else if (type == "get") {
- ProtocolTreeNode *childNode = node->getChild(0);
- if (ProtocolTreeNode::tagEquals(childNode, "ping")) {
- if (m_pEventHandler != NULL)
- m_pEventHandler->onPing(id);
+ // group chats
+ else if (type == "participant") {
+ ProtocolTreeNode *subNode = node->getChild("add");
+ if (subNode != NULL) {
+ const string &jid = subNode->getAttributeValue("jid");
+ if (m_pGroupEventHandler)
+ m_pGroupEventHandler->onGroupAddUser(from, jid, ts);
}
- else if ((ProtocolTreeNode::tagEquals(childNode, "query") && !from.empty()) ? false : (ProtocolTreeNode::tagEquals(childNode, "relay")) && !from.empty()) {
- const string &pin = childNode->getAttributeValue("pin");
- if (!pin.empty() && m_pEventHandler != NULL) {
- int timeoutSeconds = atoi(childNode->getAttributeValue("timeout").c_str());
- m_pEventHandler->onRelayRequest(pin, timeoutSeconds, id);
- }
+ else if ((subNode = node->getChild("remove")) != NULL) {
+ const string &jid = subNode->getAttributeValue("jid");
+ if (m_pGroupEventHandler)
+ m_pGroupEventHandler->onGroupRemoveUser(from, jid, ts);
}
+ else return;
+
}
- 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 if (type == "subject") {
+ ProtocolTreeNode *bodyNode = node->getChild("body");
+ if (bodyNode != NULL && m_pGroupEventHandler != NULL)
+ m_pGroupEventHandler->onGroupNewSubject(from, participant, bodyNode->getDataAsString(), ts);
+ return; // don't set ack
}
- else throw WAException("unknown iq type attribute: " + type, WAException::CORRUPT_STREAM_EX, 0);
+
+ ProtocolTreeNode sendNode("ack");
+ sendNode << XATTR("to", from) << XATTR("id", id) << XATTR("type", type) << XATTR("class", "notification");
+ const string &to = node->getAttributeValue("to");
+ if (!to.empty())
+ sendNode << XATTR("from", to);
+ if (!participant.empty())
+ sendNode << XATTR("participant", participant);
+ out.write(sendNode);
}
void WAConnection::parsePresense(ProtocolTreeNode *node) throw(WAException)
@@ -544,17 +580,18 @@ void WAConnection::parsePresense(ProtocolTreeNode *node) throw(WAException) if (from.empty())
return;
+ int ts = atoi(node->getAttributeValue("t").c_str());
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 (m_pGroupEventHandler != NULL)
- m_pGroupEventHandler->onGroupAddUser(from, add);
+ m_pGroupEventHandler->onGroupAddUser(from, add, ts);
}
else if (!remove.empty()) {
if (m_pGroupEventHandler != NULL)
- m_pGroupEventHandler->onGroupRemoveUser(from, remove);
+ m_pGroupEventHandler->onGroupRemoveUser(from, remove, ts);
}
else if (status == "dirty") {
std::map<string, string> categories = parseCategories(node);
@@ -575,6 +612,22 @@ void WAConnection::parsePresense(ProtocolTreeNode *node) throw(WAException) }
}
+void WAConnection::parseReceipt(ProtocolTreeNode *node) throw(WAException)
+{
+ const string &from = node->getAttributeValue("from");
+ const string &id = node->getAttributeValue("id");
+ const string &ts = node->getAttributeValue("t");
+
+ if (m_pEventHandler != NULL) {
+ FMessage msg(from, false, id);
+ msg.status = FMessage::STATUS_RECEIVED_BY_TARGET;
+ m_pEventHandler->onMessageStatusUpdate(msg);
+ }
+
+ out.write(ProtocolTreeNode("ack")
+ << XATTR("to", from) << XATTR("id", id) << XATTR("type", "read") << XATTRI("t", time(0)));
+}
+
std::vector<ProtocolTreeNode*>* WAConnection::processGroupSettings(const std::vector<GroupSetting>& groups)
{
std::vector<ProtocolTreeNode*>* result = new std::vector<ProtocolTreeNode*>(groups.size());
@@ -650,29 +703,11 @@ void WAConnection::sendDeleteAccount() throw (WAException) void WAConnection::sendGetGroups() throw (WAException)
{
m_pMutex->lock();
- std::string id = makeId("get_groups_");
+ std::string id = makeId("iq_");
this->pending_server_requests[id] = new IqResultGetGroupsHandler(this, "participating");
- sendGetGroups(id, "participating");
- m_pMutex->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);
-
- out.write(ProtocolTreeNode("iq", listNode)
- << XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us"));
-}
-
-void WAConnection::sendGetOwningGroups() throw (WAException)
-{
- m_pMutex->lock();
- std::string id = makeId("get_owning_groups_");
- this->pending_server_requests[id] = new IqResultGetGroupsHandler(this, "owning");
-
- sendGetGroups(id, "owning");
+ out.write(ProtocolTreeNode("iq", new ProtocolTreeNode("list") << XATTR("type", "participating"))
+ << XATTR("xmlns", "w:g") << XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us"));
m_pMutex->unlock();
}
@@ -702,10 +737,9 @@ 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");
+ ProtocolTreeNode *listNode = new ProtocolTreeNode("list") << XATTR("type", "props");
- out.write(ProtocolTreeNode("iq", listNode)
+ out.write(ProtocolTreeNode("iq", listNode) << XATTR("xmlns", "w:g2")
<< XATTR("id", id) << XATTR("type", "get") << XATTR("to", "g.us"));
}
@@ -775,22 +809,14 @@ void WAConnection::sendMessageWithBody(FMessage* message) throw (WAException) delete n;
}
-void WAConnection::sendMessageReceived(FMessage* message) throw(WAException)
+void WAConnection::sendMessageReceived(const FMessage &message) throw(WAException)
{
out.write(ProtocolTreeNode("receipt") << XATTR("type", "read")
- << XATTR("to", message->key.remote_jid) << XATTR("id", message->key.id) << XATTRI("t", (int)time(0)));
+ << XATTR("to", message.key.remote_jid) << XATTR("id", message.key.id) << XATTRI("t", (int)time(0)));
}
/////////////////////////////////////////////////////////////////////////////////////////
-void WAConnection::sendNotificationReceived(const std::string &jid, const std::string &id) throw(WAException)
-{
- ProtocolTreeNode *child = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts");
-
- out.write(ProtocolTreeNode("message", child)
- << XATTR("id", id) << XATTR("type", "notification") << XATTR("to", jid));
-}
-
void WAConnection::sendPaused(const std::string &to) throw(WAException)
{
out.write(ProtocolTreeNode("chatstate", new ProtocolTreeNode("paused")) << XATTR("to", to));
@@ -851,34 +877,26 @@ void WAConnection::sendStatusUpdate(std::string& status) throw (WAException) delete n;
}
-void WAConnection::sendSubjectReceived(const std::string &to, const std::string &id)throw(WAException)
-{
- ProtocolTreeNode *receivedNode = new ProtocolTreeNode("received") << XATTR("xmlns", "urn:xmpp:receipts");
-
- 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_");
+ std::string id = makeId("iq_");
this->pending_server_requests[id] = new IqResultGetGroupInfoHandler(this);
- ProtocolTreeNode *queryNode = new ProtocolTreeNode("query") << XATTR("xmlns", "w:g");
- out.write(ProtocolTreeNode("iq", queryNode)
+ ProtocolTreeNode *queryNode = new ProtocolTreeNode("query") << XATTR("request", "interactive");
+ out.write(ProtocolTreeNode("iq", queryNode) << XATTR("xmlns", "w:g2")
<< XATTR("id", id) << XATTR("type", "get") << XATTR("to", gjid));
}
void WAConnection::sendGetParticipants(const std::string &gjid) throw (WAException)
{
- std::string id = makeId("get_participants_");
+ std::string id = makeId("iq_");
this->pending_server_requests[id] = new IqResultGetGroupParticipantsHandler(this);
- ProtocolTreeNode *listNode = new ProtocolTreeNode("list") << XATTR("xmlns", "w:g");
- out.write(ProtocolTreeNode("iq", listNode)
+ ProtocolTreeNode *listNode = new ProtocolTreeNode("list");
+ out.write(ProtocolTreeNode("iq", listNode) << XATTR("xmlns", "w:g")
<< XATTR("id", id) << XATTR("type", "get") << XATTR("to", gjid));
}
@@ -895,24 +913,14 @@ void WAConnection::sendCreateGroupChat(const std::string &subject) throw (WAExce {
logData("sending create group: %s", subject.c_str());
std::string id = makeId("create_group_");
- this->pending_server_requests[id] = new IqResultCreateGroupChatHandler(this);
+ this->pending_server_requests[id] = new IqResultCreateGroupChatHandler(this, subject);
- ProtocolTreeNode *groupNode = new ProtocolTreeNode("group")
- << XATTR("xmlns", "w:g") << XATTR("action", "create") << XATTR("subject", subject);
+ ProtocolTreeNode *groupNode = new ProtocolTreeNode("group") << XATTR("action", "create") << XATTR("subject", subject);
- out.write(ProtocolTreeNode("iq", groupNode)
+ out.write(ProtocolTreeNode("iq", groupNode) << XATTR("xmlns", "w:g")
<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", "g.us"));
}
-void WAConnection::sendEndGroupChat(const std::string &gjid) throw (WAException)
-{
- std::string id = makeId("remove_group_");
-
- ProtocolTreeNode *groupNode = new ProtocolTreeNode("group") << XATTR("xmlns", "w:g") << XATTR("action", "delete");
- out.write(ProtocolTreeNode("iq", groupNode)
- << XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid));
-}
-
void WAConnection::sendClearDirty(const std::string &category) throw (WAException)
{
std::string id = makeId("clean_dirty_");
@@ -924,49 +932,48 @@ void WAConnection::sendClearDirty(const std::string &category) throw (WAExceptio << XATTR("id", id) << XATTR("type", "set") << XATTR("to", "s.whatsapp.net"));
}
-void WAConnection::sendLeaveGroup(const std::string &gjid) throw (WAException)
+void WAConnection::sendJoinLeaveGroup(const char *gjid, bool bJoin) throw (WAException)
{
- std::string id = makeId("leave_group_");
+ std::string id = makeId("iq_");
ProtocolTreeNode *groupNode = new ProtocolTreeNode("group") << XATTR("id", gjid);
- ProtocolTreeNode *leaveNode = new ProtocolTreeNode("leave", groupNode) << XATTR("xmlns", "w:g");
- out.write(ProtocolTreeNode("iq", leaveNode)
+ ProtocolTreeNode *leaveNode = new ProtocolTreeNode((bJoin) ? "join" : "leave", groupNode);
+ out.write(ProtocolTreeNode("iq", leaveNode) << XATTR("xmlns", "w:g2")
<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", "g.us"));
}
-void WAConnection::sendAddParticipants(const std::string &gjid, const std::vector<std::string>& participants) throw (WAException)
+void WAConnection::sendAddParticipants(const std::string &gjid, const std::vector<std::string> &participants) throw (WAException)
{
- std::string id = makeId("add_group_participants_");
- this->sendVerbParticipants(gjid, participants, id, "add");
+ sendVerbParticipants(gjid, participants, "add");
}
-void WAConnection::sendRemoveParticipants(const std::string &gjid, const std::vector<std::string>& participants) throw (WAException)
+void WAConnection::sendRemoveParticipants(const std::string &gjid, const std::vector<std::string> &participants) throw (WAException)
{
- std::string id = makeId("remove_group_participants_");
- this->sendVerbParticipants(gjid, participants, id, "remove");
+ sendVerbParticipants(gjid, participants, "remove");
}
-void WAConnection::sendVerbParticipants(const std::string &gjid, const std::vector<std::string>& participants, const std::string &id, const std::string &inner_tag) throw (WAException)
+void WAConnection::sendVerbParticipants(const std::string &gjid, const std::vector<std::string> &participants, const std::string &inner_tag) throw (WAException)
{
+ std::string id = makeId("iq_");
+
size_t size = participants.size();
std::vector<ProtocolTreeNode*>* children = new std::vector<ProtocolTreeNode*>(size);
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)
- << XATTR("xmlns", "w:g");
+ ProtocolTreeNode *innerNode = new ProtocolTreeNode(inner_tag, NULL, children);
- out.write(ProtocolTreeNode("iq", innerNode)
+ out.write(ProtocolTreeNode("iq", innerNode) << XATTR("xmlns", "w:g")
<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid));
}
void WAConnection::sendSetNewSubject(const std::string &gjid, const std::string &subject) throw (WAException)
{
- std::string id = this->makeId("set_group_subject_");
+ std::string id = this->makeId("iq_");
- ProtocolTreeNode *subjectNode = new ProtocolTreeNode("subject")
- << XATTR("xmlns", "w:g") << XATTR("value", subject);
+ std::vector<unsigned char> *data = new std::vector<unsigned char>(subject.begin(), subject.end());
+ ProtocolTreeNode *subjectNode = new ProtocolTreeNode("subject", data);
- out.write(ProtocolTreeNode("iq", subjectNode)
+ out.write(ProtocolTreeNode("iq", subjectNode) << XATTR("xmlns", "w:g2")
<< XATTR("id", id) << XATTR("type", "set") << XATTR("to", gjid));
}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h index 6f4fb2b4f2..bddfe1ccd7 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h @@ -30,42 +30,41 @@ class BinTreeNodeReader; class WAListener {
public:
- virtual void onMessageForMe(FMessage* paramFMessage, bool paramBoolean) throw (WAException)=0;
- virtual void onMessageStatusUpdate(FMessage* paramFMessage)=0;
- virtual void onMessageError(FMessage* message, int paramInt)=0;
- virtual void onPing(const std::string& paramString) throw (WAException)=0;
- virtual void onPingResponseReceived()=0;
- virtual void onAvailable(const std::string& paramString, bool paramBoolean)=0;
- virtual void onClientConfigReceived(const std::string& paramString)=0;
- virtual void onLastSeen(const std::string& paramString1, int paramInt, const string ¶mString2) = 0;
- virtual void onIsTyping(const std::string& paramString, bool paramBoolean)=0;
- virtual void onAccountChange(int paramInt, time_t paramLong)=0;
- virtual void onPrivacyBlockListAdd(const std::string& paramString)=0;
- virtual void onPrivacyBlockListClear()=0;
- virtual void onDirty(const std::map<string,string>& paramHashtable)=0;
- virtual void onDirtyResponse(int paramHashtable)=0;
- virtual void onRelayRequest(const std::string& paramString1, int paramInt, const std::string& paramString2)=0;
- virtual void onSendGetPicture(const std::string& jid, const std::vector<unsigned char>& data, const std::string& id)=0;
- virtual void onPictureChanged(const std::string& from, const std::string& author, bool set)=0;
- virtual void onDeleteAccount(bool result)=0;
+ virtual void onMessageForMe(const FMessage ¶mFMessage) throw (WAException) = 0;
+ virtual void onMessageStatusUpdate(const FMessage ¶mFMessage) = 0;
+ virtual void onMessageError(const FMessage &message, int paramInt) = 0;
+ virtual void onPing(const std::string ¶mString) throw (WAException) = 0;
+ virtual void onPingResponseReceived() = 0;
+ virtual void onAvailable(const std::string ¶mString, bool paramBoolean) = 0;
+ virtual void onClientConfigReceived(const std::string ¶mString) = 0;
+ virtual void onLastSeen(const std::string ¶mString1, int paramInt, const string ¶mString2) = 0;
+ virtual void onIsTyping(const std::string ¶mString, bool paramBoolean) = 0;
+ virtual void onAccountChange(int paramInt, time_t paramLong) = 0;
+ virtual void onPrivacyBlockListAdd(const std::string ¶mString) = 0;
+ virtual void onPrivacyBlockListClear() = 0;
+ virtual void onDirty(const std::map<string, string>& paramHashtable) = 0;
+ virtual void onDirtyResponse(int paramHashtable) = 0;
+ virtual void onRelayRequest(const std::string ¶mString1, int paramInt, const std::string ¶mString2) = 0;
+ virtual void onSendGetPicture(const std::string &jid, const std::vector<unsigned char>& data, const std::string &id) = 0;
+ virtual void onContactChanged(const std::string &jid, bool added) = 0;
+ virtual void onPictureChanged(const std::string &jid, const std::string &id, bool set) = 0;
+ virtual void onDeleteAccount(bool result) = 0;
};
class WAGroupListener {
public:
- virtual void onGroupAddUser(const std::string& paramString1, const std::string& paramString2)=0;
- virtual void onGroupRemoveUser(const std::string& paramString1, const std::string& paramString2)=0;
- virtual void onGroupNewSubject(const std::string& from, const std::string& author, const std::string& newSubject, int paramInt)=0;
- virtual void onServerProperties(std::map<std::string, std::string>* nameValueMap)=0;
- virtual void onGroupCreated(const std::string& paramString1, const std::string& paramString2)=0;
- virtual void onGroupInfo(const std::string& paramString1, const std::string& paramString2, const std::string& paramString3, const std::string& paramString4, int paramInt1, int paramInt2)=0;
- virtual void onGroupInfoFromList(const std::string& paramString1, const std::string& paramString2, const std::string& paramString3, const std::string& paramString4, int paramInt1, int paramInt2)=0;
- virtual void onOwningGroups(const std::vector<string>& paramVector)=0;
- virtual void onSetSubject(const std::string& paramString)=0;
- virtual void onAddGroupParticipants(const std::string& paramString, const std::vector<string>& paramVector, int paramHashtable)=0;
- virtual void onRemoveGroupParticipants(const std::string& paramString, const std::vector<string>& paramVector, int paramHashtable)=0;
- virtual void onGetParticipants(const std::string& gjid, const std::vector<string>& participants)=0;
- virtual void onParticipatingGroups(const std::vector<string>& paramVector)=0;
- virtual void onLeaveGroup(const std::string& paramString)=0;
+ virtual void onGroupAddUser(const std::string &gjid, const std::string &ujid, int ts) = 0;
+ virtual void onGroupRemoveUser(const std::string &gjid, const std::string &ujid, int ts) = 0;
+ virtual void onGroupNewSubject(const std::string &from, const std::string &author, const std::string &newSubject, int paramInt) = 0;
+ virtual void onGroupMessage(const FMessage ¶mFMessage) = 0;
+ virtual void onServerProperties(std::map<std::string, std::string>* nameValueMap) = 0;
+ virtual void onGroupCreated(const std::string &gjid, const std::string &nick) = 0;
+ virtual void onGroupInfo(const std::string &jid, const std::string &owner, const std::string &subject, const std::string &subject_owner, int time_subject, int time_created) = 0;
+ virtual void onSetSubject(const std::string ¶mString) = 0;
+ virtual void onAddGroupParticipants(const std::string ¶mString, const std::vector<string> ¶mVector, int paramHashtable) = 0;
+ virtual void onRemoveGroupParticipants(const std::string ¶mString, const std::vector<string> ¶mVector, int paramHashtable) = 0;
+ virtual void onGetParticipants(const std::string &gjid, const std::vector<string> &participants) = 0;
+ virtual void onLeaveGroup(const std::string ¶mString) = 0;
};
class GroupSetting {
@@ -88,7 +87,7 @@ class WAConnection WAConnection* con;
public:
IqResultHandler(WAConnection* con) {this->con = con;}
- virtual void parse(ProtocolTreeNode* paramProtocolTreeNode, const std::string& paramString) throw (WAException)=0;
+ virtual void parse(ProtocolTreeNode* paramProtocolTreeNode, const std::string ¶mString) throw (WAException)=0;
void error(ProtocolTreeNode* node, int code) {
con->logData("WAConnection: error node %s: code = %d", node->getAttributeValue("id").c_str(), code);
}
@@ -112,7 +111,7 @@ class WAConnection class IqResultPingHandler: public IqResultHandler {
public:
IqResultPingHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
if (this->con->m_pEventHandler != NULL)
this->con->m_pEventHandler->onPingResponseReceived();
}
@@ -127,23 +126,17 @@ class WAConnection private:
std::string type;
public:
- IqResultGetGroupsHandler(WAConnection* con, const std::string& type ):IqResultHandler(con) {this->type = type;}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ IqResultGetGroupsHandler(WAConnection* con, const std::string &type ):IqResultHandler(con) {this->type = type;}
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
std::vector<std::string> groups;
this->con->readGroupList(node, groups);
- if (this->con->m_pGroupEventHandler != NULL) {
- if (this->type.compare("participating") == 0)
- this->con->m_pGroupEventHandler->onParticipatingGroups(groups);
- else if (this->type.compare("owning") == 0)
- this->con->m_pGroupEventHandler->onOwningGroups(groups);
- }
}
};
class IqResultServerPropertiesHandler: public IqResultHandler {
public:
IqResultServerPropertiesHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
std::vector<ProtocolTreeNode*> nodes(node->getAllChildren("prop"));
std::map<std::string,std::string> nameValueMap;
for (size_t i = 0; i < nodes.size();i++) {
@@ -161,7 +154,7 @@ class WAConnection class IqResultPrivayListHandler: public IqResultHandler {
public:
IqResultPrivayListHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
ProtocolTreeNode* queryNode = node->getChild(0);
ProtocolTreeNode::require(queryNode, "query");
ProtocolTreeNode* listNode = queryNode->getChild(0);
@@ -185,7 +178,7 @@ class WAConnection class IqResultGetGroupInfoHandler: public IqResultHandler {
public:
IqResultGetGroupInfoHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
ProtocolTreeNode* groupNode = node->getChild(0);
ProtocolTreeNode::require(groupNode, "group");
const string &owner = groupNode->getAttributeValue("owner");
@@ -201,30 +194,34 @@ class WAConnection class IqResultGetGroupParticipantsHandler: public IqResultHandler {
public:
IqResultGetGroupParticipantsHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
- std::vector<std::string> participants;
- this->con->readAttributeList(node, participants, "participant", "jid");
- if (this->con->m_pGroupEventHandler != NULL)
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
+ if (this->con->m_pGroupEventHandler != NULL) {
+ std::vector<std::string> participants;
+ this->con->readAttributeList(node, participants, "participant", "jid");
this->con->m_pGroupEventHandler->onGetParticipants(from, participants);
+ }
}
};
class IqResultCreateGroupChatHandler: public IqResultHandler {
+ std::string subject;
public:
- IqResultCreateGroupChatHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ IqResultCreateGroupChatHandler(WAConnection* con, const std::string &_subject) :
+ IqResultHandler(con),
+ subject(_subject) {}
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
ProtocolTreeNode* groupNode = node->getChild(0);
ProtocolTreeNode::require(groupNode, "group");
const string &groupId = groupNode->getAttributeValue("id");
if (!groupId.empty() && con->m_pGroupEventHandler != NULL)
- this->con->m_pGroupEventHandler->onGroupCreated(from, groupId);
+ this->con->m_pGroupEventHandler->onGroupCreated(groupId + "@" + from, subject);
}
};
class IqResultQueryLastOnlineHandler: public IqResultHandler {
public:
IqResultQueryLastOnlineHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
ProtocolTreeNode* firstChild = node->getChild(0);
ProtocolTreeNode::require(firstChild, "query");
const string &seconds = firstChild->getAttributeValue("seconds");
@@ -241,10 +238,10 @@ class WAConnection std::string oldId;
std::string newId;
public:
- IqResultGetPhotoHandler(WAConnection* con, const std::string& jid):IqResultHandler(con) {
+ IqResultGetPhotoHandler(WAConnection* con, const std::string &jid):IqResultHandler(con) {
this->jid = jid;
}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
const string &attributeValue = node->getAttributeValue("type");
if (!attributeValue.empty() && attributeValue == "result" && this->con->m_pEventHandler != NULL) {
@@ -272,8 +269,8 @@ class WAConnection private:
std::string jid;
public:
- IqResultSetPhotoHandler(WAConnection* con, const std::string& jid):IqResultHandler(con) {this->jid = jid;}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ IqResultSetPhotoHandler(WAConnection* con, const std::string &jid):IqResultHandler(con) {this->jid = jid;}
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
if (this->con->m_pEventHandler != NULL) {
ProtocolTreeNode* child = node->getChild("picture");
if (child != NULL)
@@ -287,7 +284,7 @@ class WAConnection class IqResultSendDeleteAccount: public IqResultHandler {
public:
IqResultSendDeleteAccount(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
if (this->con->m_pEventHandler != NULL)
this->con->m_pEventHandler->onDeleteAccount(true);
}
@@ -301,14 +298,14 @@ class WAConnection class IqResultClearDirtyHandler: public IqResultHandler {
public:
IqResultClearDirtyHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
}
};
class IqSendClientConfigHandler: public IqResultHandler {
public:
IqSendClientConfigHandler(WAConnection* con):IqResultHandler(con) {}
- virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
+ virtual void parse(ProtocolTreeNode* node, const std::string &from) throw (WAException) {
con->logData("Clientconfig response %s", node->toString().c_str());
}
@@ -334,25 +331,25 @@ private: void parseChatStates(ProtocolTreeNode *node) throw (WAException);
void parseIq(ProtocolTreeNode *node) throw(WAException);
void parseMessage(ProtocolTreeNode* node) throw(WAException);
+ void parseNotification(ProtocolTreeNode *node) throw(WAException);
void parsePresense(ProtocolTreeNode*) throw(WAException);
void parseReceipt(ProtocolTreeNode *node) throw (WAException);
std::map<string, string> parseCategories(ProtocolTreeNode* node) throw(WAException);
void sendMessageWithMedia(FMessage* message) throw(WAException);
void sendMessageWithBody(FMessage* message) 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);
+ ProtocolTreeNode* getReceiptAck(const std::string &to, const std::string &id, const std::string &receiptType) throw(WAException);
+ std::string makeId(const std::string &prefix);
void readGroupList(ProtocolTreeNode* node, std::vector<std::string>& groups) throw (WAException);
- std::string gidToGjid(const std::string& gid);
- void readAttributeList(ProtocolTreeNode* node, std::vector<std::string>& vector, const std::string& tag, const std::string& attribute) throw (WAException);
- void sendVerbParticipants(const std::string& gjid, const std::vector<std::string>& participants, const std::string& id, const std::string& inner_tag) throw (WAException);
+ std::string gidToGjid(const std::string &gid);
+ void readAttributeList(ProtocolTreeNode* node, std::vector<std::string> &vector, const std::string &tag, const std::string &attribute) throw (WAException);
+ void sendVerbParticipants(const std::string &gjid, const std::vector<std::string> &participants, const std::string &inner_tag) throw (WAException);
bool supportsReceiptAcks();
static ProtocolTreeNode* getMessageNode(FMessage* message, ProtocolTreeNode* node);
std::vector<ProtocolTreeNode*>* processGroupSettings(const std::vector<GroupSetting>& gruops);
public:
- WAConnection(const std::string& user, const std::string& resource, IMutex* mutex, IMutex *write_mutex, ISocketConnection *conn, WAListener* m_pEventHandler, WAGroupListener* m_pGroupEventHandler);
+ WAConnection(const std::string &user, const std::string &resource, IMutex* mutex, IMutex *write_mutex, ISocketConnection *conn, WAListener* m_pEventHandler, WAGroupListener* m_pGroupEventHandler);
virtual ~WAConnection();
std::string user;
@@ -374,7 +371,7 @@ public: void logData(const char *format, ...);
- static std::string removeResourceFromJid(const std::string& jid);
+ static std::string removeResourceFromJid(const std::string &jid);
void setLogin(WALogin *login);
void setVerboseId(bool b);
@@ -384,36 +381,32 @@ public: bool read() throw(WAException);
void sendPing() throw(WAException);
- void sendQueryLastOnline(const std::string& jid) throw (WAException);
- void sendPong(const std::string& id) throw(WAException);
- void sendComposing(const std::string& to) throw(WAException);
+ void sendQueryLastOnline(const std::string &jid) throw (WAException);
+ void sendPong(const std::string &id) throw(WAException);
+ void sendComposing(const std::string &to) throw(WAException);
void sendActive() throw(WAException);
void sendInactive() throw(WAException);
- 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 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);
+ void sendPaused(const std::string &to) throw(WAException);
+ void sendMessageReceived(const FMessage &message) 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);
void sendClose() throw (WAException);
void sendAvailable() throw (WAException); // U.H.
void sendGetPrivacyList() throw (WAException);
void sendGetServerProperties() throw (WAException);
void sendGetGroups() throw (WAException);
- void sendGetOwningGroups() throw (WAException);
- void sendCreateGroupChat(const std::string& subject) throw (WAException);
- void sendEndGroupChat(const std::string& gjid) throw (WAException);
- void sendGetGroupInfo(const std::string& gjid) throw (WAException);
- void sendGetParticipants(const std::string& gjid) throw (WAException);
- void sendClearDirty(const std::string& category) throw (WAException);
- void sendLeaveGroup(const std::string& gjid) throw (WAException);
- void sendAddParticipants(const std::string& gjid, const std::vector<std::string>& participants) throw (WAException);
- void sendRemoveParticipants(const std::string& gjid, const std::vector<std::string>& participants) throw (WAException);
- void sendSetNewSubject(const std::string& gjid, const std::string& subject) throw (WAException);
+ void sendCreateGroupChat(const std::string &subject) throw (WAException);
+ void sendGetGroupInfo(const std::string &gjid) throw (WAException);
+ void sendGetParticipants(const std::string &gjid) throw (WAException);
+ void sendClearDirty(const std::string &category) throw (WAException);
+ void sendJoinLeaveGroup(const char *gjid, bool bJoin) throw (WAException);
+ void sendAddParticipants(const std::string &gjid, const std::vector<std::string> &participants) throw (WAException);
+ void sendRemoveParticipants(const std::string &gjid, const std::vector<std::string> &participant) throw (WAException);
+ void sendSetNewSubject(const std::string &gjid, const std::string &subject) throw (WAException);
void sendStatusUpdate(std::string& status) throw (WAException);
- void sendGetPicture(const std::string& jid, const std::string& type) throw (WAException);
- void sendSetPicture(const std::string& jid, std::vector<unsigned char>* data, std::vector<unsigned char>* preview) throw (WAException);
- void sendNotificationReceived(const std::string& from, const std::string& id) throw(WAException);
+ void sendGetPicture(const std::string &jid, const std::string &type) throw (WAException);
+ void sendSetPicture(const std::string &jid, std::vector<unsigned char>* data, std::vector<unsigned char>* preview) throw (WAException);
void sendDeleteAccount() throw(WAException);
};
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAException.h b/protocols/WhatsApp/src/WhatsAPI++/WAException.h index 47d5cdfaf7..4255850ffc 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAException.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAException.h @@ -32,9 +32,9 @@ public: static const int SOCKET_EX_SEND = 3;
static const int SOCKET_EX_RECV = 4;
- WAException(const std::string& err): runtime_error(err) {this->type = 0; this->subtype = 0; this->expire_date = 0;};
- WAException(const std::string& err, int type, int subtype): runtime_error(err), type(type), subtype(subtype), expire_date(0) {};
- WAException(const std::string& err, int type, int subtype, time_t expireDate): runtime_error(err), type(type), subtype(subtype), expire_date(expireDate) {};
+ WAException(const std::string &err): runtime_error(err) {this->type = 0; this->subtype = 0; this->expire_date = 0;};
+ WAException(const std::string &err, int type, int subtype): runtime_error(err), type(type), subtype(subtype), expire_date(0) {};
+ WAException(const std::string &err, int type, int subtype, time_t expireDate): runtime_error(err), type(type), subtype(subtype), expire_date(expireDate) {};
};
#endif /* WAEXCEPTION_H_ */
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp index edec990dfa..80be5402ed 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp @@ -8,7 +8,6 @@ #include "WALogin.h"
#include "ByteArray.h"
#include "ProtocolTreeNode.h"
-#include "WAException.h"
#include <iostream>
#include <vector>
#include <map>
@@ -18,7 +17,7 @@ using namespace Utilities;
-WALogin::WALogin(WAConnection* connection, const std::string& password)
+WALogin::WALogin(WAConnection* connection, const std::string &password)
{
m_pConnection = connection;
m_szPassword = password;
@@ -97,12 +96,9 @@ std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char std::vector<unsigned char> WALogin::readFeaturesUntilChallengeOrSuccess()
{
while (ProtocolTreeNode *root = m_pConnection->in.nextTree()) {
- #ifdef _DEBUG
- {
- string tmp = root->toString();
- m_pConnection->logData(tmp.c_str());
- }
- #endif
+ string tmp = root->toString();
+ m_pConnection->logData(tmp.c_str());
+
if (ProtocolTreeNode::tagEquals(root, "stream:features")) {
m_pConnection->supports_receipt_acks = root->getChild("receipt_acks") != NULL;
delete root;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h index 30c5937810..0d4d30af5b 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.h @@ -35,7 +35,7 @@ public: void init(unsigned char *_key, unsigned char *_keyMac);
- static void keyFromPasswordAndNonce(const std::string& pass, const std::vector<unsigned char>& nonce, unsigned char *out);
+ 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);
};
@@ -58,7 +58,7 @@ public: int m_iAccountKind;
std::string m_szPassword;
- WALogin(WAConnection* connection, const std::string& password);
+ WALogin(WAConnection* connection, const std::string &password);
~WALogin();
std::vector<unsigned char> login(const std::vector<unsigned char> &blob);
diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp index 0734c34210..1c6f28e009 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp @@ -14,7 +14,7 @@ const static char digits[] = { 'u', 'v', 'w', 'x', 'y', 'z'
};
-std::string reverseString(const std::string& str)
+std::string reverseString(const std::string &str)
{
return std::string(str.rbegin(), str.rend());
}
@@ -51,7 +51,7 @@ std::string itoa(int value, unsigned int base) }
-std::string processIdentity(const std::string& id)
+std::string processIdentity(const std::string &id)
{
std::string buffer_str = reverseString(id);
@@ -69,7 +69,7 @@ std::string processIdentity(const std::string& id) return buffer_str;
}
-void debug(const std::string& msg)
+void debug(const std::string &msg)
{
#ifdef _LOGWIN32
cout << "DEBUG: " << msg << endl;
@@ -153,7 +153,7 @@ time_t parseBBDate(const string& s) return mktime(&timeinfo);
}
-long long parseLongLong(const std::string& str)
+long long parseLongLong(const std::string &str)
{
std::stringstream sstr(str);
long long val;
@@ -235,7 +235,7 @@ vector<unsigned char>* loadFileToBytes(const string& path) return bytes;
}
-bool fileExists(const std::string& path)
+bool fileExists(const std::string &path)
{
return _access(path.c_str(), 0) == 0;
}
@@ -260,7 +260,7 @@ string removeWaDomainFromJid(const string& jid) return jid;
}
-string getNameFromPath(const std::string& path)
+string getNameFromPath(const std::string &path)
{
size_t i = path.rfind('/');
if (i == string::npos)
@@ -270,17 +270,17 @@ string getNameFromPath(const std::string& path) return path.substr(i);
}
-vector<unsigned char>* getChallengeData(const std::string& challengeFile)
+vector<unsigned char>* getChallengeData(const std::string &challengeFile)
{
return loadFileToBytes(challengeFile);
}
-bool saveChallengeData(const std::vector<unsigned char>& data, const std::string& challengeFile)
+bool saveChallengeData(const std::vector<unsigned char>& data, const std::string &challengeFile)
{
return saveBytesToFile(data, challengeFile);
}
-std::string utf8_to_utf16(const std::string& utf8)
+std::string utf8_to_utf16(const std::string &utf8)
{
std::vector<unsigned long> unicode;
size_t i = 0;
diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.h b/protocols/WhatsApp/src/WhatsAPI++/utilities.h index 4df6fde13d..5f5dd5713a 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.h +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.h @@ -38,20 +38,20 @@ using namespace std; // these functions must be declared somewhere in the same linking module
std::string base64_encode(void*, size_t);
-void md5_string(const std::string& data, unsigned char digest[16]);
+void md5_string(const std::string &data, unsigned char digest[16]);
namespace Utilities{
string getMcc();
string getMnc();
string reverseString(const string& str);
- string processIdentity(const std::string& password);
+ string processIdentity(const std::string &password);
int64_t randLong();
int64_t absLong(int64_t num);
string str(int64_t number, int radix);
std::string itoa(int value, unsigned int base);
std::string intToStr(int i);
std::string doubleToStr(double d);
- long long parseLongLong(const std::string& str);
+ long long parseLongLong(const std::string &str);
time_t parseBBDate(const string& s);
long long getCurrentTimeMillis();
std::string bytesToHex(unsigned char* bytes, int length);
@@ -60,11 +60,11 @@ namespace Utilities{ bool saveBytesToFile(const string& data, const string& filePath);
bool saveBytesToFile(const std::vector<unsigned char>& data, const string& filePath);
string removeWaDomainFromJid(const string& jid);
- string getNameFromPath(const std::string& path);
+ string getNameFromPath(const std::string &path);
vector<unsigned char>* loadFileToBytes(const string& path);
- bool fileExists(const std::string& path);
- std::vector<unsigned char>* getChallengeData(const std::string& file);
- bool saveChallengeData(const std::vector<unsigned char>& data, const std::string& file);
- std::string utf8_to_utf16(const std::string& utf8);
+ bool fileExists(const std::string &path);
+ std::vector<unsigned char>* getChallengeData(const std::string &file);
+ bool saveChallengeData(const std::vector<unsigned char>& data, const std::string &file);
+ std::string utf8_to_utf16(const std::string &utf8);
}
#endif
diff --git a/protocols/WhatsApp/src/chat.cpp b/protocols/WhatsApp/src/chat.cpp index 361da25850..1f855f9b55 100644 --- a/protocols/WhatsApp/src/chat.cpp +++ b/protocols/WhatsApp/src/chat.cpp @@ -1,64 +1,485 @@ #include "common.h"
-// #TODO Remove, as we are not using the chat-module for groups anymore
+static const TCHAR *sttStatuses[] = { LPGENT("Members"), LPGENT("Owners") };
-INT_PTR WhatsAppProto::OnJoinChat(WPARAM, LPARAM)
+enum
{
- return 0;
-}
+ IDM_CANCEL,
+
+ IDM_INVITE, IDM_LEAVE, IDM_TOPIC,
-INT_PTR WhatsAppProto::OnLeaveChat(WPARAM, LPARAM)
+ IDM_MESSAGE, IDM_KICK,
+ IDM_CPY_NICK, IDM_CPY_TOPIC,
+ IDM_ADD_RJID, IDM_CPY_RJID
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// protocol menu handler - create a new group
+
+INT_PTR __cdecl WhatsAppProto::OnCreateGroup(WPARAM wParam, LPARAM lParam)
{
- return 0;
+ ENTER_STRING es = { 0 };
+ es.cbSize = sizeof(es);
+ es.type = ESF_MULTILINE;
+ es.caption = _T("Enter a subject for new group");
+ es.szModuleName = m_szModuleName;
+ if (EnterString(&es)) {
+ if (isOnline()) {
+ std::string groupName(ptrA(mir_utf8encodeT(es.ptszResult)));
+ m_pConnection->sendCreateGroupChat(groupName);
+ }
+ mir_free(es.ptszResult);
+ }
+
+ return FALSE;
}
-int WhatsAppProto::OnChatOutgoing(WPARAM wParam, LPARAM lParam)
+/////////////////////////////////////////////////////////////////////////////////////////
+// handler to pass events from SRMM to WAConnection
+
+int WhatsAppProto::onGroupChatEvent(WPARAM wParam, LPARAM lParam)
{
- GCHOOK *hook = reinterpret_cast<GCHOOK*>(lParam);
- char *text;
+ GCHOOK *gch = (GCHOOK*)lParam;
+ if (mir_strcmp(gch->pDest->pszModule, m_szModuleName))
+ return 0;
- if (strcmp(hook->pDest->pszModule, m_szModuleName))
+ std::string chat_id(ptrA(mir_utf8encodeT(gch->pDest->ptszID)));
+ WAChatInfo *pInfo = SafeGetChat(chat_id);
+ if (pInfo == NULL)
return 0;
- switch (hook->pDest->iType) {
+ switch (gch->pDest->iType) {
+ case GC_USER_LEAVE:
+ case GC_SESSION_TERMINATE:
+ break;
+
+ case GC_USER_LOGMENU:
+ ChatLogMenuHook(pInfo, gch);
+ break;
+
+ case GC_USER_NICKLISTMENU:
+ NickListMenuHook(pInfo, gch);
+ break;
+
case GC_USER_MESSAGE:
- text = mir_t2a_cp(hook->ptszText, CP_UTF8);
- {
- std::string msg = text;
-
- char *id = mir_t2a_cp(hook->pDest->ptszID, CP_UTF8);
- std::string chat_id = id;
-
- mir_free(text);
- mir_free(id);
-
- if (isOnline()) {
- MCONTACT hContact = this->ContactIDToHContact(chat_id);
- if (hContact) {
- debugLogA("**Chat - Outgoing message: %s", text);
- this->SendMsg(hContact, IS_CHAT, msg.c_str());
-
- GCDEST gcd = { m_szModuleName, hook->pDest->ptszID, GC_EVENT_MESSAGE };
- GCEVENT gce = { sizeof(gce), &gcd };
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.ptszNick = mir_a2t(m_szNick.c_str());
- gce.ptszUID = mir_a2t(m_szJid.c_str());
- gce.time = time(NULL);
- gce.ptszText = hook->ptszText;
- gce.bIsMe = TRUE;
- CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
-
- mir_free((void*)gce.ptszUID);
- mir_free((void*)gce.ptszNick);
- }
+ if (isOnline()) {
+ std::string msg(ptrA(mir_utf8encodeT(gch->ptszText)));
+
+ try {
+ int msgId = GetSerial();
+ time_t now = time(NULL);
+ std::string id = Utilities::intToStr(now) + "-" + Utilities::intToStr(msgId);
+
+ FMessage fmsg(chat_id, true, id);
+ fmsg.timestamp = now;
+ fmsg.data = msg;
+ m_pConnection->sendMessage(&fmsg);
+
+ pInfo->m_unsentMsgs[id] = gch->ptszText;
}
+ CODE_BLOCK_CATCH_ALL
}
break;
+ }
- case GC_USER_LEAVE:
- case GC_SESSION_TERMINATE:
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// chat log menu event handler
+
+static gc_item sttLogListItems[] =
+{
+ { LPGENT("&Invite a user"), IDM_INVITE, MENU_ITEM },
+ { NULL, 0, MENU_SEPARATOR },
+ { LPGENT("&Room options"), 0, MENU_NEWPOPUP },
+ { LPGENT("View/change &topic"), IDM_TOPIC, MENU_POPUPITEM },
+ { LPGENT("&Leave chat session"), IDM_LEAVE, MENU_POPUPITEM },
+ { NULL, 0, MENU_SEPARATOR },
+ { LPGENT("Copy room &JID"), IDM_CPY_RJID, MENU_ITEM },
+ { LPGENT("Copy room topic"), IDM_CPY_TOPIC, MENU_ITEM },
+};
+
+void WhatsAppProto::ChatLogMenuHook(WAChatInfo *pInfo, struct GCHOOK *gch)
+{
+ switch (gch->dwData) {
+ case IDM_INVITE:
+ InviteChatUser(pInfo);
break;
+
+ case IDM_TOPIC:
+ EditChatSubject(pInfo);
+ break;
+
+ case IDM_CPY_RJID:
+ utils::copyText(pcli->hwndContactList, pInfo->tszJid);
+ break;
+
+ case IDM_CPY_TOPIC:
+ utils::copyText(pcli->hwndContactList, pInfo->tszNick);
+ break;
+
+ case IDM_LEAVE:
+ if (isOnline())
+ m_pConnection->sendJoinLeaveGroup(_T2A(pInfo->tszJid), false);
+ break;
+ }
+}
+
+void WhatsAppProto::EditChatSubject(WAChatInfo *pInfo)
+{
+ CMString title(FORMAT, TranslateT("Set new subject for %s"), pInfo->tszNick);
+ ptrT tszOldValue(getTStringA(pInfo->hContact, "Nick"));
+
+ ENTER_STRING es = { 0 };
+ es.cbSize = sizeof(es);
+ es.type = ESF_RICHEDIT;
+ es.szModuleName = m_szModuleName;
+ es.ptszInitVal = tszOldValue;
+ es.caption = title;
+ es.szDataPrefix = "setSubject_";
+ if (EnterString(&es)) {
+ ptrA gjid(mir_utf8encodeT(pInfo->tszJid));
+ ptrA gsubject(mir_utf8encodeT(es.ptszResult));
+ m_pConnection->sendSetNewSubject(std::string(gjid), std::string(gsubject));
+ mir_free(es.ptszResult);
+ }
+}
+
+void WhatsAppProto::InviteChatUser(WAChatInfo *pInfo)
+{
+ if (TRUE != DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_GROUPCHAT_INVITE), NULL, InviteDialogProc, (LPARAM)this))
+ return;
+
+ if (isOnline()) {
+ m_pConnection->sendAddParticipants((char*)_T2A(pInfo->tszJid), m_szInviteJids);
+ m_szInviteJids.clear();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// nicklist menu event handler
+
+static gc_item sttListItems[] =
+{
+ { LPGENT("&Add to roster"), IDM_ADD_RJID, MENU_POPUPITEM },
+ { NULL, 0, MENU_SEPARATOR },
+ { LPGENT("&Kick"), IDM_KICK, MENU_ITEM },
+ { NULL, 0, MENU_SEPARATOR },
+ { LPGENT("Copy &nickname"), IDM_CPY_NICK, MENU_ITEM },
+ { LPGENT("Copy real &JID"), IDM_CPY_RJID, MENU_ITEM },
+};
+
+void WhatsAppProto::NickListMenuHook(WAChatInfo *pInfo, struct GCHOOK *gch)
+{
+ switch (gch->dwData) {
+ case IDM_ADD_RJID:
+ AddChatUser(pInfo, gch->ptszUID);
+ break;
+
+ case IDM_KICK:
+ KickChatUser(pInfo, gch->ptszUID);
+ break;
+
+ case IDM_CPY_NICK:
+ utils::copyText(pcli->hwndContactList, GetChatUserNick(std::string((char*)_T2A(gch->ptszUID))));
+ break;
+
+ case IDM_CPY_RJID:
+ utils::copyText(pcli->hwndContactList, gch->ptszUID);
+ break;
+ }
+}
+
+void WhatsAppProto::AddChatUser(WAChatInfo *pInfo, const TCHAR *ptszJid)
+{
+ std::string jid((char*)_T2A(ptszJid));
+ MCONTACT hContact = ContactIDToHContact(jid);
+ if (hContact && !db_get_b(hContact, "CList", "NotInList", 0))
+ return;
+
+ PROTOSEARCHRESULT sr = { 0 };
+ sr.cbSize = sizeof(sr);
+ sr.flags = PSR_TCHAR;
+ sr.id = (TCHAR*)ptszJid;
+ sr.nick = GetChatUserNick(jid);
+
+ ADDCONTACTSTRUCT acs = { 0 };
+ acs.handleType = HANDLE_SEARCHRESULT;
+ acs.szProto = m_szModuleName;
+ acs.psr = (PROTOSEARCHRESULT*)&sr;
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM)CallService(MS_CLUI_GETHWND, 0, 0), (LPARAM)&acs);
+}
+
+void WhatsAppProto::KickChatUser(WAChatInfo *pInfo, const TCHAR *ptszJid)
+{
+ if (!isOnline())
+ return;
+
+ std::string gjid((char*)_T2A(pInfo->tszJid));
+ std::vector<std::string> jids(1);
+ jids[0] = (char*)_T2A(ptszJid);
+ m_pConnection->sendRemoveParticipants(gjid, jids);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// handler to customize chat menus
+
+int WhatsAppProto::OnChatMenu(WPARAM wParam, LPARAM lParam)
+{
+ GCMENUITEMS *gcmi = (GCMENUITEMS*)lParam;
+ if (gcmi == NULL)
+ return 0;
+
+ if (mir_strcmpi(gcmi->pszModule, m_szModuleName))
+ return 0;
+
+ if (gcmi->Type == MENU_ON_LOG) {
+ gcmi->nItems = SIZEOF(sttLogListItems);
+ gcmi->Item = sttLogListItems;
+ }
+ else if (gcmi->Type == MENU_ON_NICKLIST) {
+ gcmi->nItems = SIZEOF(sttListItems);
+ gcmi->Item = sttListItems;
}
return 0;
}
+
+///////////////////////////////////////////////////////////////////////////////
+// chat helpers
+
+WAChatInfo* WhatsAppProto::InitChat(const std::string &jid, const std::string &nick)
+{
+ TCHAR *ptszJid = str2t(jid), *ptszNick = str2t(nick);
+
+ WAChatInfo *pInfo = new WAChatInfo(ptszJid, ptszNick);
+ m_chats[jid] = pInfo;
+
+ GCSESSION gcw = { sizeof(GCSESSION) };
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszModule = m_szModuleName;
+ gcw.ptszName = ptszNick;
+ gcw.ptszID = ptszJid;
+ CallServiceSync(MS_GC_NEWSESSION, NULL, (LPARAM)&gcw);
+
+ pInfo->hContact = ContactIDToHContact(jid);
+
+ GCDEST gcd = { m_szModuleName, ptszJid, GC_EVENT_ADDGROUP };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ for (int i = SIZEOF(sttStatuses) - 1; i >= 0; i--) {
+ gce.ptszStatus = TranslateTS(sttStatuses[i]);
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+ }
+
+ gcd.iType = GC_EVENT_CONTROL;
+ CallServiceSync(MS_GC_EVENT, (m_pConnection) ? WINDOW_HIDDEN : SESSION_INITDONE, (LPARAM)&gce);
+ CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
+
+ if (m_pConnection)
+ m_pConnection->sendGetParticipants(jid);
+
+ return pInfo;
+}
+
+TCHAR* WhatsAppProto::GetChatUserNick(const std::string &jid)
+{
+ if (m_szJid == jid)
+ return str2t(m_szNick);
+
+ MCONTACT hContact = ContactIDToHContact(jid);
+ return (hContact == 0) ? utils::removeA(str2t(jid)) : mir_tstrdup(pcli->pfnGetContactDisplayName(hContact, 0));
+}
+
+WAChatInfo* WhatsAppProto::SafeGetChat(const std::string &jid)
+{
+ mir_cslock lck(m_csChats);
+ return m_chats[jid];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WAGroupListener members
+
+void WhatsAppProto::onGroupInfo(const std::string &jid, const std::string &owner, const std::string &subject, const std::string &subject_owner, int time_subject, int time_created)
+{
+ WAChatInfo *pInfo = SafeGetChat(jid);
+ if (pInfo == NULL) {
+ pInfo = InitChat(jid, subject);
+ pInfo->bActive = true;
+ }
+
+ if (!subject.empty()) {
+ pInfo->tszOwner = str2t(owner);
+
+ onGroupNewSubject(jid, subject_owner, subject, time_subject);
+ }
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_CONTROL };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
+}
+
+void WhatsAppProto::onGroupMessage(const FMessage &msg)
+{
+ WAChatInfo *pInfo = SafeGetChat(msg.key.remote_jid);
+ if (pInfo == NULL) {
+ pInfo = InitChat(msg.key.remote_jid, "");
+ pInfo->bActive = true;
+ }
+
+ ptrT tszText(str2t(msg.data));
+ ptrT tszUID(str2t(msg.remote_resource));
+ ptrT tszNick(GetChatUserNick(msg.remote_resource));
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_MESSAGE };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszUID = tszUID;
+ gce.ptszNick = tszNick;
+ gce.time = msg.timestamp;
+ gce.ptszText = tszText;
+ gce.bIsMe = m_szJid == msg.remote_resource;
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+
+ if (isOnline())
+ m_pConnection->sendMessageReceived(msg);
+}
+
+void WhatsAppProto::onGroupNewSubject(const std::string &gjid, const std::string &author, const std::string &newSubject, int ts)
+{
+ WAChatInfo *pInfo = SafeGetChat(gjid);
+ if (pInfo == NULL)
+ return;
+
+ ptrT tszUID(str2t(author));
+ ptrT tszNick(GetChatUserNick(author));
+ ptrT tszText(str2t(newSubject));
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_TOPIC };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszUID = tszUID;
+ gce.ptszNick = tszNick;
+ gce.time = ts;
+ gce.ptszText = tszText;
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+
+ setTString(pInfo->hContact, "Nick", tszText);
+}
+
+void WhatsAppProto::onGroupAddUser(const std::string &gjid, const std::string &ujid, int ts)
+{
+ WAChatInfo *pInfo = SafeGetChat(gjid);
+ if (pInfo == NULL)
+ return;
+
+ ptrT tszUID(str2t(ujid));
+ ptrT tszNick(GetChatUserNick(ujid));
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_JOIN };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszUID = tszUID;
+ gce.ptszNick = tszNick;
+ gce.time = ts;
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+}
+
+void WhatsAppProto::onGroupRemoveUser(const std::string &gjid, const std::string &ujid, int ts)
+{
+ WAChatInfo *pInfo = SafeGetChat(gjid);
+ if (pInfo == NULL)
+ return;
+
+ ptrT tszUID(str2t(ujid));
+ ptrT tszNick(GetChatUserNick(ujid));
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_PART };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszUID = tszUID;
+ gce.ptszNick = tszNick;
+ gce.time = ts;
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+}
+
+void WhatsAppProto::onLeaveGroup(const std::string &gjid)
+{
+ WAChatInfo *pInfo = SafeGetChat(gjid);
+ if (pInfo == NULL)
+ return;
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_CONTROL };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.ptszUID = pInfo->tszJid;
+ CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
+
+ CallService(MS_DB_CONTACT_DELETE, pInfo->hContact, 0);
+ m_chats.erase((char*)_T2A(pInfo->tszJid));
+}
+
+void WhatsAppProto::onGetParticipants(const std::string &gjid, const std::vector<string> &participants)
+{
+ mir_cslock lck(m_csChats);
+
+ WAChatInfo *pInfo = m_chats[gjid];
+ if (pInfo == NULL)
+ return;
+
+ for (size_t i = 0; i < participants.size(); i++) {
+ std::string curr = participants[i];
+
+ ptrT ujid(str2t(curr)), nick(GetChatUserNick(curr));
+ bool bIsOwner = !mir_tstrcmp(ujid, pInfo->tszOwner);
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_JOIN };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.ptszNick = nick;
+ gce.ptszUID = utils::removeA(ujid);
+ gce.ptszStatus = (bIsOwner) ? _T("Owners") : _T("Members");
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+ }
+}
+
+void WhatsAppProto::onGroupCreated(const std::string &gjid, const std::string &subject)
+{
+ WAChatInfo *pInfo = InitChat(gjid, subject);
+ pInfo->tszOwner = str2t(m_szJid);
+
+ // also set new subject if it's present
+ if (!subject.empty())
+ onGroupNewSubject(gjid, "Server", subject, time(0));
+}
+
+void WhatsAppProto::onGroupMessageReceived(const FMessage &msg)
+{
+ WAChatInfo *pInfo = SafeGetChat(msg.key.remote_jid);
+ if (pInfo == NULL)
+ return;
+
+ auto p = pInfo->m_unsentMsgs.find(msg.key.id);
+ if (p == pInfo->m_unsentMsgs.end())
+ return;
+
+ ptrT tszUID(str2t(m_szJid));
+ ptrT tszNick(str2t(m_szNick));
+
+ GCDEST gcd = { m_szModuleName, pInfo->tszJid, GC_EVENT_MESSAGE };
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszUID = tszUID;
+ gce.ptszNick = tszNick;
+ gce.time = msg.timestamp;
+ gce.ptszText = p->second.c_str();
+ gce.bIsMe = m_szJid == msg.remote_resource;
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+
+ pInfo->m_unsentMsgs.erase(p);
+}
diff --git a/protocols/WhatsApp/src/common.h b/protocols/WhatsApp/src/common.h index 41a9dc1866..338b4578ca 100644 --- a/protocols/WhatsApp/src/common.h +++ b/protocols/WhatsApp/src/common.h @@ -70,10 +70,6 @@ Copyright © 2013-14 Uli Hecht #include <m_folders.h>
#include <m_json.h>
-#include "WhatsAPI++/WAConnection.h"
-
-class WhatsAppProto;
-
#include "constants.h"
#include "utils.h"
#include "db.h"
diff --git a/protocols/WhatsApp/src/connection.cpp b/protocols/WhatsApp/src/connection.cpp index c0710e626e..5ad51e788c 100644 --- a/protocols/WhatsApp/src/connection.cpp +++ b/protocols/WhatsApp/src/connection.cpp @@ -134,7 +134,7 @@ void WhatsAppProto::sentinelLoop(void*) debugLogA("Exiting sentinel loop");
}
-void WhatsAppProto::onPing(const std::string& id)
+void WhatsAppProto::onPing(const std::string &id)
{
if (isOnline()) {
try {
diff --git a/protocols/WhatsApp/src/contacts.cpp b/protocols/WhatsApp/src/contacts.cpp index f3c93204e6..e1a3a33bf1 100644 --- a/protocols/WhatsApp/src/contacts.cpp +++ b/protocols/WhatsApp/src/contacts.cpp @@ -1,55 +1,39 @@ #include "common.h"
-bool WhatsAppProto::IsMyContact(MCONTACT hContact, bool include_chat)
-{
- const char *proto = GetContactProto(hContact);
- if (proto && strcmp(m_szModuleName, proto) == 0) {
- if (include_chat)
- return true;
-
- return !isChatRoom(hContact);
- }
-
- return false;
-}
-
-MCONTACT WhatsAppProto::AddToContactList(const std::string& jid, BYTE , bool dont_check, const char *new_name, bool isChatRoom, bool isHidden)
+MCONTACT WhatsAppProto::AddToContactList(const std::string &jid, const char *new_name)
{
if (jid == m_szJid)
return NULL;
- if (!dont_check) {
- // First, check if this contact exists
- MCONTACT hContact = ContactIDToHContact(jid);
- if (hContact) {
- if (new_name != NULL) {
- DBVARIANT dbv;
- string oldName;
- if (db_get_utf(hContact, m_szModuleName, WHATSAPP_KEY_NICK, &dbv))
- oldName = jid.c_str();
- else {
- oldName = dbv.pszVal;
- db_free(&dbv);
- }
-
- if (oldName.compare(string(new_name)) != 0) {
- db_set_utf(hContact, m_szModuleName, WHATSAPP_KEY_NICK, new_name);
-
- CMString tmp(FORMAT, TranslateT("is now known as '%s'"), ptrT(mir_utf8decodeT(new_name)));
- this->NotifyEvent(_A2T(oldName.c_str()), tmp, hContact, WHATSAPP_EVENT_OTHER);
- }
+ // First, check if this contact exists
+ MCONTACT hContact = ContactIDToHContact(jid);
+ if (hContact) {
+ if (new_name != NULL) {
+ DBVARIANT dbv;
+ string oldName;
+ if (db_get_utf(hContact, m_szModuleName, WHATSAPP_KEY_NICK, &dbv))
+ oldName = jid.c_str();
+ else {
+ oldName = dbv.pszVal;
+ db_free(&dbv);
}
- if (db_get_b(hContact, "CList", "Hidden", 0) > 0)
- db_unset(hContact, "CList", "Hidden");
+ if (oldName.compare(string(new_name)) != 0) {
+ db_set_utf(hContact, m_szModuleName, WHATSAPP_KEY_NICK, new_name);
- return hContact;
+ CMString tmp(FORMAT, TranslateT("is now known as '%s'"), ptrT(mir_utf8decodeT(new_name)));
+ this->NotifyEvent(_A2T(oldName.c_str()), tmp, hContact, WHATSAPP_EVENT_OTHER);
+ }
}
+
+ if (db_get_b(hContact, "CList", "Hidden", 0) > 0)
+ db_unset(hContact, "CList", "Hidden");
+
+ return hContact;
}
// If not, make a new contact!
- MCONTACT hContact = CallService(MS_DB_CONTACT_ADD, 0, 0);
- if (hContact == 0)
+ if ((hContact = CallService(MS_DB_CONTACT_ADD, 0, 0)) == 0)
return INVALID_CONTACT_ID;
CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)m_szModuleName);
@@ -66,13 +50,10 @@ MCONTACT WhatsAppProto::AddToContactList(const std::string& jid, BYTE , bool don if (new_name != NULL)
db_set_utf(hContact, m_szModuleName, WHATSAPP_KEY_NICK, new_name);
- if (isChatRoom)
- setByte(hContact, "SimpleChatRoom", 1);
-
return hContact;
}
-MCONTACT WhatsAppProto::ContactIDToHContact(const std::string& phoneNumber)
+MCONTACT WhatsAppProto::ContactIDToHContact(const std::string &phoneNumber)
{
// Cache
std::map<string, MCONTACT>::iterator it = this->hContactByJid.find(phoneNumber);
@@ -132,10 +113,7 @@ void WhatsAppProto::ProcessBuddyList(void*) ptrA jid(getStringA(hContact, WHATSAPP_KEY_ID));
if (jid) {
try {
- if (getByte(hContact, "SimpleChatRoom", 0) == 0) {
- m_pConnection->sendQueryLastOnline((char*)jid);
- m_pConnection->sendPresenceSubscriptionRequest((char*)jid);
- }
+ m_pConnection->sendQueryLastOnline(std::string(jid));
}
CODE_BLOCK_CATCH_ALL
}
@@ -143,14 +121,13 @@ void WhatsAppProto::ProcessBuddyList(void*) try {
m_pConnection->sendGetGroups();
- m_pConnection->sendGetOwningGroups();
}
CODE_BLOCK_CATCH_ALL
}
-void WhatsAppProto::onAvailable(const std::string& paramString, bool paramBoolean)
+void WhatsAppProto::onAvailable(const std::string ¶mString, bool paramBoolean)
{
- MCONTACT hContact = this->AddToContactList(paramString, 0, false);
+ MCONTACT hContact = this->AddToContactList(paramString);
if (hContact != NULL) {
if (paramBoolean)
setWord(hContact, "Status", ID_STATUS_ONLINE);
@@ -164,9 +141,9 @@ void WhatsAppProto::onAvailable(const std::string& paramString, bool paramBoolea this->UpdateStatusMsg(hContact);
}
-void WhatsAppProto::onLastSeen(const std::string& paramString1, int paramInt, const string ¶mString2)
+void WhatsAppProto::onLastSeen(const std::string ¶mString1, int paramInt, const string ¶mString2)
{
- MCONTACT hContact = this->AddToContactList(paramString1, 0, false);
+ MCONTACT hContact = this->AddToContactList(paramString1);
setDword(hContact, WHATSAPP_KEY_LAST_SEEN, paramInt);
this->UpdateStatusMsg(hContact);
@@ -187,16 +164,17 @@ void WhatsAppProto::UpdateStatusMsg(MCONTACT hContact) db_set_ws(hContact, "CList", "StatusMsg", ss.str().c_str());
}
-void WhatsAppProto::onPictureChanged(const std::string& from, const std::string& author, bool set)
+void WhatsAppProto::onContactChanged(const std::string &jid, bool added)
{
- if (this->isOnline()) {
- vector<string> ids;
- ids.push_back(from);
- m_pConnection->sendGetPicture(from, "image");
- }
}
-void WhatsAppProto::onSendGetPicture(const std::string& jid, const std::vector<unsigned char>& data, const std::string& id)
+void WhatsAppProto::onPictureChanged(const std::string &jid, const std::string &id, bool set)
+{
+ if (isOnline())
+ m_pConnection->sendGetPicture(jid, "image");
+}
+
+void WhatsAppProto::onSendGetPicture(const std::string &jid, const std::vector<unsigned char>& data, const std::string &id)
{
MCONTACT hContact = this->ContactIDToHContact(jid);
if (hContact) {
@@ -230,299 +208,3 @@ TCHAR* WhatsAppProto::GetContactDisplayName(const string& jid) MCONTACT hContact = this->ContactIDToHContact(jid);
return (hContact) ? pcli->pfnGetContactDisplayName(hContact, 0) : _T("none");
}
-
-// Group contacts --------------------------
-
-void WhatsAppProto::SendGetGroupInfoWorker(void* data)
-{
- if (this->isOnline())
- m_pConnection->sendGetGroupInfo(*((std::string*) data));
-}
-
-void WhatsAppProto::onGroupInfo(const std::string& gjid, const std::string& ownerJid, const std::string& subject, const std::string& createrJid, int paramInt1, int paramInt2)
-{
- debugLogA("'%s', '%s', '%s', '%s'", gjid.c_str(), ownerJid.c_str(), subject.c_str(), createrJid.c_str());
- MCONTACT hContact = ContactIDToHContact(gjid);
- if (!hContact) {
- debugLogA("Group info requested for non existing contact '%s'", gjid.c_str());
- return;
- }
- setByte(hContact, "SimpleChatRoom", ownerJid.compare(m_szJid) == 0 ? 2 : 1);
- if (this->isOnline())
- m_pConnection->sendGetParticipants(gjid);
-}
-
-void WhatsAppProto::onGroupInfoFromList(const std::string& paramString1, const std::string& paramString2, const std::string& paramString3, const std::string& paramString4, int paramInt1, int paramInt2)
-{
- // Called before onOwningGroups() or onParticipatingGroups() is called!
-}
-
-void WhatsAppProto::onGroupNewSubject(const std::string& from, const std::string& author, const std::string& newSubject, int paramInt)
-{
- debugLogA("'%s', '%s', '%s'", from.c_str(), author.c_str(), newSubject.c_str());
- MCONTACT hContact = this->AddToContactList(from, 0, false, newSubject.c_str(), true);
-}
-
-void WhatsAppProto::onGroupAddUser(const std::string& paramString1, const std::string& paramString2)
-{
- debugLogA("%s - user: %s", paramString1.c_str(), paramString2.c_str());
- MCONTACT hContact = this->AddToContactList(paramString1);
- TCHAR *ptszGroupName = pcli->pfnGetContactDisplayName(hContact, 0);
-
- if (paramString2.compare(m_szJid) == 0) {
- this->NotifyEvent(ptszGroupName, TranslateT("You have been added to the group"), hContact, WHATSAPP_EVENT_OTHER);
- setByte(hContact, "IsGroupMember", 1);
- }
- else {
- CMString tmp(FORMAT, TranslateT("User '%s' has been added to the group"), this->GetContactDisplayName(paramString2));
- this->NotifyEvent(ptszGroupName, tmp, hContact, WHATSAPP_EVENT_OTHER);
- }
-
- if (this->isOnline())
- m_pConnection->sendGetGroupInfo(paramString1);
-}
-
-void WhatsAppProto::onGroupRemoveUser(const std::string ¶mString1, const std::string ¶mString2)
-{
- debugLogA("%s - user: %s", paramString1.c_str(), paramString2.c_str());
- MCONTACT hContact = this->ContactIDToHContact(paramString1);
- if (!hContact)
- return;
-
- TCHAR *ptszGroupName = pcli->pfnGetContactDisplayName(hContact, 0);
-
- if (paramString2.compare(m_szJid) == 0) {
- //db_set_b(hContact, "CList", "Hidden", 1);
- setByte(hContact, "IsGroupMember", 0);
-
- this->NotifyEvent(ptszGroupName, TranslateT("You have been removed from the group"), hContact, WHATSAPP_EVENT_OTHER);
- }
- else if (this->isOnline()) {
- CMString tmp(FORMAT, TranslateT("User '%s' has been removed from the group"), this->GetContactDisplayName(paramString2));
- this->NotifyEvent(ptszGroupName, tmp, hContact, WHATSAPP_EVENT_OTHER);
-
- m_pConnection->sendGetGroupInfo(paramString1);
- }
-}
-
-void WhatsAppProto::onLeaveGroup(const std::string ¶mString)
-{
- // Won't be called for unknown reasons!
- debugLogA("%s", this->GetContactDisplayName(paramString));
- MCONTACT hContact = this->ContactIDToHContact(paramString);
- if (hContact)
- setByte(hContact, "IsGroupMember", 0);
-}
-
-void WhatsAppProto::onGetParticipants(const std::string& gjid, const std::vector<string>& participants)
-{
- debugLogA("%s", this->GetContactDisplayName(gjid));
-
- MCONTACT hUserContact, hContact = this->ContactIDToHContact(gjid);
- if (!hContact)
- return;
-
- if (db_get_b(hContact, "CList", "Hidden", 0) == 1)
- return;
-
- bool isHidden = true;
- bool isOwningGroup = getByte(hContact, "SimpleChatRoom", 0) == 2;
-
- if (isOwningGroup)
- this->isMemberByGroupContact[hContact].clear();
-
- for (std::vector<string>::const_iterator it = participants.begin(); it != participants.end(); ++it) {
- // Hide, if we are not member of the group
- // Sometimes the group is shown shortly after hiding it again, due to other threads which stored the contact
- // in a cache before it has been removed (E.g. picture-id list in processBuddyList)
- if (isHidden && m_szJid.compare(*it) == 0) {
- isHidden = false;
- if (!isOwningGroup) {
- // Break, as we don't need to collect group-members
- break;
- }
- }
-
- // #TODO Slow for big count of participants
- // #TODO If a group is hidden it has been deleted from the local contact list
- // => don't allow to add users anymore
- if (isOwningGroup) {
- hUserContact = this->ContactIDToHContact(*it);
- if (hUserContact) {
- this->isMemberByGroupContact[hContact][hUserContact] = true;
- }
- }
- }
- if (isHidden) {
- //db_set_b(hContact, "CList", "Hidden", 1);
- // #TODO Check if it's possible to reach this point at all
- setByte(hContact, "IsGroupMember", 0);
- }
-}
-
-// Menu handler
-INT_PTR __cdecl WhatsAppProto::OnAddContactToGroup(WPARAM wParam, LPARAM, LPARAM lParam)
-{
- TCHAR *a = pcli->pfnGetContactDisplayName((MCONTACT)wParam, 0);
- TCHAR *b = pcli->pfnGetContactDisplayName((MCONTACT)lParam, 0);
- debugLogA("Request add user %S to group %S", a, b);
-
- if (!this->isOnline())
- return NULL;
-
- DBVARIANT dbv;
- if (getString((MCONTACT)wParam, "ID", &dbv))
- return NULL;
-
- std::vector<string> participants;
- participants.push_back(string(dbv.pszVal));
- db_free(&dbv);
-
- if (getString((MCONTACT)lParam, "ID", &dbv))
- return NULL;
-
- m_pConnection->sendAddParticipants(string(dbv.pszVal), participants);
-
- db_free(&dbv);
- return NULL;
-}
-
-// Menu handler
-INT_PTR __cdecl WhatsAppProto::OnRemoveContactFromGroup(WPARAM wParam, LPARAM, LPARAM lParam)
-{
- TCHAR *a = pcli->pfnGetContactDisplayName((MCONTACT)wParam, 0);
- TCHAR *b = pcli->pfnGetContactDisplayName((MCONTACT)lParam, 0);
- debugLogA("Request remove user %S from group %S", a, b);
-
- if (!this->isOnline())
- return NULL;
-
- DBVARIANT dbv;
- if (getString((MCONTACT)lParam, "ID", &dbv))
- return NULL;
-
- std::vector<string> participants;
- participants.push_back(string(dbv.pszVal));
- db_free(&dbv);
-
- if (getString((MCONTACT)wParam, "ID", &dbv))
- return NULL;
-
- m_pConnection->sendRemoveParticipants(string(dbv.pszVal), participants);
-
- db_free(&dbv);
- return NULL;
-}
-
-void WhatsAppProto::onOwningGroups(const std::vector<string>& paramVector)
-{
- this->HandleReceiveGroups(paramVector, true);
-}
-
-void WhatsAppProto::onParticipatingGroups(const std::vector<string>& paramVector)
-{
- this->HandleReceiveGroups(paramVector, false);
-}
-
-void WhatsAppProto::HandleReceiveGroups(const std::vector<string>& groups, bool isOwned)
-{
- MCONTACT hContact;
- map<MCONTACT, bool> isMember; // at the moment, only members of owning groups are stored
-
- // This could take long time if there are many new groups which aren't
- // yet stored to the database. But that should be a rare case
- for (std::vector<string>::const_iterator it = groups.begin(); it != groups.end(); ++it) {
- hContact = this->AddToContactList(*it, 0, false, NULL, true);
- setByte(hContact, "IsGroupMember", 1);
- if (isOwned) {
- this->isMemberByGroupContact[hContact]; // []-operator creates entry, if it doesn't exist
- setByte(hContact, "SimpleChatRoom", 2);
- m_pConnection->sendGetParticipants(*it);
- }
- else isMember[hContact] = true;
- }
-
- // Mark as non-meber if group only exists locally
- if (!isOwned)
- for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName))
- if (!isChatRoom(hContact) && getByte(hContact, "SimpleChatRoom", 0) > 0)
- setByte(hContact, "IsGroupMember", isMember.find(hContact) == isMember.end() ? 0 : 1);
-}
-
-void WhatsAppProto::onGroupCreated(const std::string& paramString1, const std::string& paramString2)
-{
- // Must be received after onOwningGroups() :/
- debugLogA("%s / %s", paramString1.c_str(), paramString2.c_str());
- string jid = paramString2 + string("@") + paramString1;
- MCONTACT hContact = this->AddToContactList(jid, 0, false, NULL, true);
- setByte(hContact, "SimpleChatRoom", 2);
-}
-
-// Menu-handler
-INT_PTR __cdecl WhatsAppProto::OnCreateGroup(WPARAM wParam, LPARAM lParam)
-{
- input_box* ib = new input_box;
- ib->defaultValue = _T("");
- ib->limit = WHATSAPP_GROUP_NAME_LIMIT;
- ib->proto = this;
- ib->text = _T("Enter group subject");
- ib->title = _T("WhatsApp - Create Group");
- ib->thread = &WhatsAppProto::SendCreateGroupWorker;
- HWND hDlg = CreateDialogParam(g_hInstance, MAKEINTRESOURCE(IDD_INPUTBOX), 0, WhatsAppInputBoxProc, LPARAM(ib));
- ShowWindow(hDlg, SW_SHOW);
- return FALSE;
-}
-
-void __cdecl WhatsAppProto::SendSetGroupNameWorker(void* data)
-{
- input_box_ret* ibr(static_cast<input_box_ret*>(data));
- string groupName(ibr->value);
- mir_free(ibr->value);
-
- ptrA jid(getStringA(*((MCONTACT*)ibr->userData), WHATSAPP_KEY_ID));
- if (jid && this->isOnline())
- m_pConnection->sendSetNewSubject((char*)jid, groupName);
-
- delete ibr->userData;
- delete ibr;
-}
-
-void __cdecl WhatsAppProto::SendCreateGroupWorker(void* data)
-{
- input_box_ret* ibr(static_cast<input_box_ret*>(data));
- string groupName(ibr->value);
- mir_free(ibr->value);
- if (this->isOnline())
- m_pConnection->sendCreateGroupChat(groupName);
-}
-
-INT_PTR __cdecl WhatsAppProto::OnChangeGroupSubject(WPARAM hContact, LPARAM lParam)
-{
- input_box* ib = new input_box;
-
- ptrT szNick(getTStringA(hContact, WHATSAPP_KEY_NICK));
- if (szNick != NULL)
- ib->defaultValue = szNick;
-
- ib->limit = WHATSAPP_GROUP_NAME_LIMIT;
- ib->text = _T("Enter new group subject");
- ib->title = _T("WhatsApp - Change Group Subject");
- ib->thread = &WhatsAppProto::SendSetGroupNameWorker;
- ib->proto = this;
- MCONTACT *hContactPtr = new MCONTACT(hContact);
- ib->userData = (void*)hContactPtr;
-
- HWND hDlg = CreateDialogParam(g_hInstance, MAKEINTRESOURCE(IDD_INPUTBOX), 0, WhatsAppInputBoxProc, LPARAM(ib));
- ShowWindow(hDlg, SW_SHOW);
- return 0;
-}
-
-INT_PTR __cdecl WhatsAppProto::OnLeaveGroup(WPARAM hContact, LPARAM)
-{
- ptrA jid(getStringA(hContact, WHATSAPP_KEY_ID));
- if (jid && this->isOnline()) {
- setByte(hContact, "IsGroupMember", 0);
- m_pConnection->sendLeaveGroup((char*)jid);
- }
- return 0;
-}
diff --git a/protocols/WhatsApp/src/dialogs.cpp b/protocols/WhatsApp/src/dialogs.cpp index 0550dc4102..0d93fd2afd 100644 --- a/protocols/WhatsApp/src/dialogs.cpp +++ b/protocols/WhatsApp/src/dialogs.cpp @@ -3,16 +3,16 @@ #define szAskSendSms LPGEN("An SMS with registration code will be sent to your mobile phone.\nNotice that you are not able to use the real WhatsApp and this plugin simultaneously!\nContinue?")
#define szPasswordSet LPGEN("Your password has been set automatically. You can proceed with login now")
-INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT message, WPARAM wparam, LPARAM lparam)
+INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- WhatsAppProto *proto;
+ WhatsAppProto *proto = (WhatsAppProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- switch (message) {
+ switch (uMsg) {
case WM_INITDIALOG:
TranslateDialogDefault(hwndDlg);
- proto = reinterpret_cast<WhatsAppProto*>(lparam);
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lparam);
+ proto = (WhatsAppProto*)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
SendDlgItemMessage(hwndDlg, IDC_PW, EM_LIMITTEXT, 3, 0);
SendDlgItemMessage(hwndDlg, IDC_PW2, EM_LIMITTEXT, 3, 0);
CheckDlgButton(hwndDlg, IDC_SSL, db_get_b(NULL, proto->m_szModuleName, WHATSAPP_KEY_SSL, 0) ? BST_CHECKED : BST_UNCHECKED);
@@ -42,16 +42,14 @@ INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT message, WPARAM wparam, return TRUE;
case WM_COMMAND:
- if (LOWORD(wparam) == IDC_BUTTON_REQUEST_CODE || LOWORD(wparam) == IDC_BUTTON_REGISTER) {
- proto = reinterpret_cast<WhatsAppProto*>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
-
+ if (LOWORD(wParam) == IDC_BUTTON_REQUEST_CODE || LOWORD(wParam) == IDC_BUTTON_REGISTER) {
string password;
char cc[5];
char number[128];
GetDlgItemTextA(hwndDlg, IDC_CC, cc, SIZEOF(cc));
GetDlgItemTextA(hwndDlg, IDC_LOGIN, number, SIZEOF(number));
- if (LOWORD(wparam) == IDC_BUTTON_REQUEST_CODE) {
+ if (LOWORD(wParam) == IDC_BUTTON_REQUEST_CODE) {
if (IDYES == MessageBox(NULL, TranslateT(szAskSendSms), PRODUCT_NAME, MB_YESNO)) {
if (proto->Register(REG_STATE_REQ_CODE, string(cc), string(number), string(), password)) {
if (!password.empty()) {
@@ -65,7 +63,7 @@ INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT message, WPARAM wparam, }
}
}
- else if (LOWORD(wparam) == IDC_BUTTON_REGISTER) {
+ else if (LOWORD(wParam) == IDC_BUTTON_REGISTER) {
HWND hwnd1 = GetDlgItem(hwndDlg, IDC_PW), hwnd2 = GetDlgItem(hwndDlg, IDC_PW2);
if (GetWindowTextLength(hwnd1) != 3 || GetWindowTextLength(hwnd2) != 3) {
MessageBox(NULL, TranslateT("Please correctly specify your registration code received by SMS"), PRODUCT_NAME, MB_ICONEXCLAMATION);
@@ -83,8 +81,8 @@ INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT message, WPARAM wparam, }
}
- if (HIWORD(wparam) == EN_CHANGE && reinterpret_cast<HWND>(lparam) == GetFocus()) {
- switch (LOWORD(wparam)) {
+ if (HIWORD(wParam) == EN_CHANGE && reinterpret_cast<HWND>(lParam) == GetFocus()) {
+ switch (LOWORD(wParam)) {
case IDC_CC:
case IDC_LOGIN:
case IDC_NICK:
@@ -97,8 +95,7 @@ INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT message, WPARAM wparam, break;
case WM_NOTIFY:
- if (reinterpret_cast<NMHDR *>(lparam)->code == PSN_APPLY) {
- proto = reinterpret_cast<WhatsAppProto *>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+ if (reinterpret_cast<NMHDR *>(lParam)->code == PSN_APPLY) {
char str[128];
GetDlgItemTextA(hwndDlg, IDC_CC, str, SIZEOF(str));
@@ -114,68 +111,88 @@ INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT message, WPARAM wparam, return TRUE;
}
break;
-
}
return FALSE;
}
-INT_PTR CALLBACK WhatsAppInputBoxProc(HWND hwndDlg, UINT message, WPARAM wparam, LPARAM lparam)
+/////////////////////////////////////////////////////////////////////////////////////////
+// Invite dialog
+
+static void InitList(HWND hwndClist, WhatsAppProto *ppro)
+{
+ SetWindowLongPtr(hwndClist, GWL_STYLE,
+ GetWindowLongPtr(hwndClist, GWL_STYLE) | CLS_CHECKBOXES | CLS_HIDEEMPTYGROUPS | CLS_USEGROUPS | CLS_GREYALTERNATE);
+ SendMessage(hwndClist, CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP | CLS_EX_TRACKSELECT, 0);
+ SendMessage(hwndClist, CLM_SETBKBITMAP, 0, 0);
+ SendMessage(hwndClist, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(hwndClist, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(hwndClist, CLM_SETLEFTMARGIN, 4, 0);
+ SendMessage(hwndClist, CLM_SETINDENT, 10, 0);
+ SendMessage(hwndClist, CLM_SETBKBITMAP, 0, 0);
+ SendMessage(hwndClist, CLM_SETHIDEEMPTYGROUPS, TRUE, 0);
+ SendMessage(hwndClist, CLM_SETHIDEOFFLINEROOT, TRUE, 0);
+
+ for (int i = 0; i <= FONTID_MAX; i++)
+ SendMessage(hwndClist, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+
+ for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
+ char *proto = GetContactProto(hContact);
+ if (mir_strcmp(proto, ppro->m_szModuleName) || ppro->isChatRoom(hContact))
+ if (MCONTACT hItem = SendMessage(hwndClist, CLM_FINDCONTACT, hContact, 0))
+ SendMessage(hwndClist, CLM_DELETEITEM, hItem, 0);
+ }
+}
+
+INT_PTR CALLBACK InviteDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- input_box* ib;
+ WhatsAppProto *proto = (WhatsAppProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- switch (message) {
+ switch (uMsg) {
case WM_INITDIALOG:
TranslateDialogDefault(hwndDlg);
- ib = reinterpret_cast<input_box*>(lparam);
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lparam);
- SendDlgItemMessage(hwndDlg, IDC_VALUE, EM_LIMITTEXT, ib->limit, 0);
- SetDlgItemText(hwndDlg, IDC_VALUE, ib->defaultValue.c_str());
- SetDlgItemText(hwndDlg, IDC_TEXT, ib->text.c_str());
-
- SetWindowText(hwndDlg, ib->title.c_str());
-
- EnableWindow(GetDlgItem(hwndDlg, IDC_OK), FALSE);
- return TRUE;
+ proto = (WhatsAppProto*)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ InitList(GetDlgItem(hwndDlg, IDC_CLIST), proto);
+ return 1;
+
case WM_COMMAND:
- if (LOWORD(wparam) == IDC_VALUE && HIWORD(wparam) == EN_CHANGE) {
- ib = reinterpret_cast<input_box*>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
- size_t len = SendDlgItemMessage(hwndDlg, IDC_VALUE, WM_GETTEXTLENGTH, 0, 0);
- TCHAR str[4];
- mir_sntprintf(str, SIZEOF(str), TEXT("%d"), ib->limit - len);
- //SetDlgItemText(hwndDlg,IDC_CHARACTERS,str);
-
- EnableWindow(GetDlgItem(hwndDlg, IDC_OK), len > 0);
- return TRUE;
- }
-
- if (LOWORD(wparam) == IDC_OK) {
- ib = reinterpret_cast<input_box*>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
- TCHAR* value = new TCHAR[ib->limit + 1];
-
- GetDlgItemText(hwndDlg, IDC_VALUE, value, ib->limit + 1);
- ShowWindow(hwndDlg, SW_HIDE);
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case IDOK:
+ proto->m_szInviteJids.clear();
+
+ // invite users from clist
+ for (MCONTACT hContact = db_find_first(proto->m_szModuleName); hContact; hContact = db_find_next(hContact, proto->m_szModuleName)) {
+ if (proto->isChatRoom(hContact))
+ continue;
+
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_CLIST);
+ if (int hItem = SendMessage(hwndList, CLM_FINDCONTACT, hContact, 0)) {
+ if (SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hItem, 0)) {
+ ptrA jid(proto->getStringA(hContact, "ID"));
+ if (jid != NULL)
+ proto->m_szInviteJids.push_back((char*)jid);
+ }
+ }
+ }
- input_box_ret* ret = new input_box_ret;
- ret->userData = ib->userData;
- ret->value = mir_utf8encodeT(value);
- delete value;
- ib->proto->ForkThread(ib->thread, ret);
- EndDialog(hwndDlg, wparam);
- delete ib;
- return TRUE;
- }
+ HWND hwndEntry = GetDlgItem(hwndDlg, IDC_NEWJID);
+ int len = GetWindowTextLength(hwndEntry);
+ if (len > 0) {
+ std::string szOther; szOther.resize(len + 1);
+ GetWindowTextA(hwndEntry, (char*)szOther.data(), len);
+ proto->m_szInviteJids.push_back(szOther);
+ }
- if (LOWORD(wparam) == IDC_CANCEL) {
- EndDialog(hwndDlg, wparam);
- ib = reinterpret_cast<input_box*>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
- delete ib;
- return TRUE;
+ EndDialog(hwndDlg, 1);
}
- break;
}
- return FALSE;
-}
\ No newline at end of file + return 0;
+}
diff --git a/protocols/WhatsApp/src/dialogs.h b/protocols/WhatsApp/src/dialogs.h index 3284755496..f31cc322c6 100644 --- a/protocols/WhatsApp/src/dialogs.h +++ b/protocols/WhatsApp/src/dialogs.h @@ -1,7 +1,7 @@ #if !defined(DIALOGS_H)
#define DIALOGS_H
-INT_PTR CALLBACK WhatsAppAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-INT_PTR CALLBACK WhatsAppInputBoxProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
+INT_PTR CALLBACK InviteDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK WhatsAppAccountProc(HWND hwndDlg, UINT uMsg, WPARAM wparam, LPARAM lParam);
#endif
\ No newline at end of file diff --git a/protocols/WhatsApp/src/messages.cpp b/protocols/WhatsApp/src/messages.cpp index f1ad83d252..dd32451850 100644 --- a/protocols/WhatsApp/src/messages.cpp +++ b/protocols/WhatsApp/src/messages.cpp @@ -7,11 +7,11 @@ int WhatsAppProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) return Proto_RecvMessage(hContact, pre);
}
-void WhatsAppProto::onMessageForMe(FMessage *pMsg, bool paramBoolean)
+void WhatsAppProto::onMessageForMe(const FMessage &pMsg)
{
// someone sent us a contact. launch contact addition dialog
- if (pMsg->media_wa_type == FMessage::WA_TYPE_CONTACT) {
- MCONTACT hContact = AddToContactList(pMsg->remote_resource, 0, false, pMsg->media_name.c_str());
+ if (pMsg.media_wa_type == FMessage::WA_TYPE_CONTACT) {
+ MCONTACT hContact = AddToContactList(pMsg.remote_resource, pMsg.media_name.c_str());
ADDCONTACTSTRUCT acs = { 0 };
acs.handleType = HANDLE_CONTACT;
@@ -20,29 +20,24 @@ void WhatsAppProto::onMessageForMe(FMessage *pMsg, bool paramBoolean) CallServiceSync(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
}
else {
- bool isChatRoom = !pMsg->remote_resource.empty();
-
- std::string msg(pMsg->data);
- if (!pMsg->media_url.empty()) {
+ std::string msg(pMsg.data);
+ if (!pMsg.media_url.empty()) {
if (!msg.empty())
msg.append("\n");
- msg += pMsg->media_url;
+ msg += pMsg.media_url;
}
- if (isChatRoom)
- msg.insert(0, std::string("[").append(pMsg->notifyname).append("]: "));
-
- MCONTACT hContact = this->AddToContactList(pMsg->key.remote_jid, 0, false,
- isChatRoom ? NULL : pMsg->notifyname.c_str(), isChatRoom);
+ MCONTACT hContact = this->AddToContactList(pMsg.key.remote_jid, pMsg.notifyname.c_str());
PROTORECVEVENT recv = { 0 };
recv.flags = PREF_UTF;
recv.szMessage = const_cast<char*>(msg.c_str());
- recv.timestamp = pMsg->timestamp;
+ recv.timestamp = pMsg.timestamp;
ProtoChainRecvMsg(hContact, &recv);
}
- m_pConnection->sendMessageReceived(pMsg);
+ if (isOnline())
+ m_pConnection->sendMessageReceived(pMsg);
}
int WhatsAppProto::SendMsg(MCONTACT hContact, int flags, const char *msg)
@@ -56,11 +51,6 @@ int WhatsAppProto::SendMsg(MCONTACT hContact, int flags, const char *msg) return 0;
}
- if (getByte(hContact, "SimpleChatRoom", 0) > 0 && getByte(hContact, "IsGroupMember", 0) == 0) {
- debugLogA("not a group member");
- return 0;
- }
-
int msgId = GetSerial();
try {
time_t now = time(NULL);
@@ -84,9 +74,9 @@ int WhatsAppProto::SendMsg(MCONTACT hContact, int flags, const char *msg) return msgId;
}
-void WhatsAppProto::onIsTyping(const std::string& paramString, bool paramBoolean)
+void WhatsAppProto::onIsTyping(const std::string ¶mString, bool paramBoolean)
{
- MCONTACT hContact = this->AddToContactList(paramString, 0, false);
+ MCONTACT hContact = this->AddToContactList(paramString);
if (hContact != NULL) {
CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)
paramBoolean ? PROTOTYPE_CONTACTTYPING_INFINITE : PROTOTYPE_CONTACTTYPING_OFF);
@@ -108,28 +98,33 @@ int WhatsAppProto::UserIsTyping(MCONTACT hContact, int type) return 0;
}
-void WhatsAppProto::onMessageStatusUpdate(FMessage* fmsg)
+void WhatsAppProto::onMessageStatusUpdate(const FMessage &fmsg)
{
- MCONTACT hContact = this->ContactIDToHContact(fmsg->key.remote_jid);
+ MCONTACT hContact = this->ContactIDToHContact(fmsg.key.remote_jid);
if (hContact == 0)
return;
+ if (isChatRoom(hContact)) {
+ onGroupMessageReceived(fmsg);
+ return;
+ }
+
const TCHAR *ptszBy;
- switch (fmsg->status) {
+ switch (fmsg.status) {
case FMessage::STATUS_RECEIVED_BY_SERVER: ptszBy = TranslateT("server"); break;
case FMessage::STATUS_RECEIVED_BY_TARGET: ptszBy = pcli->pfnGetContactDisplayName(hContact, 0); break;
default:
return;
}
- size_t delim = fmsg->key.id.find('-');
+ size_t delim = fmsg.key.id.find('-');
if (delim == string::npos)
return;
- int msgId = atoi(fmsg->key.id.substr(delim+1).c_str());
+ int msgId = atoi(fmsg.key.id.substr(delim+1).c_str());
ProtoBroadcastAck(hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)msgId, 0);
- time_t timestamp = atol(fmsg->key.id.substr(0, delim).c_str());
+ time_t timestamp = atol(fmsg.key.id.substr(0, delim).c_str());
TCHAR ttime[64];
_tcsftime(ttime, SIZEOF(ttime), _T("%X"), localtime(×tamp));
diff --git a/protocols/WhatsApp/src/proto.cpp b/protocols/WhatsApp/src/proto.cpp index 42ec1990eb..ca412a77e8 100644 --- a/protocols/WhatsApp/src/proto.cpp +++ b/protocols/WhatsApp/src/proto.cpp @@ -17,9 +17,10 @@ WhatsAppProto::WhatsAppProto(const char* proto_name, const TCHAR* username) : {
update_loop_lock_ = CreateEvent(NULL, false, false, NULL);
+ db_set_resident(m_szModuleName, "Status");
+ db_set_resident(m_szModuleName, "StatusMsg");
+
CreateProtoService(PS_CREATEACCMGRUI, &WhatsAppProto::SvcCreateAccMgrUI);
- CreateProtoService(PS_JOINCHAT, &WhatsAppProto::OnJoinChat);
- CreateProtoService(PS_LEAVECHAT, &WhatsAppProto::OnLeaveChat);
CreateProtoService(PS_GETAVATARINFOT, &WhatsAppProto::GetAvatarInfo);
CreateProtoService(PS_GETAVATARCAPS, &WhatsAppProto::GetAvatarCaps);
@@ -27,11 +28,8 @@ WhatsAppProto::WhatsAppProto(const char* proto_name, const TCHAR* username) : CreateProtoService(PS_SETMYAVATART, &WhatsAppProto::SetMyAvatar);
HookProtoEvent(ME_OPT_INITIALISE, &WhatsAppProto::OnOptionsInit);
- HookProtoEvent(ME_SYSTEM_MODULESLOADED, &WhatsAppProto::OnModulesLoaded);
HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &WhatsAppProto::OnBuildStatusMenu);
- this->InitContactMenus();
-
// Create standard network connection
TCHAR descr[512];
mir_sntprintf(descr, SIZEOF(descr), TranslateT("%s server connection"), m_tszUserName);
@@ -59,16 +57,19 @@ WhatsAppProto::~WhatsAppProto() CloseHandle(update_loop_lock_);
}
-int WhatsAppProto::OnModulesLoaded(WPARAM wParam, LPARAM lParam)
+int WhatsAppProto::OnEvent(PROTOEVENTTYPE evType, WPARAM wParam, LPARAM lParam)
{
- // Register group chat
- GCREGISTER gcr = { sizeof(gcr) };
- gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR;
- gcr.ptszDispName = m_tszUserName;
- gcr.pszModule = m_szModuleName;
- CallServiceSync(MS_GC_REGISTER, 0, (LPARAM)&gcr);
-
- HookProtoEvent(ME_GC_EVENT, &WhatsAppProto::OnChatOutgoing);
+ if (evType == EV_PROTO_ONLOAD) {
+ // Register group chat
+ GCREGISTER gcr = { sizeof(gcr) };
+ gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR;
+ gcr.ptszDispName = m_tszUserName;
+ gcr.pszModule = m_szModuleName;
+ CallServiceSync(MS_GC_REGISTER, 0, (LPARAM)&gcr);
+
+ HookProtoEvent(ME_GC_EVENT, &WhatsAppProto::onGroupChatEvent);
+ HookProtoEvent(ME_GC_BUILDMENU, &WhatsAppProto::OnChatMenu);
+ }
return 0;
}
@@ -165,7 +166,7 @@ MCONTACT WhatsAppProto::AddToList(int flags, PROTOSEARCHRESULT* psr) std::string phone(ptrA(mir_utf8encodeT(psr->id)));
std::string jid(phone + "@s.whatsapp.net");
- MCONTACT hContact = AddToContactList(jid, 0, false, phone.c_str());
+ MCONTACT hContact = AddToContactList(jid, phone.c_str());
if (!(flags & PALF_TEMPORARY))
db_unset(hContact, "CList", "NotOnList");
diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h index b0c5c8a6bf..b07d8aed87 100644 --- a/protocols/WhatsApp/src/proto.h +++ b/protocols/WhatsApp/src/proto.h @@ -3,11 +3,28 @@ class WASocketConnection;
+#include "WhatsAPI++/WAConnection.h"
+
+struct WAChatInfo
+{
+ WAChatInfo(TCHAR *_jid, TCHAR *_nick) :
+ tszJid(_jid), tszNick(_nick)
+ {
+ bActive = false;
+ }
+
+ map<std::string, std::tstring> m_unsentMsgs;
+ ptrT tszJid, tszNick, tszOwner;
+ bool bActive;
+
+ MCONTACT hContact;
+};
+
class WhatsAppProto : public PROTO<WhatsAppProto>, public WAListener, public WAGroupListener
{
public:
WhatsAppProto(const char *proto_name, const TCHAR *username);
- ~WhatsAppProto( );
+ ~WhatsAppProto();
inline bool isOnline() const
{ return (m_pConnection != NULL);
@@ -21,20 +38,20 @@ public: { return (m_iStatus == ID_STATUS_INVISIBLE);
}
- // PROTO_INTERFACE
+ // PROTO_INTERFACE ///////////////////////////////////////////////////////////////////
- virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT* psr);
- virtual MCONTACT __cdecl AddToListByEvent(int flags, int iContact, MEVENT hDbEvent) { return NULL; }
+ virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT* psr);
+ virtual MCONTACT __cdecl AddToListByEvent(int flags, int iContact, MEVENT hDbEvent) { return NULL; }
- virtual int __cdecl Authorize(MEVENT hDbEvent);
- virtual int __cdecl AuthDeny(MEVENT hDbEvent, const PROTOCHAR* szReason) { return 1; }
- virtual int __cdecl AuthRecv(MCONTACT hContact, PROTORECVEVENT*) { return 1; }
- virtual int __cdecl AuthRequest(MCONTACT hContact, const PROTOCHAR* szMessage);
+ virtual int __cdecl Authorize(MEVENT hDbEvent);
+ virtual int __cdecl AuthDeny(MEVENT hDbEvent, const PROTOCHAR* szReason) { return 1; }
+ virtual int __cdecl AuthRecv(MCONTACT hContact, PROTORECVEVENT*) { return 1; }
+ virtual int __cdecl AuthRequest(MCONTACT hContact, const PROTOCHAR* szMessage);
- virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath) { return NULL; }
- virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer) { return 1; }
- virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason) { return 1; }
- virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename) { return 1; }
+ virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath) { return NULL; }
+ virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer) { return 1; }
+ virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason) { return 1; }
+ virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename) { return 1; }
virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL);
virtual int __cdecl GetInfo(MCONTACT hContact, int infoType) { return 1; }
@@ -65,86 +82,76 @@ public: virtual int __cdecl UserIsTyping(MCONTACT hContact, int type);
- virtual int __cdecl OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam) { return 1; }
+ virtual int __cdecl OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam);
- //////////////////////////////////////////////////////////////////////////////////////
- // Services
+ // Services //////////////////////////////////////////////////////////////////////////
INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM);
- INT_PTR __cdecl OnJoinChat(WPARAM, LPARAM);
- INT_PTR __cdecl OnLeaveChat(WPARAM, LPARAM);
- INT_PTR __cdecl OnCreateGroup(WPARAM, LPARAM);
- //////////////////////////////////////////////////////////////////////////////////////
- // Events
+ // Events ////////////////////////////////////////////////////////////////////////////
int __cdecl OnOptionsInit(WPARAM, LPARAM);
- int __cdecl OnModulesLoaded(WPARAM, LPARAM);
int __cdecl OnBuildStatusMenu(WPARAM, LPARAM);
- int __cdecl OnChatOutgoing(WPARAM, LPARAM);
- int __cdecl OnPrebuildContactMenu(WPARAM, LPARAM);
- INT_PTR __cdecl OnAddContactToGroup(WPARAM, LPARAM, LPARAM);
- INT_PTR __cdecl OnRemoveContactFromGroup(WPARAM, LPARAM, LPARAM);
- INT_PTR __cdecl OnChangeGroupSubject(WPARAM, LPARAM);
- INT_PTR __cdecl OnLeaveGroup(WPARAM, LPARAM);
+ // Worker Threads ////////////////////////////////////////////////////////////////////
- // Loops
- bool NegotiateConnection();
void __cdecl stayConnectedLoop(void*);
void __cdecl sentinelLoop(void*);
- //////////////////////////////////////////////////////////////////////////////////////
- // Processing Threads
+ // Processing Threads ////////////////////////////////////////////////////////////////
void __cdecl ProcessBuddyList(void*);
void __cdecl SearchAckThread(void*);
- //////////////////////////////////////////////////////////////////////////////////////
- // Worker Threads
-
- void __cdecl SendGetGroupInfoWorker(void*);
- void __cdecl SendSetGroupNameWorker(void*);
- void __cdecl SendCreateGroupWorker(void*);
+ // Contacts handling /////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////////
- // Contacts handling
+ MCONTACT AddToContactList(const std::string &jid, const char *new_name = NULL);
- 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);
void UpdateStatusMsg(MCONTACT hContact);
TCHAR* GetContactDisplayName(const string &jid);
- void InitContactMenus();
- void HandleReceiveGroups(const std::vector<string> &groups, bool isOwned);
void RequestFriendship(MCONTACT hContact);
- bool IsGroupChat(MCONTACT hC, bool checkIsAdmin = false)
- {
- return getByte(hC, "SimpleChatRoom", 0) > (checkIsAdmin ? 1 : 0);
- }
+ // Group chats ///////////////////////////////////////////////////////////////////////
+
+ std::vector<string> m_szInviteJids;
+ map<std::string, WAChatInfo*> m_chats;
+ mir_cs m_csChats;
+
+ void ChatLogMenuHook(WAChatInfo *pInfo, GCHOOK *gch);
+ void NickListMenuHook(WAChatInfo *pInfo, GCHOOK *gch);
+
+ void AddChatUser(WAChatInfo *pInfo, const TCHAR *ptszJid);
+ void EditChatSubject(WAChatInfo *pInfo);
+ void InviteChatUser(WAChatInfo *pInfo);
+ void KickChatUser(WAChatInfo *pInfo, const TCHAR *ptszJid);
+ TCHAR* GetChatUserNick(const std::string &jid);
+
+ void onGroupMessageReceived(const FMessage &fmsg);
- LONG GetSerial();
+ WAChatInfo* InitChat(const std::string &jidjid, const std::string &nick);
+ WAChatInfo* SafeGetChat(const std::string &jid);
- //////////////////////////////////////////////////////////////////////////////////////
- // Registration
+ int __cdecl onGroupChatEvent(WPARAM, LPARAM);
+ int __cdecl OnChatMenu(WPARAM, LPARAM);
+ INT_PTR __cdecl OnCreateGroup(WPARAM, LPARAM);
+
+ // Registration //////////////////////////////////////////////////////////////////////
bool Register(int state, const string &cc, const string &number, const string &code, string &password);
private:
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Helpers
+ // Helpers //////////////////////////////////////////////////////////////////////////
LONG m_iSerial;
+ __forceinline LONG GetSerial()
+ { return ::_InterlockedIncrement(&m_iSerial);
+ }
void ToggleStatusMenuItems(BOOL bEnable);
- //////////////////////////////////////////////////////////////////////////////////////
- // Avatars
+ /// Avatars //////////////////////////////////////////////////////////////////////////
std::tstring GetAvatarFileName(MCONTACT);
std::tstring m_tszAvatarFolder;
@@ -154,14 +161,11 @@ private: INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM);
INT_PTR __cdecl SetMyAvatar(WPARAM, LPARAM);
- //////////////////////////////////////////////////////////////////////////////////////
- // Handles, Locks
-
+ // Private data //////////////////////////////////////////////////////////////////////
+
HGENMENU m_hMenuRoot;
HANDLE m_hMenuCreateGroup;
- HANDLE signon_lock_;
- HANDLE log_lock_;
HANDLE update_loop_lock_;
WASocketConnection *conn;
@@ -170,18 +174,16 @@ private: time_t m_tLastWriteTime;
std::vector<unsigned char> m_Challenge;
- string m_szPhoneNumber;
- string m_szJid, m_szNick;
+ std::string m_szPhoneNumber;
+ std::string m_szJid, m_szNick;
std::map<string, MCONTACT> hContactByJid;
map<MCONTACT, map<MCONTACT, bool>> isMemberByGroupContact;
- //////////////////////////////////////////////////////////////////////////////////////
- // WhatsApp Events
-
protected:
- virtual void onMessageForMe(FMessage *paramFMessage, bool paramBoolean);
- virtual void onMessageStatusUpdate(FMessage *paramFMessage);
- virtual void onMessageError(FMessage *message, int paramInt) { ; }
+ // WAListener methods ////////////////////////////////////////////////////////////////
+ virtual void onMessageForMe(const FMessage ¶mFMessage);
+ virtual void onMessageStatusUpdate(const FMessage ¶mFMessage);
+ virtual void onMessageError(const FMessage &message, int paramInt) { ; }
virtual void onPing(const std::string &id) throw (WAException);
virtual void onPingResponseReceived() { }
virtual void onAvailable(const std::string ¶mString, bool paramBoolean);
@@ -195,29 +197,28 @@ protected: virtual void onDirtyResponse(int paramHashtable) { }
virtual void onRelayRequest(const std::string ¶mString1, int paramInt, const std::string ¶mString2) { }
virtual void onSendGetPicture(const std::string &jid, const std::vector<unsigned char>& data, const std::string &id);
- virtual void onPictureChanged(const std::string &from, const std::string &author, bool set);
- virtual void onDeleteAccount(bool result) { }
-
- virtual void onGroupAddUser(const std::string ¶mString1, const std::string ¶mString2);
- virtual void onGroupRemoveUser(const std::string ¶mString1, const std::string ¶mString2);
- 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 ¶mString1, const std::string ¶mString2);
- virtual void onGroupInfo(const std::string ¶mString1, const std::string ¶mString2, const std::string ¶mString3, const std::string ¶mString4, int paramInt1, int paramInt2);
- virtual void onGroupInfoFromList(const std::string ¶mString1, const std::string ¶mString2, const std::string ¶mString3, const std::string ¶mString4, int paramInt1, int paramInt2);
- virtual void onOwningGroups(const std::vector<string>& paramVector);
+ virtual void onPictureChanged(const std::string &jid, const std::string &id, bool set);
+ virtual void onContactChanged(const std::string &jid, bool added);
+ virtual void onDeleteAccount(bool result) {}
+
+ // WAGroupListener methods ///////////////////////////////////////////////////////////
+ virtual void onGroupAddUser(const std::string &gjid, const std::string &ujid, int ts);
+ virtual void onGroupRemoveUser(const std::string &gjid, const std::string &ujid, int ts);
+ virtual void onGroupNewSubject(const std::string &from, const std::string &author, const std::string &newSubject, int ts);
+ virtual void onGroupMessage(const FMessage ¶mFMessage);
+ virtual void onServerProperties(std::map<std::string, std::string>* nameValueMap) {}
+ virtual void onGroupCreated(const std::string &gjid, const std::string &nick);
+ virtual void onGroupInfo(const std::string &jid, const std::string &owner, const std::string &subject, const std::string &subject_owner, int time_subject, int time_created);
virtual void onSetSubject(const std::string ¶mString) { }
- virtual void onAddGroupParticipants(const std::string ¶mString, const std::vector<string>& paramVector, int paramHashtable) { }
- virtual void onRemoveGroupParticipants(const std::string ¶mString, 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 onAddGroupParticipants(const std::string ¶mString, const std::vector<string> ¶mVector, int paramHashtable) { }
+ virtual void onRemoveGroupParticipants(const std::string ¶mString, const std::vector<string> ¶mVector, int paramHashtable) { }
+ virtual void onGetParticipants(const std::string &gjid, const std::vector<string> &participants);
virtual void onLeaveGroup(const std::string ¶mString);
- //////////////////////////////////////////////////////////////////////////////////////
- // Information providing
+ // Information providing /////////////////////////////////////////////////////////////
void NotifyEvent(const TCHAR *title, const TCHAR *info, MCONTACT contact, DWORD flags, TCHAR *url = NULL);
void NotifyEvent(const std::string &title, const std::string &info, MCONTACT contact, DWORD flags, TCHAR *url = NULL);
};
-#endif
\ No newline at end of file +#endif
diff --git a/protocols/WhatsApp/src/resource.h b/protocols/WhatsApp/src/resource.h index c9872322c0..ebab688804 100644 --- a/protocols/WhatsApp/src/resource.h +++ b/protocols/WhatsApp/src/resource.h @@ -5,13 +5,12 @@ #define IDD_INPUTBOX 102
#define IDR_REGISTERUTILITY 103
#define IDD_WHATSAPOPTIONS 104
+#define IDD_GROUPCHAT_INVITE 105
#define IDI_WHATSAPP 203
#define IDI_ADD_GROUP 206
-#define IDI_ADD_USER_TO_GROUP 207
#define IDI_RENAME_GROUP 208
-#define IDI_CHANGE_GROUP_SUBJECT 209
-#define IDI_LEAVE_GROUP 210
-#define IDI_REMOVE_USER_FROM_GROUP 211
+#define IDC_CLIST 1001
+#define IDC_NEWJID 1002
#define IDC_LOGIN 1003
#define IDC_PW 1004
#define IDC_SSL 1005
@@ -24,14 +23,15 @@ #define IDC_OK 1012
#define IDC_PW2 1013
#define IDC_TEXT 1014
+#define IDC_INVITE 1015
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_CONTROL_VALUE 1016
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/WhatsApp/src/theme.cpp b/protocols/WhatsApp/src/theme.cpp index 94e46e8b14..b95e7649b2 100644 --- a/protocols/WhatsApp/src/theme.cpp +++ b/protocols/WhatsApp/src/theme.cpp @@ -5,12 +5,7 @@ extern OBJLIST<WhatsAppProto> g_Instances; static IconItem icons[] =
{
{ LPGEN("WhatsApp icon"), "whatsApp", IDI_WHATSAPP },
- { LPGEN("Add to group"), "addContactToGroup", IDI_ADD_USER_TO_GROUP},
- { LPGEN("Create chat group"), "createGroup", IDI_ADD_GROUP },
- { LPGEN("Remove from chat group"), "removeContactFromGroup", IDI_REMOVE_USER_FROM_GROUP },
- { LPGEN("Leave and delete group"), "leaveAndDeleteGroup", IDI_LEAVE_GROUP },
- { LPGEN("Leave group"), "leaveGroup", IDI_LEAVE_GROUP },
- { LPGEN("Change group subject"), "changeGroupSubject", IDI_CHANGE_GROUP_SUBJECT }
+ { LPGEN("Create chat group"), "createGroup", IDI_ADD_GROUP }
};
void InitIcons(void)
@@ -36,9 +31,6 @@ char* GetIconDescription(const char* name) return "";
}
-// Contact List menu stuff
-HGENMENU g_hContactMenuItems[CMITEMS_COUNT];
-
// Helper functions
static WhatsAppProto* GetInstanceByHContact(MCONTACT hContact)
{
@@ -53,163 +45,6 @@ static WhatsAppProto* GetInstanceByHContact(MCONTACT hContact) return 0;
}
-template<INT_PTR(__cdecl WhatsAppProto::*Fcn)(WPARAM, LPARAM)>
-INT_PTR GlobalService(WPARAM wParam, LPARAM lParam)
-{
- WhatsAppProto *proto = GetInstanceByHContact(MCONTACT(wParam));
- return proto ? (proto->*Fcn)(wParam, lParam) : 0;
-}
-
-template<INT_PTR(__cdecl WhatsAppProto::*Fcn)(WPARAM, LPARAM, LPARAM)>
-INT_PTR GlobalServiceParam(WPARAM wParam, LPARAM lParam, LPARAM lParam2)
-{
- WhatsAppProto *proto = GetInstanceByHContact(MCONTACT(wParam));
- return proto ? (proto->*Fcn)(wParam, lParam, lParam2) : 0;
-}
-
-static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
-{
- for (size_t i = 0; i < SIZEOF(g_hContactMenuItems); i++)
- Menu_ShowItem(g_hContactMenuItems[i], false);
-
- WhatsAppProto *proto = GetInstanceByHContact(MCONTACT(wParam));
- return proto ? proto->OnPrebuildContactMenu(wParam, lParam) : 0;
-}
-
-void WhatsAppProto::InitContactMenus()
-{
- ::HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu);
-
- CLISTMENUITEM mi = { sizeof(mi) };
- mi.position = -2000006100;
- mi.icolibItem = GetIconHandle("leaveGroup");
- mi.pszName = GetIconDescription("leaveGroup");
- mi.pszService = "WhatsAppProto/LeaveGroup";
- CreateServiceFunction(mi.pszService, GlobalService<&WhatsAppProto::OnLeaveGroup>);
- g_hContactMenuItems[CMI_LEAVE_GROUP] = Menu_AddContactMenuItem(&mi);
-
- mi.position = -2000006100;
- mi.icolibItem = GetIconHandle("leaveAndDeleteGroup");
- mi.pszName = GetIconDescription("leaveAndDeleteGroup");
- g_hContactMenuItems[CMI_REMOVE_GROUP] = Menu_AddContactMenuItem(&mi);
-
- mi.position = -2000006099;
- mi.icolibItem = GetIconHandle("changeGroupSubject");
- mi.pszName = GetIconDescription("changeGroupSubject");
- mi.pszService = "WhatsAppProto/ChangeGroupSubject";
- CreateServiceFunction(mi.pszService, GlobalService<&WhatsAppProto::OnChangeGroupSubject>);
- g_hContactMenuItems[CMI_CHANGE_GROUP_SUBJECT] = Menu_AddContactMenuItem(&mi);
-}
-
-int WhatsAppProto::OnPrebuildContactMenu(WPARAM wParam, LPARAM lParam)
-{
- MCONTACT hContact = MCONTACT(wParam);
- if (hContact)
- debugLog(pcli->pfnGetContactDisplayName(hContact, 0));
- else
- debugLogA("No contact found");
-
- if (g_hContactMenuItems[CMI_ADD_CONTACT_TO_GROUP] != NULL)
- CallService("CList/RemoveContactMenuItem", (WPARAM)g_hContactMenuItems[CMI_ADD_CONTACT_TO_GROUP], (LPARAM)0);
-
- if (g_hContactMenuItems[CMI_REMOVE_CONTACT_FROM_GROUP] != NULL)
- CallService("CList/RemoveContactMenuItem", (WPARAM)g_hContactMenuItems[CMI_REMOVE_CONTACT_FROM_GROUP], (LPARAM)0);
-
- int chatType = getByte(hContact, "SimpleChatRoom", 0);
-
- CLISTMENUITEM mi = { sizeof(mi) };
-
- if (chatType == 0) {
- mi.flags = CMIF_CHILDPOPUP;
- mi.position = -2000006102;
- mi.icolibItem = GetIconHandle("addContactToGroup");
- mi.pszName = GetIconDescription("addContactToGroup");
- mi.pszService = NULL;
- g_hContactMenuItems[CMI_ADD_CONTACT_TO_GROUP] = Menu_AddContactMenuItem(&mi);
-
- if (!isOnline()) {
- Menu_ShowItem(g_hContactMenuItems[CMI_ADD_CONTACT_TO_GROUP], false);
- return 0;
- }
-
- mi.hParentMenu = (HGENMENU)g_hContactMenuItems[CMI_ADD_CONTACT_TO_GROUP];
- mi.flags = CMIF_ROOTHANDLE | CMIF_TCHAR;
-
- int iGrpCount = 0;
- string fullSvcName;
- string svcName = m_szModuleName;
- svcName += "/AddContactToGroup_";
- DBVARIANT dbv;
-
- for (map<MCONTACT, map<MCONTACT, bool>>::iterator it = this->isMemberByGroupContact.begin();
- it != this->isMemberByGroupContact.end(); ++it) {
- map<MCONTACT, bool>::iterator memberIt = it->second.find(hContact);
- // Only, if current contact is not already member of this group
- if ((memberIt == it->second.end() || memberIt->second == false) && !getString(it->first, "ID", &dbv)) {
- fullSvcName = svcName + dbv.pszVal;
- mi.pszService = (char*)fullSvcName.c_str();
- mi.ptszName = pcli->pfnGetContactDisplayName(it->first, 0);
- CreateServiceFunctionParam(mi.pszService, GlobalServiceParam<&WhatsAppProto::OnAddContactToGroup>, (LPARAM)it->first);
- Menu_AddContactMenuItem(&mi);
- db_free(&dbv);
- iGrpCount++;
- }
- }
- if (!iGrpCount)
- Menu_ShowItem(g_hContactMenuItems[CMI_ADD_CONTACT_TO_GROUP], false);
- }
- else if (chatType == 1) {
- mi.flags = CMIM_FLAGS;
- if (!isOnline() || getByte(hContact, "IsGroupMember", 0) == 0)
- mi.flags |= CMIF_GRAYED;
- CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)g_hContactMenuItems[CMI_LEAVE_GROUP], (LPARAM)&mi);
- }
- else if (chatType == 2) {
- // owning chat/group
- mi.flags = CMIF_CHILDPOPUP;
- mi.position = -2000006102;
- mi.icolibItem = GetIconHandle("removeContactFromGroup");
- mi.pszName = GetIconDescription("removeContactFromGroup");
- mi.pszService = NULL;
- g_hContactMenuItems[CMI_REMOVE_CONTACT_FROM_GROUP] = Menu_AddContactMenuItem(&mi);
-
- bool bShow = false;
- if (isOnline() && getByte(hContact, "IsGroupMember", 0) == 1) {
- map<MCONTACT, map<MCONTACT, bool>>::iterator groupsIt = this->isMemberByGroupContact.find(hContact);
- if (groupsIt == this->isMemberByGroupContact.end())
- debugLogA("Group exists only on contact list");
- else {
- mi.hParentMenu = (HGENMENU)g_hContactMenuItems[CMI_REMOVE_CONTACT_FROM_GROUP];
- mi.flags = CMIF_ROOTHANDLE | CMIF_TCHAR;
-
- string fullSvcName;
- string svcName = m_szModuleName;
- svcName += "/RemoveContactFromGroup_";
- DBVARIANT dbv;
-
- for (map<MCONTACT, bool>::iterator it = groupsIt->second.begin(); it != groupsIt->second.end(); ++it) {
- if (!getString(it->first, "ID", &dbv)) {
- fullSvcName = svcName + dbv.pszVal;
- mi.pszService = (char*)fullSvcName.c_str();
- mi.ptszName = pcli->pfnGetContactDisplayName(it->first, 0);
- CreateServiceFunctionParam(mi.pszService,
- GlobalServiceParam<&WhatsAppProto::OnRemoveContactFromGroup>, (LPARAM)it->first);
- Menu_AddContactMenuItem(&mi);
- db_free(&dbv);
- bShow = true;
- }
- }
- }
- }
- else Menu_ShowItem(g_hContactMenuItems[CMI_REMOVE_CONTACT_FROM_GROUP], false);
-
- Menu_ShowItem(g_hContactMenuItems[CMI_REMOVE_GROUP], bShow);
- Menu_ShowItem(g_hContactMenuItems[CMI_CHANGE_GROUP_SUBJECT], bShow);
- }
-
- return 0;
-}
-
int WhatsAppProto::OnBuildStatusMenu(WPARAM wParam, LPARAM lParam)
{
char text[200];
@@ -223,7 +58,7 @@ int WhatsAppProto::OnBuildStatusMenu(WPARAM wParam, LPARAM lParam) if (hRoot == NULL) {
mi.popupPosition = 500085000;
mi.hParentMenu = HGENMENU_ROOT;
- mi.flags = CMIF_ROOTPOPUP | CMIF_TCHAR | CMIF_KEEPUNTRANSLATED | (this->isOnline() ? 0 : CMIF_GRAYED);
+ mi.flags = CMIF_ROOTPOPUP | CMIF_TCHAR | CMIF_KEEPUNTRANSLATED | (isOnline() ? 0 : CMIF_GRAYED);
mi.icolibItem = GetIconHandle("whatsApp");
mi.ptszName = m_tszUserName;
hRoot = m_hMenuRoot = Menu_AddProtoMenuItem(&mi);
@@ -234,7 +69,7 @@ int WhatsAppProto::OnBuildStatusMenu(WPARAM wParam, LPARAM lParam) m_hMenuRoot = NULL;
}
- mi.flags = CMIF_CHILDPOPUP | (this->isOnline() ? 0 : CMIF_GRAYED);
+ mi.flags = CMIF_CHILDPOPUP | (isOnline() ? 0 : CMIF_GRAYED);
mi.position = 201001;
CreateProtoService("/CreateGroup", &WhatsAppProto::OnCreateGroup);
diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp index 2b9ebd2b2f..652a9c7c4a 100644 --- a/protocols/WhatsApp/src/utils.cpp +++ b/protocols/WhatsApp/src/utils.cpp @@ -1,8 +1,26 @@ #include "common.h"
-LONG WhatsAppProto::GetSerial()
+TCHAR* utils::removeA(TCHAR *str)
{
- return ::_InterlockedIncrement(&m_iSerial);
+ if (str == NULL)
+ return NULL;
+
+ TCHAR *p = _tcschr(str, '@');
+ if (p) *p = 0;
+ return str;
+}
+
+void utils::copyText(HWND hwnd, const TCHAR *text)
+{
+ if (!hwnd || !text) return;
+
+ OpenClipboard(hwnd);
+ EmptyClipboard();
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR)*(mir_tstrlen(text) + 1));
+ mir_tstrcpy((TCHAR*)GlobalLock(hMem), text);
+ GlobalUnlock(hMem);
+ SetClipboardData(CF_UNICODETEXT, hMem);
+ CloseClipboard();
}
std::string getLastErrorMsg()
diff --git a/protocols/WhatsApp/src/utils.h b/protocols/WhatsApp/src/utils.h index a14a707a14..d9a1218312 100644 --- a/protocols/WhatsApp/src/utils.h +++ b/protocols/WhatsApp/src/utils.h @@ -27,8 +27,15 @@ public: std::string getLastErrorMsg();
+__forceinline TCHAR* str2t(const std::string &str)
+{ return mir_utf8decodeT(str.c_str());
+}
+
namespace utils
{
+ TCHAR* removeA(TCHAR *str);
+ void copyText(HWND hwnd, const TCHAR *text);
+
void setStatusMessage(MCONTACT hContact, const TCHAR *ptszMessage);
BYTE* md5string(const BYTE*, int, BYTE* digest);
diff --git a/protocols/WhatsApp/src/version.h b/protocols/WhatsApp/src/version.h index 5d83753125..6f591420cd 100644 --- a/protocols/WhatsApp/src/version.h +++ b/protocols/WhatsApp/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0
#define __MINOR_VERSION 1
#define __RELEASE_NUM 2
-#define __BUILD_NUM 6
+#define __BUILD_NUM 7
#include <stdver.h>
|