int CIcqProto::StringToListItemId(const char *szSetting,int def) { int i; for(i=0;i<settingCount;i++) if (!strcmpnull(szSetting,setting[i].szDbSetting)) break; if (i == settingCount) return def; FieldNamesItem *list = (FieldNamesItem*)setting[i].pList; char *szValue = getSettingStringUtf(NULL, szSetting, NULL); if (!szValue) return def; for (i=0; list[i].text; i++) if (!strcmpnull(list[i].text, szValue)) break; SAFE_FREE(&szValue); if (!list[i].text) return def; return list[i].code; }
static int thumb_getreg(const char *str) { if (!str) return -1; if (*str=='r') return atoi (str+1); //FIXME Note that pc is only allowed in pop; lr in push in Thumb1 mode. if (!strcmpnull (str, "pc") || !strcmpnull(str,"lr")) return 8; return -1; }
static int HookContactSettingChanged(WPARAM hContact, LPARAM lParam) { DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; char *szProto = GetContactProto(hContact); if (strcmpnull(cws->szModule, "CList") && strcmpnull(cws->szModule, szProto)) return 0; WindowList_Broadcast(g_hSendWindowList, DM_UPDATETITLE, 0, 0); WindowList_Broadcast(g_hRecvWindowList, DM_UPDATETITLE, 0, 0); return 0; }
static void SetAllContactChecks(HWND hwndList, HANDLE hReceiver) // doubtful name { if (binListEvent) return; binListEvent = TRUE; char *szProto = GetContactProto(hReceiver); if (szProto == NULL) return; if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_HIDEEMPTYGROUPS && db_get_b(NULL, "CList", "HideEmptyGroups", SETTING_USEGROUPS_DEFAULT)) SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, (WPARAM)TRUE, 0); else SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, (WPARAM)FALSE, 0); HANDLE hItem, hContact = FindFirstClistContact(hwndList, &hItem); while (hContact) { char* szProto2 = GetContactProto(hContact); // different protocols or protocol undefined, remove contact, useless anyway if (strcmpnull(szProto, szProto2)) SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hItem, 0); else // otherwise uncheck SendMessage(hwndList, CLM_SETCHECKMARK, (WPARAM)hItem, 0); hContact = FindNextClistContact(hwndList, hContact, &hItem); } binListEvent = FALSE; }
int ChangeInfoData::UploadSettings(void) { if (!ppro->icqOnline()) { MessageBox(hwndDlg, TranslateT("You are not currently connected to the ICQ network. You must be online in order to update your information on the server."), TranslateT("Change ICQ Details"), MB_OK); return 0; } hUpload[0] = (HANDLE)ppro->ChangeInfoEx(CIXT_FULL, 0); //password char* tmp = ppro->GetUserPassword(TRUE); if (tmp) { if (strlennull(Password) > 0 && strcmpnull(Password, tmp)) { // update password in user info dialog (still open) strcpy(Password, tmp); // update password in protocol strcpy(ppro->m_szPassword, tmp); hUpload[1] = (HANDLE)ppro->icq_changeUserPasswordServ(tmp); char szPwd[PASSWORDMAXLEN] = {0}; // password is stored in DB, update if (ppro->GetUserStoredPassword(szPwd, sizeof(szPwd))) ppro->setString("Password", tmp); } } return 1; }
static int getshift_unused (const char *s) { int i; const char *shifts[] = { "lsl", "lsr", "asr", "ror", NULL }; for (i=0; shifts[i]; i++) if (!strcmpnull (s, shifts[i])) return i * 0x20; return 0; }
static INT_PTR CALLBACK PwConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { PwConfirmDlgParam* dat = (PwConfirmDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch(msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); SendDlgItemMessage(hwndDlg,IDC_PASSWORD,EM_LIMITTEXT,15,0); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: { char szTest[16]; GetDlgItemTextA(hwndDlg,IDC_OLDPASS,szTest,sizeof(szTest)); if (strcmpnull(szTest, dat->ppro->GetUserPassword(TRUE))) { MessageBox(hwndDlg, TranslateT("The password does not match your current password. Check Caps Lock and try again."), TranslateT("Change ICQ Details"), MB_OK); SendDlgItemMessage(hwndDlg,IDC_OLDPASS,EM_SETSEL,0,(LPARAM)-1); SetFocus(GetDlgItem(hwndDlg,IDC_OLDPASS)); break; } GetDlgItemTextA(hwndDlg,IDC_PASSWORD,szTest,sizeof(szTest)); if(strcmpnull(szTest, dat->Pass)) { MessageBox(hwndDlg, TranslateT("The password does not match the password you originally entered. Check Caps Lock and try again."), TranslateT("Change ICQ Details"), MB_OK); SendDlgItemMessage(hwndDlg,IDC_PASSWORD,EM_SETSEL,0,(LPARAM)-1); SetFocus(GetDlgItem(hwndDlg,IDC_PASSWORD)); break; } } case IDCANCEL: EndDialog(hwndDlg,wParam); break; } break; } return FALSE; }
void CIcqProto::handleXtrazData(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC) { MCONTACT hContact; char* szPluginID; hContact = HContactFromUIN(dwUin, NULL); if (hContact) // user sent us xtraz, he supports it SetContactCapabilities(hContact, CAPF_XTRAZ); szPluginID = getXmlPidItem(szMsg, nMsgLen); if (!strcmpnull(szPluginID, "viewCard")) { // it is a greeting card char *szWork, *szEnd, *szUrl, *szNum; szWork = strstrnull(szMsg, "<InD>"); szEnd = strstrnull(szMsg, "</InD>"); if (szWork && szEnd) { int nDataLen = szEnd - szWork; szUrl = (char*)_alloca(nDataLen); memcpy(szUrl, szWork + 5, nDataLen); szUrl[nDataLen - 5] = '\0'; if (!_strnicmp(szUrl, "view_", 5)) { szNum = szUrl + 5; szWork = strstrnull(szUrl, ".html"); if (szWork) { strcpy(szWork, ".php"); strcat(szWork, szWork + 5); } while (szWork = strstrnull(szUrl, "&")) // unescape & code strcpy(szWork + 1, szWork + 5); szWork = (char*)SAFE_MALLOC(nDataLen + MAX_PATH); ICQTranslateUtfStatic(LPGEN("Greeting card:"), szWork, MAX_PATH); strcat(szWork, "\r\nhttp://www.icq.com/friendship/pages/view_page_"); strcat(szWork, szNum); // Create message to notify user PROTORECVEVENT pre = { 0 }; pre.timestamp = time(NULL); pre.szMessage = szWork; pre.flags = PREF_UTF; int bAdded; ProtoChainRecvMsg(HContactFromUIN(dwUin, &bAdded), &pre); SAFE_FREE(&szWork); } else NetLog_Uni(bThruDC, "Error: Non-standard greeting card message"); } else NetLog_Uni(bThruDC, "Error: Malformed greeting card message"); } else NetLog_Uni(bThruDC, "Error: Unknown plugin \"%s\" in Xtraz message", szPluginID); SAFE_FREE(&szPluginID); }
void ChangeInfoData::EndListEdit(int save) { if (hwndListEdit == NULL || iEditItem == -1 || this != dataListEdit) return; if (save) { const SettingItem &si = setting[iEditItem]; SettingItemData &sid = settingData[iEditItem]; int iItem = SendMessage(hwndListEdit, LB_GETCURSEL, 0, 0); int i = SendMessage(hwndListEdit, LB_GETITEMDATA, iItem, 0); if (iItem != -1 && i != -1) { FieldNamesItem *list = (FieldNamesItem*)si.pList; if (list == timezonesField) { tmi.storeListResults(NULL, ppro->m_szModuleName, hwndListEdit, TZF_PLF_LB); list[i = 0].code = ppro->getDword("Timezone", 0); } FieldNamesItem &pItem = list[i]; if (si.dbType == DBVT_ASCIIZ) { char *szNewValue = pItem.text; if (pItem.code || (si.displayType & LIF_ZEROISVALID)) { sid.changed = strcmpnull(szNewValue, (char*)sid.value); SAFE_FREE((void**)&sid.value); sid.value = (LPARAM)null_strdup(szNewValue); } else { sid.changed = (char*)sid.value != NULL; SAFE_FREE((void**)&sid.value); } } else { sid.changed = pItem.code != sid.value; sid.value = pItem.code; } if (sid.changed) { char buf[MAX_PATH]; TCHAR tbuf[MAX_PATH]; if (utf8_to_tchar_static(ICQTranslateUtfStatic(pItem.text, buf, SIZEOF(buf)), tbuf, SIZEOF(buf))) ListView_SetItemText(hwndList, iEditItem, 1, tbuf); EnableDlgItem(GetParent(hwndList), IDC_SAVE, TRUE); } } } ListView_RedrawItems(hwndList, iEditItem, iEditItem); iEditItem = -1; dataListEdit = NULL; DestroyWindow(hwndListEdit); hwndListEdit = NULL; }
static HANDLE CreateTemporaryContactForItem(HWND hwndDlg, TRecvContactsData* wndData, int iItem) { char* caUIN = ListView_GetItemTextEx(GetDlgItem(hwndDlg, IDC_CONTACTS), iItem, 0); char* szProto = GetContactProto(wndData->mhContact); wndData->rhSearch = (HANDLE)SRCCallProtoService(szProto, PS_BASICSEARCH, 0, (LPARAM)caUIN); // find it SAFE_FREE((void**)&wndData->haUin); wndData->haUin = caUIN; for (int j = 0; j < wndData->cbReceived; j++) if (!strcmpnull(wndData->maReceived[j]->mcaUIN, caUIN)) return (HANDLE)SRCCallProtoService(szProto, PS_ADDTOLISTBYEVENT, MAKEWPARAM(PALF_TEMPORARY, j), (LPARAM)wndData->mhDbEvent); return NULL; }
static int CompareFlashItems(const flash_avatar_item* p1, const flash_avatar_item* p2) { if (p1->hContact < p2->hContact) return -1; if (p1->hContact > p2->hContact) return 1; int cProto = strcmpnull(p1->hFA.cProto, p2->hFA.cProto); if (cProto) return cProto; return (p1->hFA.id > p2->hFA.id) ? -1 : (p1->hFA.id == p2->hFA.id) ? 0 : 1; };
void CIcqProto::handleXtrazInvitation(DWORD dwUin, DWORD dwMID, DWORD dwMID2, WORD wCookie, char* szMsg, int nMsgLen, BOOL bThruDC) { MCONTACT hContact = HContactFromUIN(dwUin, NULL); if (hContact) // user sent us xtraz, he supports it SetContactCapabilities(hContact, CAPF_XTRAZ); char *szPluginID = getXmlPidItem(szMsg, nMsgLen); if (!strcmpnull(szPluginID, "ICQChatRecv")) // it is a invitation to multi-user chat ; else NetLog_Uni(bThruDC, "Error: Unknown plugin \"%s\" in Xtraz message", szPluginID); SAFE_FREE(&szPluginID); }
//ret register #; -1 if failed static int getreg(const char *str) { int i; const char *aliases[] = { "sl", "fp", "ip", "sp", "lr", "pc", NULL }; if (!str) return -1; if (*str=='r') return atoi (str+1); for (i=0; aliases[i]; i++) { if (!strcmpnull (str, aliases[i])) { return 10 + i; } } return -1; }
static inline int arm_opcode_cond(ArmOpcode *ao, int delta) { const char *conds[] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0 }; int i, cond = 14; // 'always' is default char *c = ao->op+delta; for (i=0; conds[i]; i++) { if (!strcmpnull (c, conds[i])) { cond = i; break; } } ao->o |= cond<<4; return cond; }
void ChangeInfoData::EndListEdit(int save) { if (hwndListEdit == NULL || iEditItem == -1 || this != dataListEdit) return; if (save) { int iItem = SendMessage(hwndListEdit, LB_GETCURSEL, 0, 0); int i = SendMessage(hwndListEdit, LB_GETITEMDATA, iItem, 0); if (setting[iEditItem].dbType == DBVT_ASCIIZ) { char *szNewValue = (((FieldNamesItem*)setting[iEditItem].pList)[i].text); if (((FieldNamesItem*)setting[iEditItem].pList)[i].code || setting[iEditItem].displayType & LIF_ZEROISVALID) { settingData[iEditItem].changed = strcmpnull(szNewValue, (char*)settingData[iEditItem].value); SAFE_FREE((void**)&settingData[iEditItem].value); settingData[iEditItem].value = (LPARAM)null_strdup(szNewValue); } else { settingData[iEditItem].changed = (char*)settingData[iEditItem].value!=NULL; SAFE_FREE((void**)&settingData[iEditItem].value); } } else { settingData[iEditItem].changed = ((FieldNamesItem*)setting[iEditItem].pList)[i].code != settingData[iEditItem].value; settingData[iEditItem].value = ((FieldNamesItem*)setting[iEditItem].pList)[i].code; } if (settingData[iEditItem].changed) { char buf[MAX_PATH]; TCHAR tbuf[MAX_PATH]; if (utf8_to_tchar_static(ICQTranslateUtfStatic(((FieldNamesItem*)setting[iEditItem].pList)[i].text, buf, SIZEOF(buf)), tbuf, SIZEOF(buf))) ListView_SetItemText(hwndList, iEditItem, 1, tbuf); EnableDlgItem(GetParent(hwndList), IDC_SAVE, TRUE); } } ListView_RedrawItems(hwndList, iEditItem, iEditItem); iEditItem = -1; dataListEdit = NULL; DestroyWindow(hwndListEdit); hwndListEdit = NULL; }
static bool DownloadFlashFile(char *url, const TCHAR* save_file, int recurse_count /*=0*/) { if (!url || recurse_count > 5) return false; NETLIBHTTPREQUEST req = {0}; req.cbSize = sizeof(req); req.requestType = REQUEST_GET; req.szUrl = url; req.flags = 0;//NLHRF_HTTP11; NETLIBHTTPREQUEST *resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUser, (LPARAM)&req); if(resp) { if(resp->resultCode == 200) { HANDLE hSaveFile = CreateFile(save_file, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(hSaveFile != INVALID_HANDLE_VALUE) { unsigned long bytes_written = 0; if(WriteFile(hSaveFile, resp->pData, resp->dataLength, &bytes_written, NULL)) { CloseHandle(hSaveFile); CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; return true; } CloseHandle(hSaveFile); } } else if(resp->resultCode >= 300 && resp->resultCode < 400) { // get new location bool ret = false; for(int i = 0; i < resp->headersCount; i++) { if(strcmpnull(resp->headers[i].szName, "Location") == 0) { ret = DownloadFlashFile(resp->headers[i].szValue, save_file, recurse_count + 1); break; } } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; return ret; } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; } return false; }
static int ownStatusChanged(WPARAM wParam, LPARAM lParam) { WORD status = (WORD)wParam; const char* proto = (char*)lParam; Lock l(cs); for(int i = 0; i < FlashList.getCount(); i++) { flash_avatar_item *item = FlashList[i]; if(item->hContact == NULL && (!proto || (strcmpnull(item->hFA.cProto, proto) == 0))) { IShockwaveFlash* flash = item->pFlash; if (flash) { getFace(); flash->SetVariable(L"face.emotion", _bstr_t(face).copy()); } } else if (item->hContact) break; // the list is sorted by hContact } return 0; }
void CIcqProto::handleXtrazNotifyResponse(DWORD dwUin, MCONTACT hContact, WORD wCookie, char* szMsg, int nMsgLen) { char *szMem, *szRes, *szEnd; int nResLen; #ifdef _DEBUG debugLogA("Received Xtraz Notify Response"); #endif szRes = strstrnull(szMsg, "<RES>"); szEnd = strstrnull(szMsg, "</RES>"); if (szRes && szEnd) { // valid response char *szNode, *szWork; szRes += 5; nResLen = szEnd - szRes; szMem = szRes = DemangleXml(szRes, nResLen); #ifdef _DEBUG debugLogA("Response: %s", szRes); #endif ProtoBroadcastAck(hContact, ICQACKTYPE_XTRAZNOTIFY_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, (LPARAM)szRes); NextVal: szNode = strstrnull(szRes, "<val srv_id="); if (szNode) szEnd = strstrnull(szNode, ">"); else szEnd = NULL; if (szNode && szEnd) { *(szEnd - 1) = '\0'; szNode += 13; //one more than the length of the string to skip ' or " too szWork = szEnd + 1; if (!stricmpnull(szNode, "cAwaySrv")) { int bChanged = FALSE; *szEnd = ' '; szNode = strstrnull(szWork, "<index>"); szEnd = strstrnull(szWork, "</index>"); if (szNode && szEnd) { szNode += 7; *szEnd = '\0'; if (atoi(szNode) != getContactXStatus(hContact)) { // this is strange - but go on debugLogA("Warning: XStatusIds do not match!"); } *szEnd = ' '; } szNode = strstrnull(szWork, "<title>"); szEnd = strstrnull(szWork, "</title>"); if (szNode && szEnd) { // we got XStatus title, save it char *szXName, *szOldXName; szNode += 7; *szEnd = '\0'; szXName = DemangleXml(szNode, strlennull(szNode)); // check if the name changed szOldXName = getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, NULL); if (strcmpnull(szOldXName, szXName)) bChanged = TRUE; SAFE_FREE(&szOldXName); db_set_utf(hContact, m_szModuleName, DBSETTING_XSTATUS_NAME, szXName); SAFE_FREE(&szXName); *szEnd = ' '; } szNode = strstrnull(szWork, "<desc>"); szEnd = strstrnull(szWork, "</desc>"); if (szNode && szEnd) { // we got XStatus mode msg, save it char *szXMsg, *szOldXMsg; szNode += 6; *szEnd = '\0'; szXMsg = DemangleXml(szNode, strlennull(szNode)); // check if the decription changed szOldXMsg = getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, NULL); if (strcmpnull(szOldXMsg, szXMsg)) bChanged = TRUE; SAFE_FREE(&szOldXMsg); db_set_utf(hContact, m_szModuleName, DBSETTING_XSTATUS_MSG, szXMsg); SAFE_FREE(&szXMsg); } ProtoBroadcastAck(hContact, ICQACKTYPE_XSTATUS_RESPONSE, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); } else { char *szSrvEnd = strstrnull(szEnd, "</srv>"); if (szSrvEnd && strstrnull(szSrvEnd, "<val srv_id=")) { // check all values ! szRes = szSrvEnd + 6; // after first value goto NextVal; } // no next val, we were unable to handle packet, write error debugLogA("Error: Unknown serverId \"%s\" in Xtraz response", szNode); } } else debugLogA("Error: Missing serverId in Xtraz response"); SAFE_FREE(&szMem); } else debugLogA("Error: Invalid Xtraz Notify response"); }
int CIcqProto::IsICQContact(HANDLE hContact) { char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); return !strcmpnull(szProto, m_szModuleName); }
// TODO: group similar instructions like for non-thumb static int thumb_assemble(ArmOpcode *ao, const char *str) { int reg, j; ao->o = UT32_MAX; if (!strcmpnull (ao->op, "pop") && ao->a[0]) { ao->o = 0xbc; if (*ao->a[0]++=='{') { // XXX: inverse order? for (j=0; j<16; j++) { if (ao->a[j] && *ao->a[j]) { getrange (ao->a[j]); // XXX filter regname string reg = thumb_getreg (ao->a[j]); if (reg != -1) { if (reg<8) ao->o |= 1<<(8+reg); if (reg==8){ ao->o |= 1; } // else ignore... } } } } else ao->o |= getnum (ao->a[0])<<24; // ??? return 2; } else if (!strcmpnull (ao->op, "push") && ao->a[0]) { ao->o = 0xb4; if (*ao->a[0]++=='{') { for (j=0; j<16; j++) { if (ao->a[j] && *ao->a[j]) { getrange (ao->a[j]); // XXX filter regname string reg = thumb_getreg (ao->a[j]); if (reg != -1) { if (reg<8) ao->o |= 1<<(8+reg); if (reg==8) ao->o |= 1; // else ignore... } } } } else ao->o |= getnum (ao->a[0])<<24; // ??? return 2; } else if (!strcmpnull (ao->op, "ldmia")) { ao->o = 0xc8 + getreg (ao->a[0]); ao->o |= getlist(ao->opstr) << 8; return 2; } else if (!strcmpnull (ao->op, "stmia")) { ao->o = 0xc0 + getreg (ao->a[0]); ao->o |= getlist(ao->opstr) << 8; return 2; } else if (!strcmpnull (ao->op, "nop")) { ao->o = 0xbf; return 2; } else if (!strcmpnull (ao->op, "yield")) { ao->o = 0x10bf; return 2; } else if (!strcmpnull (ao->op, "udf")) { ao->o = 0xde; ao->o |= getnum (ao->a[0])<<8; return 2; } else if (!strcmpnull (ao->op, "wfe")) { ao->o = 0x20bf; return 2; } else if (!strcmpnull (ao->op, "wfi")) { ao->o = 0x30bf; return 2; } else if (!strcmpnull (ao->op, "sev")) { ao->o = 0x40bf; return 2; } else if (!strcmpnull (ao->op, "bkpt")) { ao->o = 0xbe; ao->o |= (0xff & getnum (ao->a[0]))<<8; return 2; } else #if 0 if (!strcmpnull (ao->op, "and")) { ao->o = 0x40; ao->o |= (0xff & getreg (ao->a[0])) << 8; ao->o |= (0xff & getreg (ao->a[1])) << 11; } else #endif if (!strcmpnull (ao->op, "svc")) { ao->o = 0xdf; ao->o |= (0xff & getnum (ao->a[0])) << 8; return 2; } else if (!strcmpnull (ao->op, "b") || !strcmpnull (ao->op, "b.n")) { //uncond branch : PC += 4 + (delta*2) int delta = getnum (ao->a[0]) - 4 - ao->off; if ((delta < -2048) || (delta > 2046) || (delta & 1)) { eprintf("branch out of range or not even\n"); return 0; } ut16 opcode = 0xe000 | ((delta / 2) & 0x7ff); //11bit offset>>1 ao->o = opcode >>8; ao->o |= (opcode & 0xff)<<8; // (ut32) ao->o holds the opcode in little-endian format !? return 2; } else
void CIcqProto::parseDirectoryUserDetailsData(MCONTACT hContact, oscar_tlv_chain *cDetails, DWORD dwCookie, cookie_directory_data *pCookieData, WORD wReplySubType) { oscar_tlv *pTLV; WORD wRecordCount; if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOMULTI && !hContact) { DWORD dwUin = 0; char *szUid = cDetails->getString(0x32, 1); if (!szUid) { debugLogA("Error: Received unrecognized data from the directory"); return; } if (IsStringUIN(szUid)) dwUin = atoi(szUid); hContact = HContactFromUID(dwUin, szUid, NULL); if (hContact == INVALID_CONTACT_ID) { debugLogA("Error: Received details for unknown contact \"%s\"", szUid); SAFE_FREE(&szUid); return; } #ifdef _DEBUG else debugLogA("Received user info for %s from directory", szUid); #endif SAFE_FREE(&szUid); } #ifdef _DEBUG else { char *szUid = cDetails->getString(0x32, 1); if (!hContact) debugLogA("Received owner user info from directory"); else debugLogA("Received user info for %s from directory", szUid); SAFE_FREE(&szUid); } #endif pTLV = cDetails->getTLV(0x50, 1); if (pTLV && pTLV->wLen > 0) writeDbInfoSettingTLVStringUtf(hContact, "e-mail", cDetails, 0x50); // Verified e-mail else writeDbInfoSettingTLVStringUtf(hContact, "e-mail", cDetails, 0x55); // Pending e-mail writeDbInfoSettingTLVStringUtf(hContact, "FirstName", cDetails, 0x64); writeDbInfoSettingTLVStringUtf(hContact, "LastName", cDetails, 0x6E); writeDbInfoSettingTLVStringUtf(hContact, "Nick", cDetails, 0x78); // Home Address parseUserInfoRecord(hContact, cDetails->getTLV(0x96, 1), rAddress, SIZEOF(rAddress), 1); // Origin Address parseUserInfoRecord(hContact, cDetails->getTLV(0xA0, 1), rOriginAddress, SIZEOF(rOriginAddress), 1); // Phones pTLV = cDetails->getTLV(0xC8, 1); if (pTLV && pTLV->wLen >= 2) { BYTE *pRecords = pTLV->pData; unpackWord(&pRecords, &wRecordCount); oscar_tlv_record_list *cPhones = readIntoTLVRecordList(&pRecords, pTLV->wLen - 2, wRecordCount); if (cPhones) { oscar_tlv_chain *cPhone; cPhone = cPhones->getRecordByTLV(0x6E, 1); writeDbInfoSettingTLVStringUtf(hContact, "Phone", cPhone, 0x64); cPhone = cPhones->getRecordByTLV(0x6E, 2); writeDbInfoSettingTLVStringUtf(hContact, "CompanyPhone", cPhone, 0x64); cPhone = cPhones->getRecordByTLV(0x6E, 3); writeDbInfoSettingTLVStringUtf(hContact, "Cellular", cPhone, 0x64); cPhone = cPhones->getRecordByTLV(0x6E, 4); writeDbInfoSettingTLVStringUtf(hContact, "Fax", cPhone, 0x64); cPhone = cPhones->getRecordByTLV(0x6E, 5); writeDbInfoSettingTLVStringUtf(hContact, "CompanyFax", cPhone, 0x64); disposeRecordList(&cPhones); } else { // Remove old data when phones not available delSetting(hContact, "Phone"); delSetting(hContact, "CompanyPhone"); delSetting(hContact, "Cellular"); delSetting(hContact, "Fax"); delSetting(hContact, "CompanyFax"); } } else { // Remove old data when phones not available delSetting(hContact, "Phone"); delSetting(hContact, "CompanyPhone"); delSetting(hContact, "Cellular"); delSetting(hContact, "Fax"); delSetting(hContact, "CompanyFax"); } // Emails parseUserInfoRecord(hContact, cDetails->getTLV(0x8C, 1), rEmail, SIZEOF(rEmail), 4); writeDbInfoSettingTLVByte(hContact, "Timezone", cDetails, 0x17C); // Company parseUserInfoRecord(hContact, cDetails->getTLV(0x118, 1), rCompany, SIZEOF(rCompany), 1); // Education parseUserInfoRecord(hContact, cDetails->getTLV(0x10E, 1), rEducation, SIZEOF(rEducation), 1); switch (cDetails->getNumber(0x82, 1)) { case 1: setByte(hContact, "Gender", 'F'); break; case 2: setByte(hContact, "Gender", 'M'); break; default: delSetting(hContact, "Gender"); } writeDbInfoSettingTLVStringUtf(hContact, "Homepage", cDetails, 0xFA); writeDbInfoSettingTLVDate(hContact, "BirthYear", "BirthMonth", "BirthDay", cDetails, 0x1A4); writeDbInfoSettingTLVByte(hContact, "Language1", cDetails, 0xAA); writeDbInfoSettingTLVByte(hContact, "Language2", cDetails, 0xB4); writeDbInfoSettingTLVByte(hContact, "Language3", cDetails, 0xBE); writeDbInfoSettingTLVByte(hContact, "MaritalStatus", cDetails, 0x12C); // Interests parseUserInfoRecord(hContact, cDetails->getTLV(0x122, 1), rInterest, SIZEOF(rInterest), 4); writeDbInfoSettingTLVStringUtf(hContact, "About", cDetails, 0x186); // if (hContact) // writeDbInfoSettingTLVStringUtf(hContact, DBSETTING_STATUS_NOTE, cDetails, 0x226); // else if (!hContact) { // Owner contact needs special processing, in the database is current status note for the client // We just received the last status note set on directory, if it differs call SetStatusNote() to // ensure the directory will be updated (it should be in process anyway) char *szClientStatusNote = getSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, NULL); char *szDirectoryStatusNote = cDetails->getString(0x226, 1); if (strcmpnull(szClientStatusNote, szDirectoryStatusNote)) SetStatusNote(szClientStatusNote, 1000, TRUE); // Release memory SAFE_FREE(&szDirectoryStatusNote); SAFE_FREE(&szClientStatusNote); } writeDbInfoSettingTLVByte(hContact, "PrivacyLevel", cDetails, 0x1F9); if (!hContact) { setByte(hContact, "Auth", !cDetails->getByte(0x19A, 1)); writeDbInfoSettingTLVByte(hContact, "WebAware", cDetails, 0x212); writeDbInfoSettingTLVByte(hContact, "AllowSpam", cDetails, 0x1EA); } writeDbInfoSettingTLVWord(hContact, "InfoCP", cDetails, 0x1C2); if (hContact) { // Handle deprecated setting (Age & Birthdate are not separate fields anymore) int nAge = calcAgeFromBirthDate(cDetails->getDouble(0x1A4, 1)); if (nAge) setWord(hContact, "Age", nAge); else delSetting(hContact, "Age"); } else // we do not need to calculate age for owner delSetting(hContact, "Age"); { // Save user info last update time and privacy token double dInfoTime; BYTE pbEmptyMetaToken[0x10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int bHasMetaToken = FALSE; // Check if the details arrived with privacy token! if ((pTLV = cDetails->getTLV(0x3C, 1)) && pTLV->wLen == 0x10 && memcmp(pTLV->pData, pbEmptyMetaToken, 0x10)) bHasMetaToken = TRUE; // !Important, we need to save the MDir server-item time - it can be newer than the one from the directory if ((dInfoTime = getSettingDouble(hContact, DBSETTING_METAINFO_TIME, 0)) > 0) setSettingDouble(hContact, DBSETTING_METAINFO_SAVED, dInfoTime); else if (bHasMetaToken || !hContact) writeDbInfoSettingTLVDouble(hContact, DBSETTING_METAINFO_SAVED, cDetails, 0x1CC); else setDword(hContact, DBSETTING_METAINFO_SAVED, time(NULL)); } if (wReplySubType == META_DIRECTORY_RESPONSE) if (pCookieData->bRequestType == DIRECTORYREQUEST_INFOUSER) ProtoBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0); // Remove user from info update queue. Removing is fast so we always call this // even if it is likely that the user is not queued at all. if (hContact) icq_DequeueUser(getContactUin(hContact)); }
void CIcqProto::handleUserOnline(BYTE *buf, size_t wLen, serverthread_info*) { DWORD dwPort = 0; DWORD dwRealIP = 0; DWORD dwUIN; uid_str szUID; DWORD dwDirectConnCookie = 0; DWORD dwWebPort = 0; DWORD dwFT1 = 0, dwFT2 = 0, dwFT3 = 0; const char *szClient = NULL; BYTE bClientId = 0; WORD wVersion = 0; WORD wTLVCount; WORD wWarningLevel; WORD wStatusFlags; WORD wStatus = 0, wOldStatus = 0; BYTE nTCPFlag = 0; char szStrBuf[MAX_PATH]; // Unpack the sender's user ID if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return; // Syntax check if (wLen < 4) return; // Warning level? unpackWord(&buf, &wWarningLevel); wLen -= 2; // TLV count unpackWord(&buf, &wTLVCount); wLen -= 2; // Ignore status notification if the user is not already on our list MCONTACT hContact = HContactFromUID(dwUIN, szUID, NULL); if (hContact == INVALID_CONTACT_ID) { debugLogA("Ignoring user online (%s)", strUID(dwUIN, szUID)); return; } // Read user info TLVs oscar_tlv_chain *pChain; oscar_tlv *pTLV; // Syntax check if (wLen < 4) return; // Get chain if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount))) return; // Get Class word WORD wClass = pChain->getWord(0x01, 1); int nIsICQ = wClass & CLASS_ICQ; if (dwUIN) { // Get DC info TLV pTLV = pChain->getTLV(0x0C, 1); if (pTLV && (pTLV->wLen >= 15)) { BYTE *pBuffer = pTLV->pData; nIsICQ = TRUE; unpackDWord(&pBuffer, &dwRealIP); unpackDWord(&pBuffer, &dwPort); unpackByte(&pBuffer, &nTCPFlag); unpackWord(&pBuffer, &wVersion); unpackDWord(&pBuffer, &dwDirectConnCookie); unpackDWord(&pBuffer, &dwWebPort); // Web front port pBuffer += 4; // Client features // Get faked time signatures, used to identify clients if (pTLV->wLen >= 0x23) { unpackDWord(&pBuffer, &dwFT1); unpackDWord(&pBuffer, &dwFT2); unpackDWord(&pBuffer, &dwFT3); } } // Get Status info TLV pTLV = pChain->getTLV(0x06, 1); if (pTLV && (pTLV->wLen >= 4)) { BYTE *pBuffer = pTLV->pData; unpackWord(&pBuffer, &wStatusFlags); unpackWord(&pBuffer, &wStatus); } else if (!nIsICQ) { // Connected thru AIM client, guess by user class if (wClass & CLASS_AWAY) wStatus = ID_STATUS_AWAY; else if (wClass & CLASS_WIRELESS) wStatus = ID_STATUS_ONTHEPHONE; else wStatus = ID_STATUS_ONLINE; wStatusFlags = 0; } else { // Huh? No status TLV? Lets guess then... wStatusFlags = 0; wStatus = ICQ_STATUS_ONLINE; } } else { nIsICQ = FALSE; if (wClass & CLASS_AWAY) wStatus = ID_STATUS_AWAY; else if (wClass & CLASS_WIRELESS) wStatus = ID_STATUS_ONTHEPHONE; else wStatus = ID_STATUS_ONLINE; wStatusFlags = 0; } debugLogA("Flags are %x", wStatusFlags); debugLogA("Status is %x", wStatus); // Get IP TLV DWORD dwIP = pChain->getDWord(0x0A, 1); // Get Online Since TLV DWORD dwOnlineSince = pChain->getDWord(0x03, 1); // Get Away Since TLV DWORD dwAwaySince = pChain->getDWord(0x29, 1); // Get Member Since TLV DWORD dwMemberSince = pChain->getDWord(0x05, 1); // Get Idle timer TLV WORD wIdleTimer = pChain->getWord(0x04, 1); time_t tIdleTS = 0; if (wIdleTimer) { time(&tIdleTS); tIdleTS -= (wIdleTimer*60); } if (wIdleTimer) debugLogA("Idle timer is %u.", wIdleTimer); debugLogA("Online since %s", time2text(dwOnlineSince)); if (dwAwaySince) debugLogA("Status was set on %s", time2text(dwAwaySince)); // Check client capabilities if (hContact != NULL) { wOldStatus = getContactStatus(hContact); // Collect all Capability info from TLV chain BYTE *capBuf = NULL; WORD capLen = 0; // Get Location Capability Info TLVs oscar_tlv *pFullTLV = pChain->getTLV(0x0D, 1); oscar_tlv *pShortTLV = pChain->getTLV(0x19, 1); if (pFullTLV && (pFullTLV->wLen >= BINARY_CAP_SIZE)) capLen += pFullTLV->wLen; if (pShortTLV && (pShortTLV->wLen >= 2)) capLen += (pShortTLV->wLen * 8); capBuf = (BYTE*)_alloca(capLen + BINARY_CAP_SIZE); if (capLen) { BYTE *pCapability = capBuf; capLen = 0; // we need to recount that if (pFullTLV && (pFullTLV->wLen >= BINARY_CAP_SIZE)) { // copy classic Capabilities BYTE *cData = pFullTLV->pData; int cLen = pFullTLV->wLen; while (cLen) { // be impervious to duplicates (AOL sends them sometimes) if (!capLen || !MatchCapability(capBuf, capLen, (capstr*)cData, BINARY_CAP_SIZE)) { // not present, add memcpy(pCapability, cData, BINARY_CAP_SIZE); capLen += BINARY_CAP_SIZE; pCapability += BINARY_CAP_SIZE; } cData += BINARY_CAP_SIZE; cLen -= BINARY_CAP_SIZE; } } if (pShortTLV && (pShortTLV->wLen >= 2)) { // copy short Capabilities capstr tmp; BYTE *cData = pShortTLV->pData; int cLen = pShortTLV->wLen; memcpy(tmp, capShortCaps, BINARY_CAP_SIZE); while (cLen) { // be impervious to duplicates (AOL sends them sometimes) tmp[2] = cData[0]; tmp[3] = cData[1]; if (!capLen || !MatchCapability(capBuf, capLen, &tmp, BINARY_CAP_SIZE)) { // not present, add memcpy(pCapability, tmp, BINARY_CAP_SIZE); capLen += BINARY_CAP_SIZE; pCapability += BINARY_CAP_SIZE; } cData += 2; cLen -= 2; } } debugLogA("Detected %d capability items.", capLen / BINARY_CAP_SIZE); } if (capLen) { // Update the contact's capabilies if present in packet SetCapabilitiesFromBuffer(hContact, capBuf, capLen, wOldStatus == ID_STATUS_OFFLINE); char *szCurrentClient = wOldStatus == ID_STATUS_OFFLINE ? NULL : getSettingStringUtf(hContact, "MirVer", NULL); szClient = detectUserClient(hContact, nIsICQ, wClass, dwOnlineSince, szCurrentClient, wVersion, dwFT1, dwFT2, dwFT3, dwDirectConnCookie, dwWebPort, capBuf, capLen, &bClientId, szStrBuf); // Check if the client changed, if not do not change if (szCurrentClient && !strcmpnull(szCurrentClient, szClient)) szClient = (const char*)-1; SAFE_FREE(&szCurrentClient); } else if (wOldStatus == ID_STATUS_OFFLINE) { // Remove the contact's capabilities if coming from offline ClearAllContactCapabilities(hContact); // no capability debugLogA("No capability info TLVs"); szClient = detectUserClient(hContact, nIsICQ, wClass, dwOnlineSince, NULL, wVersion, dwFT1, dwFT2, dwFT3, dwDirectConnCookie, dwWebPort, NULL, capLen, &bClientId, szStrBuf); } else // Capabilities not present in update packet, do not touch szClient = (const char*)-1; // we don't want to client be overwritten // handle Xtraz status char *moodData = NULL; WORD moodSize = 0; unpackSessionDataItem(pChain, 0x0E, (BYTE**)&moodData, &moodSize, NULL); if (capLen || wOldStatus == ID_STATUS_OFFLINE) handleXStatusCaps(dwUIN, szUID, hContact, capBuf, capLen, moodData, moodSize); else handleXStatusCaps(dwUIN, szUID, hContact, NULL, 0, moodData, moodSize); // Determine support for extended status messages if (pChain->getWord(0x08, 1) == 0x0A06) SetContactCapabilities(hContact, CAPF_STATUS_MESSAGES); else if (wOldStatus == ID_STATUS_OFFLINE) ClearContactCapabilities(hContact, CAPF_STATUS_MESSAGES); if (wOldStatus == ID_STATUS_OFFLINE) { if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY)) debugLogA("Supports advanced messages"); else debugLogA("Does NOT support advanced messages"); } if (!nIsICQ) { // AIM clients does not advertise these, but do support them SetContactCapabilities(hContact, CAPF_UTF | CAPF_TYPING); // Server relayed messages are only supported by ICQ clients ClearContactCapabilities(hContact, CAPF_SRV_RELAY); if (dwUIN && wOldStatus == ID_STATUS_OFFLINE) debugLogA("Logged in with AIM client"); } if (nIsICQ && wVersion < 8) { ClearContactCapabilities(hContact, CAPF_SRV_RELAY); if (wOldStatus == ID_STATUS_OFFLINE) debugLogA("Forcing simple messages due to compability issues"); } // Process Avatar Hash pTLV = pChain->getTLV(0x1D, 1); if (pTLV) handleAvatarContactHash(dwUIN, szUID, hContact, pTLV->pData, pTLV->wLen); else handleAvatarContactHash(dwUIN, szUID, hContact, NULL, 0); // Process Status Note parseStatusNote(dwUIN, szUID, hContact, pChain); } // Free TLV chain disposeChain(&pChain); // Save contacts details in database if (hContact != NULL) { setDword(hContact, "LogonTS", dwOnlineSince); setDword(hContact, "AwayTS", dwAwaySince); setDword(hContact, "IdleTS", tIdleTS); if (dwMemberSince) setDword(hContact, "MemberTS", dwMemberSince); if (nIsICQ) { // on AIM these are not used setDword(hContact, "DirectCookie", dwDirectConnCookie); setByte(hContact, "DCType", (BYTE)nTCPFlag); setWord(hContact, "UserPort", (WORD)(dwPort & 0xffff)); setWord(hContact, "Version", wVersion); } else { delSetting(hContact, "DirectCookie"); delSetting(hContact, "DCType"); delSetting(hContact, "UserPort"); delSetting(hContact, "Version"); } // if no detection, set uknown if (!szClient) szClient = (nIsICQ ? "Unknown" : "Unknown AIM"); if (szClient != (char*)-1) { db_set_utf(hContact, m_szModuleName, "MirVer", szClient); setByte(hContact, "ClientID", bClientId); } if (wOldStatus == ID_STATUS_OFFLINE) { setDword(hContact, "IP", dwIP); setDword(hContact, "RealIP", dwRealIP); } else { // if not first notification only write significant information if (dwIP) setDword(hContact, "IP", dwIP); if (dwRealIP) setDword(hContact, "RealIP", dwRealIP); } setWord(hContact, "Status", (WORD)IcqStatusToMiranda(wStatus)); // Update info? if (dwUIN) { // check if the local copy of user details is up-to-date if (IsMetaInfoChanged(hContact)) icq_QueueUser(hContact); } } LPCTSTR ptszStatus = pcli->pfnGetStatusModeDescription(IcqStatusToMiranda(wStatus), 0); if (wOldStatus != IcqStatusToMiranda(wStatus)) { // And a small log notice... if status was changed if (nIsICQ) debugLogA("%u changed status to %S (v%d).", dwUIN, ptszStatus, wVersion); else debugLogA("%s changed status to %S.", strUID(dwUIN, szUID), ptszStatus); } if (szClient == cliSpamBot) { if (getByte("KillSpambots", DEFAULT_KILLSPAM_ENABLED) && db_get_b(hContact, "CList", "NotOnList", 0)) { // kill spammer icq_DequeueUser(dwUIN); icq_sendRemoveContact(dwUIN, NULL); AddToSpammerList(dwUIN); if (getByte("PopupsSpamEnabled", DEFAULT_SPAM_POPUPS_ENABLED)) ShowPopupMsg(hContact, LPGEN("Spambot Detected"), LPGEN("Contact deleted & further events blocked."), POPTYPE_SPAM); CallService(MS_DB_CONTACT_DELETE, hContact, 0); debugLogA("Contact %u deleted", dwUIN); } } }
static int eventAdded(WPARAM wParam, LPARAM lParam) { DBEVENTINFO dbei = { sizeof(dbei) }; dbei.cbBlob = db_event_getBlobSize((HANDLE)lParam); if (dbei.cbBlob == 0xFFFFFFFF) return 0; dbei.pBlob = new BYTE[dbei.cbBlob]; db_event_get((HANDLE)lParam, &dbei); if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_READ)) { Lock l(cs); if(FlashList.getCount() > 0) { //size_t aLen = strlen((char *)dbei.pBlob)+1; char* face = NULL; if ( (strstr((char*)dbei.pBlob, (char*)":-)") != NULL) || (strstr((char*)dbei.pBlob, (char*)":)") != NULL) || (strstr((char*)dbei.pBlob, (char*)";)") != NULL) || (strstr((char*)dbei.pBlob, (char*)";-)") != NULL) || (strstr((char*)dbei.pBlob, (char*)"*THUMBS UP*") != NULL) || (strstr((char*)dbei.pBlob, (char*)"O:-)") != NULL) || (strstr((char*)dbei.pBlob, (char*)":P") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-P") != NULL) || (strstr((char*)dbei.pBlob, (char*)"*Drink*") != NULL)) { face = AV_SMILE; } else if ( (strstr((char*)dbei.pBlob, (char*)":-(") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-$") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-!") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-X") != NULL)) { face = AV_SAD; } else if ( (strstr((char*)dbei.pBlob, (char*)"*JOKINGLY*") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-D") != NULL)) { face = AV_LAUGH; } else if ( (strstr((char*)dbei.pBlob, (char*)":'(") != NULL) || (strstr((char*)dbei.pBlob, (char*)":'-(") != NULL)) { face = AV_CRY; } else if ( (strstr((char*)dbei.pBlob, (char*)">:o") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-@") != NULL) || (strstr((char*)dbei.pBlob, (char*)"*STOP*") != NULL) || (strstr((char*)dbei.pBlob, (char*)"]:->") != NULL) || (strstr((char*)dbei.pBlob, (char*)"@=") != NULL)) { face = AV_MAD; } else if ( (strstr((char*)dbei.pBlob, (char*)":-*") != NULL) || (strstr((char*)dbei.pBlob, (char*)":-[") != NULL) || (strstr((char*)dbei.pBlob, (char*)"*KISSED*") != NULL) || (strstr((char*)dbei.pBlob, (char*)"*KISSING*") != NULL) || (strstr((char*)dbei.pBlob, (char*)"@}->--") != NULL) || (strstr((char*)dbei.pBlob, (char*)"*IN LOVE*") != NULL)) { face = AV_LOVE; } else { face = AV_NORMAL; } MCONTACT hContact = (dbei.flags & DBEF_SENT) ? 0 : wParam; for(int i=0; i<FlashList.getCount(); i++) { flash_avatar_item *item = FlashList[i]; if (item->hContact == hContact && !strcmpnull(dbei.szModule, item->getProto())) { IShockwaveFlash* flash = item->pFlash; flash->SetVariable(L"face.emotion", _bstr_t(face).copy()); //break; } else if (item->hContact > hContact) break; // the list is sorted } } } delete[] dbei.pBlob; return 0; }
void ChangeInfoData::BeginListEdit(int iItem, RECT *rc, int iSetting, WORD wVKey) { int j,n; POINT pt; int itemHeight; char str[MAX_PATH]; if (dataListEdit) dataListEdit->EndListEdit(0); pt.x=pt.y=0; ClientToScreen(hwndList,&pt); OffsetRect(rc,pt.x,pt.y); InflateRect(rc,-2,-2); rc->left-=2; iEditItem = iItem; ListView_RedrawItems(hwndList, iEditItem, iEditItem); UpdateWindow(hwndList); dataListEdit = this; hwndListEdit = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, _T("LISTBOX"), _T(""), WS_POPUP|WS_BORDER|WS_VSCROLL, rc->left, rc->bottom, rc->right - rc->left, 150, NULL, NULL, hInst, NULL); SendMessage(hwndListEdit, WM_SETFONT, (WPARAM)hListFont, 0); itemHeight = SendMessage(hwndListEdit, LB_GETITEMHEIGHT, 0, 0); FieldNamesItem *list = (FieldNamesItem*)setting[iSetting].pList; if (list == countryField) { // some country codes were changed leaving old details uknown, convert it for the user if (settingData[iSetting].value == 420) settingData[iSetting].value = 42; // conversion of obsolete codes (OMG!) else if (settingData[iSetting].value == 421) settingData[iSetting].value = 4201; else if (settingData[iSetting].value == 102) settingData[iSetting].value = 1201; } n = ListBoxAddStringUtf(hwndListEdit, "Unspecified"); for (j=0; ; j++) if (!list[j].text) { SendMessage(hwndListEdit, LB_SETITEMDATA, n, j); if ((settingData[iSetting].value == 0 && list[j].code == 0) || (setting[iSetting].dbType != DBVT_ASCIIZ && settingData[iSetting].value == list[j].code)) SendMessage(hwndListEdit, LB_SETCURSEL, n, 0); break; } for (j=0; list[j].text; j++) { n = ListBoxAddStringUtf(hwndListEdit, list[j].text); SendMessage(hwndListEdit, LB_SETITEMDATA, n, j); if ((setting[iSetting].dbType == DBVT_ASCIIZ && (!strcmpnull((char*)settingData[iSetting].value, list[j].text)) || (setting[iSetting].dbType == DBVT_ASCIIZ && (!strcmpnull((char*)settingData[iSetting].value, ICQTranslateUtfStatic(list[j].text, str, MAX_PATH)))) || ((char*)settingData[iSetting].value == NULL && list[j].code == 0)) || (setting[iSetting].dbType != DBVT_ASCIIZ && settingData[iSetting].value == list[j].code)) SendMessage(hwndListEdit, LB_SETCURSEL, n, 0); } SendMessage(hwndListEdit, LB_SETTOPINDEX, SendMessage(hwndListEdit, LB_GETCURSEL, 0, 0) - 3, 0); int listCount = SendMessage(hwndListEdit, LB_GETCOUNT, 0, 0); if (itemHeight * listCount < 150) SetWindowPos(hwndListEdit, 0, 0, 0, rc->right - rc->left, itemHeight * listCount + GetSystemMetrics(SM_CYBORDER) * 2, SWP_NOZORDER|SWP_NOMOVE); OldListEditProc = (WNDPROC)SetWindowLongPtr(hwndListEdit, GWLP_WNDPROC, (LONG_PTR)ListEditSubclassProc); if (MyAnimateWindow = (BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(GetModuleHandleA("user32"), "AnimateWindow")) { BOOL enabled; SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &enabled, FALSE); if (enabled) MyAnimateWindow(hwndListEdit, 200, AW_SLIDE|AW_ACTIVATE|AW_VER_POSITIVE); } ShowWindow(hwndListEdit, SW_SHOW); SetFocus(hwndListEdit); if (wVKey) PostMessage(hwndListEdit, WM_KEYDOWN, wVKey, 0); }
INT_PTR CALLBACK RecvDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { TRecvContactsData* wndData = (TRecvContactsData*)GetWindowLong(hwndDlg, DWLP_USER); switch (msg) { case WM_INITDIALOG: { CLISTEVENT* pcle = (CLISTEVENT*)lParam; /// got it TranslateDialogDefault(hwndDlg); WindowList_Add(ghRecvWindowList, hwndDlg, pcle->hContact); SendMessageT(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_CONTACTS))); EnableDlgItem(hwndDlg, IDOK, FALSE); EnableDlgItem(hwndDlg, IDDETAILS, FALSE); wndData = new TRecvContactsData(pcle->hContact); SetWindowLong(hwndDlg, DWLP_USER, (LONG)wndData); wndData->mhDbEvent = pcle->hDbEvent; /// initialized, pcle not needed anymore wndData->mhListIcon = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLORDDB|ILC_MASK, 0, 1); wndData->mhPopup = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTACTMENU)); CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)wndData->mhPopup, 0); wndData->hHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_EVENTSENT); char *szProto = GetContactProto(wndData->mhContact); HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); ListView_SetExtendedListViewStyle(hLV, LVS_EX_CHECKBOXES|LVS_EX_FULLROWSELECT); // add columns RecvListView_AddColumn(hLV, 120, (char*)SRCCallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDTEXT, 0), FALSE, 0); RecvListView_AddColumn(hLV, 100, "Nick", TRUE, 1); RecvListView_AddColumn(hLV, 100, "First Name", TRUE, 2); RecvListView_AddColumn(hLV, 100, "Last Name", TRUE, 3); // fill in groups SendMessageT(GetDlgItem(hwndDlg, IDC_ENABLEGROUPS), BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); RebuildGroupCombo(hwndDlg); { // fill listview with received contacts DBEVENTINFO dbe = {0}; dbe.cbSize = sizeof(DBEVENTINFO); dbe.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)wndData->mhDbEvent, 0); if (dbe.cbBlob != -1) // this marks an invalid hDbEvent - all smashed anyway... dbe.pBlob = (PBYTE)_malloca(dbe.cbBlob); CallService(MS_DB_EVENT_GET, (WPARAM)wndData->mhDbEvent, (LPARAM)&dbe); char* pcBlob = (char*)dbe.pBlob; char* pcEnd = (char*)dbe.pBlob + dbe.cbBlob; HICON hiProto = LoadContactProtoIcon(wndData->mhContact); ImageList_AddIcon(wndData->mhListIcon, hiProto); DestroyIcon(hiProto); // imagelist copied the resource ListView_SetImageList(hLV, wndData->mhListIcon, LVSIL_SMALL); LVITEM lvi = {0}; lvi.iImage = 0; lvi.mask = LVIF_TEXT | LVIF_IMAGE; for (int nItem = 0; ; nItem++) { // Nick int strsize = (int)strlennull(pcBlob); TReceivedItem* pItem = wndData->AddReceivedItem(); if (dbe.flags & DBEF_UTF) pItem->mcaNick = utf8_to_tchar((unsigned char*)pcBlob); else pItem->mcaNick = ansi_to_tchar(pcBlob); pcBlob += strsize + 1; // UIN strsize = (int)strlennull(pcBlob); pItem->mcaUIN = null_strdup(pcBlob); pcBlob += strsize + 1; // add to listview lvi.iItem = nItem; lvi.pszText = pItem->mcaUIN; ListView_InsertItem(hLV, &lvi); // with image ListView_SetItemTextT(hLV, nItem, 1, pItem->mcaNick); // check for end of contacts if (pcBlob >= pcEnd) break; } } // new dlg init wndData->hIcons[0] = InitMButton(hwndDlg, IDC_ADD, MAKEINTRESOURCEA(IDI_ADDCONTACT), "Add Contact Permanently to List"); wndData->hIcons[1] = InitMButton(hwndDlg, IDC_DETAILS, MAKEINTRESOURCEA(IDI_USERDETAILS), "View User's Details"); wndData->hIcons[2] = InitMButton(hwndDlg, IDC_HISTORY, MAKEINTRESOURCEA(IDI_HISTORY), "View User's History"); wndData->hIcons[3] = InitMButton(hwndDlg, IDC_USERMENU, MAKEINTRESOURCEA(IDI_DOWNARROW), "User Menu"); SendMessageT(hwndDlg,DM_UPDATETITLE,0,0); // new dialog init done Utils_RestoreWindowPosition(hwndDlg, NULL, MODULENAME, ""); return TRUE; } case WM_NOTIFY: if (((LPNMHDR)lParam)->idFrom == IDC_CONTACTS) { switch (((LPNMHDR)lParam)->code) { case NM_DBLCLK: { HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); if (ListView_GetSelectedCount(hLV) != 1) break; // if not clicking on item, bye wndData->iPopupItem = ListView_GetNextItem(hLV, -1, LVNI_ALL|LVNI_SELECTED); if (wndData->iPopupItem == -1) break; // if no item selected no user details available return SendMessageT(hwndDlg, WM_COMMAND, ID_POPUP_USERDETAILS, 0); // show user details } case LVN_ITEMCHANGED: { LPNMLISTVIEW pNMLV = (LPNMLISTVIEW)lParam; HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); // optimisation, for FOR-Cycle bool bExistsCheckedItem = false; // there must be no checked items to disable "Add" button if (ListView_GetCheckState(hLV, pNMLV->iItem)) { // the user has checked this item bExistsCheckedItem = true; // enable "Add" button } else { // loop thru items and check if at least one is checked for (int i = 0; i < ListView_GetItemCount(hLV); i++) if (ListView_GetCheckState(hLV, i)) { // we found checked item, enable add, exit loop bExistsCheckedItem = true; break; } } EnableDlgItem(hwndDlg, IDOK, bExistsCheckedItem); EnableDlgItem(hwndDlg, IDDETAILS, ListView_GetSelectedCount(hLV) > 0); break; } } } break; case WM_COMMAND: { if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)wndData->mhContact)) break; switch(LOWORD(wParam)) { case IDOK: // "Add Selected" button click { // for each selected item, find its index in the hDbEvent // and after that add this item to the DB permanently char* caUIN; HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); HWND hGroupsCombo = GetDlgItem(hwndDlg, IDC_GROUPS); HWND hGroupsCheck = GetDlgItem(hwndDlg, IDC_ENABLEGROUPS); int curs = SendMessageT(hGroupsCombo, CB_GETCURSEL, 0, 0); TCHAR* caGroup = NULL; int nGroupId = -1; if (curs != CB_ERR && IsWindowEnabled(hGroupsCheck) && SendMessageT(hGroupsCheck, BM_GETCHECK, 0, 0)) { //got groups, get the one selected in combo TCHAR* caGroup = (TCHAR*)_malloca((SendMessageT(hGroupsCombo, CB_GETLBTEXTLEN, curs, 0) + 1) * sizeof(WCHAR)); SendMessageT(hGroupsCombo, CB_GETLBTEXT, curs, (LPARAM)caGroup); nGroupId = SendMessageT(hGroupsCombo, CB_GETITEMDATA, curs, 0); } for (int i = 0; i < ListView_GetItemCount(hLV); i++) if (ListView_GetCheckState(hLV, i)) { // found checked contact item, add it caUIN = ListView_GetItemTextEx(hLV, i, 0); for (int j = 0; j < wndData->cbReceived; j++) // determine item index in packet if (!strcmpnull(wndData->maReceived[j]->mcaUIN, caUIN)) { char* szProto = GetContactProto(wndData->mhContact); HANDLE hContact = (HANDLE)SRCCallProtoService(szProto, PS_ADDTOLISTBYEVENT, MAKEWPARAM(0, j), (LPARAM)wndData->mhDbEvent); if (hContact && caGroup) { // use newest group API if available if (ServiceExists(MS_CLIST_CONTACTCHANGEGROUP)) CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, (LPARAM)nGroupId); else DBWriteContactSettingStringT(hContact, "CList", "Group", caGroup); } break; } SAFE_FREE((void**)&caUIN); } // move to next item break; } case IDDETAILS: { // for each selected item, find its index in the hDbEvent // and after that add this item to the DB // finally, request Details window for this hContact HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); for (int i = 0; i < ListView_GetItemCount(hLV); i++) if (ListView_GetItemState(hLV, i, LVIS_SELECTED)) { HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, i); if (hContact) CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0); } break; } case IDCANCEL: { SendMessageT(hwndDlg, WM_CLOSE, 0, 0); break; } case IDC_ENABLEGROUPS: { EnableGroupCombo(hwndDlg); break; } case IDC_GROUPS: { // rebuild group list on popup if (HIWORD(wParam) == CBN_DROPDOWN) RebuildGroupCombo(hwndDlg); break; } case ID_POPUP_ADDUSER: { HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem); if (hContact) DialogAddContactExecute(hwndDlg, hContact); break; } case ID_POPUP_USERDETAILS: { HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem); if (hContact) CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0 ); break; } case ID_POPUP_SENDMESSAGE: { HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem); if (hContact) CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0); break; } case IDC_USERMENU: { RECT rc; HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)wndData->mhContact, 0); GetWindowRect(GetDlgItem(hwndDlg,IDC_USERMENU), &rc); TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); DestroyMenu(hMenu); break; } case IDC_HISTORY: CallService(MS_HISTORY_SHOWCONTACTHISTORY,(WPARAM)wndData->mhContact,0); break; case IDC_DETAILS: CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)wndData->mhContact,0); break; case IDC_ADD: DialogAddContactExecute(hwndDlg, wndData->mhContact); break; } break; } case WM_CONTEXTMENU: { HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); LVHITTESTINFO lvh; RECT rt; wndData->iPopupItem = -1; if ((HWND)wParam != hLV) break; // if not our ListView go away lvh.pt.x = LOWORD(lParam); lvh.pt.y = HIWORD(lParam); if (GetWindowRect(hLV, &rt)==0) return FALSE; // ?? why this, some check ?? ScreenToClient(hLV, &lvh.pt); // convert to ListView local coordinates int ci = ListView_HitTest(hLV, &lvh); if (ci==-1) break; // mouse is not over any item wndData->iPopupItem = ci; TrackPopupMenu(GetSubMenu(wndData->mhPopup, 0), TPM_LEFTALIGN|TPM_TOPALIGN, LOWORD(lParam), HIWORD(lParam), 0, hwndDlg, NULL); break; } case HM_EVENTSENT: { ACKDATA *ack=(ACKDATA*)lParam; if (ack->type!=ACKTYPE_SEARCH) break; // not search ack, go away if (ack->hProcess!=wndData->rhSearch) break; //not our search, go away if (ack->result==ACKRESULT_DATA) { HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); PROTOSEARCHRESULT* psr = (PROTOSEARCHRESULT*)ack->lParam; LVFINDINFO fi; fi.flags = LVFI_STRING; fi.psz = wndData->haUin; int iLPos = ListView_FindItem(hLV, -1, &fi); if (iLPos==-1) iLPos=0; // ListView_SetItemText(hLV, iLPos, 0, psr->email); // not sent by ICQ, and currently unsupported either if (strcmpnull(psr->nick, "") && psr->nick) ListView_SetItemText(hLV, iLPos, 1, psr->nick); ListView_SetItemText(hLV, iLPos, 2, psr->firstName); ListView_SetItemText(hLV, iLPos, 3, psr->lastName); break; } SAFE_FREE((void**)&wndData->haUin); break; } case WM_CLOSE: // user closed window, so destroy it { WindowList_Remove(ghRecvWindowList, hwndDlg); DestroyWindow(hwndDlg); break; } case WM_DESTROY: // last message received by this dialog, cleanup { CallService(MS_DB_EVENT_MARKREAD, (WPARAM)wndData->mhContact, (LPARAM)wndData->mhDbEvent); Utils_SaveWindowPosition(hwndDlg, NULL, MODULENAME, ""); ImageList_Destroy(wndData->mhListIcon); UnhookEvent(wndData->hHook); DestroyMenu(wndData->mhPopup); for (int i=0; i < SIZEOF(wndData->hIcons); i++) DestroyIcon(wndData->hIcons[i]); delete wndData; // automatically calls destructor break; } case WM_MEASUREITEM: return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); case WM_DRAWITEM: { DrawProtocolIcon(hwndDlg, lParam, wndData->mhContact); return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); } case WM_SIZE: { // make the dlg resizeable UTILRESIZEDIALOG urd = {0}; if (IsIconic(hwndDlg)) break; urd.cbSize = sizeof(urd); urd.hInstance = hInst; urd.hwndDlg = hwndDlg; urd.lParam = 0; // user-defined urd.lpTemplate = MAKEINTRESOURCEA(IDD_RECEIVE); urd.pfnResizer = RecvDlg_Resize; CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd); break; } case WM_GETMINMAXINFO: { MINMAXINFO* mmi=(MINMAXINFO*)lParam; mmi->ptMinTrackSize.x = 480+2*GetSystemMetrics(SM_CXSIZEFRAME); mmi->ptMinTrackSize.y = 130+2*GetSystemMetrics(SM_CYSIZEFRAME); break; } case DM_UPDATETITLE: { UpdateDialogTitle(hwndDlg, wndData?wndData->mhContact:NULL, "Contacts from"); if (wndData) UpdateDialogAddButton(hwndDlg, wndData->mhContact); break; } } return FALSE; }
void ChangeInfoData::BeginListEdit(int iItem, RECT *rc, int iSetting, WORD wVKey) { if (dataListEdit) dataListEdit->EndListEdit(0); POINT pt = { 0, 0 }; ClientToScreen(hwndList, &pt); OffsetRect(rc, pt.x, pt.y); InflateRect(rc, -2, -2); rc->left -= 2; iEditItem = iItem; ListView_RedrawItems(hwndList, iEditItem, iEditItem); UpdateWindow(hwndList); dataListEdit = this; hwndListEdit = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, _T("LISTBOX"), _T(""), WS_POPUP | WS_BORDER | WS_VSCROLL, rc->left, rc->bottom, rc->right - rc->left, 150, NULL, NULL, hInst, NULL); SendMessage(hwndListEdit, WM_SETFONT, (WPARAM)hListFont, 0); int itemHeight = SendMessage(hwndListEdit, LB_GETITEMHEIGHT, 0, 0); const SettingItem &si = setting[iSetting]; SettingItemData &sid = settingData[iSetting]; FieldNamesItem *list = (FieldNamesItem*)si.pList; // some country codes were changed leaving old details uknown, convert it for the user if (list == countryField) { if (sid.value == 420) sid.value = 42; // conversion of obsolete codes (OMG!) else if (sid.value == 421) sid.value = 4201; else if (sid.value == 102) sid.value = 1201; } if (list == timezonesField) { tmi.prepareList(NULL, ppro->m_szModuleName, hwndListEdit, TZF_PLF_LB); } else { int j, n = ListBoxAddStringUtf(hwndListEdit, "Unspecified"); for (j = 0;; j++) if (!list[j].text) { SendMessage(hwndListEdit, LB_SETITEMDATA, n, j); if ((sid.value == 0 && list[j].code == 0) || (si.dbType != DBVT_ASCIIZ && sid.value == list[j].code)) SendMessage(hwndListEdit, LB_SETCURSEL, n, 0); break; } for (j = 0; list[j].text; j++) { char str[MAX_PATH]; n = ListBoxAddStringUtf(hwndListEdit, list[j].text); SendMessage(hwndListEdit, LB_SETITEMDATA, n, j); if ((si.dbType == DBVT_ASCIIZ && (!strcmpnull((char*)sid.value, list[j].text)) || (si.dbType == DBVT_ASCIIZ && (!strcmpnull((char*)sid.value, ICQTranslateUtfStatic(list[j].text, str, MAX_PATH)))) || ((char*)sid.value == NULL && list[j].code == 0)) || (si.dbType != DBVT_ASCIIZ && sid.value == list[j].code)) SendMessage(hwndListEdit, LB_SETCURSEL, n, 0); } SendMessage(hwndListEdit, LB_SETTOPINDEX, SendMessage(hwndListEdit, LB_GETCURSEL, 0, 0) - 3, 0); } int listCount = SendMessage(hwndListEdit, LB_GETCOUNT, 0, 0); if (itemHeight * listCount < 150) SetWindowPos(hwndListEdit, 0, 0, 0, rc->right - rc->left, itemHeight * listCount + GetSystemMetrics(SM_CYBORDER) * 2, SWP_NOZORDER | SWP_NOMOVE); mir_subclassWindow(hwndListEdit, ListEditSubclassProc); AnimateWindow(hwndListEdit, 200, AW_SLIDE | AW_ACTIVATE | AW_VER_POSITIVE); ShowWindow(hwndListEdit, SW_SHOW); SetFocus(hwndListEdit); if (wVKey) PostMessage(hwndListEdit, WM_KEYDOWN, wVKey, 0); }