summaryrefslogtreecommitdiff
path: root/protocols/IcqOscarJ/utilities.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-10-12 14:53:57 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-10-12 14:53:57 +0000
commit3b55a62fdcb1f8222de3c2c8fbed530792c419a0 (patch)
tree5b2f628e847f61bb3e16f95ecaed6e187963362f /protocols/IcqOscarJ/utilities.cpp
parent1f9c986d82657f965462d289bf94aa012cf026fc (diff)
GTalkExt, ICQ, IRC, Jabber: folders restructurization
git-svn-id: http://svn.miranda-ng.org/main/trunk@1890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/IcqOscarJ/utilities.cpp')
-rw-r--r--protocols/IcqOscarJ/utilities.cpp2183
1 files changed, 0 insertions, 2183 deletions
diff --git a/protocols/IcqOscarJ/utilities.cpp b/protocols/IcqOscarJ/utilities.cpp
deleted file mode 100644
index 70f7547108..0000000000
--- a/protocols/IcqOscarJ/utilities.cpp
+++ /dev/null
@@ -1,2183 +0,0 @@
-// ---------------------------------------------------------------------------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-2004 Martin Öberg, Sam Kothari, Robert Rainwater
-// Copyright © 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// -----------------------------------------------------------------------------
-// DESCRIPTION:
-//
-// Describe me here please...
-//
-// -----------------------------------------------------------------------------
-#include "icqoscar.h"
-
-
-struct gateway_index
-{
- HANDLE hConn;
- DWORD dwIndex;
-};
-
-static icq_critical_section *gatewayMutex = NULL;
-
-static gateway_index *gateways = NULL;
-static int gatewayCount = 0;
-
-static DWORD *spammerList = NULL;
-static int spammerListCount = 0;
-
-
-void MoveDlgItem(HWND hwndDlg, int iItem, int left, int top, int width, int height)
-{
- RECT rc;
-
- rc.left = left;
- rc.top = top;
- rc.right = left + width;
- rc.bottom = top + height;
- MapDialogRect(hwndDlg, &rc);
- MoveWindow(GetDlgItem(hwndDlg, iItem), rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
-}
-
-
-void EnableDlgItem(HWND hwndDlg, UINT control, int state)
-{
- EnableWindow(GetDlgItem(hwndDlg, control), state);
-}
-
-
-void ShowDlgItem(HWND hwndDlg, UINT control, int state)
-{
- ShowWindow(GetDlgItem(hwndDlg, control), state);
-}
-
-
-void icq_EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
-{
- for (int i = 0; i < cControls; i++)
- EnableDlgItem(hwndDlg, controls[i], state);
-}
-
-
-void icq_ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
-{
- for (int i = 0; i < cControls; i++)
- ShowDlgItem(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_OFFLINE:
- nSupportedStatus = nMirandaStatus;
- break;
-
-case ID_STATUS_FREECHAT:
- nSupportedStatus = ID_STATUS_ONLINE;
- 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 tchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, GSMDF_TCHAR));
-}
-
-char** CIcqProto::MirandaStatusToAwayMsg(int nStatus)
-{
- switch (nStatus) {
-
-case ID_STATUS_ONLINE:
- return &m_modeMsgs.szOnline;
-
-case ID_STATUS_AWAY:
- return &m_modeMsgs.szAway;
-
-case ID_STATUS_NA:
- return &m_modeMsgs.szNa;
-
-case ID_STATUS_OCCUPIED:
- return &m_modeMsgs.szOccupied;
-
-case ID_STATUS_DND:
- return &m_modeMsgs.szDnd;
-
-case ID_STATUS_FREECHAT:
- return &m_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)
-{
- icq_lock l(gatewayMutex);
-
- for (int i = 0; i < gatewayCount; i++)
- {
- if (hConn == gateways[i].hConn)
- {
- gateways[i].dwIndex = dwIndex;
- return;
- }
- }
-
- gateways = (gateway_index *)SAFE_REALLOC(gateways, sizeof(gateway_index) * (gatewayCount + 1));
- gateways[gatewayCount].hConn = hConn;
- gateways[gatewayCount].dwIndex = dwIndex;
- gatewayCount++;
-}
-
-
-DWORD GetGatewayIndex(HANDLE hConn)
-{
- icq_lock l(gatewayMutex);
-
- for (int i = 0; i < gatewayCount; i++)
- {
- if (hConn == gateways[i].hConn)
- return gateways[i].dwIndex;
- }
-
- return 1; // this is default
-}
-
-
-void FreeGatewayIndex(HANDLE hConn)
-{
- icq_lock l(gatewayMutex);
-
- for (int 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;
- }
- }
-}
-
-
-void CIcqProto::AddToSpammerList(DWORD dwUIN)
-{
- icq_lock l(gatewayMutex);
-
- spammerList = (DWORD *)SAFE_REALLOC(spammerList, sizeof(DWORD) * (spammerListCount + 1));
- spammerList[spammerListCount] = dwUIN;
- spammerListCount++;
-}
-
-
-BOOL CIcqProto::IsOnSpammerList(DWORD dwUIN)
-{
- icq_lock l(gatewayMutex);
-
- for (int i = 0; i < spammerListCount; i++)
- {
- if (dwUIN == spammerList[i])
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-// ICQ contacts cache
-
-void CIcqProto::AddToContactsCache(HANDLE hContact, DWORD dwUin, const char *szUid)
-{
- if (!hContact || (!dwUin && !szUid))
- return;
-
-#ifdef _DEBUG
- NetLog_Server("Adding contact to cache: %u%s%s", dwUin, dwUin ? "" : " - ", dwUin ? "" : szUid);
-#endif
-
- icq_contacts_cache *cache_item = (icq_contacts_cache*)SAFE_MALLOC(sizeof(icq_contacts_cache));
- cache_item->hContact = hContact;
- cache_item->dwUin = dwUin;
- if (!dwUin)
- cache_item->szUid = null_strdup(szUid);
-
- icq_lock l(contactsCacheMutex);
- contactsCache.insert(cache_item);
-}
-
-
-void CIcqProto::InitContactsCache()
-{
- if (!gatewayMutex)
- gatewayMutex = new icq_critical_section();
- else
- gatewayMutex->_Lock();
-
- contactsCacheMutex = new icq_critical_section();
-
- // build cache
- icq_lock l(contactsCacheMutex);
-
- HANDLE hContact = FindFirstContact();
-
- while (hContact)
- {
- DWORD dwUin;
- uid_str szUid;
-
- if (!getContactUid(hContact, &dwUin, &szUid))
- AddToContactsCache(hContact, dwUin, szUid);
-
- hContact = FindNextContact(hContact);
- }
-}
-
-
-void CIcqProto::UninitContactsCache(void)
-{
- contactsCacheMutex->Enter();
-
- // cleanup the cache
- for (int i = 0; i < contactsCache.getCount(); i++)
- {
- icq_contacts_cache *cache_item = contactsCache[i];
-
- SAFE_FREE((void**)&cache_item->szUid);
- SAFE_FREE((void**)&cache_item);
- }
-
- contactsCache.destroy();
-
- contactsCacheMutex->Leave();
-
- SAFE_DELETE(&contactsCacheMutex);
-
- if (gatewayMutex && gatewayMutex->getLockCount() > 1)
- gatewayMutex->_Release();
- else
- SAFE_DELETE(&gatewayMutex);
-}
-
-
-void CIcqProto::DeleteFromContactsCache(HANDLE hContact)
-{
- icq_lock l(contactsCacheMutex);
-
- for (int i = 0; i < contactsCache.getCount(); i++)
- {
- icq_contacts_cache *cache_item = contactsCache[i];
-
- if (cache_item->hContact == hContact)
- {
-#ifdef _DEBUG
- NetLog_Server("Removing contact from cache: %u%s%s, position: %u", cache_item->dwUin, cache_item->dwUin ? "" : " - ", cache_item->dwUin ? "" : cache_item->szUid, i);
-#endif
- contactsCache.remove(i);
- // Release memory
- SAFE_FREE((void**)&cache_item->szUid);
- SAFE_FREE((void**)&cache_item);
- break;
- }
- }
-}
-
-
-HANDLE CIcqProto::HandleFromCacheByUid(DWORD dwUin, const char *szUid)
-{
- icq_contacts_cache cache_item = {NULL, dwUin, szUid};
-
- icq_lock l(contactsCacheMutex);
- // find in list
- int i = contactsCache.getIndex(&cache_item);
- if (i != -1)
- return contactsCache[i]->hContact;
-
- return NULL;
-}
-
-
-HANDLE CIcqProto::HContactFromUIN(DWORD dwUin, int *Added)
-{
- if (Added) *Added = 0;
-
- HANDLE hContact = HandleFromCacheByUid(dwUin, NULL);
- if (hContact) return hContact;
-
- hContact = FindFirstContact();
- while (hContact)
- {
- DWORD dwContactUin;
-
- dwContactUin = getContactUin(hContact);
- if (dwContactUin == dwUin)
- {
- AddToContactsCache(hContact, dwUin, NULL);
- return hContact;
- }
-
- hContact = FindNextContact(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", dwUin);
- return INVALID_HANDLE_VALUE;
- }
-
- if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)m_szModuleName) != 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", dwUin);
- return INVALID_HANDLE_VALUE;
- }
-
- setSettingDword(hContact, UNIQUEIDSETTING, dwUin);
-
- if (!bIsSyncingCL)
- {
- DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
- setContactHidden(hContact, 1);
-
- setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
-
- icq_QueueUser(hContact);
-
- if (icqOnline())
- icq_sendNewContact(dwUin, NULL);
- }
- AddToContactsCache(hContact, dwUin, NULL);
- *Added = 1;
-
- return hContact;
- }
-
- // not in list, check that uin do not belong to us
- if (getContactUin(NULL) == dwUin)
- return NULL;
-
- return INVALID_HANDLE_VALUE;
-}
-
-
-HANDLE CIcqProto::HContactFromUID(DWORD dwUin, const char *szUid, int *Added)
-{
- if (dwUin)
- return HContactFromUIN(dwUin, Added);
-
- if (Added) *Added = 0;
-
- if (!m_bAimEnabled) return INVALID_HANDLE_VALUE;
-
- HANDLE hContact = HandleFromCacheByUid(dwUin, szUid);
- if (hContact) return hContact;
-
- hContact = FindFirstContact();
- while (hContact)
- {
- DWORD dwContactUin;
- uid_str szContactUid;
-
- if (!getContactUid(hContact, &dwContactUin, &szContactUid))
- {
- if (!dwContactUin && !stricmpnull(szContactUid, szUid))
- {
- if (strcmpnull(szContactUid, szUid))
- { // fix case in SN
- setSettingString(hContact, UNIQUEIDSETTING, szUid);
- }
- return hContact;
- }
- }
- hContact = FindNextContact(hContact);
- }
-
- //not present: add
- if (Added)
- {
- hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
- CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)m_szModuleName);
-
- setSettingString(hContact, UNIQUEIDSETTING, szUid);
-
- if (!bIsSyncingCL)
- {
- DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
- setContactHidden(hContact, 1);
-
- setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
-
- if (icqOnline())
- icq_sendNewContact(0, szUid);
- }
- AddToContactsCache(hContact, 0, szUid);
- *Added = 1;
-
- return hContact;
- }
-
- return INVALID_HANDLE_VALUE;
-}
-
-
-HANDLE CIcqProto::HContactFromAuthEvent(HANDLE hEvent)
-{
- DBEVENTINFO dbei = { sizeof(dbei) };
- DWORD body[3];
-
- dbei.cbBlob = sizeof(DWORD)*2;
- dbei.pBlob = (PBYTE)&body;
-
- if (CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei))
- return INVALID_HANDLE_VALUE;
-
- if (dbei.eventType != EVENTTYPE_AUTHREQUEST)
- return INVALID_HANDLE_VALUE;
-
- if (strcmpnull(dbei.szModule, m_szModuleName))
- return INVALID_HANDLE_VALUE;
-
- return DbGetAuthEventContact(&dbei);
-}
-
-char *NickFromHandle(HANDLE hContact)
-{
- if (hContact == INVALID_HANDLE_VALUE)
- return null_strdup(Translate("<invalid>"));
-
- return null_strdup((char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0));
-}
-
-char *NickFromHandleUtf(HANDLE hContact)
-{
- if (hContact == INVALID_HANDLE_VALUE)
- return ICQTranslateUtf(LPGEN("<invalid>"));
-
- return tchar_to_utf8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
-}
-
-char *strUID(DWORD dwUIN, char *pszUID)
-{
- if (dwUIN && pszUID)
- _ltoa(dwUIN, pszUID, 10);
-
- return pszUID;
-}
-
-
-/* a strlen() that likes NULL */
-int __fastcall strlennull(const char *string)
-{
- if (string)
- return (int)strlen(string);
-
- return 0;
-}
-
-
-/* a wcslen() that likes NULL */
-int __fastcall strlennull(const WCHAR *string)
-{
- if (string)
- return (int)wcslen(string);
-
- return 0;
-}
-
-
-/* a strcmp() that likes NULL */
-int __fastcall strcmpnull(const char *str1, const char *str2)
-{
- if (str1 && str2)
- return strcmp(str1, str2);
-
- if (!str1 && !str2)
- return 0;
-
- return 1;
-}
-
-/* a stricmp() that likes NULL */
-int __fastcall stricmpnull(const char *str1, const char *str2)
-{
- if (str1 && str2)
- return _stricmp(str1, str2);
-
- if (!str1 && !str2)
- return 0;
-
- return 1;
-}
-
-char* __fastcall strstrnull(const char *str, const char *substr)
-{
- if (str)
- return (char*)strstr(str, substr);
-
- return NULL;
-}
-
-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;
-}
-
-int null_snprintf(WCHAR *buffer, size_t count, const WCHAR *fmt, ...)
-{
- va_list va;
- int len;
-
- ZeroMemory(buffer, count * sizeof(WCHAR));
- va_start(va, fmt);
- len = _vsnwprintf(buffer, count, fmt, va);
- va_end(va);
- return len;
-}
-
-
-char* __fastcall null_strdup(const char *string)
-{
- if (string)
- return _strdup(string);
-
- return NULL;
-}
-
-
-WCHAR* __fastcall null_strdup(const WCHAR *string)
-{
- if (string)
- return wcsdup(string);
-
- return NULL;
-}
-
-
-char* __fastcall null_strcpy(char *dest, const char *src, size_t maxlen)
-{
- if (!dest)
- return NULL;
-
- if (src && src[0])
- {
- strncpy(dest, src, maxlen);
- dest[maxlen] = '\0';
- }
- else
- dest[0] = '\0';
-
- return dest;
-}
-
-
-WCHAR* __fastcall null_strcpy(WCHAR *dest, const WCHAR *src, size_t maxlen)
-{
- if (!dest)
- return NULL;
-
- if (src && src[0])
- {
- wcsncpy(dest, src, maxlen);
- dest[maxlen] = '\0';
- }
- else
- dest[0] = '\0';
-
- return dest;
-}
-
-
-int __fastcall null_strcut(char *string, int maxlen)
-{ // limit the string to max length (null & utf-8 strings ready)
- int len = (int)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, "&gt;", 4))
- {
- *szChar = '>';
- szChar++;
- i += 3;
- }
- else if (!_strnicmp(string+i, "&lt;", 4))
- {
- *szChar = '<';
- szChar++;
- i += 3;
- }
- else if (!_strnicmp(string+i, "&amp;", 5))
- {
- *szChar = '&';
- szChar++;
- i += 4;
- }
- else if (!_strnicmp(string+i, "&quot;", 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 if (string[i]=='"') l += 6; 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 if (string[i]=='"')
- {
- *(DWORD*)szChar = 'ouq&';
- szChar += 4;
- *(WORD*)szChar = ';t';
- szChar += 2;
- }
- 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((void**)&tmp);
-
- return res;
-}
-
-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);
- }
- if (!_strnicmp(pszEncoding, "unicode-2-0", 11))
- { // it is UCS-2 encoded
- int wLen = strlennull((WCHAR*)string) + 1;
- WCHAR *szStr = (WCHAR*)_alloca(wLen*2);
- BYTE *tmp = (BYTE*)string;
-
- unpackWideString(&tmp, szStr, (WORD)(wLen*2));
-
- return make_utf8_string(szStr);
- }
- 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 CIcqProto::ResetSettingsOnListReload()
-{
- // Reset a bunch of session specific settings
- setSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, 0);
- setSettingWord(NULL, DBSETTING_SERVLIST_METAINFO, 0);
- setSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, 0);
- setSettingWord(NULL, DBSETTING_SERVLIST_PHOTO, 0);
- setSettingWord(NULL, "SrvRecordCount", 0);
- deleteSetting(NULL, DBSETTING_SERVLIST_UNHANDLED);
-
- HANDLE hContact = FindFirstContact();
-
- while (hContact)
- {
- // All these values will be restored during the serv-list receive
- setSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
- setSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0);
- setSettingWord(hContact, DBSETTING_SERVLIST_PERMIT, 0);
- setSettingWord(hContact, DBSETTING_SERVLIST_DENY, 0);
- deleteSetting(hContact, DBSETTING_SERVLIST_IGNORE);
- setSettingByte(hContact, "Auth", 0);
- deleteSetting(hContact, DBSETTING_SERVLIST_DATA);
-
- hContact = FindNextContact(hContact);
- }
-
- FlushSrvGroupsCache();
-}
-
-void CIcqProto::ResetSettingsOnConnect()
-{
- // Reset a bunch of session specific settings
- setSettingByte(NULL, "SrvVisibility", 0);
- setSettingDword(NULL, "IdleTS", 0);
-
- HANDLE hContact = FindFirstContact();
-
- while (hContact)
- {
- setSettingDword(hContact, "LogonTS", 0);
- setSettingDword(hContact, "IdleTS", 0);
- setSettingDword(hContact, "TickTS", 0);
- setSettingByte(hContact, "TemporaryVisible", 0);
-
- // All these values will be restored during the login
- if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
- setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
-
- hContact = FindNextContact(hContact);
- }
-}
-
-void CIcqProto::ResetSettingsOnLoad()
-{
- setSettingDword(NULL, "IdleTS", 0);
- setSettingDword(NULL, "LogonTS", 0);
-
- HANDLE hContact = FindFirstContact();
-
- while (hContact)
- {
- setSettingDword(hContact, "LogonTS", 0);
- setSettingDword(hContact, "IdleTS", 0);
- setSettingDword(hContact, "TickTS", 0);
- if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
- {
- setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
-
- deleteSetting(hContact, DBSETTING_XSTATUS_ID);
- deleteSetting(hContact, DBSETTING_XSTATUS_NAME);
- deleteSetting(hContact, DBSETTING_XSTATUS_MSG);
- }
- setSettingByte(hContact, "DCStatus", 0);
-
- hContact = FindNextContact(hContact);
- }
-}
-
-int RandRange(int nLow, int nHigh)
-{
- return nLow + (int)((nHigh-nLow+1)*rand()/(RAND_MAX+1.0));
-}
-
-
-BOOL IsStringUIN(const 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;
-}
-
-
-void __cdecl CIcqProto::ProtocolAckThread(icq_ack_args* pArguments)
-{
- Sleep(150);
-
- if (pArguments->nAckResult == ACKRESULT_SUCCESS)
- NetLog_Server("Sent fake message ack");
- else if (pArguments->nAckResult == ACKRESULT_FAILED)
- NetLog_Server("Message delivery failed");
-
- BroadcastAck(pArguments->hContact, pArguments->nAckType, pArguments->nAckResult, pArguments->hSequence, pArguments->pszMessage);
-
- SAFE_FREE((void**)(char **)&pArguments->pszMessage);
- SAFE_FREE((void**)&pArguments);
-}
-
-void CIcqProto::SendProtoAck(HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, char* pszMessage)
-{
- icq_ack_args* 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(( IcqThreadFunc )&CIcqProto::ProtocolAckThread, pArgs );
-}
-
-void CIcqProto::SetCurrentStatus(int nStatus)
-{
- int nOldStatus = m_iStatus;
-
- m_iStatus = nStatus;
- BroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)nOldStatus, nStatus);
-}
-
-
-int CIcqProto::IsMetaInfoChanged(HANDLE hContact)
-{
- DBVARIANT infoToken = {DBVT_DELETED};
- int res = 0;
-
- if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &infoToken))
- { // contact does have info from directory, check if it is not outdated
- double dInfoTime = 0;
- double dInfoSaved = 0;
-
- if ((dInfoTime = getSettingDouble(hContact, DBSETTING_METAINFO_TIME, 0)) > 0)
- {
- if ((dInfoSaved = getSettingDouble(hContact, DBSETTING_METAINFO_SAVED, 0)) > 0)
- {
- if (dInfoSaved < dInfoTime)
- res = 2; // directory info outdated
- }
- else
- res = 1; // directory info not saved at all
- }
-
- ICQFreeVariant(&infoToken);
- }
- else
- { // it cannot be detected if user info was not changed, so use a generic threshold
- DBVARIANT infoSaved = {DBVT_DELETED};
- DWORD dwInfoTime = 0;
-
- if (!getSetting(hContact, DBSETTING_METAINFO_SAVED, &infoSaved))
- {
- if (infoSaved.type == DBVT_BLOB && infoSaved.cpbVal == 8)
- {
- double dwTime = *(double*)infoSaved.pbVal;
-
- dwInfoTime = (dwTime - 25567) * 86400;
- }
- else if (infoSaved.type == DBVT_DWORD)
- dwInfoTime = infoSaved.dVal;
-
- ICQFreeVariant(&infoSaved);
-
- if ((time(NULL) - dwInfoTime) > 14*3600*24)
- {
- res = 3; // threshold exceeded
- }
- }
- else
- res = 4; // no timestamp found
- }
-
- return res;
-}
-
-
-void __cdecl CIcqProto::SetStatusNoteThread(void *pDelay)
-{
- if (pDelay)
- SleepEx((DWORD)pDelay, TRUE);
-
- cookieMutex->Enter();
-
- if (icqOnline() && (setStatusNoteText || setStatusMoodData))
- { // send status note change packets, write status note to database
- if (setStatusNoteText)
- { // change status note in directory
- m_ratesMutex->Enter();
- if (m_rates)
- { // rate management
- WORD wGroup = m_rates->getGroupFromSNAC(ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST);
-
- while (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_LIMIT))
- { // we are over rate, need to wait before sending
- int nDelay = m_rates->getDelayToLimitLevel(wGroup, RML_IDLE_10);
-
- m_ratesMutex->Leave();
- cookieMutex->Leave();
-#ifdef _DEBUG
- NetLog_Server("Rates: SetStatusNote delayed %dms", nDelay);
-#endif
- SleepEx(nDelay, TRUE); // do not keep things locked during sleep
- cookieMutex->Enter();
- m_ratesMutex->Enter();
- if (!m_rates) // we lost connection when we slept, go away
- break;
- }
- }
- m_ratesMutex->Leave();
-
- BYTE *pBuffer = NULL;
- int cbBuffer = 0;
-
- ppackTLV(&pBuffer, &cbBuffer, 0x226, strlennull(setStatusNoteText), (BYTE*)setStatusNoteText);
- icq_changeUserDirectoryInfoServ(pBuffer, cbBuffer, DIRECTORYREQUEST_UPDATENOTE);
-
- SAFE_FREE((void**)&pBuffer);
- }
-
- if (setStatusNoteText || setStatusMoodData)
- { // change status note and mood in session data
- m_ratesMutex->Enter();
- if (m_rates)
- { // rate management
- WORD wGroup = m_rates->getGroupFromSNAC(ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS);
-
- while (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_LIMIT))
- { // we are over rate, need to wait before sending
- int nDelay = m_rates->getDelayToLimitLevel(wGroup, RML_IDLE_10);
-
- m_ratesMutex->Leave();
- cookieMutex->Leave();
-#ifdef _DEBUG
- NetLog_Server("Rates: SetStatusNote delayed %dms", nDelay);
-#endif
- SleepEx(nDelay, TRUE); // do not keep things locked during sleep
- cookieMutex->Enter();
- m_ratesMutex->Enter();
- if (!m_rates) // we lost connection when we slept, go away
- break;
- }
- }
- m_ratesMutex->Leave();
-
- // check if the session data were not updated already
- char *szCurrentStatusNote = getSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, NULL);
- char *szCurrentStatusMood = NULL;
- DBVARIANT dbv = {DBVT_DELETED};
-
- if (m_bMoodsEnabled && !getSettingString(NULL, DBSETTING_STATUS_MOOD, &dbv))
- szCurrentStatusMood = dbv.pszVal;
-
- if (!setStatusNoteText && szCurrentStatusNote)
- setStatusNoteText = null_strdup(szCurrentStatusNote);
- if (m_bMoodsEnabled && !setStatusMoodData && szCurrentStatusMood)
- setStatusMoodData = null_strdup(szCurrentStatusMood);
-
- if (strcmpnull(szCurrentStatusNote, setStatusNoteText) || (m_bMoodsEnabled && strcmpnull(szCurrentStatusMood, setStatusMoodData)))
- {
- setSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, setStatusNoteText);
- if (m_bMoodsEnabled)
- setSettingString(NULL, DBSETTING_STATUS_MOOD, setStatusMoodData);
-
- WORD wStatusNoteLen = strlennull(setStatusNoteText);
- WORD wStatusMoodLen = m_bMoodsEnabled ? strlennull(setStatusMoodData) : 0;
- icq_packet packet;
- WORD wDataLen = (wStatusNoteLen ? wStatusNoteLen + 4 : 0) + 4 + wStatusMoodLen + 4;
-
- serverPacketInit(&packet, wDataLen + 14);
- packFNACHeader(&packet, ICQ_SERVICE_FAMILY, ICQ_CLIENT_SET_STATUS);
- // Change only session data
- packWord(&packet, 0x1D); // TLV 1D
- packWord(&packet, wDataLen); // TLV length
- packWord(&packet, 0x02); // Item Type
- if (wStatusNoteLen)
- {
- packWord(&packet, 0x400 | (WORD)(wStatusNoteLen + 4)); // Flags + Item Length
- packWord(&packet, wStatusNoteLen); // Text Length
- packBuffer(&packet, (LPBYTE)setStatusNoteText, wStatusNoteLen);
- packWord(&packet, 0); // Encoding not specified (utf-8 is default)
- }
- else
- packWord(&packet, 0); // Flags + Item Length
- packWord(&packet, 0x0E); // Item Type
- packWord(&packet, wStatusMoodLen); // Flags + Item Length
- if (wStatusMoodLen)
- packBuffer(&packet, (LPBYTE)setStatusMoodData, wStatusMoodLen); // Mood
-
- sendServPacket(&packet);
- }
- SAFE_FREE(&szCurrentStatusNote);
- ICQFreeVariant(&dbv);
- }
- }
- SAFE_FREE(&setStatusNoteText);
- SAFE_FREE(&setStatusMoodData);
-
- cookieMutex->Leave();
-}
-
-
-int CIcqProto::SetStatusNote(const char *szStatusNote, DWORD dwDelay, int bForce)
-{
- int bChanged = FALSE;
-
- // bForce is intended for login sequence - need to call this earlier than icqOnline()
- // the process is delayed and icqOnline() is ready when needed inside SetStatusNoteThread()
- if (!bForce && !icqOnline()) return bChanged;
-
- // reuse generic critical section (used for cookies list and object variables locks)
- icq_lock l(cookieMutex);
-
- if (!setStatusNoteText && (!m_bMoodsEnabled || !setStatusMoodData))
- { // check if the status note was changed and if yes, create thread to change it
- char *szCurrentStatusNote = getSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, NULL);
-
- if (strcmpnull(szCurrentStatusNote, szStatusNote))
- { // status note was changed
- // create thread to change status note on existing server connection
- setStatusNoteText = null_strdup(szStatusNote);
-
- if (dwDelay)
- ForkThread(&CIcqProto::SetStatusNoteThread, (void*)dwDelay);
- else // we cannot afford any delay, so do not run in separate thread
- SetStatusNoteThread(NULL);
-
- bChanged = TRUE;
- }
- SAFE_FREE(&szCurrentStatusNote);
- }
- else
- { // only alter status note object with new status note, keep the thread waiting for execution
- SAFE_FREE(&setStatusNoteText);
- setStatusNoteText = null_strdup(szStatusNote);
-
- bChanged = TRUE;
- }
-
- return bChanged;
-}
-
-
-int CIcqProto::SetStatusMood(const char *szMoodData, DWORD dwDelay)
-{
- int bChanged = FALSE;
-
- if (!icqOnline()) return bChanged;
-
- // reuse generic critical section (used for cookies list and object variables locks)
- icq_lock l(cookieMutex);
-
- if (!setStatusNoteText && !setStatusMoodData)
- { // check if the status mood was changed and if yes, create thread to change it
- char *szCurrentStatusMood = NULL;
- DBVARIANT dbv = {DBVT_DELETED};
-
- if (!getSettingString(NULL, DBSETTING_STATUS_MOOD, &dbv))
- szCurrentStatusMood = dbv.pszVal;
-
- if (strcmpnull(szCurrentStatusMood, szMoodData))
- { // status mood was changed
- // create thread to change status mood on existing server connection
- setStatusMoodData = null_strdup(szMoodData);
- if (dwDelay)
- ForkThread(&CIcqProto::SetStatusNoteThread, (void*)dwDelay);
- else // we cannot afford any delay, so do not run in separate thread
- SetStatusNoteThread(NULL);
-
- bChanged = TRUE;
- }
- ICQFreeVariant(&dbv);
- }
- else
- { // only alter status mood object with new status mood, keep the thread waiting for execution
- SAFE_FREE(&setStatusMoodData);
- setStatusMoodData = null_strdup(szMoodData);
-
- bChanged = TRUE;
- }
-
- return bChanged;
-}
-
-
-void CIcqProto::writeDbInfoSettingTLVStringUtf(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
-{
- oscar_tlv *pTLV = chain->getTLV(wTlv, 1);
-
- if (pTLV && pTLV->wLen > 0)
- {
- char *str = (char*)_alloca(pTLV->wLen + 1);
-
- memcpy(str, pTLV->pData, pTLV->wLen);
- str[pTLV->wLen] = '\0';
- setSettingStringUtf(hContact, szSetting, str);
- }
- else
- deleteSetting(hContact, szSetting);
-}
-
-
-void CIcqProto::writeDbInfoSettingTLVString(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
-{
- oscar_tlv *pTLV = chain->getTLV(wTlv, 1);
-
- if (pTLV && pTLV->wLen > 0)
- {
- char *str = (char*)_alloca(pTLV->wLen + 1);
-
- memcpy(str, pTLV->pData, pTLV->wLen);
- str[pTLV->wLen] = '\0';
- setSettingString(hContact, szSetting, str);
- }
- else
- deleteSetting(hContact, szSetting);
-}
-
-
-void CIcqProto::writeDbInfoSettingTLVWord(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
-{
- int num = chain->getNumber(wTlv, 1);
-
- if (num > 0)
- setSettingWord(hContact, szSetting, num);
- else
- deleteSetting(hContact, szSetting);
-}
-
-
-void CIcqProto::writeDbInfoSettingTLVByte(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
-{
- int num = chain->getNumber(wTlv, 1);
-
- if (num > 0)
- setSettingByte(hContact, szSetting, num);
- else
- deleteSetting(hContact, szSetting);
-}
-
-
-void CIcqProto::writeDbInfoSettingTLVDouble(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
-{
- double num = chain->getDouble(wTlv, 1);
-
- if (num > 0)
- setSettingDouble(hContact, szSetting, num);
- else
- deleteSetting(hContact, szSetting);
-}
-
-void CIcqProto::writeDbInfoSettingTLVDate(HANDLE hContact, const char* szSettingYear, const char* szSettingMonth, const char* szSettingDay, oscar_tlv_chain* chain, WORD wTlv)
-{
- double time = chain->getDouble(wTlv, 1);
-
- if (time > 0)
- { // date is stored as double with unit equal to a day, incrementing since 1/1/1900 0:00 GMT
- SYSTEMTIME sTime = {0};
- if (VariantTimeToSystemTime(time + 2, &sTime))
- {
- setSettingWord(hContact, szSettingYear, sTime.wYear);
- setSettingByte(hContact, szSettingMonth, (BYTE)sTime.wMonth);
- setSettingByte(hContact, szSettingDay, (BYTE)sTime.wDay);
- }
- else
- {
- deleteSetting(hContact, szSettingYear);
- deleteSetting(hContact, szSettingMonth);
- deleteSetting(hContact, szSettingDay);
- }
- }
- else
- {
- deleteSetting(hContact, szSettingYear);
- deleteSetting(hContact, szSettingMonth);
- deleteSetting(hContact, szSettingDay);
- }
-}
-
-
-void CIcqProto::writeDbInfoSettingTLVBlob(HANDLE hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv)
-{
- oscar_tlv *pTLV = chain->getTLV(wTlv, 1);
-
- if (pTLV && pTLV->wLen > 0)
- setSettingBlob(hContact, szSetting, pTLV->pData, pTLV->wLen);
- else
- deleteSetting(hContact, szSetting);
-}
-
-
-BOOL CIcqProto::writeDbInfoSettingString(HANDLE hContact, const char* szSetting, char** buf, WORD* pwLength)
-{
- WORD wLen;
-
- if (*pwLength < 2)
- return FALSE;
-
- unpackLEWord((LPBYTE*)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 = getSettingWord(hContact, "InfoCodePage", getSettingWord(hContact, "InfoCP", CP_ACP));
-
- if (wCp != CP_ACP)
- {
- char *szUtf = ansi_to_utf8_codepage(*buf, wCp);
-
- if (szUtf)
- {
- setSettingStringUtf(hContact, szSetting, szUtf);
- SAFE_FREE((void**)&szUtf);
- }
- else
- setSettingString(hContact, szSetting, *buf);
- }
- else
- setSettingString(hContact, szSetting, *buf);
- }
- else
- deleteSetting(hContact, szSetting);
-
- *buf += wLen;
- *pwLength -= wLen;
-
- return TRUE;
-}
-
-BOOL CIcqProto::writeDbInfoSettingWord(HANDLE hContact, const char *szSetting, char **buf, WORD* pwLength)
-{
- WORD wVal;
-
-
- if (*pwLength < 2)
- return FALSE;
-
- unpackLEWord((LPBYTE*)buf, &wVal);
- *pwLength -= 2;
-
- if (wVal != 0)
- setSettingWord(hContact, szSetting, wVal);
- else
- deleteSetting(hContact, szSetting);
-
- return TRUE;
-}
-
-BOOL CIcqProto::writeDbInfoSettingWordWithTable(HANDLE hContact, const char *szSetting, const FieldNamesItem *table, char **buf, WORD* pwLength)
-{
- WORD wVal;
- char sbuf[MAX_PATH];
- char *text;
-
- if (*pwLength < 2)
- return FALSE;
-
- unpackLEWord((LPBYTE*)buf, &wVal);
- *pwLength -= 2;
-
- text = LookupFieldNameUtf(table, wVal, sbuf, MAX_PATH);
- if (text)
- setSettingStringUtf(hContact, szSetting, text);
- else
- deleteSetting(hContact, szSetting);
-
- return TRUE;
-}
-
-BOOL CIcqProto::writeDbInfoSettingByte(HANDLE hContact, const char *pszSetting, char **buf, WORD* pwLength)
-{
- BYTE byVal;
-
- if (*pwLength < 1)
- return FALSE;
-
- unpackByte((LPBYTE*)buf, &byVal);
- *pwLength -= 1;
-
- if (byVal != 0)
- setSettingByte(hContact, pszSetting, byVal);
- else
- deleteSetting(hContact, pszSetting);
-
- return TRUE;
-}
-
-BOOL CIcqProto::writeDbInfoSettingByteWithTable(HANDLE hContact, const char *szSetting, const FieldNamesItem *table, char **buf, WORD* pwLength)
-{
- BYTE byVal;
- char sbuf[MAX_PATH];
- char *text;
-
- if (*pwLength < 1)
- return FALSE;
-
- unpackByte((LPBYTE*)buf, &byVal);
- *pwLength -= 1;
-
- text = LookupFieldNameUtf(table, byVal, sbuf, MAX_PATH);
- if (text)
- setSettingStringUtf(hContact, szSetting, text);
- else
- deleteSetting(hContact, szSetting);
-
- return TRUE;
-}
-
-char* time2text(time_t time)
-{
- tm *local = localtime(&time);
-
- if (local)
- {
- char *str = asctime(local);
- str[24] = '\0'; // remove new line
- return str;
- }
- else
- return "<invalid>";
-}
-
-
-BOOL CIcqProto::validateStatusMessageRequest(HANDLE hContact, WORD byMessageType)
-{
- // Privacy control
- if (getSettingByte(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 (getSettingByte(NULL, "StatusMsgReplyVisible", 0))
- {
- WORD wStatus = getContactStatus(hContact);
- if (wStatus == ID_STATUS_OFFLINE)
- return FALSE;
- }
- }
-
- // Dont send messages to people you are hiding from
- if (hContact != INVALID_HANDLE_VALUE &&
- getSettingWord(hContact, "ApparentMode", 0) == ID_STATUS_OFFLINE)
- {
- return FALSE;
- }
-
- // Dont respond to request for other statuses than your current one
- if ((byMessageType == MTYPE_AUTOONLINE && m_iStatus != ID_STATUS_ONLINE) ||
- (byMessageType == MTYPE_AUTOAWAY && m_iStatus != ID_STATUS_AWAY) ||
- (byMessageType == MTYPE_AUTOBUSY && m_iStatus != ID_STATUS_OCCUPIED) ||
- (byMessageType == MTYPE_AUTONA && m_iStatus != ID_STATUS_NA) ||
- (byMessageType == MTYPE_AUTODND && m_iStatus != ID_STATUS_DND) ||
- (byMessageType == MTYPE_AUTOFFC && m_iStatus != ID_STATUS_FREECHAT))
- {
- return FALSE;
- }
-
- if (hContact != INVALID_HANDLE_VALUE && m_iStatus==ID_STATUS_INVISIBLE &&
- getSettingWord(hContact, "ApparentMode", 0) != ID_STATUS_ONLINE)
- {
- if (!getSettingByte(hContact, "TemporaryVisible", 0))
- { // Allow request to temporary visible contacts
- return FALSE;
- }
- }
-
- // All OK!
- return TRUE;
-}
-
-
-void __fastcall SAFE_DELETE(MZeroedObject **p)
-{
- if (*p)
- {
- delete *p;
- *p = NULL;
- }
-}
-
-
-void __fastcall SAFE_DELETE(lockable_struct **p)
-{
- if (*p)
- {
- (*p)->_Release();
- *p = NULL;
- }
-}
-
-
-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);
-}
-
-
-DWORD ICQWaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds, int bWaitAlways)
-{
- DWORD dwResult;
-
- do { // will get WAIT_IO_COMPLETION for QueueUserAPC(), ignore it unless terminating
- dwResult = WaitForSingleObjectEx(hObject, dwMilliseconds, TRUE);
- } while (dwResult == WAIT_IO_COMPLETION && (bWaitAlways || !Miranda_Terminated()));
-
- return dwResult;
-}
-
-
-HANDLE NetLib_OpenConnection(HANDLE hUser, const char* szIdent, NETLIBOPENCONNECTION* nloc)
-{
- Netlib_Logf(hUser, "%sConnecting to %s:%u", szIdent?szIdent:"", nloc->szHost, nloc->wPort);
-
- nloc->cbSize = sizeof(NETLIBOPENCONNECTION);
- nloc->flags |= NLOCF_V2;
-
- return (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc);
-}
-
-
-HANDLE CIcqProto::NetLib_BindPort(NETLIBNEWCONNECTIONPROC_V2 pFunc, void* lParam, WORD* pwPort, DWORD* pdwIntIP)
-{
- NETLIBBIND nlb = {0};
-
- nlb.cbSize = sizeof(NETLIBBIND);
- nlb.pfnNewConnectionV2 = pFunc;
- nlb.pExtra = lParam;
- SetLastError(ERROR_INVALID_PARAMETER); // this must be here - NetLib does not set any error :((
-
- HANDLE hBoundPort = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)m_hDirectNetlibUser, (LPARAM)&nlb);
-
- if (pwPort) *pwPort = nlb.wPort;
- if (pdwIntIP) *pdwIntIP = nlb.dwInternalIP;
-
- return hBoundPort;
-}
-
-
-void NetLib_CloseConnection(HANDLE *hConnection, int bServerConn)
-{
- if (*hConnection)
- {
- NetLib_SafeCloseHandle(hConnection);
-
- if (bServerConn)
- FreeGatewayIndex(*hConnection);
- }
-}
-
-
-void NetLib_SafeCloseHandle(HANDLE *hConnection)
-{
- if (*hConnection)
- {
- Netlib_CloseHandle(*hConnection);
- *hConnection = NULL;
- }
-}
-
-
-int CIcqProto::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)m_hServerNetlibUser,(LPARAM)szText);
-}
-
-int CIcqProto::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)m_hDirectNetlibUser,(LPARAM)szText);
-}
-
-int CIcqProto::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 = m_hDirectNetlibUser;
- else
- hNetlib = m_hServerNetlibUser;
-
- return CallService(MS_NETLIB_LOG,(WPARAM)hNetlib,(LPARAM)szText);
-}
-
-int CIcqProto::BroadcastAck(HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam)
-{
- ACKDATA ack={0};
-
- ack.cbSize = sizeof(ACKDATA);
- ack.szModule = m_szModuleName;
- ack.hContact = hContact;
- ack.type = type;
- ack.result = result;
- ack.hProcess = hProcess;
- ack.lParam = lParam;
- return CallService(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack);
-}
-
-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((void**)&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((void**)&usrc);
- }
- else
- buf[0] = '\0';
-
- return buf;
-}
-
-void CIcqProto::ForkThread( IcqThreadFunc pFunc, void* arg )
-{
- CloseHandle(( HANDLE )mir_forkthreadowner(( pThreadFuncOwner )*( void** )&pFunc, this, arg, NULL ));
-}
-
-HANDLE CIcqProto::ForkThreadEx( IcqThreadFunc pFunc, void* arg, UINT* threadID )
-{
- return ( HANDLE )mir_forkthreadowner(( pThreadFuncOwner )*( void** )&pFunc, this, arg, threadID );
-}
-
-
-char* CIcqProto::GetUserStoredPassword(char *szBuffer, int cbSize)
-{
- if (!getSettingStringStatic(NULL, "Password", szBuffer, cbSize))
- {
- CallService(MS_DB_CRYPT_DECODESTRING, strlennull(szBuffer) + 1, (LPARAM)szBuffer);
-
- if (strlennull(szBuffer))
- return szBuffer;
- }
- return NULL;
-}
-
-
-char* CIcqProto::GetUserPassword(BOOL bAlways)
-{
- if (m_szPassword[0] != '\0' && (m_bRememberPwd || bAlways))
- return m_szPassword;
-
- if (GetUserStoredPassword(m_szPassword, sizeof(m_szPassword)))
- {
- m_bRememberPwd = TRUE;
-
- return m_szPassword;
- }
-
- return NULL;
-}
-
-
-WORD CIcqProto::GetMyStatusFlags()
-{
- WORD wFlags = 0;
-
- // Webaware setting bit flag
- if (getSettingByte(NULL, "WebAware", 0))
- wFlags |= STATUS_WEBAWARE;
-
- // DC setting bit flag
- switch (getSettingByte(NULL, "DCType", 0))
- {
- case 0:
- break;
-
- case 1:
- wFlags |= STATUS_DCCONT;
- break;
-
- case 2:
- wFlags |= STATUS_DCAUTH;
- break;
-
- default:
- wFlags |= STATUS_DCDISABLED;
- break;
- }
- return wFlags;
-}
-
-
-int IsValidRelativePath(const char *filename)
-{
- if (strstrnull(filename, "..\\") || strstrnull(filename, "../") ||
- strstrnull(filename, ":\\") || strstrnull(filename, ":/") ||
- filename[0] == '\\' || filename[0] == '/')
- return 0; // Contains malicious chars, Failure
-
- return 1; // Success
-}
-
-
-const char* ExtractFileName(const char *fullname)
-{
- const char *szFileName;
-
- // already is only filename
- if (((szFileName = strrchr(fullname, '\\')) == NULL) && ((szFileName = strrchr(fullname, '/')) == NULL))
- return fullname;
-
- return szFileName + 1; // skip backslash
-}
-
-
-char* FileNameToUtf(const TCHAR *filename)
-{
- // reasonable only on NT systems
- HINSTANCE hKernel = GetModuleHandle(_T("KERNEL32"));
- DWORD (CALLBACK *RealGetLongPathName)(LPCWSTR, LPWSTR, DWORD);
-
- *(FARPROC *)&RealGetLongPathName = GetProcAddress(hKernel, "GetLongPathNameW");
-
- if (RealGetLongPathName)
- { // the function is available (it is not on old NT systems)
- WCHAR *usFileName = NULL;
- int wchars = RealGetLongPathName(filename, usFileName, 0);
- usFileName = (WCHAR*)_alloca((wchars + 1) * sizeof(WCHAR));
- RealGetLongPathName(filename, usFileName, wchars);
-
- return make_utf8_string(usFileName);
- }
- return make_utf8_string(filename);
-}
-
-
-int FileAccessUtf(const char *path, int mode)
-{
- int size = strlennull(path) + 2;
- TCHAR *szPath = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(path, szPath, size))
- return _taccess(szPath, mode);
-
- return -1;
-}
-
-
-int FileStatUtf(const char *path, struct _stati64 *buffer)
-{
- int size = strlennull(path) + 2;
- TCHAR *szPath = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(path, szPath, size))
- return _tstati64(szPath, buffer);
-
- return -1;
-}
-
-
-int MakeDirUtf(const char *dir)
-{
- int wRes = -1;
- int size = strlennull(dir) + 2;
- TCHAR *szDir = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(dir, szDir, size))
- { // _tmkdir can created only one dir at once
- wRes = _tmkdir(szDir);
- // 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
- char *szLast = (char*)strrchr(dir, '\\');
- if (!szLast) szLast = (char*)strrchr(dir, '/');
- if (szLast)
- {
- char cOld = *szLast;
-
- *szLast = '\0';
- if (!MakeDirUtf(dir))
- wRes = _tmkdir(szDir);
-
- *szLast = cOld;
- }
- }
- }
-
- return wRes;
-}
-
-
-int OpenFileUtf(const char *filename, int oflag, int pmode)
-{
- int size = strlennull(filename) + 2;
- TCHAR *szFile = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(filename, szFile, size))
- return _topen(szFile, oflag, pmode);
-
- return -1;
-}
-
-
-WCHAR *GetWindowTextUcs(HWND hWnd)
-{
- WCHAR *utext;
- int nLen = GetWindowTextLengthW(hWnd);
- utext = (WCHAR*)SAFE_MALLOC((nLen+2)*sizeof(WCHAR));
- GetWindowTextW(hWnd, utext, nLen + 1);
- return utext;
-}
-
-
-void SetWindowTextUcs(HWND hWnd, WCHAR *text)
-{
- SetWindowTextW(hWnd, text);
-}
-
-
-char* GetWindowTextUtf(HWND hWnd)
-{
- int nLen = GetWindowTextLength(hWnd);
- TCHAR *szText = (TCHAR*)_alloca((nLen + 2) * sizeof(TCHAR));
-
- GetWindowText(hWnd, 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)
-{
- int size = strlennull(szText) + 2;
- TCHAR *tszText = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(szText, tszText, size))
- SetWindowText(hWnd, tszText);
-}
-
-
-void SetDlgItemTextUtf(HWND hwndDlg, int iItem, const char *szText)
-{
- SetWindowTextUtf(GetDlgItem(hwndDlg, iItem), szText);
-}
-
-
-static int ControlAddStringUtf(HWND ctrl, DWORD msg, const char *szString)
-{
- char str[MAX_PATH];
- char *szItem = ICQTranslateUtfStatic(szString, str, MAX_PATH);
- int item = -1;
- WCHAR *wItem = make_unicode_string(szItem);
- item = SendMessage(ctrl, msg, 0, (LPARAM)wItem);
- SAFE_FREE((void**)&wItem);
- 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);
-}
-
-int MessageBoxUtf(HWND hWnd, const char *szText, const char *szCaption, UINT uType)
-{
- int res;
- char str[1024];
- char cap[MAX_PATH];
- 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((void**)&caption);
- SAFE_FREE((void**)&text);
- return res;
-}
-
-char* CIcqProto::ConvertMsgToUserSpecificAnsi(HANDLE hContact, const char* szMsg)
-{ // this takes utf-8 encoded message
- WORD wCP = getSettingWord(hContact, "CodePage", m_wAnsiCodepage);
- char* szAnsi = NULL;
-
- if (wCP != CP_ACP) // convert to proper codepage
- if (!utf8_decode_codepage(szMsg, &szAnsi, wCP))
- return NULL;
-
- return szAnsi;
-}
-
-// just broadcast generic send error with dummy cookie and return that cookie
-DWORD CIcqProto::ReportGenericSendError(HANDLE hContact, int nType, const char* szErrorMsg)
-{
- DWORD dwCookie = GenerateCookie(0);
- SendProtoAck(hContact, dwCookie, ACKRESULT_FAILED, nType, Translate(szErrorMsg));
- return dwCookie;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CIcqProto::CreateProtoService(const char* szService, IcqServiceFunc serviceProc)
-{
- char temp[MAX_PATH*2];
-
- null_snprintf(temp, sizeof(temp), "%s%s", m_szModuleName, szService);
- CreateServiceFunctionObj( temp, ( MIRANDASERVICEOBJ )*( void** )&serviceProc, this );
-}
-
-void CIcqProto::CreateProtoServiceParam(const char* szService, IcqServiceFuncParam serviceProc, LPARAM lParam)
-{
- char temp[MAX_PATH*2];
-
- null_snprintf(temp, sizeof(temp), "%s%s", m_szModuleName, szService);
- CreateServiceFunctionObjParam( temp, ( MIRANDASERVICEOBJPARAM )*( void** )&serviceProc, this, lParam );
-}
-
-
-HANDLE CIcqProto::HookProtoEvent(const char* szEvent, IcqEventFunc pFunc)
-{
- return ::HookEventObj(szEvent, (MIRANDAHOOKOBJ)*(void**)&pFunc, this);
-}
-
-
-HANDLE CIcqProto::CreateProtoEvent(const char* szEvent)
-{
- char str[MAX_PATH + 32];
- strcpy(str, m_szModuleName);
- strcat(str, szEvent);
- return CreateHookableEvent(str);
-}