2 // This file is part of the aMule Project.
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 )
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
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.
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
38 CFriendList::CFriendList()
43 CFriendList::~CFriendList()
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
);
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() ) {
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
);
86 if ( toremove
->GetLinkedClient() ){
87 toremove
->GetLinkedClient()->SetFriendSlot(false);
88 toremove
->GetLinkedClient()->SetFriend(NULL
);
89 toremove
->UnLinkClient();
92 m_FriendList
.remove(toremove
);
100 void CFriendList::LoadList()
102 CPath metfile
= CPath(theApp
->ConfigDir
+ wxT("emfriends.met"));
104 if (!metfile
.FileExists()) {
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
);
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()
134 if (file
.Create(theApp
->ConfigDir
+ wxT("emfriends.met"), true)) {
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());
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
) {
164 } else if (cur_friend
->GetIP() == dwIP
&& cur_friend
->GetPort() == nPort
) {
173 bool CFriendList::IsAlreadyFriend( uint32 dwLastUsedIP
, uint32 nLastUsedPort
)
175 return (FindFriend( CMD4Hash(), dwLastUsedIP
, nLastUsedPort
) != NULL
);
179 void CFriendList::RemoveAllFriendSlots()
181 for(FriendList::iterator it
= m_FriendList
.begin(); it
!= m_FriendList
.end(); ++it
) {
182 CFriend
* cur_friend
= *it
;
183 if ( cur_friend
->GetLinkedClient() ) {
184 cur_friend
->GetLinkedClient()->SetFriendSlot(false);
189 void CFriendList::RequestSharedFileList(const CMD4Hash
& userhash
, uint32 dwIP
, uint16 nPort
) {
190 CFriend
* cur_friend
= FindFriend(userhash
, dwIP
, nPort
);
192 CUpDownClient
* client
= cur_friend
->GetLinkedClient();
194 client
= new CUpDownClient(cur_friend
->GetPort(), cur_friend
->GetIP(), 0, 0, 0, true, true);
195 client
->SetUserName(cur_friend
->GetName());
196 theApp
->clientlist
->AddClient(client
);
198 client
->RequestSharedFileList();
202 void CFriendList::SetFriendSlot(const CMD4Hash
& userhash
, uint32 dwIP
, uint16 nPort
, bool new_state
) {
203 CFriend
* cur_friend
= FindFriend(userhash
, dwIP
, nPort
);
204 if (cur_friend
&& cur_friend
->GetLinkedClient()) {
205 RemoveAllFriendSlots();
206 cur_friend
->GetLinkedClient()->SetFriendSlot(new_state
);
210 void CFriendList::StartChatSession(const CMD4Hash
& userhash
, uint32 dwIP
, uint16 nPort
) {
211 CFriend
* friend_client
= FindFriend(userhash
, dwIP
, nPort
);
213 CUpDownClient
* client
= friend_client
->GetLinkedClient();
215 client
= new CUpDownClient(friend_client
->GetPort(), friend_client
->GetIP(), 0, 0, 0, true, true);
216 client
->SetIP(friend_client
->GetIP());
217 client
->SetUserName(friend_client
->GetName());
218 theApp
->clientlist
->AddClient(client
);
219 friend_client
->LinkClient(client
);
222 AddLogLineC(_("CRITICAL - no client on StartChatSession"));
227 void CFriendList::UpdateFriendName(const CMD4Hash
& userhash
, const wxString
& name
, uint32 dwIP
, uint16 nPort
) {
228 CFriend
* friend_client
= FindFriend(userhash
, dwIP
, nPort
);
229 friend_client
->SetName(name
);
232 // File_checked_for_headers