From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- icqj_mod/utilities.c | 1941 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1941 insertions(+) create mode 100644 icqj_mod/utilities.c (limited to 'icqj_mod/utilities.c') diff --git a/icqj_mod/utilities.c b/icqj_mod/utilities.c new file mode 100644 index 0000000..279874c --- /dev/null +++ b/icqj_mod/utilities.c @@ -0,0 +1,1941 @@ +// ---------------------------------------------------------------------------80 +// ICQ plugin for Miranda Instant Messenger +// ________________________________________ +// +// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede +// Copyright © 2001,2002 Jon Keating, Richard Hughes +// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater +// Copyright © 2004,2005,2006 Joe Kucera +// +// 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. +// +// ----------------------------------------------------------------------------- +// +// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/utilities.c,v $ +// Revision : $Revision: 3130 $ +// Last change on : $Date: 2006-06-13 23:02:57 +0200 (Tue, 13 Jun 2006) $ +// Last change by : $Author: jokusoftware $ +// +// DESCRIPTION: +// +// Describe me here please... +// +// ----------------------------------------------------------------------------- + +#include "icqoscar.h" + + + +typedef struct gateway_index_s +{ + HANDLE hConn; + DWORD dwIndex; +} gateway_index; + +extern CRITICAL_SECTION cookieMutex; + +static gateway_index *gateways = NULL; +static int gatewayCount = 0; + +static DWORD *spammerList = NULL; +static int spammerListCount = 0; + + +static icq_contacts_cache *contacts_cache = NULL; +static int cacheCount = 0; +static int cacheListSize = 0; +static CRITICAL_SECTION cacheMutex; + +extern BYTE gbOverRate; +extern DWORD gtLastRequest; +extern BOOL bIsSyncingCL; + + +void EnableDlgItem(HWND hwndDlg, UINT control, int state) +{ + EnableWindow(GetDlgItem(hwndDlg, control), state); +} + + + +void icq_EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state) +{ + int i; + + for (i = 0; i < cControls; i++) + EnableDlgItem(hwndDlg, controls[i], state); +} + + + +void icq_ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state) +{ + int i; + + for(i = 0; i < cControls; i++) + ShowWindow(GetDlgItem(hwndDlg, controls[i]), state); +} + + +// Maps the ICQ status flag (as seen in the status change SNACS) and returns +// a Miranda style status. +int IcqStatusToMiranda(WORD nIcqStatus) +{ + int nMirandaStatus; + + // :NOTE: The order in which the flags are compared are important! + // I dont like this method but it works. + + if (nIcqStatus & ICQ_STATUSF_INVISIBLE) + nMirandaStatus = ID_STATUS_INVISIBLE; + else + if (nIcqStatus & ICQ_STATUSF_DND) + nMirandaStatus = ID_STATUS_DND; + else + if (nIcqStatus & ICQ_STATUSF_OCCUPIED) + nMirandaStatus = ID_STATUS_OCCUPIED; + else + if (nIcqStatus & ICQ_STATUSF_NA) + nMirandaStatus = ID_STATUS_NA; + else + if (nIcqStatus & ICQ_STATUSF_AWAY) + nMirandaStatus = ID_STATUS_AWAY; + else + if (nIcqStatus & ICQ_STATUSF_FFC) + nMirandaStatus = ID_STATUS_FREECHAT; + else + // Can be discussed, but I think 'online' is the most generic ICQ status + nMirandaStatus = ID_STATUS_ONLINE; + + return nMirandaStatus; +} + + + +WORD MirandaStatusToIcq(int nMirandaStatus) +{ + WORD nIcqStatus; + + + switch (nMirandaStatus) + { + + case ID_STATUS_ONLINE: + nIcqStatus = ICQ_STATUS_ONLINE; + break; + + case ID_STATUS_AWAY: + nIcqStatus = ICQ_STATUS_AWAY; + break; + + case ID_STATUS_OUTTOLUNCH: + case ID_STATUS_NA: + nIcqStatus = ICQ_STATUS_NA; + break; + + case ID_STATUS_ONTHEPHONE: + case ID_STATUS_OCCUPIED: + nIcqStatus = ICQ_STATUS_OCCUPIED; + break; + + case ID_STATUS_DND: + nIcqStatus = ICQ_STATUS_DND; + break; + + case ID_STATUS_INVISIBLE: + nIcqStatus = ICQ_STATUS_INVISIBLE; + break; + + case ID_STATUS_FREECHAT: + nIcqStatus = ICQ_STATUS_FFC; + break; + + case ID_STATUS_OFFLINE: + // Oscar doesnt have anything that maps to this status. This should never happen. + _ASSERTE(nMirandaStatus != ID_STATUS_OFFLINE); + nIcqStatus = 0; + break; + + default: + // Online seems to be a good default. + // Since it cant be offline, it must be a new type of online status. + nIcqStatus = ICQ_STATUS_ONLINE; + break; + } + + return nIcqStatus; +} + + + +int MirandaStatusToSupported(int nMirandaStatus) +{ + int nSupportedStatus; + + switch (nMirandaStatus) + { + + // These status mode does not need any mapping + case ID_STATUS_ONLINE: + case ID_STATUS_AWAY: + case ID_STATUS_NA: + case ID_STATUS_OCCUPIED: + case ID_STATUS_DND: + case ID_STATUS_INVISIBLE: + case ID_STATUS_FREECHAT: + case ID_STATUS_OFFLINE: + nSupportedStatus = nMirandaStatus; + break; + + // This mode is not support and must be mapped to something else + case ID_STATUS_OUTTOLUNCH: + nSupportedStatus = ID_STATUS_NA; + break; + + // This mode is not support and must be mapped to something else + case ID_STATUS_ONTHEPHONE: + nSupportedStatus = ID_STATUS_OCCUPIED; + break; + + // This is not supposed to happen. + default: + _ASSERTE(0); + // Online seems to be a good default. + nSupportedStatus = ID_STATUS_ONLINE; + break; + } + + return nSupportedStatus; +} + + + +char* MirandaStatusToString(int mirandaStatus) +{ + return (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, 0); +} + + + +char* MirandaStatusToStringUtf(int mirandaStatus) +{ + char* szRes = NULL; + + if (gbUnicodeCore) + { // we can get unicode version, request, give utf-8 + szRes = make_utf8_string((wchar_t *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, GCMDF_UNICODE)); + } + else + { // we are ansi only, get it, convert to utf-8 + utf8_encode(MirandaStatusToString(mirandaStatus), &szRes); + } + return szRes; +} + + + +char**MirandaStatusToAwayMsg(int nStatus) +{ + switch (nStatus) + { + + case ID_STATUS_AWAY: + return &modeMsgs.szAway; + break; + + case ID_STATUS_NA: + return &modeMsgs.szNa; + + case ID_STATUS_OCCUPIED: + return &modeMsgs.szOccupied; + + case ID_STATUS_DND: + return &modeMsgs.szDnd; + + case ID_STATUS_FREECHAT: + return &modeMsgs.szFfc; + + default: + return NULL; + } +} + + + +int AwayMsgTypeToStatus(int nMsgType) +{ + switch (nMsgType) + { + case MTYPE_AUTOAWAY: + return ID_STATUS_AWAY; + + case MTYPE_AUTOBUSY: + return ID_STATUS_OCCUPIED; + + case MTYPE_AUTONA: + return ID_STATUS_NA; + + case MTYPE_AUTODND: + return ID_STATUS_DND; + + case MTYPE_AUTOFFC: + return ID_STATUS_FREECHAT; + + default: + return ID_STATUS_OFFLINE; + } +} + + + +void SetGatewayIndex(HANDLE hConn, DWORD dwIndex) +{ + int i; + + EnterCriticalSection(&cookieMutex); + + for (i = 0; i < gatewayCount; i++) + { + if (hConn == gateways[i].hConn) + { + gateways[i].dwIndex = dwIndex; + + LeaveCriticalSection(&cookieMutex); + + return; + } + } + + gateways = (gateway_index *)realloc(gateways, sizeof(gateway_index) * (gatewayCount + 1)); + gateways[gatewayCount].hConn = hConn; + gateways[gatewayCount].dwIndex = dwIndex; + gatewayCount++; + + LeaveCriticalSection(&cookieMutex); + + return; +} + + + +DWORD GetGatewayIndex(HANDLE hConn) +{ + int i; + + EnterCriticalSection(&cookieMutex); + + for (i = 0; i < gatewayCount; i++) + { + if (hConn == gateways[i].hConn) + { + LeaveCriticalSection(&cookieMutex); + + return gateways[i].dwIndex; + } + } + + LeaveCriticalSection(&cookieMutex); + + return 1; // this is default +} + + + +void FreeGatewayIndex(HANDLE hConn) +{ + int i; + + + EnterCriticalSection(&cookieMutex); + + for (i = 0; i < gatewayCount; i++) + { + if (hConn == gateways[i].hConn) + { + gatewayCount--; + memmove(&gateways[i], &gateways[i+1], sizeof(gateway_index) * (gatewayCount - i)); + gateways = (gateway_index*)realloc(gateways, sizeof(gateway_index) * gatewayCount); + + // Gateway found, exit loop + break; + } + } + + LeaveCriticalSection(&cookieMutex); +} + + + +void AddToSpammerList(DWORD dwUIN) +{ + EnterCriticalSection(&cookieMutex); + + spammerList = (DWORD *)realloc(spammerList, sizeof(DWORD) * (spammerListCount + 1)); + spammerList[spammerListCount] = dwUIN; + spammerListCount++; + + LeaveCriticalSection(&cookieMutex); +} + + + +BOOL IsOnSpammerList(DWORD dwUIN) +{ + int i; + + EnterCriticalSection(&cookieMutex); + + for (i = 0; i < spammerListCount; i++) + { + if (dwUIN == spammerList[i]) + { + LeaveCriticalSection(&cookieMutex); + + return TRUE; + } + } + + LeaveCriticalSection(&cookieMutex); + + return FALSE; +} + + + +// ICQ contacts cache +static void AddToCache(HANDLE hContact, DWORD dwUin) +{ + int i = 0; + + if (!hContact || !dwUin) + return; + + EnterCriticalSection(&cacheMutex); + + if (cacheCount + 1 >= cacheListSize) + { + cacheListSize += 100; + contacts_cache = (icq_contacts_cache *)realloc(contacts_cache, sizeof(icq_contacts_cache) * cacheListSize); + } + +#ifdef _DEBUG + Netlib_Logf(ghServerNetlibUser, "Adding contact to cache: %u, position: %u", dwUin, cacheCount); +#endif + + contacts_cache[cacheCount].hContact = hContact; + contacts_cache[cacheCount].dwUin = dwUin; + + cacheCount++; + + LeaveCriticalSection(&cacheMutex); +} + +int GetFromCacheByID(int ID, HANDLE *hContact, DWORD *dwUin) +{ + + DWORD uin; + + if (ID < 0 || ID >= cacheCount) + return 0; + + EnterCriticalSection(&cacheMutex); + + if (hContact) + *hContact = contacts_cache[ID].hContact; + + uin = contacts_cache[ID].dwUin; + + if (dwUin) + *dwUin = uin; + + LeaveCriticalSection(&cacheMutex); + + return uin; // to be sure it is not 0 + +} + + +void InitCache(void) +{ + HANDLE hContact; + + InitializeCriticalSection(&cacheMutex); + cacheCount = 0; + cacheListSize = 0; + contacts_cache = NULL; + + // build cache + EnterCriticalSection(&cacheMutex); + + hContact = ICQFindFirstContact(); + + while (hContact) + { + DWORD dwUin; + + dwUin = ICQGetContactSettingUIN(hContact); + if (dwUin) AddToCache(hContact, dwUin); + + hContact = ICQFindNextContact(hContact); + } + + LeaveCriticalSection(&cacheMutex); +} + + + +void UninitCache(void) +{ + SAFE_FREE(&contacts_cache); + + DeleteCriticalSection(&cacheMutex); +} + + + +void DeleteFromCache(HANDLE hContact) +{ + int i; + + if (cacheCount == 0) + return; + + EnterCriticalSection(&cacheMutex); + + for (i = cacheCount-1; i >= 0; i--) + if (contacts_cache[i].hContact == hContact) + { + cacheCount--; + +#ifdef _DEBUG + Netlib_Logf(ghServerNetlibUser, "Removing contact from cache: %u, position: %u", contacts_cache[i].dwUin, i); +#endif + // move last contact to deleted position + if (i < cacheCount) + memcpy(&contacts_cache[i], &contacts_cache[cacheCount], sizeof(icq_contacts_cache)); + + // clear last contact position + ZeroMemory(&contacts_cache[cacheCount], sizeof(icq_contacts_cache)); + + break; + } + + LeaveCriticalSection(&cacheMutex); +} + + + +static HANDLE HandleFromCacheByUin(DWORD dwUin) +{ + int i; + HANDLE hContact = NULL; + + if (cacheCount == 0) + return hContact; + + EnterCriticalSection(&cacheMutex); + + for (i = cacheCount-1; i >= 0; i--) + if (contacts_cache[i].dwUin == dwUin) + { + hContact = contacts_cache[i].hContact; + break; + } + + LeaveCriticalSection(&cacheMutex); + + return hContact; +} + + + +HANDLE HContactFromUIN(DWORD uin, int *Added) +{ + HANDLE hContact; + + if (Added) *Added = 0; + + hContact = HandleFromCacheByUin(uin); + if (hContact) return hContact; + + hContact = ICQFindFirstContact(); + while (hContact != NULL) + { + DWORD dwUin; + + dwUin = ICQGetContactSettingUIN(hContact); + if (dwUin == uin) + { + AddToCache(hContact, dwUin); + return hContact; + } + + hContact = ICQFindNextContact(hContact); + } + + //not present: add + if (Added) + { + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + if (!hContact) + { + NetLog_Server("Failed to create ICQ contact %u", uin); + return INVALID_HANDLE_VALUE; + } + + if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)gpszICQProtoName) != 0) + { + // For some reason we failed to register the protocol to this contact + CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + NetLog_Server("Failed to register ICQ contact %u", uin); + return INVALID_HANDLE_VALUE; + } + + ICQWriteContactSettingDword(hContact, UNIQUEIDSETTING, uin); + + if (!bIsSyncingCL) + { + DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + SetContactHidden(hContact, 1); + + ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE); + + icq_QueueUser(hContact); + + if (icqOnline) + { + icq_sendNewContact(uin, NULL); + // else need to wait for CList/NotOnList to be deleted + //icq_GetUserStatus(hContact, 3); + } + } + AddToCache(hContact, uin); + *Added = 1; + + return hContact; + } + + // not in list, check that uin do not belong to us + if (ICQGetContactSettingUIN(NULL) == uin) + return NULL; + + return INVALID_HANDLE_VALUE; +} + + + +HANDLE HContactFromUID(DWORD dwUIN, char* pszUID, int *Added) +{ + HANDLE hContact; + DWORD dwUin; + uid_str szUid; + + if (dwUIN) + return HContactFromUIN(dwUIN, Added); + + if (Added) *Added = 0; + + if (!gbAimEnabled) return INVALID_HANDLE_VALUE; + + hContact = ICQFindFirstContact(); + while (hContact != NULL) + { + if (!ICQGetContactSettingUID(hContact, &dwUin, &szUid)) + { + if (!dwUin && !stricmp(szUid, pszUID)) + { + if (strcmpnull(szUid, pszUID)) + { // fix case in SN + ICQWriteContactSettingString(hContact, UNIQUEIDSETTING, pszUID); + } + return hContact; + } + } + hContact = ICQFindNextContact(hContact); + } + + //not present: add + if (Added) + { + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)gpszICQProtoName); + + ICQWriteContactSettingString(hContact, UNIQUEIDSETTING, pszUID); + + if (!bIsSyncingCL) + { + DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + SetContactHidden(hContact, 1); + + ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE); + + if (icqOnline) + { + icq_sendNewContact(0, pszUID); + } + } + *Added = 1; + + return hContact; + } + + return INVALID_HANDLE_VALUE; +} + + + +char *NickFromHandle(HANDLE hContact) +{ + if (hContact == INVALID_HANDLE_VALUE) + return null_strdup(ICQTranslate("")); + + return null_strdup((char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0)); +} + +void NickFromHandleStatic(HANDLE hContact, char *szNick, WORD wLen) +{ + + if (!wLen || !szNick) return; + + if (hContact == INVALID_HANDLE_VALUE) + lstrcpyn(szNick, "", wLen); + else + lstrcpyn(szNick, (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0), wLen); + +} + + +char *NickFromHandleUtf(HANDLE hContact) +{ + if (hContact == INVALID_HANDLE_VALUE) + return ICQTranslateUtf(""); + + if (gbUnicodeCore) + return make_utf8_string((wchar_t*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_UNICODE)); + else + { + unsigned char *utf = NULL; + + utf8_encode((char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0), &utf); + return utf; + } +} + + + +char *strUID(DWORD dwUIN, char *pszUID) +{ + if (dwUIN) + ltoa(dwUIN, pszUID, 10); + + return pszUID; +} + + + +void SetContactHidden(HANDLE hContact, BYTE bHidden) +{ + DBWriteContactSettingByte(hContact, "CList", "Hidden", bHidden); + + if (!bHidden) // clear zero setting + DBDeleteContactSetting(hContact, "CList", "Hidden"); +} + + + +/* a strlennull() that likes NULL */ +size_t __fastcall strlennull(const char *string) +{ + if (string) + return strlen(string); + + return 0; +} + + +/* a strcmp() that likes NULL */ +int __fastcall strcmpnull(const char *str1, const char *str2) +{ + if (str1 && str2) + return strcmp(str1, str2); + + return 1; +} + + + +int null_snprintf(char *buffer, size_t count, const char* fmt, ...) +{ + va_list va; + int len; + + ZeroMemory(buffer, count); + va_start(va, fmt); + len = _vsnprintf(buffer, count-1, fmt, va); + va_end(va); + return len; +} + + + +char* __fastcall null_strdup(const char *string) +{ + if (string) + return strdup(string); + + return NULL; +} + + + +void parseServerAddress(char* szServer, WORD* wPort) +{ + int i = 0; + + while (szServer[i] && szServer[i] != ':') i++; + if (szServer[i] == ':') + { // port included + *wPort = atoi(&szServer[i + 1]); + } + else // port not found, use pre-configured + { + *wPort = ICQGetContactSettingWord(NULL, "OscarPort", DEFAULT_SERVER_PORT); + if (!*wPort) *wPort = (WORD)RandRange(1024, 65535); + } + + szServer[i] = '\0'; +} + + + +char *DemangleXml(const char *string, int len) +{ + char *szWork = (char*)SAFE_MALLOC(len+1), *szChar = szWork; + int i; + + for (i=0; i') l += 4; else if (string[i]=='&') l += 5; else l++; + } + szChar = szWork = (char*)SAFE_MALLOC(l + 1); + for (i = 0; i') + { + *(DWORD*)szChar = ';tg&'; + szChar += 4; + } + else if (string[i]=='&') + { + *(DWORD*)szChar = 'pma&'; + szChar += 4; + *szChar = ';'; + szChar++; + } + else + { + *szChar = string[i]; + szChar++; + } + } + *szChar = '\0'; + + return szWork; +} + + + +char *EliminateHtml(const char *string, int len) +{ + char *tmp = (char*)SAFE_MALLOC(len + 1); + int i,j; + BOOL tag = FALSE; + char *res; + + for (i=0,j=0;i", 4) || !strnicmp(string + i, "
", 5))) + { // insert newline + tmp[j] = '\r'; + j++; + tmp[j] = '\n'; + j++; + } + tag = TRUE; + } + else if (tag && string[i] == '>') + { + tag = FALSE; + } + else if (!tag) + { + tmp[j] = string[i]; + j++; + } + tmp[j] = '\0'; + } + SAFE_FREE((void**)&string); + res = DemangleXml(tmp, strlennull(tmp)); + SAFE_FREE(&tmp); + + return res; +} + +void makeUserOffline(HANDLE hContact) +{ + + WORD w; + DWORD dw; + + if (DBGetContactSettingWord(hContact, gpszICQProtoName, "Status", 0) != ID_STATUS_OFFLINE) + DBWriteContactSettingWord(hContact, gpszICQProtoName, "Status", ID_STATUS_OFFLINE); + + if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "LogonTS", 0)) { + DBWriteContactSettingDword(hContact, gpszICQProtoName, "LogonTS", 0); + DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldLogonTS", dw); + } + + if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "IdleTS", 0)) { + DBWriteContactSettingDword(hContact, gpszICQProtoName, "IdleTS", 0); + DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldIdleTS", dw); + } + + if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "RealIP", 0)) { + DBWriteContactSettingDword(hContact, gpszICQProtoName, "RealIP", 0); + DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldRealIP", dw); + } + + if (dw=DBGetContactSettingDword(hContact, gpszICQProtoName, "IP", 0)) { + DBWriteContactSettingDword(hContact, gpszICQProtoName, "IP", 0); + DBWriteContactSettingDword(hContact, gpszICQProtoName, "OldIP", dw); + } + + if (w=DBGetContactSettingWord(hContact, gpszICQProtoName, "UserPort", 0)) { + DBWriteContactSettingWord(hContact, gpszICQProtoName, "UserPort", 0); + DBWriteContactSettingWord(hContact, gpszICQProtoName, "OldUserPort", w); + } + + if (w=DBGetContactSettingWord(hContact, gpszICQProtoName, "Version", 0)) { + DBWriteContactSettingWord(hContact, gpszICQProtoName, "Version", 0); + DBWriteContactSettingWord(hContact, gpszICQProtoName, "OldVersion", w); + } + + + // if (DBGetContactSettingDword(hContact, gpszICQProtoName, "TickTS", 0)) + // DBWriteContactSettingDword(hContact, gpszICQProtoName, "TickTS", 0); + + //DBWriteContactSettingDword(hContact, gpszICQProtoName, "DirectCookie", 0); +} + + +void ResetSettingsOnListReload() +{ + HANDLE hContact; + + // Reset a bunch of session specific settings + ICQWriteContactSettingWord(NULL, "SrvVisibilityID", 0); + ICQWriteContactSettingWord(NULL, "SrvAvatarID", 0); + ICQWriteContactSettingWord(NULL, "SrvRecordCount", 0); + + hContact = ICQFindFirstContact(); + + while (hContact) + { + // All these values will be restored during the serv-list receive + ICQWriteContactSettingWord(hContact, "ServerId", 0); + ICQWriteContactSettingWord(hContact, "SrvGroupId", 0); + ICQWriteContactSettingWord(hContact, "SrvPermitId", 0); + ICQWriteContactSettingWord(hContact, "SrvDenyId", 0); + ICQWriteContactSettingByte(hContact, "Auth", 0); + + hContact = ICQFindNextContact(hContact); + } + + FlushSrvGroupsCache(); +} + + + +void ResetSettingsOnConnect() +{ + HANDLE hContact; + + gbOverRate = 0; // init + gtLastRequest = 0; + + // Reset a bunch of session specific settings + ICQWriteContactSettingByte(NULL, "SrvVisibility", 0); + ICQWriteContactSettingDword(NULL, "IdleTS", 0); + + hContact = ICQFindFirstContact(); + + while (hContact) + { + ICQWriteContactSettingDword(hContact, "LogonTS", 0); + ICQWriteContactSettingDword(hContact, "IdleTS", 0); + ICQWriteContactSettingDword(hContact, "TickTS", 0); + ICQDeleteContactSetting(hContact, "TemporaryVisible"); + + // All these values will be restored during the login + if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE) + ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE); + + hContact = ICQFindNextContact(hContact); + } +} + + + +void ResetSettingsOnLoad() +{ + HANDLE hContact; + + ICQWriteContactSettingDword(NULL, "IdleTS", 0); + ICQWriteContactSettingDword(NULL, "LogonTS", 0); + + hContact = ICQFindFirstContact(); + + while (hContact) + { + ICQWriteContactSettingDword(hContact, "LogonTS", 0); + ICQWriteContactSettingDword(hContact, "IdleTS", 0); + ICQWriteContactSettingDword(hContact, "TickTS", 0); + if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE) + { + ICQWriteContactSettingWord(hContact, "Status", ID_STATUS_OFFLINE); + + ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSID); + ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSNAME); + ICQDeleteContactSetting(hContact, DBSETTING_XSTATUSMSG); + } + hContact = ICQFindNextContact(hContact); + } +} + + + +int RandRange(int nLow, int nHigh) +{ + return nLow + (int)((nHigh-nLow+1)*rand()/(RAND_MAX+1.0)); +} + + + +BOOL IsStringUIN(char* pszString) +{ + int i; + int nLen = strlennull(pszString); + + + if (nLen > 0 && pszString[0] != '0') + { + for (i=0; i '9')) + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + + + +void __cdecl icq_ProtocolAckThread(icq_ack_args* pArguments) +{ + ICQBroadcastAck(pArguments->hContact, pArguments->nAckType, pArguments->nAckResult, pArguments->hSequence, pArguments->pszMessage); + + if (pArguments->nAckResult == ACKRESULT_SUCCESS) + NetLog_Server("Sent fake message ack"); + else if (pArguments->nAckResult == ACKRESULT_FAILED) + NetLog_Server("Message delivery failed"); + + SAFE_FREE((char **)&pArguments->pszMessage); + SAFE_FREE(&pArguments); + + return; +} + + + +void icq_SendProtoAck(HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, char* pszMessage) +{ + icq_ack_args* pArgs; + + + pArgs = (icq_ack_args*)SAFE_MALLOC(sizeof(icq_ack_args)); // This will be freed in the new thread + + pArgs->hContact = hContact; + pArgs->hSequence = (HANDLE)dwCookie; + pArgs->nAckResult = nAckResult; + pArgs->nAckType = nAckType; + pArgs->pszMessage = (LPARAM)null_strdup(pszMessage); + + forkthread(icq_ProtocolAckThread, 0, pArgs); +} + + + +void SetCurrentStatus(int nStatus) +{ + int nOldStatus = gnCurrentStatus; + + gnCurrentStatus = nStatus; + ICQBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)nOldStatus, nStatus); +} + + + +BOOL writeDbInfoSettingString(HANDLE hContact, const char* szSetting, char** buf, WORD* pwLength) +{ + WORD wLen; + + + if (*pwLength < 2) + return FALSE; + + unpackLEWord(buf, &wLen); + *pwLength -= 2; + + if (*pwLength < wLen) + return FALSE; + + if ((wLen > 0) && (**buf) && ((*buf)[wLen-1]==0)) // Make sure we have a proper string + { + WORD wCp = ICQGetContactSettingWord(hContact, "InfoCodePage", ICQGetContactSettingWord(hContact, "InfoCP", CP_ACP)); + + if (wCp != CP_ACP) + { + char *szUtf = ansi_to_utf8_codepage(*buf, wCp); + + if (szUtf) + { + ICQWriteContactSettingUtf(hContact, szSetting, szUtf); + SAFE_FREE(&szUtf); + } + else + ICQWriteContactSettingString(hContact, szSetting, *buf); + } + else + ICQWriteContactSettingString(hContact, szSetting, *buf); + } + else + ICQDeleteContactSetting(hContact, szSetting); + + *buf += wLen; + *pwLength -= wLen; + + return TRUE; +} + + + +BOOL writeDbInfoSettingWord(HANDLE hContact, const char *szSetting, char **buf, WORD* pwLength) +{ + WORD wVal; + + + if (*pwLength < 2) + return FALSE; + + unpackLEWord(buf, &wVal); + *pwLength -= 2; + + if (wVal != 0) + ICQWriteContactSettingWord(hContact, szSetting, wVal); + else + ICQDeleteContactSetting(hContact, szSetting); + + return TRUE; +} + + + +BOOL writeDbInfoSettingWordWithTable(HANDLE hContact, const char *szSetting, struct fieldnames_t *table, char **buf, WORD* pwLength) +{ + WORD wVal; + char sbuf[MAX_PATH]; + char *text; + + if (*pwLength < 2) + return FALSE; + + unpackLEWord(buf, &wVal); + *pwLength -= 2; + + text = LookupFieldNameUtf(table, wVal, sbuf); + if (text) + ICQWriteContactSettingUtf(hContact, szSetting, text); + else + ICQDeleteContactSetting(hContact, szSetting); + + return TRUE; +} + + + +BOOL writeDbInfoSettingByte(HANDLE hContact, const char *pszSetting, char **buf, WORD* pwLength) +{ + BYTE byVal; + + if (*pwLength < 1) + return FALSE; + + unpackByte(buf, &byVal); + *pwLength -= 1; + + if (byVal != 0) + ICQWriteContactSettingByte(hContact, pszSetting, byVal); + else + ICQDeleteContactSetting(hContact, pszSetting); + + return TRUE; +} + + + +BOOL writeDbInfoSettingByteWithTable(HANDLE hContact, const char *szSetting, struct fieldnames_t *table, char **buf, WORD* pwLength) +{ + BYTE byVal; + char sbuf[MAX_PATH]; + char *text; + + if (*pwLength < 1) + return FALSE; + + unpackByte(buf, &byVal); + *pwLength -= 1; + + text = LookupFieldNameUtf(table, byVal, sbuf); + if (text) + ICQWriteContactSettingUtf(hContact, szSetting, text); + else + ICQDeleteContactSetting(hContact, szSetting); + + return TRUE; +} + + + +// Returns the current GMT offset in seconds +int GetGMTOffset(void) +{ + TIME_ZONE_INFORMATION tzinfo; + DWORD dwResult; + int nOffset = 0; + + + dwResult = GetTimeZoneInformation(&tzinfo); + + switch(dwResult) + { + + case TIME_ZONE_ID_STANDARD: + nOffset = -(tzinfo.Bias + tzinfo.StandardBias) * 60; + break; + + case TIME_ZONE_ID_DAYLIGHT: + nOffset = -(tzinfo.Bias + tzinfo.DaylightBias) * 60; + break; + + case TIME_ZONE_ID_UNKNOWN: + case TIME_ZONE_ID_INVALID: + default: + nOffset = 0; + break; + + } + + return nOffset; +} + + + +BOOL validateStatusMessageRequest(HANDLE hContact, WORD byMessageType) +{ + // Privacy control + if (ICQGetContactSettingByte(NULL, "StatusMsgReplyCList", 0)) + { + // Don't send statusmessage to unknown contacts + if (hContact == INVALID_HANDLE_VALUE) + return FALSE; + + // Don't send statusmessage to temporary contacts or hidden contacts + if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) || + DBGetContactSettingByte(hContact, "CList", "Hidden", 0)) + return FALSE; + + // Don't send statusmessage to invisible contacts + if (ICQGetContactSettingByte(NULL, "StatusMsgReplyVisible", 0)) + { + WORD wStatus = ICQGetContactStatus(hContact); + if (wStatus == ID_STATUS_OFFLINE) + return FALSE; + } + } + + // Dont send messages to people you are hiding from + if (hContact != INVALID_HANDLE_VALUE && + ICQGetContactSettingWord(hContact, "ApparentMode", 0) == ID_STATUS_OFFLINE) + { + return FALSE; + } + + // Dont respond to request for other statuses than your current one + if ((byMessageType == MTYPE_AUTOAWAY && gnCurrentStatus != ID_STATUS_AWAY) || + (byMessageType == MTYPE_AUTOBUSY && gnCurrentStatus != ID_STATUS_OCCUPIED) || + (byMessageType == MTYPE_AUTONA && gnCurrentStatus != ID_STATUS_NA) || + (byMessageType == MTYPE_AUTODND && gnCurrentStatus != ID_STATUS_DND) || + (byMessageType == MTYPE_AUTOFFC && gnCurrentStatus != ID_STATUS_FREECHAT)) + { + return FALSE; + } + + if (hContact != INVALID_HANDLE_VALUE && gnCurrentStatus==ID_STATUS_INVISIBLE && + ICQGetContactSettingWord(hContact, "ApparentMode", 0) != ID_STATUS_ONLINE) + { + if (!ICQGetContactSettingByte(hContact, "TemporaryVisible", 0)) + { // Allow request to temporary visible contacts + return FALSE; + } + } + + // All OK! + return TRUE; +} + + + +void __fastcall SAFE_FREE(void** p) +{ + if (*p) + { + free(*p); + *p = NULL; + } +} + + + +void* __fastcall SAFE_MALLOC(size_t size) +{ + void* p = malloc(size); + + if (p) + ZeroMemory(p, size); + + return p; +} + + +static int bPhotoLock = 0; + +void LinkContactPhotoToFile(HANDLE hContact, char* szFile) +{ // set contact photo if linked if no photo set link + if (ICQGetContactSettingByte(NULL, "AvatarsAutoLink", DEFAULT_LINK_AVATARS)) + { + bPhotoLock = 1; + { + if (DBGetContactSettingByte(hContact, "ContactPhoto", "ICQLink", 0)) + { // we are linked update DB + if (szFile) + { + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); // delete that setting + DBDeleteContactSetting(hContact, "ContactPhoto", "Link"); + if (DBWriteContactSettingString(hContact, "ContactPhoto", "File", szFile)) + NetLog_Server("Avatar file could not be linked to ContactPhoto."); + } + else + { // no file, unlink + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + DBDeleteContactSetting(hContact, "ContactPhoto", "ICQLink"); + } + } + else if (szFile) + { // link only if file valid + DBVARIANT dbv; + if (DBGetContactSetting(hContact, "ContactPhoto", "File", &dbv)) + { + if (DBGetContactSetting(hContact, "ContactPhoto", "Link", &dbv)) + { // no photo defined + DBWriteContactSettingString(hContact, "ContactPhoto", "File", szFile); + DBWriteContactSettingByte(hContact, "ContactPhoto", "ICQLink", 1); + } + ICQFreeVariant(&dbv); + } + else + { // some file already defined, check if it is not the same, if yes, set link + if (!strcmpnull(dbv.pszVal, szFile)) + { + DBWriteContactSettingByte(hContact, "ContactPhoto", "ICQLink", 1); + } + ICQFreeVariant(&dbv); + } + } + } + bPhotoLock = 0; + } +} + + +static int bNoChanging = 0; + +void ContactPhotoSettingChanged(HANDLE hContact) +{ // the setting was changed - if it is done externaly unlink... + if (bNoChanging) return; + bNoChanging = 1; + + if (!bPhotoLock && ICQGetContactSettingByte(NULL, "AvatarsAutoLink", DEFAULT_LINK_AVATARS)) + DBDeleteContactSetting(hContact, "ContactPhoto", "ICQLink"); + + bNoChanging = 0; +} + + + +HANDLE NetLib_OpenConnection(HANDLE hUser, NETLIBOPENCONNECTION* nloc) +{ + HANDLE hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc); + if (!hConnection && (GetLastError() == 87)) + { // this ensures, an old Miranda will be able to connect also + nloc->cbSize = NETLIBOPENCONNECTION_V1_SIZE; + hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc); + } + return hConnection; +} + + + +int NetLog_Server(const char *fmt,...) +{ + va_list va; + char szText[1024]; + + va_start(va,fmt); + mir_vsnprintf(szText,sizeof(szText),fmt,va); + va_end(va); + return CallService(MS_NETLIB_LOG,(WPARAM)ghServerNetlibUser,(LPARAM)szText); +} + + + +int NetLog_Direct(const char *fmt,...) +{ + va_list va; + char szText[1024]; + + va_start(va,fmt); + mir_vsnprintf(szText,sizeof(szText),fmt,va); + va_end(va); + return CallService(MS_NETLIB_LOG,(WPARAM)ghDirectNetlibUser,(LPARAM)szText); +} + + + +int NetLog_Uni(BOOL bDC, const char *fmt,...) +{ + va_list va; + char szText[1024]; + HANDLE hNetlib; + + va_start(va,fmt); + mir_vsnprintf(szText,sizeof(szText),fmt,va); + va_end(va); + + if (bDC) + hNetlib = ghDirectNetlibUser; + else + hNetlib = ghServerNetlibUser; + + return CallService(MS_NETLIB_LOG,(WPARAM)hNetlib,(LPARAM)szText); +} + + + +int ICQBroadcastAck(HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam) +{ + ACKDATA ack={0}; + + ack.cbSize=sizeof(ACKDATA); + ack.szModule=gpszICQProtoName; + ack.hContact=hContact; + ack.type=type; + ack.result=result; + ack.hProcess=hProcess; + ack.lParam=lParam; + return CallService(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack); +} + + + +int __fastcall ICQTranslateDialog(HWND hwndDlg) +{ + LANGPACKTRANSLATEDIALOG lptd; + + lptd.cbSize=sizeof(lptd); + lptd.flags=0; + lptd.hwndDlg=hwndDlg; + lptd.ignoreControls=NULL; + return CallService(MS_LANGPACK_TRANSLATEDIALOG,0,(LPARAM)&lptd); +} + + + +char* __fastcall ICQTranslate(const char* src) +{ + return (char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)src); +} + + + +char* __fastcall ICQTranslateUtf(const char* src) +{ // this takes UTF-8 strings only!!! + char* szRes = NULL; + + if (!strlennull(src)) + { // for the case of empty strings + return null_strdup(src); + } + + if (gbUtfLangpack) + { // we can use unicode translate + wchar_t* usrc = make_unicode_string(src); + + szRes = make_utf8_string(TranslateW(usrc)); + + SAFE_FREE(&usrc); + } + else + { + int size = strlennull(src)+2; + char* asrc = (char*)_alloca(size); + + utf8_decode_static(src, asrc, size); + utf8_encode(Translate(asrc), &szRes); + } + return szRes; +} + + + +char* __fastcall ICQTranslateUtfStatic(const char* src, char* buf) +{ // this takes UTF-8 strings only!!! + char* t; + + if (strlennull(src)) + { + t = ICQTranslateUtf(src); + strcpy(buf, t); + SAFE_FREE(&t); + } + else + buf[0] = '\0'; + + return buf; +} + + + +char* GetUserPassword(BOOL bAlways) +{ + if (gpszPassword[0] != '\0' && (gbRememberPwd || bAlways)) + return gpszPassword; + + if (!ICQGetContactStaticString(NULL, "Password", gpszPassword, sizeof(gpszPassword))) + { + CallService(MS_DB_CRYPT_DECODESTRING, strlennull(gpszPassword) + 1, (LPARAM)gpszPassword); + + if (!strlennull(gpszPassword)) return NULL; + + gbRememberPwd = TRUE; + + return gpszPassword; + } + + return NULL; +} + + + +WORD GetMyStatusFlags() +{ + WORD wFlags = 0; + + // Webaware setting bit flag + if (ICQGetContactSettingByte(NULL, "WebAware", 0)) + wFlags = STATUS_WEBAWARE; + + // DC setting bit flag + switch (ICQGetContactSettingByte(NULL, "DCType", 0)) + { + case 0: + break; + + case 1: + wFlags = wFlags | STATUS_DCCONT; + break; + + case 2: + wFlags = wFlags | STATUS_DCAUTH; + break; + + default: + wFlags = wFlags | STATUS_DCDISABLED; + break; + } + return wFlags; +} + + + +wchar_t *GetWindowTextUcs(HWND hWnd) +{ + wchar_t *utext; + + if (gbUnicodeAPI) + { + int nLen = GetWindowTextLengthW(hWnd); + + utext = (wchar_t*)SAFE_MALLOC((nLen+2)*sizeof(wchar_t)); + GetWindowTextW(hWnd, utext, nLen + 1); + } + else + { + char *text; + int wchars, nLen = GetWindowTextLengthA(hWnd); + + text = (char*)_alloca(nLen+2); + GetWindowTextA(hWnd, text, nLen + 1); + + wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text, + strlennull(text), NULL, 0); + + utext = (wchar_t*)SAFE_MALLOC((wchars + 1)*sizeof(unsigned short)); + + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text, + strlennull(text), utext, wchars); + } + return utext; +} + + + +void SetWindowTextUcs(HWND hWnd, wchar_t *text) +{ + if (gbUnicodeAPI) + { + SetWindowTextW(hWnd, text); + } + else + { + char *tmp = (char*)SAFE_MALLOC(wcslen(text) + 1); + + WideCharToMultiByte(CP_ACP, 0, text, -1, tmp, wcslen(text)+1, NULL, NULL); + SetWindowTextA(hWnd, tmp); + SAFE_FREE(&tmp); + } +} + + + +char* GetWindowTextUtf(HWND hWnd) +{ + if (gbUnicodeAPI) + { + wchar_t* usText; + int nLen = GetWindowTextLengthW(hWnd); + + usText = (wchar_t*)_alloca((nLen+2)*sizeof(wchar_t)); + GetWindowTextW(hWnd, usText, nLen + 1); + return make_utf8_string(usText); + } + else + { + char* szAnsi; + int nLen = GetWindowTextLengthA(hWnd); + + szAnsi = (char*)_alloca(nLen+2); + GetWindowTextA(hWnd, szAnsi, nLen + 1); + return ansi_to_utf8(szAnsi); + } +} + + + +char* GetDlgItemTextUtf(HWND hwndDlg, int iItem) +{ + return GetWindowTextUtf(GetDlgItem(hwndDlg, iItem)); +} + + + +void SetWindowTextUtf(HWND hWnd, const char* szText) +{ + if (gbUnicodeAPI) + { + wchar_t* usText = make_unicode_string(szText); + + SetWindowTextW(hWnd, usText); + SAFE_FREE(&usText); + } + else + { + int size = strlennull(szText)+2; + char* szAnsi = (char*)_alloca(size); + + if (utf8_decode_static(szText, szAnsi, size)) + SetWindowTextA(hWnd, szAnsi); + } +} + + + +void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char* szText) +{ + SetWindowTextUtf(GetDlgItem(hwndDlg, iItem), szText); +} + + + +LONG SetWindowLongUtf(HWND hWnd, int nIndex, LONG dwNewLong) +{ + if (gbUnicodeAPI) + return SetWindowLongW(hWnd, nIndex, dwNewLong); + else + return SetWindowLongA(hWnd, nIndex, dwNewLong); +} + + + +LRESULT CallWindowProcUtf(WNDPROC OldProc, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (gbUnicodeAPI) + return CallWindowProcW(OldProc,hWnd,msg,wParam,lParam); + else + return CallWindowProcA(OldProc,hWnd,msg,wParam,lParam); +} + + + +static int ControlAddStringUtf(HWND ctrl, DWORD msg, const char* szString) +{ + char str[MAX_PATH]; + char *szItem = ICQTranslateUtfStatic(szString, str); + int item; + + if (gbUnicodeAPI) + { + wchar_t *wItem = make_unicode_string(szItem); + + item = SendMessageW(ctrl, msg, 0, (LPARAM)wItem); + SAFE_FREE(&wItem); + } + else + { + int size = strlennull(szItem) + 2; + char *aItem = (char*)_alloca(size); + + utf8_decode_static(szItem, aItem, size); + item = SendMessageA(ctrl, msg, 0, (LPARAM)aItem); + } + return item; +} + + + +int ComboBoxAddStringUtf(HWND hCombo, const char* szString, DWORD data) +{ + int item = ControlAddStringUtf(hCombo, CB_ADDSTRING, szString); + SendMessage(hCombo, CB_SETITEMDATA, item, data); + + return item; +} + + + +int ListBoxAddStringUtf(HWND hList, const char* szString) +{ + return ControlAddStringUtf(hList, LB_ADDSTRING, szString); +} + + + +HWND DialogBoxUtf(BOOL bModal, HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +{ // Unicode pump ready dialog box + if (gbUnicodeAPI) + { + if (bModal) + return (HANDLE)DialogBoxParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam); + else + return CreateDialogParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam); + } + else + { + if (bModal) + return (HANDLE)DialogBoxParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam); + else + return CreateDialogParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam); + } +} + + + +HWND CreateDialogUtf(HINSTANCE hInstance, const char* lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc) +{ + if (gbUnicodeAPI) + return CreateDialogW(hInstance, (LPCWSTR)lpTemplate, hWndParent, lpDialogFunc); + else + return CreateDialogA(hInstance, lpTemplate, hWndParent, lpDialogFunc); +} + + + +int MessageBoxUtf(HWND hWnd, const char* szText, const char* szCaption, UINT uType) +{ + int res; + char str[1024]; + char cap[MAX_PATH]; + + if (gbUnicodeAPI) + { + wchar_t *text = make_unicode_string(ICQTranslateUtfStatic(szText, str)); + wchar_t *caption = make_unicode_string(ICQTranslateUtfStatic(szCaption, cap)); + res = MessageBoxW(hWnd, text, caption, uType); + SAFE_FREE(&caption); + SAFE_FREE(&text); + } + else + { + int size = strlennull(szText) + 2, size2 = strlennull(szCaption) + 2; + char *text = (char*)_alloca(size); + char *caption = (char*)_alloca(size2); + + utf8_decode_static(ICQTranslateUtfStatic(szText, str), text, size); + utf8_decode_static(ICQTranslateUtfStatic(szCaption, cap), caption, size2); + res = MessageBoxA(hWnd, text, caption, uType); + } + return res; +} + + +int CacheIDCount(void) +{ + + return cacheCount; + +} + +int IDFromCacheByUin(DWORD dwUin) +{ + + int i = -1; + + if (cacheCount == 0) + return i; + + EnterCriticalSection(&cacheMutex); + + for (i = cacheCount-1; i >= 0; i--) + if (contacts_cache[i].dwUin == dwUin) + break; + + LeaveCriticalSection(&cacheMutex); + + return i; + +} + +int SetCacheFlagsByID(int ID, DWORD flags) +{ + + if (ID < 0 || ID >= cacheCount) + return 0; + + contacts_cache[ID].flags = flags; + + return 1; + +} + +int GetCacheByID(int ID, icq_contacts_cache *icc) +{ + + if (!icc || ID < 0 || ID >= cacheCount) + return 0; + + EnterCriticalSection(&cacheMutex); + + icc->hContact = contacts_cache[ID].hContact; + icc->dwUin = contacts_cache[ID].dwUin; + icc->flags = contacts_cache[ID].flags; + + LeaveCriticalSection(&cacheMutex); + + return icc->dwUin; // to be sure it is not 0 + +} \ No newline at end of file -- cgit v1.2.3