diff options
author | George Hazan <ghazan@miranda.im> | 2019-06-18 10:28:17 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-06-18 10:28:17 +0300 |
commit | 062224cae32f5fbc5f47e5af74563b7389a4f7c0 (patch) | |
tree | 4de2d2ded04959cc5bf71046dbe8f17f65d246d0 /protocols/Facebook | |
parent | e49424a51bc3fbb0ccb2d1ecafec3f4fe3689930 (diff) |
first login packet
Diffstat (limited to 'protocols/Facebook')
-rw-r--r-- | protocols/Facebook/src/db.h | 1 | ||||
-rw-r--r-- | protocols/Facebook/src/http.cpp | 142 | ||||
-rw-r--r-- | protocols/Facebook/src/mqtt.cpp | 169 | ||||
-rw-r--r-- | protocols/Facebook/src/mqtt.h | 61 | ||||
-rw-r--r-- | protocols/Facebook/src/proto.cpp | 134 | ||||
-rw-r--r-- | protocols/Facebook/src/proto.h | 58 | ||||
-rw-r--r-- | protocols/Facebook/src/server.cpp | 39 | ||||
-rw-r--r-- | protocols/Facebook/src/stdafx.h | 1 |
8 files changed, 578 insertions, 27 deletions
diff --git a/protocols/Facebook/src/db.h b/protocols/Facebook/src/db.h index 6c79ded525..89d908ac9a 100644 --- a/protocols/Facebook/src/db.h +++ b/protocols/Facebook/src/db.h @@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define DBKEY_NICK "Nick" #define DBKEY_USERNAME "Username" #define DBKEY_PASS "Password" +#define DBKEY_CLIENT_ID "ClientID" #define DBKEY_DEVICE_ID "DeviceID" #define DBKEY_AVATAR "Avatar" #define DBKEY_DELETED "DeletedTS" diff --git a/protocols/Facebook/src/http.cpp b/protocols/Facebook/src/http.cpp new file mode 100644 index 0000000000..aa2d4a5c5e --- /dev/null +++ b/protocols/Facebook/src/http.cpp @@ -0,0 +1,142 @@ +/* + +Facebook plugin for Miranda NG +Copyright © 2019 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +static int CompareParams(const AsyncHttpRequest::Param *p1, const AsyncHttpRequest::Param *p2) +{ + return strcmp(p1->key, p2->key); +} + +AsyncHttpRequest::AsyncHttpRequest() : + params(5, CompareParams) +{ +} + +void AsyncHttpRequest::CalcSig() +{ + CMStringA buf; + for (auto &it : params) + buf.AppendFormat("%s=%s", it->key.c_str(), it->val.c_str()); + buf.Append(FB_APP_SECRET); + + char szHash[33]; + BYTE digest[16]; + mir_md5_hash((BYTE*)buf.c_str(), buf.GetLength(), digest); + bin2hex(digest, sizeof(digest), szHash); + this << CHAR_PARAM("sig", szHash); + + for (auto &it : params) { + if (!m_szParam.IsEmpty()) + m_szParam.AppendChar('&'); + m_szParam.AppendFormat("%s=%s", it->key.c_str(), mir_urlEncode(it->val.c_str()).c_str()); + } +} + +AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const CHAR_PARAM ¶m) +{ + pReq->params.insert(new AsyncHttpRequest::Param(param.szName, param.szValue)); + return pReq; +} + +AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const INT_PARAM ¶m) +{ + char value[40]; + itoa(param.iValue, value, 10); + pReq->params.insert(new AsyncHttpRequest::Param(param.szName, value)); + return pReq; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) +{ + if (pReply == nullptr) { + m_errorCode = 500; + return; + } + + m_errorCode = pReply->resultCode; + if (m_errorCode != 200) + return; + + m_root = json_parse(pReply->pData); + if (m_root == nullptr) { + m_errorCode = 500; + return; + } + + m_errorCode = (*m_root)["error_code"].as_int(); +} + +JsonReply::~JsonReply() +{ + json_delete(m_root); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +AsyncHttpRequest* FacebookProto::CreateRequest(const char *szName, const char *szMethod) +{ + AsyncHttpRequest *pReq = new AsyncHttpRequest(); + pReq->requestType = REQUEST_POST; + pReq << CHAR_PARAM("api_key", FB_APP_KEY) << CHAR_PARAM("device_id", m_szDeviceID) << CHAR_PARAM("fb_api_req_friendly_name", szName) + << CHAR_PARAM("format", "json") << CHAR_PARAM("method", szMethod); + + CMStringA szLocale = getMStringA(DBKEY_LOCALE); + if (szLocale.IsEmpty()) + szLocale = "en"; + pReq << CHAR_PARAM("locale", szLocale); + + pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); + + unsigned int id; + Utils_GetRandom(&id, sizeof(id)); + id &= ~0x80000000; + pReq << INT_PARAM("queryid", id); + + return pReq; +} + +NETLIBHTTPREQUEST* FacebookProto::ExecuteRequest(AsyncHttpRequest *pReq) +{ + CMStringA str; + + pReq->flags |= NLHRF_HTTP11; + pReq->szUrl = pReq->m_szUrl.GetBuffer(); + if (!pReq->m_szParam.IsEmpty()) { + if (pReq->requestType == REQUEST_GET) { + str.Format("%s?%s", pReq->m_szUrl.c_str(), pReq->m_szParam.c_str()); + pReq->szUrl = str.GetBuffer(); + } + else { + pReq->dataLength = pReq->m_szParam.GetLength(); + pReq->pData = mir_strdup(pReq->m_szParam); + } + } + + debugLogA("Executing request:\n%s", pReq->szUrl); + + NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, pReq); + delete pReq; + return reply; +} diff --git a/protocols/Facebook/src/mqtt.cpp b/protocols/Facebook/src/mqtt.cpp new file mode 100644 index 0000000000..ba81cbad32 --- /dev/null +++ b/protocols/Facebook/src/mqtt.cpp @@ -0,0 +1,169 @@ +/* + +Facebook plugin for Miranda NG +Copyright © 2019 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "stdafx.h" + +static uint8_t encodeType(int type) +{ + switch (type) { + case FB_THRIFT_TYPE_BOOL: + return 2; + case FB_THRIFT_TYPE_BYTE: + return 3; + case FB_THRIFT_TYPE_I16: + return 4; + case FB_THRIFT_TYPE_I32: + return 5; + case FB_THRIFT_TYPE_I64: + return 6; + case FB_THRIFT_TYPE_DOUBLE: + return 7; + case FB_THRIFT_TYPE_STRING: + return 8; + case FB_THRIFT_TYPE_LIST: + return 9; + case FB_THRIFT_TYPE_SET: + return 10; + case FB_THRIFT_TYPE_MAP: + return 11; + case FB_THRIFT_TYPE_STRUCT: + return 12; + default: + return 0; + } +} + +FbThrift& FbThrift::operator<<(uint8_t value) +{ + m_buf.append(&value, 1); + return *this; +} + +FbThrift& FbThrift::operator<<(const char *str) +{ + size_t len = mir_strlen(str); + writeInt32((int)len); + m_buf.append((void*)str, len); + return *this; +} + +void FbThrift::writeBool(bool bValue) +{ + uint8_t b = (bValue) ? 1 : 2; + m_buf.append(&b, 1); +} + +void FbThrift::writeBuf(const void *pData, size_t cbLen) +{ + m_buf.append((void*)pData, cbLen); +} + +void FbThrift::writeField(int iType, int id) +{ + uint8_t type = encodeType(iType); + m_buf.append(&type, 1); + writeInt64(id); +} + +void FbThrift::writeField(int iType, int id, int lastid) +{ + uint8_t type = encodeType(iType); + uint8_t diff = uint8_t(id - lastid); + if (diff > 0x0F) { + m_buf.append(&type, 1); + writeInt64(id); + } + else { + type += (diff << 4); + m_buf.append(&type, 1); + } +} + +void FbThrift::writeInt32(__int32 value) +{ + writeIntV((value << 1) ^ (value >> 31)); +} + +void FbThrift::writeInt64(__int64 value) +{ + writeIntV((value << 1) ^ (value >> 63)); +} + +void FbThrift::writeIntV(__int64 value) +{ + bool bLast; + do { + bLast = (value & ~0x7F) == 0; + uint8_t b = value & 0x7F; + if (!bLast) { + b |= 0x80; + value >>= 7; + } + m_buf.append(&b, 1); + } while (!bLast); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MQTT functions + +void FacebookProto::MqttOpen() +{ + FbThrift thrift; + thrift.writeField(FB_THRIFT_TYPE_STRING, 1); // Client identifier + thrift << m_szClientID; + + thrift.writeField(FB_THRIFT_TYPE_STRUCT, 4, 1); + + thrift.writeField(FB_THRIFT_TYPE_I64, 1); // User identifier + thrift.writeInt64(m_uid); + + thrift.writeField(FB_THRIFT_TYPE_STRING, 2); // User agent + thrift << NETLIB_USER_AGENT; + + thrift.writeField(FB_THRIFT_TYPE_I64, 3); + thrift.writeInt64(23); + thrift.writeField(FB_THRIFT_TYPE_I64, 4); + thrift.writeInt64(26); + thrift.writeField(FB_THRIFT_TYPE_I32, 5); + thrift.writeInt32(1); + thrift.writeField(FB_THRIFT_TYPE_BOOL, 6); + thrift.writeBool(true); + thrift.writeField(FB_THRIFT_TYPE_BOOL, 7); // visibility + thrift.writeBool(m_iStatus != ID_STATUS_INVISIBLE); + + thrift.writeField(FB_THRIFT_TYPE_STRING, 8); // device id + thrift << m_szDeviceID; + + thrift.writeField(FB_THRIFT_TYPE_BOOL, 9); + thrift.writeBool(true); + thrift.writeField(FB_THRIFT_TYPE_I32, 10); + thrift.writeInt32(1); + thrift.writeField(FB_THRIFT_TYPE_I32, 11); + thrift.writeInt32(0); + thrift.writeField(FB_THRIFT_TYPE_I64, 12); + thrift.writeInt64(m_iMqttId); + + thrift.writeField(FB_THRIFT_TYPE_LIST, 14, 12); + thrift.writeField(FB_THRIFT_TYPE_I32, 0); + thrift << (BYTE)0; + + thrift.writeField(FB_THRIFT_TYPE_LIST, 15); + thrift << m_szAuthToken << (BYTE)0; +} diff --git a/protocols/Facebook/src/mqtt.h b/protocols/Facebook/src/mqtt.h new file mode 100644 index 0000000000..5b8147e5f2 --- /dev/null +++ b/protocols/Facebook/src/mqtt.h @@ -0,0 +1,61 @@ +/* + +Facebook plugin for Miranda NG +Copyright © 2019 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#pragma once + +#define FB_THRIFT_TYPE_STOP 0 +#define FB_THRIFT_TYPE_VOID 1 +#define FB_THRIFT_TYPE_BOOL 2 +#define FB_THRIFT_TYPE_BYTE 3 +#define FB_THRIFT_TYPE_DOUBLE 4 +#define FB_THRIFT_TYPE_I16 6 +#define FB_THRIFT_TYPE_I32 8 +#define FB_THRIFT_TYPE_I64 10 +#define FB_THRIFT_TYPE_STRING 11 +#define FB_THRIFT_TYPE_STRUCT 12 +#define FB_THRIFT_TYPE_MAP 13 +#define FB_THRIFT_TYPE_SET 14 +#define FB_THRIFT_TYPE_LIST 15 + +class FbThrift +{ + MBinBuffer m_buf; + +public: + FbThrift& operator<<(uint8_t); + FbThrift& operator<<(const char *); + + void writeBool(bool value); + void writeBuf(const void *pData, size_t cbLen); + void writeInt32(__int32 value); + void writeInt64(__int64 value); + void writeIntV(__int64 value); + void writeField(int type, int id); + void writeField(int type, int id, int lastid); +}; + +#define FB_MQTT_CONNECT_FLAG_CLR 0x0002 +#define FB_MQTT_CONNECT_FLAG_WILL 0x0004 +#define FB_MQTT_CONNECT_FLAG_QOS0 0x0000 +#define FB_MQTT_CONNECT_FLAG_QOS1 0x0008 +#define FB_MQTT_CONNECT_FLAG_QOS2 0x0010 +#define FB_MQTT_CONNECT_FLAG_RET 0x0020 +#define FB_MQTT_CONNECT_FLAG_PASS 0x0040 +#define FB_MQTT_CONNECT_FLAG_USER 0x0080 diff --git a/protocols/Facebook/src/proto.cpp b/protocols/Facebook/src/proto.cpp index 4ef785127d..a30b7c1ac1 100644 --- a/protocols/Facebook/src/proto.cpp +++ b/protocols/Facebook/src/proto.cpp @@ -23,17 +23,49 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. FacebookProto::FacebookProto(const char *proto_name, const wchar_t *username) : PROTO<FacebookProto>(proto_name, username) { - szDeviceID = getMStringA(DBKEY_DEVICE_ID); - if (szDeviceID.IsEmpty()) { + // to upgrade previous settings + if (getByte("Compatibility") < 1) { + setByte("Compatibility", 1); + delSetting(DBKEY_DEVICE_ID); + } + + m_szDeviceID = getMStringA(DBKEY_DEVICE_ID); + if (m_szDeviceID.IsEmpty()) { UUID deviceId; UuidCreate(&deviceId); RPC_CSTR szId; UuidToStringA(&deviceId, &szId); - szDeviceID = szId; - setString(DBKEY_DEVICE_ID, szDeviceID); + m_szDeviceID = szId; + setString(DBKEY_DEVICE_ID, m_szDeviceID); RpcStringFreeA(&szId); } + m_szClientID = getMStringA(DBKEY_CLIENT_ID); + if (m_szClientID.IsEmpty()) { + for (int i = 0; i < 20; i++) { + int c = rand() % 62; + if (c >= 0 && c < 26) + c += 'a'; + else if (c >= 26 && c < 52) + c += 'A' - 26; + else if (c >= 52 && c < 62) + c += '0' - 52; + m_szClientID.AppendChar(c); + } + setString(DBKEY_CLIENT_ID, m_szClientID); + } + + m_uid = _atoi64(getMStringA(DBKEY_ID)); + + // Create standard network connection + wchar_t descr[512]; + mir_snwprintf(descr, TranslateT("%s server connection"), m_tszUserName); + + NETLIBUSER nlu = {}; + nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE; + nlu.szSettingsModule = m_szModuleName; + nlu.szDescriptiveName.w = descr; + m_hNetlibUser = Netlib_RegisterUser(&nlu); } FacebookProto::~FacebookProto() @@ -43,3 +75,97 @@ FacebookProto::~FacebookProto() void FacebookProto::OnModulesLoaded() { } + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR FacebookProto::GetCaps(int type, MCONTACT) +{ + switch (type) { + case PFLAGNUM_1: + { + DWORD_PTR flags = PF1_IM | PF1_CHAT | PF1_SERVERCLIST | PF1_AUTHREQ | PF1_BASICSEARCH | PF1_SEARCHBYEMAIL | PF1_SEARCHBYNAME | PF1_ADDSEARCHRES; + + if (getByte(DBKEY_SET_MIRANDA_STATUS)) + return flags |= PF1_MODEMSG; + else + return flags |= PF1_MODEMSGRECV; + } + + case PFLAGNUM_2: + return PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE | PF2_IDLE; + + case PFLAGNUM_3: + if (getByte(DBKEY_SET_MIRANDA_STATUS)) + return PF2_ONLINE; // | PF2_SHORTAWAY; + else + return 0; + + case PFLAGNUM_4: + return PF4_NOCUSTOMAUTH | PF4_AVATARS | PF4_SUPPORTTYPING | PF4_NOAUTHDENYREASON | PF4_IMSENDOFFLINE | PF4_READNOTIFY; + + case PFLAG_MAXLENOFMESSAGE: + return FACEBOOK_MESSAGE_LIMIT; + + case PFLAG_UNIQUEIDTEXT: + return (INT_PTR) "Facebook ID"; + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int FacebookProto::SetStatus(int iNewStatus) +{ + if (iNewStatus != ID_STATUS_OFFLINE && IsStatusConnecting(m_iStatus)) { + debugLogA("=== Status is already connecting, no change"); + return 0; + } + + // Routing statuses not supported by Facebook + switch (iNewStatus) { + case ID_STATUS_ONLINE: + case ID_STATUS_AWAY: + case ID_STATUS_INVISIBLE: + case ID_STATUS_OFFLINE: + break; + + case ID_STATUS_NA: + iNewStatus = ID_STATUS_AWAY; + break; + default: + iNewStatus = getByte(DBKEY_MAP_STATUSES) ? ID_STATUS_INVISIBLE : ID_STATUS_AWAY; + break; + } + + if (m_iStatus == iNewStatus) { + debugLogA("=== Statuses are same, no change"); + return 0; + } + + m_invisible = (iNewStatus == ID_STATUS_INVISIBLE); + m_iDesiredStatus = iNewStatus; + + int iOldStatus = m_iStatus; + + // log off & free all resources + if (iNewStatus == ID_STATUS_OFFLINE) { + OnLoggedOut(); + + m_iStatus = ID_STATUS_OFFLINE; + } + else if (m_iStatus == ID_STATUS_OFFLINE) { // we gonna connect + debugLogA("*** Beginning SignOn process"); + + m_iStatus = ID_STATUS_CONNECTING; + + ForkThread(&FacebookProto::ServerThread); + } + else { + // SetServerStatus(iNewStatus); + + m_iStatus = iNewStatus; + } + + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)iOldStatus, m_iStatus); + return 0; +} diff --git a/protocols/Facebook/src/proto.h b/protocols/Facebook/src/proto.h index ed4342b773..aa8a9e60ab 100644 --- a/protocols/Facebook/src/proto.h +++ b/protocols/Facebook/src/proto.h @@ -20,20 +20,70 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #pragma once +#define FB_HOST_BAPI "https://b-api.facebook.com" + +#define FACEBOOK_MESSAGE_LIMIT 100000 + #include "../../../miranda-private-keys/Facebook/app_secret.h" class FacebookProto; struct AsyncHttpRequest : public MTHttpRequest<FacebookProto> { + struct Param + { + Param(const char *p1, const char *p2) : + key(p1), val(p2) + {} + + CMStringA key, val; + }; + OBJLIST<Param> params; + + AsyncHttpRequest(); + void CalcSig(); }; +AsyncHttpRequest *operator<<(AsyncHttpRequest *, const CHAR_PARAM &); +AsyncHttpRequest *operator<<(AsyncHttpRequest *, const INT_PARAM &); + +class JsonReply +{ + JSONNode *m_root = nullptr; + int m_errorCode = 0; + JSONNode *m_data = nullptr; + +public: + JsonReply(NETLIBHTTPREQUEST *); + ~JsonReply(); + + __forceinline JSONNode &data() const { return *m_data; } + __forceinline int error() const { return m_errorCode; } +}; + class FacebookProto : public PROTO<FacebookProto> { - AsyncHttpRequest* CreateGraphql(const char *szName, const char *szMethod); + AsyncHttpRequest* CreateRequest(const char *szName, const char *szMethod); + NETLIBHTTPREQUEST* ExecuteRequest(AsyncHttpRequest *pReq); + + // MQTT functions + void MqttOpen(); + + // internal data + CMStringA m_szDeviceID; // stored, GUID that identifies this miranda's account + CMStringA m_szClientID; // stored, random alphanumeric string of 20 chars + __int64 m_uid; // stored, Facebook user id + __int64 m_iMqttId; + + bool m_invisible; + bool m_bOnline; - CMStringA szDeviceID; + CMStringA m_szAuthToken; // calculated + + void OnLoggedOut(); + + void __cdecl ServerThread(void *); public: FacebookProto(const char *proto_name, const wchar_t *username); @@ -43,6 +93,10 @@ public: // PROTO_INTERFACE void OnModulesLoaded() override; + + INT_PTR GetCaps(int type, MCONTACT hContact) override; + + int SetStatus(int iNewStatus) override; }; struct CMPlugin : public ACCPROTOPLUGIN<FacebookProto> diff --git a/protocols/Facebook/src/server.cpp b/protocols/Facebook/src/server.cpp index e8387997e0..bcf2d2fdfe 100644 --- a/protocols/Facebook/src/server.cpp +++ b/protocols/Facebook/src/server.cpp @@ -20,29 +20,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "stdafx.h" -AsyncHttpRequest* FacebookProto::CreateGraphql(const char *szName, const char *szMethod) +void FacebookProto::OnLoggedOut() { - AsyncHttpRequest *pReq = new AsyncHttpRequest(); - pReq->requestType = REQUEST_POST; - pReq->szUrl = "https://graph.facebook.com/graphql"; - pReq << CHAR_PARAM("api_key", FB_APP_KEY) << CHAR_PARAM("device_id", szDeviceID) << CHAR_PARAM("fb_api_req_friendly_name", szName) - << CHAR_PARAM("format", "json") << CHAR_PARAM("method", szMethod); - - CMStringA szLocale = getMStringA(DBKEY_LOCALE); - if (szLocale.IsEmpty()) - szLocale = "en"; - pReq << CHAR_PARAM("locale", szLocale); - - unsigned int id; - Utils_GetRandom(&id, sizeof(id)); - id &= ~0x80000000; - pReq << INT_PARAM("queryid", id); - - return pReq; + m_bOnline = false; } -void AsyncHttpRequest::CalcSig() +///////////////////////////////////////////////////////////////////////////////////////// + +void FacebookProto::ServerThread(void *) { - CMStringA szSrc = m_szParam; - szSrc.Append(FB_APP_SECRET); + auto *pReq = CreateRequest("authenticate", "auth.login"); + pReq->m_szUrl = FB_HOST_BAPI "/method/auth.login"; + pReq << CHAR_PARAM("email", getMStringA("Email")) << CHAR_PARAM("password", getMStringA("Password")); + pReq->CalcSig(); + + JsonReply reply(ExecuteRequest(pReq)); + if (reply.error()) { +FAIL: + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_FAILED, (HANDLE)m_iStatus, m_iDesiredStatus); + + m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, m_iDesiredStatus); + } } diff --git a/protocols/Facebook/src/stdafx.h b/protocols/Facebook/src/stdafx.h index 0fe4dc69ce..dca99fc578 100644 --- a/protocols/Facebook/src/stdafx.h +++ b/protocols/Facebook/src/stdafx.h @@ -51,6 +51,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <m_gui.h> #include "db.h" +#include "mqtt.h" #include "proto.h" extern bool g_bMessageState; |