2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2011 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
37 #include "GuiEvents.h"
38 #include "Preferences.h" // Needed for thePrefs
40 CFriendList::CFriendList()
44 CFriendList::~CFriendList()
48 DeleteContents(m_FriendList
);
52 void CFriendList::AddFriend(CFriend
* toadd
, bool notify
)
54 m_FriendList
.push_back(toadd
);
57 Notify_ChatUpdateFriend(toadd
);
62 void CFriendList::AddFriend(const CMD4Hash
& userhash
, uint32 lastUsedIP
, uint32 lastUsedPort
, const wxString
& name
, uint32 lastSeen
, uint32 lastChatted
)
64 CFriend
* NewFriend
= new CFriend( userhash
, lastSeen
, lastUsedIP
, lastUsedPort
, lastChatted
, name
);
66 AddFriend( NewFriend
);
71 void CFriendList::AddFriend(const CClientRef
& toadd
)
73 if ( toadd
.IsFriend() ) {
77 CFriend
* NewFriend
= new CFriend( toadd
);
78 toadd
.SetFriend(NewFriend
);
80 AddFriend(NewFriend
, false); // has already notified
84 void CFriendList::RemoveFriend(CFriend
* toremove
)
87 CClientRef client
= toremove
->GetLinkedClient();
88 if (client
.IsLinked()) {
89 client
.SetFriendSlot(false);
90 client
.SetFriend(NULL
);
91 toremove
->UnLinkClient();
94 m_FriendList
.remove(toremove
);
98 Notify_ChatRemoveFriend(toremove
); // this deletes the friend
102 void CFriendList::LoadList()
104 CPath metfile
= CPath(thePrefs::GetConfigDir() + wxT("emfriends.met"));
106 if (!metfile
.FileExists()) {
112 if ( file
.Open(metfile
) ) {
113 if ( file
.ReadUInt8() /*header*/ == MET_HEADER
) {
114 uint32 nRecordsNumber
= file
.ReadUInt32();
115 for (uint32 i
= 0; i
< nRecordsNumber
; i
++) {
116 CFriend
* Record
= new CFriend();
117 Record
->LoadFromFile(&file
);
118 m_FriendList
.push_back(Record
);
119 Notify_ChatUpdateFriend(Record
);
123 AddLogLineN(_("Failed to open friend list file 'emfriends.met' for reading!"));
125 } catch (const CInvalidPacket
& e
) {
126 AddDebugLogLineC(logGeneral
, wxT("Invalid entry in friend list, file may be corrupt: ") + e
.what());
127 } catch (const CSafeIOException
& e
) {
128 AddDebugLogLineC(logGeneral
, wxT("IO error while reading 'emfriends.met': ") + e
.what());
134 void CFriendList::SaveList()
137 if (file
.Create(thePrefs::GetConfigDir() + wxT("emfriends.met"), true)) {
139 file
.WriteUInt8(MET_HEADER
);
140 file
.WriteUInt32(m_FriendList
.size());
142 for (FriendList::iterator it
= m_FriendList
.begin(); it
!= m_FriendList
.end(); ++it
) {
143 (*it
)->WriteToFile(&file
);
145 } catch (const CIOFailureException
& e
) {
146 AddDebugLogLineC(logGeneral
, wxT("IO failure while saving 'emfriends.met': ") + e
.what());
149 AddLogLineN(_("Failed to open friend list file 'emfriends.met' for writing!"));
154 CFriend
* CFriendList::FindFriend(const CMD4Hash
& userhash
, uint32 dwIP
, uint16 nPort
)
157 for(FriendList::iterator it
= m_FriendList
.begin(); it
!= m_FriendList
.end(); ++it
) {
159 CFriend
* cur_friend
= *it
;
160 // to avoid that unwanted clients become a friend, we have to distinguish between friends with
161 // a userhash and of friends which are identified by IP+port only.
162 if ( !userhash
.IsEmpty() && cur_friend
->HasHash() ) {
163 // check for a friend which has the same userhash as the specified one
164 if (cur_friend
->GetUserHash() == userhash
) {
167 } else if (cur_friend
->GetIP() == dwIP
&& cur_friend
->GetPort() == nPort
) {
168 if (!userhash
.IsEmpty() && !cur_friend
->HasHash() ) {
169 // Friend without hash (probably IP entered through dialog)
171 cur_friend
->SetUserHash(userhash
);
182 CFriend
* CFriendList::FindFriend(uint32 ecid
)
184 for (FriendList::iterator it
= m_FriendList
.begin(); it
!= m_FriendList
.end(); ++it
) {
185 CFriend
* cur_friend
= *it
;
186 if (cur_friend
->ECID() == ecid
) {
195 bool CFriendList::IsAlreadyFriend( uint32 dwLastUsedIP
, uint32 nLastUsedPort
)
197 return (FindFriend( CMD4Hash(), dwLastUsedIP
, nLastUsedPort
) != NULL
);
201 void CFriendList::RemoveAllFriendSlots()
203 for(FriendList::iterator it
= m_FriendList
.begin(); it
!= m_FriendList
.end(); ++it
) {
204 CFriend
* cur_friend
= *it
;
205 if (cur_friend
->GetLinkedClient().IsLinked()) {
206 cur_friend
->GetLinkedClient().SetFriendSlot(false);
212 void CFriendList::RequestSharedFileList(CFriend
* cur_friend
)
215 CUpDownClient
* client
= cur_friend
->GetLinkedClient().GetClient();
217 client
= new CUpDownClient(cur_friend
->GetPort(), cur_friend
->GetIP(), 0, 0, 0, true, true);
218 client
->SetUserName(cur_friend
->GetName());
219 theApp
->clientlist
->AddClient(client
);
220 cur_friend
->LinkClient(CCLIENTREF(client
, wxT("CFriendList::RequestSharedFileList")));
222 client
->RequestSharedFileList();
227 void CFriendList::SetFriendSlot(CFriend
* Friend
, bool new_state
)
229 if (Friend
&& Friend
->GetLinkedClient().IsLinked()) {
230 RemoveAllFriendSlots();
231 Friend
->GetLinkedClient().SetFriendSlot(new_state
);
232 CoreNotify_Upload_Resort_Queue();
237 void CFriendList::StartChatSession(CFriend
* Friend
)
240 CUpDownClient
* client
= Friend
->GetLinkedClient().GetClient();
242 client
= new CUpDownClient(Friend
->GetPort(), Friend
->GetIP(), 0, 0, 0, true, true);
243 client
->SetIP(Friend
->GetIP());
244 client
->SetUserName(Friend
->GetName());
245 theApp
->clientlist
->AddClient(client
);
246 Friend
->LinkClient(CCLIENTREF(client
, wxT("CFriendList::StartChatSession")));
249 AddLogLineC(_("CRITICAL - no client on StartChatSession"));
254 // File_checked_for_headers