summaryrefslogtreecommitdiff
path: root/protocols/IcqOscarJ/icq_servlist.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/icq_servlist.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/icq_servlist.cpp')
-rw-r--r--protocols/IcqOscarJ/icq_servlist.cpp2829
1 files changed, 0 insertions, 2829 deletions
diff --git a/protocols/IcqOscarJ/icq_servlist.cpp b/protocols/IcqOscarJ/icq_servlist.cpp
deleted file mode 100644
index b2adc4831c..0000000000
--- a/protocols/IcqOscarJ/icq_servlist.cpp
+++ /dev/null
@@ -1,2829 +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:
-//
-// Functions that handles list of used server IDs, sends low-level packets for SSI information
-//
-// -----------------------------------------------------------------------------
-#include "icqoscar.h"
-
-
-// SERVER-LIST UPDATE BOARD
-//
-
-void CIcqProto::servlistBeginOperation(int operationCount, int bImport)
-{
- if (operationCount)
- { // check if we should send operation begin packet
- if (!servlistEditCount)
- icq_sendServerBeginOperation(bImport);
- // update count of active operations
- servlistEditCount += operationCount;
-#ifdef _DEBUG
- NetLog_Server("Server-List: Begin operation processed (%d operations active)", servlistEditCount);
-#endif
- }
-}
-
-void CIcqProto::servlistEndOperation(int operationCount)
-{
- if (operationCount)
- {
- if (operationCount > servlistEditCount)
- { // sanity check
- NetLog_Server("Error: Server-List End operation is not paired!");
- operationCount = servlistEditCount;
- }
- // update count of active operations
- servlistEditCount -= operationCount;
- // check if we should send operation end packet
- if (!servlistEditCount)
- icq_sendServerEndOperation();
-#ifdef _DEBUG
- NetLog_Server("Server-List: End operation processed (%d operations active)", servlistEditCount);
-#endif
- }
-}
-
-void __cdecl CIcqProto::servlistQueueThread(void *param)
-{
- int* queueState = ( int* )param;
-
-#ifdef _DEBUG
- NetLog_Server("Server-List: Starting Update board.");
-#endif
-
- SleepEx(50, FALSE);
- // handle server-list requests queue
- servlistQueueMutex->Enter();
- while (servlistQueueCount)
- {
- ssiqueueditems* pItem = NULL;
- int bItemDouble;
- WORD wItemAction;
- icq_packet groupPacket = {0};
- icq_packet groupPacket2 = {0};
- cookie_servlist_action* pGroupCookie = NULL;
- int nEndOperations;
-
- // first check if the state is calm
- while (*queueState)
- {
- int i;
- time_t tNow = time(NULL);
- int bFound = FALSE;
-
- for (i = 0; i < servlistQueueCount; i++)
- { // check if we do not have some expired items to handle, otherwise keep sleeping
- if ((servlistQueueList[i]->tAdded + servlistQueueList[i]->dwTimeout) < tNow)
- { // got expired item, stop sleep even when changes goes on
- bFound = TRUE;
- break;
- }
- }
- if (bFound) break;
- // reset queue state, keep sleeping
- *queueState = FALSE;
- servlistQueueMutex->Leave();
- SleepEx(100, TRUE);
- servlistQueueMutex->Enter();
- }
- if (!icqOnline())
- { // do not try to send packets if offline
- servlistQueueMutex->Leave();
- SleepEx(100, TRUE);
- servlistQueueMutex->Enter();
- continue;
- }
-#ifdef _DEBUG
- NetLog_Server("Server-List: %d items in queue.", servlistQueueCount);
-#endif
- // take the oldest item (keep the board FIFO)
- pItem = servlistQueueList[0]; // take first (queue contains at least one item here)
- wItemAction = (WORD)(pItem->pItems[0]->dwOperation & SSOF_ACTIONMASK);
- bItemDouble = pItem->pItems[0]->dwOperation & SSOG_DOUBLE;
- // check item rate - too high -> sleep
- m_ratesMutex->Enter();
- {
- WORD wRateGroup = m_rates->getGroupFromSNAC(ICQ_LISTS_FAMILY, wItemAction);
- int nRateLevel = bItemDouble ? RML_IDLE_30 : RML_IDLE_10;
-
- while (m_rates->getNextRateLevel(wRateGroup) < m_rates->getLimitLevel(wRateGroup, nRateLevel))
- { // the rate is higher, keep sleeping
- int nDelay = m_rates->getDelayToLimitLevel(wRateGroup, nRateLevel);
-
- m_ratesMutex->Leave();
- // do not keep the queue frozen
- servlistQueueMutex->Leave();
- if (nDelay < 10) nDelay = 10;
-#ifdef _DEBUG
- NetLog_Server("Server-List: Delaying %dms [Rates]", nDelay);
-#endif
- SleepEx(nDelay, FALSE);
- // check if the rate is now ok
- servlistQueueMutex->Enter();
- m_ratesMutex->Enter();
- }
- }
- m_ratesMutex->Leave();
- { // setup group packet(s) & cookie
- int totalSize = 0;
- int i;
- cookie_servlist_action *pGroupCookie;
- DWORD dwGroupCookie;
- // determine the total size of the packet
- for(i = 0; i < pItem->nItems; i++)
- totalSize += pItem->pItems[i]->packet.wLen - 0x10;
-
- // process begin & end operation flags
- {
- int bImportOperation = FALSE;
- int nBeginOperations = 0;
-
- nEndOperations = 0;
- for(i = 0; i < pItem->nItems; i++)
- { // collect begin & end operation flags
- if (pItem->pItems[i]->dwOperation & SSOF_BEGIN_OPERATION)
- nBeginOperations++;
- if (pItem->pItems[i]->dwOperation & SSOF_END_OPERATION)
- nEndOperations++;
- // check if the operation is import
- if (pItem->pItems[i]->dwOperation & SSOF_IMPORT_OPERATION)
- bImportOperation = TRUE;
- }
- // really begin operation if requested
- if (nBeginOperations)
- servlistBeginOperation(nBeginOperations, bImportOperation);
- }
-
- if (pItem->nItems > 1)
- { // pack all packet's data, create group cookie
- pGroupCookie = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
- pGroupCookie->dwAction = SSA_ACTION_GROUP;
- pGroupCookie->dwGroupCount = pItem->nItems;
- pGroupCookie->pGroupItems = (cookie_servlist_action**)SAFE_MALLOC(pItem->nItems * sizeof(cookie_servlist_action*));
- for (i = 0; i < pItem->nItems; i++)
- { // build group cookie data - assign cookies datas
- pGroupCookie->pGroupItems[i] = pItem->pItems[i]->cookie;
- // release the separate cookie id
- FreeCookieByData(CKT_SERVERLIST, pItem->pItems[i]->cookie);
- }
- // allocate cookie id
- dwGroupCookie = AllocateCookie(CKT_SERVERLIST, wItemAction, 0, pGroupCookie);
- // prepare packet data
- serverPacketInit(&groupPacket, (WORD)(totalSize + 0x0A)); // FLAP size added inside
- packFNACHeader(&groupPacket, ICQ_LISTS_FAMILY, wItemAction, 0, dwGroupCookie);
- for (i = 0; i < pItem->nItems; i++)
- packBuffer(&groupPacket, pItem->pItems[i]->packet.pData + 0x10, (WORD)(pItem->pItems[i]->packet.wLen - 0x10));
-
- if (bItemDouble)
- { // prepare second packet
- wItemAction = ((servlistgroupitemdouble*)(pItem->pItems[0]))->wAction2;
- totalSize = 0;
- // determine the total size of the packet
- for(i = 0; i < pItem->nItems; i++)
- totalSize += ((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.wLen - 0x10;
-
- pGroupCookie = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
- pGroupCookie->dwAction = SSA_ACTION_GROUP;
- pGroupCookie->dwGroupCount = pItem->nItems;
- pGroupCookie->pGroupItems = (cookie_servlist_action**)SAFE_MALLOC(pItem->nItems * sizeof(cookie_servlist_action*));
- for (i = 0; i < pItem->nItems; i++)
- pGroupCookie->pGroupItems[i] = pItem->pItems[i]->cookie;
- // allocate cookie id
- dwGroupCookie = AllocateCookie(CKT_SERVERLIST, wItemAction, 0, pGroupCookie);
- // prepare packet data
- serverPacketInit(&groupPacket2, (WORD)(totalSize + 0x0A)); // FLAP size added inside
- packFNACHeader(&groupPacket2, ICQ_LISTS_FAMILY, wItemAction, 0, dwGroupCookie);
- for (i = 0; i < pItem->nItems; i++)
- packBuffer(&groupPacket2, ((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.pData + 0x10, (WORD)(((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.wLen - 0x10));
- }
- }
- else
- { // just send the one packet, do not create action group
- pGroupCookie = pItem->pItems[0]->cookie;
- memcpy(&groupPacket, &pItem->pItems[0]->packet, sizeof(icq_packet));
- if (bItemDouble)
- memcpy(&groupPacket2, &((servlistgroupitemdouble*)(pItem->pItems[0]))->packet2, sizeof(icq_packet));
- }
-
- { // remove grouped item from queue & release grouped item
- servlistQueueCount--;
- servlistQueueList[0] = servlistQueueList[servlistQueueCount];
-
- for (i = 0; i < pItem->nItems; i++)
- { // release memory
- if (pItem->nItems > 1)
- { // free the packet only if we created the group packet
- SAFE_FREE((void**)&pItem->pItems[i]->packet.pData);
- if (pItem->pItems[i]->dwOperation & SSOG_DOUBLE)
- SAFE_FREE((void**)&((servlistgroupitemdouble*)(pItem->pItems[i]))->packet2.pData);
- }
- SAFE_FREE((void**)&pItem->pItems[i]);
- break;
- }
- SAFE_FREE((void**)&pItem);
- // resize the queue
- if (servlistQueueSize > servlistQueueCount + 6)
- {
- servlistQueueSize -= 4;
- servlistQueueList = (ssiqueueditems**)SAFE_REALLOC(servlistQueueList, servlistQueueSize * sizeof(ssiqueueditems*));
- }
- }
- }
- servlistQueueMutex->Leave();
- // send group packet
- sendServPacket(&groupPacket);
- // send second group packet (if present)
- if (bItemDouble)
- sendServPacket(&groupPacket2);
- // process end operation marks
- if (nEndOperations)
- servlistEndOperation(nEndOperations);
- // loose the loop a bit
- SleepEx(100, TRUE);
- servlistQueueMutex->Enter();
- }
- // clean-up thread
- CloseHandle(servlistQueueThreadHandle);
- servlistQueueThreadHandle = NULL;
- servlistQueueMutex->Leave();
-#ifdef _DEBUG
- NetLog_Server("Server-List: Update Board ending.");
-#endif
-}
-
-void CIcqProto::servlistQueueAddGroupItem(servlistgroupitem* pGroupItem, int dwTimeout)
-{
- icq_lock l(servlistQueueMutex);
-
- { // add the packet to queue
- DWORD dwMark = pGroupItem->dwOperation & SSOF_GROUPINGMASK;
- ssiqueueditems* pItem = NULL;
-
- // try to find compatible item
- for (int i = 0; i < servlistQueueCount; i++)
- {
- if ((servlistQueueList[i]->pItems[0]->dwOperation & SSOF_GROUPINGMASK) == dwMark && servlistQueueList[i]->nItems < MAX_SERVLIST_PACKET_ITEMS)
- { // found compatible item, check if it does not contain operation for the same server-list item
- pItem = servlistQueueList[i];
-
- for (int j = 0; j < pItem->nItems; j++)
- if (pItem->pItems[j]->cookie->wContactId == pGroupItem->cookie->wContactId &&
- pItem->pItems[j]->cookie->wGroupId == pGroupItem->cookie->wGroupId)
- {
- pItem = NULL;
- break;
- }
- // cannot send two operations for the same server-list record in one packet, look for another
- if (!pItem) continue;
-
-#ifdef _DEBUG
- NetLog_Server("Server-List: Adding packet to item #%d with operation %x.", i, servlistQueueList[i]->pItems[0]->dwOperation);
-#endif
- break;
- }
- }
- if (!pItem)
- { // compatible item was not found, create new one, add to queue
- pItem = (ssiqueueditems*)SAFE_MALLOC(sizeof(ssiqueueditems));
- pItem->tAdded = time(NULL);
- pItem->dwTimeout = dwTimeout;
-
- if (servlistQueueCount == servlistQueueSize)
- { // resize the queue - it is too small
- servlistQueueSize += 4;
- servlistQueueList = (ssiqueueditems**)SAFE_REALLOC(servlistQueueList, servlistQueueSize * sizeof(ssiqueueditems*));
- }
- // really add to queue
- servlistQueueList[servlistQueueCount++] = pItem;
-#ifdef _DEBUG
- NetLog_Server("Server-List: Adding new item to queue.");
-#endif
- }
- else if (pItem->dwTimeout > dwTimeout)
- { // if the timeout of currently added packet is shorter, update the previous one
- pItem->dwTimeout = dwTimeout;
- }
- // add GroupItem to queueditems (pItem)
- pItem->pItems[pItem->nItems++] = pGroupItem;
- }
- // wake up board thread (keep sleeping or start new one)
- if (!servlistQueueThreadHandle)
- {
- // create new board thread
- servlistQueueThreadHandle = ForkThreadEx( &CIcqProto::servlistQueueThread, &servlistQueueState );
- }
- else // signal thread, that queue was changed during sleep
- servlistQueueState = TRUE;
-}
-
-int CIcqProto::servlistHandlePrimitives(DWORD dwOperation)
-{
- if (dwOperation & SSO_BEGIN_OPERATION)
- { // operation starting, no action ready yet
- servlistBeginOperation(1, dwOperation & SSOF_IMPORT_OPERATION);
- return TRUE;
- }
- else if (dwOperation & SSO_END_OPERATION)
- { // operation ending without action
- servlistEndOperation(1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void CIcqProto::servlistPostPacket(icq_packet* packet, DWORD dwCookie, DWORD dwOperation, DWORD dwTimeout)
-{
- cookie_servlist_action* pCookie;
-
- if (servlistHandlePrimitives(dwOperation))
- return;
-
- if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
- return; // invalid cookie
-
- if (dwOperation & SSOF_SEND_DIRECTLY)
- { // send directly - this is for some special cases
- // begin operation if requested
- if (dwOperation & SSOF_BEGIN_OPERATION)
- servlistBeginOperation(1, dwOperation & SSOF_IMPORT_OPERATION);
-
- // send the packet
- sendServPacket(packet);
-
- // end operation if requested
- if (dwOperation & SSOF_END_OPERATION)
- servlistEndOperation(1);
- }
- else
- { // add to server-list update board
- servlistgroupitem* pGroupItem;
-
- // prepare group item
- pGroupItem = (servlistgroupitem*)SAFE_MALLOC(sizeof(servlistgroupitem));
- pGroupItem->dwOperation = dwOperation;
- pGroupItem->cookie = pCookie;
- // packet data are alloced, keep them until they are sent
- memcpy(&pGroupItem->packet, packet, sizeof(icq_packet));
-
- servlistQueueAddGroupItem(pGroupItem, dwTimeout);
- }
-}
-
-void CIcqProto::servlistPostPacketDouble(icq_packet* packet1, DWORD dwCookie, DWORD dwOperation, DWORD dwTimeout, icq_packet* packet2, WORD wAction2)
-{
- cookie_servlist_action* pCookie;
-
- if (servlistHandlePrimitives(dwOperation))
- return;
-
- if (!FindCookie(dwCookie, NULL, (void**)&pCookie))
- return; // invalid cookie
-
- if (dwOperation & SSOF_SEND_DIRECTLY)
- { // send directly - this is for some special cases
- // begin operation if requested
- if (dwOperation & SSOF_BEGIN_OPERATION)
- servlistBeginOperation(1, dwOperation & SSOF_IMPORT_OPERATION);
-
- // send the packets
- sendServPacket(packet1);
- sendServPacket(packet2);
-
- // end operation if requested
- if (dwOperation & SSOF_END_OPERATION)
- servlistEndOperation(1);
- }
- else
- { // add to server-list update board
- servlistgroupitemdouble* pGroupItem;
-
- // prepare group item
- pGroupItem = (servlistgroupitemdouble*)SAFE_MALLOC(sizeof(servlistgroupitemdouble));
- pGroupItem->dwOperation = dwOperation;
- pGroupItem->cookie = pCookie;
- pGroupItem->wAction2 = wAction2;
- // packets data are alloced, keep them until they are sent
- memcpy(&pGroupItem->packet, packet1, sizeof(icq_packet));
- memcpy(&pGroupItem->packet2, packet2, sizeof(icq_packet));
-
- servlistQueueAddGroupItem((servlistgroupitem*)pGroupItem, dwTimeout);
- }
-}
-
-void CIcqProto::servlistProcessLogin()
-{
- // reset edit state counter
- servlistEditCount = 0;
-
- /// TODO: preserve queue state in DB! restore here!
-
- // if the server-list queue contains items and thread is not running, start it
- if (servlistQueueCount && !servlistQueueThreadHandle)
- servlistQueueThreadHandle = ForkThreadEx( &CIcqProto::servlistQueueThread, &servlistQueueState );
-}
-
-// HERE ENDS SERVER-LIST UPDATE BOARD IMPLEMENTATION //
-///////////////////////////////////////////////////////
-//===================================================//
-
-// PENDING SERVER-LIST OPERATIONS
-//
-#define ITEM_PENDING_CONTACT 0x01
-#define ITEM_PENDING_GROUP 0x02
-
-#define CALLBACK_RESULT_CONTINUE 0x00
-#define CALLBACK_RESULT_POSTPONE 0x0D
-#define CALLBACK_RESULT_PURGE 0x10
-
-
-#define SPOF_AUTO_CREATE_ITEM 0x01
-
-int CIcqProto::servlistPendingFindItem(int nType, HANDLE hContact, const char *pszGroup)
-{
- if (servlistPendingList)
- for (int i = 0; i < servlistPendingCount; i++)
- if (servlistPendingList[i]->nType == nType)
- {
- if (((nType == ITEM_PENDING_CONTACT) && (servlistPendingList[i]->hContact == hContact)) ||
- ((nType == ITEM_PENDING_GROUP) && (!strcmpnull(servlistPendingList[i]->szGroup, pszGroup))))
- return i;
- }
- return -1;
-}
-
-
-void CIcqProto::servlistPendingAddItem(servlistpendingitem *pItem)
-{
- if (servlistPendingCount >= servlistPendingSize) // add new
- {
- servlistPendingSize += 10;
- servlistPendingList = (servlistpendingitem**)SAFE_REALLOC(servlistPendingList, servlistPendingSize * sizeof(servlistpendingitem*));
- }
-
- servlistPendingList[servlistPendingCount++] = pItem;
-}
-
-
-servlistpendingitem* CIcqProto::servlistPendingRemoveItem(int nType, HANDLE hContact, const char *pszGroup)
-{ // unregister pending item, trigger pending operations
- int iItem;
- servlistpendingitem *pItem = NULL;
-
- icq_lock l(servlistMutex);
-
- if ((iItem = servlistPendingFindItem(nType, hContact, pszGroup)) != -1)
- { // found, remove from the pending list
- pItem = servlistPendingList[iItem];
-
- servlistPendingList[iItem] = servlistPendingList[--servlistPendingCount];
-
- if (servlistPendingCount + 10 < servlistPendingSize)
- {
- servlistPendingSize -= 5;
- servlistPendingList = (servlistpendingitem**)SAFE_REALLOC(servlistPendingList, servlistPendingSize * sizeof(servlistpendingitem*));
- }
- // was the first operation was created automatically to postpone ItemAdd?
- if (pItem->operations && pItem->operations[0].flags & SPOF_AUTO_CREATE_ITEM)
- { // yes, add new item
- servlistpendingitem *pNewItem = (servlistpendingitem*)SAFE_MALLOC(sizeof(servlistpendingitem));
-
- if (pNewItem)
- { // move the remaining operations
-#ifdef _DEBUG
- if (pItem->nType == ITEM_PENDING_CONTACT)
- NetLog_Server("Server-List: Resuming contact %x operation.", pItem->hContact);
- else
- NetLog_Server("Server-List: Resuming group \"%s\" operation.", pItem->szGroup);
-#endif
-
- pNewItem->nType = pItem->nType;
- pNewItem->hContact = pItem->hContact;
- pNewItem->szGroup = null_strdup(pItem->szGroup);
- pNewItem->wContactID = pItem->wContactID;
- pNewItem->wGroupID = pItem->wGroupID;
- pNewItem->operationsCount = pItem->operationsCount - 1;
- pNewItem->operations = (servlistpendingoperation*)SAFE_MALLOC(pNewItem->operationsCount * sizeof(servlistpendingoperation));
- memcpy(pNewItem->operations, pItem->operations + 1, pNewItem->operationsCount * sizeof(servlistpendingoperation));
- pItem->operationsCount = 1;
-
- servlistPendingAddItem(pNewItem);
- // clear the flag
- pItem->operations[0].flags &= ~SPOF_AUTO_CREATE_ITEM;
- }
- }
- }
-#ifdef _DEBUG
- else
- NetLog_Server("Server-List Error: Trying to remove non-existing pending %s.", nType == ITEM_PENDING_CONTACT ? "contact" : "group");
-#endif
-
- return pItem;
-}
-
-
-void CIcqProto::servlistPendingAddContactOperation(HANDLE hContact, LPARAM param, PENDING_CONTACT_CALLBACK callback, DWORD flags)
-{ // add postponed operation (add contact, update contact, regroup resume, etc.)
- // - after contact is added
- int iItem;
- servlistpendingitem *pItem = NULL;
-
- icq_lock l(servlistMutex);
-
- if ((iItem = servlistPendingFindItem(ITEM_PENDING_CONTACT, hContact, NULL)) != -1)
- pItem = servlistPendingList[iItem];
-
- if (pItem)
- {
- int iOperation = pItem->operationsCount++;
-
- pItem->operations = (servlistpendingoperation*)SAFE_REALLOC(pItem->operations, pItem->operationsCount * sizeof(servlistpendingoperation));
- pItem->operations[iOperation].param = param;
- pItem->operations[iOperation].callback = (PENDING_GROUP_CALLBACK)callback;
- pItem->operations[iOperation].flags = flags;
- }
- else
- {
- NetLog_Server("Server-List Error: Trying to add pending operation to a non existing contact.");
- }
-}
-
-
-void CIcqProto::servlistPendingAddGroupOperation(const char *pszGroup, LPARAM param, PENDING_GROUP_CALLBACK callback, DWORD flags)
-{ // add postponed operation - after group is added
- int iItem;
- servlistpendingitem *pItem = NULL;
-
- icq_lock l(servlistMutex);
-
- if ((iItem = servlistPendingFindItem(ITEM_PENDING_GROUP, NULL, pszGroup)) != -1)
- pItem = servlistPendingList[iItem];
-
- if (pItem)
- {
- int iOperation = pItem->operationsCount++;
-
- pItem->operations = (servlistpendingoperation*)SAFE_REALLOC(pItem->operations, pItem->operationsCount * sizeof(servlistpendingoperation));
- pItem->operations[iOperation].param = param;
- pItem->operations[iOperation].callback = callback;
- pItem->operations[iOperation].flags = flags;
- }
- else
- {
- NetLog_Server("Server-List Error: Trying to add pending operation to a non existing group.");
- }
-}
-
-
-int CIcqProto::servlistPendingAddContact(HANDLE hContact, WORD wContactID, WORD wGroupID, LPARAM param, PENDING_CONTACT_CALLBACK callback, int bDoInline, LPARAM operationParam, PENDING_CONTACT_CALLBACK operationCallback)
-{
- int iItem;
- servlistpendingitem *pItem = NULL;
-
- servlistMutex->Enter();
-
- if ((iItem = servlistPendingFindItem(ITEM_PENDING_CONTACT, hContact, NULL)) != -1)
- pItem = servlistPendingList[iItem];
-
- if (pItem)
- {
-#ifdef _DEBUG
- NetLog_Server("Server-List: Pending contact %x already in list; adding as operation.", hContact);
-#endif
- servlistPendingAddContactOperation(hContact, param, callback, SPOF_AUTO_CREATE_ITEM);
-
- if (operationCallback)
- servlistPendingAddContactOperation(hContact, operationParam, operationCallback, 0);
-
- servlistMutex->Leave();
-
- return 0; // Pending
- }
-
-#ifdef _DEBUG
- NetLog_Server("Server-List: Starting contact %x operation.", hContact);
-#endif
-
- pItem = (servlistpendingitem *)SAFE_MALLOC(sizeof(servlistpendingitem));
- pItem->nType = ITEM_PENDING_CONTACT;
- pItem->hContact = hContact;
- pItem->wContactID = wContactID;
- pItem->wGroupID = wGroupID;
-
- servlistPendingAddItem(pItem);
-
- if (operationCallback)
- servlistPendingAddContactOperation(hContact, operationParam, operationCallback, 0);
-
- servlistMutex->Leave();
-
- if (bDoInline)
- { // not postponed, called directly if requested
- (this->*callback)(hContact, wContactID, wGroupID, param, PENDING_RESULT_INLINE);
- }
-
- return 1; // Ready
-}
-
-
-int CIcqProto::servlistPendingAddGroup(const char *pszGroup, WORD wGroupID, LPARAM param, PENDING_GROUP_CALLBACK callback, int bDoInline, LPARAM operationParam, PENDING_GROUP_CALLBACK operationCallback)
-{
- int iItem;
- servlistpendingitem *pItem = NULL;
-
- servlistMutex->Enter();
-
- if ((iItem = servlistPendingFindItem(ITEM_PENDING_GROUP, NULL, pszGroup)) != -1)
- pItem = servlistPendingList[iItem];
-
- if (pItem)
- {
-#ifdef _DEBUG
- NetLog_Server("Server-List: Pending group \"%s\" already in list; adding as operation.", pszGroup);
-#endif
- servlistPendingAddGroupOperation(pszGroup, param, callback, SPOF_AUTO_CREATE_ITEM);
-
- if (operationCallback)
- servlistPendingAddGroupOperation(pszGroup, operationParam, operationCallback, 0);
-
- servlistMutex->Leave();
-
- return 0; // Pending
- }
-
-#ifdef _DEBUG
- NetLog_Server("Server-List: Starting group \"%s\" operation.", pszGroup);
-#endif
-
- pItem = (servlistpendingitem *)SAFE_MALLOC(sizeof(servlistpendingitem));
- pItem->nType = ITEM_PENDING_GROUP;
- pItem->szGroup = null_strdup(pszGroup);
- pItem->wGroupID = wGroupID;
-
- servlistPendingAddItem(pItem);
-
- if (operationCallback)
- servlistPendingAddGroupOperation(pszGroup, operationParam, operationCallback, 0);
-
- servlistMutex->Leave();
-
- if (bDoInline)
- { // not postponed, called directly if requested
- (this->*callback)(pszGroup, wGroupID, param, PENDING_RESULT_INLINE);
- }
-
- return 1; // Ready
-}
-
-
-void CIcqProto::servlistPendingRemoveContact(HANDLE hContact, WORD wContactID, WORD wGroupID, int nResult)
-{
-#ifdef _DEBUG
- NetLog_Server("Server-List: %s contact %x operation.", (nResult != PENDING_RESULT_PURGE) ? "Ending" : "Purging", hContact);
-#endif
-
- servlistpendingitem *pItem = servlistPendingRemoveItem(ITEM_PENDING_CONTACT, hContact, NULL);
-
- if (pItem)
- { // process pending operations
- if (pItem->operations)
- {
- for (int i = 0; i < pItem->operationsCount; i++)
- {
- int nCallbackState = (this->*(PENDING_CONTACT_CALLBACK)(pItem->operations[i].callback))(hContact, wContactID, wGroupID, pItem->operations[i].param, nResult);
-
- if (nResult != PENDING_RESULT_PURGE && nCallbackState == CALLBACK_RESULT_POSTPONE)
- { // any following pending operations cannot be processed now, move them to the new pending contact
- for (int j = i + 1; j < pItem->operationsCount; j++)
- servlistPendingAddContactOperation(hContact, pItem->operations[j].param, (PENDING_CONTACT_CALLBACK)(pItem->operations[j].callback), pItem->operations[j].flags);
- break;
- }
- else if (nCallbackState == CALLBACK_RESULT_PURGE)
- { // purge all following operations - fatal failure occured
- nResult = PENDING_RESULT_PURGE;
- }
- }
- SAFE_FREE((void**)&pItem->operations);
- }
- // release item's memory
- SAFE_FREE((void**)&pItem);
- }
- else
- NetLog_Server("Server-List Error: Trying to remove a non existing pending contact.");
-}
-
-
-void CIcqProto::servlistPendingRemoveGroup(const char *pszGroup, WORD wGroupID, int nResult)
-{
-#ifdef _DEBUG
- NetLog_Server("Server-List: %s group \"%s\" operation.", (nResult != PENDING_RESULT_PURGE) ? "Ending" : "Purging", pszGroup);
-#endif
-
- servlistpendingitem *pItem = servlistPendingRemoveItem(ITEM_PENDING_GROUP, NULL, pszGroup);
-
- if (pItem)
- { // process pending operations
- if (pItem->operations)
- {
- for (int i = 0; i < pItem->operationsCount; i++)
- {
- int nCallbackState = (this->*pItem->operations[i].callback)(pItem->szGroup, wGroupID, pItem->operations[i].param, nResult);
-
- if (nResult != PENDING_RESULT_PURGE && nCallbackState == CALLBACK_RESULT_POSTPONE)
- { // any following pending operations cannot be processed now, move them to the new pending group
- for (int j = i + 1; j < pItem->operationsCount; j++)
- servlistPendingAddGroupOperation(pItem->szGroup, pItem->operations[j].param, pItem->operations[j].callback, pItem->operations[j].flags);
- break;
- }
- else if (nCallbackState == CALLBACK_RESULT_PURGE)
- { // purge all following operations - fatal failure occured
- nResult = PENDING_RESULT_PURGE;
- }
- }
- SAFE_FREE((void**)&pItem->operations);
- }
- // release item's memory
- SAFE_FREE((void**)&pItem->szGroup);
- SAFE_FREE((void**)&pItem);
- }
- else
- NetLog_Server("Server-List Error: Trying to remove a non existing pending group.");
-}
-
-
-// Remove All pending operations
-void CIcqProto::servlistPendingFlushOperations()
-{
- icq_lock l(servlistMutex);
-
- for (int i = servlistPendingCount; i; i--)
- { // purge all items
- servlistpendingitem *pItem = servlistPendingList[i - 1];
-
- if (pItem->nType == ITEM_PENDING_CONTACT)
- servlistPendingRemoveContact(pItem->hContact, 0, 0, PENDING_RESULT_PURGE);
- else if (pItem->nType == ITEM_PENDING_GROUP)
- servlistPendingRemoveGroup(pItem->szGroup, 0, PENDING_RESULT_PURGE);
- }
- // release the list completely
- SAFE_FREE((void**)&servlistPendingList);
- servlistPendingCount = 0;
- servlistPendingSize = 0;
-}
-
-// END OF SERVER-LIST PENDING OPERATIONS
-////
-
-
-// used for adding new contacts to list - sync with visible items
-void CIcqProto::AddJustAddedContact(HANDLE hContact)
-{
- icq_lock l(servlistMutex);
-
- if (nJustAddedCount >= nJustAddedSize)
- {
- nJustAddedSize += 10;
- pdwJustAddedList = (HANDLE*)SAFE_REALLOC(pdwJustAddedList, nJustAddedSize * sizeof(HANDLE));
- }
-
- pdwJustAddedList[nJustAddedCount] = hContact;
- nJustAddedCount++;
-}
-
-
-// was the contact added during this serv-list load
-BOOL CIcqProto::IsContactJustAdded(HANDLE hContact)
-{
- icq_lock l(servlistMutex);
-
- if (pdwJustAddedList)
- {
- for (int i = 0; i<nJustAddedCount; i++)
- {
- if (pdwJustAddedList[i] == hContact)
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-void CIcqProto::FlushJustAddedContacts()
-{
- icq_lock l(servlistMutex);
-
- SAFE_FREE((void**)&pdwJustAddedList);
- nJustAddedSize = 0;
- nJustAddedCount = 0;
-}
-
-
-// Add a server ID to the list of reserved IDs.
-// To speed up the process, no checks is done, if
-// you try to reserve an ID twice, it will be added again.
-// You should call CheckServerID before reserving an ID.
-void CIcqProto::ReserveServerID(WORD wID, int bGroupType, int bFlags)
-{
- servlistMutex->Enter();
- if (nServerIDListCount >= nServerIDListSize)
- {
- nServerIDListSize += 100;
- pdwServerIDList = (DWORD*)SAFE_REALLOC(pdwServerIDList, nServerIDListSize * sizeof(DWORD));
- }
-
- pdwServerIDList[nServerIDListCount] = wID | (bGroupType & 0x00FF0000) | (bFlags & 0xFF000000);
- nServerIDListCount++;
- servlistMutex->Leave();
-
- if (!bIsSyncingCL)
- StoreServerIDs();
-}
-
-
-// Remove a server ID from the list of reserved IDs.
-// Used for deleting contacts and other modifications.
-void CIcqProto::FreeServerID(WORD wID, int bGroupType)
-{
- DWORD dwId = wID | (bGroupType & 0x00FF0000);
-
- icq_lock l(servlistMutex);
-
- if (pdwServerIDList)
- {
- for (int i = 0; i<nServerIDListCount; i++)
- {
- if ((pdwServerIDList[i] & 0x00FFFFFF) == dwId)
- { // we found it, so remove
- for (int j = i+1; j<nServerIDListCount; j++)
- pdwServerIDList[j-1] = pdwServerIDList[j];
-
- nServerIDListCount--;
- }
- }
- }
-}
-
-
-// Returns true if dwID is reserved
-BOOL CIcqProto::CheckServerID(WORD wID, unsigned int wCount)
-{
- icq_lock l(servlistMutex);
-
- if (pdwServerIDList)
- {
- for (int i = 0; i<nServerIDListCount; i++)
- {
- if (((pdwServerIDList[i] & 0xFFFF) >= wID) && ((pdwServerIDList[i] & 0xFFFF) <= wID + wCount))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void CIcqProto::FlushServerIDs()
-{
- icq_lock l(servlistMutex);
-
- SAFE_FREE((void**)&pdwServerIDList);
- nServerIDListCount = 0;
- nServerIDListSize = 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct GroupReserveIdsEnumParam
-{
- CIcqProto *ppro;
- char *szModule;
-};
-
-static int GroupReserveIdsEnumProc(const char *szSetting,LPARAM lParam)
-{
- if (szSetting && strlennull(szSetting)<5)
- {
- // it is probably server group
- GroupReserveIdsEnumParam *param = (GroupReserveIdsEnumParam*)lParam;
- char val[MAX_PATH+2]; // dummy
-
- DBVARIANT dbv = {DBVT_DELETED};
- dbv.type = DBVT_ASCIIZ;
- dbv.pszVal = val;
- dbv.cchVal = MAX_PATH;
-
- DBCONTACTGETSETTING cgs;
- cgs.szModule = param->szModule;
- cgs.szSetting = szSetting;
- cgs.pValue = &dbv;
- if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC,(WPARAM)NULL,(LPARAM)&cgs))
- { // we failed to read setting, try also utf8 - DB bug
- dbv.type = DBVT_UTF8;
- dbv.pszVal = val;
- dbv.cchVal = MAX_PATH;
- if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC,(WPARAM)NULL,(LPARAM)&cgs))
- return 0; // we failed also, invalid setting
- }
- if (dbv.type != DBVT_ASCIIZ)
- { // it is not a cached server-group name
- return 0;
- }
- param->ppro->ReserveServerID((WORD)strtoul(szSetting, NULL, 0x10), SSIT_GROUP, 0);
-#ifdef _DEBUG
- param->ppro->NetLog_Server("Loaded group %u:'%s'", strtoul(szSetting, NULL, 0x10), val);
-#endif
- }
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Load all known server IDs from DB to list
-void CIcqProto::LoadServerIDs()
-{
- WORD wSrvID;
- int nGroups = 0, nContacts = 0, nPermits = 0, nDenys = 0, nIgnores = 0, nUnhandled = 0;
-
- servlistMutex->Enter();
- if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_AVATAR, 0))
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_PHOTO, 0))
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_PRIVACY, 0))
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- if (wSrvID = getSettingWord(NULL, DBSETTING_SERVLIST_METAINFO, 0))
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- if (wSrvID = getSettingWord(NULL, "SrvImportID", 0))
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
-
- DBCONTACTENUMSETTINGS dbces;
- int nStart = nServerIDListCount;
-
- char szModule[MAX_PATH];
- null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
-
- GroupReserveIdsEnumParam param = { this, szModule };
- dbces.pfnEnumProc = &GroupReserveIdsEnumProc;
- dbces.szModule = szModule;
- dbces.lParam = (LPARAM)&param;
- CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
-
- nGroups = nServerIDListCount - nStart;
-
- HANDLE hContact = FindFirstContact();
-
- while (hContact)
- { // search all our contacts, reserve their server IDs
- if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0))
- {
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- nContacts++;
- }
- if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_DENY, 0))
- {
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- nDenys++;
- }
- if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_PERMIT, 0))
- {
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- nPermits++;
- }
- if (wSrvID = getSettingWord(hContact, DBSETTING_SERVLIST_IGNORE, 0))
- {
- ReserveServerID(wSrvID, SSIT_ITEM, 0);
- nIgnores++;
- }
-
- hContact = FindNextContact(hContact);
- }
- servlistMutex->Leave();
-
- DBVARIANT dbv = {0};
- if (!getSetting(NULL, DBSETTING_SERVLIST_UNHANDLED, &dbv))
- {
- int dataLen = dbv.cpbVal;
- BYTE *pData = dbv.pbVal;
-
- while (dataLen >= 4)
- {
- BYTE bGroupType;
- BYTE bFlags;
-
- unpackLEWord(&pData, &wSrvID);
- unpackByte(&pData, &bGroupType);
- unpackByte(&pData, &bFlags);
-
- ReserveServerID(wSrvID, bGroupType, bFlags);
- dataLen -= 4;
- nUnhandled++;
- }
-
- ICQFreeVariant(&dbv);
- }
-
- NetLog_Server("Loaded SSI: %d contacts, %d groups, %d permit, %d deny, %d ignore, %d unknown items.", nContacts, nGroups, nPermits, nDenys, nIgnores, nUnhandled);
-}
-
-
-void CIcqProto::StoreServerIDs() /// TODO: allow delayed
-{
- BYTE *pUnhandled = NULL;
- int cbUnhandled = 0;
-
- servlistMutex->Enter();
- if (pdwServerIDList)
- for (int i = 0; i<nServerIDListCount; i++)
- if ((pdwServerIDList[i] & 0xFF000000) == SSIF_UNHANDLED)
- {
- ppackLEWord(&pUnhandled, &cbUnhandled, pdwServerIDList[i] & 0xFFFF);
- ppackByte(&pUnhandled, &cbUnhandled, (pdwServerIDList[i] & 0x00FF0000) >> 0x10);
- ppackByte(&pUnhandled, &cbUnhandled, (pdwServerIDList[i] & 0xFF000000) >> 0x18);
- }
- servlistMutex->Leave();
-
- if (pUnhandled)
- setSettingBlob(NULL, DBSETTING_SERVLIST_UNHANDLED, pUnhandled, cbUnhandled);
- else
- deleteSetting(NULL, DBSETTING_SERVLIST_UNHANDLED);
-
- SAFE_FREE((void**)&pUnhandled);
-}
-
-
-// Generate server ID with wCount IDs free after it, for sub-groups.
-WORD CIcqProto::GenerateServerID(int bGroupType, int bFlags, int wCount)
-{
- WORD wId;
-
- while (TRUE)
- {
- // Randomize a new ID
- // Max value is probably 0x7FFF, lowest value is probably 0x0001 (generated by Icq2Go)
- // We use range 0x1000-0x7FFF.
- wId = (WORD)RandRange(0x1000, 0x7FFF);
-
- if (!CheckServerID(wId, wCount))
- break;
- }
-
- ReserveServerID(wId, bGroupType, bFlags);
-
- return wId;
-}
-
-
-/***********************************************
-*
-* --- Low-level packet sending functions ---
-*
-*/
-
-struct doubleServerItemObject
-{
- WORD wAction;
- icq_packet packet;
-};
-
-DWORD CIcqProto::icq_sendServerItem(DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wItemId, const char *szName, BYTE *pTLVs, int nTlvLength, WORD wItemType, DWORD dwOperation, DWORD dwTimeout, void **doubleObject)
-{ // generic packet
- icq_packet packet;
- int nNameLen;
- WORD wTLVlen = (WORD)nTlvLength;
-
- // Prepare item name length
- nNameLen = strlennull(szName);
-
- // Build the packet
- serverPacketInit(&packet, (WORD)(nNameLen + 20 + wTLVlen));
- packFNACHeader(&packet, ICQ_LISTS_FAMILY, wAction, 0, dwCookie);
- packWord(&packet, (WORD)nNameLen);
- if (nNameLen)
- packBuffer(&packet, (LPBYTE)szName, (WORD)nNameLen);
- packWord(&packet, wGroupId);
- packWord(&packet, wItemId);
- packWord(&packet, wItemType);
- packWord(&packet, wTLVlen);
- if (wTLVlen)
- packBuffer(&packet, pTLVs, wTLVlen);
-
- if (!doubleObject)
- { // Send the packet and return the cookie
- servlistPostPacket(&packet, dwCookie, dwOperation | wAction, dwTimeout);
- }
- else
- {
- if (*doubleObject)
- { // Send both packets and return the cookie
- doubleServerItemObject* helper = (doubleServerItemObject*)*doubleObject;
-
- servlistPostPacketDouble(&helper->packet, dwCookie, dwOperation | helper->wAction, dwTimeout, &packet, wAction);
- SAFE_FREE(doubleObject);
- }
- else
- { // Create helper object, return the cookie
- doubleServerItemObject* helper = (doubleServerItemObject*)SAFE_MALLOC(sizeof(doubleServerItemObject));
-
- if (helper)
- {
- helper->wAction = wAction;
- memcpy(&helper->packet, &packet, sizeof(icq_packet));
- *doubleObject = helper;
- }
- else // memory alloc failed
- return 0;
- }
- }
-
- // Force reload of server-list after change
- setSettingWord(NULL, "SrvRecordCount", 0);
-
- return dwCookie;
-}
-
-
-DWORD CIcqProto::icq_sendServerContact(HANDLE hContact, DWORD dwCookie, WORD wAction, WORD wGroupId, WORD wContactId, DWORD dwOperation, DWORD dwTimeout, void **doubleObject)
-{
- DWORD dwUin;
- uid_str szUid;
- icq_packet pBuffer;
- char *szNick = NULL, *szNote = NULL;
- BYTE *pData = NULL, *pMetaToken = NULL, *pMetaTime = NULL;
- int nNickLen, nNoteLen, nDataLen = 0, nMetaTokenLen = 0, nMetaTimeLen = 0;
- WORD wTLVlen;
- BYTE bAuth;
- int bDataTooLong = FALSE;
-
- // Prepare UID
- if (getContactUid(hContact, &dwUin, &szUid))
- {
- NetLog_Server("Buddy upload failed (UID missing).");
- return 0;
- }
-
- bAuth = getSettingByte(hContact, "Auth", 0);
- szNick = getSettingStringUtf(hContact, "CList", "MyHandle", NULL);
- szNote = getSettingStringUtf(hContact, "UserInfo", "MyNotes", NULL);
-
- DBVARIANT dbv;
-
- if (!getSetting(hContact, DBSETTING_METAINFO_TOKEN, &dbv))
- {
- nMetaTokenLen = dbv.cpbVal;
- pMetaToken = (BYTE*)_alloca(dbv.cpbVal);
- memcpy(pMetaToken, dbv.pbVal, dbv.cpbVal);
-
- ICQFreeVariant(&dbv);
- }
- if (!getSetting(hContact, DBSETTING_METAINFO_TIME, &dbv))
- {
- nMetaTimeLen = dbv.cpbVal;
- pMetaTime = (BYTE*)_alloca(dbv.cpbVal);
- for (int i = 0; i < dbv.cpbVal; i++)
- pMetaTime[i] = dbv.pbVal[dbv.cpbVal - i - 1];
-
- ICQFreeVariant(&dbv);
- }
-
- if (!getSetting(hContact, DBSETTING_SERVLIST_DATA, &dbv))
- { // read additional server item data
- nDataLen = dbv.cpbVal;
- pData = (BYTE*)_alloca(nDataLen);
- memcpy(pData, dbv.pbVal, nDataLen);
-
- ICQFreeVariant(&dbv);
- }
-
- nNickLen = strlennull(szNick);
- nNoteLen = strlennull(szNote);
-
- // Limit the strings
- if (nNickLen > MAX_SSI_TLV_NAME_SIZE)
- {
- bDataTooLong = TRUE;
- nNickLen = null_strcut(szNick, MAX_SSI_TLV_NAME_SIZE);
- }
- if (nNoteLen > MAX_SSI_TLV_COMMENT_SIZE)
- {
- bDataTooLong = TRUE;
- nNoteLen = null_strcut(szNote, MAX_SSI_TLV_COMMENT_SIZE);
- }
- if (bDataTooLong)
- { // Inform the user
- /// TODO: do something with this for Manage Server-List dialog.
- if (wAction != ICQ_LISTS_REMOVEFROMLIST) // do not report this when removing from list
- icq_LogMessage(LOG_WARNING, LPGEN("The contact's information was too big and was truncated."));
- }
-
- // Build the packet
- wTLVlen = (nNickLen?4+nNickLen:0) + (nNoteLen?4+nNoteLen:0) + (bAuth?4:0) + nDataLen + (nMetaTokenLen?4+nMetaTokenLen:0) + (nMetaTimeLen?4+nMetaTimeLen:0);
-
- // Initialize our handy data buffer
- pBuffer.wPlace = 0;
- pBuffer.pData = (BYTE *)_alloca(wTLVlen);
- pBuffer.wLen = wTLVlen;
-
- if (nNickLen)
- packTLV(&pBuffer, SSI_TLV_NAME, (WORD)nNickLen, (LPBYTE)szNick); // Nickname TLV
-
- if (nNoteLen)
- packTLV(&pBuffer, SSI_TLV_COMMENT, (WORD)nNoteLen, (LPBYTE)szNote); // Comment TLV
-
- if (nMetaTokenLen)
- packTLV(&pBuffer, SSI_TLV_METAINFO_TOKEN, (WORD)nMetaTokenLen, pMetaToken);
-
- if (nMetaTimeLen)
- packTLV(&pBuffer, SSI_TLV_METAINFO_TIME, (WORD)nMetaTimeLen, pMetaTime);
-
- if (pData)
- packBuffer(&pBuffer, pData, (WORD)nDataLen);
-
- if (bAuth) // icq5 gives this as last TLV
- packDWord(&pBuffer, 0x00660000); // "Still waiting for auth" TLV
-
- SAFE_FREE((void**)&szNick);
- SAFE_FREE((void**)&szNote);
-
- return icq_sendServerItem(dwCookie, wAction, wGroupId, wContactId, strUID(dwUin, szUid), pBuffer.pData, wTLVlen, SSI_ITEM_BUDDY, dwOperation, dwTimeout, doubleObject);
-}
-
-
-DWORD CIcqProto::icq_sendSimpleItem(DWORD dwCookie, WORD wAction, DWORD dwUin, char* szUID, WORD wGroupId, WORD wItemId, WORD wItemType, DWORD dwOperation, DWORD dwTimeout)
-{ // for privacy items
- return icq_sendServerItem(dwCookie, wAction, wGroupId, wItemId, strUID(dwUin, szUID), NULL, 0, wItemType, dwOperation, dwTimeout, NULL);
-}
-
-
-DWORD CIcqProto::icq_sendServerGroup(DWORD dwCookie, WORD wAction, WORD wGroupId, const char *szName, void *pContent, int cbContent, DWORD dwOperationFlags)
-{
- WORD wTLVlen;
- icq_packet pBuffer; // I reuse the ICQ packet type as a generic buffer
- // I should be ashamed! ;)
-
- if (strlennull(szName) == 0 && wGroupId != 0)
- {
- NetLog_Server("Group upload failed (GroupName missing).");
- return 0; // without name we could not change the group
- }
-
- // Calculate buffer size
- wTLVlen = (cbContent?4+cbContent:0);
-
- // Initialize our handy data buffer
- pBuffer.wPlace = 0;
- pBuffer.pData = (BYTE *)_alloca(wTLVlen);
- pBuffer.wLen = wTLVlen;
-
- if (wTLVlen)
- packTLV(&pBuffer, SSI_TLV_SUBITEMS, (WORD)cbContent, (LPBYTE)pContent); // Groups TLV
-
- return icq_sendServerItem(dwCookie, wAction, wGroupId, 0, szName, pBuffer.pData, wTLVlen, SSI_ITEM_GROUP, SSOP_GROUP_ACTION | dwOperationFlags, 400, NULL);
-}
-
-
-DWORD CIcqProto::icq_modifyServerPrivacyItem(HANDLE hContact, DWORD dwUin, char *szUid, WORD wAction, DWORD dwOperation, WORD wItemId, WORD wType)
-{
- cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
- DWORD dwCookie;
-
- if (ack)
- {
- ack->dwAction = dwOperation; // remove privacy item
- ack->hContact = hContact;
- ack->wContactId = wItemId;
-
- dwCookie = AllocateCookie(CKT_SERVERLIST, wAction, hContact, ack);
- }
- else // cookie failed
- return 0;
-
- return icq_sendSimpleItem(dwCookie, wAction, dwUin, szUid, 0, wItemId, wType, SSOP_ITEM_ACTION, 400);
-}
-
-
-DWORD CIcqProto::icq_removeServerPrivacyItem(HANDLE hContact, DWORD dwUin, char *szUid, WORD wItemId, WORD wType)
-{
- return icq_modifyServerPrivacyItem(hContact, dwUin, szUid, ICQ_LISTS_REMOVEFROMLIST, SSA_PRIVACY_REMOVE, wItemId, wType);
-}
-
-
-DWORD CIcqProto::icq_addServerPrivacyItem(HANDLE hContact, DWORD dwUin, char *szUid, WORD wItemId, WORD wType)
-{
- return icq_modifyServerPrivacyItem(hContact, dwUin, szUid, ICQ_LISTS_ADDTOLIST, SSA_PRIVACY_ADD, wItemId, wType);
-}
-
-/*****************************************
-*
-* --- Contact DB Utilities ---
-*
-*/
-
-
-/// TODO: do not check by plugin version, check by ServListStructures version!
-int CIcqProto::IsServerGroupsDefined()
-{
- int iRes = 1;
-
- if (getSettingDword(NULL, "Version", 0) < 0x00030608)
- { // group cache & linking data too old, flush, reload from server
- char szModule[MAX_PATH];
-
- // flush obsolete linking data
- null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
- CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szModule);
-
- iRes = 0; // no groups defined, or older version
- }
- // store our current version
- setSettingDword(NULL, "Version", ICQ_PLUG_VERSION & 0x00FFFFFF);
-
- return iRes;
-}
-
-
-void CIcqProto::FlushSrvGroupsCache()
-{
- char szModule[MAX_PATH];
-
- null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
- CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szModule);
-}
-
-
-// Look thru DB and collect all ContactIDs from a group
-void* CIcqProto::collectBuddyGroup(WORD wGroupID, int *count)
-{
- WORD* buf = NULL;
- int cnt = 0;
- HANDLE hContact;
- WORD wItemID;
-
- hContact = FindFirstContact();
-
- while (hContact)
- { // search all contacts
- if (wGroupID == getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0))
- { // add only buddys from specified group
- wItemID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
-
- if (wItemID)
- { // valid ID, add
- cnt++;
- buf = (WORD*)SAFE_REALLOC(buf, cnt*sizeof(WORD));
- buf[cnt-1] = wItemID;
- if (!count) break;
- }
- }
-
- hContact = FindNextContact(hContact);
- }
-
- if (count)
- *count = cnt<<1; // we return size in bytes
- return buf;
-}
-
-
-// Look thru DB and collect all GroupIDs
-void* CIcqProto::collectGroups(int *count)
-{
- WORD* buf = NULL;
- int cnt = 0;
- int i;
- HANDLE hContact;
- WORD wGroupID;
-
- hContact = FindFirstContact();
-
- while (hContact)
- { // search all contacts
- if (wGroupID = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0))
- { // add only valid IDs
- for (i = 0; i<cnt; i++)
- { // check for already added ids
- if (buf[i] == wGroupID) break;
- }
-
- if (i == cnt)
- { // not preset, add
- cnt++;
- buf = (WORD*)SAFE_REALLOC(buf, cnt*sizeof(WORD));
- buf[i] = wGroupID;
- }
- }
-
- hContact = FindNextContact(hContact);
- }
-
- *count = cnt<<1;
- return buf;
-}
-
-
-static int GroupLinksEnumProc(const char *szSetting,LPARAM lParam)
-{
- // check link target, add if match
- if (DBGetContactSettingWord(NULL, ((char**)lParam)[2], szSetting, 0) == (WORD)((char**)lParam)[1])
- {
- char** block = (char**)SAFE_MALLOC(2*sizeof(char*));
- block[1] = null_strdup(szSetting);
- block[0] = ((char**)lParam)[0];
- ((char**)lParam)[0] = (char*)block;
- }
- return 0;
-}
-
-void CIcqProto::removeGroupPathLinks(WORD wGroupID)
-{ // remove miranda grouppath links targeting to this groupid
- DBCONTACTENUMSETTINGS dbces;
- char szModule[MAX_PATH];
- char* pars[3];
-
- null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
-
- pars[0] = NULL;
- pars[1] = (char*)wGroupID;
- pars[2] = szModule;
-
- dbces.pfnEnumProc = &GroupLinksEnumProc;
- dbces.szModule = szModule;
- dbces.lParam = (LPARAM)pars;
-
- if (!CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces))
- { // we found some links, remove them
- char** list = (char**)pars[0];
- while (list)
- {
- void* bet;
-
- DBDeleteContactSetting(NULL, szModule, list[1]);
- SAFE_FREE((void**)&list[1]);
- bet = list;
- list = (char**)list[0];
- SAFE_FREE((void**)&bet);
- }
- }
-}
-
-
-char *CIcqProto::getServListGroupName(WORD wGroupID)
-{
- char szModule[MAX_PATH];
- char szGroup[16];
-
- if (!wGroupID)
- {
- NetLog_Server("Warning: Cannot get group name (Group ID missing)!");
- return NULL;
- }
-
- null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
- _itoa(wGroupID, szGroup, 0x10);
-
- if (!CheckServerID(wGroupID, 0))
- { // check if valid id, if not give empty and remove
- NetLog_Server("Removing group %u from cache...", wGroupID);
- DBDeleteContactSetting(NULL, szModule, szGroup);
- return NULL;
- }
-
- return getSettingStringUtf(NULL, szModule, szGroup, NULL);
-}
-
-
-void CIcqProto::setServListGroupName(WORD wGroupID, const char *szGroupName)
-{
- char szModule[MAX_PATH];
- char szGroup[16];
-
- if (!wGroupID)
- {
- NetLog_Server("Warning: Cannot set group name (Group ID missing)!");
- return;
- }
-
- null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
- _itoa(wGroupID, szGroup, 0x10);
-
- if (szGroupName)
- setSettingStringUtf(NULL, szModule, szGroup, szGroupName);
- else
- {
- DBDeleteContactSetting(NULL, szModule, szGroup);
- removeGroupPathLinks(wGroupID);
- }
- return;
-}
-
-
-WORD CIcqProto::getServListGroupLinkID(const char *szPath)
-{
- char szModule[MAX_PATH];
- WORD wGroupId;
-
- null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
-
- wGroupId = DBGetContactSettingWord(NULL, szModule, szPath, 0);
-
- if (wGroupId && !CheckServerID(wGroupId, 0))
- { // known, check if still valid, if not remove
- NetLog_Server("Removing group \"%s\" from cache...", szPath);
- DBDeleteContactSetting(NULL, szModule, szPath);
- wGroupId = 0;
- }
-
- return wGroupId;
-}
-
-
-void CIcqProto::setServListGroupLinkID(const char *szPath, WORD wGroupID)
-{
- char szModule[MAX_PATH];
-
- null_snprintf(szModule, SIZEOF(szModule), "%sGroups", m_szModuleName);
-
- if (wGroupID)
- DBWriteContactSettingWord(NULL, szModule, szPath, wGroupID);
- else
- DBDeleteContactSetting(NULL, szModule, szPath);
-}
-
-
-// this function takes all backslashes in szGroup as group-level separators
-int CIcqProto::getCListGroupHandle(const char *szGroup)
-{
- char *pszGroup = (char*)szGroup;
- int hParentGroup = 0, hGroup = 0;
-
- if (!strlennull(szGroup)) return 0; // no group
-
- if (strrchr(szGroup, '\\'))
- { // create parent group
- char *szSeparator = (char*)strrchr(szGroup, '\\');
-
- *szSeparator = '\0';
- hParentGroup = getCListGroupHandle(szGroup);
- *szSeparator = '\\';
- // take only sub-group name
- pszGroup = ++szSeparator;
- }
-
- int size = strlennull(szGroup) + 2;
- TCHAR *tszGroup = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(pszGroup, tszGroup, size))
- hGroup = CallService(MS_CLIST_GROUPCREATE, hParentGroup, (LPARAM)tszGroup); // 0.7+
-
-#ifdef _DEBUG
- NetLog_Server("Obtained CList group \"%s\" handle %x", szGroup, hGroup);
-#endif
-
- return hGroup;
-}
-
-
-// determine if the specified clist group path exists
-//!! this function is not thread-safe due to the use of cli->pfnGetGroupName()
-int CIcqProto::getCListGroupExists(const char *szGroup)
-{
- int hGroup = 0;
- CLIST_INTERFACE *clint = NULL;
-
- if (!szGroup) return 0;
-
- if (ServiceExists(MS_CLIST_RETRIEVE_INTERFACE))
- clint = (CLIST_INTERFACE*)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, 0);
-
- if (clint && clint->version >= 1)
- { // we've got clist interface, use it
- int size = strlennull(szGroup) + 2;
- TCHAR *tszGroup = (TCHAR*)_alloca(size * sizeof(TCHAR));
-
- if (utf8_to_tchar_static(szGroup, tszGroup, size))
- for (int i = 1; TRUE; i++)
- {
- TCHAR *tszGroupName = (TCHAR*)clint->pfnGetGroupName(i, NULL);
-
- if (!tszGroupName) break;
-
- if (!_tcscmp(tszGroup, tszGroupName))
- { // we have found the group
- hGroup = i;
- break;
- }
- }
- }
- else
- { // old ansi version - no other way
- int size = strlennull(szGroup) + 2;
- char *aszGroup = (char*)_alloca(size);
-
- utf8_decode_static(szGroup, aszGroup, size);
-
- for (int i = 1; TRUE; i++)
- {
- char *paszGroup = (char*)CallService(MS_CLIST_GROUPGETNAME, i, 0);
-
- if (!paszGroup) break;
-
- if (!strcmpnull(aszGroup, paszGroup))
- { // we found the group
- hGroup = i;
- break;
- }
- }
- }
-
- return hGroup;
-}
-
-
-int CIcqProto::moveContactToCListGroup(HANDLE hContact, const char *szGroup)
-{
- int hGroup = getCListGroupHandle(szGroup);
-
- if (ServiceExists(MS_CLIST_CONTACTCHANGEGROUP))
- return CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, hGroup);
- else /// TODO: is this neccessary ?
- return setSettingStringUtf(hContact, "CList", "Group", szGroup);
-}
-
-
-// utility function which counts > on start of a server group name
-static int countGroupNameLevel(const char *szGroupName)
-{
- int nNameLen = strlennull(szGroupName);
- int i = 0;
-
- while (i<nNameLen)
- {
- if (szGroupName[i] != '>')
- return i;
-
- i++;
- }
- return -1;
-}
-
-static int countCListGroupLevel(const char *szClistName)
-{
- int nNameLen = strlennull(szClistName);
- int i, level = 0;
-
- for (i = 0; i < nNameLen; i++)
- if (szClistName[i] == '\\') level++;
-
- return level;
-}
-
-int CIcqProto::getServListGroupLevel(WORD wGroupId)
-{
- char *szGroupName = getServListGroupName(wGroupId);
- int cnt = -1;
-
- if (szGroupName)
- { // groupid is valid count group name level
- if (m_bSsiSimpleGroups)
- cnt = countCListGroupLevel(szGroupName);
- else
- cnt = countGroupNameLevel(szGroupName);
-
- SAFE_FREE((void**)&szGroupName);
- }
-
- return cnt;
-}
-
-
-// demangle group path
-char *CIcqProto::getServListGroupCListPath(WORD wGroupId)
-{
- char *szGroup = NULL;
-
- if (szGroup = getServListGroupName(wGroupId))
- { // this groupid is valid
- if (!m_bSsiSimpleGroups)
- while (strstrnull(szGroup, "\\")) *strstrnull(szGroup, "\\") = '_'; // remove invalid char
-
- if (getServListGroupLinkID(szGroup) == wGroupId)
- { // this grouppath is known and is for this group, set user group
- return szGroup;
- }
- else if (m_bSsiSimpleGroups)
- { // with simple groups it is mapped 1:1, give real serv-list group name
- setServListGroupLinkID(szGroup, wGroupId);
- return szGroup;
- }
- else
- { // advanced groups, determine group level
- int nGroupLevel = getServListGroupLevel(wGroupId);
-
- if (nGroupLevel > 0)
- { // it is probably a sub-group locate parent group
- WORD wParentGroupId = wGroupId;
- int nParentGroupLevel;
-
- do
- { // we look for parent group at the correct level
- wParentGroupId--;
- nParentGroupLevel = getServListGroupLevel(wParentGroupId);
- } while ((nParentGroupLevel >= nGroupLevel) && (nParentGroupLevel != -1));
-
- if (nParentGroupLevel == -1)
- { // that was not a sub-group, it was just a group starting with >
- setServListGroupLinkID(szGroup, wGroupId);
- return szGroup;
- }
-
- { // recursively determine parent group clist path
- char *szParentGroup = getServListGroupCListPath(wParentGroupId);
-
- /// FIXME: properly handle ~N suffixes
- szParentGroup = (char*)SAFE_REALLOC(szParentGroup, strlennull(szGroup) + strlennull(szParentGroup) + 2);
- strcat(szParentGroup, "\\");
- strcat(szParentGroup, (char*)szGroup + nGroupLevel);
- /* if (strstrnull(szGroup, "~"))
- { // check if the ~ was not added to obtain unique servlist item name
- char *szUniqueMark = strrchr(szParentGroup, '~');
-
- *szUniqueMark = '\0';
- // not the same group without ~, return it
- if (getServListGroupLinkID(szParentGroup) != wGroupId)
- *szUniqueMark = '~';
- } */ /// FIXME: this is necessary, but needs group loading changes
- SAFE_FREE((void**)&szGroup);
- szGroup = szParentGroup;
-
-
- if (getServListGroupLinkID(szGroup) == wGroupId)
- { // known path, give
- return szGroup;
- }
- else
- { // unknown path, setup a link
- setServListGroupLinkID(szGroup, wGroupId);
- return szGroup;
- }
- }
- }
- else
- { // normal group, setup a link
- setServListGroupLinkID(szGroup, wGroupId);
- return szGroup;
- }
- }
- }
- return NULL;
-}
-
-
-static int SrvGroupNamesEnumProc(const char *szSetting, LPARAM lParam)
-{ // check server-group cache item
- const char **params = (const char**)lParam;
- CIcqProto *ppro = (CIcqProto*)params[0];
- char *szGroupName = ppro->getSettingStringUtf(NULL, params[3], szSetting, NULL);
-
- if (!strcmpnull(szGroupName, params[2]))
- params[1] = szSetting; // do not need the real value, just arbitrary non-NULL
-
- SAFE_FREE(&szGroupName);
- return 0;
-}
-
-char* CIcqProto::getServListUniqueGroupName(const char *szGroupName, int bAlloced)
-{ // enum ICQSrvGroups and create unique name if neccessary
- DBCONTACTENUMSETTINGS dbces;
- char szModule[MAX_PATH];
- char *pars[4];
- int uniqueID = 1;
- char *szGroupNameBase = (char*)szGroupName;
- char *szNewGroupName = NULL;
-
- if (!bAlloced)
- szGroupNameBase = null_strdup(szGroupName);
- null_strcut(szGroupNameBase, m_wServerListRecordNameMaxLength);
-
- null_snprintf(szModule, SIZEOF(szModule), "%sSrvGroups", m_szModuleName);
-
- do {
- pars[0] = (char*)this;
- pars[1] = NULL;
- pars[2] = szNewGroupName ? szNewGroupName : szGroupNameBase;
- pars[3] = szModule;
-
- dbces.pfnEnumProc = &SrvGroupNamesEnumProc;
- dbces.szModule = szModule;
- dbces.lParam = (LPARAM)pars;
-
- CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&dbces);
-
- if (pars[1])
- { // the groupname already exists, create another
- SAFE_FREE((void**)&szNewGroupName);
-
- char szUnique[10];
- _itoa(uniqueID++, szUnique, 10);
- null_strcut(szGroupNameBase, m_wServerListRecordNameMaxLength - strlennull(szUnique) - 1);
- szNewGroupName = (char*)SAFE_MALLOC(strlennull(szUnique) + strlennull(szGroupNameBase) + 2);
- if (szNewGroupName)
- {
- strcpy(szNewGroupName, szGroupNameBase);
- strcat(szNewGroupName, "~");
- strcat(szNewGroupName, szUnique);
- }
- }
- } while (pars[1] && szNewGroupName);
-
- if (szNewGroupName)
- {
- SAFE_FREE(&szGroupNameBase);
- return szNewGroupName;
- }
- if (szGroupName != szGroupNameBase)
- {
- SAFE_FREE(&szGroupNameBase);
- return (char*)szGroupName;
- }
- else
- return szGroupNameBase;
-}
-
-
-// this is the second part of recursive event-driven procedure
-int CIcqProto::servlistCreateGroup_gotParentGroup(const char *szGroup, WORD wGroupID, LPARAM param, int nResult)
-{
- cookie_servlist_action* clue = (cookie_servlist_action*)param;
- char *szSubGroupName = clue->szGroupName;
- char *szSubGroup;
- int wSubGroupLevel = -1;
- WORD wSubGroupID;
-
- SAFE_FREE((void**)&clue);
-
- if (nResult == PENDING_RESULT_PURGE)
- { // only cleanup
- return CALLBACK_RESULT_CONTINUE;
- }
-
- szSubGroup = (char*)SAFE_MALLOC(strlennull(szGroup) + strlennull(szSubGroupName) + 2);
- if (szSubGroup)
- {
- strcpy(szSubGroup, szGroup);
- strcat(szSubGroup, "\\");
- strcat(szSubGroup, szSubGroupName);
- }
-
- if (nResult == PENDING_RESULT_SUCCESS) // if we got an id count level
- wSubGroupLevel = getServListGroupLevel(wGroupID);
-
- if (wSubGroupLevel == -1)
- { // something went wrong, give the id and go away
- servlistPendingRemoveGroup(szSubGroup, wGroupID, PENDING_RESULT_FAILED);
-
- SAFE_FREE((void**)&szSubGroupName);
- SAFE_FREE((void**)&szSubGroup);
- return CALLBACK_RESULT_CONTINUE;
- }
- wSubGroupLevel++; // we are a sub-group
- wSubGroupID = wGroupID + 1;
-
- // check if on that id is not group of the same or greater level, if yes, try next
- while (CheckServerID(wSubGroupID, 0) && (getServListGroupLevel(wSubGroupID) >= wSubGroupLevel))
- {
- wSubGroupID++;
- }
-
- if (!CheckServerID(wSubGroupID, 0))
- { // the next id is free, so create our group with that id
- cookie_servlist_action *ack;
- DWORD dwCookie;
- char *szSubGroupItem = (char*)SAFE_MALLOC(strlennull(szSubGroupName) + wSubGroupLevel + 1);
-
- if (szSubGroupItem)
- {
- int i;
-
- for (i=0; i < wSubGroupLevel; i++)
- szSubGroupItem[i] = '>';
-
- strcpy(szSubGroupItem + wSubGroupLevel, szSubGroupName);
- szSubGroupItem[strlennull(szSubGroupName) + wSubGroupLevel] = '\0';
- SAFE_FREE((void**)&szSubGroupName);
- // check and create unique group name (Miranda does allow more subgroups with the same name!)
- szSubGroupItem = getServListUniqueGroupName(szSubGroupItem, TRUE);
-
- if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
- { // we have cookie good, go on
-#ifdef _DEBUG
- NetLog_Server("Server-List: Creating sub-group \"%s\", parent group \"%s\".", szSubGroupItem, szGroup);
-#endif
- ReserveServerID(wSubGroupID, SSIT_GROUP, 0);
-
- ack->wGroupId = wSubGroupID;
- ack->szGroupName = szSubGroupItem; // we need that name
- ack->szGroup = szSubGroup;
- ack->dwAction = SSA_GROUP_ADD;
- dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
-
- icq_sendServerGroup(dwCookie, ICQ_LISTS_ADDTOLIST, ack->wGroupId, szSubGroupItem, NULL, 0, SSOF_BEGIN_OPERATION);
- return CALLBACK_RESULT_CONTINUE;
- }
- SAFE_FREE((void**)&szSubGroupItem);
- }
- }
- // we failed to create sub-group give parent groupid
- icq_LogMessage(LOG_ERROR, LPGEN("Failed to create the correct sub-group, the using closest parent group."));
-
- servlistPendingRemoveGroup(szSubGroup, wGroupID, PENDING_RESULT_FAILED);
-
- SAFE_FREE((void**)&szSubGroupName);
- SAFE_FREE((void**)&szSubGroup);
- return CALLBACK_RESULT_CONTINUE;
-}
-
-
-int CIcqProto::servlistCreateGroup_Ready(const char *szGroup, WORD groupID, LPARAM param, int nResult)
-{
- WORD wGroupID = 0;
-
- if (nResult == PENDING_RESULT_PURGE)
- return CALLBACK_RESULT_CONTINUE;
-
- if (wGroupID = getServListGroupLinkID(szGroup))
- { // the path is known, continue the process
- servlistPendingRemoveGroup(szGroup, wGroupID, PENDING_RESULT_SUCCESS);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- if (!strstrnull(szGroup, "\\") || m_bSsiSimpleGroups)
- { // a root group can be simply created without problems; simple groups are mapped directly
- cookie_servlist_action* ack;
- DWORD dwCookie;
-
- if (ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action)))
- { // we have cookie good, go on
-#ifdef _DEBUG
- NetLog_Server("Server-List: Creating root group \"%s\".", szGroup);
-#endif
- ack->wGroupId = GenerateServerID(SSIT_GROUP, 0);
- ack->szGroup = null_strdup(szGroup); // we need that name
- // check if the groupname is unique - just to be sure, Miranda should handle that!
- ack->szGroupName = getServListUniqueGroupName(ack->szGroup, FALSE);
- ack->dwAction = SSA_GROUP_ADD;
- dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, 0, ack);
-
- icq_sendServerGroup(dwCookie, ICQ_LISTS_ADDTOLIST, ack->wGroupId, ack->szGroup, NULL, 0, SSOF_BEGIN_OPERATION);
-
- return CALLBACK_RESULT_POSTPONE;
- }
- }
- else
- { // this is a sub-group
- char* szSub = null_strdup(szGroup); // create subgroup, recursive, event-driven, possibly relocate
- cookie_servlist_action* ack;
- char *szLast;
-
- if (strstrnull(szSub, "\\"))
- { // determine parent group
- szLast = strrchr(szSub, '\\') + 1;
-
- szLast[-1] = '\0';
- }
- // make parent group id
- ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
- if (ack)
- {
- ack->szGroupName = null_strdup(szLast); // groupname
- servlistCreateGroup(szSub, (LPARAM)ack, &CIcqProto::servlistCreateGroup_gotParentGroup);
- SAFE_FREE((void**)&szSub);
-
- return CALLBACK_RESULT_POSTPONE;
- }
-
- SAFE_FREE((void**)&szSub);
- }
- servlistPendingRemoveGroup(szGroup, groupID, PENDING_RESULT_FAILED);
-
- return CALLBACK_RESULT_CONTINUE;
-}
-
-
-// create group with this path, a bit complex task
-// this supposes that all server groups are known
-void CIcqProto::servlistCreateGroup(const char *szGroupPath, LPARAM param, PENDING_GROUP_CALLBACK callback)
-{
- char *szGroup = (char*)szGroupPath;
-
- if (!strlennull(szGroup)) szGroup = DEFAULT_SS_GROUP;
-
- servlistPendingAddGroup(szGroup, 0, 0, &CIcqProto::servlistCreateGroup_Ready, TRUE, param, callback);
-}
-
-
-/*****************************************
-*
-* --- Server-List Operations ---
-*
-*/
-
-int CIcqProto::servlistAddContact_gotGroup(const char *szGroup, WORD wGroupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action* ack = (cookie_servlist_action*)lParam;
-
- if (ack) SAFE_FREE(&ack->szGroup);
-
- if (nResult == PENDING_RESULT_PURGE)
- { // only cleanup
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- if (!ack || !wGroupID) // something went wrong
- {
- if (ack) servlistPendingRemoveContact(ack->hContact, 0, wGroupID, PENDING_RESULT_FAILED);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
-
- if (wItemID) /// TODO: redundant ???
- { // Only add the contact if it doesnt already have an ID
- servlistPendingRemoveContact(ack->hContact, wItemID, wGroupID, PENDING_RESULT_SUCCESS);
- NetLog_Server("Failed to add contact to server side list (%s)", "already there");
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- wItemID = GenerateServerID(SSIT_ITEM, 0);
-
- ack->dwAction = SSA_CONTACT_ADD;
- ack->wGroupId = wGroupID;
- ack->wContactId = wItemID;
-
- DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, ack->hContact, ack);
-
- icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupID, wItemID, SSOP_ITEM_ACTION | SSOF_CONTACT | SSOF_BEGIN_OPERATION, 400, NULL);
-
- return CALLBACK_RESULT_CONTINUE;
-}
-
-
-// Need to be called when Pending Contact is active
-int CIcqProto::servlistAddContact_Ready(HANDLE hContact, WORD wContactID, WORD wGroupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action* ack = (cookie_servlist_action*)lParam;
-
- if (nResult == PENDING_RESULT_PURGE)
- { // removing obsolete items, just free the memory
- SAFE_FREE((void**)&ack->szGroup);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
-
- if (wItemID)
- { // Only add the contact if it doesn't already have an ID
- servlistPendingRemoveContact(ack->hContact, wItemID, getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0), PENDING_RESULT_SUCCESS);
- NetLog_Server("Failed to add contact to server side list (%s)", "already there");
- SAFE_FREE((void**)&ack->szGroup);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- // obtain a correct groupid first
- servlistCreateGroup(ack->szGroup, lParam, &CIcqProto::servlistAddContact_gotGroup);
-
- return CALLBACK_RESULT_POSTPONE;
-}
-
-
-// Called when contact should be added to server list, if group does not exist, create one
-void CIcqProto::servlistAddContact(HANDLE hContact, const char *pszGroup)
-{
- DWORD dwUin;
- uid_str szUid;
- cookie_servlist_action* ack;
-
- // Get UID
- if (getContactUid(hContact, &dwUin, &szUid))
- { // Could not do anything without uid
- NetLog_Server("Failed to add contact to server side list (%s)", "no UID");
- return;
- }
-
- if (!(ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action))))
- { // Could not do anything without cookie
- NetLog_Server("Failed to add contact to server side list (%s)", "malloc failed");
- return;
- }
- else
- {
- ack->hContact = hContact;
- ack->szGroup = null_strdup(pszGroup);
- // call thru pending operations - makes sure the contact is ready to be added
- servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistAddContact_Ready, TRUE);
- return;
- }
-}
-
-
-int CIcqProto::servlistRemoveContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult)
-{
- WORD wGroupID;
- WORD wItemID;
- cookie_servlist_action* ack = (cookie_servlist_action*)lParam;
- DWORD dwCookie;
-
- if (nResult == PENDING_RESULT_PURGE)
- {
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- // Get the contact's group ID
- if (!(wGroupID = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0)))
- { // Could not find a usable group ID
- servlistPendingRemoveContact(hContact, contactID, groupID, PENDING_RESULT_FAILED);
-
- NetLog_Server("Failed to remove contact from server side list (%s)", "no group ID");
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- // Get the contact's item ID
- if (!(wItemID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0)))
- { // Could not find usable item ID
- servlistPendingRemoveContact(hContact, contactID, wGroupID, PENDING_RESULT_FAILED);
-
- NetLog_Server("Failed to remove contact from server side list (%s)", "no item ID");
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- ack->dwAction = SSA_CONTACT_REMOVE;
- ack->hContact = hContact;
- ack->wGroupId = wGroupID;
- ack->wContactId = wItemID;
-
- dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, hContact, ack);
-
- icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupID, wItemID, SSOP_ITEM_ACTION | SSOF_CONTACT | SSOF_BEGIN_OPERATION, 400, NULL);
-
- return CALLBACK_RESULT_POSTPONE;
-}
-
-
-// Called when contact should be removed from server list, remove group if it remain empty
-void CIcqProto::servlistRemoveContact(HANDLE hContact)
-{
- DWORD dwUin;
- uid_str szUid;
- cookie_servlist_action* ack;
-
- // Get UID
- if (getContactUid(hContact, &dwUin, &szUid))
- {
- // Could not do anything without uid
- NetLog_Server("Failed to remove contact from server side list (%s)", "no UID");
- return;
- }
-
- if (!(ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action))))
- { // Could not do anything without cookie
- NetLog_Server("Failed to remove contact from server side list (%s)", "malloc failed");
- return;
- }
- else
- {
- ack->hContact = hContact;
- // call thru pending operations - makes sure the contact is ready to be removed
- servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistRemoveContact_Ready, TRUE);
- return;
- }
-}
-
-
-int CIcqProto::servlistMoveContact_gotTargetGroup(const char *szGroup, WORD wNewGroupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
-
- if (ack) SAFE_FREE(&ack->szGroup);
-
- if (nResult == PENDING_RESULT_PURGE)
- { // removing obsolete items, just free the memory
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- if (!ack || !wNewGroupID || !ack->hContact) // something went wrong
- {
- if (ack) servlistPendingRemoveContact(ack->hContact, 0, 0, PENDING_RESULT_FAILED);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
- WORD wGroupID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_GROUP, 0);
-
- if (!wItemID)
- { // We have no ID, so try to simply add the contact to serv-list
- NetLog_Server("Unable to move contact (no ItemID) -> trying to add");
- // we know the GroupID, so directly call add
- return servlistAddContact_gotGroup(szGroup, wNewGroupID, lParam, nResult);
- }
-
- if (wGroupID == wNewGroupID)
- { // Only move the contact if it had different GroupID
- servlistPendingRemoveContact(ack->hContact, wItemID, wNewGroupID, PENDING_RESULT_SUCCESS);
- NetLog_Server("Contact not moved to group on server side list (same Group)");
- return CALLBACK_RESULT_CONTINUE;
- }
-
- ack->szGroupName = NULL;
- ack->dwAction = SSA_CONTACT_SET_GROUP;
- ack->wGroupId = wGroupID;
- ack->wContactId = wItemID;
- ack->wNewContactId = GenerateServerID(SSIT_ITEM, 0); // icq5 recreates also this, imitate
- ack->wNewGroupId = wNewGroupID;
- ack->lParam = 0; // we use this as a sign
-
- DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, ack->hContact, ack);
- DWORD dwCookie2 = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_ADDTOLIST, ack->hContact, ack);
-
- { // imitate icq5, previously here was different order, but AOL changed and it ceased to work
- void *doubleObject = NULL;
-
- icq_sendServerContact(ack->hContact, dwCookie2, ICQ_LISTS_ADDTOLIST, wNewGroupID, ack->wNewContactId, SSO_CONTACT_SETGROUP | SSOF_BEGIN_OPERATION, 500, &doubleObject);
- icq_sendServerContact(ack->hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupID, wItemID, SSO_CONTACT_SETGROUP | SSOF_BEGIN_OPERATION, 500, &doubleObject);
- }
- return CALLBACK_RESULT_CONTINUE;
-}
-
-
-int CIcqProto::servlistMoveContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
-
- if (nResult == PENDING_RESULT_PURGE)
- { // removing obsolete items, just free the memory
- SAFE_FREE(&ack->szGroup);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- WORD wItemID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_ID, 0);
- WORD wGroupID = getSettingWord(ack->hContact, DBSETTING_SERVLIST_GROUP, 0);
-
- if (!wGroupID && wItemID)
- { // Only move the contact if it had an GroupID
- servlistPendingRemoveContact(ack->hContact, contactID, groupID, PENDING_RESULT_FAILED);
-
- NetLog_Server("Failed to move contact to group on server side list (%s)", "no Group");
- SAFE_FREE(&ack->szGroup);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- // obtain a correct target groupid first
- servlistCreateGroup(ack->szGroup, lParam, &CIcqProto::servlistMoveContact_gotTargetGroup);
-
- return CALLBACK_RESULT_POSTPONE;
-}
-
-
-// Called when contact should be moved from one group to another, create new, remove empty
-void CIcqProto::servlistMoveContact(HANDLE hContact, const char *pszNewGroup)
-{
- DWORD dwUin;
- uid_str szUid;
-
- if (!hContact) return; // we do not move us, caused our uin was wrongly added to list
-
- // Get UID
- if (getContactUid(hContact, &dwUin, &szUid))
- { // Could not do anything without uin
- NetLog_Server("Failed to move contact to group on server side list (%s)", "no UID");
- return;
- }
-
- if ((pszNewGroup != NULL) && (pszNewGroup[0]!='\0') && !getCListGroupExists(pszNewGroup))
- { // the contact moved to non existing group, do not do anything: MetaContact hack
- NetLog_Server("Contact not moved - probably hiding by MetaContacts.");
- return;
- }
-
- if (!getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0)) /// FIXME:::: this should be in _ready
- { // the contact is not stored on the server, check if we should try to add
- if (!getSettingByte(NULL, "ServerAddRemove", DEFAULT_SS_ADDSERVER) ||
- DBGetContactSettingByte(hContact, "CList", "Hidden", 0))
- return;
- }
- cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
-
- if (!ack)
- { // Could not do anything without cookie
- NetLog_Server("Failed to add contact to server side list (%s)", "malloc failed");
- return;
- }
- else
- {
- ack->hContact = hContact;
- ack->szGroup = null_strdup(pszNewGroup);
- // call thru pending operations - makes sure the contact is ready to be moved
- servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistMoveContact_Ready, TRUE);
- return;
- }
-}
-
-
-int CIcqProto::servlistUpdateContact_Ready(HANDLE hContact, WORD contactID, WORD groupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
-
- if (nResult == PENDING_RESULT_PURGE)
- { // removing obsolete items, just free the memory
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
- WORD wItemID;
- WORD wGroupID;
-
- // Get the contact's group ID
- if (!(wGroupID = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0)))
- {
- servlistPendingRemoveContact(hContact, contactID, groupID, PENDING_RESULT_FAILED);
- // Could not find a usable group ID
- NetLog_Server("Failed to update contact's details on server side list (%s)", "no group ID");
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- // Get the contact's item ID
- if (!(wItemID = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0)))
- {
- servlistPendingRemoveContact(hContact, contactID, wGroupID, PENDING_RESULT_FAILED);
- // Could not find usable item ID
- NetLog_Server("Failed to update contact's details on server side list (%s)", "no item ID");
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- ack->dwAction = SSA_CONTACT_UPDATE;
- ack->wContactId = wItemID;
- ack->wGroupId = wGroupID;
- ack->hContact = hContact;
-
- DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, hContact, ack);
-
- // There is no need to send ICQ_LISTS_CLI_MODIFYSTART or
- // ICQ_LISTS_CLI_MODIFYEND when just changing nick name
- icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_UPDATEGROUP, wGroupID, wItemID, SSOP_ITEM_ACTION | SSOF_CONTACT, 400, NULL);
-
- return CALLBACK_RESULT_POSTPONE;
-}
-
-
-// Is called when a contact' details has been changed locally to update
-// the server side details.
-void CIcqProto::servlistUpdateContact(HANDLE hContact)
-{
- DWORD dwUin;
- uid_str szUid;
-
- // Get UID
- if (getContactUid(hContact, &dwUin, &szUid))
- {
- // Could not set nickname on server without uid
- NetLog_Server("Failed to update contact's details on server side list (%s)", "no UID");
- return;
- }
- cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
-
- if (!ack)
- {
- // Could not allocate cookie - use old fake
- NetLog_Server("Failed to update contact's details on server side list (%s)", "malloc failed");
- return;
- }
- else
- {
- ack->hContact = hContact;
- // call thru pending operations - makes sure the contact is ready to be updated
- servlistPendingAddContact(hContact, 0, 0, (LPARAM)ack, &CIcqProto::servlistUpdateContact_Ready, TRUE);
- return;
- }
-}
-
-
-int CIcqProto::servlistRenameGroup_Ready(const char *szGroup, WORD wGroupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
-
- if (nResult == PENDING_RESULT_PURGE)
- { // only cleanup
- if (ack) SAFE_FREE(&ack->szGroupName);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- if (!ack || !wGroupID) // something went wrong
- {
- servlistPendingRemoveGroup(szGroup, wGroupID, PENDING_RESULT_FAILED);
-
- if (ack) SAFE_FREE(&ack->szGroupName);
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
- void *groupData;
- int groupSize;
-
- if (groupData = collectBuddyGroup(wGroupID, &groupSize))
- {
- ack->dwAction = SSA_GROUP_RENAME;
- ack->wGroupId = wGroupID;
- ack->szGroup = null_strdup(szGroup); // we need this name
- // check if the new name is unique, create unique groupname if necessary
- ack->szGroupName = getServListUniqueGroupName(ack->szGroupName, TRUE);
-
- DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_UPDATEGROUP, 0, ack);
-
- icq_sendServerGroup(dwCookie, ICQ_LISTS_UPDATEGROUP, wGroupID, ack->szGroupName, groupData, groupSize, 0);
- SAFE_FREE(&groupData);
- }
- return CALLBACK_RESULT_POSTPONE;
-}
-
-
-void CIcqProto::servlistRenameGroup(char *szGroup, WORD wGroupId, char *szNewGroup)
-{
- char *szNewGroupName;
- int nGroupLevel = getServListGroupLevel(wGroupId);
-
- if (nGroupLevel == -1) return; // we failed to prepare group
-
- if (!m_bSsiSimpleGroups)
- {
- char *szGroupName = szGroup;
- int i = nGroupLevel;
- while (i)
- { // find correct part of grouppath
- szGroupName = strstrnull(szGroupName, "\\");
- if (!szGroupName) return; // failed to get correct part of the grouppath
- szGroupName++;
- i--;
- }
- szNewGroupName = szNewGroup;
- i = nGroupLevel;
- while (i)
- { // find correct part of new grouppath
- szNewGroupName = strstrnull(szNewGroupName, "\\");
- if (!szNewGroupName) return; // failed to get correct part of the new grouppath
- szNewGroupName++;
- i--;
- }
- // truncate possible sub-groups
- char *szLast = strstrnull(szGroupName, "\\");
- if (szLast)
- szLast[0] = '\0';
- szLast = strstrnull(szNewGroupName, "\\");
- if (szLast)
- szLast[0] = '\0';
-
- // this group was not changed, nothing to rename
- if (!strcmpnull(szGroupName, szNewGroupName)) return;
-
- szGroupName = szNewGroupName;
- szNewGroupName = (char*)SAFE_MALLOC(strlennull(szGroupName) + 1 + nGroupLevel);
- if (!szNewGroupName) return; // Failure
-
- for (i = 0; i < nGroupLevel; i++)
- { // create level prefix
- szNewGroupName[i] = '>';
- }
- strcat(szNewGroupName, szGroupName);
- }
- else // simple groups do not require any conversion
- szNewGroupName = null_strdup(szNewGroup);
-
- cookie_servlist_action* ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
- if (!ack)
- { // cookie failed
- NetLog_Server("Error: Failed to allocate cookie");
-
- SAFE_FREE(&szNewGroupName);
- return;
- }
- // store new group name for future use
- ack->szGroupName = szNewGroupName;
- // call thru pending operations - makes sure the group is ready for rename
- servlistPendingAddGroup(szGroup, wGroupId, (LPARAM)ack, &CIcqProto::servlistRenameGroup_Ready, TRUE);
-}
-
-
-int CIcqProto::servlistRemoveGroup_Ready(const char *szGroup, WORD groupID, LPARAM lParam, int nResult)
-{
- cookie_servlist_action *ack = (cookie_servlist_action*)lParam;
-
- if (nResult == PENDING_RESULT_PURGE)
- { // only cleanup
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
- WORD wGroupID = getServListGroupLinkID(szGroup);
- char *szGroupName;
-
- if (wGroupID && (szGroupName = getServListGroupName(wGroupID)))
- { // the group is valid, check if it is empty
- void *groupData = collectBuddyGroup(wGroupID, NULL);
-
- if (groupData)
- { // the group is not empty, cannot delete
- SAFE_FREE(&groupData);
- SAFE_FREE(&szGroupName);
- // end operation
- servlistPendingRemoveGroup(szGroup, wGroupID, PENDING_RESULT_SUCCESS);
- // cleanup
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
- }
-
- if (!CheckServerID((WORD)(wGroupID+1), 0) || getServListGroupLevel((WORD)(wGroupID+1)) == 0)
- { // is next id an sub-group, if yes, we cannot delete this group
- ack->dwAction = SSA_GROUP_REMOVE;
- ack->wContactId = 0;
- ack->wGroupId = wGroupID;
- ack->hContact = NULL;
- ack->szGroup = null_strdup(szGroup); // we need that name
- ack->szGroupName = szGroupName;
- DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, ICQ_LISTS_REMOVEFROMLIST, 0, ack);
-
- icq_sendServerGroup(dwCookie, ICQ_LISTS_REMOVEFROMLIST, ack->wGroupId, ack->szGroupName, NULL, 0, 0);
- }
- return CALLBACK_RESULT_POSTPONE;
- }
- // end operation
- servlistPendingRemoveGroup(szGroup, groupID, PENDING_RESULT_SUCCESS);
- // cleanup
- SAFE_FREE((void**)&ack);
- return CALLBACK_RESULT_CONTINUE;
-}
-
-
-void CIcqProto::servlistRemoveGroup(const char *szGroup, WORD wGroupId)
-{
- if (!szGroup) return;
-
- cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
-
- if (!ack)
- { // cookie failed
- NetLog_Server("Error: Failed to allocate cookie");
- return;
- }
-
- // call thru pending operations - makes sure the group is ready for removal
- servlistPendingAddGroup(szGroup, wGroupId, (LPARAM)ack, &CIcqProto::servlistRemoveGroup_Ready, TRUE);
-}
-
-
-/*void CIcqProto::servlistMoveGroup(const char *szGroup, WORD wNewGroupId)
-{
-// relocate the group
-}*/
-
-
-void CIcqProto::resetServContactAuthState(HANDLE hContact, DWORD dwUin)
-{
- WORD wContactId = getSettingWord(hContact, DBSETTING_SERVLIST_ID, 0);
- WORD wGroupId = getSettingWord(hContact, DBSETTING_SERVLIST_GROUP, 0);
-
- if (wContactId && wGroupId)
- {
- cookie_servlist_action *ack = (cookie_servlist_action*)SAFE_MALLOC(sizeof(cookie_servlist_action));
-
- if (ack)
- { // we have cookie good, go on
- ack->hContact = hContact;
- ack->wContactId = wContactId;
- ack->wGroupId = wGroupId;
- ack->dwAction = SSA_CONTACT_FIX_AUTH;
-
- DWORD dwCookie = AllocateCookie(CKT_SERVERLIST, 0, hContact, ack);
-
- {
- void *doubleObject = NULL;
-
- icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_REMOVEFROMLIST, wGroupId, wContactId, SSO_CONTACT_FIXAUTH | SSOF_BEGIN_OPERATION | SSOF_END_OPERATION, 200, &doubleObject);
- deleteSetting(hContact, DBSETTING_METAINFO_TOKEN);
- deleteSetting(hContact, DBSETTING_METAINFO_TIME);
- deleteSetting(hContact, DBSETTING_SERVLIST_DATA);
- icq_sendServerContact(hContact, dwCookie, ICQ_LISTS_ADDTOLIST, wGroupId, wContactId, SSO_CONTACT_FIXAUTH | SSOF_BEGIN_OPERATION | SSOF_END_OPERATION, 200, &doubleObject);
- }
- }
- else
- NetLog_Server("Error: Failed to allocate cookie");
- }
-}
-
-/*****************************************
-*
-* --- Miranda Contactlist Hooks ---
-*
-*/
-
-int CIcqProto::ServListDbSettingChanged(WPARAM wParam, LPARAM lParam)
-{
- DBCONTACTWRITESETTING* cws = (DBCONTACTWRITESETTING*)lParam;
-
- // TODO: Queue changes that occur while offline
- if (!icqOnline() || !m_bSsiEnabled || bIsSyncingCL)
- return 0;
-
-#ifdef _DEBUG
- if (cws->value.type == DBVT_DELETED)
- NetLog_Server("DB-Events: Module \"%s\", setting \"%s\" deleted.", cws->szModule, cws->szSetting);
- else
- NetLog_Server("DB-Events: Module \"%s\", setting \"%s\" changed, data type %x.", cws->szModule, cws->szSetting, cws->value.type);
-#endif
-
- if (!strcmpnull(cws->szModule, "CList"))
- {
- // Has contact been renamed?
- if (!strcmpnull(cws->szSetting, "MyHandle") &&
- getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
- { // Update contact's details in server-list
- servlistUpdateContact((HANDLE)wParam);
- }
-
- // Has contact been moved to another group?
- if (!strcmpnull(cws->szSetting, "Group") &&
- getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
- { // Read group from DB
- char* szNewGroup = getContactCListGroup((HANDLE)wParam);
-
- SAFE_FREE(&szNewGroup);
- }
- }
- else if (!strcmpnull(cws->szModule, "UserInfo"))
- {
- if (!strcmpnull(cws->szSetting, "MyNotes") &&
- getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
- { // Update contact's details in server-list
- servlistUpdateContact((HANDLE)wParam);
- }
- }
-
- return 0;
-}
-
-
-int CIcqProto::ServListDbContactDeleted(WPARAM wParam, LPARAM lParam)
-{
-#ifdef _DEBUG
- NetLog_Server("DB-Events: Contact %x deleted.", wParam);
-#endif
-
- DeleteFromContactsCache((HANDLE)wParam);
-
- if ( !icqOnline() && m_bSsiEnabled)
- { // contact was deleted only locally - retrieve full list on next connect
- setSettingWord((HANDLE)wParam, "SrvRecordCount", 0);
- }
-
- if ( !icqOnline() || !m_bSsiEnabled)
- return 0;
-
- { // we need all server contacts on local buddy list
- DWORD dwUIN;
- uid_str szUID;
-
- if (getContactUid((HANDLE)wParam, &dwUIN, &szUID))
- return 0;
-
- WORD wContactID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_ID, 0);
- WORD wGroupID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_GROUP, 0);
- WORD wVisibleID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_PERMIT, 0);
- WORD wInvisibleID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_DENY, 0);
- WORD wIgnoreID = getSettingWord((HANDLE)wParam, DBSETTING_SERVLIST_IGNORE, 0);
-
- // Remove from queue for user details request
- icq_DequeueUser(dwUIN);
-
- // Close all opened peer connections
- CloseContactDirectConns((HANDLE)wParam);
-
- if ((wGroupID && wContactID) || wVisibleID || wInvisibleID || wIgnoreID)
- {
- if (wContactID)
- { // delete contact from server
- servlistRemoveContact((HANDLE)wParam);
- }
-
- if (wVisibleID)
- { // detete permit record
- icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wVisibleID, SSI_ITEM_PERMIT);
- }
-
- if (wInvisibleID)
- { // delete deny record
- icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wInvisibleID, SSI_ITEM_DENY);
- }
-
- if (wIgnoreID)
- { // delete ignore record
- icq_removeServerPrivacyItem((HANDLE)wParam, dwUIN, szUID, wIgnoreID, SSI_ITEM_IGNORE);
- }
- }
- }
-
- return 0;
-}
-
-
-int CIcqProto::ServListCListGroupChange(WPARAM wParam, LPARAM lParam)
-{
- HANDLE hContact = (HANDLE)wParam;
- CLISTGROUPCHANGE *grpchg = (CLISTGROUPCHANGE*)lParam;
-
- if (!icqOnline() || !m_bSsiEnabled || bIsSyncingCL)
- return 0;
-
- // only change server-list if it is allowed
- if (!getSettingByte(NULL, "StoreServerDetails", DEFAULT_SS_STORE))
- return 0;
-
-
- if (hContact == NULL)
- { // change made to group
- if (grpchg->pszNewName == NULL && grpchg->pszOldName != NULL)
- { // group removed
- char *szOldName = tchar_to_utf8(grpchg->pszOldName);
- WORD wGroupId = getServListGroupLinkID(szOldName);
-
-#ifdef _DEBUG
- NetLog_Server("CList-Events: Group %x:\"%s\" deleted.", wGroupId, szOldName);
-#endif
- if (wGroupId)
- { // the group is known, remove from server
- servlistPostPacket(NULL, 0, SSO_BEGIN_OPERATION, 100); // start server modifications here
- servlistRemoveGroup(szOldName, wGroupId);
- }
- SAFE_FREE(&szOldName);
- }
- else if (grpchg->pszNewName != NULL && grpchg->pszOldName != NULL)
- { // group renamed
- char *szNewName = tchar_to_utf8(grpchg->pszNewName);
- char *szOldName = tchar_to_utf8(grpchg->pszOldName);
- WORD wGroupId = getServListGroupLinkID(szOldName);
-
-#ifdef _DEBUG
- NetLog_Server("CList-Events: Group %x:\"%s\" changed to \"%s\".", wGroupId, szOldName, szNewName);
-#endif
- if (wGroupId)
- { // group is known, rename on server
- servlistRenameGroup(szOldName, wGroupId, szNewName);
- }
- SAFE_FREE(&szOldName);
- SAFE_FREE(&szNewName);
- }
- }
- else
- { // change to contact
- if (IsICQContact(hContact))
- { // our contact, fine move on the server as well
- char *szNewName = grpchg->pszNewName ? tchar_to_utf8(grpchg->pszNewName) : NULL;
-
-#ifdef _DEBUG
- NetLog_Server("CList-Events: Contact %x moved to group \"%s\".", hContact, szNewName);
-#endif
- servlistMoveContact(hContact, szNewName);
- SAFE_FREE(&szNewName);
- }
- }
- return 0;
-}