From 226427505784cb0db153e44baa45d1b7d028aff9 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 31 Mar 2020 14:44:40 +0300 Subject: Jabber: - fixes #2279 (Jabber: add HTTP File Upload support for group chats); - major file transfer code cleaning; --- protocols/JabberG/src/jabber_byte.cpp | 10 +-- protocols/JabberG/src/jabber_byte.h | 2 +- protocols/JabberG/src/jabber_chat.cpp | 14 +-- protocols/JabberG/src/jabber_events.cpp | 2 +- protocols/JabberG/src/jabber_file.cpp | 7 +- protocols/JabberG/src/jabber_ft.cpp | 130 ++++++++++++++++----------- protocols/JabberG/src/jabber_groupchat.cpp | 14 +++ protocols/JabberG/src/jabber_ibb.cpp | 4 +- protocols/JabberG/src/jabber_ibb.h | 2 +- protocols/JabberG/src/jabber_iq_handlers.cpp | 2 +- protocols/JabberG/src/jabber_list.cpp | 37 +------- protocols/JabberG/src/jabber_privacy.cpp | 5 +- protocols/JabberG/src/jabber_proto.cpp | 50 +++-------- protocols/JabberG/src/jabber_proto.h | 11 +-- protocols/JabberG/src/stdafx.h | 7 +- 15 files changed, 136 insertions(+), 161 deletions(-) (limited to 'protocols/JabberG/src') diff --git a/protocols/JabberG/src/jabber_byte.cpp b/protocols/JabberG/src/jabber_byte.cpp index 0a1f24e297..1103a5e49b 100644 --- a/protocols/JabberG/src/jabber_byte.cpp +++ b/protocols/JabberG/src/jabber_byte.cpp @@ -176,7 +176,7 @@ void CJabberProto::ByteSendThread(JABBER_BYTE_TRANSFER *jbt) debugLogA("Bytestream proxy failure"); MsgPopup(pInfo->GetHContact(), TranslateT("Bytestream Proxy not available"), _A2T(proxyJid)); jbt->ft->state = FT_DENIED; - (this->*jbt->pfnFinal)(FALSE, jbt->ft); + (this->*jbt->pfnFinal)(false, jbt->ft); jbt->ft = nullptr; delete jbt; return; @@ -256,7 +256,7 @@ void CJabberProto::ByteSendThread(JABBER_BYTE_TRANSFER *jbt) jbt->hConn = nullptr; ListRemove(LIST_BYTE, szPort); } - (this->*jbt->pfnFinal)((jbt->state == JBT_DONE) ? TRUE : FALSE, jbt->ft); + (this->*jbt->pfnFinal)(jbt->state == JBT_DONE, jbt->ft); jbt->ft = nullptr; // stupid fix: wait for listening thread exit Sleep(100); @@ -284,7 +284,7 @@ void CJabberProto::ByteSendThread(JABBER_BYTE_TRANSFER *jbt) CloseHandle(hEvent); CloseHandle(jbt->hSendEvent); jbt->hEvent = nullptr; - (this->*jbt->pfnFinal)((jbt->state == JBT_DONE) ? TRUE : FALSE, jbt->ft); + (this->*jbt->pfnFinal)(jbt->state == JBT_DONE, jbt->ft); jbt->ft = nullptr; if (jbt->hConn != nullptr) Netlib_CloseHandle(jbt->hConn); @@ -472,7 +472,7 @@ void CJabberProto::ByteSendViaProxy(JABBER_BYTE_TRANSFER *jbt) Netlib_CloseHandle(hConn); } mir_free(buffer); - (this->*jbt->pfnFinal)((jbt->state == JBT_DONE) ? TRUE : FALSE, jbt->ft); + (this->*jbt->pfnFinal)(jbt->state == JBT_DONE, jbt->ft); jbt->ft = nullptr; if (!validStreamhost) m_ThreadInfo->send(XmlNodeIq("error", jbt->iqId, jbt->srcJID) @@ -653,7 +653,7 @@ void __cdecl CJabberProto::ByteReceiveThread(JABBER_BYTE_TRANSFER *jbt) } } - (this->*jbt->pfnFinal)((jbt->state == JBT_DONE) ? TRUE : FALSE, jbt->ft); + (this->*jbt->pfnFinal)(jbt->state == JBT_DONE, jbt->ft); jbt->ft = nullptr; if (!validStreamhost && szId && from) { debugLogA("bytestream_recv_connection session not completed"); diff --git a/protocols/JabberG/src/jabber_byte.h b/protocols/JabberG/src/jabber_byte.h index d2308214ef..a8bab12416 100644 --- a/protocols/JabberG/src/jabber_byte.h +++ b/protocols/JabberG/src/jabber_byte.h @@ -47,7 +47,7 @@ struct JABBER_BYTE_TRANSFER : public MZeroedObject TiXmlElement *iqNode; bool (CJabberProto::*pfnSend)(HNETLIBCONN hConn, filetransfer *ft); int (CJabberProto::*pfnRecv)(HNETLIBCONN hConn, filetransfer *ft, char* buffer, int datalen); - void (CJabberProto::*pfnFinal)(BOOL success, filetransfer *ft); + void (CJabberProto::*pfnFinal)(bool success, filetransfer *ft); filetransfer *ft; // XEP-0065 proxy support diff --git a/protocols/JabberG/src/jabber_chat.cpp b/protocols/JabberG/src/jabber_chat.cpp index 1b07311a7e..3da6353f19 100644 --- a/protocols/JabberG/src/jabber_chat.cpp +++ b/protocols/JabberG/src/jabber_chat.cpp @@ -1374,18 +1374,8 @@ int CJabberProto::JabberGcEventHook(WPARAM, LPARAM lParam) case GC_USER_MESSAGE: if (gch->ptszText && mir_wstrlen(gch->ptszText) > 0) { rtrimw(gch->ptszText); - - if (m_bJabberOnline) { - char szId[100]; - int64_t id = (_time64(nullptr) << 16) + (GetTickCount() & 0xFFFF); - _i64toa(id, szId, 36); - - wchar_t *buf = NEWWSTR_ALLOCA(gch->ptszText); - Chat_UnescapeTags(buf); - m_ThreadInfo->send( - XmlNode("message") << XATTR("id", szId) << XATTR("to", item->jid) << XATTR("type", "groupchat") - << XCHILD("body", T2Utf(buf))); - } + Chat_UnescapeTags(gch->ptszText); + GroupchatSendMsg(item, T2Utf(gch->ptszText)); } break; diff --git a/protocols/JabberG/src/jabber_events.cpp b/protocols/JabberG/src/jabber_events.cpp index 23c2d1e931..3285ab91a1 100644 --- a/protocols/JabberG/src/jabber_events.cpp +++ b/protocols/JabberG/src/jabber_events.cpp @@ -36,7 +36,7 @@ void CJabberProto::OnContactDeleted(MCONTACT hContact) if (!m_bJabberOnline) // should never happen return; - ptrA jid(getUStringA(hContact, isChatRoom(hContact) ? "ChatRoomID" : "jid")); + ptrA jid(ContactToJID(hContact)); if (jid == nullptr) return; diff --git a/protocols/JabberG/src/jabber_file.cpp b/protocols/JabberG/src/jabber_file.cpp index 2e9b30f90f..dfd6a26632 100644 --- a/protocols/JabberG/src/jabber_file.cpp +++ b/protocols/JabberG/src/jabber_file.cpp @@ -436,11 +436,10 @@ int CJabberProto::FileSendParse(HNETLIBCONN s, filetransfer *ft, char* buffer, i ///////////////////////////////////////////////////////////////////////////////////////// // filetransfer class members -filetransfer::filetransfer(CJabberProto *proto) +filetransfer::filetransfer(CJabberProto *_proto, JABBER_LIST_ITEM *_item) : + ppro(_proto), + pItem(_item) { - memset(this, 0, sizeof(filetransfer)); - ppro = proto; - fileId = -1; std.flags = PFTS_UNICODE; } diff --git a/protocols/JabberG/src/jabber_ft.cpp b/protocols/JabberG/src/jabber_ft.cpp index 774ee23d0b..674e793b2d 100644 --- a/protocols/JabberG/src/jabber_ft.cpp +++ b/protocols/JabberG/src/jabber_ft.cpp @@ -84,7 +84,7 @@ static void __cdecl FakeAckThread(void *param) delete ft; } -void CJabberProto::FtInitiate(const char* jid, filetransfer *ft) +void CJabberProto::FtInitiate(filetransfer *ft) { if (ft == nullptr) return; @@ -104,8 +104,8 @@ LBL_Error: // if we enabled XEP-0231, try to inline a picture if (m_bInlinePictures && ProtoGetAvatarFileFormat(ft->std.szCurrentFile.w)) { - if (FtTryInlineFile(ft->std.hContact, ft->std.szCurrentFile.w)) { - mir_forkthread(FakeAckThread, ft); + if (FtTryInlineFile(ft)) { + FtSendFinal(true, ft); return; } } @@ -148,41 +148,66 @@ LBL_Error: goto LBL_Error; } - char *rs = ListGetBestClientResourceNamePtr(jid); - if (rs == nullptr) { + auto r = ft->pItem->getBestResource(); + if (r == nullptr) { debugLogA("%S has no current resource available, file transfer failed", Clist_GetContactDisplayName(ft->std.hContact)); goto LBL_Error; } + JabberCapsBits jcb = GetResourceCapabilities(ft->pItem->jid, r); + if (jcb == JABBER_RESOURCE_CAPS_IN_PROGRESS) { + Sleep(600); + jcb = GetResourceCapabilities(ft->pItem->jid); + } + + // fix for very smart clients, like gajim + if (!m_bBsDirect && !m_bBsProxyManual) { + // disable bytestreams + jcb &= ~JABBER_CAPS_BYTESTREAMS; + } + + // if only JABBER_CAPS_SI_FT feature set (without BS or IBB), disable JABBER_CAPS_SI_FT + if ((jcb & (JABBER_CAPS_SI_FT | JABBER_CAPS_IBB | JABBER_CAPS_BYTESTREAMS)) == JABBER_CAPS_SI_FT) + jcb &= ~JABBER_CAPS_SI_FT; + + if ((jcb & JABBER_RESOURCE_CAPS_ERROR) // can't get caps + || (jcb == JABBER_RESOURCE_CAPS_NONE) // caps not already received + || !(jcb & (JABBER_CAPS_SI_FT | JABBER_CAPS_OOB))) // XEP-0096 and OOB not supported? + { + MsgPopup(ft->std.hContact, TranslateT("No compatible file transfer mechanism exists"), Utf2T(ft->pItem->jid)); + goto LBL_Error; + } + // no cloud services enabled, try to initiate a p2p file transfer - ft->type = FT_SI; - char sid[9]; - for (int i = 0; i < 8; i++) - sid[i] = (rand() % 10) + '0'; - sid[8] = '\0'; - replaceStr(ft->sid, sid); - - auto *pIq = AddIQ(&CJabberProto::OnFtSiResult, JABBER_IQ_TYPE_SET, MakeJid(jid, rs), ft); - pIq->SetParamsToParse(JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_TO); - XmlNodeIq iq(pIq); - TiXmlElement *si = iq << XCHILDNS("si", JABBER_FEAT_SI) << XATTR("id", sid) - << XATTR("mime-type", "binary/octet-stream") << XATTR("profile", JABBER_FEAT_SI_FT); - si << XCHILDNS("file", JABBER_FEAT_SI_FT) << XATTR("name", T2Utf(filename)) - << XATTRI64("size", ft->fileSize[ft->std.currentFileNumber]) << XCHILD("desc", T2Utf(ft->szDescription)); - - TiXmlElement *field = si << XCHILDNS("feature", JABBER_FEAT_FEATURE_NEG) - << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "form") - << XCHILD("field") << XATTR("var", "stream-method") << XATTR("type", "list-single"); - - BOOL bDirect = m_bBsDirect; - BOOL bProxy = m_bBsProxyManual; - - // bytestreams support? - if (bDirect || bProxy) - field << XCHILD("option") << XCHILD("value", JABBER_FEAT_BYTESTREAMS); - - field << XCHILD("option") << XCHILD("value", JABBER_FEAT_IBB); - m_ThreadInfo->send(iq); + if (jcb & JABBER_CAPS_SI_FT) { + ft->type = FT_SI; + char sid[9]; + for (int i = 0; i < 8; i++) + sid[i] = (rand() % 10) + '0'; + sid[8] = '\0'; + replaceStr(ft->sid, sid); + + auto *pIq = AddIQ(&CJabberProto::OnFtSiResult, JABBER_IQ_TYPE_SET, MakeJid(ft->pItem->jid, r->m_szResourceName), ft); + pIq->SetParamsToParse(JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_TO); + XmlNodeIq iq(pIq); + TiXmlElement *si = iq << XCHILDNS("si", JABBER_FEAT_SI) << XATTR("id", sid) + << XATTR("mime-type", "binary/octet-stream") << XATTR("profile", JABBER_FEAT_SI_FT); + si << XCHILDNS("file", JABBER_FEAT_SI_FT) << XATTR("name", T2Utf(filename)) + << XATTRI64("size", ft->fileSize[ft->std.currentFileNumber]) << XCHILD("desc", T2Utf(ft->szDescription)); + + TiXmlElement *field = si << XCHILDNS("feature", JABBER_FEAT_FEATURE_NEG) + << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "form") + << XCHILD("field") << XATTR("var", "stream-method") << XATTR("type", "list-single"); + + // bytestreams support? + if (m_bBsDirect || m_bBsProxyManual) + field << XCHILD("option") << XCHILD("value", JABBER_FEAT_BYTESTREAMS); + + field << XCHILD("option") << XCHILD("value", JABBER_FEAT_IBB); + m_ThreadInfo->send(iq); + } + else // OOB then + ForkThread((MyThreadFunc)&CJabberProto::FileServerThread, ft); } void CJabberProto::OnFtSiResult(const TiXmlElement *iqNode, CJabberIqInfo *pInfo) @@ -330,7 +355,7 @@ bool CJabberProto::FtIbbSend(int blocksize, filetransfer *ft) return true; } -void CJabberProto::FtSendFinal(BOOL success, filetransfer *ft) +void CJabberProto::FtSendFinal(bool success, filetransfer *ft) { if (!success) { debugLogA("File transfer complete with error"); @@ -341,7 +366,7 @@ void CJabberProto::FtSendFinal(BOOL success, filetransfer *ft) ft->std.currentFileNumber++; replaceStrW(ft->std.szCurrentFile.w, ft->std.pszFiles.w[ft->std.currentFileNumber]); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft); - FtInitiate(ft->jid, ft); + FtInitiate(ft); return; } @@ -402,7 +427,7 @@ void CJabberProto::FtHandleSiRequest(const TiXmlElement *iqNode) if (optionNode != nullptr) { // Found known stream mechanism - filetransfer *ft = new filetransfer(this); + filetransfer *ft = new filetransfer(this, 0); ft->dwExpectedRecvFileSize = filesize; ft->jid = mir_strdup(from); ft->std.hContact = HContactFromJID(from); @@ -582,13 +607,13 @@ int CJabberProto::FtReceive(HNETLIBCONN, filetransfer *ft, char* buffer, int dat return 0; } -void CJabberProto::FtReceiveFinal(BOOL success, filetransfer *ft) +void CJabberProto::FtReceiveFinal(bool success, filetransfer *ft) { if (success) { - debugLogA("File transfer complete successfully"); + debugLogA("File transfer completed successfully"); ft->complete(); } - else debugLogA("File transfer complete with error"); + else debugLogA("File transfer completed with error"); delete ft; } @@ -679,16 +704,17 @@ LBL_Fail: if (szGetUrl == nullptr) szGetUrl = szUrl; - if (ProtoChainSend(ft->std.hContact, PSS_MESSAGE, 0, (LPARAM)szGetUrl) != -1) { + if (isChatRoom(ft->std.hContact)) + GroupchatSendMsg(ft->pItem, ptrA(mir_utf8encode(szGetUrl))); + else if (ProtoChainSend(ft->std.hContact, PSS_MESSAGE, 0, (LPARAM)szGetUrl) != -1) { PROTORECVEVENT recv = {}; recv.flags = PREF_CREATEREAD | PREF_SENT; - recv.szMessage = (char*)szGetUrl; + recv.szMessage = (char *)szGetUrl; recv.timestamp = time(0); ProtoChainRecvMsg(ft->std.hContact, &recv); } - ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft); - delete ft; + FtSendFinal(true, ft); return; } } @@ -700,23 +726,23 @@ LBL_Fail: ///////////////////////////////////////////////////////////////////////////////////////// -bool CJabberProto::FtTryInlineFile(MCONTACT hContact, const wchar_t *pwszFileName) +bool CJabberProto::FtTryInlineFile(filetransfer *ft) { - int fileFormat = ProtoGetAvatarFormat(pwszFileName); + int fileFormat = ProtoGetAvatarFormat(ft->std.szCurrentFile.w); if (fileFormat == PA_FORMAT_UNKNOWN) { debugLogA("Unknown picture format"); return false; } char szClientJid[JABBER_MAX_JID_LEN]; - if (!m_bJabberOnline || !GetClientJID(hContact, szClientJid, _countof(szClientJid))) { - debugLogA("Protocol is offline or no contact %d", hContact); + if (!m_bJabberOnline || !GetClientJID(ft->std.hContact, szClientJid, _countof(szClientJid))) { + debugLogA("Protocol is offline or no contact %d", ft->std.hContact); return false; } - int fileId = _wopen(pwszFileName, _O_BINARY | _O_RDONLY); + int fileId = _wopen(ft->std.szCurrentFile.w, _O_BINARY | _O_RDONLY); if (fileId < 0) { - debugLogW(L"File %s cannot be opened for inlining", pwszFileName); + debugLogW(L"File %s cannot be opened for inlining", ft->std.szCurrentFile.w); return false; } @@ -739,9 +765,9 @@ bool CJabberProto::FtTryInlineFile(MCONTACT hContact, const wchar_t *pwszFileNam CMStringW wszFileName(FORMAT, L"%s\\%S%s", wszTempPath.get(), szHash, ProtoGetAvatarExtension(fileFormat)); if (_waccess(wszFileName, 0)) - if (!CopyFileW(pwszFileName, wszFileName, FALSE)) { + if (!CopyFileW(ft->std.szCurrentFile.w, wszFileName, FALSE)) { DWORD dwError = GetLastError(); - debugLogW(L"File <%s> cannot be copied to <%s>: error %d", pwszFileName, wszFileName.c_str(), dwError); + debugLogW(L"File <%s> cannot be copied to <%s>: error %d", ft->std.szCurrentFile.w, wszFileName.c_str(), dwError); return false; } @@ -770,7 +796,7 @@ bool CJabberProto::FtTryInlineFile(MCONTACT hContact, const wchar_t *pwszFileNam recv.flags = PREF_CREATEREAD | PREF_SENT; recv.szMessage = szMsg.GetBuffer(); recv.timestamp = time(0); - ProtoChainRecvMsg(hContact, &recv); + ProtoChainRecvMsg(ft->std.hContact, &recv); return true; } diff --git a/protocols/JabberG/src/jabber_groupchat.cpp b/protocols/JabberG/src/jabber_groupchat.cpp index 3af128e858..255583ddc4 100644 --- a/protocols/JabberG/src/jabber_groupchat.cpp +++ b/protocols/JabberG/src/jabber_groupchat.cpp @@ -1190,3 +1190,17 @@ void CJabberProto::AcceptGroupchatInvite(const char *roomJid, const char *reason char *server = strtok(nullptr, "@"); GroupchatJoinRoom(server, p, reason, password); } + +void CJabberProto::GroupchatSendMsg(JABBER_LIST_ITEM *pItem, const char *msg) +{ + if (!m_bJabberOnline) + return; + + char szId[100]; + int64_t id = (_time64(nullptr) << 16) + (GetTickCount() & 0xFFFF); + _i64toa(id, szId, 36); + + m_ThreadInfo->send( + XmlNode("message") << XATTR("id", szId) << XATTR("to", pItem->jid) << XATTR("type", "groupchat") + << XCHILD("body", msg)); +} diff --git a/protocols/JabberG/src/jabber_ibb.cpp b/protocols/JabberG/src/jabber_ibb.cpp index 1ce839ede7..4dcc4a2755 100644 --- a/protocols/JabberG/src/jabber_ibb.cpp +++ b/protocols/JabberG/src/jabber_ibb.cpp @@ -128,7 +128,7 @@ void CJabberProto::IbbSendThread(JABBER_IBB_TRANSFER *jibb) else jibb->state = JIBB_ERROR; } - (this->*jibb->pfnFinal)((jibb->state == JIBB_DONE) ? TRUE : FALSE, jibb->ft); + (this->*jibb->pfnFinal)(jibb->state == JIBB_DONE, jibb->ft); jibb->ft = nullptr; JabberIbbFreeJibb(jibb); } @@ -157,7 +157,7 @@ void __cdecl CJabberProto::IbbReceiveThread(JABBER_IBB_TRANSFER *jibb) if (jibb->bStreamClosed && jibb->dwTransferredSize == ft->dwExpectedRecvFileSize) jibb->state = JIBB_DONE; - (this->*jibb->pfnFinal)((jibb->state == JIBB_DONE) ? TRUE : FALSE, jibb->ft); + (this->*jibb->pfnFinal)(jibb->state == JIBB_DONE, jibb->ft); jibb->ft = nullptr; ListRemove(LIST_FTRECV, jibb->sid); diff --git a/protocols/JabberG/src/jabber_ibb.h b/protocols/JabberG/src/jabber_ibb.h index e6f31187ec..f361419084 100644 --- a/protocols/JabberG/src/jabber_ibb.h +++ b/protocols/JabberG/src/jabber_ibb.h @@ -41,7 +41,7 @@ struct JABBER_IBB_TRANSFER WORD wPacketId; bool (CJabberProto::*pfnSend)(int blocksize, filetransfer *ft); int (CJabberProto::*pfnRecv)(HNETLIBCONN hConn, filetransfer *ft, char* buffer, int datalen); - void (CJabberProto::*pfnFinal)(BOOL success, filetransfer *ft); + void (CJabberProto::*pfnFinal)(bool success, filetransfer *ft); filetransfer *ft; }; diff --git a/protocols/JabberG/src/jabber_iq_handlers.cpp b/protocols/JabberG/src/jabber_iq_handlers.cpp index 692130c27b..a6cff1e088 100644 --- a/protocols/JabberG/src/jabber_iq_handlers.cpp +++ b/protocols/JabberG/src/jabber_iq_handlers.cpp @@ -285,7 +285,7 @@ bool CJabberProto::OnIqRequestOOB(const TiXmlElement*, CJabberIqInfo *pInfo) return true; } - filetransfer *ft = new filetransfer(this); + filetransfer *ft = new filetransfer(this, 0); ft->std.totalFiles = 1; ft->jid = mir_strdup(pInfo->GetFrom()); ft->std.hContact = pInfo->GetHContact(); diff --git a/protocols/JabberG/src/jabber_list.cpp b/protocols/JabberG/src/jabber_list.cpp index 0b05136806..ea2c0083dd 100644 --- a/protocols/JabberG/src/jabber_list.cpp +++ b/protocols/JabberG/src/jabber_list.cpp @@ -355,10 +355,10 @@ pResourceStatus JABBER_LIST_ITEM::getBestResource() const if (arResources.getCount() == 1) return arResources[0]; - if (resourceMode == RSMODE_LASTSEEN) + if (resourceMode == RSMODE_LASTSEEN && m_pLastSeenResource) return m_pLastSeenResource; - if (resourceMode == RSMODE_MANUAL) + if (resourceMode == RSMODE_MANUAL && m_pManualResource) return m_pManualResource; int nBestPos = -1, nBestPri = -200; @@ -390,36 +390,5 @@ char* CJabberProto::ListGetBestClientResourceNamePtr(const char *jid) if (r != nullptr) return r->m_szResourceName; - int status = ID_STATUS_OFFLINE; - char *res = nullptr; - for (auto &it : LI->arResources) { - bool foundBetter = false; - switch (it->m_iStatus) { - case ID_STATUS_FREECHAT: - foundBetter = true; - break; - case ID_STATUS_ONLINE: - if (status != ID_STATUS_FREECHAT) - foundBetter = true; - break; - case ID_STATUS_DND: - if (status != ID_STATUS_FREECHAT && status != ID_STATUS_ONLINE) - foundBetter = true; - break; - case ID_STATUS_AWAY: - if (status != ID_STATUS_FREECHAT && status != ID_STATUS_ONLINE && status != ID_STATUS_DND) - foundBetter = true; - break; - case ID_STATUS_NA: - if (status != ID_STATUS_FREECHAT && status != ID_STATUS_ONLINE && status != ID_STATUS_DND && status != ID_STATUS_AWAY) - foundBetter = true; - break; - } - if (foundBetter) { - res = it->m_szResourceName; - status = it->m_iStatus; - } - } - - return res; + return nullptr; } diff --git a/protocols/JabberG/src/jabber_privacy.cpp b/protocols/JabberG/src/jabber_privacy.cpp index f55d0bbbd8..30b01f49fd 100644 --- a/protocols/JabberG/src/jabber_privacy.cpp +++ b/protocols/JabberG/src/jabber_privacy.cpp @@ -1105,10 +1105,9 @@ lbl_return: for (auto &hContact : Contacts()) { hItem = m_clcClist.FindContact(hContact); - ptrW jid(m_proto->getWStringA(hContact, "jid")); + ptrA jid(m_proto->ContactToJID(hContact)); if (jid == nullptr) - if ((jid = m_proto->getWStringA(hContact, "ChatRoomID")) == nullptr) - continue; + continue; if (dwPackets = CListGetPackets(hItem, true)) pList->AddRule(Jid, szJid, TRUE, dwOrder++, dwPackets); diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 4bdacb12ea..edee15ae30 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -830,46 +830,26 @@ HANDLE CJabberProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, w if (!m_bJabberOnline) return nullptr; - ptrA jid(getUStringA(hContact, "jid")); - if (jid == nullptr) + ptrA jid(ContactToJID(hContact)); + if (jid == nullptr) { + debugLogA("invalid contact passed for a file transfer: %d", hContact); return nullptr; + } JABBER_LIST_ITEM *item = ListGetItemPtr(LIST_ROSTER, jid); if (item == nullptr) - return nullptr; + if ((item = ListGetItemPtr(LIST_CHATROOM, jid)) == nullptr) { + debugLogA("invalid jid passed for a file transfer: %s", jid); + return nullptr; + } // Check if another file transfer session request is pending (waiting for disco result) - if (item->ft != nullptr) + if (item->ft != nullptr) { + debugLogA("another file transfer is active for %s, exiting", item->jid); return nullptr; - - JabberCapsBits jcb = 0; - if (!m_bUseHttpUpload) { - jcb = GetResourceCapabilities(item->jid); - if (jcb == JABBER_RESOURCE_CAPS_IN_PROGRESS) { - Sleep(600); - jcb = GetResourceCapabilities(item->jid); - } - - // fix for very smart clients, like gajim - if (!m_bBsDirect && !m_bBsProxyManual) { - // disable bytestreams - jcb &= ~JABBER_CAPS_BYTESTREAMS; - } - - // if only JABBER_CAPS_SI_FT feature set (without BS or IBB), disable JABBER_CAPS_SI_FT - if ((jcb & (JABBER_CAPS_SI_FT | JABBER_CAPS_IBB | JABBER_CAPS_BYTESTREAMS)) == JABBER_CAPS_SI_FT) - jcb &= ~JABBER_CAPS_SI_FT; - - if ((jcb & JABBER_RESOURCE_CAPS_ERROR) // can't get caps - || (jcb == JABBER_RESOURCE_CAPS_NONE) // caps not already received - || !(jcb & (JABBER_CAPS_SI_FT | JABBER_CAPS_OOB))) // XEP-0096 and OOB not supported? - { - MsgPopup(hContact, TranslateT("No compatible file transfer mechanism exists"), Utf2T(item->jid)); - return nullptr; - } } - filetransfer *ft = new filetransfer(this); + filetransfer *ft = new filetransfer(this, item); ft->std.hContact = hContact; while (ppszFiles[ft->std.totalFiles] != nullptr) ft->std.totalFiles++; @@ -890,6 +870,7 @@ HANDLE CJabberProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, w } } if (j == 0) { + debugLogA("no valid files to send, exiting"); delete ft; return nullptr; } @@ -897,12 +878,7 @@ HANDLE CJabberProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, w ft->std.szCurrentFile.w = mir_wstrdup(ppszFiles[0]); ft->szDescription = mir_wstrdup(szDescription); ft->jid = mir_strdup(jid); - - if ((m_bInlinePictures && ProtoGetAvatarFileFormat(ft->std.szCurrentFile.w)) || m_bUseHttpUpload || (jcb & JABBER_CAPS_SI_FT)) - FtInitiate(item->jid, ft); - else if (jcb & JABBER_CAPS_OOB) - ForkThread((MyThreadFunc)&CJabberProto::FileServerThread, ft); - + FtInitiate(ft); return ft; } diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index 961329212c..43320a09c3 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -491,7 +491,6 @@ struct CJabberProto : public PROTO, public IJabberInterface void GroupchatJoinRoomByJid(HWND hwndParent, char *jid); void RenameParticipantNick(JABBER_LIST_ITEM *item, const char *oldNick, const TiXmlElement *itemNode); - void AcceptGroupchatInvite(const char *roomJid, const char *reason, const char *password); //---- jabber_ft.c ------------------------------------------------------------------- @@ -499,13 +498,13 @@ struct CJabberProto : public PROTO, public IJabberInterface void __cdecl FileServerThread(filetransfer *ft); void FtCancel(filetransfer *ft); - void FtInitiate(const char* jid, filetransfer *ft); + void FtInitiate(filetransfer *ft); void FtHandleSiRequest(const TiXmlElement *iqNode); void FtAcceptSiRequest(filetransfer *ft); void FtAcceptIbbRequest(filetransfer *ft); bool FtHandleBytestreamRequest(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); bool FtHandleIbbRequest(const TiXmlElement *iqNode, bool bOpen); - bool FtTryInlineFile(MCONTACT hContact, const wchar_t *pwszFileName); + bool FtTryInlineFile(filetransfer *ft); bool FtHandleCidRequest(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); //---- jabber_groupchat.c ------------------------------------------------------------ @@ -515,10 +514,12 @@ struct CJabberProto : public PROTO, public IJabberInterface INT_PTR __cdecl OnJoinChat(WPARAM wParam, LPARAM lParam); INT_PTR __cdecl OnLeaveChat(WPARAM wParam, LPARAM lParam); + void AcceptGroupchatInvite(const char *roomJid, const char *reason, const char *password); void GroupchatJoinRoom(const char *server, const char *room, const char *nick, const char *password, bool autojoin = false); void GroupchatProcessPresence(const TiXmlElement *node); void GroupchatProcessMessage(const TiXmlElement *node); void GroupchatProcessInvite(const char *roomJid, const char *from, const char *reason, const char *password); + void GroupchatSendMsg(JABBER_LIST_ITEM *pItem, const char *msg); void OnIqResultDiscovery(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); //---- jabber_icolib.cpp ------------------------------------------------------------- @@ -599,9 +600,9 @@ struct CJabberProto : public PROTO, public IJabberInterface void OnFtSiResult(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); bool FtIbbSend(int blocksize, filetransfer *ft); bool FtSend(HNETLIBCONN hConn, filetransfer *ft); - void FtSendFinal(BOOL success, filetransfer *ft); + void FtSendFinal(bool success, filetransfer *ft); int FtReceive(HNETLIBCONN hConn, filetransfer *ft, char* buffer, int datalen); - void FtReceiveFinal(BOOL success, filetransfer *ft); + void FtReceiveFinal(bool success, filetransfer *ft); //---- jabber_iqid.cpp --------------------------------------------------------------- diff --git a/protocols/JabberG/src/stdafx.h b/protocols/JabberG/src/stdafx.h index 1cfc249659..5fd07d23e3 100755 --- a/protocols/JabberG/src/stdafx.h +++ b/protocols/JabberG/src/stdafx.h @@ -411,9 +411,9 @@ struct JABBER_MODEMSGS enum JABBER_FT_TYPE { FT_SI, FT_OOB, FT_BYTESTREAM, FT_IBB, FT_HTTP }; enum JABBER_FILE_STATE { FT_CONNECTING, FT_INITIALIZING, FT_RECEIVING, FT_DONE, FT_ERROR, FT_DENIED }; -struct filetransfer +struct filetransfer : public MZeroedObject { - filetransfer(CJabberProto *proto); + filetransfer(CJabberProto *proto, struct JABBER_LIST_ITEM *item); ~filetransfer(); void close(); @@ -425,8 +425,9 @@ struct filetransfer JABBER_FT_TYPE type; HNETLIBCONN s; JABBER_FILE_STATE state; + JABBER_LIST_ITEM *pItem; char* jid; - int fileId; + int fileId = -1; char* szId; char* sid; int bCompleted; -- cgit v1.2.3