summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-03-31 14:44:40 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-03-31 14:44:40 +0300
commit226427505784cb0db153e44baa45d1b7d028aff9 (patch)
treef6b208fd0b49207ad8da8e29c572400ba4835a78 /protocols
parente8096c13782500587c1396d0c296cdddee10089b (diff)
Jabber:
- fixes #2279 (Jabber: add HTTP File Upload support for group chats); - major file transfer code cleaning;
Diffstat (limited to 'protocols')
-rw-r--r--protocols/JabberG/src/jabber_byte.cpp10
-rw-r--r--protocols/JabberG/src/jabber_byte.h2
-rw-r--r--protocols/JabberG/src/jabber_chat.cpp14
-rw-r--r--protocols/JabberG/src/jabber_events.cpp2
-rw-r--r--protocols/JabberG/src/jabber_file.cpp7
-rw-r--r--protocols/JabberG/src/jabber_ft.cpp130
-rw-r--r--protocols/JabberG/src/jabber_groupchat.cpp14
-rw-r--r--protocols/JabberG/src/jabber_ibb.cpp4
-rw-r--r--protocols/JabberG/src/jabber_ibb.h2
-rw-r--r--protocols/JabberG/src/jabber_iq_handlers.cpp2
-rw-r--r--protocols/JabberG/src/jabber_list.cpp37
-rw-r--r--protocols/JabberG/src/jabber_privacy.cpp5
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.cpp50
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h11
-rwxr-xr-xprotocols/JabberG/src/stdafx.h7
15 files changed, 136 insertions, 161 deletions
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<CJabberProto>, 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<CJabberProto>, 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<CJabberProto>, 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<CJabberProto>, 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;