From 456293e5f1d7373d1c7a3a0b8888a9dc28b6945d Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 29 Jun 2020 19:00:02 +0300 Subject: fixes #2453 (Jabber: add ability to load whole history via Message Archive Management) --- protocols/JabberG/src/jabber_mam.cpp | 59 ++++++++++++++++++++++++++++++++++ protocols/JabberG/src/jabber_menu.cpp | 10 ++++-- protocols/JabberG/src/jabber_proto.cpp | 1 + protocols/JabberG/src/jabber_proto.h | 12 ++++--- 4 files changed, 74 insertions(+), 8 deletions(-) (limited to 'protocols/JabberG/src') diff --git a/protocols/JabberG/src/jabber_mam.cpp b/protocols/JabberG/src/jabber_mam.cpp index 43e80d76b8..f369dcb0c4 100644 --- a/protocols/JabberG/src/jabber_mam.cpp +++ b/protocols/JabberG/src/jabber_mam.cpp @@ -78,3 +78,62 @@ void CJabberProto::MamRetrieveMissingMessages() set << XCHILD("after", szLastId); m_ThreadInfo->send(iq); } + +///////////////////////////////////////////////////////////////////////////////////////// +// Contact's history loader + +void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInfo) +{ + if (auto *fin = XmlGetChildByTag(iqNode, "fin", "xmlns", JABBER_FEAT_MAM)) { + // if dataset is complete, there's nothing more to do + if (!mir_strcmp(XmlGetAttr(fin, "complete"), "true")) + return; + + auto *lastId = XmlGetChildText(fin, "last"); + if (lastId) { + ptrA jid(getUStringA(pInfo->GetHContact(), "jid")); + + auto *pReq = AddIQ(&CJabberProto::OnIqResultRsm, JABBER_IQ_TYPE_SET); + pReq->SetParamsToParse(JABBER_IQ_PARSE_FROM); + + XmlNodeIq iq(pReq); + auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM); + auto *x = query << XCHILDNS("x", "jabber:x:data") << XATTR("type", "submit"); + x << XCHILD("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM); + x << XCHILD("var", "with") << XCHILD("value", jid); + auto *rsm = query << XCHILDNS("set", "http://jabber.org/protocol/rsm"); + rsm << XCHILD("max", "100"); + rsm << XCHILD("after", lastId); + m_ThreadInfo->send(iq); + } + } +} + +INT_PTR __cdecl CJabberProto::OnMenuLoadHistory(WPARAM hContact, LPARAM) +{ + if (hContact == 0) + return 0; + + // wipe out old history first + DB::ECPTR pCursor(DB::Events(hContact)); + while (pCursor.FetchNext()) + pCursor.DeleteEvent(); + + // load remaining items from server + if (m_bJabberOnline) { + ptrA jid(getUStringA(hContact, "jid")); + if (jid != nullptr) { + auto *pReq = AddIQ(&CJabberProto::OnIqResultRsm, JABBER_IQ_TYPE_SET); + pReq->SetParamsToParse(JABBER_IQ_PARSE_FROM); + + XmlNodeIq iq(pReq); + auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM); + auto *x = query << XCHILDNS("x", "jabber:x:data") << XATTR("type", "submit"); + x << XCHILD("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM); + x << XCHILD("var", "with") << XCHILD("value", jid); + query << XCHILDNS("set", "http://jabber.org/protocol/rsm") << XCHILD("max", "100"); + m_ThreadInfo->send(iq); + } + } + return 0; +} diff --git a/protocols/JabberG/src/jabber_menu.cpp b/protocols/JabberG/src/jabber_menu.cpp index 6bb8ec5444..87db94d7a3 100644 --- a/protocols/JabberG/src/jabber_menu.cpp +++ b/protocols/JabberG/src/jabber_menu.cpp @@ -266,6 +266,7 @@ int CJabberProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM) if (hContact == 0) return 0; + Menu_ShowItem(GetMenuItem(PROTO_MENU_LOAD_HISTORY), false); bool bIsChatRoom = isChatRoom(hContact); bool bIsTransport = getBool(hContact, "IsTransport", false); @@ -276,6 +277,9 @@ int CJabberProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM) for (int i = 0; i < _countof(PresenceModeArray); i++) Menu_ModifyItem(g_hMenuDirectPresence[i + 1], nullptr, Skin_GetProtoIcon(m_szModuleName, PresenceModeArray[i].mode)); + if (m_ThreadInfo && (m_ThreadInfo->jabberServerCaps & JABBER_CAPS_MAM)) + Menu_ShowItem(GetMenuItem(PROTO_MENU_LOAD_HISTORY), true); + if (bIsChatRoom) { ptrA roomid(getUStringA(hContact, "ChatRoomID")); if (ListGetItemPtr(LIST_BOOKMARK, roomid) == nullptr) @@ -301,9 +305,9 @@ int CJabberProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM) return 0; bool bCtrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) != 0; - Menu_ShowItem(m_hmiReqAuth, item->subscription == SUB_FROM || item->subscription == SUB_NONE || bCtrlPressed); - Menu_ShowItem(m_hmiGrantAuth, bCtrlPressed); - Menu_ShowItem(m_hmiRevokeAuth, item->subscription == SUB_FROM || item->subscription == SUB_BOTH || bCtrlPressed); + Menu_ShowItem(GetMenuItem(PROTO_MENU_REQ_AUTH), item->subscription == SUB_FROM || item->subscription == SUB_NONE || bCtrlPressed); + Menu_ShowItem(GetMenuItem(PROTO_MENU_GRANT_AUTH), bCtrlPressed); + Menu_ShowItem(GetMenuItem(PROTO_MENU_REVOKE_AUTH), item->subscription == SUB_FROM || item->subscription == SUB_BOTH || bCtrlPressed); Menu_ShowItem(g_hMenuCommands, ((jcb & JABBER_CAPS_COMMANDS) != 0) || bCtrlPressed); Menu_ShowItem(g_hMenuSendNote, TRUE); diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index a28fcc7b87..685f39eb14 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -167,6 +167,7 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) : CreateProtoService(PS_MENU_REQAUTH, &CJabberProto::OnMenuHandleRequestAuth); CreateProtoService(PS_MENU_GRANTAUTH, &CJabberProto::OnMenuHandleGrantAuth); CreateProtoService(PS_MENU_REVOKEAUTH, &CJabberProto::OnMenuHandleRevokeAuth); + CreateProtoService(PS_MENU_LOADHISTORY, &CJabberProto::OnMenuLoadHistory); CreateProtoService(JS_DB_GETEVENTTEXT_CHATSTATES, &CJabberProto::OnGetEventTextChatStates); CreateProtoService(JS_DB_GETEVENTTEXT_PRESENCE, &CJabberProto::OnGetEventTextPresence); diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index 5dd2f0e8fc..9a0588d6e1 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -640,22 +640,24 @@ struct CJabberProto : public PROTO, public IJabberInterface //---- jabber_mam.cpp ---------------------------------------------------------------- void OnIqResultMamInfo(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); + void OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); void MamRetrieveMissingMessages(void); void MamSetMode(int iNewMode); //---- jabber_menu.cpp --------------------------------------------------------------- - INT_PTR __cdecl OnMenuHandleRequestAuth(WPARAM wParam, LPARAM lParam); - INT_PTR __cdecl OnMenuHandleGrantAuth(WPARAM wParam, LPARAM lParam); - INT_PTR __cdecl OnMenuOptions(WPARAM wParam, LPARAM lParam); - INT_PTR __cdecl OnMenuTransportLogin(WPARAM wParam, LPARAM lParam); - INT_PTR __cdecl OnMenuTransportResolve(WPARAM wParam, LPARAM lParam); INT_PTR __cdecl OnMenuBookmarkAdd(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl OnMenuHandleGrantAuth(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl OnMenuHandleRequestAuth(WPARAM wParam, LPARAM lParam); INT_PTR __cdecl OnMenuHandleRevokeAuth(WPARAM wParam, LPARAM lParam); INT_PTR __cdecl OnMenuHandleResource(WPARAM wParam, LPARAM lParam, LPARAM res); INT_PTR __cdecl OnMenuHandleDirectPresence(WPARAM wParam, LPARAM lParam, LPARAM res); + INT_PTR __cdecl OnMenuLoadHistory(WPARAM wParam, LPARAM lParam); INT_PTR __cdecl OnMenuSetPriority(WPARAM wParam, LPARAM lParam, LPARAM dwDelta); + INT_PTR __cdecl OnMenuOptions(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl OnMenuTransportLogin(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl OnMenuTransportResolve(WPARAM wParam, LPARAM lParam); void GlobalMenuInit(void); void GlobalMenuUninit(void); -- cgit v1.2.3