summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xprotocols/JabberG/src/jabber_iqid.cpp91
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h4
-rw-r--r--protocols/JabberG/src/jabber_svc.cpp10
-rwxr-xr-xprotocols/JabberG/src/jabber_thread.cpp13
-rwxr-xr-xprotocols/JabberG/src/jabber_util.cpp4
-rw-r--r--protocols/JabberG/src/jabber_vcard.cpp72
-rw-r--r--protocols/JabberG/src/jabber_xml.cpp38
-rw-r--r--protocols/JabberG/src/jabber_xml.h16
8 files changed, 164 insertions, 84 deletions
diff --git a/protocols/JabberG/src/jabber_iqid.cpp b/protocols/JabberG/src/jabber_iqid.cpp
index 9150e6aeb2..8c9ecf530e 100755
--- a/protocols/JabberG/src/jabber_iqid.cpp
+++ b/protocols/JabberG/src/jabber_iqid.cpp
@@ -205,10 +205,16 @@ void CJabberProto::OnLoggedIn()
QueryPrivacyLists(m_ThreadInfo);
ptrA szServerName(getStringA("LastLoggedServer"));
- if (szServerName == nullptr || mir_strcmp(m_ThreadInfo->conn.server, szServerName))
- SendGetVcard(m_szJabberJID);
+ if (szServerName == nullptr || mir_strcmp(m_ThreadInfo->conn.server, szServerName)) {
+ setString("LastLoggedServer", m_ThreadInfo->conn.server);
+ SendGetVcard();
+ }
+ else {
+ time_t lastReadVcard(getDword("LastGetVcard"));
+ if (time(0) - lastReadVcard > 84600) // read vcard on login once a day
+ SendGetVcard();
+ }
- setString("LastLoggedServer", m_ThreadInfo->conn.server);
m_pepServices.ResetPublishAll();
if (m_bEnableStreamMgmt)
m_StrmMgmt.CheckState();
@@ -564,6 +570,21 @@ void CJabberProto::OnIqResultGetVcardPhoto(const TiXmlElement *n, MCONTACT hCont
if (szPicType == nullptr)
return;
+ BYTE digest[MIR_SHA1_HASH_SIZE];
+ mir_sha1_ctx sha1ctx;
+ mir_sha1_init(&sha1ctx);
+ mir_sha1_append(&sha1ctx, (BYTE *)buffer.get(), bufferLen);
+ mir_sha1_finish(&sha1ctx, digest);
+
+ char digestHex[MIR_SHA1_HASH_SIZE*2 + 1];
+ bin2hex(digest, sizeof(digest), digestHex);
+ CMStringA oldHash(getMStringA(hContact, "AvatarHash"));
+ if (oldHash == digestHex) {
+ hasPhoto = true;
+ debugLogA("same avatar hash, skipping");
+ return;
+ }
+
wchar_t szAvatarFileName[MAX_PATH];
GetAvatarFileName(hContact, szAvatarFileName, _countof(szAvatarFileName));
@@ -580,11 +601,13 @@ void CJabberProto::OnIqResultGetVcardPhoto(const TiXmlElement *n, MCONTACT hCont
return;
debugLogA("%d bytes written", nWritten);
+
+ setString(hContact, "AvatarHash", digestHex);
+
if (hContact == 0) {
hasPhoto = true;
- CallService(MS_AV_SETMYAVATARW, (WPARAM)m_szModuleName, (LPARAM)szAvatarFileName);
-
debugLogW(L"My picture saved to %s", szAvatarFileName);
+ ReportSelfAvatarChanged();
}
else {
ptrA jid(getUStringA(hContact, "jid"));
@@ -613,12 +636,9 @@ void CJabberProto::OnIqResultGetVcardPhoto(const TiXmlElement *n, MCONTACT hCont
void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*)
{
- const TiXmlElement *vCardNode;
- const char *type, *jid;
- MCONTACT hContact;
- DBVARIANT dbv;
-
debugLogA("<iq/> iqIdGetVcard");
+
+ const char *type, *jid;
if ((type = XmlGetAttr(iqNode, "type")) == nullptr) return;
if ((jid = XmlGetAttr(iqNode, "from")) == nullptr) return;
int id = JabberGetPacketID(iqNode);
@@ -626,7 +646,7 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
if (id == m_nJabberSearchID) {
m_nJabberSearchID = -1;
- if ((vCardNode = XmlFirstChild(iqNode, "vCard")) != nullptr) {
+ if (auto *vCardNode = XmlFirstChild(iqNode, "vCard")) {
if (!mir_strcmp(type, "result")) {
PROTOSEARCHRESULT psr = { 0 };
psr.cbSize = sizeof(psr);
@@ -645,6 +665,7 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
return;
}
+ MCONTACT hContact;
size_t len = mir_strlen(m_szJabberJID);
if (!strnicmp(jid, m_szJabberJID, len) && (jid[len] == '/' || jid[len] == '\0')) {
hContact = 0;
@@ -674,7 +695,14 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
hasOrgname = false, hasOrgunit = false, hasRole = false, hasTitle = false, hasDesc = false, hasPhoto = false;
int nEmail = 0, nPhone = 0, nYear, nMonth, nDay;
- if ((vCardNode = XmlFirstChild(iqNode, "vCard")) != nullptr) {
+ CMStringA szNodeHash;
+ if (auto *vCardNode = XmlFirstChild(iqNode, "vCard")) {
+ if (hContact == 0) {
+ XmlNodeHash hasher;
+ vCardNode->Accept(&hasher);
+ szNodeHash = hasher.getResult();
+ }
+
for (auto *n : TiXmlEnum(vCardNode)) {
if (n->Name() == nullptr)
continue;
@@ -986,8 +1014,7 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
else {
char text[100];
mir_snprintf(text, "e-mail%d", nEmail - 1);
- if (db_get_s(hContact, m_szModuleName, text, &dbv)) break;
- db_free(&dbv);
+ if (!ptrA(getStringA(hContact, text))) break;
delSetting(hContact, text);
}
nEmail++;
@@ -997,9 +1024,8 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
while (true) {
char text[100];
mir_snprintf(text, "e-mail%d", nEmail);
- if (getString(text, &dbv)) break;
- db_free(&dbv);
- delSetting(text);
+ if (delSetting(text))
+ break;
mir_snprintf(text, "e-mailFlag%d", nEmail);
delSetting(text);
nEmail++;
@@ -1031,9 +1057,8 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
while (true) {
char text[100];
mir_snprintf(text, "Phone%d", nPhone);
- if (getString(text, &dbv)) break;
- db_free(&dbv);
- delSetting(text);
+ if (delSetting(text))
+ break;
mir_snprintf(text, "PhoneFlag%d", nPhone);
delSetting(text);
nPhone++;
@@ -1078,12 +1103,8 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
delSetting(hContact, "About");
if (!hasPhoto) {
debugLogA("Has no avatar");
- delSetting(hContact, "AvatarHash");
-
- if (ptrW(getWStringA(hContact, "AvatarSaved")) != nullptr) {
- delSetting(hContact, "AvatarSaved");
+ if (!delSetting(hContact, "AvatarHash"))
ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, nullptr, 0);
- }
}
if (id == m_ThreadInfo->resolveID) {
@@ -1091,8 +1112,15 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
ResolveTransportNicks((p != nullptr) ? p + 1 : jid);
}
else {
- if ((hContact = HContactFromJID(jid)) != 0)
+ if (hContact != 0)
ProtoBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1);
+ else {
+ CMStringA oldHash(getMStringA("VCardHash"));
+ if (oldHash != szNodeHash) {
+ setString("VCardHash", szNodeHash);
+ SendPresence(m_iStatus, false);
+ }
+ }
WindowList_Broadcast(m_hWindowList, WM_JABBER_REFRESH_VCARD, 0, 0);
}
}
@@ -1100,8 +1128,10 @@ void CJabberProto::OnIqResultGetVcard(const TiXmlElement *iqNode, CJabberIqInfo*
void CJabberProto::OnIqResultSetVcard(const TiXmlElement *iqNode, CJabberIqInfo*)
{
debugLogA("<iq/> iqIdSetVcard");
- if (XmlGetAttr(iqNode, "type"))
+ if (XmlGetAttr(iqNode, "type")) {
WindowList_Broadcast(m_hWindowList, WM_JABBER_REFRESH_VCARD, 0, 0);
+ SendPresence(m_iStatus, false);
+ }
}
void CJabberProto::OnIqResultSetSearch(const TiXmlElement *iqNode, CJabberIqInfo*)
@@ -1247,11 +1277,8 @@ void CJabberProto::OnIqResultGetVCardAvatar(const TiXmlElement *iqNode, CJabberI
if (vCard == nullptr) return;
if (vCard->NoChildren()) {
- delSetting(hContact, "AvatarHash");
- if (ptrW(getWStringA(hContact, "AvatarSaved")) != nullptr) {
- delSetting(hContact, "AvatarSaved");
+ if (!delSetting(hContact, "AvatarHash"))
ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, nullptr, 0);
- }
return;
}
@@ -1343,7 +1370,7 @@ void CJabberProto::OnIqResultGotAvatar(MCONTACT hContact, const char *pszText, c
fclose(out);
char buffer[41];
- setString(hContact, "AvatarSaved", bin2hex(digest, sizeof(digest), buffer));
+ setString(hContact, "AvatarHash", bin2hex(digest, sizeof(digest), buffer));
ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, HANDLE(&ai), 0);
debugLogW(L"Broadcast new avatar: %s", ai.filename);
}
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h
index dd29dda47b..bcd444066c 100755
--- a/protocols/JabberG/src/jabber_proto.h
+++ b/protocols/JabberG/src/jabber_proto.h
@@ -795,7 +795,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
MCONTACT ChatRoomHContactFromJID(const char *jid);
void SendVisibleInvisiblePresence(bool invisible);
void SendPresenceTo(int status, const char* to, const TiXmlElement *extra = nullptr, const char *msg = nullptr);
- void SendPresence(int m_iStatus, bool bSendToAll);
+ void SendPresence(int iStatus, bool bSendToAll);
void RebuildInfoFrame(void);
void InitInfoFrame(void);
@@ -818,7 +818,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
wchar_t m_szPhotoFileName[MAX_PATH];
void OnUserInfoInit_VCard(WPARAM, LPARAM);
- int SendGetVcard(const char *jid);
+ int SendGetVcard(const char *jid = nullptr);
void AppendVcardFromDB(TiXmlElement *n, char* tag, char* key);
void SetServerVcard(BOOL bPhotoChanged, wchar_t* szPhotoFileName);
void SaveVcardToDB(HWND hwndPage, int iPage);
diff --git a/protocols/JabberG/src/jabber_svc.cpp b/protocols/JabberG/src/jabber_svc.cpp
index fccdcdef0b..d1119b6bbf 100644
--- a/protocols/JabberG/src/jabber_svc.cpp
+++ b/protocols/JabberG/src/jabber_svc.cpp
@@ -127,11 +127,8 @@ INT_PTR __cdecl CJabberProto::JabberGetAvatarInfo(WPARAM wParam, LPARAM lParam)
pai->format = (pai->hContact == 0) ? PA_FORMAT_PNG : getByte(pai->hContact, "AvatarType", 0);
if (::_waccess(pai->filename, 0) == 0) {
- ptrA szSavedHash(getStringA(pai->hContact, "AvatarSaved"));
- if (szSavedHash != nullptr && !mir_strcmp(szSavedHash, szHashValue)) {
- debugLogA("Avatar is Ok: %s == %s", szSavedHash, szHashValue);
- return GAIR_SUCCESS;
- }
+ debugLogA("Avatar is Ok");
+ return GAIR_SUCCESS;
}
if ((wParam & GAIF_FORCE) != 0 && pai->hContact != 0 && m_bJabberOnline) {
@@ -236,7 +233,6 @@ INT_PTR __cdecl CJabberProto::JabberSetAvatar(WPARAM, LPARAM lParam)
GetAvatarFileName(0, tFileName, MAX_PATH);
DeleteFile(tFileName);
- delSetting("AvatarSaved");
delSetting("AvatarHash");
}
else {
@@ -280,7 +276,7 @@ INT_PTR __cdecl CJabberProto::JabberSetAvatar(WPARAM, LPARAM lParam)
}
delete[] pResult;
- setString("AvatarSaved", buf);
+ setString("AvatarHash", buf);
}
return 0;
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index 545c20131b..25e4a43315 100755
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -1641,12 +1641,13 @@ void CJabberProto::OnProcessPresence(const TiXmlElement *node, ThreadData *info)
auto *szPhoto = XmlGetChildText(xNode, "photo");
if (szPhoto && !bHasAvatar) {
if (mir_strlen(szPhoto)) {
- setString(hContact, "AvatarHash", szPhoto);
bHasAvatar = true;
- ptrA saved(getStringA(hContact, "AvatarSaved"));
+ ptrA saved(getStringA(hContact, "AvatarHash"));
if (saved == nullptr || mir_strcmp(saved, szPhoto)) {
- debugLogA("Avatar was changed. Using vcard-temp:x:update");
+ debugLogA("Avatar was changed, reloading");
+ setString(hContact, "AvatarHash", szPhoto);
ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, nullptr, 0);
+ continue;
}
}
else bRemovedAvatar = true;
@@ -1666,12 +1667,8 @@ void CJabberProto::OnProcessPresence(const TiXmlElement *node, ThreadData *info)
if (!bHasAvatar && bRemovedAvatar) {
debugLogA("Has no avatar");
- delSetting(hContact, "AvatarHash");
-
- if (ptrW(getWStringA(hContact, "AvatarSaved")) != nullptr) {
- delSetting(hContact, "AvatarSaved");
+ if (!delSetting(hContact, "AvatarHash"))
ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, nullptr, 0);
- }
}
}
return;
diff --git a/protocols/JabberG/src/jabber_util.cpp b/protocols/JabberG/src/jabber_util.cpp
index cfa261de6b..db99565983 100755
--- a/protocols/JabberG/src/jabber_util.cpp
+++ b/protocols/JabberG/src/jabber_util.cpp
@@ -912,7 +912,7 @@ void __cdecl CJabberProto::LoadHttpAvatars(void* param)
mir_sha1_finish(&sha, digest);
bin2hex(digest, sizeof(digest), buffer);
- ptrA cmpsha(getStringA(ai.hContact, "AvatarSaved"));
+ ptrA cmpsha(getStringA(ai.hContact, "AvatarHash"));
if (cmpsha == nullptr || strnicmp(cmpsha, buffer, sizeof(buffer))) {
wchar_t tszFileName[MAX_PATH];
GetAvatarFileName(ai.hContact, tszFileName, _countof(tszFileName));
@@ -921,7 +921,7 @@ void __cdecl CJabberProto::LoadHttpAvatars(void* param)
if (out != nullptr) {
fwrite(res->pData, res->dataLength, 1, out);
fclose(out);
- setString(ai.hContact, "AvatarSaved", buffer);
+ setString(ai.hContact, "AvatarHash", buffer);
ProtoBroadcastAck(ai.hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai, 0);
debugLogW(L"Broadcast new avatar: %s", ai.filename);
}
diff --git a/protocols/JabberG/src/jabber_vcard.cpp b/protocols/JabberG/src/jabber_vcard.cpp
index f5e8f27531..75c916b176 100644
--- a/protocols/JabberG/src/jabber_vcard.cpp
+++ b/protocols/JabberG/src/jabber_vcard.cpp
@@ -35,6 +35,15 @@ int CJabberProto::SendGetVcard(const char *jid)
{
if (!m_bJabberOnline) return 0;
+ if (jid == nullptr) {
+ jid = m_szJabberJID;
+ setDword("LastGetVcard", time(0));
+ }
+ else {
+ char szBareJid[JABBER_MAX_JID_LEN];
+ jid = JabberStripJid(jid, szBareJid, sizeof(szBareJid));
+ }
+
CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultGetVcard, JABBER_IQ_TYPE_GET, jid);
m_ThreadInfo->send(XmlNodeIq(pInfo) << XCHILDNS("vCard", JABBER_FEAT_VCARD_TEMP)
<< XATTR("prodid", "-//HandGen//NONSGML vGen v1.0//EN") << XATTR("version", "2.0"));
@@ -44,7 +53,7 @@ int CJabberProto::SendGetVcard(const char *jid)
/////////////////////////////////////////////////////////////////////////////////////////
-static void SetDialogField(CJabberProto *ppro, HWND hwndDlg, int nDlgItem, char* key, bool bTranslate = false)
+static void SetDialogField(CJabberProto *ppro, HWND hwndDlg, int nDlgItem, char *key, bool bTranslate = false)
{
ptrW tszValue(ppro->getWStringA(key));
if (tszValue != nullptr)
@@ -148,8 +157,7 @@ static INT_PTR CALLBACK HomeDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA
case WM_COMMAND:
if (((HWND)lParam == GetFocus() && HIWORD(wParam) == EN_CHANGE) ||
- ((HWND)lParam == GetDlgItem(hwndDlg, IDC_COUNTRY) && (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE)))
- {
+ ((HWND)lParam == GetDlgItem(hwndDlg, IDC_COUNTRY) && (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE))) {
ppro->m_vCardUpdates |= (1UL << iPageId);
SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
}
@@ -215,8 +223,7 @@ static INT_PTR CALLBACK WorkDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA
case WM_COMMAND:
if (((HWND)lParam == GetFocus() && HIWORD(wParam) == EN_CHANGE) ||
- ((HWND)lParam == GetDlgItem(hwndDlg, IDC_COUNTRY) && (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE)))
- {
+ ((HWND)lParam == GetDlgItem(hwndDlg, IDC_COUNTRY) && (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE))) {
ppro->m_vCardUpdates |= (1UL << iPageId);
SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
}
@@ -258,7 +265,7 @@ static INT_PTR CALLBACK PhotoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPAR
const unsigned long iPageId = 3;
wchar_t szAvatarFileName[MAX_PATH], szTempPath[MAX_PATH], szTempFileName[MAX_PATH];
- PhotoDlgProcData* dat = (PhotoDlgProcData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ PhotoDlgProcData *dat = (PhotoDlgProcData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch (msg) {
case WM_INITDIALOG:
@@ -410,12 +417,12 @@ static INT_PTR CALLBACK PhotoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPAR
else {
if (((float)(ptSize.x - rect.right)) / ptSize.x > ((float)(ptSize.y - rect.bottom)) / ptSize.y) {
ptFitSize.x = rect.right;
- ptFitSize.y = (ptSize.y*rect.right) / ptSize.x;
+ ptFitSize.y = (ptSize.y * rect.right) / ptSize.x;
pt.x = 0;
pt.y = (rect.bottom - ptFitSize.y) / 2;
}
else {
- ptFitSize.x = (ptSize.x*rect.bottom) / ptSize.y;
+ ptFitSize.x = (ptSize.x * rect.bottom) / ptSize.y;
ptFitSize.y = rect.bottom;
pt.x = (rect.right - ptFitSize.x) / 2;
pt.y = 0;
@@ -512,7 +519,7 @@ static INT_PTR CALLBACK NoteDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA
SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam);
break;
case PSN_APPLY:
- ppro->m_vCardUpdates &= ~(1UL<<iPageId);
+ ppro->m_vCardUpdates &= ~(1UL << iPageId);
ppro->SaveVcardToDB(hwndDlg, iPageId);
if (!ppro->m_vCardUpdates)
ppro->SetServerVcard(ppro->m_bPhotoChanged, ppro->m_szPhotoFileName);
@@ -601,7 +608,7 @@ static INT_PTR CALLBACK EditEmailDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam,
static INT_PTR CALLBACK EditPhoneDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
- EditDlgParam* dat = (EditDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ EditDlgParam *dat = (EditDlgParam *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch (msg) {
case WM_INITDIALOG:
@@ -729,10 +736,10 @@ static INT_PTR CALLBACK ContactDlgProc(HWND hwndDlg, UINT msg, WPARAM, LPARAM lP
lvi.iItem = 0;
for (i=0;;i++) {
mir_snprintf(idstr, "e-mail%d", i);
- ptrW email( ppro->getWStringA(idstr));
+ ptrW email(ppro->getWStringA(idstr));
if (email == nullptr) break;
- mir_snwprintf(number, L"%d", i+1);
+ mir_snwprintf(number, L"%d", i + 1);
lvi.pszText = number;
lvi.lParam = (LPARAM)i;
ListView_InsertItem(GetDlgItem(hwndDlg, IDC_EMAILS), &lvi);
@@ -750,10 +757,10 @@ static INT_PTR CALLBACK ContactDlgProc(HWND hwndDlg, UINT msg, WPARAM, LPARAM lP
lvi.iItem = 0;
for (i=0;;i++) {
mir_snprintf(idstr, "Phone%d", i);
- ptrW phone( ppro->getWStringA(idstr));
+ ptrW phone(ppro->getWStringA(idstr));
if (phone == nullptr) break;
- mir_snwprintf(number, L"%d", i+1);
+ mir_snwprintf(number, L"%d", i + 1);
lvi.pszText = number;
lvi.lParam = (LPARAM)i;
ListView_InsertItem(GetDlgItem(hwndDlg, IDC_PHONES), &lvi);
@@ -820,8 +827,8 @@ static INT_PTR CALLBACK ContactDlgProc(HWND hwndDlg, UINT msg, WPARAM, LPARAM lP
if (nm->iSubItem < 2)
break;
- const char* szIdTemplate = (nm->hdr.idFrom == IDC_PHONES) ? "Phone%d" : "e-mail%d";
- const char* szFlagTemplate = (nm->hdr.idFrom == IDC_PHONES) ? "PhoneFlag%d" : "e-mailFlag%d";
+ const char *szIdTemplate = (nm->hdr.idFrom == IDC_PHONES) ? "Phone%d" : "e-mail%d";
+ const char *szFlagTemplate = (nm->hdr.idFrom == IDC_PHONES) ? "PhoneFlag%d" : "e-mailFlag%d";
LVHITTESTINFO hti;
hti.pt.x = (short)LOWORD(GetMessagePos());
@@ -932,18 +939,17 @@ void CJabberProto::SaveVcardToDB(HWND hwndPage, int iPage)
GetDlgItemText(hwndPage, IDC_BIRTH, text, _countof(text));
setWString("BirthDate", text);
switch (SendDlgItemMessage(hwndPage, IDC_GENDER, CB_GETCURSEL, 0, 0)) {
- case 0: setString("GenderString", "Male"); break;
- case 1: setString("GenderString", "Female"); break;
- default: setString("GenderString", ""); break;
+ case 0: setString("GenderString", "Male"); break;
+ case 1: setString("GenderString", "Female"); break;
+ default: setString("GenderString", ""); break;
}
GetDlgItemText(hwndPage, IDC_OCCUPATION, text, _countof(text));
setWString("Role", text);
GetDlgItemText(hwndPage, IDC_HOMEPAGE, text, _countof(text));
setWString("Homepage", text);
break;
-
- // Page 1: Home
- case 1:
+
+ case 1: // Page 1: Home
GetDlgItemText(hwndPage, IDC_ADDRESS1, text, _countof(text));
setWString("Street", text);
GetDlgItemText(hwndPage, IDC_ADDRESS2, text, _countof(text));
@@ -961,9 +967,8 @@ void CJabberProto::SaveVcardToDB(HWND hwndPage, int iPage)
mir_free(country);
}
break;
-
- // Page 2: Work
- case 2:
+
+ case 2: // Page 2: Work
GetDlgItemText(hwndPage, IDC_COMPANY, text, _countof(text));
setWString("Company", text);
GetDlgItemText(hwndPage, IDC_DEPARTMENT, text, _countof(text));
@@ -988,11 +993,10 @@ void CJabberProto::SaveVcardToDB(HWND hwndPage, int iPage)
}
break;
- // Page 3: Photo
- // not needed to be saved into db
+ // Page 3: Photo
+ // not needed to be saved into db
- // Page 4: Note
- case 4:
+ case 4: // Page 4: Note
GetDlgItemText(hwndPage, IDC_DESC, text, _countof(text));
setWString("About", text);
break;
@@ -1008,7 +1012,7 @@ void CJabberProto::AppendVcardFromDB(TiXmlElement *n, char *tag, char *key)
n << XCHILD(tag, tszValue);
}
-void CJabberProto::SetServerVcard(BOOL bPhotoChanged, wchar_t* szPhotoFileName)
+void CJabberProto::SetServerVcard(BOOL bPhotoChanged, wchar_t *szPhotoFileName)
{
if (!m_bJabberOnline) return;
@@ -1114,7 +1118,6 @@ void CJabberProto::SetServerVcard(BOOL bPhotoChanged, wchar_t* szPhotoFileName)
if (szFileName == nullptr || szFileName[0] == 0) {
v << XCHILD("PHOTO");
DeleteFile(szAvatarName);
- delSetting("AvatarSaved");
delSetting("AvatarHash");
}
else {
@@ -1156,7 +1159,6 @@ void CJabberProto::SetServerVcard(BOOL bPhotoChanged, wchar_t* szPhotoFileName)
}
setString("AvatarHash", buf);
- setString("AvatarSaved", buf);
}
}
}
@@ -1165,6 +1167,10 @@ void CJabberProto::SetServerVcard(BOOL bPhotoChanged, wchar_t* szPhotoFileName)
}
}
+ XmlNodeHash hasher;
+ v->Accept(&hasher);
+ setString("VCardHash", hasher.getResult());
+
m_ThreadInfo->send(iq);
}
@@ -1211,5 +1217,5 @@ void CJabberProto::OnUserInfoInit_VCard(WPARAM wParam, LPARAM)
odp.szTab.w = LPGENW("Note");
g_plugin.addUserInfo(wParam, &odp);
- SendGetVcard(m_szJabberJID);
+ SendGetVcard();
}
diff --git a/protocols/JabberG/src/jabber_xml.cpp b/protocols/JabberG/src/jabber_xml.cpp
index b981aab7fb..cc0dc76c66 100644
--- a/protocols/JabberG/src/jabber_xml.cpp
+++ b/protocols/JabberG/src/jabber_xml.cpp
@@ -29,6 +29,44 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ATTR_MAX_LEN 8192
/////////////////////////////////////////////////////////////////////////////////////////
+// XmlNodeHash class members
+
+XmlNodeHash::XmlNodeHash()
+{
+ mir_md5_init(&state);
+}
+
+bool XmlNodeHash::VisitEnter(const TiXmlElement &pNode, const tinyxml2::XMLAttribute *attr)
+{
+ add(pNode.Name());
+ add(pNode.GetText());
+
+ for (auto *p = attr; p != nullptr; p = p->Next()) {
+ add(p->Name());
+ add(p->Value());
+ }
+
+ return true;
+}
+
+void XmlNodeHash::add(const char *str)
+{
+ if (str)
+ mir_md5_append(&state, (const BYTE *)str, strlen(str));
+}
+
+CMStringA XmlNodeHash::getResult()
+{
+ BYTE digest[16];
+ mir_md5_finish(&state, digest);
+
+ CMStringA res;
+ res.Truncate(33);
+ bin2hex(digest, sizeof(digest), res.GetBuffer());
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
// XmlNodeIq class members
XmlNodeIq::XmlNodeIq(const char *type, int id, const char *to) :
diff --git a/protocols/JabberG/src/jabber_xml.h b/protocols/JabberG/src/jabber_xml.h
index 5d96ded78f..c4b70e6fd9 100644
--- a/protocols/JabberG/src/jabber_xml.h
+++ b/protocols/JabberG/src/jabber_xml.h
@@ -28,6 +28,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void XmlAddAttrID(TiXmlElement*, int id);
+class XmlNodeHash : public tinyxml2::XMLVisitor
+{
+ mir_md5_state_t state;
+
+ void add(const char *);
+
+public:
+ XmlNodeHash();
+
+ CMStringA getResult();
+
+ virtual bool VisitEnter(const TiXmlElement &, const tinyxml2::XMLAttribute *);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
class XmlNode : public TiXmlDocument, private MNonCopyable
{
protected: