summaryrefslogtreecommitdiff
path: root/protocols/ICQ-WIM
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-02-06 15:30:02 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-02-06 15:30:16 +0300
commit194edfc6fdf27874e51b3ac9c8c439adfcac3c6d (patch)
tree3ee0deb65d577bf825eb8f232b9ec00f6806a802 /protocols/ICQ-WIM
parentbe0f3de3ea7da8c4e171620eee9c7220f5549952 (diff)
fixes #1809 (ICQ10: client detection)
Diffstat (limited to 'protocols/ICQ-WIM')
-rw-r--r--protocols/ICQ-WIM/src/poll.cpp2
-rw-r--r--protocols/ICQ-WIM/src/proto.h11
-rw-r--r--protocols/ICQ-WIM/src/server.cpp42
3 files changed, 50 insertions, 5 deletions
diff --git a/protocols/ICQ-WIM/src/poll.cpp b/protocols/ICQ-WIM/src/poll.cpp
index 4b31779393..7360544ec5 100644
--- a/protocols/ICQ-WIM/src/poll.cpp
+++ b/protocols/ICQ-WIM/src/poll.cpp
@@ -57,6 +57,8 @@ void CIcqProto::ProcessBuddyList(const JSONNode &ev)
for (auto &it : m_arCache)
if (!it->m_bInList)
db_set_b(it->m_hContact, "CList", "NotOnList", 1);
+
+ RetrieveUserInfo();
}
void CIcqProto::ProcessDiff(const JSONNode &ev)
diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h
index c9fb72f146..7bae6ec031 100644
--- a/protocols/ICQ-WIM/src/proto.h
+++ b/protocols/ICQ-WIM/src/proto.h
@@ -37,6 +37,15 @@
#define ICQ_API_SERVER "https://api.icq.net"
#define ICQ_ROBUST_SERVER "https://rapi.icq.net"
+#define WIM_CAP_VOIP_VOICE "094613504c7f11d18222444553540000"
+#define WIM_CAP_VOIP_VIDEO "094613514c7f11d18222444553540000"
+#define WIM_CAP_FILETRANSFER "094613434c7f11d18222444553540000"
+#define WIM_CAP_UNIQ_REQ_ID "094613534c7f11d18222444553540000"
+#define WIM_CAP_EMOJI "094613544c7f11d18222444553540000"
+#define WIM_CAP_MENTIONS "0946135b4c7f11d18222444553540000"
+#define WIM_CAP_MAIL_NOTIFICATIONS "094613594c7f11d18222444553540000"
+#define WIM_CAP_INTRO_DLG_STATE "0946135a4c7f11d18222444553540000"
+
typedef CProtoDlgBase<CIcqProto> CIcqDlgBase;
enum ChatMenuItems
@@ -141,7 +150,7 @@ class CIcqProto : public PROTO<CIcqProto>
void GetPermitDeny();
void MoveContactToGroup(MCONTACT hContact, const wchar_t *pwszGroup, const wchar_t *pwszNewGroup);
void RetrieveUserHistory(MCONTACT, __int64 startMsgId, __int64 endMsgId = -1);
- void RetrieveUserInfo(MCONTACT);
+ void RetrieveUserInfo(MCONTACT = INVALID_CONTACT_ID);
void SetServerStatus(int iNewStatus);
void ShutdownSession(void);
void StartSession(void);
diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp
index 9c0c199c8a..6f28fbdc3e 100644
--- a/protocols/ICQ-WIM/src/server.cpp
+++ b/protocols/ICQ-WIM/src/server.cpp
@@ -231,6 +231,30 @@ MCONTACT CIcqProto::ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact)
FindContactByUIN(dwUin)->m_bInList = true;
}
+ bool bVersionDetected = false;
+ for (auto &it : buddy["capabilities"]) {
+ CMStringW wszCap(it.as_mstring());
+ if (wszCap.GetLength() != 32)
+ continue;
+
+ BYTE cap[16];
+ hex2binW(wszCap, cap, sizeof(cap));
+ if (!memcmp(cap, "MiNG", 4)) { // Miranda
+ int v[4];
+ swscanf(wszCap.c_str() + 16, L"%04x%04x%04x%04x", &v[0], &v[1], &v[2], &v[3]);
+ CMStringA szVer(FORMAT, "Miranda NG %d.%d.%d.%d (ICQ %d.%d.%d.%d)", v[0], v[1], v[2], v[3], cap[4], cap[5], cap[6], cap[7]);
+ setString(hContact, "MirVer", szVer);
+ bVersionDetected = true;
+ }
+ else if (!memcmp(cap, "Mod by Mikanoshi", 16)) {
+ setString(hContact, "MirVer", "R&Q build by Mikanoshi");
+ bVersionDetected = true;
+ }
+ }
+
+ if (!bVersionDetected)
+ delSetting(hContact, "MirVer");
+
CMStringW str(buddy["state"].as_mstring());
setDword(hContact, "Status", StatusFromString(str));
@@ -405,7 +429,13 @@ void CIcqProto::RetrieveUserInfo(MCONTACT hContact)
auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, ICQ_API_SERVER "/presence/get", &CIcqProto::OnGetUserInfo);
pReq->flags |= NLHRF_NODUMPSEND;
pReq->hContact = hContact;
- pReq << CHAR_PARAM("f", "json") << CHAR_PARAM("aimsid", m_aimsid) << INT_PARAM("mdir", 1) << CHAR_PARAM("t", GetUserId(hContact));
+ pReq << CHAR_PARAM("f", "json") << CHAR_PARAM("aimsid", m_aimsid) << INT_PARAM("mdir", 1) << INT_PARAM("capabilities", 1);
+ if (hContact == INVALID_CONTACT_ID)
+ for (auto &it : m_arCache)
+ pReq << CHAR_PARAM("t", GetUserId(it->m_hContact));
+ else
+ pReq << CHAR_PARAM("t", GetUserId(hContact));
+
Push(pReq);
}
@@ -478,7 +508,6 @@ void CIcqProto::ShutdownSession()
/////////////////////////////////////////////////////////////////////////////////////////
-#define CAPS "094613504c7f11d18222444553540000,094613514c7f11d18222444553540000,094613534c7f11d18222444553540000,094613544c7f11d18222444553540000,094613594c7f11d18222444553540000,0946135b4c7f11d18222444553540000,0946135a4c7f11d18222444553540000"
#define EVENTS "myInfo,presence,buddylist,typing,dataIM,userAddedToBuddyList,mchat,hist,hiddenChat,diff,permitDeny,imState,notification,apps"
#define FIELDS "aimId,buddyIcon,bigBuddyIcon,iconId,bigIconId,largeIconId,displayId,friendly,offlineMsg,state,statusMsg,userType,phoneNumber,cellNumber,smsNumber,workNumber,otherNumber,capabilities,ssl,abPhoneNumber,moodIcon,lastName,abPhones,abContactName,lastseen,mute,livechat,official"
@@ -497,10 +526,15 @@ void CIcqProto::StartSession()
int ts = time(0);
CMStringA nonce(FORMAT, "%d-2", ts);
+ CMStringA caps(WIM_CAP_UNIQ_REQ_ID "," WIM_CAP_EMOJI "," WIM_CAP_MAIL_NOTIFICATIONS "," WIM_CAP_INTRO_DLG_STATE);
- auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, ICQ_API_SERVER "/aim/startSession", &CIcqProto::OnStartSession);
+ MFileVersion v;
+ Miranda_GetFileVersion(&v);
+ caps.AppendFormat(",%02x%02x%02x%02x%02x%02x%02x%02x%04x%04x%04x%04x", 'M', 'i', 'N', 'G',
+ __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM, v[0], v[1], v[2], v[3]);
- pReq << CHAR_PARAM("a", m_szAToken) << INT_PARAM("activeTimeout", 180) << CHAR_PARAM("assertCaps", CAPS)
+ auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, ICQ_API_SERVER "/aim/startSession", &CIcqProto::OnStartSession);
+ pReq << CHAR_PARAM("a", m_szAToken) << INT_PARAM("activeTimeout", 180) << CHAR_PARAM("assertCaps", caps)
<< INT_PARAM("buildNumber", __BUILD_NUM) << CHAR_PARAM("deviceId", szDeviceId) << CHAR_PARAM("events", EVENTS)
<< CHAR_PARAM("f", "json") << CHAR_PARAM("imf", "plain") << CHAR_PARAM("inactiveView", "offline")
<< CHAR_PARAM("includePresenceFields", FIELDS) << CHAR_PARAM("invisible", "false")