summaryrefslogtreecommitdiff
path: root/protocols/ICQ-WIM
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-11-22 18:34:05 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-11-22 18:34:05 +0300
commit2eb37fb6f496abec9da2e00bdf937abdcc4555bb (patch)
treefb6cb2b0a5ccddd575f70ef52e57b3dfcee7d91b /protocols/ICQ-WIM
parent635dfc08ff3eeab5cc44e47d9efb0935f7ed279a (diff)
fixes #2616 (support for stickers & file transfers in ICQ)
Diffstat (limited to 'protocols/ICQ-WIM')
-rw-r--r--protocols/ICQ-WIM/src/proto.h61
-rw-r--r--protocols/ICQ-WIM/src/server.cpp199
2 files changed, 144 insertions, 116 deletions
diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h
index 9bfb80c4a5..14527204fa 100644
--- a/protocols/ICQ-WIM/src/proto.h
+++ b/protocols/ICQ-WIM/src/proto.h
@@ -247,37 +247,38 @@ class CIcqProto : public PROTO<CIcqProto>
friend AsyncHttpRequest* operator <<(AsyncHttpRequest*, const AIMSID&);
- bool m_bOnline, m_bTerminated, m_bFirstBos;
- int m_iTimeShift;
-
- MCONTACT CheckOwnMessage(const CMStringA &reqId, const CMStringA &msgId, bool bRemove);
- void CheckPassword(void);
- void ConnectionFailed(int iReason, int iErrorCode = 0);
- void EmailNotification(const wchar_t *pwszText);
- void GetPermitDeny();
- wchar_t* GetUIN(MCONTACT hContact);
- void MarkAsRead(MCONTACT hContact);
- void MoveContactToGroup(MCONTACT hContact, const wchar_t *pwszGroup, const wchar_t *pwszNewGroup);
- bool RetrievePassword();
- void RetrieveUserHistory(MCONTACT, __int64 startMsgId, bool bCreateRead);
- void RetrieveUserInfo(MCONTACT = INVALID_CONTACT_ID);
- void SetServerStatus(int iNewStatus);
- void ShutdownSession(void);
- void StartSession(void);
-
- void CheckAvatarChange(MCONTACT hContact, const JSONNode&);
- void CheckLastId(MCONTACT hContact, const JSONNode&);
- void Json2int(MCONTACT, const JSONNode&, const char *szJson, const char *szSetting);
- void Json2string(MCONTACT, const JSONNode&, const char *szJson, const char *szSetting);
- MCONTACT ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact = -1);
- void ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &msg, bool bCreateRead, bool bLocalTime);
-
- void OnLoggedIn(void);
- void OnLoggedOut(void);
-
- mir_cs m_csMarkReadQueue;
+ bool m_bOnline, m_bTerminated, m_bFirstBos;
+ int m_iTimeShift;
+
+ MCONTACT CheckOwnMessage(const CMStringA &reqId, const CMStringA &msgId, bool bRemove);
+ void CheckPassword(void);
+ void ConnectionFailed(int iReason, int iErrorCode = 0);
+ void EmailNotification(const wchar_t *pwszText);
+ void GetPermitDeny();
+ wchar_t* GetUIN(MCONTACT hContact);
+ void MarkAsRead(MCONTACT hContact);
+ void MoveContactToGroup(MCONTACT hContact, const wchar_t *pwszGroup, const wchar_t *pwszNewGroup);
+ bool RetrievePassword();
+ void RetrieveUserHistory(MCONTACT, __int64 startMsgId, bool bCreateRead);
+ void RetrieveUserInfo(MCONTACT = INVALID_CONTACT_ID);
+ void SetServerStatus(int iNewStatus);
+ void ShutdownSession(void);
+ void StartSession(void);
+
+ void CheckAvatarChange(MCONTACT hContact, const JSONNode&);
+ IcqFileInfo* CheckFile(MCONTACT hContact, CMStringW &wszFileName, bool &bIsFile);
+ void CheckLastId(MCONTACT hContact, const JSONNode&);
+ void Json2int(MCONTACT, const JSONNode&, const char *szJson, const char *szSetting);
+ void Json2string(MCONTACT, const JSONNode&, const char *szJson, const char *szSetting);
+ MCONTACT ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact = -1);
+ void ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &msg, bool bCreateRead, bool bLocalTime);
+
+ void OnLoggedIn(void);
+ void OnLoggedOut(void);
+
+ mir_cs m_csMarkReadQueue;
LIST<IcqCacheItem> m_arMarkReadQueue;
- void SendMarkRead();
+ void SendMarkRead();
AsyncHttpRequest* UserInfoRequest(MCONTACT);
diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp
index 3c87ccb350..ff62ba3a7a 100644
--- a/protocols/ICQ-WIM/src/server.cpp
+++ b/protocols/ICQ-WIM/src/server.cpp
@@ -101,6 +101,55 @@ void CIcqProto::CheckPassword()
else StartSession();
}
+IcqFileInfo* CIcqProto::CheckFile(MCONTACT hContact, CMStringW &wszText, bool &bIsFile)
+{
+ CMStringW wszUrl(wszText.Mid(26));
+ int idx = wszUrl.Find(' ');
+ if (idx != -1)
+ wszUrl.Truncate(idx);
+
+ bIsFile = false;
+ IcqFileInfo *pFileInfo = nullptr;
+
+ // is it already downloaded sticker?
+ CMStringW wszLoadedPath(FORMAT, L"%s\\%S\\Stickers\\STK{%s}.png", VARSW(L"%miranda_avatarcache%").get(), m_szModuleName, wszUrl.c_str());
+ if (!_waccess(wszLoadedPath, 0)) {
+ pFileInfo = (IcqFileInfo *)this;
+ wszText.Format(L"STK{%s}", wszUrl.c_str());
+ }
+ else {
+ // download file info
+ CMStringA szUrl(FORMAT, ICQ_FILE_SERVER "/info/%S/", wszUrl.c_str());
+ auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, szUrl, &CIcqProto::OnFileInfo);
+ pReq->hContact = hContact;
+ pReq->pUserInfo = &pFileInfo;
+ pReq << CHAR_PARAM("aimsid", m_aimsid) << CHAR_PARAM("previews", "192,600,xlarge");
+ if (!ExecuteRequest(pReq))
+ return nullptr;
+
+ // is it a sticker?
+ if (pFileInfo->bIsSticker) {
+ if (ServiceExists(MS_SMILEYADD_LOADCONTACTSMILEYS)) {
+ auto *pNew = new AsyncHttpRequest(CONN_NONE, REQUEST_GET, pFileInfo->szUrl, &CIcqProto::OnGetSticker);
+ pNew->flags |= NLHRF_NODUMP | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT;
+ pNew->pUserInfo = wszUrl.GetBuffer();
+ pNew->AddHeader("Sec-Fetch-User", "?1");
+ pNew->AddHeader("Sec-Fetch-Site", "cross-site");
+ pNew->AddHeader("Sec-Fetch-Mode", "navigate");
+ if (!ExecuteRequest(pNew))
+ return nullptr;
+
+ wszText.Format(L"STK{%s}", wszUrl.c_str());
+ delete pFileInfo;
+ }
+ else wszText = TranslateT("SmileyAdd plugin required to support stickers");
+ }
+ else bIsFile = true;
+ }
+
+ return pFileInfo;
+}
+
void CIcqProto::CheckStatus()
{
time_t now = time(0);
@@ -403,6 +452,7 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo
}
int iMsgTime = (bLocalTime) ? time(0) : it["time"].as_int();
+ bool bIsOutgoing = it["outgoing"].as_bool(), bIsFileTransfer = false;
if (isChatRoom(hContact)) {
CMStringA reqId(it["reqId"].as_mstring());
@@ -411,6 +461,17 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo
CMStringW wszSender(it["chat"]["sender"].as_mstring());
CMStringW wszChatId(getMStringW(hContact, "ChatRoomID"));
+ if (!bCreateRead && !bIsOutgoing && wszText.Left(26) == L"https://files.icq.net/get/") {
+ auto *pFileInfo = CheckFile(hContact, wszText, bIsFileTransfer);
+ if (!pFileInfo)
+ return;
+
+ if (bIsFileTransfer) {
+ wszText = pFileInfo->szUrl;
+ delete pFileInfo;
+ }
+ }
+
GCEVENT gce = { m_szModuleName, 0, GC_EVENT_MESSAGE };
gce.pszID.w = wszChatId;
gce.dwFlags = GCEF_ADDTOLOG;
@@ -419,101 +480,67 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo
gce.time = iMsgTime;
gce.bIsMe = wszSender == m_szOwnId;
Chat_Event(&gce);
+ return;
+ }
+
+ // skip own messages, just set the server msgid
+ CMStringA reqId(it["reqId"].as_mstring());
+ if (CheckOwnMessage(reqId, szMsgId, true)) {
+ debugLogA("Skipping our own message %s", szMsgId.c_str());
+ return;
+ }
+
+ // ignore duplicates
+ MEVENT hDbEvent = db_event_getById(m_szModuleName, szMsgId);
+ if (hDbEvent != 0) {
+ debugLogA("Message %s already exists", szMsgId.c_str());
+ return;
}
- else {
- // skip own messages, just set the server msgid
- CMStringA reqId(it["reqId"].as_mstring());
- if (CheckOwnMessage(reqId, szMsgId, true))
- return;
- // ignore duplicates
- MEVENT hDbEvent = db_event_getById(m_szModuleName, szMsgId);
- if (hDbEvent != 0) {
- debugLogA("Message %s already exists", szMsgId.c_str());
+ // filter out file transfers
+ if (!bCreateRead && !bIsOutgoing && wszText.Left(26) == L"https://files.icq.net/get/") {
+ auto *pFileInfo = CheckFile(hContact, wszText, bIsFileTransfer);
+ if (!pFileInfo)
return;
- }
- // filter out file transfers
- bool bIsOutgoing = it["outgoing"].as_bool();
- if (!bCreateRead && !bIsOutgoing && wszText.Left(26) == L"https://files.icq.net/get/") {
- CMStringW wszUrl(wszText.Mid(26));
- int idx = wszUrl.Find(' ');
- if (idx != -1)
- wszUrl.Truncate(idx);
-
- // is it already downloaded sticker?
- CMStringW wszLoadedPath(FORMAT, L"%s\\%S\\Stickers\\STK{%s}.png", VARSW(L"%miranda_avatarcache%").get(), m_szModuleName, wszUrl.c_str());
- if (!_waccess(wszLoadedPath, 0))
- wszText.Format(L"STK{%s}", wszUrl.c_str());
- else {
- // download file info
- IcqFileInfo *pFileInfo = nullptr;
-
- CMStringA szUrl(FORMAT, ICQ_FILE_SERVER "/info/%S/", wszUrl.c_str());
- auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, szUrl, &CIcqProto::OnFileInfo);
- pReq->hContact = hContact;
- pReq->pUserInfo = &pFileInfo;
- pReq << CHAR_PARAM("aimsid", m_aimsid) << CHAR_PARAM("previews", "192,600,xlarge");
- if (!ExecuteRequest(pReq))
- return;
-
- // is it a sticker?
- if (pFileInfo->bIsSticker) {
- if (ServiceExists(MS_SMILEYADD_LOADCONTACTSMILEYS)) {
- auto *pNew = new AsyncHttpRequest(CONN_NONE, REQUEST_GET, pFileInfo->szUrl, &CIcqProto::OnGetSticker);
- pNew->flags |= NLHRF_NODUMP | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT;
- pNew->pUserInfo = wszUrl.GetBuffer();
- pNew->AddHeader("Sec-Fetch-User", "?1");
- pNew->AddHeader("Sec-Fetch-Site", "cross-site");
- pNew->AddHeader("Sec-Fetch-Mode", "navigate");
- if (!ExecuteRequest(pNew))
- return;
-
- wszText.Format(L"STK{%s}", wszUrl.c_str());
- delete pFileInfo;
- }
- else wszText = TranslateT("SmileyAdd plugin required to support stickers");
- }
- else {
- // detach a file transfer
- auto *ft = new IcqFileTransfer(hContact, pFileInfo->szUrl);
- ft->pfts.totalBytes = ft->pfts.currentFileSize = pFileInfo->dwFileSize;
- ft->pfts.szCurrentFile.w = ft->m_wszFileName.GetBuffer();
-
- PROTORECVFILE pre = {};
- pre.dwFlags = PRFF_UNICODE;
- pre.fileCount = 1;
- pre.timestamp = iMsgTime;
- pre.files.w = &ft->m_wszShortName;
- pre.descr.w = pFileInfo->wszDescr;
- pre.lParam = (LPARAM)ft;
- ProtoChainRecvFile(hContact, &pre);
-
- delete pFileInfo;
- return;
- }
- }
+ if (bIsFileTransfer) {
+ // convert a file info into Miranda's file transfer
+ auto *ft = new IcqFileTransfer(hContact, pFileInfo->szUrl);
+ ft->pfts.totalBytes = ft->pfts.currentFileSize = pFileInfo->dwFileSize;
+ ft->pfts.szCurrentFile.w = ft->m_wszFileName.GetBuffer();
+
+ PROTORECVFILE pre = {};
+ pre.dwFlags = PRFF_UNICODE;
+ pre.fileCount = 1;
+ pre.timestamp = iMsgTime;
+ pre.files.w = &ft->m_wszShortName;
+ pre.descr.w = pFileInfo->wszDescr;
+ pre.lParam = (LPARAM)ft;
+ ProtoChainRecvFile(hContact, &pre);
+
+ delete pFileInfo;
+ return;
}
+ }
- // suppress notifications for already loaded/processed messages
- __int64 storedLastId = getId(hContact, DB_KEY_LASTMSGID);
- if (msgId <= storedLastId) {
- debugLogA("Parsing old/processed message with id %lld < %lld, setting CR to true", msgId, storedLastId);
- bCreateRead = true;
- }
+ // suppress notifications for already loaded/processed messages
+ __int64 storedLastId = getId(hContact, DB_KEY_LASTMSGID);
+ if (msgId <= storedLastId) {
+ debugLogA("Parsing old/processed message with id %lld < %lld, setting CR to true", msgId, storedLastId);
+ bCreateRead = true;
+ }
- debugLogA("Adding message %d:%lld (CR=%d)", hContact, msgId, bCreateRead);
+ debugLogA("Adding message %d:%lld (CR=%d)", hContact, msgId, bCreateRead);
- ptrA szUtf(mir_utf8encodeW(wszText));
+ ptrA szUtf(mir_utf8encodeW(wszText));
- PROTORECVEVENT pre = {};
- if (bIsOutgoing) pre.flags |= PREF_SENT;
- if (bCreateRead) pre.flags |= PREF_CREATEREAD;
- pre.szMsgId = szMsgId;
- pre.timestamp = iMsgTime;
- pre.szMessage = szUtf;
- ProtoChainRecvMsg(hContact, &pre);
- }
+ PROTORECVEVENT pre = {};
+ if (bIsOutgoing) pre.flags |= PREF_SENT;
+ if (bCreateRead) pre.flags |= PREF_CREATEREAD;
+ pre.szMsgId = szMsgId;
+ pre.timestamp = iMsgTime;
+ pre.szMessage = szUtf;
+ ProtoChainRecvMsg(hContact, &pre);
}
bool CIcqProto::RefreshRobustToken()