diff options
author | watcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb> | 2011-04-21 14:14:52 +0000 |
---|---|---|
committer | watcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb> | 2011-04-21 14:14:52 +0000 |
commit | cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c (patch) | |
tree | 30df260fdc5a1b5a7049c2f8cac8b7ef17513d6d /icqj_s7_sss_mod/utilities.c | |
parent | 19b6f534d2e784a1e120bf52c4aa07004798f473 (diff) |
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
Diffstat (limited to 'icqj_s7_sss_mod/utilities.c')
-rw-r--r-- | icqj_s7_sss_mod/utilities.c | 2909 |
1 files changed, 2909 insertions, 0 deletions
diff --git a/icqj_s7_sss_mod/utilities.c b/icqj_s7_sss_mod/utilities.c new file mode 100644 index 0000000..c6cd863 --- /dev/null +++ b/icqj_s7_sss_mod/utilities.c @@ -0,0 +1,2909 @@ +// ---------------------------------------------------------------------------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,2007 Joe Kucera
+// Copyright © 2006,2007,2008 [sss], chaos.persei, [sin], Faith Healer, Thief, Angeli-Ka, nullbie
+// Copyright © 2008 [sss], chaos.persei, nullbie, baloo, jarvis
+//
+// 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 : $HeadURL: https://icqjplusmod.googlecode.com/svn/trunk/utilities.c $
+// Revision : $Revision: 51 $
+// Last change on : $Date: 2007-08-30 23:46:51 +0300 (Чт, 30 авг 2007) $
+// Last change by : $Author: sss123next $
+//
+// 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 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)
+{ // return miranda status description in utf-8, use unicode service is possible
+ return mtchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, gbUnicodeCore ? GCMDF_UNICODE : 0));
+}
+
+
+
+char**MirandaStatusToAwayMsg(int nStatus)
+{
+ switch (nStatus)
+ {
+
+ case ID_STATUS_ONLINE:
+ return &modeMsgs.szOnline;
+ break;
+
+ 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_AUTOONLINE:
+ return ID_STATUS_ONLINE;
+
+ 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 *)SAFE_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*)SAFE_REALLOC(gateways, sizeof(gateway_index) * gatewayCount);
+
+ // Gateway found, exit loop
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&cookieMutex);
+}
+
+
+
+void AddToSpammerList(DWORD dwUIN)
+{
+ EnterCriticalSection(&cookieMutex);
+
+ spammerList = (DWORD *)SAFE_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 *)SAFE_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);
+ }
+ if (ICQGetContactSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED))
+ icq_sendGetLocationInfo(hContact, uin, NULL);
+ }
+ 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);
+ }
+ if (ICQGetContactSettingByte(NULL, "KillSpambots", DEFAULT_KILLSPAM_ENABLED))
+ icq_sendGetLocationInfo(hContact, 0, pszUID);
+ }
+ *Added = 1;
+
+ return hContact;
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+
+char *NickFromHandle(HANDLE hContact)
+{
+ if (hContact == INVALID_HANDLE_VALUE)
+ return null_strdup(ICQTranslate("<invalid>"));
+
+ 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, "<invalid>", wLen);
+ else
+ lstrcpyn(szNick, (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0), wLen);
+
+}
+
+
+char *NickFromHandleUtf(HANDLE hContact)
+{
+ if (hContact == INVALID_HANDLE_VALUE)
+ return ICQTranslateUtf("<invalid>");
+
+ return mtchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, gbUnicodeCore ? GCDNF_UNICODE : 0));
+}
+
+
+
+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;
+}
+
+
+
+size_t __fastcall null_strcut(char *string, size_t maxlen)
+{ // limit the string to max length (null & utf-8 strings ready)
+ size_t len = strlennull(string);
+
+ if (len < maxlen)
+ return len;
+
+ len = maxlen;
+
+ if (UTF8_IsValid(string)) // handle utf-8 string
+ { // find the first byte of possible multi-byte character
+ while ((string[len] & 0xc0) == 0x80) len--;
+ }
+ // simply cut the string
+ string[len] = '\0';
+
+ return len;
+}
+
+
+
+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]);
+ } // otherwise do not change port
+
+ 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<len; i++)
+ {
+ if (!strnicmp(string+i, ">", 4))
+ {
+ *szChar = '>';
+ szChar++;
+ i += 3;
+ }
+ else if (!strnicmp(string+i, "<", 4))
+ {
+ *szChar = '<';
+ szChar++;
+ i += 3;
+ }
+ else if (!strnicmp(string+i, "&", 5))
+ {
+ *szChar = '&';
+ szChar++;
+ i += 4;
+ }
+ else if (!strnicmp(string+i, """, 6))
+ {
+ *szChar = '"';
+ szChar++;
+ i += 5;
+ }
+ else
+ {
+ *szChar = string[i];
+ szChar++;
+ }
+ }
+ *szChar = '\0';
+
+ return szWork;
+}
+
+
+
+char *MangleXml(const char *string, int len)
+{
+ int i, l = 1;
+ char *szWork, *szChar;
+
+ for (i = 0; i<len; i++)
+ {
+ if (string[i]=='<' || string[i]=='>') l += 4; else if (string[i]=='&') l += 5; else l++;
+ }
+ szChar = szWork = (char*)SAFE_MALLOC(l + 1);
+ for (i = 0; i<len; i++)
+ {
+ if (string[i]=='<')
+ {
+ *(DWORD*)szChar = ';tl&';
+ szChar += 4;
+ }
+ else if (string[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<len;i++)
+ {
+ if (!tag && string[i] == '<')
+ {
+ if ((i + 4 <= len) && (!strnicmp(string + i, "<br>", 4) || !strnicmp(string + i, "<br/>", 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);
+}
+
+char* ApplyEncoding(const char *string, const char* pszEncoding)
+{ // decode encoding to Utf-8
+ if (string && pszEncoding)
+ { // we do only encodings known to icq5.1 // TODO: check if this is enough
+ if (!strnicmp(pszEncoding, "utf-8", 5))
+ { // it is utf-8 encoded
+ return null_strdup(string);
+ }
+ else if (!strnicmp(pszEncoding, "unicode-2-0", 11))
+ { // it is UCS-2 encoded
+ int wLen = wcslen((WCHAR*)string) + 1;
+ WCHAR *szStr = (WCHAR*)_alloca(wLen*2);
+ char *tmp = (char*)string;
+
+ unpackWideString(&tmp, szStr, (WORD)(wLen*2));
+
+ return make_utf8_string(szStr);
+ }
+ else if (!strnicmp(pszEncoding, "iso-8859-1", 10))
+ { // we use "Latin I" instead - it does the job
+ return ansi_to_utf8_codepage(string, 1252);
+ }
+ }
+ if (string)
+ { // consider it CP_ACP
+ return ansi_to_utf8(string);
+ }
+
+ return NULL;
+}
+
+
+
+void ResetSettingsOnListReload()
+{
+ HANDLE hContact;
+
+ // Reset a bunch of session specific settings
+ ICQWriteContactSettingWord(NULL, "SrvVisibilityID", 0);
+ ICQWriteContactSettingWord(NULL, "SrvAvatarID", 0);
+ ICQWriteContactSettingWord(NULL, "SrvPhotoID", 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;
+
+ // 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);
+ ICQWriteContactSettingByte(hContact, "TemporaryVisible", 0);
+
+ // 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);
+ }
+ ICQWriteContactSettingByte(hContact, "DCStatus", 0);
+
+ 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<nLen; i++)
+ {
+ if ((pszString[i] < '0') || (pszString[i] > '9'))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+static DWORD __stdcall 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 0;
+}
+
+
+
+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);
+
+ ICQCreateThread(icq_ProtocolAckThread, 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, MAX_PATH);
+ 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, MAX_PATH);
+ 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)
+{
+ DWORD uin = DBGetContactSettingDword(hContact,gpszICQProtoName,"UIN",0);
+ // 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;
+ }
+ }
+
+ //Don't send any status message reply, if on
+ if(bNoStatusReply)
+ return FALSE;
+
+ // Dont send messages to people you are hiding from
+ if (hContact != INVALID_HANDLE_VALUE &&
+ ICQGetContactSettingWord(hContact, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ {
+ CHECKCONTACT chk = {0};
+ chk.hContact = hContact;
+ chk.dbeventflag=DBEF_READ;
+ chk.popup=chk.logtofile=chk.historyevent=TRUE;
+ chk.popuptype=POPTYPE_VIS;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.dwUin = uin;
+ chk.msg = "contact which you are invisible for requests your status message";
+ CheckContact(chk);
+ 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))
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin=uin;
+ chk.hContact=hContact;
+ chk.dbeventflag=DBEF_READ;
+ chk.popup=chk.logtofile=chk.historyevent=TRUE;
+ chk.icqeventtype=ICQEVENTTYPE_CHECK_STATUS;
+ chk.popuptype=POPTYPE_INFO_REQUEST;
+ chk.msg="requested wrong status type";
+ CheckContact(chk);
+ return FALSE;
+ }
+
+ if (hContact != INVALID_HANDLE_VALUE && gnCurrentStatus==ID_STATUS_INVISIBLE)
+ {
+ if (!ICQGetContactSettingByte(hContact, "TemporaryVisible", 0))
+ { // Allow request to temporary visible contacts
+ return FALSE;
+ }
+ }
+
+ {
+ CHECKCONTACT chk = {0};
+ chk.dwUin = uin;
+ chk.hContact=hContact;
+ chk.PSD = -1;
+ CheckContact(chk);
+ }
+ // 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 = NULL;
+
+ if (size)
+ {
+ p = malloc(size);
+
+ if (p)
+ ZeroMemory(p, size);
+ }
+ return p;
+}
+
+
+
+void* __fastcall SAFE_REALLOC(void* p, size_t size)
+{
+ if (p)
+ {
+ return realloc(p, size);
+ }
+ else
+ return SAFE_MALLOC(size);
+}
+
+
+
+HANDLE NetLib_OpenConnection(HANDLE hUser, const char* szIdent, NETLIBOPENCONNECTION* nloc)
+{
+ HANDLE hConnection;
+
+ Netlib_Logf(hUser, "%sConnecting to %s:%u", szIdent?szIdent:"", nloc->szHost, nloc->wPort);
+
+ nloc->cbSize = sizeof(NETLIBOPENCONNECTION);
+ nloc->flags |= NLOCF_V2;
+
+ 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;
+}
+
+
+
+HANDLE NetLib_BindPort(NETLIBNEWCONNECTIONPROC_V2 pFunc, void* lParam, WORD* pwPort, DWORD* pdwIntIP)
+{
+ NETLIBBIND nlb = {0};
+ HANDLE hBoundPort;
+
+ nlb.cbSize = sizeof(NETLIBBIND);
+ nlb.pfnNewConnectionV2 = pFunc;
+ nlb.pExtra = lParam;
+ SetLastError(ERROR_INVALID_PARAMETER); // this must be here - NetLib does not set any error :((
+ hBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)ghDirectNetlibUser, (LPARAM)&nlb);
+ if (!hBoundPort && (GetLastError() == ERROR_INVALID_PARAMETER))
+ { // this ensures older Miranda also can bind a port for a dc - pre 0.6
+ nlb.cbSize = NETLIBBIND_SIZEOF_V2;
+ hBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)ghDirectNetlibUser, (LPARAM)&nlb);
+ }
+ if (pwPort) *pwPort = nlb.wPort;
+ if (pdwIntIP) *pdwIntIP = nlb.dwInternalIP;
+
+ return hBoundPort;
+}
+
+
+
+void NetLib_CloseConnection(HANDLE *hConnection, int bServerConn)
+{
+ if (*hConnection)
+ {
+ int sck = CallService(MS_NETLIB_GETSOCKET, (WPARAM)*hConnection, (LPARAM)0);
+
+ if (sck!=INVALID_SOCKET) shutdown(sck, 2); // close gracefully
+
+ NetLib_SafeCloseHandle(hConnection);
+
+ if (bServerConn)
+ FreeGatewayIndex(*hConnection);
+ }
+}
+
+
+
+void NetLib_SafeCloseHandle(HANDLE *hConnection)
+{
+ if (*hConnection)
+ {
+ Netlib_CloseHandle(*hConnection);
+ *hConnection = NULL;
+ }
+}
+
+
+
+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);
+ }
+
+ { // we can use unicode translate (0.5+)
+ WCHAR* usrc = make_unicode_string(src);
+
+ szRes = make_utf8_string(TranslateW(usrc));
+
+ SAFE_FREE(&usrc);
+ }
+ return szRes;
+}
+
+
+
+char* __fastcall ICQTranslateUtfStatic(const char* src, char* buf, size_t bufsize)
+{ // this takes UTF-8 strings only!!!
+ if (strlennull(src))
+ { // we can use unicode translate (0.5+)
+ WCHAR* usrc = make_unicode_string(src);
+
+ make_utf8_string_static(TranslateW(usrc), buf, bufsize);
+
+ SAFE_FREE(&usrc);
+ }
+ else
+ buf[0] = '\0';
+
+ return buf;
+}
+
+
+
+HANDLE ICQCreateThreadEx(pThreadFuncEx AFunc, void* arg, DWORD* pThreadID)
+{
+ FORK_THREADEX_PARAMS params;
+ DWORD dwThreadId;
+ HANDLE hThread;
+
+ params.pFunc = AFunc;
+ params.arg = arg;
+ params.iStackSize = 0;
+ params.threadID = &dwThreadId;
+ hThread = (HANDLE)CallService(MS_SYSTEM_FORK_THREAD_EX, 0, (LPARAM)¶ms);
+ if (pThreadID)
+ *pThreadID = dwThreadId;
+
+ return hThread;
+}
+
+
+
+void ICQCreateThread(pThreadFuncEx AFunc, void* arg)
+{
+ HANDLE hThread = ICQCreateThreadEx(AFunc, arg, NULL);
+
+ CloseHandle(hThread);
+}
+
+
+
+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;
+}
+
+
+
+int IsValidRelativePath(const char *filename)
+{
+ if (strstr(filename, "..\\") || strstr(filename, "../") ||
+ strstr(filename, ":\\") || strstr(filename, ":/") ||
+ filename[0] == '\\' || filename[0] == '/')
+ return 0; // Contains malicious chars, Failure
+
+ return 1; // Success
+}
+
+
+
+char* ExtractFileName(const char *fullname)
+{
+ char* szFileName;
+
+ if (((szFileName = strrchr(fullname, '\\')) == NULL) && ((szFileName = strrchr(fullname, '/')) == NULL))
+ { // already is only filename
+ return (char*)fullname;
+ }
+ szFileName++; // skip backslash
+
+ return szFileName;
+}
+
+
+
+char* FileNameToUtf(const char *filename)
+{
+ if (gbUnicodeAPI)
+ { // reasonable only on NT systems
+ HINSTANCE hKernel;
+ DWORD (CALLBACK *RealGetLongPathName)(LPCWSTR, LPWSTR, DWORD);
+
+ hKernel = GetModuleHandle("KERNEL32");
+ *(FARPROC *)&RealGetLongPathName = GetProcAddress(hKernel, "GetLongPathNameW");
+
+ if (RealGetLongPathName)
+ { // the function is available (it is not on old NT systems)
+ WCHAR *unicode, *usFileName = NULL;
+ int wchars;
+
+ wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename,
+ strlennull(filename), NULL, 0);
+
+ unicode = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ unicode[wchars] = 0;
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename,
+ strlennull(filename), unicode, wchars);
+
+ wchars = RealGetLongPathName(unicode, usFileName, 0);
+ usFileName = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
+ RealGetLongPathName(unicode, usFileName, wchars);
+
+ return make_utf8_string(usFileName);
+ }
+ else
+ return ansi_to_utf8(filename);
+ }
+ else
+ return ansi_to_utf8(filename);
+}
+
+
+
+int FileStatUtf(const char *path, struct _stati64 *buffer)
+{
+ int wRes = -1;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR* usPath = make_unicode_string(path);
+
+ wRes = _wstati64(usPath, buffer);
+ SAFE_FREE(&usPath);
+ }
+ else
+ {
+ int size = strlennull(path)+2;
+ char* szAnsiPath = (char*)_alloca(size);
+
+ if (utf8_decode_static(path, szAnsiPath, size))
+ wRes = _stati64(szAnsiPath, buffer);
+ }
+ return wRes;
+}
+
+
+
+int MakeDirUtf(const char *dir)
+{
+ int wRes = -1;
+ char *szLast;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR* usDir = make_unicode_string(dir);
+ // _wmkdir can created only one dir at once
+ wRes = _wmkdir(usDir);
+ // check if dir not already existed - return success if yes
+ if (wRes == -1 && errno == 17 /* EEXIST */)
+ wRes = 0;
+ else if (wRes && errno == 2 /* ENOENT */)
+ { // failed, try one directory less first
+ szLast = strrchr(dir, '\\');
+ if (!szLast) szLast = strrchr(dir, '/');
+ if (szLast)
+ {
+ char cOld = *szLast;
+
+ *szLast = '\0';
+ if (!MakeDirUtf(dir))
+ wRes = _wmkdir(usDir);
+ *szLast = cOld;
+ }
+ }
+ SAFE_FREE(&usDir);
+ }
+ else
+ {
+ int size = strlennull(dir)+2;
+ char* szAnsiDir = (char*)_alloca(size);
+
+ if (utf8_decode_static(dir, szAnsiDir, size))
+ { // _mkdir can create only one dir at once
+ wRes = _mkdir(szAnsiDir);
+ // check if dir not already existed - return success if yes
+ if (wRes == -1 && errno == 17 /* EEXIST */)
+ wRes = 0;
+ else if (wRes && errno == 2 /* ENOENT */)
+ { // failed, try one directory less first
+ szLast = strrchr(dir, '\\');
+ if (!szLast) szLast = strrchr(dir, '/');
+ if (szLast)
+ {
+ char cOld = *szLast;
+
+ *szLast = '\0';
+ if (!MakeDirUtf(dir))
+ wRes = _mkdir(szAnsiDir);
+ *szLast = cOld;
+ }
+ }
+ }
+ }
+ return wRes;
+}
+
+
+
+int OpenFileUtf(const char *filename, int oflag, int pmode)
+{
+ int hFile = -1;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR* usFile = make_unicode_string(filename);
+
+ hFile = _wopen(usFile, oflag, pmode);
+ SAFE_FREE(&usFile);
+ }
+ else
+ {
+ int size = strlennull(filename)+2;
+ char* szAnsiFile = (char*)_alloca(size);
+
+ if (utf8_decode_static(filename, szAnsiFile, size))
+ hFile = _open(szAnsiFile, oflag, pmode);
+ }
+ return hFile;
+}
+
+
+
+WCHAR *GetWindowTextUcs(HWND hWnd)
+{
+ WCHAR *utext;
+
+ if (gbUnicodeAPI)
+ {
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ utext = (WCHAR*)SAFE_MALLOC((nLen+2)*sizeof(WCHAR));
+ 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*)SAFE_MALLOC((wchars + 1)*sizeof(WCHAR));
+
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text,
+ strlennull(text), utext, wchars);
+ }
+ return utext;
+}
+
+
+
+void SetWindowTextUcs(HWND hWnd, WCHAR *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)
+{
+ TCHAR* szText;
+
+ if (gbUnicodeAPI)
+ {
+ int nLen = GetWindowTextLengthW(hWnd);
+
+ szText = (TCHAR*)_alloca((nLen+2)*sizeof(WCHAR));
+ GetWindowTextW(hWnd, (WCHAR*)szText, nLen + 1);
+ }
+ else
+ {
+ int nLen = GetWindowTextLengthA(hWnd);
+
+ szText = (TCHAR*)_alloca(nLen+2);
+ GetWindowTextA(hWnd, (char*)szText, nLen + 1);
+ }
+ return tchar_to_utf8(szText);
+}
+
+
+
+char* GetDlgItemTextUtf(HWND hwndDlg, int iItem)
+{
+ return GetWindowTextUtf(GetDlgItem(hwndDlg, iItem));
+}
+
+
+
+void SetWindowTextUtf(HWND hWnd, const char* szText)
+{
+ if (gbUnicodeAPI)
+ {
+ WCHAR* 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, MAX_PATH);
+ int item = -1;
+
+ if (gbUnicodeAPI)
+ {
+ WCHAR *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);
+
+ if (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 *text = make_unicode_string(ICQTranslateUtfStatic(szText, str, 1024));
+ WCHAR *caption = make_unicode_string(ICQTranslateUtfStatic(szCaption, cap, MAX_PATH));
+ 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, 1024), text, size);
+ utf8_decode_static(ICQTranslateUtfStatic(szCaption, cap, MAX_PATH), 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
+
+}
+
+/*BOOL invis_for(DWORD dwUin, HANDLE hContact) //this function checking are you invisible for hContact or dwUin, need optimization...
+{
+ WORD wApparent = DBGetContactSettingWord(hContact,gpszICQProtoName,"ApparentMode",0);
+
+ if(bVisibility==0x02)
+ return TRUE;
+ if (dwUin && !hContact)
+ hContact=HContactFromUIN(dwUin,0);
+ if (!hContact)
+ {
+ return TRUE;
+ }
+ if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)&&bVisibility!=0x01||bVisibility!=0x04)
+ return TRUE;
+ if((wApparent==ID_STATUS_OFFLINE||gnCurrentStatus == ID_STATUS_INVISIBLE&&bVisibility!=0x04&&wApparent!=ID_STATUS_ONLINE)&&bVisibility!=0x01)
+ return TRUE;
+ return FALSE;
+} */
+
+
+
+BOOL invis_for(DWORD dwUin, HANDLE hContact) //this function checking are you invisible for hContact or dwUin, need optimization... (modified by Bio)
+{
+ WORD wApparent;
+
+ // Block all users from seeing you
+// if ( bVisibility==0x02 || !dwUin )
+ if ( bVisibility==0x02) //we support AIM which do not use UIN's
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+
+ // Allow all users to see you
+ if ( bVisibility == 0x01 )
+ return FALSE;
+
+ if ( !hContact ) {
+ hContact=HContactFromUIN(dwUin,0);
+ if (!hContact)
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ }
+
+ if ( DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) )
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+
+ // Allow only users in the buddy list to see you
+ if ( bVisibility == 0x05 ) {
+ if ( DBGetContactSettingByte(hContact, "CList", "Hidden", 0) )
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ wApparent = DBGetContactSettingWord(hContact,gpszICQProtoName,"ApparentMode",0);
+
+ // Allow only users in the permit list to see you
+ if ( bVisibility == 0x03 ) {
+ if ( wApparent == ID_STATUS_ONLINE )
+ return FALSE;
+ else
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ }
+
+ // Block only users in the invisible list from seeing you
+ if ( bVisibility == 0x04 ) {
+ if ( wApparent == ID_STATUS_OFFLINE )
+ {
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ // invisible by default
+ NetLog_Server("we invisible for %u, blocking all unsafe requests", dwUin);
+ return TRUE;
+}
+
+void CheckContact(CHECKCONTACT chk) //dwUin necessary, function for show popups, write events, log to file, call PSD, parsing temporary contacts, NEED TO BE FINISHED
+{
+ BYTE Hidden = DBGetContactSettingByte(chk.hContact, "CList", "Hidden", 0);
+ BYTE InDb = CallService(MS_DB_CONTACT_IS, (WPARAM)chk.hContact, 0);
+ BYTE NotOnList = DBGetContactSettingByte(chk.hContact,"CList","NotOnList",0);
+ BOOL Cancel = FALSE;
+ BOOL showpopup = TRUE;
+ char popmsg[512] = {0}, eventmsghistory[512] = {0}, eventmsgfile[512] = {0};
+ if(!InDb||NotOnList||Hidden)
+ {
+ if(!bPopUpForNotOnList)
+ showpopup = FALSE;
+ if(bNoPSDForHidden)
+ Cancel = TRUE;
+ }
+ if(!chk.popuptype) //
+ chk.popup=FALSE; //
+ if(!chk.icqeventtype) //
+ { //wrong call check ... (missing event types)
+ chk.historyevent=FALSE; //
+ chk.logtofile=FALSE; //
+ } //
+ if(chk.dwUin)
+ {
+ if (bTmpContacts == 1)
+ {
+ int added;
+ chk.hContact = HContactFromUIN(chk.dwUin, &added);
+ if(NotOnList)
+ {
+ {
+ DBCONTACTWRITESETTING dbcws;
+ dbcws.value.type = DBVT_UTF8;
+ dbcws.value.pszVal = TmpGroupName;
+ dbcws.szModule = "CList";
+ dbcws.szSetting = "Group";
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)chk.hContact, (LPARAM)&dbcws);
+ }
+ DBWriteContactSettingByte(chk.hContact,"CList","Hidden",0);
+ DBWriteContactSettingByte(chk.hContact,"CList","NotOnList",bAddTemp);
+ DBWriteContactSettingByte(chk.hContact, gpszICQProtoName, "CheckSelfRemove", 1);//excluding from checkselfremove
+ // DBWriteContactSettingByte(hContact, gpszICQProtoName, "FoundedContact", 1); //mark founded contacts
+ }
+ }
+ if(InDb)
+ {
+ if(chk.msg)
+ {
+ if(strlen(chk.msg) > 1 && showpopup)
+ {
+ popmsg[0] = '\0';
+ switch(chk.popuptype)
+ {
+ case POPTYPE_SPAM:
+ //nothing here, used direct ShowPopupMsg call
+ break;
+ case POPTYPE_UNKNOWN:
+ //nothing here, used direct ShowPopupMsg call
+ break;
+ case POPTYPE_VIS:
+ if(bVisPopUp)
+ {
+ strcpy(popmsg,"... is checking your real status ");
+ }
+ break;
+ case LOG_NOTE:
+ case LOG_WARNING:
+ case LOG_ERROR:
+ case LOG_FATAL:
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_FOUND:
+ if(bFoundPopUp)
+ {
+ strcpy(popmsg,chk.msg);
+ }
+ break;
+ case POPTYPE_SCAN:
+ if(bScanPopUp)
+ {
+ strcpy(popmsg,chk.msg);
+ }
+ break;
+ case POPTYPE_CLIENT_CHANGE:
+ if(bClientChangePopUp)
+ {
+ strcpy(popmsg,chk.msg);
+ }
+ break;
+ case POPTYPE_INFO_REQUEST:
+ if(bInfoRequestPopUp)
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_IGNORE_CHECK:
+ if(bIgnoreCheckPop)
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_SELFREMOVE:
+ if(bPopSelfRem)
+ strcpy(popmsg,chk.msg);
+ break;
+ case POPTYPE_AUTH:
+ if(bAuthPopUp)
+ strcpy(popmsg,chk.msg);
+ break;
+ default:
+ break;
+ }
+ if(chk.historyevent||chk.logtofile)
+ {
+ switch(chk.icqeventtype)
+ {
+ case ICQEVENTTYPE_AUTH_DENIED:
+ if(bLogAuthHistory)
+ strcpy(eventmsghistory,"was denied your authorization request");
+ if(bLogAuthFile)
+ strcpy(eventmsgfile,"was denied your authorization request");
+ break;
+ case ICQEVENTTYPE_AUTH_GRANTED:
+ if(bLogAuthHistory)
+ strcpy(eventmsghistory,"Authorization request granted");
+ if(bLogAuthFile)
+ strcpy(eventmsgfile,"Authorization request granted");
+ break;
+ case ICQEVENTTYPE_CHECK_STATUS:
+ if(bLogStatusCheckHistory)
+ strcpy(eventmsghistory,"check your status ");
+ if(bLogStatusCheckFile)
+ strcpy(eventmsgfile,"check your status ");
+ break;
+ case ICQEVENTTYPE_WAS_FOUND:
+ if(bLogASDHistory)
+ strcpy(eventmsghistory,"");
+ if(bLogASDFile)
+ strcpy(eventmsgfile,"");
+ break;
+ case ICQEVENTTYPE_CLIENT_CHANGE:
+ if(bLogIgnoreCheckHistory)
+ strcpy(eventmsghistory,chk.msg);
+ if(bLogIgnoreCheckFile)
+ strcpy(eventmsgfile,chk.msg);
+ break;
+ case ICQEVENTTYPE_EMAILEXPRESS:
+ //nothing to do here at this time ...
+ break;
+ case ICQEVENTTYPE_FUTURE_AUTH:
+ //i do not know what can i do here, fix me....
+ break;
+ case ICQEVENTTYPE_IGNORECHECK_STATUS:
+ if(bLogIgnoreCheckHistory)
+ strcpy(eventmsghistory,"check your ignore list");
+ if(bLogIgnoreCheckFile)
+ strcpy(eventmsgfile,"check your ignore list");
+ break;
+ case ICQEVENTTYPE_SELF_REMOVE:
+ if(bLogSelfRemoveHistory)
+ strcpy(eventmsghistory,"removed himself from your Serverlist!");
+ if(bLogSelfRemoveFile)
+ strcpy(eventmsgfile,"removed himself from your Serverlist!");
+ break;
+ case ICQEVENTTYPE_SMS:
+ //nothing to do here at this time ...
+ break;
+ case ICQEVENTTYPE_WEBPAGER:
+ //nothing to do here at this time ...
+ break;
+ case ICQEVENTTYPE_YOU_ADDED:
+ break;
+ case ICQEVENTTYPE_AUTH_REQUESTED:
+ break;
+ default:
+ break;
+ }
+ if(popmsg && strlen(popmsg) > 1)
+ {
+ if(!strstr(chk.msg,popmsg))
+ strcat(popmsg, chk.msg);
+ ShowPopUpMsg(chk.hContact, chk.dwUin, NickFromHandleUtf(chk.hContact), popmsg, chk.popuptype);
+ }
+ if(eventmsghistory && strlen(eventmsghistory) > 1)
+ {
+ if(!strstr(chk.msg,eventmsghistory))
+ strcat(eventmsghistory, chk.msg);
+ HistoryLog(chk.hContact, chk.dwUin, eventmsghistory, chk.icqeventtype, chk.dbeventflag);
+ }
+ if(eventmsgfile && strlen(eventmsgfile) > 1)
+ {
+ if(!strstr(chk.msg,eventmsgfile))
+ strcat(eventmsgfile, chk.msg);
+ LogToFile(chk.hContact, chk.dwUin, eventmsgfile, chk.icqeventtype);
+ }
+ }
+ }
+ }
+ if(chk.PSD != -1 && !Cancel)
+ {
+ if(!chk.PSD)
+ chk.PSD=21;
+ if(gbASD&&chk.PSD<10)
+ icq_SetUserStatus(chk.dwUin, 0, chk.PSD, 0);
+ else if(ICQGetContactSettingWord(chk.hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE && (bPSD&&chk.PSD>20)) //check for wrong PSD call
+ icq_SetUserStatus(chk.dwUin, 0, chk.PSD, 0);
+ }
+ }
+ }
+}
+int IncognitoAwayRequest(WPARAM wParam, LPARAM lParam)
+{
+ bIncognitoRequest = TRUE;
+
+ CallService(MS_AWAYMSG_SHOWAWAYMSG, wParam, 0);
+ return 0;
+}
+
+
+
+void HistoryLog(HANDLE hContact, DWORD dwUin, char *data, int event_type, int flag)
+{
+ extern BOOL bHcontactHistory;
+ PBYTE pCurBlob;
+ WORD wTextLen;
+ char szText[MAX_PATH];
+ DBEVENTINFO Event = {0};
+ Event.cbSize=sizeof(Event);
+ Event.szModule=gpszICQProtoName;
+ Event.eventType=event_type;
+ Event.flags=flag,DBEF_UTF;
+ Event.timestamp=(DWORD)time(NULL);
+ mir_snprintf(szText, sizeof(szText), "%s %s ( %s: %s, %s: (%u) )", Translate(data), Translate("by"), Translate("Nick"), (NickFromHandle(hContact)), Translate("UIN"), dwUin);
+ wTextLen = strlen(szText);
+ Event.cbBlob = sizeof(DWORD)+sizeof(HANDLE)+wTextLen+1;
+ pCurBlob = Event.pBlob = (PBYTE)_alloca(Event.cbBlob);
+ memcpy(pCurBlob,&szText,wTextLen); pCurBlob+=wTextLen;
+ *(char *)pCurBlob = 0; pCurBlob++;
+ memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ memcpy(pCurBlob,&hContact,sizeof(HANDLE));
+ if(bHcontactHistory)
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)hContact,(LPARAM)&Event);
+ else
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&Event);
+ //we need show popups for events from here
+}
+
+
+void LogToFile(HANDLE hContact, DWORD dwUin, char *string, int event_type)
+{
+
+ char szTime[30];
+ char content[MAX_PATH];
+ char filename[1024];
+ time_t now;
+ FILE *f;
+
+ wsprintf(filename, UniGetContactSettingUtf(NULL, gpszICQProtoName, "EventsLog", "EventsLog.txt"));
+
+
+ switch(event_type)
+ {
+ case ICQEVENTTYPE_AUTH_GRANTED:
+ if(!bLogAuthFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("granted your authorization request "), Translate(string));
+ break;
+ case ICQEVENTTYPE_AUTH_DENIED:
+ if(!bLogAuthFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("denied your authorization request "), Translate(string));
+ break;
+ case ICQEVENTTYPE_SELF_REMOVE:
+ if(!bLogSelfRemoveFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("removed himself from your serverlist "), Translate(string));
+ break;
+ case ICQEVENTTYPE_FUTURE_AUTH:
+ if(!bLogAuthFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("granted you future authorization "), Translate(string));
+ break;
+ case ICQEVENTTYPE_CLIENT_CHANGE:
+ if(!bLogClientChangeFile)
+ return;
+ utf8_decode_static(string, content, strlen(string));
+ break;
+
+ case ICQEVENTTYPE_CHECK_STATUS:
+ if(!bLogStatusCheckFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("checked your real status "), Translate(string));
+ break;
+ case ICQEVENTTYPE_WAS_FOUND:
+ if(!bLogASDFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s", Translate(string));
+ break;
+ case ICQEVENTTYPE_IGNORECHECK_STATUS:
+ if(!bLogIgnoreCheckFile)
+ return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate("checked his ignore state"), Translate(string));
+ break;
+
+ default:
+ wsprintf(content, "unknown eventype processed");
+ return;
+ }
+
+
+ now = time(NULL);
+ strftime(szTime, sizeof(szTime), "%a, %d %b %Y %H:%M:%S", localtime(&now));
+ /* Sun, 00 Jan 0000 00:00:00 */
+ f = fopen( filename, "a+" );
+ if( f != NULL )
+ {
+ fprintf( f, "[%s] %s (%u) %s\n", szTime, NickFromHandle(hContact), dwUin, content);
+ fclose(f);
+ }
+}
+
+WORD GetProtoVersion()
+{
+ int ver = 0;
+ if (gbVerEnabled)
+ {
+ ver = (DBGetContactSettingWord(NULL,gpszICQProtoName,"setVersion", 0));
+ }
+ else
+ {
+ switch (DBGetContactSettingWord(NULL,gpszICQProtoName,"CurrentID",0)) //client change version
+ {
+ case 1: //unknown
+ ver = 66;
+ break;
+ case 23:
+ case 24:
+ case 2: //qip
+ case 3: //ysm
+ case 7: //trillian
+ case 46: //qip infium
+ ver = 11;
+ break;
+ case 6: //Jimm
+ ver = 5;
+ break;
+ case 9: //Kopete
+ case 52: //NanoICQ
+ ver = 10;
+ break;
+ case 11:
+ ver = 13;
+ break;
+ case 4: //icq lite
+ case 5: //&RQ
+ case 12: //rambler
+ case 13: //icq 5.1
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 26: //icq6
+ case 44: //QNEXT
+ case 45: //pyICQ
+ ver = 9;
+ break;
+ case 21: //stICQ
+ ver = 2;
+ break;
+ case 36: //ICQ99
+ ver = 6;
+ break;
+ case 37: //WebICQ
+ ver = 7;
+ break;
+ case 35: //GAIM
+ ver = 0;
+ break;
+ default : //miranda
+ ver = 8;
+ break;
+ }
+ }
+ DBWriteContactSettingWord(NULL,gpszICQProtoName,"setVersion",(WORD)ver);
+ return ver;
+}
+
+void SetTimeStamps(DWORD *dwFT1, DWORD *dwFT2, DWORD *dwFT3)
+{
+ switch (DBGetContactSettingWord(NULL, gpszICQProtoName, "CurrentID", 0)) //client change dwFT
+ {
+ case 3: //ysm
+ *dwFT1=0xFFFFFFAB; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 4: //ICQ lite
+ *dwFT1=0x3AA773EE; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 5: //&RQ
+ *dwFT1=0xFFFFFF7F; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 7: //trillian
+ *dwFT1=0x3B75AC09; // Abused timestamp
+ *dwFT2=0x00000000; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 8: //licq
+ *dwFT1=0x2C0BA3DD; // Abused timestamp
+ *dwFT2=0x7D800403; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 2: //qip
+ *dwFT1=0x08000300; // Abused timestamp
+ *dwFT2=0x0000000E; // Abused timestamp
+ *dwFT3=0x0000000F; // Timestamp
+ break;
+ case 46: //QIP Infium
+ *dwFT1=0x0000232C; // Abused timestamp
+ *dwFT2=0x0000000B; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 18:
+ case 19:
+ *dwFT1=0x3AA773EE; // Abused timestamp
+ *dwFT2=0x3AA66380; // Abused timestamp
+ *dwFT3=0x00000000; // Timestamp
+ break;
+ case 21:
+ *dwFT1=0x3BA8DBAF;
+ *dwFT2=0x3BEB5373;
+ *dwFT3=0x3BEB5262;
+ break;
+ case 22:
+ *dwFT1=0x3B4C4C0C;
+ *dwFT2=0x00000000;
+ *dwFT3=0x3B7248ed;
+ break;
+ case 1: //unknown
+ case 6: //Jimm
+ case 9: //Kopete
+ case 10: ////icq for mac
+ case 12: //rambler
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 20:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 40: //uIM
+ case 41: //TICQClient
+ case 42: //IC@
+ case 43: //PreludeICQ
+ case 44: //QNEXT
+ case 45: //pyICQ
+ case 47: //JICQ
+ case 49: //MIP
+ case 50: //Trillian Astra
+ case 52: //NanoICQ
+ case 53: //IMadering
+ *dwFT1=0x00000000;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 29:
+ *dwFT1=0x44F523B0;
+ *dwFT2=0x44F523A6;
+ *dwFT3=0x44F523A6;
+ break;
+ case 30: //alicq
+ *dwFT1=0xffffffbe;
+ *dwFT2=0x00090800;
+ *dwFT3=0x00000000;
+ break;
+ case 31: //mICQ
+ *dwFT1=0xFFFFFF42;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 32: //StrICQ 0.4
+ *dwFT1=0xFFFFFF8F;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 33: //vICQ 0.43.0.0
+ *dwFT1=0x04031980;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 34: //IM2
+ *dwFT1=0x3FF19BEB;
+ *dwFT2=0x00000000;
+ *dwFT3=0x3FF19BEB;
+ break;
+ case 35: //GAIM
+ *dwFT1=0xffffffff;
+ *dwFT2=0xffffffff;
+ *dwFT3=0xffffffff;
+ break;
+ case 36: //ICQ99
+ *dwFT1=0x3AA773EE;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 37: //WebICQ
+ *dwFT1=0xFFFFFFFF;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 38: //SmartICQ
+ *dwFT1=0xDDDDEEFF;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 39: //IM+
+ *dwFT1=0x494D2B00;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 48: //SpamBot
+ *dwFT1=0xffffffff;
+ *dwFT2=0x00000000;
+ *dwFT3=0x3B7248ED;
+ break;
+ case 51: //R&Q
+ *dwFT1=0xFFFFF666;
+ *dwFT2=0x00000000;
+ *dwFT3=0x00000000;
+ break;
+ case 11:
+ *dwFT1=0xFFFFFFFF; //Abused timestamp
+ *dwFT2=0x06060600; //Abused timestamp
+ if(gbHideIdEnabled)
+ *dwFT3=gbUnicodeCore?0x80000000:0x00000000;
+ else
+ *dwFT3=gbSecureIM?0x5AFEC0DE:0x00000000;
+ break;
+ default : //miranda
+ *dwFT1=gbHideIdEnabled?0xffffffff:(gbUnicodeCore?0x7fffffff:0xffffffff); //Abused timestamp
+ *dwFT2=ICQ_PLUG_VERSION; //Abused timestamp
+ if(gbHideIdEnabled)
+ *dwFT3=gbUnicodeCore?0x80000000:0x00000000;
+ else
+ *dwFT3=gbSecureIM?0x5AFEC0DE:0x00000000;
+ break;
+ }
+}
+
+/*void logtofile(HANDLE hContact, DWORD dwUin, char *string, int event_type)
+{
+
+ char szTime[30];
+ char content[MAX_PATH];
+ char filename[1024];
+ time_t now;
+ FILE *f;
+ int i;
+
+
+ static struct
+ {
+ int type;
+ BOOL *flag;
+ char *message;
+ } eventTypes[] =
+ {
+ { ICQEVENTTYPE_AUTH_GRANTED, &bLogAuthFile, "granted your authorization request" },
+ { ICQEVENTTYPE_SELF_REMOVE, &bLogSelfRemoveFile, "removed himself from your serverlist" },
+ };
+ int eventTypesCount = sizeof(eventTypes) / sizeof(*eventTypes);
+
+ for (i = 0; i < eventTypesCount; ++i)
+ if (eventTypes.type == event_type)
+ {
+ if (!*eventTypes.flag) return;
+ mir_snprintf(content, sizeof(content), "%s %s", Translate(eventTypes.message), Translate(string)) ;
+ break;
+ }
+
+ // type not found
+ if (i == eventTypesCount)
+ return;
+
+ now = time(NULL);
+ strftime(szTime, sizeof(szTime), "%a, %d %b %Y %H:%M:%S", localtime(&now)) ;
+ // Sun, 00 Jan 0000 00:00:00
+
+ wsprintf(filename, UniGetContactSettingUtf(NULL, gpszICQProtoName, "EventsLog", "EventsLog.txt")) ;
+ f = fopen( filename, "a+" );
+ if( f != NULL )
+ {
+ fprintf( f, "[%s] %s (%u) %s\n", szTime, NickFromHandleUtf(hContact), dwUin, content);
+ fclose(f);
+ }
+ //another realisation by Nullbie
+} */
|