From 3b55a62fdcb1f8222de3c2c8fbed530792c419a0 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 12 Oct 2012 14:53:57 +0000 Subject: GTalkExt, ICQ, IRC, Jabber: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/JabberG/src/jabber_list.cpp | 474 ++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) create mode 100644 protocols/JabberG/src/jabber_list.cpp (limited to 'protocols/JabberG/src/jabber_list.cpp') diff --git a/protocols/JabberG/src/jabber_list.cpp b/protocols/JabberG/src/jabber_list.cpp new file mode 100644 index 0000000000..8a956ebc47 --- /dev/null +++ b/protocols/JabberG/src/jabber_list.cpp @@ -0,0 +1,474 @@ +/* + +Jabber Protocol Plugin for Miranda IM +Copyright ( C ) 2002-04 Santithorn Bunchua +Copyright ( C ) 2005-12 George Hazan +Copyright ( C ) 2007 Maxim Mluhov + +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 "jabber.h" +#include "jabber_list.h" + +void MenuUpdateSrmmIcon(JABBER_LIST_ITEM *item); + +///////////////////////////////////////////////////////////////////////////////////////// +// List item freeing + +static void JabberListFreeResourceInternal( JABBER_RESOURCE_STATUS *r) +{ + if ( r->resourceName ) mir_free( r->resourceName ); + if ( r->nick ) mir_free( r->nick ); + if ( r->statusMessage ) mir_free( r->statusMessage ); + if ( r->software ) mir_free( r->software ); + if ( r->version ) mir_free( r->version ); + if ( r->system ) mir_free( r->system ); + if ( r->szCapsNode ) mir_free( r->szCapsNode ); + if ( r->szCapsVer ) mir_free( r->szCapsVer ); + if ( r->szCapsExt ) mir_free( r->szCapsExt ); + if ( r->szRealJid ) mir_free( r->szRealJid ); + if ( r->pSoftwareInfo) delete r->pSoftwareInfo; +} + +static void JabberListFreeItemInternal( JABBER_LIST_ITEM *item ) +{ + if ( item == NULL ) + return; + + if ( item->jid ) mir_free( item->jid ); + if ( item->nick ) mir_free( item->nick ); + + JABBER_RESOURCE_STATUS* r = item->resource; + for ( int i=0; i < item->resourceCount; i++, r++ ) + JabberListFreeResourceInternal( r ); + if ( item->resource ) mir_free( item->resource ); + + JabberListFreeResourceInternal( &item->itemResource ); + + if ( item->group ) mir_free( item->group ); + if ( item->photoFileName ) { + DeleteFile( item->photoFileName ); + mir_free( item->photoFileName ); + } + if ( item->messageEventIdStr ) mir_free( item->messageEventIdStr ); + if ( item->name ) mir_free( item->name ); + if ( item->type ) mir_free( item->type ); + if ( item->service ) mir_free( item->service ); + if ( item->password ) mir_free( item->password ); + if ( item->list==LIST_ROSTER && item->ft ) delete item->ft; + mir_free( item ); +} + +void CJabberProto::ListWipe( void ) +{ + int i; + + EnterCriticalSection( &m_csLists ); + for ( i=0; i < m_lstRoster.getCount(); i++ ) + JabberListFreeItemInternal( m_lstRoster[i] ); + + m_lstRoster.destroy(); + LeaveCriticalSection( &m_csLists ); +} + +int CJabberProto::ListExist( JABBER_LIST list, const TCHAR* jid ) +{ + JABBER_LIST_ITEM tmp; + tmp.list = list; + tmp.jid = (TCHAR*)jid; + tmp.bUseResource = FALSE; + + EnterCriticalSection( &m_csLists ); + + //fyr + if ( list == LIST_ROSTER ) + { + tmp.list = LIST_CHATROOM; + int id = m_lstRoster.getIndex( &tmp ); + if ( id != -1) + tmp.bUseResource = TRUE; + tmp.list = list; + } + + int idx = m_lstRoster.getIndex( &tmp ); + + if ( idx == -1 ) { + LeaveCriticalSection( &m_csLists ); + return 0; + } + + LeaveCriticalSection( &m_csLists ); + return idx+1; +} + +JABBER_LIST_ITEM *CJabberProto::ListAdd( JABBER_LIST list, const TCHAR* jid ) +{ + JABBER_LIST_ITEM* item; + BOOL bUseResource=FALSE; + EnterCriticalSection( &m_csLists ); + if (( item = ListGetItemPtr( list, jid )) != NULL ) { + LeaveCriticalSection( &m_csLists ); + return item; + } + + TCHAR *s = mir_tstrdup( jid ); + TCHAR *q = NULL; + // strip resource name if any + //fyr + if ( !((list== LIST_ROSTER ) && ListExist(LIST_CHATROOM, jid))) { // but only if it is not chat room contact + if ( list != LIST_VCARD_TEMP ) { + TCHAR *p; + if (( p = _tcschr( s, '@' )) != NULL ) + if (( q = _tcschr( p, '/' )) != NULL ) + *q = '\0'; + } + } else { + bUseResource=TRUE; + } + + if ( !bUseResource && list== LIST_ROSTER ) + { + //if it is a chat room keep resource and made it resource sensitive + if ( ChatRoomHContactFromJID( s )) + { + if (q != NULL) *q='/'; + bUseResource=TRUE; + } + } + item = ( JABBER_LIST_ITEM* )mir_alloc( sizeof( JABBER_LIST_ITEM )); + ZeroMemory( item, sizeof( JABBER_LIST_ITEM )); + item->list = list; + item->jid = s; + item->itemResource.status = ID_STATUS_OFFLINE; + item->resource = NULL; + item->resourceMode = RSMODE_LASTSEEN; + item->lastSeenResource = -1; + item->manualResource = -1; + item->bUseResource = bUseResource; + + m_lstRoster.insert( item ); + LeaveCriticalSection( &m_csLists ); + + MenuUpdateSrmmIcon(item); + return item; +} + +void CJabberProto::ListRemove( JABBER_LIST list, const TCHAR* jid ) +{ + EnterCriticalSection( &m_csLists ); + int i = ListExist( list, jid ); + if ( i != 0 ) { + JabberListFreeItemInternal( m_lstRoster[ --i ] ); + m_lstRoster.remove( i ); + } + LeaveCriticalSection( &m_csLists ); +} + +void CJabberProto::ListRemoveList( JABBER_LIST list ) +{ + int i = 0; + while (( i=ListFindNext( list, i )) >= 0 ) + ListRemoveByIndex( i ); +} + +void CJabberProto::ListRemoveByIndex( int index ) +{ + EnterCriticalSection( &m_csLists ); + if ( index >= 0 && index < m_lstRoster.getCount()) { + JabberListFreeItemInternal( m_lstRoster[index] ); + m_lstRoster.remove( index ); + } + LeaveCriticalSection( &m_csLists ); +} + +JABBER_RESOURCE_STATUS *CJabberProto::ListFindResource( JABBER_LIST list, const TCHAR* jid ) +{ + JABBER_RESOURCE_STATUS *result = NULL; + + EnterCriticalSection( &m_csLists ); + int i = ListExist( list, jid ); + if ( !i ) { + LeaveCriticalSection( &m_csLists ); + return 0; + } + + JABBER_LIST_ITEM* LI = m_lstRoster[i-1]; + + const TCHAR* p = _tcschr( jid, '@' ); + const TCHAR* q = _tcschr(( p == NULL ) ? jid : p, '/' ); + if (q) + { + const TCHAR *resource = q+1; + if (*resource) + for ( int j=0; j < LI->resourceCount; j++ ) + if ( !_tcscmp( LI->resource[j].resourceName, resource )) + { + result = LI->resource + j; + break; + } + } + + LeaveCriticalSection( &m_csLists ); + + return result; +} + +int CJabberProto::ListAddResource( JABBER_LIST list, const TCHAR* jid, int status, const TCHAR* statusMessage, char priority, const TCHAR* nick ) +{ + EnterCriticalSection( &m_csLists ); + int i = ListExist( list, jid ); + if ( !i ) { + LeaveCriticalSection( &m_csLists ); + return 0; + } + + JABBER_LIST_ITEM* LI = m_lstRoster[i-1]; + int bIsNewResource = false, j; + + const TCHAR* p = _tcschr( jid, '@' ); + const TCHAR* q = _tcschr(( p == NULL ) ? jid : p, '/' ); + if ( q ) { + const TCHAR* resource = q+1; + if ( resource[0] ) { + JABBER_RESOURCE_STATUS* r = LI->resource; + for ( j=0; j < LI->resourceCount; j++, r++ ) { + if ( !_tcscmp( r->resourceName, resource )) { + // Already exist, update status and statusMessage + r->status = status; + replaceStrT( r->statusMessage, statusMessage ); + r->priority = priority; + break; + } } + + if ( j >= LI->resourceCount ) { + // Not already exist, add new resource + LI->resource = ( JABBER_RESOURCE_STATUS * ) mir_realloc( LI->resource, ( LI->resourceCount+1 )*sizeof( JABBER_RESOURCE_STATUS )); + bIsNewResource = true; + r = LI->resource + LI->resourceCount++; + memset( r, 0, sizeof( JABBER_RESOURCE_STATUS )); + r->status = status; + r->affiliation = AFFILIATION_NONE; + r->role = ROLE_NONE; + r->resourceName = mir_tstrdup( resource ); + r->nick = mir_tstrdup( nick ); + if ( statusMessage ) + r->statusMessage = mir_tstrdup( statusMessage ); + r->priority = priority; + } } + } + // No resource, update the main statusMessage + else { + LI->itemResource.status = status; + replaceStrT( LI->itemResource.statusMessage, statusMessage ); + } + + LeaveCriticalSection( &m_csLists ); + + MenuUpdateSrmmIcon(LI); + return bIsNewResource; +} + +void CJabberProto::ListRemoveResource( JABBER_LIST list, const TCHAR* jid ) +{ + EnterCriticalSection( &m_csLists ); + int i = ListExist( list, jid ); + JABBER_LIST_ITEM* LI = m_lstRoster[i-1]; + if ( !i || LI == NULL ) { + LeaveCriticalSection( &m_csLists ); + return; + } + + const TCHAR* p = _tcschr( jid, '@' ); + const TCHAR* q = _tcschr(( p == NULL ) ? jid : p, '/' ); + if ( q ) { + const TCHAR* resource = q+1; + if ( resource[0] ) { + JABBER_RESOURCE_STATUS* r = LI->resource; + int j; + for ( j=0; j < LI->resourceCount; j++, r++ ) { + if ( !_tcsicmp( r->resourceName, resource )) + break; + } + if ( j < LI->resourceCount ) { + // Found last seen resource ID to be removed + if ( LI->lastSeenResource == j ) + LI->lastSeenResource = -1; + else if ( LI->lastSeenResource > j ) + LI->lastSeenResource--; + // update manually selected resource ID + if (LI->resourceMode == RSMODE_MANUAL) + { + if ( LI->manualResource == j ) + { + LI->resourceMode = RSMODE_LASTSEEN; + LI->manualResource = -1; + } else if ( LI->manualResource > j ) + LI->manualResource--; + } + + // Update MirVer due to possible resource changes + UpdateMirVer(LI); + + JabberListFreeResourceInternal( r ); + + if ( LI->resourceCount-- == 1 ) { + mir_free( r ); + LI->resource = NULL; + } + else { + memmove( r, r+1, ( LI->resourceCount-j )*sizeof( JABBER_RESOURCE_STATUS )); + LI->resource = ( JABBER_RESOURCE_STATUS* )mir_realloc( LI->resource, LI->resourceCount*sizeof( JABBER_RESOURCE_STATUS )); + } } } } + + LeaveCriticalSection( &m_csLists ); + + MenuUpdateSrmmIcon(LI); +} + +TCHAR* CJabberProto::ListGetBestResourceNamePtr( const TCHAR* jid ) +{ + EnterCriticalSection( &m_csLists ); + int i = ListExist( LIST_ROSTER, jid ); + if ( !i ) { + LeaveCriticalSection( &m_csLists ); + return NULL; + } + + TCHAR* res = NULL; + + JABBER_LIST_ITEM* LI = m_lstRoster[i-1]; + if ( LI->resourceCount > 1 ) { + if ( LI->resourceMode == RSMODE_LASTSEEN && LI->lastSeenResource>=0 && LI->lastSeenResource < LI->resourceCount ) + res = LI->resource[ LI->lastSeenResource ].resourceName; + else if (LI->resourceMode == RSMODE_MANUAL && LI->manualResource>=0 && LI->manualResource < LI->resourceCount ) + res = LI->resource[ LI->manualResource ].resourceName; + else { + int nBestPos = -1, nBestPri = -200, j; + for ( j = 0; j < LI->resourceCount; j++ ) { + if ( LI->resource[ j ].priority > nBestPri ) { + nBestPri = LI->resource[ j ].priority; + nBestPos = j; + } + } + if ( nBestPos != -1 ) + res = LI->resource[ nBestPos ].resourceName; + } + } + + if ( !res && LI->resource) + res = LI->resource[0].resourceName; + + LeaveCriticalSection( &m_csLists ); + return res; +} + +TCHAR* CJabberProto::ListGetBestClientResourceNamePtr( const TCHAR* jid ) +{ + EnterCriticalSection( &m_csLists ); + int i = ListExist( LIST_ROSTER, jid ); + if ( !i ) { + LeaveCriticalSection( &m_csLists ); + return NULL; + } + + JABBER_LIST_ITEM* LI = m_lstRoster[i-1]; + TCHAR* res = ListGetBestResourceNamePtr( jid ); + if ( res == NULL ) { + JABBER_RESOURCE_STATUS* r = LI->resource; + int status = ID_STATUS_OFFLINE; + res = NULL; + for ( i=0; i < LI->resourceCount; i++ ) { + int s = r[i].status; + BOOL foundBetter = FALSE; + switch ( s ) { + case ID_STATUS_FREECHAT: + foundBetter = TRUE; + break; + case ID_STATUS_ONLINE: + if ( status != ID_STATUS_FREECHAT ) + foundBetter = TRUE; + break; + case ID_STATUS_DND: + if ( status != ID_STATUS_FREECHAT && status != ID_STATUS_ONLINE ) + foundBetter = TRUE; + break; + case ID_STATUS_AWAY: + if ( status != ID_STATUS_FREECHAT && status != ID_STATUS_ONLINE && status != ID_STATUS_DND ) + foundBetter = TRUE; + break; + case ID_STATUS_NA: + if ( status != ID_STATUS_FREECHAT && status != ID_STATUS_ONLINE && status != ID_STATUS_DND && status != ID_STATUS_AWAY ) + foundBetter = TRUE; + break; + } + if ( foundBetter ) { + res = r[i].resourceName; + status = s; + } } } + + LeaveCriticalSection( &m_csLists ); + return res; +} + +int CJabberProto::ListFindNext( JABBER_LIST list, int fromOffset ) +{ + EnterCriticalSection( &m_csLists ); + int i = ( fromOffset >= 0 ) ? fromOffset : 0; + for ( ; ilist == list ) { + LeaveCriticalSection( &m_csLists ); + return i; + } + LeaveCriticalSection( &m_csLists ); + return -1; +} + +JABBER_LIST_ITEM *CJabberProto::ListGetItemPtr( JABBER_LIST list, const TCHAR* jid ) +{ + EnterCriticalSection( &m_csLists ); + int i = ListExist( list, jid ); + if ( !i ) { + LeaveCriticalSection( &m_csLists ); + return NULL; + } + i--; + LeaveCriticalSection( &m_csLists ); + return m_lstRoster[i]; +} + +JABBER_LIST_ITEM *CJabberProto::ListGetItemPtrFromIndex( int index ) +{ + EnterCriticalSection( &m_csLists ); + if ( index >= 0 && index < m_lstRoster.getCount()) { + LeaveCriticalSection( &m_csLists ); + return m_lstRoster[index]; + } + LeaveCriticalSection( &m_csLists ); + return NULL; +} + +BOOL CJabberProto::ListLock() +{ + EnterCriticalSection( &m_csLists ); + return TRUE; +} + +BOOL CJabberProto::ListUnlock() +{ + LeaveCriticalSection( &m_csLists ); + return TRUE; +} -- cgit v1.2.3