From 1b9b12484af65dbae34eb59baea6c8dc9c685c28 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 15 Jul 2019 17:16:20 +0300 Subject: Jabber: - global vcard hash added to the presence; - "AvatarSaved" setting isn't used anymore, because it's crazy; - when vcard reader writes our own avatar, an update is not send back to the server --- protocols/JabberG/src/jabber_iqid.cpp | 91 +++++++++++++++++++++------------ protocols/JabberG/src/jabber_proto.h | 4 +- protocols/JabberG/src/jabber_svc.cpp | 10 ++-- protocols/JabberG/src/jabber_thread.cpp | 13 ++--- protocols/JabberG/src/jabber_util.cpp | 4 +- protocols/JabberG/src/jabber_vcard.cpp | 72 ++++++++++++++------------ protocols/JabberG/src/jabber_xml.cpp | 38 ++++++++++++++ protocols/JabberG/src/jabber_xml.h | 16 ++++++ 8 files changed, 164 insertions(+), 84 deletions(-) (limited to 'protocols/JabberG') 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(" 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(" 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, 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, 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<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 @@ -28,6 +28,44 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TAG_MAX_LEN 128 #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 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: -- cgit v1.2.3