/* * xfirelib - C++ Library for the xfire protocol. * Copyright (C) 2006 by * Beat Wolf / http://gfire.sf.net * Herbert Poul / http://goim.us * http://xfirelib.sphene.net * * 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "stdafx.h" #include #include #include "buddylist.h" #include "buddylistonlinepacket.h" #include "buddylistgamespacket.h" #include "buddylistgames2packet.h" #include "recvremovebuddypacket.h" #include "recvstatusmessagepacket.h" #include "recvbuddychangednick.h" #include "xdebug.h" //buddylist verarbeitung von der main in buddylist verschoben, um doppelte schleifenverarbeitung zuunterbinden #include "baseProtocol.h" extern HANDLE handlingBuddys(xfirelib::BuddyListEntry *entry, int clan=0,char* group=NULL,BOOL dontscan=FALSE); extern void setBuddyStatusMsg(xfirelib::BuddyListEntry *entry); namespace xfirelib { using namespace std; BuddyList::BuddyList(Client *client) { entries = new vector; //clan entries initialisieren - dufte entriesClan = new vector; this->client = client; this->client->addPacketListener( this ); } BuddyList::~BuddyList() { for(vector::iterator it = entries->begin(); it != entries->end(); it++) { delete *it; } delete entries; //clan entries entfernen - dufte for(vector::iterator it = entriesClan->begin(); it != entriesClan->end(); it++) { delete *it; } delete entriesClan; } BuddyListEntry *BuddyList::getBuddyById(long userid) { for(uint i = 0 ; i < entries->size() ; i++) { BuddyListEntry *entry = entries->at(i); if(entry->userid == userid) return entry; } //clan entries durchsuchen - dufte for(uint i = 0 ; i < entriesClan->size() ; i++) { BuddyListEntry *entry = entriesClan->at(i); if(entry->userid == userid) return entry; } return 0; } BuddyListEntry *BuddyList::getBuddyByName(string username) { for(uint i = 0 ; i < entries->size() ; i++) { BuddyListEntry *entry = entries->at(i); if(entry->username == username) return entry; } //clan entries durchsuchen - dufte for(uint i = 0 ; i < entriesClan->size() ; i++) { BuddyListEntry *entry = entriesClan->at(i); if(entry->username == username) return entry; } return 0; } BuddyListEntry *BuddyList::getBuddyBySid(const char *sid) { for(uint i = 0 ; i < entries->size() ; i++) { BuddyListEntry *entry = entries->at(i); if(memcmp((void *)sid,(void *)entry->sid,16) == 0) return entry; } //clan entries durchsuchen - dufte for(uint i = 0 ; i < entriesClan->size() ; i++) { BuddyListEntry *entry = entriesClan->at(i); if(memcmp((void *)sid,(void *)entry->sid,16) == 0) return entry; } return 0; } void BuddyList::initEntries(BuddyListNamesPacket *buddyNames) { for(uint i = 0 ; i < buddyNames->usernames->size() ; i++) { BuddyListEntry *entry = new BuddyListEntry; entry->username = buddyNames->usernames->at(i); entry->userid = buddyNames->userids->at(i); entry->nick = buddyNames->nicks->at(i); //buddies in miranda verarbeiten handlingBuddys(entry,0,NULL); entries->push_back(entry); } } // funktion zum initialisieren der clanliste - dufte void BuddyList::initEntriesClan(ClanBuddyListNamesPacket *buddyNames) { for(uint i = 0 ; i < buddyNames->usernames->size() ; i++) { BuddyListEntry *entry = new BuddyListEntry; entry->username = buddyNames->usernames->at(i); entry->userid = buddyNames->userids->at(i); entry->nick = buddyNames->nicks->at(i); entry->clanid = buddyNames->clanid; /* ## buddies im miranda verarbietn */ char temp[255]; char * dummy; mir_snprintf(temp,255,"Clan_%d",entry->clanid); DBVARIANT dbv; if(!db_get(NULL,protocolname,temp,&dbv)) { dummy=dbv.pszVal; } else dummy=NULL; handlingBuddys(entry,entry->clanid,dummy); /* ## ende */ entriesClan->push_back(entry); } } void BuddyList::updateFriendsofFriend(FriendsBuddyListNamesPacket* friends) { for(uint i = 0 ; i < friends->sids->size() ; i++) { BuddyListEntry *entry = getBuddyBySid( friends->sids->at(i) ); if(entry){ XDEBUG2("Friends of Friend %s!\n",friends->usernames->at(i).c_str()); entry->nick=friends->nicks->at(i); entry->username=friends->usernames->at(i); entry->userid=friends->userids->at(i); }else{ XERROR(("updateFriendsofFriendBuddies: sid not found!\n")); } } } void BuddyList::updateOnlineBuddies(BuddyListOnlinePacket* buddiesOnline) { for(uint i = 0 ; i < buddiesOnline->userids->size() ; i++) { BuddyListEntry *entry = getBuddyById( buddiesOnline->userids->at(i) ); if(entry){ entry->setSid( buddiesOnline->sids->at(i) ); //buddies in miranda verarbeiten handlingBuddys(entry,0,NULL); }else{ XERROR(("updateOnlineBuddies: Could not find buddy with this sid!\n")); } } } void BuddyList::updateBuddiesGame(BuddyListGamesPacket* buddiesGames) { bool isFirst = buddiesGames->getPacketId() == XFIRE_BUDDYS_GAMES_ID; for(uint i = 0 ; i < buddiesGames->sids->size() ; i++) { BuddyListEntry *entry = getBuddyBySid( buddiesGames->sids->at(i) ); if(!entry) { //nicht zuordbare sids zuordnen XERROR("Add dummy Contact in buddylist for friends of friends!\n"); BuddyListEntry *newentry = new BuddyListEntry; newentry->username = ""; newentry->userid = 0; newentry->nick = ""; newentry->setSid(buddiesGames->sids->at(i)); entries->push_back(newentry); //nochmal entry suchen entry = newentry; //getBuddyBySid( buddiesGames->sids->at(i) ); } if(entry){ if(isFirst) { entry->game = buddiesGames->gameids->at(i); delete entry->gameObj; entry->gameObj = NULL; } else { entry->game2 = buddiesGames->gameids->at(i); delete entry->game2Obj; entry->game2Obj = NULL; } XDEBUG(( "Resolving Game... \n" )); XFireGameResolver *resolver = client->getGameResolver(); if(resolver) { XDEBUG(( "Resolving Game... \n" )); if(isFirst) entry->gameObj = resolver->resolveGame( entry->game, i, buddiesGames ); else entry->game2Obj = resolver->resolveGame( entry->game2, i, buddiesGames ); } else { XDEBUG(( "No GameResolver ? :(\n" )); } XDEBUG(( "%s: Game (%ld): %s / Game2 (%ld): %s\n", entry->username.c_str(), entry->game, (entry->gameObj == NULL ? "UNKNOWN" : entry->gameObj->getGameName().c_str()), entry->game2, (entry->game2Obj== NULL ? "UNKNOWN" :entry->game2Obj->getGameName().c_str()) )); }else{ XERROR("updateBuddiesGame: Could not find buddy with this sid!\n"); } } } void BuddyList::receivedPacket(XFirePacket *packet) { XFirePacketContent *content = packet->getContent(); if(content == 0) return; XDEBUG2( "hmm... %d\n", content->getPacketId() ); switch(content->getPacketId()) { case XFIRE_BUDDYS_NAMES_ID: { XINFO(( "Received Buddy List..\n" )); this->initEntries( (BuddyListNamesPacket*)content ); break; } case XFIRE_CLAN_BUDDYS_NAMES_ID: { XINFO(( "Received Clan Buddy List..\n" )); this->initEntriesClan( (ClanBuddyListNamesPacket*)content ); break; } //neue nicks updaten, dufte case XFIRE_RECVBUDDYCHANGEDNICK: { RecvBuddyChangedNick* recvchangednick=(RecvBuddyChangedNick*)content; XINFO(( "Received new nick of a buddy..\n" )); BuddyListEntry* entry=NULL; entry=this->getBuddyById(recvchangednick->userid); if(entry) { entry->nick=recvchangednick->newnick; recvchangednick->entry=(void*)entry; handlingBuddys(entry,0,NULL); } break; } case XFIRE_BUDDYS_ONLINE_ID: { XINFO(( "Received Buddy Online Packet..\n" )); this->updateOnlineBuddies( (BuddyListOnlinePacket *)content ); break; } case XFIRE_FRIENDS_BUDDYS_NAMES_ID: { XINFO(( "Received Friends of Friend..\n" )); this->updateFriendsofFriend( (FriendsBuddyListNamesPacket *)content ); break; } case XFIRE_BUDDYS_GAMES2_ID: case XFIRE_BUDDYS_GAMES_ID: { XINFO(( "Recieved the game a buddy is playing..\n" )); this->updateBuddiesGame( (BuddyListGamesPacket *)content ); break; } case XFIRE_RECVREMOVEBUDDYPACKET: { RecvRemoveBuddyPacket *p = (RecvRemoveBuddyPacket*)content; XDEBUG2( "Buddy was removed from contact list (userid: %ld)\n", p->userid ); std::vector::iterator i = entries->begin(); while( i != entries->end() ) { if((*i)->userid == p->userid) { BuddyListEntry *buddy = *i; XINFO(( "%s (%s) was removed from BuddyList.\n", buddy->username.c_str(), buddy->nick.c_str() )); p->username = buddy->username; p->handle = buddy->hcontact; // handle übergeben - dufte entries->erase(i); // i.erase(); break; // we are done. } ++i; } break; } case XFIRE_RECV_STATUSMESSAGE_PACKET_ID: { RecvStatusMessagePacket *status = (RecvStatusMessagePacket*) content; //status->entries=new PBuddyListEntry[status->sids->size]; for(uint i = 0 ; i < status->sids->size() ; i++) { BuddyListEntry *entry = getBuddyBySid( status->sids->at(i) ); //status->entries[i]=entry; if(entry == NULL) { XERROR(( "No such Entry - Got StatusMessage from someone who is not in the buddylist ??\n" )); return; } else { entry->statusmsg = status->msgs->at(i); setBuddyStatusMsg(entry); //auf eine funktion reduziert, verringert cpuauslastung und beseitigt das //das problem der fehlenden statusmsg } } break; } } } BuddyListEntry::~BuddyListEntry() { if(lastpopup) { delete[] lastpopup; lastpopup=NULL; } } BuddyListEntry::BuddyListEntry() { memset(sid,0,16); statusmsg = std::string(); game = 0; game2 = 0; gameObj = NULL; game2Obj = NULL; hcontact = NULL; clanid = 0; lastpopup=NULL; } bool BuddyListEntry::isOnline() { for(int i = 0 ; i < 16 ; i++) { if(sid[i]) return true; } return false; } void BuddyListEntry::setSid(const char *sid) { int s=0; for(int i = 0 ; i < 16 ; i++) { //wenn buddy offline geht, seine gameinfos zurücksetzen - dufte if(sid[i]) { s=1; break; } } if(s) { this->statusmsg = std::string(); this->game = 0; this->game2 = 0; this->gameObj = NULL; this->game2Obj = NULL; } memcpy(this->sid,sid,16); } };