/* Jabber Protocol Plugin for Miranda IM Tlen Protocol Plugin for Miranda NG Copyright (C) 2002-2004 Santithorn Bunchua Copyright (C) 2004-2007 Piotr Piastucki This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tlen.h" #include "tlen_list.h" static void TlenListFreeItemInternal(TLEN_LIST_ITEM *item); void TlenListInit(TlenProtocol *proto) { proto->lists = NULL; proto->listsCount = 0; InitializeCriticalSection(&proto->csLists); } void TlenListUninit(TlenProtocol *proto) { TlenListWipe(proto); DeleteCriticalSection(&proto->csLists); } void TlenListWipe(TlenProtocol *proto) { int i; EnterCriticalSection(&proto->csLists); for (i=0; ilistsCount; i++) TlenListFreeItemInternal(&(proto->lists[i])); if (proto->lists != NULL) { mir_free(proto->lists); proto->lists = NULL; } proto->listsCount=0; LeaveCriticalSection(&proto->csLists); } void TlenListWipeSpecial(TlenProtocol *proto) { int i; EnterCriticalSection(&proto->csLists); for (i=0; ilistsCount; i++) { if (proto->lists[i].list != LIST_FILE && proto->lists[i].list != LIST_VOICE) { TlenListFreeItemInternal(&(proto->lists[i])); proto->listsCount--; memmove(proto->lists+i, proto->lists+i+1, sizeof(TLEN_LIST_ITEM)*(proto->listsCount-i)); i--; } } proto->lists = (TLEN_LIST_ITEM *) mir_realloc(proto->lists, sizeof(TLEN_LIST_ITEM)*proto->listsCount); LeaveCriticalSection(&proto->csLists); } static void TlenListFreeItemInternal(TLEN_LIST_ITEM *item) { if (item == NULL) return; if (item->jid) mir_free(item->jid); if (item->nick) mir_free(item->nick); if (item->statusMessage) mir_free(item->statusMessage); if (item->group) mir_free(item->group); if (item->messageEventIdStr) mir_free(item->messageEventIdStr); // if (item->type) mir_free(item->type); //if (item->ft) TlenFileFreeFt(item->ft); // No need to free (it is always free when exit from TlenFileServerThread()) if (item->roomName) mir_free(item->roomName); if (item->version) mir_free(item->version); if (item->software) mir_free(item->software); if (item->system) mir_free(item->system); if (item->avatarHash) mir_free(item->avatarHash); if (item->protocolVersion) mir_free(item->protocolVersion); if (item->id2) mir_free(item->id2); } static char * GetItemId(TLEN_LIST list, const char *jid) { char *s, *p, *q; s = mir_strdup(jid); if (list != LIST_PICTURE) { _strlwr(s); // strip resouce name if any if ((p=strchr(s, '@')) != NULL) { if ((q=strchr(p, '/')) != NULL) *q = '\0'; } } return s; } int TlenListExist(TlenProtocol *proto, TLEN_LIST list, const char *jid) { int i; size_t len; char *s, *p; s = GetItemId(list, jid); len = strlen(s); EnterCriticalSection(&proto->csLists); for (i=0; ilistsCount; i++) if (proto->lists[i].list == list) { p = proto->lists[i].jid; if (p && strlen(p) >= len && (p[(int)len] == '\0' || p[(int)len] == '/') && !strncmp(p, s, len)) { LeaveCriticalSection(&proto->csLists); mir_free(s); return i+1; } } LeaveCriticalSection(&proto->csLists); mir_free(s); return 0; } TLEN_LIST_ITEM *TlenListAdd(TlenProtocol *proto, TLEN_LIST list, const char *jid) { char *s; TLEN_LIST_ITEM *item; EnterCriticalSection(&proto->csLists); if ((item=TlenListGetItemPtr(proto, list, jid)) != NULL) { LeaveCriticalSection(&proto->csLists); return item; } s = GetItemId(list, jid); proto->lists = (TLEN_LIST_ITEM *) mir_realloc(proto->lists, sizeof(TLEN_LIST_ITEM)*(proto->listsCount+1)); item = &(proto->lists[proto->listsCount]); memset(item, 0, sizeof(TLEN_LIST_ITEM)); item->list = list; item->jid = s; item->nick = NULL; item->status = ID_STATUS_OFFLINE; item->statusMessage = NULL; item->group = NULL; item->messageEventIdStr = NULL; item->wantComposingEvent = FALSE; item->isTyping = FALSE; // item->type = NULL; item->ft = NULL; item->roomName = NULL; item->version = NULL; item->software = NULL; item->system = NULL; item->avatarHash = NULL; item->avatarFormat = PA_FORMAT_UNKNOWN; item->newAvatarDownloading = FALSE; item->versionRequested = FALSE; item->infoRequested = FALSE; proto->listsCount++; LeaveCriticalSection(&proto->csLists); return item; } void TlenListRemove(TlenProtocol *proto, TLEN_LIST list, const char *jid) { int i; EnterCriticalSection(&proto->csLists); i = TlenListExist(proto, list, jid); if (!i) { LeaveCriticalSection(&proto->csLists); return; } i--; TlenListFreeItemInternal(&(proto->lists[i])); proto->listsCount--; memmove(proto->lists+i, proto->lists+i+1, sizeof(TLEN_LIST_ITEM)*(proto->listsCount-i)); proto->lists = (TLEN_LIST_ITEM *) mir_realloc(proto->lists, sizeof(TLEN_LIST_ITEM)*proto->listsCount); LeaveCriticalSection(&proto->csLists); } void TlenListRemoveList(TlenProtocol *proto, TLEN_LIST list) { int i; i = 0; while ((i=TlenListFindNext(proto, list, i)) >= 0) { TlenListRemoveByIndex(proto, i); } } void TlenListRemoveByIndex(TlenProtocol *proto, int index) { EnterCriticalSection(&proto->csLists); if (index >= 0 && indexlistsCount) { TlenListFreeItemInternal(&(proto->lists[index])); proto->listsCount--; memmove(proto->lists+index, proto->lists+index+1, sizeof(TLEN_LIST_ITEM)*(proto->listsCount-index)); proto->lists = (TLEN_LIST_ITEM *) mir_realloc(proto->lists, sizeof(TLEN_LIST_ITEM)*proto->listsCount); } LeaveCriticalSection(&proto->csLists); } void TlenListAddResource(TlenProtocol *proto, TLEN_LIST list, const char *jid, int status, const char *statusMessage) { int i; EnterCriticalSection(&proto->csLists); i = TlenListExist(proto, list, jid); if (!i) { LeaveCriticalSection(&proto->csLists); return; } i--; if (proto->lists[i].statusMessage != NULL) mir_free(proto->lists[i].statusMessage); if (statusMessage) proto->lists[i].statusMessage = mir_strdup(statusMessage); else proto->lists[i].statusMessage = NULL; LeaveCriticalSection(&proto->csLists); } void TlenListRemoveResource(TlenProtocol *proto, TLEN_LIST list, const char *jid) { int i; EnterCriticalSection(&proto->csLists); i = TlenListExist(proto, list, jid); if (!i) { LeaveCriticalSection(&proto->csLists); return; } i--; LeaveCriticalSection(&proto->csLists); } int TlenListFindNext(TlenProtocol *proto, TLEN_LIST list, int fromOffset) { int i; EnterCriticalSection(&proto->csLists); i = (fromOffset >= 0) ? fromOffset : 0; for (; ilistsCount; i++) if (proto->lists[i].list == list) { LeaveCriticalSection(&proto->csLists); return i; } LeaveCriticalSection(&proto->csLists); return -1; } TLEN_LIST_ITEM *TlenListGetItemPtr(TlenProtocol *proto, TLEN_LIST list, const char *jid) { int i; EnterCriticalSection(&proto->csLists); i = TlenListExist(proto, list, jid); if (!i) { LeaveCriticalSection(&proto->csLists); return NULL; } i--; LeaveCriticalSection(&proto->csLists); return &(proto->lists[i]); } TLEN_LIST_ITEM *TlenListFindItemPtrById2(TlenProtocol *proto, TLEN_LIST list, const char *id) { int i; size_t len; char *p; len = strlen(id); EnterCriticalSection(&proto->csLists); for (i=0; ilistsCount; i++) { if (proto->lists[i].list == list) { p = proto->lists[i].id2; if (p != NULL) { if (!strncmp(p, id, len)) { LeaveCriticalSection(&proto->csLists); return &(proto->lists[i]); } } } } LeaveCriticalSection(&proto->csLists); return NULL; } TLEN_LIST_ITEM *TlenListGetItemPtrFromIndex(TlenProtocol *proto, int index) { EnterCriticalSection(&proto->csLists); if (index >= 0 && indexlistsCount) { LeaveCriticalSection(&proto->csLists); return &(proto->lists[index]); } LeaveCriticalSection(&proto->csLists); return NULL; }