From 52c57ef89cc24bdb8c70908f544ae86fd87db129 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 28 Jan 2015 16:30:05 +0000 Subject: - statusbar icon added to notify user that a message was read; - FMessage own numbering removed as atavism; - WAConnection::msg_id followed FMessage::id on its road to hell - WhatsAppProto::GetSerial() added as the only method that increments message numbers git-svn-id: http://svn.miranda-ng.org/main/trunk@11941 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp | 44 ++---------- protocols/WhatsApp/src/WhatsAPI++/FMessage.h | 23 ++----- protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp | 78 ++++++++++------------ protocols/WhatsApp/src/WhatsAPI++/WAConnection.h | 1 - protocols/WhatsApp/src/main.cpp | 1 - protocols/WhatsApp/src/messages.cpp | 19 ++++-- protocols/WhatsApp/src/proto.cpp | 3 +- protocols/WhatsApp/src/proto.h | 4 ++ protocols/WhatsApp/src/utils.cpp | 21 +++++- protocols/WhatsApp/src/utils.h | 2 + 10 files changed, 84 insertions(+), 112 deletions(-) (limited to 'protocols/WhatsApp') diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp index a684d1e3e3..e3c3367b04 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp @@ -9,15 +9,9 @@ #include "utilities.h" -//SDL_mutex* FMessage::generating_lock = SDL_CreateMutex(); -IMutex* FMessage::generating_lock = NULL; -int FMessage::generating_id = 0; -std::string FMessage::generating_header = Utilities::intToStr(static_cast (time(NULL))).append("-"); - - -FMessage::FMessage() +FMessage::FMessage() : + key("", false, "") { - this->key = NULL; this->timestamp = 0; this->media_wa_type = 0; this->longitude = 0; @@ -29,15 +23,9 @@ FMessage::FMessage() this->data = ""; } -FMessage::FMessage(const std::string& remote_jid, bool from_me, const std::string& data) +FMessage::FMessage(const std::string &remote_jid, bool from_me, const std::string &id) : + key(remote_jid, from_me, id) { - Key* local_key; - FMessage::generating_lock->lock(); - FMessage::generating_id++; - local_key = new Key(remote_jid, from_me, generating_header + Utilities::intToStr(generating_id)); - this->key = local_key; - FMessage::generating_lock->unlock(); - this->data = data; this->timestamp = time(NULL); this->media_wa_type = 0; this->longitude = 0; @@ -48,28 +36,6 @@ FMessage::FMessage(const std::string& remote_jid, bool from_me, const std::strin this->media_url = ""; } -std::string FMessage::nextKeyIdNumber() -{ - int id = 0; - FMessage::generating_lock->lock(); - id = (FMessage::generating_id++); - FMessage::generating_lock->unlock(); - return generating_header + (Utilities::intToStr(id)); -} - -FMessage::FMessage(Key* key) -{ - this->key = key; - this->timestamp = 0; - this->media_wa_type = 0; - this->longitude = 0; - this->latitude = 0; - this->media_duration_seconds = 0; - this->media_size = 0; - this->media_name = ""; - this->media_url = ""; -} - std::string FMessage::getMessage_WA_Type_StrValue(unsigned char type) { switch (type) { @@ -94,8 +60,6 @@ std::string FMessage::getMessage_WA_Type_StrValue(unsigned char type) FMessage::~FMessage() { - if (this->key != NULL) - delete key; } Key::Key(const std::string& remote_jid, bool from_me, const std::string& id) diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.h b/protocols/WhatsApp/src/WhatsAPI++/FMessage.h index fb523d9c8e..e53b7d88dd 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.h +++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.h @@ -15,8 +15,8 @@ #include #include "IMutex.h" -class Key { -public: +struct Key +{ std::string remote_jid; bool from_me; std::string id; @@ -26,16 +26,9 @@ public: }; -class FMessage { -private: - static int generating_id; - static std::string generating_header; - - -public: - static IMutex* generating_lock; // #WORKAROUND - - Key* key; +struct FMessage +{ + Key key; unsigned char media_wa_type; std::string data; long long timestamp; @@ -79,12 +72,10 @@ public: }; static std::string getMessage_WA_Type_StrValue(unsigned char type); - static std::string nextKeyIdNumber(); - static unsigned char getMessage_WA_Type(const std::string& typeString); + static unsigned char getMessage_WA_Type(const std::string &typeString); FMessage(); - FMessage(const std::string& remote_jid, bool from_me = true, const std::string& data = ""); - FMessage(Key* key); + FMessage(const std::string &remote_jid, bool from_me, const std::string &id); virtual ~FMessage(); }; diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp index c87f88b619..29aaec738b 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp @@ -105,7 +105,6 @@ WAConnection::WAConnection(const std::string &user, const std::string &resource, this->in = NULL; this->out = NULL; - this->msg_id = 0; this->retry = true; this->user = user; @@ -269,7 +268,7 @@ void WAConnection::parseAck(ProtocolTreeNode *node) throw(WAException) const string &ts = node->getAttributeValue("t"); if (cls == "message" && this->event_handler != NULL) { - FMessage msg(new Key(from, true, id)); + FMessage msg(from, true, id); msg.status = FMessage::STATUS_RECEIVED_BY_SERVER; this->event_handler->onMessageStatusUpdate(&msg); } @@ -312,13 +311,11 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio errorCode = atoi(errorNode->getAttributeValue("code").c_str()); } - Key* key = new Key(from, true, id); - FMessage* message = new FMessage(key); - message->status = FMessage::STATUS_SERVER_BOUNCE; + FMessage message(from, true, id); + message.status = FMessage::STATUS_SERVER_BOUNCE; if (this->event_handler != NULL) - this->event_handler->onMessageError(message, errorCode); - delete message; + this->event_handler->onMessageError(&message, errorCode); } else if (typeAttribute == "subject") { bool receiptRequested = false; @@ -337,29 +334,28 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio sendSubjectReceived(from, id); } else if (typeAttribute == "chat" || typeAttribute == "text") { - FMessage* fmessage = new FMessage(); - fmessage->wants_receipt = false; - fmessage->timestamp = atoi(attribute_t.c_str()); + FMessage fmessage; + fmessage.wants_receipt = false; + fmessage.timestamp = atoi(attribute_t.c_str()); bool duplicate = false; std::vector messageChildren(messageNode->getAllChildren()); for (size_t i = 0; i < messageChildren.size(); i++) { ProtocolTreeNode *childNode = messageChildren[i]; if (ProtocolTreeNode::tagEquals(childNode, "body")) { - Key* key = new Key(from, false, id); - fmessage->key = key; - fmessage->remote_resource = author; - fmessage->data = childNode->getDataAsString(); - fmessage->status = FMessage::STATUS_UNSENT; + fmessage.key = Key(from, false, id); + fmessage.remote_resource = author; + fmessage.data = childNode->getDataAsString(); + fmessage.status = FMessage::STATUS_UNSENT; } else if (ProtocolTreeNode::tagEquals(childNode, "media") && !id.empty()) { - fmessage->media_wa_type = FMessage::getMessage_WA_Type(childNode->getAttributeValue("type")); - fmessage->media_url = childNode->getAttributeValue("url"); - fmessage->media_name = childNode->getAttributeValue("file"); - fmessage->media_size = Utilities::parseLongLong(childNode->getAttributeValue("size")); - fmessage->media_duration_seconds = atoi(childNode->getAttributeValue("seconds").c_str()); + fmessage.media_wa_type = FMessage::getMessage_WA_Type(childNode->getAttributeValue("type")); + fmessage.media_url = childNode->getAttributeValue("url"); + fmessage.media_name = childNode->getAttributeValue("file"); + fmessage.media_size = Utilities::parseLongLong(childNode->getAttributeValue("size")); + fmessage.media_duration_seconds = atoi(childNode->getAttributeValue("seconds").c_str()); - if (fmessage->media_wa_type == FMessage::WA_TYPE_LOCATION) { + if (fmessage.media_wa_type == FMessage::WA_TYPE_LOCATION) { const string &latitudeString = childNode->getAttributeValue("latitude"); const string &longitudeString = childNode->getAttributeValue("longitude"); if (latitudeString.empty() || longitudeString.empty()) @@ -367,42 +363,39 @@ void WAConnection::parseMessage(ProtocolTreeNode *messageNode) throw (WAExceptio double latitude = atof(latitudeString.c_str()); double longitude = atof(longitudeString.c_str()); - fmessage->latitude = latitude; - fmessage->longitude = longitude; + fmessage.latitude = latitude; + fmessage.longitude = longitude; } - if (fmessage->media_wa_type == FMessage::WA_TYPE_CONTACT) { + if (fmessage.media_wa_type == FMessage::WA_TYPE_CONTACT) { ProtocolTreeNode *contactChildNode = childNode->getChild(0); if (contactChildNode != NULL) { - fmessage->media_name = contactChildNode->getAttributeValue("name"); - fmessage->data = contactChildNode->getDataAsString(); + fmessage.media_name = contactChildNode->getAttributeValue("name"); + fmessage.data = contactChildNode->getDataAsString(); } } else { const string &encoding = childNode->getAttributeValue("encoding"); if (encoding.empty() || encoding == "text") - fmessage->data = childNode->getDataAsString(); + fmessage.data = childNode->getDataAsString(); else { logData("Media data encoding type '%s'", encoding.empty() ? "text" : encoding.c_str()); - fmessage->data = (childNode->data == NULL ? "" : std::string(base64_encode(childNode->data->data(), childNode->data->size()))); + fmessage.data = (childNode->data == NULL ? "" : std::string(base64_encode(childNode->data->data(), childNode->data->size()))); } } - Key* key = new Key(from, false, id); - fmessage->key = key; - fmessage->remote_resource = author; + fmessage.key = Key(from, false, id); + fmessage.remote_resource = author; } } - if (fmessage->timestamp == 0) { - fmessage->timestamp = time(NULL); - fmessage->offline = false; + if (fmessage.timestamp == 0) { + fmessage.timestamp = time(NULL); + fmessage.offline = false; } - if (fmessage->key != NULL && this->event_handler != NULL) - this->event_handler->onMessageForMe(fmessage, duplicate); - - delete fmessage; + if (!fmessage.key.remote_jid.empty() && this->event_handler != NULL) + this->event_handler->onMessageForMe(&fmessage, duplicate); } else if (typeAttribute == "notification") { logData("Notification node %s", messageNode->toString().c_str()); @@ -720,7 +713,7 @@ ProtocolTreeNode* WAConnection::getMessageNode(FMessage* message, ProtocolTreeNo messageChildren->push_back(child); return new ProtocolTreeNode("message", NULL, messageChildren) << - XATTR("to", message->key->remote_jid) << XATTR("type", "text") << XATTR("id", message->key->id) << XATTRI("t", message->timestamp); + XATTR("to", message->key.remote_jid) << XATTR("type", "text") << XATTR("id", message->key.id) << XATTRI("t", message->timestamp); } void WAConnection::sendMessage(FMessage* message) throw(WAException) @@ -775,7 +768,7 @@ void WAConnection::sendMessageWithBody(FMessage* message) throw (WAException) void WAConnection::sendMessageReceived(FMessage* message) throw(WAException) { this->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))); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -837,12 +830,11 @@ void WAConnection::sendSetPicture(const std::string& jid, std::vectormakeId(Utilities::intToStr((int)time(NULL))); - FMessage *message = new FMessage(new Key("s.us", true, id)); + FMessage message("s.us", true, id); ProtocolTreeNode *body = new ProtocolTreeNode("body", new std::vector(status.begin(), status.end()), NULL); - ProtocolTreeNode *n = getMessageNode(message, body); + ProtocolTreeNode *n = getMessageNode(&message, body); this->out->write(*n); delete n; - delete message; } void WAConnection::sendSubjectReceived(const std::string& to, const std::string& id)throw(WAException) diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h index bbdad6c0e6..560f957634 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h @@ -398,7 +398,6 @@ public: KeyStream inputKey, outputKey; - int msg_id; bool retry; bool supports_receipt_acks; time_t expire_date; diff --git a/protocols/WhatsApp/src/main.cpp b/protocols/WhatsApp/src/main.cpp index 1681132790..d4d607f452 100644 --- a/protocols/WhatsApp/src/main.cpp +++ b/protocols/WhatsApp/src/main.cpp @@ -92,7 +92,6 @@ extern "C" int __declspec(dllexport) Unload(void) { g_Instances.destroy(); - delete FMessage::generating_lock; WASocketConnection::quitNetwork(); return 0; diff --git a/protocols/WhatsApp/src/messages.cpp b/protocols/WhatsApp/src/messages.cpp index b359616b89..b935f1d67b 100644 --- a/protocols/WhatsApp/src/messages.cpp +++ b/protocols/WhatsApp/src/messages.cpp @@ -26,7 +26,7 @@ void WhatsAppProto::onMessageForMe(FMessage* paramFMessage, bool paramBoolean) msg->insert(0, std::string("[").append(paramFMessage->notifyname).append("]: ")); } - MCONTACT hContact = this->AddToContactList(paramFMessage->key->remote_jid, 0, false, + MCONTACT hContact = this->AddToContactList(paramFMessage->key.remote_jid, 0, false, isChatRoom ? NULL : paramFMessage->notifyname.c_str(), isChatRoom); PROTORECVEVENT recv = { 0 }; @@ -54,15 +54,16 @@ int WhatsAppProto::SendMsg(MCONTACT hContact, int flags, const char *msg) return 0; } - int msgId = ++this->m_pConnection->msg_id; + int msgId = GetSerial(); try { time_t now = time(NULL); std::string id = Utilities::intToStr(now) + "-" + Utilities::intToStr(msgId); - FMessage fmsg(new Key((const char*)jid, true, id)); + FMessage fmsg(std::string(jid), true, id); fmsg.timestamp = now; fmsg.data = msg; m_pConnection->sendMessage(&fmsg); + utils::setStatusMessage(hContact, NULL); } catch (exception &e) { debugLogA("exception: %s", e.what()); @@ -117,16 +118,22 @@ void WhatsAppProto::SendTypingWorker(void* p) void WhatsAppProto::onMessageStatusUpdate(FMessage* fmsg) { - MCONTACT hContact = this->ContactIDToHContact(fmsg->key->remote_jid); + MCONTACT hContact = this->ContactIDToHContact(fmsg->key.remote_jid); if (hContact == 0) return; if (fmsg->status == FMessage::STATUS_RECEIVED_BY_SERVER) { - 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()); + + TCHAR ttime[64]; + _tcsftime(ttime, SIZEOF(ttime), _T("%X"), localtime(×tamp)); + utils::setStatusMessage(hContact, CMString(FORMAT, TranslateT("Message read: %s by %s"), ttime, pcli->pfnGetContactDisplayName(hContact, 0))); } } diff --git a/protocols/WhatsApp/src/proto.cpp b/protocols/WhatsApp/src/proto.cpp index cd251762c3..fcd64ebd8a 100644 --- a/protocols/WhatsApp/src/proto.cpp +++ b/protocols/WhatsApp/src/proto.cpp @@ -16,7 +16,6 @@ WhatsAppProto::WhatsAppProto(const char* proto_name, const TCHAR* username) : PROTO(proto_name, username) { update_loop_lock_ = CreateEvent(NULL, false, false, NULL); - FMessage::generating_lock = new Mutex(); CreateProtoService(PS_CREATEACCMGRUI, &WhatsAppProto::SvcCreateAccMgrUI); CreateProtoService(PS_JOINCHAT, &WhatsAppProto::OnJoinChat); @@ -205,7 +204,7 @@ HANDLE WhatsAppProto::SearchBasic(const PROTOCHAR* id) return 0; // fake - we always accept search - SearchParam *param = new SearchParam(id, ++m_pConnection->msg_id); + SearchParam *param = new SearchParam(id, GetSerial()); ForkThread(&WhatsAppProto::SearchAckThread, param); return (HANDLE)param->id; } diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h index 622296cdd9..a55d357e3f 100644 --- a/protocols/WhatsApp/src/proto.h +++ b/protocols/WhatsApp/src/proto.h @@ -129,6 +129,8 @@ public: return getByte(hC, "SimpleChatRoom", 0) > (checkIsAdmin ? 1 : 0); } + LONG GetSerial(); + ////////////////////////////////////////////////////////////////////////////////////// // Registration @@ -139,6 +141,8 @@ private: ////////////////////////////////////////////////////////////////////////////////////// // Helpers + LONG m_iSerial; + std::tstring GetAvatarFolder(); void ToggleStatusMenuItems(BOOL bEnable); diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp index 0aa95f1a16..2b9ebd2b2f 100644 --- a/protocols/WhatsApp/src/utils.cpp +++ b/protocols/WhatsApp/src/utils.cpp @@ -1,11 +1,14 @@ #include "common.h" -std::string getLastErrorMsg() +LONG WhatsAppProto::GetSerial() { - // Retrieve the system error message for the last-error code + return ::_InterlockedIncrement(&m_iSerial); +} +std::string getLastErrorMsg() +{ LPVOID lpMsgBuf; - DWORD dw = WSAGetLastError(); + DWORD dw = WSAGetLastError(); // retrieve the system error message for the last-error code FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -22,6 +25,18 @@ std::string getLastErrorMsg() return ret; } +void utils::setStatusMessage(MCONTACT hContact, const TCHAR *ptszMessage) +{ + if (ptszMessage != NULL) { + StatusTextData st = { 0 }; + st.cbSize = sizeof(st); + st.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + _tcsncpy_s(st.tszText, ptszMessage, _TRUNCATE); + CallService(MS_MSG_SETSTATUSTEXT, hContact, (LPARAM)&st); + } + else CallService(MS_MSG_SETSTATUSTEXT, hContact, NULL); +} + BYTE* utils::md5string(const BYTE *data, int size, BYTE *digest) { mir_md5_state_t md5_state; diff --git a/protocols/WhatsApp/src/utils.h b/protocols/WhatsApp/src/utils.h index a5b1e17592..7f0d903d1b 100644 --- a/protocols/WhatsApp/src/utils.h +++ b/protocols/WhatsApp/src/utils.h @@ -58,6 +58,8 @@ std::string getLastErrorMsg(); namespace utils { + void setStatusMessage(MCONTACT hContact, const TCHAR *ptszMessage); + BYTE* md5string(const BYTE*, int, BYTE* digest); __forceinline BYTE* md5string(const std::string &str, BYTE* digest) { -- cgit v1.2.3