From 4bf93234f7f2b3dfe0a0ac968ca22b8a0d19c046 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 9 Jul 2023 21:01:10 +0300 Subject: fixes #3552 (ICQ: crash on cancel waiting filetransfer) --- protocols/ICQ-WIM/ICQ-WIM.vcxproj | 1 + protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters | 3 ++ protocols/ICQ-WIM/src/file.cpp | 78 +++++++++++++++++++++++++++++++ protocols/ICQ-WIM/src/proto.cpp | 3 +- protocols/ICQ-WIM/src/proto.h | 64 +++---------------------- 5 files changed, 91 insertions(+), 58 deletions(-) create mode 100644 protocols/ICQ-WIM/src/file.cpp (limited to 'protocols') diff --git a/protocols/ICQ-WIM/ICQ-WIM.vcxproj b/protocols/ICQ-WIM/ICQ-WIM.vcxproj index e9b9f8c37e..53677eedfa 100644 --- a/protocols/ICQ-WIM/ICQ-WIM.vcxproj +++ b/protocols/ICQ-WIM/ICQ-WIM.vcxproj @@ -26,6 +26,7 @@ + diff --git a/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters b/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters index 62171a5720..d52897b648 100644 --- a/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters +++ b/protocols/ICQ-WIM/ICQ-WIM.vcxproj.filters @@ -41,6 +41,9 @@ Source Files + + Source Files + diff --git a/protocols/ICQ-WIM/src/file.cpp b/protocols/ICQ-WIM/src/file.cpp new file mode 100644 index 0000000000..76b55026f9 --- /dev/null +++ b/protocols/ICQ-WIM/src/file.cpp @@ -0,0 +1,78 @@ +/* +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 . +*/ + +#include "stdafx.h" + +// create an object for receiving +IcqFileTransfer::IcqFileTransfer(MCONTACT hContact, const char *pszUrl) : + m_szHost(pszUrl) +{ + pfts.hContact = hContact; + pfts.totalFiles = 1; + pfts.flags = PFTS_UNICODE | PFTS_RECEIVING; + + ptrW pwszFileName(mir_utf8decodeW(pszUrl)); + if (pwszFileName == nullptr) + pwszFileName = mir_a2u(pszUrl); + + const wchar_t *p = wcsrchr(pwszFileName, '/'); + m_wszFileName = (p == nullptr) ? pwszFileName : p + 1; + m_wszShortName = m_wszFileName; +} + +// create an object for sending +IcqFileTransfer::IcqFileTransfer(MCONTACT hContact, const wchar_t *pwszFileName) : + m_wszFileName(pwszFileName) +{ + pfts.flags = PFTS_UNICODE | PFTS_SENDING; + pfts.hContact = hContact; + pfts.szCurrentFile.w = m_wszFileName.GetBuffer(); + + const wchar_t *p = wcsrchr(pfts.szCurrentFile.w, '\\'); + if (pwszFileName != nullptr) + p++; + else + p = pfts.szCurrentFile.w; + m_wszShortName = p; +} + +IcqFileTransfer::~IcqFileTransfer() +{ + if (m_fileId >= 0) + _close(m_fileId); +} + +void IcqFileTransfer::FillHeaders(AsyncHttpRequest *pReq) +{ + pReq->AddHeader("Content-Type", "application/octet-stream"); + pReq->AddHeader("Content-Disposition", CMStringA(FORMAT, "attachment; filename=\"%s\"", T2Utf(m_wszShortName).get())); + + uint32_t dwPortion = pfts.currentFileSize - pfts.currentFileProgress; + if (dwPortion > 1000000) + dwPortion = 1000000; + + pReq->AddHeader("Content-Range", CMStringA(FORMAT, "bytes %lld-%lld/%lld", pfts.currentFileProgress, pfts.currentFileProgress + dwPortion - 1, pfts.currentFileSize)); + pReq->AddHeader("Content-Length", CMStringA(FORMAT, "%d", dwPortion)); + + pReq->dataLength = dwPortion; + pReq->pData = (char *)mir_alloc(dwPortion); + _lseek(m_fileId, pfts.currentFileProgress, SEEK_SET); + _read(m_fileId, pReq->pData, dwPortion); + + pfts.currentFileProgress += dwPortion; + pfts.totalProgress += dwPortion; +} diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index 83fb342dec..9cade4f8d9 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -351,6 +351,7 @@ HANDLE CIcqProto::FileAllow(MCONTACT, HANDLE hTransfer, const wchar_t *pwszSaveP auto *ft = (IcqFileTransfer *)hTransfer; ft->m_wszFileName.Insert(0, pwszSavePath); ft->pfts.szCurrentFile.w = ft->m_wszFileName.GetBuffer(); + ft->Acquire(); auto *pReq = new AsyncHttpRequest(CONN_NONE, REQUEST_GET, ft->m_szHost, &CIcqProto::OnFileRecv); pReq->pUserInfo = ft; @@ -370,7 +371,7 @@ int CIcqProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) if (ft->pfts.currentFileTime != 0) ft->m_bCanceled = true; else - delete ft; + ft->Release(); return 0; } diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h index 307e3482cd..b7cac8f5c4 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -144,47 +144,8 @@ struct IcqConn int lastTs, timeout; }; -struct IcqFileTransfer : public MZeroedObject +struct IcqFileTransfer : public MZeroedObject, public MShareable { - // create an object for receiving - IcqFileTransfer(MCONTACT hContact, const char *pszUrl) : - m_szHost(pszUrl) - { - pfts.hContact = hContact; - pfts.totalFiles = 1; - pfts.flags = PFTS_UNICODE | PFTS_RECEIVING; - - ptrW pwszFileName(mir_utf8decodeW(pszUrl)); - if (pwszFileName == nullptr) - pwszFileName = mir_a2u(pszUrl); - - const wchar_t *p = wcsrchr(pwszFileName, '/'); - m_wszFileName = (p == nullptr) ? pwszFileName : p + 1; - m_wszShortName = m_wszFileName; - } - - // create an object for sending - IcqFileTransfer(MCONTACT hContact, const wchar_t *pwszFileName) : - m_wszFileName(pwszFileName) - { - pfts.flags = PFTS_UNICODE | PFTS_SENDING; - pfts.hContact = hContact; - pfts.szCurrentFile.w = m_wszFileName.GetBuffer(); - - const wchar_t *p = wcsrchr(pfts.szCurrentFile.w, '\\'); - if (pwszFileName != nullptr) - p++; - else - p = pfts.szCurrentFile.w; - m_wszShortName = p; - } - - ~IcqFileTransfer() - { - if (m_fileId >= 0) - _close(m_fileId); - } - bool m_bCanceled = false, m_bStarted = false; int m_fileId = -1; CMStringA m_szHost; @@ -193,26 +154,15 @@ struct IcqFileTransfer : public MZeroedObject PROTOFILETRANSFERSTATUS pfts; HANDLE hWaitEvent; - void FillHeaders(AsyncHttpRequest *pReq) - { - pReq->AddHeader("Content-Type", "application/octet-stream"); - pReq->AddHeader("Content-Disposition", CMStringA(FORMAT, "attachment; filename=\"%s\"", T2Utf(m_wszShortName).get())); - - uint32_t dwPortion = pfts.currentFileSize - pfts.currentFileProgress; - if (dwPortion > 1000000) - dwPortion = 1000000; + // create an object for receiving + IcqFileTransfer(MCONTACT hContact, const char *pszUrl); - pReq->AddHeader("Content-Range", CMStringA(FORMAT, "bytes %lld-%lld/%lld", pfts.currentFileProgress, pfts.currentFileProgress + dwPortion - 1, pfts.currentFileSize)); - pReq->AddHeader("Content-Length", CMStringA(FORMAT, "%d", dwPortion)); + // create an object for sending + IcqFileTransfer(MCONTACT hContact, const wchar_t *pwszFileName); - pReq->dataLength = dwPortion; - pReq->pData = (char*)mir_alloc(dwPortion); - _lseek(m_fileId, pfts.currentFileProgress, SEEK_SET); - _read(m_fileId, pReq->pData, dwPortion); + ~IcqFileTransfer() override; - pfts.currentFileProgress += dwPortion; - pfts.totalProgress += dwPortion; - } + void FillHeaders(AsyncHttpRequest *pReq); }; class CIcqProto : public PROTO -- cgit v1.2.3