1 //
2 // This file is part of the aMule Project.
3 //
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 )
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.
10 //
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.
15 //
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
24 //
25 
26 
27 #include "FriendList.h" // Interface
28 
29 #include <common/DataFileVersion.h>
30 
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"
37 #include "GuiEvents.h"
38 #include "Preferences.h"	// Needed for thePrefs
39 
CFriendList()40 CFriendList::CFriendList()
41 {
42 }
43 
~CFriendList()44 CFriendList::~CFriendList()
45 {
46 	SaveList();
47 
48 	DeleteContents(m_FriendList);
49 }
50 
51 
AddFriend(CFriend * toadd,bool notify)52 void CFriendList::AddFriend(CFriend* toadd, bool notify)
53 {
54 	m_FriendList.push_back(toadd);
55 	SaveList();
56 	if (notify) {
57 		Notify_ChatUpdateFriend(toadd);
58 	}
59 }
60 
61 
AddFriend(const CMD4Hash & userhash,uint32 lastUsedIP,uint32 lastUsedPort,const wxString & name,uint32 lastSeen,uint32 lastChatted)62 void CFriendList::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name, uint32 lastSeen, uint32 lastChatted)
63 {
64 	CFriend* NewFriend = new CFriend( userhash, lastSeen, lastUsedIP, lastUsedPort, lastChatted, name);
65 
66 	AddFriend( NewFriend );
67 
68 }
69 
70 
AddFriend(const CClientRef & toadd)71 void CFriendList::AddFriend(const CClientRef& toadd)
72 {
73 	if ( toadd.IsFriend() ) {
74 		return;
75 	}
76 
77 	CFriend* NewFriend = new CFriend( toadd );
78 	toadd.SetFriend(NewFriend);
79 
80 	AddFriend(NewFriend, false);	// has already notified
81 }
82 
83 
RemoveFriend(CFriend * toremove)84 void CFriendList::RemoveFriend(CFriend* toremove)
85 {
86 	if (toremove) {
87 		CClientRef client = toremove->GetLinkedClient();
88 		if (client.IsLinked()) {
89 			client.SetFriendSlot(false);
90 			client.SetFriend(NULL);
91 			toremove->UnLinkClient();
92 		}
93 
94 		m_FriendList.remove(toremove);
95 
96 		SaveList();
97 
98 		Notify_ChatRemoveFriend(toremove);	// this deletes the friend
99 	}
100 }
101 
LoadList()102 void CFriendList::LoadList()
103 {
104 	CPath metfile = CPath(thePrefs::GetConfigDir() + wxT("emfriends.met"));
105 
106 	if (!metfile.FileExists()) {
107 		return;
108 	}
109 
110 	CFile file;
111 	try {
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);
120 				}
121 			}
122 		} else {
123 			AddLogLineN(_("Failed to open friend list file 'emfriends.met' for reading!"));
124 		}
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());
129 	}
130 
131 }
132 
133 
SaveList()134 void CFriendList::SaveList()
135 {
136 	CFile file;
137 	if (file.Create(thePrefs::GetConfigDir() + wxT("emfriends.met"), true)) {
138 		try {
139 			file.WriteUInt8(MET_HEADER);
140 			file.WriteUInt32(m_FriendList.size());
141 
142 			for (FriendList::iterator it = m_FriendList.begin(); it != m_FriendList.end(); ++it) {
143 				(*it)->WriteToFile(&file);
144 			}
145 		} catch (const CIOFailureException& e) {
146 			AddDebugLogLineC(logGeneral, wxT("IO failure while saving 'emfriends.met': ") + e.what());
147 		}
148 	} else {
149 		AddLogLineN(_("Failed to open friend list file 'emfriends.met' for writing!"));
150 	}
151 }
152 
153 
FindFriend(const CMD4Hash & userhash,uint32 dwIP,uint16 nPort)154 CFriend* CFriendList::FindFriend(const CMD4Hash& userhash, uint32 dwIP, uint16 nPort)
155 {
156 
157 	for(FriendList::iterator it = m_FriendList.begin(); it != m_FriendList.end(); ++it) {
158 
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) {
165 				return cur_friend;
166 			}
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)
170 				// -> save the hash
171 				cur_friend->SetUserHash(userhash);
172 				SaveList();
173 			}
174 			return cur_friend;
175 		}
176 	}
177 
178 	return NULL;
179 }
180 
181 
FindFriend(uint32 ecid)182 CFriend* CFriendList::FindFriend(uint32 ecid)
183 {
184 	for (FriendList::iterator it = m_FriendList.begin(); it != m_FriendList.end(); ++it) {
185 		CFriend* cur_friend = *it;
186 		if (cur_friend->ECID() == ecid) {
187 			return cur_friend;
188 		}
189 	}
190 
191 	return NULL;
192 }
193 
194 
IsAlreadyFriend(uint32 dwLastUsedIP,uint32 nLastUsedPort)195 bool CFriendList::IsAlreadyFriend( uint32 dwLastUsedIP, uint32 nLastUsedPort )
196 {
197 	return (FindFriend( CMD4Hash(), dwLastUsedIP, nLastUsedPort ) != NULL);
198 }
199 
200 
RemoveAllFriendSlots()201 void CFriendList::RemoveAllFriendSlots()
202 {
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);
207 		}
208 	}
209 }
210 
211 
RequestSharedFileList(CFriend * cur_friend)212 void CFriendList::RequestSharedFileList(CFriend* cur_friend)
213 {
214 	if (cur_friend) {
215 		CUpDownClient* client = cur_friend->GetLinkedClient().GetClient();
216 		if (!client) {
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")));
221 		}
222 		client->RequestSharedFileList();
223 	}
224 }
225 
226 
SetFriendSlot(CFriend * Friend,bool new_state)227 void CFriendList::SetFriendSlot(CFriend* Friend, bool new_state)
228 {
229 	if (Friend && Friend->GetLinkedClient().IsLinked()) {
230 		RemoveAllFriendSlots();
231 		Friend->GetLinkedClient().SetFriendSlot(new_state);
232 		CoreNotify_Upload_Resort_Queue();
233 	}
234 }
235 
236 
StartChatSession(CFriend * Friend)237 void CFriendList::StartChatSession(CFriend* Friend)
238 {
239 	if (Friend) {
240 		CUpDownClient* client = Friend->GetLinkedClient().GetClient();
241 		if (!client) {
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")));
247 		}
248 	} else {
249 		AddLogLineC(_("CRITICAL - no client on StartChatSession"));
250 	}
251 
252 }
253 
254 // File_checked_for_headers
255