From 5fb805622a3a3368ffb3de0c649074376e70256a Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 11 Jun 2020 22:20:11 +0300 Subject: fixes #1149 (XMPP/Jabber: Implement XEP-0313 ( mam / Message Archive Management ) --- protocols/JabberG/jabber.vcxproj | 1 + protocols/JabberG/jabber.vcxproj.filters | 3 ++ protocols/JabberG/res/jabber.rc | 21 ++++++--- protocols/JabberG/src/jabber_caps.cpp | 1 + protocols/JabberG/src/jabber_caps.h | 7 ++- protocols/JabberG/src/jabber_iqid.cpp | 10 ++-- protocols/JabberG/src/jabber_mam.cpp | 78 ++++++++++++++++++++++++++++++++ protocols/JabberG/src/jabber_opt.cpp | 14 +++++- protocols/JabberG/src/jabber_proto.cpp | 1 + protocols/JabberG/src/jabber_proto.h | 44 ++++++++++-------- protocols/JabberG/src/jabber_thread.cpp | 27 +++++++++-- protocols/JabberG/src/resource.h | 3 +- 12 files changed, 175 insertions(+), 35 deletions(-) create mode 100644 protocols/JabberG/src/jabber_mam.cpp (limited to 'protocols/JabberG') diff --git a/protocols/JabberG/jabber.vcxproj b/protocols/JabberG/jabber.vcxproj index 9495f2516f..7eb80b6e17 100755 --- a/protocols/JabberG/jabber.vcxproj +++ b/protocols/JabberG/jabber.vcxproj @@ -51,6 +51,7 @@ + diff --git a/protocols/JabberG/jabber.vcxproj.filters b/protocols/JabberG/jabber.vcxproj.filters index 72b6943026..3a72f63b4b 100755 --- a/protocols/JabberG/jabber.vcxproj.filters +++ b/protocols/JabberG/jabber.vcxproj.filters @@ -164,6 +164,9 @@ Source Files + + Source Files + diff --git a/protocols/JabberG/res/jabber.rc b/protocols/JabberG/res/jabber.rc index 6280d2c403..5e6bb8a04e 100644 --- a/protocols/JabberG/res/jabber.rc +++ b/protocols/JabberG/res/jabber.rc @@ -91,7 +91,7 @@ BEGIN PUSHBUTTON "Export to file",IDC_EXPORT,272,268,71,15 END -IDD_OPT_JABBER DIALOGEX 0, 0, 304, 208 +IDD_OPT_JABBER DIALOGEX 0, 0, 304, 222 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 0, 0, 0x1 @@ -103,6 +103,7 @@ BEGIN EDITTEXT IDC_EDIT_PASSWORD,66,30,86,12,ES_PASSWORD | ES_AUTOHSCROLL PUSHBUTTON "Change password",IDC_BUTTON_CHANGE_PASSWORD,156,30,78,13 CONTROL "Save password",IDC_SAVEPASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,66,45,89,10 + CONTROL "Use Domain Login",IDC_USEDOMAINLOGIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,45,137,9 LTEXT "Priority:",IDC_PRIORITY_LABEL,12,59,41,8 EDITTEXT IDC_PRIORITY,66,57,85,12,ES_AUTOHSCROLL CONTROL "Spin1",IDC_PRIORITY_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_NOTHOUSANDS,151,57,12,12 @@ -120,18 +121,19 @@ BEGIN CONTROL "Use TLS",IDC_USE_TLS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,189,100,97,10 PUSHBUTTON "Register new user",IDC_BUTTON_REGISTER,156,16,78,13 PUSHBUTTON "Unregister",IDC_UNREGISTER,235,16,56,13 - GROUPBOX "Expert",IDC_STATIC,4,120,295,85 + GROUPBOX "Expert",IDC_STATIC,4,120,295,99 CONTROL "Manually specify connection host",IDC_MANUAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,134,223,10 RTEXT "Host:",IDC_STATIC,26,147,30,8 EDITTEXT IDC_HOST,57,145,90,12,ES_AUTOHSCROLL | WS_DISABLED RTEXT "Port:",IDC_STATIC,156,147,27,8 EDITTEXT IDC_HOSTPORT,186,145,31,12,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED - CONTROL "Keep connection alive",IDC_KEEPALIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,158,221,10 + CONTROL "Keep connection alive",IDC_KEEPALIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,159,283,10 CONTROL "Automatically delete contacts not in my roster",IDC_ROSTER_SYNC, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,172,221,10 - LTEXT "Language for human-readable resources:",IDC_MSGLANG_LABEL,11,188,170,8 - COMBOBOX IDC_MSGLANG,188,186,103,69,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - CONTROL "Use Domain Login",IDC_USEDOMAINLOGIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,45,137,9 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,172,283,10 + LTEXT "History recording mode",IDC_STATIC,12,187,170,8 + COMBOBOX IDC_MAM_MODE,188,185,103,69,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Language for human-readable resources:",IDC_MSGLANG_LABEL,11,202,170,8 + COMBOBOX IDC_MSGLANG,188,200,103,69,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP END IDD_OPT_JABBER2 DIALOGEX 0, 0, 304, 228 @@ -712,6 +714,11 @@ BEGIN BEGIN END + IDD_OPT_JABBER, DIALOG + BEGIN + BOTTOMMARGIN, 208 + END + IDD_OPT_REGISTER, DIALOG BEGIN RIGHTMARGIN, 165 diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp index d1e8b987f9..bce11fb61f 100755 --- a/protocols/JabberG/src/jabber_caps.cpp +++ b/protocols/JabberG/src/jabber_caps.cpp @@ -68,6 +68,7 @@ const JabberFeatCapPair g_JabberFeatCapPairs[] = { JABBER_FEAT_USER_TUNE_NOTIFY, JABBER_CAPS_USER_TUNE_NOTIFY, LPGEN("Receives information about the music to which a user is listening") }, { JABBER_FEAT_PRIVATE_STORAGE, JABBER_CAPS_PRIVATE_STORAGE, LPGEN("Supports private XML Storage (for bookmarks and other)") }, { JABBER_FEAT_ATTENTION, JABBER_CAPS_ATTENTION, LPGEN("Supports attention requests ('nudge')") }, + { JABBER_FEAT_MAM, JABBER_CAPS_MAM, LPGEN("Support Message Archive Management (XEP-0313)") }, { JABBER_FEAT_USER_ACTIVITY, JABBER_CAPS_USER_ACTIVITY, LPGEN("Can report information about user activity") }, { JABBER_FEAT_USER_ACTIVITY_NOTIFY, JABBER_CAPS_USER_ACTIVITY_NOTIFY, LPGEN("Receives information about user activity") }, { JABBER_FEAT_MIRANDA_NOTES, JABBER_CAPS_MIRANDA_NOTES, LPGEN("Supports Miranda NG notes extension") }, diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h index 052ee09cf5..980ff36777 100755 --- a/protocols/JabberG/src/jabber_caps.h +++ b/protocols/JabberG/src/jabber_caps.h @@ -144,6 +144,9 @@ typedef unsigned __int64 JabberCapsBits; #define JABBER_FEAT_PRIVATE_STORAGE "jabber:iq:private" #define JABBER_CAPS_PRIVATE_STORAGE ((JabberCapsBits)1<<33) +#define JABBER_FEAT_MAM "urn:xmpp:mam:2" +#define JABBER_CAPS_MAM ((JabberCapsBits)1<<34) + #define JABBER_FEAT_ATTENTION "urn:xmpp:attention:0" #define JABBER_CAPS_ATTENTION ((JabberCapsBits)1<<36) @@ -211,8 +214,8 @@ typedef unsigned __int64 JabberCapsBits; JABBER_CAPS_ROSTER_EXCHANGE | JABBER_CAPS_DIRECT_MUC_INVITE | JABBER_CAPS_CHAT_MARKERS | JABBER_CAPS_BITS | JABBER_CAPS_XHTML) #define JABBER_CAPS_MIRANDA_ALL (JABBER_CAPS_MIRANDA_PARTIAL | JABBER_CAPS_COMMANDS | \ - JABBER_CAPS_USER_MOOD_NOTIFY | JABBER_CAPS_USER_TUNE_NOTIFY | JABBER_CAPS_USER_ACTIVITY_NOTIFY \ - | JABBER_CAPS_PLATFORMX86 | JABBER_CAPS_PLATFORMX64) + JABBER_CAPS_USER_MOOD_NOTIFY | JABBER_CAPS_USER_TUNE_NOTIFY | JABBER_CAPS_USER_ACTIVITY_NOTIFY | \ + JABBER_CAPS_PLATFORMX86 | JABBER_CAPS_PLATFORMX64) #define JABBER_XMLNS_FORWARD "urn:xmpp:forward:0" diff --git a/protocols/JabberG/src/jabber_iqid.cpp b/protocols/JabberG/src/jabber_iqid.cpp index e342f39410..bdaa73dc5d 100755 --- a/protocols/JabberG/src/jabber_iqid.cpp +++ b/protocols/JabberG/src/jabber_iqid.cpp @@ -123,10 +123,14 @@ void CJabberProto::OnProcessLoginRq(ThreadData *info, DWORD rq) DWORD dwMask = JABBER_LOGIN_ROSTER | JABBER_LOGIN_BOOKMARKS | JABBER_LOGIN_SERVERINFO; if ((info->dwLoginRqs & dwMask) == dwMask && !(info->dwLoginRqs & JABBER_LOGIN_BOOKMARKS_AJ)) { - if (info->jabberServerCaps & JABBER_CAPS_CARBONS) { - // Server seems to support carbon copies, let's enable/disable them + + // Server seems to support carbon copies, let's enable/disable them + if (info->jabberServerCaps & JABBER_CAPS_CARBONS) m_ThreadInfo->send(XmlNodeIq("set", SerialNext()) << XCHILDNS((m_bEnableCarbons) ? "enable" : "disable", JABBER_FEAT_CARBONS)); - } + + // Server seems to support MAM, let's retrieve MAM settings + if (info->jabberServerCaps & JABBER_CAPS_MAM) + m_ThreadInfo->send(XmlNodeIq(AddIQ(&CJabberProto::OnIqResultMamInfo, JABBER_IQ_TYPE_GET, 0, this)) << XCHILDNS("prefs", JABBER_FEAT_MAM)); if (m_bAutoJoinBookmarks) { LIST ll(10); diff --git a/protocols/JabberG/src/jabber_mam.cpp b/protocols/JabberG/src/jabber_mam.cpp new file mode 100644 index 0000000000..41a3482119 --- /dev/null +++ b/protocols/JabberG/src/jabber_mam.cpp @@ -0,0 +1,78 @@ +/* + +Jabber Protocol Plugin for Miranda NG + +Copyright (c) 2002-04 Santithorn Bunchua +Copyright (c) 2005-12 George Hazan +Copyright (c) 2007 Maxim Mluhov +Copyright (C) 2012-20 Miranda NG team + +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; either version 2 +of the License, or (at your option) any later version. + +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, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "stdafx.h" +#include "jabber_iq.h" +#include "jabber_caps.h" + +void CJabberProto::OnIqResultMamInfo(const TiXmlElement *iqNode, CJabberIqInfo *pInfo) +{ + if (pInfo->GetIqType() != JABBER_IQ_TYPE_RESULT) + return; + + if (auto *n = XmlFirstChild(iqNode, "prefs")) { + if (auto *type = n->Attribute("default")) { + if (!strcmp(type, "never")) + m_iMamMode = 0; + else if (!strcmp(type, "roster")) + m_iMamMode = 1; + else + m_iMamMode = 2; + } + } + + // shall we retrieve missing messages? + if (pInfo->GetUserData()) + MamRetrieveMissingMessages(); +} + +void CJabberProto::MamSetMode(int iNewMode) +{ + const char *szMode; + switch (iNewMode) { + case 0: szMode = "never"; break; + case 1: szMode = "roster"; break; + default: szMode = "always"; break; + } + + XmlNodeIq iq(AddIQ(&CJabberProto::OnIqResultMamInfo, JABBER_IQ_TYPE_SET)); + auto *node = iq << XCHILDNS("prefs", JABBER_FEAT_MAM) << XATTR("default", szMode); + node << XCHILD("always"); node << XCHILD("never"); + m_ThreadInfo->send(iq); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CJabberProto::MamRetrieveMissingMessages() +{ + CMStringA szLastId = getMStringA("LastMamId"); + + XmlNodeIq iq("set", SerialNext()); + auto *set = iq << XCHILDNS("query", JABBER_FEAT_MAM) << XCHILDNS("set", "http://jabber.org/protocol/rsm"); + set << XCHILD("max", "100"); + if (!szLastId.IsEmpty()) + set << XCHILD("after", szLastId); + m_ThreadInfo->send(iq); +} diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp index 7ee006d64b..65d95086e9 100755 --- a/protocols/JabberG/src/jabber_opt.cpp +++ b/protocols/JabberG/src/jabber_opt.cpp @@ -348,7 +348,7 @@ class CDlgOptAccount : public CJabberDlgBase CCtrlEdit m_txtManualPort; CCtrlCheck m_chkKeepAlive; CCtrlCheck m_chkAutoDeleteContacts; - CCtrlCombo m_cbLocale; + CCtrlCombo m_cbLocale, m_cbMam; CCtrlButton m_btnRegister; CCtrlButton m_btnUnregister; CCtrlButton m_btnChangePassword; @@ -364,6 +364,7 @@ public: m_cbResource(this, IDC_COMBO_RESOURCE), m_chkUseHostnameAsResource(this, IDC_HOSTNAME_AS_RESOURCE), m_chkUseDomainLogin(this, IDC_USEDOMAINLOGIN), + m_cbMam(this, IDC_MAM_MODE), m_cbServer(this, IDC_EDIT_LOGIN_SERVER), m_txtPort(this, IDC_PORT), m_chkUseSsl(this, IDC_USE_SSL), @@ -429,6 +430,14 @@ protected: for (auto &it : szResources) m_cbResource.AddString(it); + + // fill MAM modes + wchar_t *szMamModes[] = { LPGENW("Never"), LPGENW("Roster"), LPGENW("Always") }; + for (auto &it : szMamModes) + m_cbMam.AddString(it, int(&it - szMamModes)); + m_cbMam.SetCurSel(m_proto->m_iMamMode); + m_cbMam.Enable(m_proto->m_ThreadInfo && (m_proto->m_ThreadInfo->jabberServerCaps & JABBER_CAPS_MAM)); + // append computer name to the resource list wchar_t szCompName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwCompNameLength = MAX_COMPUTERNAME_LENGTH; @@ -488,6 +497,9 @@ protected: } } + if (m_cbMam.Enabled() && m_cbMam.GetCurSel() != m_proto->m_iMamMode) + m_proto->MamSetMode(m_cbMam.GetCurSel()); + sttStoreJidFromUI(m_proto, m_txtUsername, m_cbServer); if (m_proto->m_bJabberOnline) { diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 349d68646b..5c496b1e6f 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -129,6 +129,7 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) : m_bUseSSL(this, "UseSSL", false), m_bUseTLS(this, "UseTLS", true), + m_iMamMode(this, "MamMode", 0), m_iConnectionKeepAliveInterval(this, "ConnectionKeepAliveInterval", 60000), m_iConnectionKeepAliveTimeout(this, "ConnectionKeepAliveTimeout", 50000) { diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index 32fcd80d64..f6a292029e 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -224,6 +224,7 @@ struct CJabberProto : public PROTO, public IJabberInterface CMOption m_bUseSSL; CMOption m_bUseTLS; + CMOption m_iMamMode; CMOption m_iConnectionKeepAliveInterval; CMOption m_iConnectionKeepAliveTimeout; @@ -419,24 +420,6 @@ struct CJabberProto : public PROTO, public IJabberInterface void AddMucListItem(JABBER_MUC_JIDLIST_INFO* jidListInfo, const char *str, const char *reason); void DeleteMucListItem(JABBER_MUC_JIDLIST_INFO* jidListInfo, const char* jid); - //---- jabber_omemo.cpp -------------------------------------------------------------- - - bool OmemoHandleMessage(const TiXmlElement *node, const char *jid, time_t msgTime); - void OmemoPutMessageToOutgoingQueue(MCONTACT hContact, int, const char* pszSrc); - void OmemoPutMessageToIncommingQueue(const TiXmlElement *node, const char *jid, time_t msgTime); - void OmemoHandleMessageQueue(); - void OmemoHandleDeviceList(const TiXmlElement *node); - void OmemoInitDevice(); - void OmemoAnnounceDevice(); - void OmemoSendBundle(); - void OmemoPublishNodes(); - bool OmemoCheckSession(MCONTACT hContact); - int OmemoEncryptMessage(XmlNode &msg, const char *msg_text, MCONTACT hContact); - bool OmemoIsEnabled(MCONTACT hContact); - void OmemoOnIqResultGetBundle(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); - - omemo::omemo_impl m_omemo; - //---- jabber_console.cpp ------------------------------------------------------------ INT_PTR __cdecl OnMenuHandleConsole(WPARAM wParam, LPARAM lParam); @@ -639,6 +622,13 @@ struct CJabberProto : public PROTO, public IJabberInterface void SetBookmarkRequest(XmlNodeIq &iqId); void UpdateItem(JABBER_LIST_ITEM *pItem, const char *name); + //---- jabber_mam.cpp ---------------------------------------------------------------- + + void OnIqResultMamInfo(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); + + void MamRetrieveMissingMessages(void); + void MamSetMode(int iNewMode); + //---- jabber_menu.cpp --------------------------------------------------------------- INT_PTR __cdecl OnMenuHandleRequestAuth(WPARAM wParam, LPARAM lParam); @@ -686,6 +676,24 @@ struct CJabberProto : public PROTO, public IJabberInterface CMStringA ExtractImage(const TiXmlElement *node); const char* GetSoftName(const char *wszName); + //---- jabber_omemo.cpp -------------------------------------------------------------- + + bool OmemoHandleMessage(const TiXmlElement *node, const char *jid, time_t msgTime); + void OmemoPutMessageToOutgoingQueue(MCONTACT hContact, int, const char *pszSrc); + void OmemoPutMessageToIncommingQueue(const TiXmlElement *node, const char *jid, time_t msgTime); + void OmemoHandleMessageQueue(); + void OmemoHandleDeviceList(const TiXmlElement *node); + void OmemoInitDevice(); + void OmemoAnnounceDevice(); + void OmemoSendBundle(); + void OmemoPublishNodes(); + bool OmemoCheckSession(MCONTACT hContact); + int OmemoEncryptMessage(XmlNode &msg, const char *msg_text, MCONTACT hContact); + bool OmemoIsEnabled(MCONTACT hContact); + void OmemoOnIqResultGetBundle(const TiXmlElement *iqNode, CJabberIqInfo *pInfo); + + omemo::omemo_impl m_omemo; + //---- jabber_password.cpp -------------------------------------------------------------- INT_PTR __cdecl OnMenuHandleChangePassword(WPARAM wParam, LPARAM lParam); diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index 30a2128c29..57b3727c90 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -1078,6 +1078,8 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info) return; } + time_t msgTime = 0; + // Handle carbons. The message MUST be coming from our bare JID. const TiXmlElement *carbon = nullptr; bool carbonSent = false; //2 cases: received or sent. @@ -1124,6 +1126,20 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info) } } } + else { // check for MAM response + if (auto *mamResult = XmlGetChildByTag(node, "result", "xmlns", JABBER_FEAT_MAM)) { + auto *xmlForwarded = XmlGetChildByTag(mamResult, "forwarded", "xmlns", JABBER_XMLNS_FORWARD); + if (auto *xmlMessage = XmlFirstChild(xmlForwarded, "message")) { + node = xmlMessage; + type = XmlGetAttr(node, "type"); + from = XmlGetAttr(node, "from"); + } + if (auto *xmlDelay = XmlGetChildByTag(xmlForwarded, "delay", "xmlns", JABBER_FEAT_DELAY)) { + if (auto *ptszTimeStamp = XmlGetAttr(xmlDelay, "stamp")) + msgTime = JabberIsoToUnixTime(ptszTimeStamp); + } + } + } } MCONTACT hContact = HContactFromJID(from); @@ -1168,15 +1184,14 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info) // check MAM support const char *szMsgId = nullptr; if (auto *n = XmlGetChildByTag(node, "stanza-id", "xmlns", JABBER_FEAT_SID)) - szMsgId = n->GetText(); + if (szMsgId = n->Attribute("id")) + setString("LastMamId", szMsgId); // If message is from a stranger (not in roster), item is nullptr JABBER_LIST_ITEM *item = ListGetItemPtr(LIST_ROSTER, from); if (item == nullptr) item = ListGetItemPtr(LIST_VCARD_TEMP, from); - time_t msgTime = 0; - // check chatstates availability if (pFromResource && XmlGetChildByTag(node, "active", "xmlns", JABBER_FEAT_CHATSTATES)) pFromResource->m_jcbManualDiscoveredCaps |= JABBER_CAPS_CHATSTATES; @@ -1370,6 +1385,12 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info) return; } + // we ignore messages without server id either if MAM is enabled + if ((info->jabberServerCaps & JABBER_CAPS_MAM) && m_iMamMode != 0 && szMsgId == nullptr) { + debugLogA("MAM is enabled, but there's no stanza-id: ignoting a message"); + return; + } + szMessage.Replace("\n", "\r\n"); if (item != nullptr) { diff --git a/protocols/JabberG/src/resource.h b/protocols/JabberG/src/resource.h index a3e3f5987f..ae97f821f8 100644 --- a/protocols/JabberG/src/resource.h +++ b/protocols/JabberG/src/resource.h @@ -114,9 +114,10 @@ #define IDC_MSGLANG 1049 #define IDC_PASSWORD 1050 #define IDC_JID 1051 -#define IDC_NEWPASSWD2 1052 #define IDC_ROSTER_SYNC 1052 #define IDC_OLDPASSWD 1053 +#define IDC_MAM_MODE 1054 +#define IDC_NEWPASSWD2 1055 #define IDC_ADDRESS1 1056 #define IDC_ADDRESS2 1057 #define IDC_CITY 1058 -- cgit v1.2.3