Upstream tarball 9667
[amule.git] / src / FriendList.cpp
bloba861c20082e45ac600510690bf870c227c031234
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "FriendList.h" // Interface
29 #include <common/DataFileVersion.h>
31 #include "amule.h" // Needed for theApp: let it first or fail under win32
32 #include "ClientList.h" // Needed for CClientList
33 #include "updownclient.h" // Needed for CUpDownClient
34 #include "Friend.h" // Needed for CFriend
35 #include "CFile.h"
36 #include "Logger.h"
38 CFriendList::CFriendList()
40 LoadList();
43 CFriendList::~CFriendList()
45 SaveList();
47 while ( m_FriendList.size() ) {
48 delete m_FriendList.front();
49 m_FriendList.pop_front();
54 void CFriendList::AddFriend(CFriend* toadd)
56 m_FriendList.push_back(toadd);
57 SaveList();
61 void CFriendList::AddFriend(const CMD4Hash& userhash, uint32 lastSeen, uint32 lastUsedIP, uint32 lastUsedPort, uint32 lastChatted, const wxString& name)
63 CFriend* NewFriend = new CFriend( userhash, lastSeen, lastUsedIP, lastUsedPort, lastChatted, name);
65 AddFriend( NewFriend );
69 void CFriendList::AddFriend(CUpDownClient* toadd)
71 if ( toadd->IsFriend() ) {
72 return;
75 CFriend* NewFriend = new CFriend( toadd );
76 toadd->SetFriend(NewFriend);
78 AddFriend( NewFriend );
82 void CFriendList::RemoveFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort)
84 CFriend* toremove = FindFriend(userhash, lastUsedIP, lastUsedPort);
85 if (toremove) {
86 if ( toremove->GetLinkedClient() ){
87 toremove->GetLinkedClient()->SetFriendSlot(false);
88 toremove->GetLinkedClient()->SetFriend(NULL);
89 toremove->UnLinkClient();
92 m_FriendList.remove(toremove);
94 SaveList();
96 delete toremove;
100 void CFriendList::LoadList()
102 CPath metfile = CPath(theApp->ConfigDir + wxT("emfriends.met"));
104 if (!metfile.FileExists()) {
105 return;
108 CFile file;
109 try {
110 if ( file.Open(metfile) ) {
111 if ( file.ReadUInt8() /*header*/ == MET_HEADER ) {
112 uint32 nRecordsNumber = file.ReadUInt32();
113 for (uint32 i = 0; i < nRecordsNumber; i++) {
114 CFriend* Record = new CFriend();
115 Record->LoadFromFile(&file);
116 m_FriendList.push_back(Record);
119 } else {
120 AddLogLineM(false, _("Failed to open friend list file 'emfriends.met' for reading!"));
122 } catch (const CInvalidPacket& e) {
123 AddDebugLogLineM(true, logGeneral, wxT("Invalid entry in friend list, file may be corrupt: ") + e.what());
124 } catch (const CSafeIOException& e) {
125 AddDebugLogLineM(true, logGeneral, wxT("IO error while reading 'emfriends.met': ") + e.what());
131 void CFriendList::SaveList()
133 CFile file;
134 if (file.Create(theApp->ConfigDir + wxT("emfriends.met"), true)) {
135 try {
136 file.WriteUInt8(MET_HEADER);
137 file.WriteUInt32(m_FriendList.size());
139 for (FriendList::iterator it = m_FriendList.begin(); it != m_FriendList.end(); ++it) {
140 (*it)->WriteToFile(&file);
142 } catch (const CIOFailureException& e) {
143 AddDebugLogLineM(true, logGeneral, wxT("IO failure while saving 'emfriends.met': ") + e.what());
145 } else {
146 AddLogLineM(false, _("Failed to open friend list file 'emfriends.met' for writing!"));
151 CFriend* CFriendList::FindFriend(const CMD4Hash& userhash, uint32 dwIP, uint16 nPort)
154 for(FriendList::iterator it = m_FriendList.begin(); it != m_FriendList.end(); ++it) {
156 CFriend* cur_friend = *it;
157 // to avoid that unwanted clients become a friend, we have to distinguish between friends with
158 // a userhash and of friends which are identified by IP+port only.
159 if ( !userhash.IsEmpty() && cur_friend->HasHash() ) {
160 // check for a friend which has the same userhash as the specified one
161 if (cur_friend->GetUserHash() == userhash) {
162 return cur_friend;
164 } else if (cur_friend->GetIP() == dwIP && cur_friend->GetPort() == nPort) {
165 if (!userhash.IsEmpty() && !cur_friend->HasHash() ) {
166 // Friend without hash (probably IP entered through dialog)
167 // -> save the hash
168 cur_friend->SetUserHash(userhash);
169 SaveList();
171 return cur_friend;
175 return NULL;
179 bool CFriendList::IsAlreadyFriend( uint32 dwLastUsedIP, uint32 nLastUsedPort )
181 return (FindFriend( CMD4Hash(), dwLastUsedIP, nLastUsedPort ) != NULL);
185 void CFriendList::RemoveAllFriendSlots()
187 for(FriendList::iterator it = m_FriendList.begin(); it != m_FriendList.end(); ++it) {
188 CFriend* cur_friend = *it;
189 if ( cur_friend->GetLinkedClient() ) {
190 cur_friend->GetLinkedClient()->SetFriendSlot(false);
195 void CFriendList::RequestSharedFileList(const CMD4Hash& userhash, uint32 dwIP, uint16 nPort) {
196 CFriend* cur_friend = FindFriend(userhash, dwIP, nPort);
197 if (cur_friend) {
198 CUpDownClient* client = cur_friend->GetLinkedClient();
199 if (!client) {
200 client = new CUpDownClient(cur_friend->GetPort(), cur_friend->GetIP(), 0, 0, 0, true, true);
201 client->SetUserName(cur_friend->GetName());
202 theApp->clientlist->AddClient(client);
204 client->RequestSharedFileList();
208 void CFriendList::SetFriendSlot(const CMD4Hash& userhash, uint32 dwIP, uint16 nPort, bool new_state) {
209 CFriend* cur_friend = FindFriend(userhash, dwIP, nPort);
210 if (cur_friend && cur_friend->GetLinkedClient()) {
211 RemoveAllFriendSlots();
212 cur_friend->GetLinkedClient()->SetFriendSlot(new_state);
216 void CFriendList::StartChatSession(const CMD4Hash& userhash, uint32 dwIP, uint16 nPort) {
217 CFriend* friend_client = FindFriend(userhash, dwIP, nPort);
218 if (friend_client) {
219 CUpDownClient* client = friend_client->GetLinkedClient();
220 if (!client) {
221 client = new CUpDownClient(friend_client->GetPort(), friend_client->GetIP(), 0, 0, 0, true, true);
222 client->SetIP(friend_client->GetIP());
223 client->SetUserName(friend_client->GetName());
224 theApp->clientlist->AddClient(client);
225 friend_client->LinkClient(client);
227 } else {
228 AddLogLineC(_("CRITICAL - no client on StartChatSession"));
233 void CFriendList::UpdateFriendName(const CMD4Hash& userhash, const wxString& name, uint32 dwIP, uint16 nPort) {
234 CFriend* friend_client = FindFriend(userhash, dwIP, nPort);
235 friend_client->SetName(name);
236 SaveList();
238 // File_checked_for_headers