/* Jabber Protocol Plugin for Miranda NG Copyright (c) 2002-04 Santithorn Bunchua Copyright (c) 2005-12 George Hazan Copyright (c) 2012-14 Miranda NG project 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 "jabber.h" #include #include #include #include "jabber_iq.h" #include "jabber_caps.h" ///////////////////////////////////////////////////////////////////////////////////////// int CJabberProto::SendGetVcard(const TCHAR *jid) { if (!m_bJabberOnline) return 0; CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultGetVcard, JABBER_IQ_TYPE_GET, jid); m_ThreadInfo->send( XmlNodeIq(pInfo) << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP) << XATTR(_T("prodid"), _T("-//HandGen//NONSGML vGen v1.0//EN")) << XATTR(_T("version"), _T("2.0"))); return pInfo->GetIqId(); } ///////////////////////////////////////////////////////////////////////////////////////// static void SetDialogField(CJabberProto *ppro, HWND hwndDlg, int nDlgItem, char* key, bool bTranslate = false) { ptrT tszValue( ppro->getTStringA(key)); if (tszValue != NULL) SetDlgItemText(hwndDlg, nDlgItem, (bTranslate) ? TranslateTS(tszValue) : tszValue); else SetDlgItemTextA(hwndDlg, nDlgItem, ""); } static INT_PTR CALLBACK PersonalDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned long iPageId = 0; CJabberProto *ppro = (CJabberProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: if (lParam) { ppro = (CJabberProto*)lParam; TranslateDialogDefault(hwndDlg); SendMessage(GetDlgItem(hwndDlg, IDC_GENDER), CB_ADDSTRING, 0, (LPARAM)TranslateT("Male")); SendMessage(GetDlgItem(hwndDlg, IDC_GENDER), CB_ADDSTRING, 0, (LPARAM)TranslateT("Female")); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0); ppro->WindowSubscribe(hwndDlg); } break; case WM_JABBER_REFRESH_VCARD: SetDialogField(ppro, hwndDlg, IDC_FULLNAME, "FullName"); SetDialogField(ppro, hwndDlg, IDC_NICKNAME, "Nick"); SetDialogField(ppro, hwndDlg, IDC_FIRSTNAME, "FirstName"); SetDialogField(ppro, hwndDlg, IDC_MIDDLE, "MiddleName"); SetDialogField(ppro, hwndDlg, IDC_LASTNAME, "LastName"); SetDialogField(ppro, hwndDlg, IDC_BIRTH, "BirthDate"); SetDialogField(ppro, hwndDlg, IDC_GENDER, "GenderString", true); SetDialogField(ppro, hwndDlg, IDC_OCCUPATION, "Role"); SetDialogField(ppro, hwndDlg, IDC_HOMEPAGE, "Homepage"); break; case WM_COMMAND: if (((HWND)lParam==GetFocus() && HIWORD(wParam)==EN_CHANGE) || ((HWND)lParam==GetDlgItem(hwndDlg, IDC_GENDER) && (HIWORD(wParam)==CBN_EDITCHANGE||HIWORD(wParam)==CBN_SELCHANGE))) { ppro->m_vCardUpdates |= (1UL<idFrom == 0) { switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: ppro->m_vCardUpdates &= ~(1UL<SaveVcardToDB(hwndDlg, iPageId); if (!ppro->m_vCardUpdates) ppro->SetServerVcard(ppro->m_bPhotoChanged, ppro->m_szPhotoFileName); break; } } break; case WM_DESTROY: ppro->WindowUnsubscribe(hwndDlg); break; } return FALSE; } static INT_PTR CALLBACK HomeDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned long iPageId = 1; CJabberProto *ppro = (CJabberProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: if (lParam) { ppro = (CJabberProto*)lParam; TranslateDialogDefault(hwndDlg); for (int i=0; i < g_cbCountries; i++) { if (g_countries[i].id != 0xFFFF && g_countries[i].id != 0) { TCHAR *country = mir_a2t(g_countries[i].szName); SendMessage(GetDlgItem(hwndDlg, IDC_COUNTRY), CB_ADDSTRING, 0, (LPARAM)TranslateTS(country)); mir_free(country); } } SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0); ppro->WindowSubscribe(hwndDlg); } break; case WM_JABBER_REFRESH_VCARD: SetDialogField(ppro, hwndDlg, IDC_ADDRESS1, "Street"); SetDialogField(ppro, hwndDlg, IDC_ADDRESS2, "Street2"); SetDialogField(ppro, hwndDlg, IDC_CITY, "City"); SetDialogField(ppro, hwndDlg, IDC_STATE, "State"); SetDialogField(ppro, hwndDlg, IDC_ZIP, "ZIP"); SetDialogField(ppro, hwndDlg, IDC_COUNTRY, "Country", true); break; 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))) { ppro->m_vCardUpdates |= (1UL<idFrom == 0) { switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: ppro->m_vCardUpdates &= ~(1UL<SaveVcardToDB(hwndDlg, iPageId); if (!ppro->m_vCardUpdates) ppro->SetServerVcard(ppro->m_bPhotoChanged, ppro->m_szPhotoFileName); break; } } break; case WM_DESTROY: ppro->WindowUnsubscribe(hwndDlg); break; } return FALSE; } static INT_PTR CALLBACK WorkDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned long iPageId = 2; CJabberProto *ppro = (CJabberProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: if (lParam) { // proto info is available ppro = (CJabberProto*)lParam; TranslateDialogDefault(hwndDlg); for (int i=0; i < g_cbCountries; i++) { if (g_countries[i].id != 0xFFFF && g_countries[i].id != 0) { TCHAR *country = mir_a2t(g_countries[i].szName); SendMessage(GetDlgItem(hwndDlg, IDC_COUNTRY), CB_ADDSTRING, 0, (LPARAM)TranslateTS(country)); mir_free(country); } } SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0); ppro->WindowSubscribe(hwndDlg); } break; case WM_JABBER_REFRESH_VCARD: SetDialogField(ppro, hwndDlg, IDC_COMPANY, "Company"); SetDialogField(ppro, hwndDlg, IDC_DEPARTMENT, "CompanyDepartment"); SetDialogField(ppro, hwndDlg, IDC_TITLE, "CompanyPosition"); SetDialogField(ppro, hwndDlg, IDC_ADDRESS1, "CompanyStreet"); SetDialogField(ppro, hwndDlg, IDC_ADDRESS2, "CompanyStreet2"); SetDialogField(ppro, hwndDlg, IDC_CITY, "CompanyCity"); SetDialogField(ppro, hwndDlg, IDC_STATE, "CompanyState"); SetDialogField(ppro, hwndDlg, IDC_ZIP, "CompanyZIP"); SetDialogField(ppro, hwndDlg, IDC_COUNTRY, "CompanyCountry", true); break; 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))) { ppro->m_vCardUpdates |= (1UL<idFrom == 0) { switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: ppro->m_vCardUpdates &= ~(1UL<SaveVcardToDB(hwndDlg, iPageId); if (!ppro->m_vCardUpdates) ppro->SetServerVcard(ppro->m_bPhotoChanged, ppro->m_szPhotoFileName); break; } } break; case WM_DESTROY: ppro->WindowUnsubscribe(hwndDlg); break; } return FALSE; } ///////////////////////////////////////////////////////////////////////////////////////// struct PhotoDlgProcData { CJabberProto *ppro; // char szPhotoFileName[MAX_PATH]; // BOOL bPhotoChanged; HBITMAP hBitmap; }; static INT_PTR CALLBACK PhotoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned long iPageId = 3; TCHAR szAvatarFileName[ MAX_PATH ], szTempPath[MAX_PATH], szTempFileName[MAX_PATH]; PhotoDlgProcData* dat = (PhotoDlgProcData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: if (!lParam) break; // Launched from userinfo TranslateDialogDefault(hwndDlg); SendDlgItemMessage(hwndDlg, IDC_LOAD, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPEN), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0)); SendDlgItemMessage(hwndDlg, IDC_LOAD, BUTTONSETASFLATBTN, TRUE, 0); SendDlgItemMessage(hwndDlg, IDC_DELETE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0)); SendDlgItemMessage(hwndDlg, IDC_DELETE, BUTTONSETASFLATBTN, TRUE, 0); ShowWindow(GetDlgItem(hwndDlg, IDC_SAVE), SW_HIDE); { dat = new PhotoDlgProcData; dat->ppro = (CJabberProto*)lParam; dat->hBitmap = NULL; dat->ppro->m_bPhotoChanged = FALSE; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); dat->ppro->WindowSubscribe(hwndDlg); } SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0); break; case WM_JABBER_REFRESH_VCARD: if (dat->hBitmap) { DeleteObject(dat->hBitmap); dat->hBitmap = NULL; DeleteFile(dat->ppro->m_szPhotoFileName); dat->ppro->m_szPhotoFileName[0] = '\0'; } EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); dat->ppro->GetAvatarFileName(NULL, szAvatarFileName, SIZEOF(szAvatarFileName)); if (_taccess(szAvatarFileName, 0) == 0) { if (GetTempPath(SIZEOF(szTempPath), szTempPath) <= 0) _tcscpy(szTempPath, _T(".\\")); if (GetTempFileName(szTempPath, _T("jab"), 0, szTempFileName) > 0) { dat->ppro->debugLogA("Temp file = %S", szTempFileName); if (CopyFile(szAvatarFileName, szTempFileName, FALSE) == TRUE) { char* p = mir_t2a(szTempFileName); if ((dat->hBitmap=(HBITMAP) CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)p)) != NULL) { FIP->FI_Premultiply(dat->hBitmap); _tcscpy(dat->ppro->m_szPhotoFileName, szTempFileName); EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); } else DeleteFile(szTempFileName); mir_free(p); } else DeleteFile(szTempFileName); } } dat->ppro->m_bPhotoChanged = FALSE; InvalidateRect(hwndDlg, NULL, TRUE); UpdateWindow(hwndDlg); break; case WM_JABBER_CHANGED: dat->ppro->SetServerVcard(dat->ppro->m_bPhotoChanged, dat->ppro->m_szPhotoFileName); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_LOAD: { TCHAR szFilter[512]; TCHAR szFileName[MAX_PATH]; CallService(MS_UTILS_GETBITMAPFILTERSTRINGST, SIZEOF(szFilter), (LPARAM)szFilter); OPENFILENAME ofn = {0}; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwndDlg; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST | OFN_DONTADDTORECENT; szFileName[0] = '\0'; if (GetOpenFileName(&ofn)) { struct _stat st; HBITMAP hNewBitmap; dat->ppro->debugLogA("File selected is %S", szFileName); if (_tstat(szFileName, &st)<0 || st.st_size>40*1024) { MessageBox(hwndDlg, TranslateT("Only JPG, GIF, and BMP image files smaller than 40 KB are supported."), TranslateT("Jabber vCard"), MB_OK|MB_SETFOREGROUND); break; } if (GetTempPath(SIZEOF(szTempPath), szTempPath) <= 0) _tcscpy(szTempPath, _T(".\\")); if (GetTempFileName(szTempPath, _T("jab"), 0, szTempFileName) > 0) { dat->ppro->debugLogA("Temp file = %S", szTempFileName); if (CopyFile(szFileName, szTempFileName, FALSE) == TRUE) { char* pszTemp = mir_t2a(szTempFileName); if ((hNewBitmap=(HBITMAP) CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)pszTemp)) != NULL) { if (dat->hBitmap) { DeleteObject(dat->hBitmap); DeleteFile(dat->ppro->m_szPhotoFileName); } dat->hBitmap = hNewBitmap; _tcscpy(dat->ppro->m_szPhotoFileName, szTempFileName); dat->ppro->m_bPhotoChanged = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); InvalidateRect(hwndDlg, NULL, TRUE); UpdateWindow(hwndDlg); dat->ppro->m_vCardUpdates |= (1UL<hBitmap) { DeleteObject(dat->hBitmap); dat->hBitmap = NULL; DeleteFile(dat->ppro->m_szPhotoFileName); dat->ppro->m_szPhotoFileName[0] = '\0'; dat->ppro->m_bPhotoChanged = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); InvalidateRect(hwndDlg, NULL, TRUE); UpdateWindow(hwndDlg); dat->ppro->m_vCardUpdates |= (1UL<hBitmap) { BITMAP bm; HDC hdcMem; HWND hwndCanvas; HDC hdcCanvas; POINT ptSize, ptOrg, pt, ptFitSize; RECT rect; hwndCanvas = GetDlgItem(hwndDlg, IDC_CANVAS); hdcCanvas = GetDC(hwndCanvas); hdcMem = CreateCompatibleDC(hdcCanvas); SelectObject(hdcMem, dat->hBitmap); SetMapMode(hdcMem, GetMapMode(hdcCanvas)); GetObject(dat->hBitmap, sizeof(BITMAP), (LPVOID) &bm); ptSize.x = bm.bmWidth; ptSize.y = bm.bmHeight; DPtoLP(hdcCanvas, &ptSize, 1); ptOrg.x = ptOrg.y = 0; DPtoLP(hdcMem, &ptOrg, 1); GetClientRect(hwndCanvas, &rect); InvalidateRect(hwndCanvas, NULL, TRUE); UpdateWindow(hwndCanvas); if (ptSize.x<=rect.right && ptSize.y<=rect.bottom) { pt.x = (rect.right - ptSize.x)/2; pt.y = (rect.bottom - ptSize.y)/2; ptFitSize = ptSize; } 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; pt.x = 0; pt.y = (rect.bottom - ptFitSize.y)/2; } else { ptFitSize.x = (ptSize.x*rect.bottom)/ptSize.y; ptFitSize.y = rect.bottom; pt.x = (rect.right - ptFitSize.x)/2; pt.y = 0; } } RECT rc; GetClientRect(hwndCanvas, &rc); if (IsThemeActive()) DrawThemeParentBackground(hwndCanvas, hdcCanvas, &rc); else FillRect(hdcCanvas, &rc, (HBRUSH)GetSysColorBrush(COLOR_BTNFACE)); if (bm.bmBitsPixel == 32) { BLENDFUNCTION bf = {0}; bf.AlphaFormat = AC_SRC_ALPHA; bf.BlendOp = AC_SRC_OVER; bf.SourceConstantAlpha = 255; GdiAlphaBlend(hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, bf); } else { SetStretchBltMode(hdcCanvas, COLORONCOLOR); StretchBlt(hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, SRCCOPY); } DeleteDC(hdcMem); } break; case WM_NOTIFY: if (((LPNMHDR)lParam)->idFrom == 0) { switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: dat->ppro->m_vCardUpdates &= ~(1UL<ppro->SaveVcardToDB(hwndDlg, iPageId); if (!dat->ppro->m_vCardUpdates) dat->ppro->SetServerVcard(dat->ppro->m_bPhotoChanged, dat->ppro->m_szPhotoFileName); break; } } break; case WM_DESTROY: DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_LOAD, BM_SETIMAGE, IMAGE_ICON, 0)); DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_DELETE, BM_SETIMAGE, IMAGE_ICON, 0)); dat->ppro->WindowUnsubscribe(hwndDlg); if (dat->hBitmap) { dat->ppro->debugLogA("Delete bitmap"); DeleteObject(dat->hBitmap); DeleteFile(dat->ppro->m_szPhotoFileName); } delete dat; break; } return FALSE; } ///////////////////////////////////////////////////////////////////////////////////////// static INT_PTR CALLBACK NoteDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned long iPageId = 4; CJabberProto *ppro = (CJabberProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: if (!lParam) break; // Launched from userinfo ppro = (CJabberProto*)lParam; TranslateDialogDefault(hwndDlg); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0); ppro->WindowSubscribe(hwndDlg); break; case WM_JABBER_REFRESH_VCARD: { SetDialogField(ppro, hwndDlg, IDC_DESC, "About"); break; } case WM_COMMAND: if ((HWND)lParam==GetFocus() && HIWORD(wParam)==EN_CHANGE) { ppro->m_vCardUpdates |= (1UL<idFrom == 0) { switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: ppro->m_vCardUpdates &= ~(1UL<SaveVcardToDB(hwndDlg, iPageId); if (!ppro->m_vCardUpdates) ppro->SetServerVcard(ppro->m_bPhotoChanged, ppro->m_szPhotoFileName); break; } } break; case WM_DESTROY: ppro->WindowUnsubscribe(hwndDlg); break; } return FALSE; } ///////////////////////////////////////////////////////////////////////////////////////// struct EditDlgParam { int id; CJabberProto *ppro; }; static INT_PTR CALLBACK EditEmailDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { EditDlgParam *dat = (EditDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: dat = (EditDlgParam*)lParam; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); TranslateDialogDefault(hwndDlg); if (lParam >= 0) { SetWindowText(hwndDlg, TranslateT("Jabber vCard: Edit Email Address")); char idstr[33]; mir_snprintf(idstr, SIZEOF(idstr), "e-mail%d", dat->id); ptrA email( dat->ppro->getStringA(idstr)); if (email != NULL) SetDlgItemTextA(hwndDlg, IDC_EMAIL, email); mir_snprintf(idstr, SIZEOF(idstr), "e-mailFlag%d", lParam); WORD nFlag = dat->ppro->getWord(idstr, 0); if (nFlag & JABBER_VCEMAIL_HOME) CheckDlgButton(hwndDlg, IDC_HOME, TRUE); if (nFlag & JABBER_VCEMAIL_WORK) CheckDlgButton(hwndDlg, IDC_WORK, TRUE); if (nFlag & JABBER_VCEMAIL_INTERNET) CheckDlgButton(hwndDlg, IDC_INTERNET, TRUE); if (nFlag & JABBER_VCEMAIL_X400) CheckDlgButton(hwndDlg, IDC_X400, TRUE); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: char idstr[33]; if (dat->id < 0) for (dat->id=0;;dat->id++) { mir_snprintf(idstr, SIZEOF(idstr), "e-mail%d", dat->id); if ( ptrA( dat->ppro->getStringA(idstr)) == NULL) break; } TCHAR text[128]; GetDlgItemText(hwndDlg, IDC_EMAIL, text, SIZEOF(text)); mir_snprintf(idstr, SIZEOF(idstr), "e-mail%d", dat->id); dat->ppro->setTString(idstr, text); { WORD nFlag = 0; if (IsDlgButtonChecked(hwndDlg, IDC_HOME)) nFlag |= JABBER_VCEMAIL_HOME; if (IsDlgButtonChecked(hwndDlg, IDC_WORK)) nFlag |= JABBER_VCEMAIL_WORK; if (IsDlgButtonChecked(hwndDlg, IDC_INTERNET)) nFlag |= JABBER_VCEMAIL_INTERNET; if (IsDlgButtonChecked(hwndDlg, IDC_X400)) nFlag |= JABBER_VCEMAIL_X400; mir_snprintf(idstr, SIZEOF(idstr), "e-mailFlag%d", dat->id); dat->ppro->setWord(idstr, nFlag); } // fall through case IDCANCEL: EndDialog(hwndDlg, wParam); break; } } return FALSE; } static INT_PTR CALLBACK EditPhoneDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { EditDlgParam* dat = (EditDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: dat = (EditDlgParam*)lParam; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); TranslateDialogDefault(hwndDlg); if (dat->id >= 0) { SetWindowText(hwndDlg, TranslateT("Jabber vCard: Edit Phone Number")); char idstr[33]; mir_snprintf(idstr, SIZEOF(idstr), "Phone%d", dat->id); ptrA phone( dat->ppro->getStringA(idstr)); if (phone != NULL) SetDlgItemTextA(hwndDlg, IDC_PHONE, phone); mir_snprintf(idstr, SIZEOF(idstr), "PhoneFlag%d", dat->id); int nFlag = dat->ppro->getWord(idstr, 0); if (nFlag & JABBER_VCTEL_HOME) CheckDlgButton(hwndDlg, IDC_HOME, TRUE); if (nFlag & JABBER_VCTEL_WORK) CheckDlgButton(hwndDlg, IDC_WORK, TRUE); if (nFlag & JABBER_VCTEL_VOICE) CheckDlgButton(hwndDlg, IDC_VOICE, TRUE); if (nFlag & JABBER_VCTEL_FAX) CheckDlgButton(hwndDlg, IDC_FAX, TRUE); if (nFlag & JABBER_VCTEL_PAGER) CheckDlgButton(hwndDlg, IDC_PAGER, TRUE); if (nFlag & JABBER_VCTEL_MSG) CheckDlgButton(hwndDlg, IDC_MSG, TRUE); if (nFlag & JABBER_VCTEL_CELL) CheckDlgButton(hwndDlg, IDC_CELL, TRUE); if (nFlag & JABBER_VCTEL_VIDEO) CheckDlgButton(hwndDlg, IDC_VIDEO, TRUE); if (nFlag & JABBER_VCTEL_BBS) CheckDlgButton(hwndDlg, IDC_BBS, TRUE); if (nFlag & JABBER_VCTEL_MODEM) CheckDlgButton(hwndDlg, IDC_MODEM, TRUE); if (nFlag & JABBER_VCTEL_ISDN) CheckDlgButton(hwndDlg, IDC_ISDN, TRUE); if (nFlag & JABBER_VCTEL_PCS) CheckDlgButton(hwndDlg, IDC_PCS, TRUE); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { char idstr[33]; if (dat->id < 0) for (dat->id=0;;dat->id++) { mir_snprintf(idstr, SIZEOF(idstr), "Phone%d", dat->id); if ( ptrA( dat->ppro->getStringA(idstr)) == NULL) break; } char text[128]; GetDlgItemTextA(hwndDlg, IDC_PHONE, text, SIZEOF(text)); mir_snprintf(idstr, SIZEOF(idstr), "Phone%d", dat->id); dat->ppro->setString(idstr, text); WORD nFlag = 0; if (IsDlgButtonChecked(hwndDlg, IDC_HOME)) nFlag |= JABBER_VCTEL_HOME; if (IsDlgButtonChecked(hwndDlg, IDC_WORK)) nFlag |= JABBER_VCTEL_WORK; if (IsDlgButtonChecked(hwndDlg, IDC_VOICE)) nFlag |= JABBER_VCTEL_VOICE; if (IsDlgButtonChecked(hwndDlg, IDC_FAX)) nFlag |= JABBER_VCTEL_FAX; if (IsDlgButtonChecked(hwndDlg, IDC_PAGER)) nFlag |= JABBER_VCTEL_PAGER; if (IsDlgButtonChecked(hwndDlg, IDC_MSG)) nFlag |= JABBER_VCTEL_MSG; if (IsDlgButtonChecked(hwndDlg, IDC_CELL)) nFlag |= JABBER_VCTEL_CELL; if (IsDlgButtonChecked(hwndDlg, IDC_VIDEO)) nFlag |= JABBER_VCTEL_VIDEO; if (IsDlgButtonChecked(hwndDlg, IDC_BBS)) nFlag |= JABBER_VCTEL_BBS; if (IsDlgButtonChecked(hwndDlg, IDC_MODEM)) nFlag |= JABBER_VCTEL_MODEM; if (IsDlgButtonChecked(hwndDlg, IDC_ISDN)) nFlag |= JABBER_VCTEL_ISDN; if (IsDlgButtonChecked(hwndDlg, IDC_PCS)) nFlag |= JABBER_VCTEL_PCS; mir_snprintf(idstr, SIZEOF(idstr), "PhoneFlag%d", dat->id); dat->ppro->setWord(idstr, nFlag); } // fall through case IDCANCEL: EndDialog(hwndDlg, wParam); break; } } return FALSE; } #define M_REMAKELISTS (WM_USER+1) static INT_PTR CALLBACK ContactDlgProc(HWND hwndDlg, UINT msg, WPARAM, LPARAM lParam) { const unsigned long iPageId = 5; CJabberProto *ppro = (CJabberProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch(msg) { case WM_INITDIALOG: if (!lParam) break; // Launched from userinfo ppro = (CJabberProto*)lParam; { LVCOLUMN lvc; RECT rc; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); TranslateDialogDefault(hwndDlg); GetClientRect(GetDlgItem(hwndDlg,IDC_EMAILS), &rc); rc.right -= GetSystemMetrics(SM_CXVSCROLL); lvc.mask = LVCF_WIDTH; lvc.cx = 30; ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_EMAILS), 0, &lvc); ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_PHONES), 0, &lvc); lvc.cx = rc.right - 30 - 40; ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_EMAILS), 1, &lvc); ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_PHONES), 1, &lvc); lvc.cx = 20; ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_EMAILS), 2, &lvc); ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_EMAILS), 3, &lvc); ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_PHONES), 2, &lvc); ListView_InsertColumn(GetDlgItem(hwndDlg,IDC_PHONES), 3, &lvc); SendMessage(hwndDlg, M_REMAKELISTS, 0, 0); ppro->WindowSubscribe(hwndDlg); } break; case M_REMAKELISTS: { int i; char idstr[33]; TCHAR number[20]; //e-mails ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_EMAILS)); LVITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iSubItem = 0; lvi.iItem = 0; for (i=0;;i++) { mir_snprintf(idstr, SIZEOF(idstr), "e-mail%d", i); ptrT email( ppro->getTStringA(idstr)); if (email == NULL) break; mir_sntprintf(number, SIZEOF(number), _T("%d"), i+1); lvi.pszText = number; lvi.lParam = (LPARAM)i; ListView_InsertItem(GetDlgItem(hwndDlg, IDC_EMAILS), &lvi); ListView_SetItemText(GetDlgItem(hwndDlg, IDC_EMAILS), lvi.iItem, 1, email); lvi.iItem++; } lvi.mask = LVIF_PARAM; lvi.lParam = (LPARAM)(-1); ListView_InsertItem(GetDlgItem(hwndDlg, IDC_EMAILS), &lvi); //phones ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_PHONES)); lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iSubItem = 0; lvi.iItem = 0; for (i=0;;i++) { mir_snprintf(idstr, SIZEOF(idstr), "Phone%d", i); ptrT phone( ppro->getTStringA(idstr)); if (phone == NULL) break; mir_sntprintf(number, SIZEOF(number), _T("%d"), i+1); lvi.pszText = number; lvi.lParam = (LPARAM)i; ListView_InsertItem(GetDlgItem(hwndDlg, IDC_PHONES), &lvi); ListView_SetItemText(GetDlgItem(hwndDlg, IDC_PHONES), lvi.iItem, 1, phone); lvi.iItem++; } lvi.mask = LVIF_PARAM; lvi.lParam = (LPARAM)(-1); ListView_InsertItem(GetDlgItem(hwndDlg, IDC_PHONES), &lvi); } break; case WM_NOTIFY: switch (((LPNMHDR)lParam)->idFrom) { case 0: switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: ppro->m_vCardUpdates &= ~(1UL<SaveVcardToDB(hwndDlg, iPageId); if (!ppro->m_vCardUpdates) ppro->SetServerVcard(ppro->m_bPhotoChanged, ppro->m_szPhotoFileName); break; } break; case IDC_EMAILS: case IDC_PHONES: switch (((LPNMHDR)lParam)->code) { case NM_CUSTOMDRAW: { NMLVCUSTOMDRAW *nm = (NMLVCUSTOMDRAW *) lParam; switch (nm->nmcd.dwDrawStage) { case CDDS_PREPAINT: case CDDS_ITEMPREPAINT: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW); return TRUE; case CDDS_SUBITEM|CDDS_ITEMPREPAINT: RECT rc; HICON hIcon; ListView_GetSubItemRect(nm->nmcd.hdr.hwndFrom, nm->nmcd.dwItemSpec, nm->iSubItem, LVIR_LABEL, &rc); if (nm->nmcd.lItemlParam==(LPARAM)(-1) && nm->iSubItem==3) hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ADDCONTACT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); else if (nm->iSubItem==2 && nm->nmcd.lItemlParam!=(LPARAM)(-1)) hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_EDIT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); else if (nm->iSubItem==3 && nm->nmcd.lItemlParam!=(LPARAM)(-1)) hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); else break; DrawIconEx(nm->nmcd.hdc, (rc.left+rc.right-GetSystemMetrics(SM_CXSMICON))/2, (rc.top+rc.bottom-GetSystemMetrics(SM_CYSMICON))/2,hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); DestroyIcon(hIcon); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT); return TRUE; } } break; case NM_CLICK: NMLISTVIEW *nm = (NMLISTVIEW *) lParam; 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"; LVHITTESTINFO hti; hti.pt.x = (short) LOWORD(GetMessagePos()); hti.pt.y = (short) HIWORD(GetMessagePos()); ScreenToClient(nm->hdr.hwndFrom, &hti.pt); if (ListView_SubItemHitTest(nm->hdr.hwndFrom, &hti) == -1) break; LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = hti.iItem; lvi.iSubItem = 0; ListView_GetItem(nm->hdr.hwndFrom, &lvi); if (lvi.lParam == (LPARAM)(-1)) { if (hti.iSubItem == 3) { //add EditDlgParam param = { -1, ppro }; int res; if (nm->hdr.idFrom == IDC_PHONES) res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_VCARD_ADDPHONE), hwndDlg, EditPhoneDlgProc, (LPARAM)¶m); else res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_VCARD_ADDEMAIL), hwndDlg, EditEmailDlgProc, (LPARAM)¶m); if (res != IDOK) break; SendMessage(hwndDlg, M_REMAKELISTS, 0, 0); ppro->m_vCardUpdates |= (1UL<getStringA(idstr)); if (fieldVal == NULL) break; mir_snprintf(idstr, SIZEOF(idstr), szIdTemplate, i); ppro->setString(idstr, fieldVal); mir_snprintf(idstr, SIZEOF(idstr), szFlagTemplate, i + 1); WORD nFlag = ppro->getWord(idstr, 0); mir_snprintf(idstr, SIZEOF(idstr), szFlagTemplate, i); ppro->setWord(idstr, nFlag); } mir_snprintf(idstr, SIZEOF(idstr), szIdTemplate, i); ppro->delSetting(idstr); mir_snprintf(idstr, SIZEOF(idstr), szFlagTemplate, i); ppro->delSetting(idstr); SendMessage(hwndDlg, M_REMAKELISTS, 0, 0); ppro->m_vCardUpdates |= (1UL << iPageId); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); } else if (hti.iSubItem == 2) { EditDlgParam param = { lvi.lParam, ppro }; int res; if (nm->hdr.idFrom == IDC_PHONES) res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_VCARD_ADDPHONE), hwndDlg, EditPhoneDlgProc, (LPARAM)¶m); else res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_VCARD_ADDEMAIL), hwndDlg, EditEmailDlgProc, (LPARAM)¶m); if (res != IDOK) break; SendMessage(hwndDlg,M_REMAKELISTS,0,0); ppro->m_vCardUpdates |= (1UL<WindowUnsubscribe(hwndDlg); break; } return FALSE; } void CJabberProto::SaveVcardToDB(HWND hwndPage, int iPage) { TCHAR text[2048]; // Page 0: Personal switch (iPage) { case 0: GetDlgItemText(hwndPage, IDC_FULLNAME, text, SIZEOF(text)); setTString("FullName", text); GetDlgItemText(hwndPage, IDC_NICKNAME, text, SIZEOF(text)); setTString("Nick", text); GetDlgItemText(hwndPage, IDC_FIRSTNAME, text, SIZEOF(text)); setTString("FirstName", text); GetDlgItemText(hwndPage, IDC_MIDDLE, text, SIZEOF(text)); setTString("MiddleName", text); GetDlgItemText(hwndPage, IDC_LASTNAME, text, SIZEOF(text)); setTString("LastName", text); GetDlgItemText(hwndPage, IDC_BIRTH, text, SIZEOF(text)); setTString("BirthDate", text); switch(SendMessage(GetDlgItem(hwndPage, IDC_GENDER), CB_GETCURSEL, 0, 0)) { case 0: setString("GenderString", "Male"); break; case 1: setString("GenderString", "Female"); break; default: setString("GenderString", ""); break; } GetDlgItemText(hwndPage, IDC_OCCUPATION, text, SIZEOF(text)); setTString("Role", text); GetDlgItemText(hwndPage, IDC_HOMEPAGE, text, SIZEOF(text)); setTString("Homepage", text); break; // Page 1: Home case 1: GetDlgItemText(hwndPage, IDC_ADDRESS1, text, SIZEOF(text)); setTString("Street", text); GetDlgItemText(hwndPage, IDC_ADDRESS2, text, SIZEOF(text)); setTString("Street2", text); GetDlgItemText(hwndPage, IDC_CITY, text, SIZEOF(text)); setTString("City", text); GetDlgItemText(hwndPage, IDC_STATE, text, SIZEOF(text)); setTString("State", text); GetDlgItemText(hwndPage, IDC_ZIP, text, SIZEOF(text)); setTString("ZIP", text); { int i = SendMessage(GetDlgItem(hwndPage, IDC_COUNTRY), CB_GETCURSEL, 0, 0); TCHAR *country = mir_a2t((i) ? g_countries[i+2].szName : g_countries[1].szName); setTString("Country", country); mir_free(country); } break; // Page 2: Work case 2: GetDlgItemText(hwndPage, IDC_COMPANY, text, SIZEOF(text)); setTString("Company", text); GetDlgItemText(hwndPage, IDC_DEPARTMENT, text, SIZEOF(text)); setTString("CompanyDepartment", text); GetDlgItemText(hwndPage, IDC_TITLE, text, SIZEOF(text)); setTString("CompanyPosition", text); GetDlgItemText(hwndPage, IDC_ADDRESS1, text, SIZEOF(text)); setTString("CompanyStreet", text); GetDlgItemText(hwndPage, IDC_ADDRESS2, text, SIZEOF(text)); setTString("CompanyStreet2", text); GetDlgItemText(hwndPage, IDC_CITY, text, SIZEOF(text)); setTString("CompanyCity", text); GetDlgItemText(hwndPage, IDC_STATE, text, SIZEOF(text)); setTString("CompanyState", text); GetDlgItemText(hwndPage, IDC_ZIP, text, SIZEOF(text)); setTString("CompanyZIP", text); { int i = SendMessage(GetDlgItem(hwndPage, IDC_COUNTRY), CB_GETCURSEL, 0, 0); TCHAR *country = mir_a2t((i) ? g_countries[i+2].szName : g_countries[1].szName); setTString("CompanyCountry", country); mir_free(country); } break; // Page 3: Photo // not needed to be saved into db // Page 4: Note case 4: GetDlgItemText(hwndPage, IDC_DESC, text, SIZEOF(text)); setTString("About", text); break; // Page 5: Contacts // is always synced with db } } void CJabberProto::AppendVcardFromDB(HXML n, char *tag, char *key) { if (n == NULL || tag == NULL || key == NULL) return; ptrT tszValue( getTStringA(key)); n << XCHILD( _A2T(tag), tszValue); } void CJabberProto::SetServerVcard(BOOL bPhotoChanged, TCHAR* szPhotoFileName) { if (!m_bJabberOnline) return; int i; char idstr[33]; XmlNodeIq iq( AddIQ(&CJabberProto::OnIqResultSetVcard, JABBER_IQ_TYPE_SET)); HXML v = iq << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP); AppendVcardFromDB(v, "FN", "FullName"); HXML n = v << XCHILD(_T("N")); AppendVcardFromDB(n, "GIVEN", "FirstName"); AppendVcardFromDB(n, "MIDDLE", "MiddleName"); AppendVcardFromDB(n, "FAMILY", "LastName"); AppendVcardFromDB(v, "NICKNAME", "Nick"); AppendVcardFromDB(v, "BDAY", "BirthDate"); AppendVcardFromDB(v, "GENDER", "GenderString"); for (i=0; ; i++) { mir_snprintf(idstr, SIZEOF(idstr), "e-mail%d", i); ptrT email( getTStringA(idstr)); if (email == NULL) break; HXML e = v << XCHILD(_T("EMAIL"), email); AppendVcardFromDB(e, "USERID", idstr); mir_snprintf(idstr, SIZEOF(idstr), "e-mailFlag%d", i); WORD nFlag = getWord(idstr, 0); if (nFlag & JABBER_VCEMAIL_HOME) e << XCHILD(_T("HOME")); if (nFlag & JABBER_VCEMAIL_WORK) e << XCHILD(_T("WORK")); if (nFlag & JABBER_VCEMAIL_INTERNET) e << XCHILD(_T("INTERNET")); if (nFlag & JABBER_VCEMAIL_X400) e << XCHILD(_T("X400")); } n = v << XCHILD(_T("ADR")); n << XCHILD(_T("HOME")); AppendVcardFromDB(n, "STREET", "Street"); AppendVcardFromDB(n, "EXTADR", "Street2"); AppendVcardFromDB(n, "EXTADD", "Street2"); // for compatibility with client using old vcard format AppendVcardFromDB(n, "LOCALITY", "City"); AppendVcardFromDB(n, "REGION", "State"); AppendVcardFromDB(n, "PCODE", "ZIP"); AppendVcardFromDB(n, "CTRY", "Country"); AppendVcardFromDB(n, "COUNTRY", "Country"); // for compatibility with client using old vcard format n = v << XCHILD(_T("ADR")); n << XCHILD(_T("WORK")); AppendVcardFromDB(n, "STREET", "CompanyStreet"); AppendVcardFromDB(n, "EXTADR", "CompanyStreet2"); AppendVcardFromDB(n, "EXTADD", "CompanyStreet2"); // for compatibility with client using old vcard format AppendVcardFromDB(n, "LOCALITY", "CompanyCity"); AppendVcardFromDB(n, "REGION", "CompanyState"); AppendVcardFromDB(n, "PCODE", "CompanyZIP"); AppendVcardFromDB(n, "CTRY", "CompanyCountry"); AppendVcardFromDB(n, "COUNTRY", "CompanyCountry"); // for compatibility with client using old vcard format n = v << XCHILD(_T("ORG")); AppendVcardFromDB(n, "ORGNAME", "Company"); AppendVcardFromDB(n, "ORGUNIT", "CompanyDepartment"); AppendVcardFromDB(v, "TITLE", "CompanyPosition"); AppendVcardFromDB(v, "ROLE", "Role"); AppendVcardFromDB(v, "URL", "Homepage"); AppendVcardFromDB(v, "DESC", "About"); for (i=0; ; i++) { mir_snprintf(idstr, SIZEOF(idstr), "Phone%d", i); ptrT phone( getTStringA(idstr)); if (phone == NULL) break; n = v << XCHILD(_T("TEL")); AppendVcardFromDB(n, "NUMBER", idstr); mir_snprintf(idstr, SIZEOF(idstr), "PhoneFlag%d", i); WORD nFlag = getWord(idstr, 0); if (nFlag & JABBER_VCTEL_HOME) n << XCHILD(_T("HOME")); if (nFlag & JABBER_VCTEL_WORK) n << XCHILD(_T("WORK")); if (nFlag & JABBER_VCTEL_VOICE) n << XCHILD(_T("VOICE")); if (nFlag & JABBER_VCTEL_FAX) n << XCHILD(_T("FAX")); if (nFlag & JABBER_VCTEL_PAGER) n << XCHILD(_T("PAGER")); if (nFlag & JABBER_VCTEL_MSG) n << XCHILD(_T("MSG")); if (nFlag & JABBER_VCTEL_CELL) n << XCHILD(_T("CELL")); if (nFlag & JABBER_VCTEL_VIDEO) n << XCHILD(_T("VIDEO")); if (nFlag & JABBER_VCTEL_BBS) n << XCHILD(_T("BBS")); if (nFlag & JABBER_VCTEL_MODEM) n << XCHILD(_T("MODEM")); if (nFlag & JABBER_VCTEL_ISDN) n << XCHILD(_T("ISDN")); if (nFlag & JABBER_VCTEL_PCS) n << XCHILD(_T("PCS")); } TCHAR szAvatarName[MAX_PATH], *szFileName; GetAvatarFileName(NULL, szAvatarName, SIZEOF(szAvatarName)); if (bPhotoChanged) szFileName = szPhotoFileName; else szFileName = szAvatarName; // Set photo element, also update the global jabberVcardPhotoFileName to reflect the update debugLogA("Before update, file name = %S", szFileName); if (szFileName == NULL || szFileName[0] == 0) { v << XCHILD(_T("PHOTO")); DeleteFile(szAvatarName); delSetting("AvatarSaved"); delSetting("AvatarHash"); } else { debugLogA("Saving picture from %S", szFileName); struct _stat st; if ( _tstat(szFileName, &st) >= 0) { // Note the FILE_SHARE_READ attribute so that the CopyFile can succeed HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { ptrA buffer((char*)mir_alloc(st.st_size)); if (buffer != NULL) { DWORD nRead; if (ReadFile(hFile, buffer, st.st_size, &nRead, NULL)) { ptrA str( mir_base64_encode((PBYTE)(LPSTR)buffer, nRead)); if (str != NULL) { n = v << XCHILD(_T("PHOTO")); TCHAR *szFileType; switch( ProtoGetBufferFormat(buffer)) { case PA_FORMAT_PNG: szFileType = _T("image/png"); break; case PA_FORMAT_GIF: szFileType = _T("image/gif"); break; case PA_FORMAT_BMP: szFileType = _T("image/bmp"); break; default: szFileType = _T("image/jpeg"); break; } n << XCHILD(_T("TYPE"), szFileType); n << XCHILD(_T("BINVAL"), _A2T(str)); // NEED TO UPDATE OUR AVATAR HASH: BYTE digest[MIR_SHA1_HASH_SIZE]; mir_sha1_ctx sha1ctx; mir_sha1_init(&sha1ctx); mir_sha1_append(&sha1ctx, (BYTE*)(LPSTR)buffer, nRead); mir_sha1_finish(&sha1ctx, digest); char buf[MIR_SHA1_HASH_SIZE*2+1]; bin2hex(digest, sizeof(digest), buf); m_options.AvatarType = ProtoGetBufferFormat(buffer); if (bPhotoChanged) { DeleteFile(szAvatarName); GetAvatarFileName(NULL, szAvatarName, SIZEOF(szAvatarName)); CopyFile(szFileName, szAvatarName, FALSE); } setString("AvatarHash", buf); setString("AvatarSaved", buf); } } } CloseHandle(hFile); } } } m_ThreadInfo->send(iq); } ///////////////////////////////////////////////////////////////////////////////////////// void CJabberProto::OnUserInfoInit_VCard(WPARAM wParam, LPARAM) { m_vCardUpdates = 0; m_bPhotoChanged = FALSE; m_szPhotoFileName[0] = 0; OPTIONSDIALOGPAGE odp = { sizeof(odp) }; odp.hInstance = hInst; odp.dwInitParam = (LPARAM)this; odp.flags = ODPF_TCHAR|ODPF_USERINFOTAB|ODPF_DONTTRANSLATE; odp.ptszTitle = m_tszUserName; odp.pfnDlgProc = PersonalDlgProc; odp.pszTemplate = MAKEINTRESOURCEA(IDD_VCARD_PERSONAL); odp.ptszTab = LPGENT("General"); UserInfo_AddPage(wParam, &odp); odp.pfnDlgProc = ContactDlgProc; odp.pszTemplate = MAKEINTRESOURCEA(IDD_VCARD_CONTACT); odp.ptszTab = LPGENT("Contacts"); UserInfo_AddPage(wParam, &odp); odp.pfnDlgProc = HomeDlgProc; odp.pszTemplate = MAKEINTRESOURCEA(IDD_VCARD_HOME); odp.ptszTab = LPGENT("Home"); UserInfo_AddPage(wParam, &odp); odp.pfnDlgProc = WorkDlgProc; odp.pszTemplate = MAKEINTRESOURCEA(IDD_VCARD_WORK); odp.ptszTab = LPGENT("Work"); UserInfo_AddPage(wParam, &odp); odp.pfnDlgProc = PhotoDlgProc; odp.pszTemplate = MAKEINTRESOURCEA(IDD_VCARD_PHOTO); odp.ptszTab = LPGENT("Photo"); UserInfo_AddPage(wParam, &odp); odp.pfnDlgProc = NoteDlgProc; odp.pszTemplate = MAKEINTRESOURCEA(IDD_VCARD_NOTE); odp.ptszTab = LPGENT("Note"); UserInfo_AddPage(wParam, &odp); SendGetVcard(m_szJabberJID); }