diff options
author | George Hazan <george.hazan@gmail.com> | 2023-07-20 21:25:40 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2023-07-20 21:25:44 +0300 |
commit | 4eba326a2e8356a02a03ecd3f07c773132a3bd0e (patch) | |
tree | b9296783d5a6e2807708a86857788db894ef715e /protocols | |
parent | 507403f37d5418397d547045787753080d928faa (diff) |
fixes #3579 (ICQ: устаревают ссылки на оффлайновые файлы)
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/ICQ-WIM/ICQ-WIM.vcxproj | 1 | ||||
-rw-r--r-- | protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/avatars.cpp | 134 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.cpp | 17 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.h | 3 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/server.cpp | 82 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/stdafx.h | 4 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/utils.cpp | 127 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/version.h | 2 |
9 files changed, 209 insertions, 164 deletions
diff --git a/protocols/ICQ-WIM/ICQ-WIM.vcxproj b/protocols/ICQ-WIM/ICQ-WIM.vcxproj index 53677eedfa..43a019b110 100644 --- a/protocols/ICQ-WIM/ICQ-WIM.vcxproj +++ b/protocols/ICQ-WIM/ICQ-WIM.vcxproj @@ -26,6 +26,7 @@ <Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" /> </ImportGroup> <ItemGroup> + <ClCompile Include="src\avatars.cpp" /> <ClCompile Include="src\file.cpp" /> <ClCompile Include="src\groupchats.cpp" /> <ClCompile Include="src\groups.cpp" /> diff --git a/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters b/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters index d52897b648..39587e6cee 100644 --- a/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters +++ b/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters @@ -44,6 +44,9 @@ <ClCompile Include="src\file.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\avatars.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="src\http.h"> diff --git a/protocols/ICQ-WIM/src/avatars.cpp b/protocols/ICQ-WIM/src/avatars.cpp new file mode 100644 index 0000000000..c7576ca60c --- /dev/null +++ b/protocols/ICQ-WIM/src/avatars.cpp @@ -0,0 +1,134 @@ +/* +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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 version 2 +of the License. + +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" + +///////////////////////////////////////////////////////////////////////////////////////// +// Avatars + +void CIcqProto::GetAvatarFileName(MCONTACT hContact, wchar_t *pszDest, size_t cbLen) +{ + CMStringW wszPath(GetAvatarPath()); + wszPath += '\\'; + + CMStringW wszFileName(getMStringW(hContact, "IconId")); + const wchar_t *szFileType = ProtoGetAvatarExtension(getByte(hContact, "AvatarType", PA_FORMAT_PNG)); + wszPath.AppendFormat(L"%s%s", wszFileName.c_str(), szFileType); + + wcsncpy_s(pszDest, cbLen, wszPath, _TRUNCATE); +} + +INT_PTR __cdecl CIcqProto::GetAvatar(WPARAM wParam, LPARAM lParam) +{ + wchar_t *buf = (wchar_t *)wParam; + int size = (int)lParam; + if (buf == nullptr || size <= 0) + return -1; + + GetAvatarFileName(0, buf, size); + return 0; +} + +INT_PTR __cdecl CIcqProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam) +{ + switch (wParam) { + case AF_MAXSIZE: + ((POINT *)lParam)->x = -1; + ((POINT *)lParam)->y = -1; + return 0; + + case AF_FORMATSUPPORTED: // nobody + return 1; + + case AF_DELAYAFTERFAIL: + return 10 * 60 * 1000; + + case AF_ENABLED: + case AF_FETCHIFPROTONOTVISIBLE: + case AF_FETCHIFCONTACTOFFLINE: + return 1; + } + return 0; +} + +INT_PTR __cdecl CIcqProto::GetAvatarInfo(WPARAM, LPARAM lParam) +{ + PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION *)lParam; + + ptrW szIconId(getWStringA(pai->hContact, "IconId")); + if (szIconId == nullptr) { + debugLogA("No avatar"); + return GAIR_NOAVATAR; + } + + GetAvatarFileName(pai->hContact, pai->filename, _countof(pai->filename)); + pai->format = getByte(pai->hContact, "AvatarType", 0); + + if (::_waccess(pai->filename, 0) == 0) + return GAIR_SUCCESS; + + debugLogA("No avatar"); + return GAIR_NOAVATAR; +} + +INT_PTR __cdecl CIcqProto::SetAvatar(WPARAM, LPARAM lParam) +{ + wchar_t *pwszFileName = (wchar_t *)lParam; + + wchar_t wszOldName[MAX_PATH]; + GetAvatarFileName(0, wszOldName, _countof(wszOldName)); + _wremove(wszOldName); + + auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, ICQ_API_SERVER "/expressions/upload"); + pReq->m_szUrl.AppendFormat("?f=json&aimsid=%s&r=%s&type=largeBuddyIcon", mir_urlEncode(m_aimsid.c_str()).c_str(), pReq->m_reqId); + + if (pwszFileName == nullptr) + delSetting("AvatarHash"); + else { + int fileId = _wopen(pwszFileName, _O_RDONLY | _O_BINARY, _S_IREAD); + if (fileId < 0) { + delete pReq; + return 1; + } + + unsigned dwSize = (unsigned)_filelengthi64(fileId); + char *pData = (char *)mir_alloc(dwSize); + if (pData == nullptr) { + _close(fileId); + delete pReq; + return 2; + } + + _read(fileId, pData, dwSize); + _close(fileId); + + pReq->pData = pData; + pReq->dataLength = dwSize; + + int iAvatarType = ProtoGetBufferFormat(pData); + if (iAvatarType == PA_FORMAT_UNKNOWN) { + delete pReq; + delete pData; + return 3; + } + + pReq->AddHeader("Content-Type", ProtoGetAvatarMimeType(iAvatarType)); + } + Push(pReq); + + return 0; // TODO +} diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index a4b3207367..91db22a652 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -172,7 +172,7 @@ void CIcqProto::OnContactDeleted(MCONTACT hContact) void CIcqProto::OnCreateOfflineFile(DB::FILE_BLOB &blob, void *hTransfer)
{
if (auto *pFileInfo = (IcqFileInfo *)hTransfer) {
- blob.setUrl(pFileInfo->szUrl);
+ blob.setUrl(pFileInfo->szOrigUrl);
blob.setSize(pFileInfo->dwFileSize);
}
}
@@ -216,12 +216,15 @@ void __cdecl CIcqProto::OfflineFileThread(void *pParam) if (dbei && !strcmp(dbei.szModule, m_szModuleName) && dbei.eventType == EVENTTYPE_FILE) {
JSONNode root = JSONNode::parse((const char *)dbei.pBlob);
if (m_bOnline && root) {
- auto *pReq = new AsyncHttpRequest(CONN_NONE, REQUEST_GET, root["u"].as_string().c_str(), &CIcqProto::OnFileRecv);
- pReq->pUserInfo = ofd;
- pReq->AddHeader("Sec-Fetch-User", "?1");
- pReq->AddHeader("Sec-Fetch-Site", "cross-site");
- pReq->AddHeader("Sec-Fetch-Mode", "navigate");
- Push(pReq);
+ MCONTACT hContact = db_event_getContact(ofd->hDbEvent);
+ if (auto *pFileInfo = RetrieveFileInfo(hContact, fileText2url(root["u"].as_mstring()))) {
+ auto *pReq = new AsyncHttpRequest(CONN_NONE, REQUEST_GET, pFileInfo->szUrl, &CIcqProto::OnFileRecv);
+ pReq->pUserInfo = ofd;
+ pReq->AddHeader("Sec-Fetch-User", "?1");
+ pReq->AddHeader("Sec-Fetch-Site", "cross-site");
+ pReq->AddHeader("Sec-Fetch-Mode", "navigate");
+ Push(pReq);
+ }
return;
}
}
diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h index a10f27c065..edac303ac1 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -78,7 +78,7 @@ struct IcqFileInfo dwFileSize(dwSize)
{}
- CMStringA szUrl;
+ CMStringA szUrl, szOrigUrl;
CMStringW wszDescr;
uint32_t dwFileSize;
bool bIsSticker = false;
@@ -232,6 +232,7 @@ class CIcqProto : public PROTO<CIcqProto> void Json2string(MCONTACT, const JSONNode&, const char *szJson, const char *szSetting, bool bIsPartial);
MCONTACT ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact = INVALID_CONTACT_ID, bool bIsPartial = false);
void ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &msg, bool bCreateRead, bool bLocalTime);
+ IcqFileInfo* RetrieveFileInfo(MCONTACT hContact, const CMStringW &wszUrl);
int StatusFromPresence(const JSONNode &presence, MCONTACT hContact);
void ProcessStatus(IcqUser *pUser, int iStatus);
diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp index 6a1eb0cbef..625aba8612 100644 --- a/protocols/ICQ-WIM/src/server.cpp +++ b/protocols/ICQ-WIM/src/server.cpp @@ -160,50 +160,56 @@ void CIcqProto::OnFileInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) res[0]->bIsSticker = bIsSticker;
}
-IcqFileInfo* CIcqProto::CheckFile(MCONTACT hContact, CMStringW &wszText, bool &bIsFile)
+IcqFileInfo *CIcqProto::RetrieveFileInfo(MCONTACT hContact, const CMStringW &wszUrl)
{
- CMStringW wszUrl(wszText.Mid(26));
- int idx = wszUrl.Find(' ');
- if (idx != -1)
- wszUrl.Truncate(idx);
+ 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 nullptr;
+ return pFileInfo;
+}
+
+IcqFileInfo* CIcqProto::CheckFile(MCONTACT hContact, CMStringW &wszText, bool &bIsFile)
+{
bIsFile = false;
- IcqFileInfo *pFileInfo = nullptr;
+ CMStringW wszUrl(fileText2url(wszText));
// 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());
+ return (IcqFileInfo *)this;
}
- 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 && 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");
+
+ // download file info
+ auto *pFileInfo = RetrieveFileInfo(hContact, wszUrl);
+ if (!pFileInfo)
+ 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());
}
- else bIsFile = true;
+ else wszText = TranslateT("SmileyAdd plugin required to support stickers");
+ }
+ else {
+ pFileInfo->szOrigUrl = wszText;
+ bIsFile = true;
}
return pFileInfo;
@@ -522,10 +528,10 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo }
bool bIsOutgoing = it["outgoing"].as_bool(), bIsFileTransfer = false;
- IcqFileInfo *pFileInfo = nullptr;
+ std::unique_ptr<IcqFileInfo> pFileInfo = nullptr;
if (!bCreateRead && !bIsOutgoing && wszText.Left(26) == L"https://files.icq.net/get/") {
- pFileInfo = CheckFile(hContact, wszText, bIsFileTransfer);
+ pFileInfo.reset(CheckFile(hContact, wszText, bIsFileTransfer));
if (!pFileInfo) {
debugLogA("Some shit happened, report this case to developers");
return;
@@ -571,10 +577,8 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo pre.timestamp = iMsgTime;
pre.files.w = &m_wszShortName;
pre.descr.w = pFileInfo->wszDescr;
- pre.lParam = (LPARAM)pFileInfo;
+ pre.lParam = (LPARAM)pFileInfo.release();
ProtoChainRecvFile(hContact, &pre);
-
- delete pFileInfo;
return;
}
diff --git a/protocols/ICQ-WIM/src/stdafx.h b/protocols/ICQ-WIM/src/stdafx.h index b45810a867..e6b9d0020b 100644 --- a/protocols/ICQ-WIM/src/stdafx.h +++ b/protocols/ICQ-WIM/src/stdafx.h @@ -32,6 +32,8 @@ // Windows includes
#include <windows.h>
+#include <memory>
+
// Standard includes
#include <stdio.h>
#include <time.h>
@@ -106,4 +108,6 @@ bool IsValidType(const JSONNode &aimid); void RefreshGroups(void);
wchar_t* time2text(time_t time);
+CMStringW fileText2url(const CMStringW &wszText);
+
extern bool g_bSecureIM, g_bMessageState;
diff --git a/protocols/ICQ-WIM/src/utils.cpp b/protocols/ICQ-WIM/src/utils.cpp index 5adde04e81..fbe99c6ad6 100644 --- a/protocols/ICQ-WIM/src/utils.cpp +++ b/protocols/ICQ-WIM/src/utils.cpp @@ -148,122 +148,6 @@ void CIcqProto::Json2string(MCONTACT hContact, const JSONNode &node, const char }
/////////////////////////////////////////////////////////////////////////////////////////
-// Avatars
-
-void CIcqProto::GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t cbLen)
-{
- CMStringW wszPath(GetAvatarPath());
- wszPath += '\\';
-
- CMStringW wszFileName(getMStringW(hContact, "IconId"));
- const wchar_t* szFileType = ProtoGetAvatarExtension(getByte(hContact, "AvatarType", PA_FORMAT_PNG));
- wszPath.AppendFormat(L"%s%s", wszFileName.c_str(), szFileType);
-
- wcsncpy_s(pszDest, cbLen, wszPath, _TRUNCATE);
-}
-
-INT_PTR __cdecl CIcqProto::GetAvatar(WPARAM wParam, LPARAM lParam)
-{
- wchar_t *buf = (wchar_t*)wParam;
- int size = (int)lParam;
- if (buf == nullptr || size <= 0)
- return -1;
-
- GetAvatarFileName(0, buf, size);
- return 0;
-}
-
-INT_PTR __cdecl CIcqProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
-{
- switch (wParam) {
- case AF_MAXSIZE:
- ((POINT*)lParam)->x = -1;
- ((POINT*)lParam)->y = -1;
- return 0;
-
- case AF_FORMATSUPPORTED: // nobody
- return 1;
-
- case AF_DELAYAFTERFAIL:
- return 10 * 60 * 1000;
-
- case AF_ENABLED:
- case AF_FETCHIFPROTONOTVISIBLE:
- case AF_FETCHIFCONTACTOFFLINE:
- return 1;
- }
- return 0;
-}
-
-INT_PTR __cdecl CIcqProto::GetAvatarInfo(WPARAM, LPARAM lParam)
-{
- PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam;
-
- ptrW szIconId(getWStringA(pai->hContact, "IconId"));
- if (szIconId == nullptr) {
- debugLogA("No avatar");
- return GAIR_NOAVATAR;
- }
-
- GetAvatarFileName(pai->hContact, pai->filename, _countof(pai->filename));
- pai->format = getByte(pai->hContact, "AvatarType", 0);
-
- if (::_waccess(pai->filename, 0) == 0)
- return GAIR_SUCCESS;
-
- debugLogA("No avatar");
- return GAIR_NOAVATAR;
-}
-
-INT_PTR __cdecl CIcqProto::SetAvatar(WPARAM, LPARAM lParam)
-{
- wchar_t* pwszFileName = (wchar_t*)lParam;
-
- wchar_t wszOldName[MAX_PATH];
- GetAvatarFileName(0, wszOldName, _countof(wszOldName));
- _wremove(wszOldName);
-
- auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, ICQ_API_SERVER "/expressions/upload");
- pReq->m_szUrl.AppendFormat("?f=json&aimsid=%s&r=%s&type=largeBuddyIcon", mir_urlEncode(m_aimsid.c_str()).c_str(), pReq->m_reqId);
-
- if (pwszFileName == nullptr)
- delSetting("AvatarHash");
- else {
- int fileId = _wopen(pwszFileName, _O_RDONLY | _O_BINARY, _S_IREAD);
- if (fileId < 0) {
- delete pReq;
- return 1;
- }
-
- unsigned dwSize = (unsigned)_filelengthi64(fileId);
- char* pData = (char*)mir_alloc(dwSize);
- if (pData == nullptr) {
- _close(fileId);
- delete pReq;
- return 2;
- }
-
- _read(fileId, pData, dwSize);
- _close(fileId);
-
- pReq->pData = pData;
- pReq->dataLength = dwSize;
-
- int iAvatarType = ProtoGetBufferFormat(pData);
- if (iAvatarType == PA_FORMAT_UNKNOWN) {
- delete pReq;
- delete pData;
- return 3;
- }
-
- pReq->AddHeader("Content-Type", ProtoGetAvatarMimeType(iAvatarType));
- }
- Push(pReq);
-
- return 0; // TODO
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
CMStringW CIcqProto::GetUserId(MCONTACT hContact)
{
@@ -361,6 +245,17 @@ void CIcqProto::setId(MCONTACT hContact, const char *szSetting, __int64 iValue) /////////////////////////////////////////////////////////////////////////////////////////
+CMStringW fileText2url(const CMStringW &wszText)
+{
+ CMStringW wszUrl(wszText.Mid(26));
+ int idx = wszUrl.Find(' ');
+ if (idx != -1)
+ wszUrl.Truncate(idx);
+ return wszUrl;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
wchar_t* time2text(time_t ts)
{
if (ts == 0)
diff --git a/protocols/ICQ-WIM/src/version.h b/protocols/ICQ-WIM/src/version.h index 13d762b563..bc77648b0b 100644 --- a/protocols/ICQ-WIM/src/version.h +++ b/protocols/ICQ-WIM/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0
#define __MINOR_VERSION 96
#define __RELEASE_NUM 3
-#define __BUILD_NUM 3
+#define __BUILD_NUM 4
#include <stdver.h>
|