1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
23 //
24 
25 
26 #include <wx/ipc.h>
27 #include <wx/cmdline.h>			// Needed for wxCmdLineParser
28 #include <wx/config.h>			// Do_not_auto_remove (win32)
29 #include <wx/fileconf.h>		// Needed for wxFileConfig
30 #include <wx/socket.h>			// Needed for wxSocketBase
31 
32 
33 #include <common/Format.h>
34 #include <common/StringFunctions.h>
35 #include <common/MD5Sum.h>
36 
37 
38 #include <include/common/EventIDs.h>
39 
40 
41 #include "amule.h"			// Interface declarations.
42 #include "amuleDlg.h"			// Needed for CamuleDlg
43 #include "ClientCredits.h"
44 #include "SourceListCtrl.h"
45 #include "ChatWnd.h"
46 #include "DataToText.h"			// Needed for GetSoftName()
47 #include "DownloadListCtrl.h"		// Needed for CDownloadListCtrl
48 #include "Friend.h"
49 #include "GetTickCount.h"	// Needed for GetTickCount
50 #include "GuiEvents.h"
51 #ifdef ENABLE_IP2COUNTRY
52 	#include "IP2Country.h"		// Needed for IP2Country
53 #endif
54 #include "InternalEvents.h"	// Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
55 #include "Logger.h"
56 #include "muuli_wdr.h"			// Needed for IDs
57 #include "PartFile.h"			// Needed for CPartFile
58 #include "SearchDlg.h"			// Needed for CSearchDlg
59 #include "Server.h"			// Needed for GetListName
60 #include "ServerWnd.h"			// Needed for CServerWnd
61 #include "SharedFilesCtrl.h"		// Needed for CSharedFilesCtrl
62 #include "SharedFilesWnd.h"		// Needed for CSharedFilesWnd
63 #include "TransferWnd.h"		// Needed for CTransferWnd
64 #include "UpDownClientEC.h"		// Needed for CUpDownClient
65 #include "ServerListCtrl.h"		// Needed for CServerListCtrl
66 #include "ScopedPtr.h"
67 #include "StatisticsDlg.h"	// Needed for CStatisticsDlg
68 
69 
CEConnectDlg()70 CEConnectDlg::CEConnectDlg()
71 :
72 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
73 {
74 	CoreConnect(this, true);
75 
76 	wxString pref_host, pref_port;
77 	wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
78 	wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
79 	wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
80 
81 	CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
82 	CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
83 	CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
84 
85 	CentreOnParent();
86 }
87 
88 
PassHash()89 wxString CEConnectDlg::PassHash()
90 {
91 	return pwd_hash;
92 }
93 
94 
BEGIN_EVENT_TABLE(CEConnectDlg,wxDialog)95 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
96   EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
97 END_EVENT_TABLE()
98 
99 
100 void CEConnectDlg::OnOK(wxCommandEvent& evt)
101 {
102 	wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
103 	port = StrToLong(s_port);
104 
105 	host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
106 	passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
107 
108 	if (passwd != pwd_hash) {
109 		pwd_hash = MD5Sum(passwd).GetHash();
110 	}
111 	m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
112 	evt.Skip();
113 }
114 
115 
116 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
117 
118 
BEGIN_EVENT_TABLE(CamuleRemoteGuiApp,wxApp)119 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
120 	// Core timer
121 	EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
122 
123 	EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
124 	EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
125 
126 	EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
127 
128 #ifdef ENABLE_IP2COUNTRY
129 	// HTTPDownload finished
130 	EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
131 #endif
132 END_EVENT_TABLE()
133 
134 
135 IMPLEMENT_APP(CamuleRemoteGuiApp)
136 
137 
138 int CamuleRemoteGuiApp::OnExit()
139 {
140 	StopTickTimer();
141 
142 	wxSocketBase::Shutdown();	// needed because we also called Initialize() manually
143 
144 	return wxApp::OnExit();
145 }
146 
147 
OnPollTimer(wxTimerEvent &)148 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
149 {
150 	static int request_step = 0;
151 	static uint32 msPrevStats = 0;
152 
153 	if (m_connect->RequestFifoFull()) {
154 		return;
155 	}
156 
157 	switch (request_step) {
158 	case 0:
159 		// We used to update the connection state here, but that's done with the stats in the next step now.
160 		request_step++;
161 		break;
162 	case 1: {
163 		CECPacket stats_req(EC_OP_STAT_REQ, EC_DETAIL_INC_UPDATE);
164 		m_connect->SendRequest(&m_stats_updater, &stats_req);
165 		request_step++;
166 		break;
167 	}
168 	case 2:
169 		if (amuledlg->m_sharedfileswnd->IsShown()
170 			|| amuledlg->m_chatwnd->IsShown()
171 			|| amuledlg->m_serverwnd->IsShown()) {
172 			// update downloads, shared files and servers
173 			knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
174 		} else if (amuledlg->m_transferwnd->IsShown()) {
175 			// update both downloads and shared files
176 			knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
177 		} else if (amuledlg->m_searchwnd->IsShown()) {
178 			if (searchlist->m_curr_search != -1) {
179 				searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
180 			}
181 		} else if (amuledlg->m_statisticswnd->IsShown()) {
182 			int sStatsUpdate = thePrefs::GetStatsInterval();
183 			uint32 msCur = theStats::GetUptimeMillis();
184 			if ((sStatsUpdate > 0) && ((int)(msCur - msPrevStats) > sStatsUpdate*1000)) {
185 				msPrevStats = msCur;
186 				stattree->DoRequery();
187 			}
188 		}
189 		// Back to the roots
190 		request_step = 0;
191 		break;
192 	default:
193 		wxFAIL;
194 		request_step = 0;
195 	}
196 
197 	// Check for new links once per second.
198 	static uint32 lastED2KLinkCheck = 0;
199 	if (GetTickCount() - lastED2KLinkCheck >= 1000) {
200 		AddLinksFromFile();
201 		lastED2KLinkCheck = GetTickCount();
202 	}
203 }
204 
205 
OnFinishedHTTPDownload(CMuleInternalEvent & event)206 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
207 {
208 	if (event.GetInt() == HTTP_GeoIP) {
209 		amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
210 		// If we updated, the dialog is already up. Redraw it to show the flags.
211 		amuledlg->Refresh();
212 	}
213 }
214 
215 
ShutDown(wxCloseEvent & WXUNUSED (evt))216 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
217 {
218 	// Stop the Core Timer
219 	delete poll_timer;
220 	poll_timer = NULL;
221 
222 #ifdef ASIO_SOCKETS
223 	m_AsioService->Stop();
224 	delete m_AsioService;
225 	m_AsioService = NULL;
226 #endif
227 
228 	// Destroy the EC socket
229 	m_connect->Destroy();
230 	m_connect = NULL;
231 
232 	//
233 	if (amuledlg) {
234 		amuledlg->DlgShutDown();
235 		amuledlg->Destroy();
236 		amuledlg = NULL;
237 	}
238 	delete m_allUploadingKnownFile;
239 	delete stattree;
240 }
241 
242 
OnInit()243 bool CamuleRemoteGuiApp::OnInit()
244 {
245 	StartTickTimer();
246 	amuledlg = NULL;
247 
248 	// Get theApp
249 	theApp = &wxGetApp();
250 
251 	// Handle uncaught exceptions
252 	InstallMuleExceptionHandler();
253 
254 	// Parse cmdline arguments.
255 	if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
256 		return false;
257 	}
258 
259 	// Initialize wx sockets (needed for http download in background with Asio sockets)
260 	wxSocketBase::Initialize();
261 
262 	// Create the polling timer
263 	poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
264 	if (!poll_timer) {
265 		AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
266 		OnExit();
267 	}
268 
269 	m_connect = new CRemoteConnect(this);
270 
271 #ifdef ASIO_SOCKETS
272 	m_AsioService = new CAsioService;
273 #endif
274 
275 	glob_prefs = new CPreferencesRem(m_connect);
276 	long enableZLIB;
277 	wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1);
278 	m_connect->SetCapabilities(enableZLIB != 0, true, false);	// ZLIB, UTF8 numbers, notification
279 
280 	InitCustomLanguages();
281 	InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
282 
283 	if (ShowConnectionDialog()) {
284 		AddLogLineNS(_("Going to event loop..."));
285 		return true;
286 	}
287 
288 	return false;
289 }
290 
291 
CryptoAvailable() const292 bool CamuleRemoteGuiApp::CryptoAvailable() const
293 {
294 	return thePrefs::IsSecureIdentEnabled(); // good enough
295 }
296 
297 
ShowConnectionDialog()298 bool CamuleRemoteGuiApp::ShowConnectionDialog()
299 {
300 	dialog = new CEConnectDlg;
301 
302 	if (m_skipConnectionDialog) {
303 		wxCommandEvent evt;
304 		dialog->OnOK(evt);
305 	} else if (dialog->ShowModal() != wxID_OK) {
306 		dialog->Destroy();
307 
308 		return false;
309 	}
310 	AddLogLineNS(_("Connecting..."));
311 	if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
312 		dialog->Login(), dialog->PassHash(),
313 		wxT("amule-remote"), wxT("0x0001"))) {
314 		wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
315 
316 		return false;
317 	}
318 
319 	return true;
320 }
321 
322 
OnECConnection(wxEvent & event)323 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
324 	wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
325 	AddLogLineNS(_("Remote GUI EC event handler"));
326 	wxString reply = evt.GetServerReply();
327 	AddLogLineC(reply);
328 	if (evt.GetResult() == true) {
329 		// Connected - go to next init step
330 		glob_prefs->LoadRemote();
331 	} else {
332 		AddLogLineNS(_("Going down"));
333 		if (dialog) {	// connect failed
334 			wxMessageBox(
335 			(CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
336 			_("ERROR"), wxOK);
337 		} else {		// server disconnected (probably terminated) later
338 			wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
339 		}
340 		wxCloseEvent ev;
341 		ShutDown(ev);
342 		ExitMainLoop();
343 	}
344 }
345 
346 
OnECInitDone(wxEvent &)347 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
348 {
349 	Startup();
350 }
351 
352 
OnNotifyEvent(CMuleGUIEvent & evt)353 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
354 {
355 	evt.Notify();
356 }
357 
358 
Startup()359 void CamuleRemoteGuiApp::Startup() {
360 
361 	if (dialog->SaveUserPass()) {
362 		wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
363 		wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
364 		wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
365 	}
366 	dialog->Destroy();
367 	dialog = NULL;
368 
369 	m_ConnState = 0;
370 	m_clientID  = 0;
371 
372 	serverconnect = new CServerConnectRem(m_connect);
373 	m_statistics = new CStatistics(*m_connect);
374 	stattree = new CStatTreeRem(m_connect);
375 
376 	clientlist = new CUpDownClientListRem(m_connect);
377 	searchlist = new CSearchListRem(m_connect);
378 	serverlist = new CServerListRem(m_connect);
379 	friendlist = new CFriendListRem(m_connect);
380 
381 
382 	sharedfiles	= new CSharedFilesRem(m_connect);
383 	knownfiles = new CKnownFilesRem(m_connect);
384 
385 	downloadqueue = new CDownQueueRem(m_connect);
386 	ipfilter = new CIPFilterRem(m_connect);
387 
388 	m_allUploadingKnownFile = new CKnownFile;
389 
390 	// Create main dialog
391 	InitGui(m_geometryEnabled, m_geometryString);
392 
393 	// Forward wxLog events to CLogger
394 	wxLog::SetActiveTarget(new CLoggerTarget);
395 	knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
396 
397 	// Start the Poll Timer
398 	poll_timer->Start(1000);
399 	amuledlg->StartGuiTimer();
400 
401 	// Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
402 #ifdef ENABLE_IP2COUNTRY
403 	if (thePrefs::IsGeoIPEnabled()) {
404 		amuledlg->m_IP2Country->Enable();
405 	}
406 #endif
407 }
408 
409 
ShowAlert(wxString msg,wxString title,int flags)410 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
411 {
412 	return CamuleGuiBase::ShowAlert(msg, title, flags);
413 }
414 
415 
AddRemoteLogLine(const wxString & line)416 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
417 {
418 	amuledlg->AddLogLine(line);
419 }
420 
InitGui(bool geometry_enabled,wxString & geom_string)421 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
422 {
423 	CamuleGuiBase::InitGui(geometry_enabled, geom_string);
424 	SetTopWindow(amuledlg);
425 	AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
426 	return 0;
427 }
428 
429 
CopyTextToClipboard(wxString strText)430 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
431 {
432 	return CamuleGuiBase::CopyTextToClipboard(strText);
433 }
434 
435 
GetPublicIP()436 uint32 CamuleRemoteGuiApp::GetPublicIP()
437 {
438 	return 0;
439 }
440 
441 
GetLog(bool reset)442 wxString CamuleRemoteGuiApp::GetLog(bool reset)
443 {
444 	if (reset) {
445 		amuledlg->ResetLog(ID_LOGVIEW);
446 		CECPacket req(EC_OP_RESET_LOG);
447 		m_connect->SendPacket(&req);
448 	}
449 	return wxEmptyString;
450 }
451 
452 
GetServerLog(bool)453 wxString CamuleRemoteGuiApp::GetServerLog(bool)
454 {
455 	return wxEmptyString;
456 }
457 
458 
AddServer(CServer * server,bool)459 bool CamuleRemoteGuiApp::AddServer(CServer * server, bool)
460 {
461 	CECPacket req(EC_OP_SERVER_ADD);
462 	req.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, CFormat(wxT("%s:%d")) % server->GetAddress() % server->GetPort()));
463 	req.AddTag(CECTag(EC_TAG_SERVER_NAME, server->GetListName()));
464 	m_connect->SendPacket(&req);
465 
466 	return true;
467 }
468 
469 
IsFirewalled() const470 bool CamuleRemoteGuiApp::IsFirewalled() const
471 {
472 	if (IsConnectedED2K() && !serverconnect->IsLowID()) {
473 		return false;
474 	}
475 
476 	return IsFirewalledKad();
477 }
478 
479 
IsConnectedED2K() const480 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
481 	return serverconnect && serverconnect->IsConnected();
482 }
483 
484 
StartKad()485 void CamuleRemoteGuiApp::StartKad() {
486 	m_connect->StartKad();
487 }
488 
489 
StopKad()490 void CamuleRemoteGuiApp::StopKad() {
491 	m_connect->StopKad();
492 }
493 
494 
BootstrapKad(uint32 ip,uint16 port)495 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
496 {
497 	CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
498 	req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
499 	req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
500 
501 	m_connect->SendPacket(&req);
502 }
503 
504 
UpdateNotesDat(const wxString & url)505 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
506 {
507 	CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
508 	req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
509 
510 	m_connect->SendPacket(&req);
511 }
512 
513 
DisconnectED2K()514 void CamuleRemoteGuiApp::DisconnectED2K() {
515 	if (IsConnectedED2K()) {
516 		m_connect->DisconnectED2K();
517 	}
518 }
519 
520 
GetED2KID() const521 uint32 CamuleRemoteGuiApp::GetED2KID() const
522 {
523 	return serverconnect ? serverconnect->GetClientID() : 0;
524 }
525 
526 
GetID() const527 uint32 CamuleRemoteGuiApp::GetID() const
528 {
529 	return m_clientID;
530 }
531 
532 
ShowUserCount()533 void CamuleRemoteGuiApp::ShowUserCount() {
534 	wxString buffer;
535 
536 	static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
537 	static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
538 
539 	if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
540 		buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
541 	} else if (thePrefs::GetNetworkED2K()) {
542 		buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
543 	} else if (thePrefs::GetNetworkKademlia()) {
544 		buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
545 	} else {
546 		buffer = _("No networks selected");
547 	}
548 
549 	Notify_ShowUserCount(buffer);
550 }
551 
552 
553 /*
554  * Preferences: holds both local and remote settings.
555  *
556  * First, everything is loaded from local config file. Later, settings
557  * that are relevant on remote side only are loaded thru EC
558  */
CPreferencesRem(CRemoteConnect * conn)559 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
560 {
561 	m_conn = conn;
562 
563 	//
564 	// Settings queried from remote side
565 	//
566 	m_exchange_send_selected_prefs =
567 		EC_PREFS_GENERAL |
568 		EC_PREFS_CONNECTIONS |
569 		EC_PREFS_MESSAGEFILTER |
570 		EC_PREFS_ONLINESIG |
571 		EC_PREFS_SERVERS |
572 		EC_PREFS_FILES |
573 		EC_PREFS_DIRECTORIES |
574 		EC_PREFS_SECURITY |
575 		EC_PREFS_CORETWEAKS |
576 		EC_PREFS_REMOTECONTROLS |
577 		EC_PREFS_KADEMLIA;
578 	m_exchange_recv_selected_prefs =
579 		m_exchange_send_selected_prefs |
580 		EC_PREFS_CATEGORIES;
581 }
582 
583 
HandlePacket(const CECPacket * packet)584 void CPreferencesRem::HandlePacket(const CECPacket *packet)
585 {
586 	static_cast<const CEC_Prefs_Packet *>(packet)->Apply();
587 
588 	const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES);
589 	if (cat_tags) {
590 		for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); ++it) {
591 			const CECTag &cat_tag = *it;
592 			Category_Struct *cat = new Category_Struct;
593 			cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
594 			cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
595 			cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
596 			cat->color =  cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
597 			cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
598 			theApp->glob_prefs->AddCat(cat);
599 		}
600 	} else {
601 		Category_Struct *cat = new Category_Struct;
602 		cat->title = _("All");
603 		cat->color =  0;
604 		cat->prio = PR_NORMAL;
605 		theApp->glob_prefs->AddCat(cat);
606 	}
607 	wxECInitDoneEvent event;
608 	theApp->AddPendingEvent(event);
609 
610 }
611 
612 
LoadRemote()613 bool CPreferencesRem::LoadRemote()
614 {
615 	//
616 	// override local settings with remote
617 	CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
618 
619 	// bring categories too
620 	req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
621 
622 	m_conn->SendRequest(this, &req);
623 
624 	return true;
625 }
626 
627 
SendToRemote()628 void CPreferencesRem::SendToRemote()
629 {
630 	CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
631 	m_conn->SendPacket(&pref_packet);
632 }
633 
634 
635 class CCatHandler : public CECPacketHandlerBase {
636 	virtual void HandlePacket(const CECPacket *packet);
637 };
638 
639 
HandlePacket(const CECPacket * packet)640 void CCatHandler::HandlePacket(const CECPacket *packet)
641 {
642 	if (packet->GetOpCode() == EC_OP_FAILED) {
643 		const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
644 		const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
645 		if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
646 			int cat = catTag->GetInt();
647 			Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
648 			wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
649 				% cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
650 				_("ERROR"), wxOK);
651 			cs->path = CPath(pathTag->GetStringData());
652 			theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
653 			theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
654 		}
655 	}
656 	delete this;
657 }
658 
659 
CreateCategory(Category_Struct * & category,const wxString & name,const CPath & path,const wxString & comment,uint32 color,uint8 prio)660 bool CPreferencesRem::CreateCategory(
661 	Category_Struct *& category,
662 	const wxString& name,
663 	const CPath& path,
664 	const wxString& comment,
665 	uint32 color,
666 	uint8 prio)
667 {
668 	CECPacket req(EC_OP_CREATE_CATEGORY);
669 	CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
670 	req.AddTag(tag);
671 	m_conn->SendRequest(new CCatHandler, &req);
672 
673 	category = new Category_Struct();
674 	category->path		= path;
675 	category->title		= name;
676 	category->comment	= comment;
677 	category->color		= color;
678 	category->prio		= prio;
679 
680 	AddCat(category);
681 
682 	return true;
683 }
684 
685 
UpdateCategory(uint8 cat,const wxString & name,const CPath & path,const wxString & comment,uint32 color,uint8 prio)686 bool CPreferencesRem::UpdateCategory(
687 	uint8 cat,
688 	const wxString& name,
689 	const CPath& path,
690 	const wxString& comment,
691 	uint32 color,
692 	uint8 prio)
693 {
694 	CECPacket req(EC_OP_UPDATE_CATEGORY);
695 	CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
696 	req.AddTag(tag);
697 	m_conn->SendRequest(new CCatHandler, &req);
698 
699 	Category_Struct *category = m_CatList[cat];
700 	category->path		= path;
701 	category->title		= name;
702 	category->comment	= comment;
703 	category->color		= color;
704 	category->prio		= prio;
705 
706 	return true;
707 }
708 
709 
RemoveCat(uint8 cat)710 void CPreferencesRem::RemoveCat(uint8 cat)
711 {
712 	CECPacket req(EC_OP_DELETE_CATEGORY);
713 	CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
714 	req.AddTag(tag);
715 	m_conn->SendPacket(&req);
716 	CPreferences::RemoveCat(cat);
717 }
718 
719 
720 //
721 // Container implementation
722 //
CServerConnectRem(CRemoteConnect * conn)723 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
724 {
725 	m_CurrServer = 0;
726 	m_Conn = conn;
727 }
728 
729 
ConnectToAnyServer()730 void CServerConnectRem::ConnectToAnyServer()
731 {
732 	CECPacket req(EC_OP_SERVER_CONNECT);
733 	m_Conn->SendPacket(&req);
734 }
735 
736 
StopConnectionTry()737 void CServerConnectRem::StopConnectionTry()
738 {
739 	// lfroen: isn't Disconnect the same ?
740 }
741 
742 
Disconnect()743 void CServerConnectRem::Disconnect()
744 {
745 	CECPacket req(EC_OP_SERVER_DISCONNECT);
746 	m_Conn->SendPacket(&req);
747 }
748 
749 
ConnectToServer(CServer * server)750 void CServerConnectRem::ConnectToServer(CServer *server)
751 {
752 	m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
753 }
754 
755 
HandlePacket(const CECPacket * packet)756 void CServerConnectRem::HandlePacket(const CECPacket *packet)
757 {
758 	const CEC_ConnState_Tag *tag = static_cast<const CEC_ConnState_Tag *>(packet->GetTagByName(EC_TAG_CONNSTATE));
759 	if (!tag) {
760 		return;
761 	}
762 
763 	theApp->m_ConnState = 0;
764 	CServer *server;
765 	m_ID = tag->GetEd2kId();
766 	theApp->m_clientID = tag->GetClientId();
767 	tag->GetKadID(theApp->m_kadID);
768 
769 	if (tag->IsConnectedED2K()) {
770 		const CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
771 		if (srvtag) {
772 			server = theApp->serverlist->GetByID(srvtag->GetInt());
773 			if (server != m_CurrServer) {
774 				theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(server, true);
775 				m_CurrServer = server;
776 			}
777 		}
778 		theApp->m_ConnState |= CONNECTED_ED2K;
779 	} else if ( m_CurrServer ) {
780 	    theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(m_CurrServer, false);
781 	    m_CurrServer = 0;
782 	}
783 
784 	if (tag->IsConnectedKademlia()) {
785 		if (tag->IsKadFirewalled()) {
786 			theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
787 		} else {
788 			theApp->m_ConnState |= CONNECTED_KAD_OK;
789 		}
790 	} else {
791 		if (tag->IsKadRunning()) {
792 			theApp->m_ConnState |= CONNECTED_KAD_NOT;
793 		}
794 	}
795 
796 	theApp->amuledlg->ShowConnectionState();
797 }
798 
799 
800 /*
801  * Server list: host list of ed2k servers.
802  */
CServerListRem(CRemoteConnect * conn)803 CServerListRem::CServerListRem(CRemoteConnect *conn)
804 :
805 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, true)
806 {
807 }
808 
809 
HandlePacket(const CECPacket *)810 void CServerListRem::HandlePacket(const CECPacket *)
811 {
812 	// There is no packet for the server list, it is part of the general update packet
813 	wxFAIL;
814 	// CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
815 }
816 
817 
UpdateServerMetFromURL(wxString url)818 void CServerListRem::UpdateServerMetFromURL(wxString url)
819 {
820 	CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
821 	req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
822 
823 	m_conn->SendPacket(&req);
824 }
825 
826 
SetStaticServer(CServer * server,bool isStatic)827 void CServerListRem::SetStaticServer(CServer* server, bool isStatic)
828 {
829 	// update display right away
830 	server->SetIsStaticMember(isStatic);
831 	Notify_ServerRefresh(server);
832 
833 	CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
834 	req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
835 	req.AddTag(CECTag(EC_TAG_SERVER_STATIC, isStatic));
836 
837 	m_conn->SendPacket(&req);
838 }
839 
840 
SetServerPrio(CServer * server,uint32 prio)841 void CServerListRem::SetServerPrio(CServer* server, uint32 prio)
842 {
843 	// update display right away
844 	server->SetPreference(prio);
845 	Notify_ServerRefresh(server);
846 
847 	CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
848 	req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
849 	req.AddTag(CECTag(EC_TAG_SERVER_PRIO, prio));
850 
851 	m_conn->SendPacket(&req);
852 }
853 
854 
RemoveServer(CServer * server)855 void CServerListRem::RemoveServer(CServer* server)
856 {
857 	m_conn->RemoveServer(server->GetIP(),server->GetPort());
858 }
859 
860 
UpdateUserFileStatus(CServer * server)861 void CServerListRem::UpdateUserFileStatus(CServer *server)
862 {
863 	if (server) {
864 		m_TotalUser = server->GetUsers();
865 		m_TotalFile = server->GetFiles();
866 	}
867 }
868 
869 
GetServerByAddress(const wxString & WXUNUSED (address),uint16 WXUNUSED (port)) const870 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
871 {
872 	// It's ok to return 0 for context where this code is used in remote gui
873 	return 0;
874 }
875 
GetServerByIPTCP(uint32 WXUNUSED (nIP),uint16 WXUNUSED (nPort)) const876 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
877 {
878 	// It's ok to return 0 for context where this code is used in remote gui
879 	return 0;
880 }
881 
CreateItem(const CEC_Server_Tag * tag)882 CServer *CServerListRem::CreateItem(const CEC_Server_Tag *tag)
883 {
884 	CServer * server = new CServer(tag);
885 	ProcessItemUpdate(tag, server);
886 	return server;
887 }
888 
889 
DeleteItem(CServer * in_srv)890 void CServerListRem::DeleteItem(CServer *in_srv)
891 {
892 	CScopedPtr<CServer> srv(in_srv);
893 	theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
894 }
895 
896 
GetItemID(CServer * server)897 uint32 CServerListRem::GetItemID(CServer *server)
898 {
899 	return server->ECID();
900 }
901 
902 
ProcessItemUpdate(const CEC_Server_Tag * tag,CServer * server)903 void CServerListRem::ProcessItemUpdate(const CEC_Server_Tag * tag, CServer * server)
904 {
905 	if (!tag->HasChildTags()) {
906 		return;
907 	}
908 	tag->ServerName(& server->listname);
909 	tag->ServerDesc(& server->description);
910 	tag->ServerVersion(& server->m_strVersion);
911 	tag->GetMaxUsers(& server->maxusers);
912 
913 	tag->GetFiles(& server->files);
914 	tag->GetUsers(& server->users);
915 
916 	tag->GetPrio(& server->preferences); // SRV_PR_NORMAL = 0, so it's ok
917     tag->GetStatic(& server->staticservermember);
918 
919 	tag->GetPing(& server->ping);
920 	tag->GetFailed(& server->failedcount);
921 
922 	theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(server);
923 }
924 
925 
CServer(const CEC_Server_Tag * tag)926 CServer::CServer(const CEC_Server_Tag *tag) : CECID(tag->GetInt())
927 {
928 	ip = tag->GetTagByNameSafe(EC_TAG_SERVER_IP)->GetInt();
929 	port = tag->GetTagByNameSafe(EC_TAG_SERVER_PORT)->GetInt();
930 
931 	Init();
932 }
933 
934 
935 /*
936  * IP filter
937  */
CIPFilterRem(CRemoteConnect * conn)938 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
939 {
940 	m_conn = conn;
941 }
942 
943 
Reload()944 void CIPFilterRem::Reload()
945 {
946 	CECPacket req(EC_OP_IPFILTER_RELOAD);
947 	m_conn->SendPacket(&req);
948 }
949 
950 
Update(wxString url)951 void CIPFilterRem::Update(wxString url)
952 {
953 	CECPacket req(EC_OP_IPFILTER_UPDATE);
954 	req.AddTag(CECTag(EC_TAG_STRING, url));
955 
956 	m_conn->SendPacket(&req);
957 }
958 
959 
960 /*
961  * Shared files list
962  */
CSharedFilesRem(CRemoteConnect * conn)963 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
964 {
965 	m_conn = conn;
966 }
967 
968 
Reload(bool,bool)969 void CSharedFilesRem::Reload(bool, bool)
970 {
971 	CECPacket req(EC_OP_SHAREDFILES_RELOAD);
972 
973 	m_conn->SendPacket(&req);
974 }
975 
976 
RenameFile(CKnownFile * file,const CPath & newName)977 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
978 {
979 	// We use the printable name, as the filename originated from user input,
980 	// and the filesystem name might not be valid on the remote host.
981 	const wxString strNewName = newName.GetPrintable();
982 
983 	CECPacket request(EC_OP_RENAME_FILE);
984 	request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
985 	request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
986 
987 	m_conn->SendPacket(&request);
988 
989 	return true;
990 }
991 
992 
SetFileCommentRating(CKnownFile * file,const wxString & newComment,int8 newRating)993 void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating)
994 {
995 	CECPacket request(EC_OP_SHARED_FILE_SET_COMMENT);
996 	request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
997 	request.AddTag(CECTag(EC_TAG_KNOWNFILE_COMMENT, newComment));
998 	request.AddTag(CECTag(EC_TAG_KNOWNFILE_RATING, newRating));
999 
1000 	m_conn->SendPacket(&request);
1001 }
1002 
1003 
CopyFileList(std::vector<CKnownFile * > & out_list) const1004 void CSharedFilesRem::CopyFileList(std::vector<CKnownFile*>& out_list) const
1005 {
1006 	out_list.reserve(size());
1007 	for (const_iterator it = begin(); it != end(); ++it) {
1008 		out_list.push_back(it->second);
1009 	}
1010 }
1011 
1012 
DeleteItem(CKnownFile * file)1013 void CKnownFilesRem::DeleteItem(CKnownFile * file)
1014 {
1015 	uint32 id = file->ECID();
1016 	if (theApp->sharedfiles->count(id)) {
1017 		theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
1018 		theApp->sharedfiles->erase(id);
1019 	}
1020 	if (theApp->downloadqueue->count(id)) {
1021 		theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile(static_cast<CPartFile *>(file));
1022 		theApp->downloadqueue->erase(id);
1023 	}
1024 	delete file;
1025 }
1026 
1027 
GetItemID(CKnownFile * file)1028 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
1029 {
1030 	return file->ECID();
1031 }
1032 
1033 
ProcessItemUpdate(const CEC_SharedFile_Tag * tag,CKnownFile * file)1034 void CKnownFilesRem::ProcessItemUpdate(const CEC_SharedFile_Tag *tag, CKnownFile *file)
1035 {
1036 	const CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1037 	if (parttag) {
1038 		const uint8 *data =	file->m_partStatus.Decode(
1039 				(uint8 *)parttag->GetTagData(),
1040 				parttag->GetTagDataLen());
1041 		for(int i = 0; i < file->GetPartCount(); ++i) {
1042 			file->m_AvailPartFrequency[i] = data[i];
1043 		}
1044 	}
1045 	wxString fileName;
1046 	if (tag->FileName(fileName)) {
1047 		file->SetFileName(CPath(fileName));
1048 	}
1049 	if (tag->FilePath(fileName)) {
1050 		file->m_filePath = CPath(fileName);
1051 	}
1052 	tag->UpPrio(&file->m_iUpPriorityEC);
1053 	tag->GetAICHHash(file->m_AICHMasterHash);
1054 	// Bad thing - direct writing another class' members
1055 	tag->GetRequests(&file->statistic.requested);
1056 	tag->GetAllRequests(&file->statistic.alltimerequested);
1057 	tag->GetAccepts(&file->statistic.accepted);
1058 	tag->GetAllAccepts(&file->statistic.alltimeaccepted);
1059 	tag->GetXferred(&file->statistic.transferred);
1060 	tag->GetAllXferred(&file->statistic.alltimetransferred);
1061 	tag->UpPrio(&file->m_iUpPriorityEC);
1062 	if (file->m_iUpPriorityEC >= 10) {
1063 		file->m_iUpPriority = file->m_iUpPriorityEC - 10;
1064 		file->m_bAutoUpPriority = true;
1065 	} else {
1066 		file->m_iUpPriority = file->m_iUpPriorityEC;
1067 		file->m_bAutoUpPriority = false;
1068 	}
1069 	tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1070 	tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1071 	tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1072 
1073 	tag->GetOnQueue(&file->m_queuedCount);
1074 
1075 	tag->GetComment(file->m_strComment);
1076 	tag->GetRating(file->m_iRating);
1077 
1078 	requested += file->statistic.requested;
1079 	transferred += file->statistic.transferred;
1080 	accepted += file->statistic.transferred;
1081 
1082 	if (!m_initialUpdate) {
1083 		theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1084 	}
1085 
1086 	if (file->IsPartFile()) {
1087 		ProcessItemUpdatePartfile(static_cast<const CEC_PartFile_Tag *>(tag), static_cast<CPartFile *>(file));
1088 	}
1089 }
1090 
SetFilePrio(CKnownFile * file,uint8 prio)1091 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1092 {
1093 	CECPacket req(EC_OP_SHARED_SET_PRIO);
1094 
1095 	CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1096 	hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1097 
1098 	req.AddTag(hashtag);
1099 
1100 	m_conn->SendPacket(&req);
1101 }
1102 
ProcessUpdate(const CECTag * reply,CECPacket *,int)1103 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1104 {
1105 	requested = 0;
1106 	transferred = 0;
1107 	accepted = 0;
1108 
1109 	std::set<uint32> core_files;
1110 	for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); ++it) {
1111 		const CECTag * curTag = &*it;
1112 		ec_tagname_t tagname = curTag->GetTagName();
1113 		if (tagname == EC_TAG_CLIENT) {
1114 			theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT);
1115 		} else if (tagname == EC_TAG_SERVER) {
1116 			theApp->serverlist->ProcessUpdate(curTag, NULL, EC_TAG_SERVER);
1117 		} else if (tagname == EC_TAG_FRIEND) {
1118 			theApp->friendlist->ProcessUpdate(curTag, NULL, EC_TAG_FRIEND);
1119 		} else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) {
1120 			const CEC_SharedFile_Tag *tag = static_cast<const CEC_SharedFile_Tag *>(curTag);
1121 			uint32 id = tag->ID();
1122 			bool isNew = true;
1123 			if (!m_initialUpdate) {
1124 				core_files.insert(id);
1125 				std::map<uint32, CKnownFile*>::iterator it2 = m_items_hash.find(id);
1126 				if (it2 != m_items_hash.end() ) {
1127 					// Item already known: update it
1128 					if (tag->HasChildTags()) {
1129 						ProcessItemUpdate(tag, it2->second);
1130 					}
1131 					isNew = false;
1132 				}
1133 			}
1134 			if (isNew) {
1135 				CKnownFile * newFile;
1136 				if (tag->GetTagName() == EC_TAG_PARTFILE) {
1137 					CPartFile *file = new CPartFile(static_cast<const CEC_PartFile_Tag *>(tag));
1138 					ProcessItemUpdate(tag, file);
1139 					(*theApp->downloadqueue)[id] = file;
1140 					theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1141 					newFile = file;
1142 				} else {
1143 					newFile = new CKnownFile(tag);
1144 					ProcessItemUpdate(tag, newFile);
1145 					(*theApp->sharedfiles)[id] = newFile;
1146 					if (!m_initialUpdate) {
1147 						theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1148 					}
1149 				}
1150 				AddItem(newFile);
1151 			}
1152 		}
1153 	}
1154 
1155 	if (m_initialUpdate) {
1156 		theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFileList();
1157 		m_initialUpdate = false;
1158 	} else {
1159 		// remove items no longer present
1160 		for(iterator it = begin(); it != end();) {
1161 			iterator it2 = it++;
1162 			if (!core_files.count(GetItemID(*it2))) {
1163 				RemoveItem(it2);	// This calls DeleteItem, where it is removed from lists and views.
1164 			}
1165 		}
1166 	}
1167 }
1168 
CKnownFilesRem(CRemoteConnect * conn)1169 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1170 {
1171 	requested = 0;
1172 	transferred = 0;
1173 	accepted = 0;
1174 	m_initialUpdate = true;
1175 }
1176 
1177 
1178 /*
1179  * List of uploading and waiting clients.
1180  */
CUpDownClientListRem(CRemoteConnect * conn)1181 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1182 :
1183 CRemoteContainer<CClientRef, uint32, CEC_UpDownClient_Tag>(conn, true)
1184 {
1185 }
1186 
1187 
CClientRef(const CEC_UpDownClient_Tag * tag)1188 CClientRef::CClientRef(const CEC_UpDownClient_Tag *tag)
1189 {
1190 	m_client = new CUpDownClient(tag);
1191 #ifdef DEBUG_ZOMBIE_CLIENTS
1192 	m_client->Link(wxT("TAG"));
1193 #else
1194 	m_client->Link();
1195 #endif
1196 }
1197 
1198 
CUpDownClient(const CEC_UpDownClient_Tag * tag)1199 CUpDownClient::CUpDownClient(const CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1200 {
1201 	m_linked = 0;
1202 #ifdef DEBUG_ZOMBIE_CLIENTS
1203 	m_linkedDebug = false;
1204 #endif
1205 	// Clients start up empty, then get asked for their data.
1206 	// So all data here is processed in ProcessItemUpdate and thus updatable.
1207 	m_bEmuleProtocol		= false;
1208 	m_AvailPartCount		= 0;
1209 	m_clientSoft			= 0;
1210 	m_nDownloadState		= 0;
1211 	m_Friend				= NULL;
1212 	m_bFriendSlot			= false;
1213 	m_nKadPort				= 0;
1214 	m_kBpsDown				= 0;
1215 	m_dwUserIP				= 0;
1216 	m_lastDownloadingPart	= 0xffff;
1217 	m_nextRequestedPart		= 0xffff;
1218 	m_obfuscationStatus		= 0;
1219 	m_nOldRemoteQueueRank	= 0;
1220 	m_nRemoteQueueRank		= 0;
1221 	m_reqfile				= NULL;
1222 	m_score					= 0;
1223 	m_dwServerIP			= 0;
1224 	m_nServerPort			= 0;
1225 	m_nSourceFrom			= SF_NONE;
1226 	m_nTransferredDown		= 0;
1227 	m_nTransferredUp		= 0;
1228 	m_nUpDatarate			= 0;
1229 	m_uploadingfile			= NULL;
1230 	m_waitingPosition		= 0;
1231 	m_nUploadState			= 0;
1232 	m_nUserIDHybrid			= 0;
1233 	m_nUserPort				= 0;
1234 	m_nClientVersion		= 0;
1235 	m_fNoViewSharedFiles	= true;
1236 	m_identState			= IS_NOTAVAILABLE;
1237 	m_bRemoteQueueFull		= false;
1238 
1239 	credits = new CClientCredits(new CreditStruct());
1240 }
1241 
1242 #ifdef DEBUG_ZOMBIE_CLIENTS
Unlink(const wxString & from)1243 void CUpDownClient::Unlink(const wxString& from)
1244 {
1245 	std::multiset<wxString>::iterator it = m_linkedFrom.find(from);
1246 	if (it != m_linkedFrom.end()) {
1247 		m_linkedFrom.erase(it);
1248 	}
1249 	m_linked--;
1250 	if (!m_linked) {
1251 		if (m_linkedDebug) {
1252 			AddLogLineN(CFormat(wxT("Last reference to client %d %p unlinked, delete it.")) % ECID() % this);
1253 		}
1254 		delete this;
1255 	}
1256 }
1257 
1258 #else
1259 
Unlink()1260 void CUpDownClient::Unlink()
1261 {
1262 	m_linked--;
1263 	if (!m_linked) {
1264 		delete this;
1265 	}
1266 }
1267 #endif
1268 
1269 
GetDownloadedTotal() const1270 uint64 CUpDownClient::GetDownloadedTotal() const
1271 {
1272 	return credits->GetDownloadedTotal();
1273 }
1274 
1275 
GetUploadedTotal() const1276 uint64 CUpDownClient::GetUploadedTotal() const
1277 {
1278 	return credits->GetUploadedTotal();
1279 }
1280 
1281 
GetScoreRatio() const1282 double CUpDownClient::GetScoreRatio() const
1283 {
1284 	return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1285 }
1286 
1287 /* End Warning */
1288 
1289 
~CUpDownClient()1290 CUpDownClient::~CUpDownClient()
1291 {
1292 	delete credits;
1293 }
1294 
1295 
CreateItem(const CEC_UpDownClient_Tag * tag)1296 CClientRef *CUpDownClientListRem::CreateItem(const CEC_UpDownClient_Tag *tag)
1297 {
1298 	CClientRef *client = new CClientRef(tag);
1299 	ProcessItemUpdate(tag, client);
1300 
1301 	return client;
1302 }
1303 
1304 
DeleteItem(CClientRef * clientref)1305 void CUpDownClientListRem::DeleteItem(CClientRef *clientref)
1306 {
1307 	CUpDownClient* client = clientref->GetClient();
1308 	if (client->m_reqfile) {
1309 		client->m_reqfile->DelSource(client);
1310 		client->m_reqfile = NULL;
1311 	}
1312 	Notify_SourceCtrlRemoveSource(client->ECID(), (CPartFile*) NULL);
1313 
1314 	if (client->m_uploadingfile) {
1315 		client->m_uploadingfile->RemoveUploadingClient(client);	// this notifies
1316 		client->m_uploadingfile = NULL;
1317 	}
1318 	theApp->m_allUploadingKnownFile->RemoveUploadingClient(client);	// in case it vanished directly while uploading
1319 	Notify_SharedCtrlRemoveClient(client->ECID(), (CKnownFile*) NULL);
1320 
1321 	if (client->m_Friend) {
1322 		client->m_Friend->UnLinkClient();	// this notifies
1323 		client->m_Friend = NULL;
1324 	}
1325 
1326 #ifdef DEBUG_ZOMBIE_CLIENTS
1327 	if (client->m_linked > 1) {
1328 		AddLogLineC(CFormat(wxT("Client %d still linked in %d places: %s")) % client->ECID() % (client->m_linked - 1) % client->GetLinkedFrom());
1329 		client->m_linkedDebug = true;
1330 	}
1331 #endif
1332 
1333 	delete clientref;
1334 }
1335 
1336 
GetItemID(CClientRef * client)1337 uint32 CUpDownClientListRem::GetItemID(CClientRef *client)
1338 {
1339 	return client->ECID();
1340 }
1341 
1342 
ProcessItemUpdate(const CEC_UpDownClient_Tag * tag,CClientRef * clientref)1343 void CUpDownClientListRem::ProcessItemUpdate(
1344 	const CEC_UpDownClient_Tag *tag,
1345 	CClientRef *clientref)
1346 {
1347 	if (!tag->HasChildTags()) {
1348 		return;		// speed exit for clients without any change
1349 	}
1350 	CUpDownClient *client = clientref->GetClient();
1351 
1352 	tag->UserID(&client->m_nUserIDHybrid);
1353 	tag->ClientName(&client->m_Username);
1354 	// Client Software
1355 	bool sw_updated = false;
1356 	if (tag->ClientSoftware(client->m_clientSoft)) {
1357 		client->m_clientSoftString = GetSoftName(client->m_clientSoft);
1358 		sw_updated = true;
1359 	}
1360 	if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) {
1361 		if (client->m_clientSoftString == _("Unknown")) {
1362 			client->m_fullClientVerString = client->m_clientSoftString;
1363 		} else {
1364 			client->m_fullClientVerString = client->m_clientSoftString + wxT(" ") + client->m_clientVerString;
1365 		}
1366 	}
1367 	// User hash
1368 	tag->UserHash(&client->m_UserHash);
1369 
1370 	// User IP:Port
1371 	tag->UserIP(client->m_dwUserIP);
1372 	tag->UserPort(&client->m_nUserPort);
1373 
1374 	// Server IP:Port
1375 	tag->ServerIP(&client->m_dwServerIP);
1376 	tag->ServerPort(&client->m_nServerPort);
1377 	tag->ServerName(&client->m_ServerName);
1378 
1379 	tag->KadPort(client->m_nKadPort);
1380 	tag->FriendSlot(client->m_bFriendSlot);
1381 
1382 	tag->GetCurrentIdentState(&client->m_identState);
1383 	tag->ObfuscationStatus(client->m_obfuscationStatus);
1384 	tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1385 
1386 	tag->WaitingPosition(&client->m_waitingPosition);
1387 	tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1388 	client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1389 	tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank);
1390 
1391 	tag->ClientDownloadState(client->m_nDownloadState);
1392 	if (tag->ClientUploadState(client->m_nUploadState)) {
1393 		if (client->m_nUploadState == US_UPLOADING) {
1394 			theApp->m_allUploadingKnownFile->AddUploadingClient(client);
1395 		} else {
1396 			theApp->m_allUploadingKnownFile->RemoveUploadingClient(client);
1397 		}
1398 	}
1399 
1400 	tag->SpeedUp(&client->m_nUpDatarate);
1401 	if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1402 		tag->SpeedDown(&client->m_kBpsDown);
1403 	} else {
1404 		client->m_kBpsDown = 0;
1405 	}
1406 
1407 	//tag->WaitTime(&client->m_WaitTime);
1408 	//tag->XferTime(&client->m_UpStartTimeDelay);
1409 	//tag->LastReqTime(&client->m_dwLastUpRequest);
1410 	//tag->QueueTime(&client->m_WaitStartTime);
1411 
1412 	CreditStruct *credit_struct = const_cast<CreditStruct *>(client->credits->GetDataStruct());
1413 	tag->XferUp(&credit_struct->uploaded);
1414 	tag->XferUpSession(&client->m_nTransferredUp);
1415 
1416 	tag->XferDown(&credit_struct->downloaded);
1417 	tag->XferDownSession(&client->m_nTransferredDown);
1418 
1419 	tag->Score(&client->m_score);
1420 
1421 	tag->NextRequestedPart(client->m_nextRequestedPart);
1422 	tag->LastDownloadingPart(client->m_lastDownloadingPart);
1423 
1424 	uint8 sourceFrom = 0;
1425 	if (tag->GetSourceFrom(sourceFrom)) {
1426 		client->m_nSourceFrom = (ESourceFrom)sourceFrom;
1427 	}
1428 
1429 	tag->RemoteFilename(client->m_clientFilename);
1430 	tag->DisableViewShared(client->m_fNoViewSharedFiles);
1431 	tag->Version(client->m_nClientVersion);
1432 	tag->ModVersion(client->m_strModVersion);
1433 	tag->OSInfo(client->m_sClientOSInfo);
1434 	tag->AvailableParts(client->m_AvailPartCount);
1435 
1436 	// Download client
1437 	uint32 fileID;
1438 	bool notified = false;
1439 	if (tag->RequestFile(fileID)) {
1440 		if (client->m_reqfile) {
1441 			Notify_SourceCtrlRemoveSource(client->ECID(), client->m_reqfile);
1442 			client->m_reqfile->DelSource(client);
1443 			client->m_reqfile = NULL;
1444 			client->m_downPartStatus.clear();
1445 		}
1446 		CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1447 		if (kf && kf->IsCPartFile()) {
1448 			client->m_reqfile = static_cast<CPartFile *>(kf);
1449 			client->m_reqfile->AddSource(client);
1450 			client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1451 			Notify_SourceCtrlAddSource(client->m_reqfile, CCLIENTREF(client, wxT("AddSource")), A4AF_SOURCE);
1452 			notified = true;
1453 		}
1454 	}
1455 
1456 	// Part status
1457 	const CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS);
1458 	if (partStatusTag) {
1459 		if (partStatusTag->GetTagDataLen() == 0) {
1460 			// empty tag means full source
1461 			client->m_downPartStatus.SetAllTrue();
1462 		} else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) {
1463 			client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData());
1464 		}
1465 		notified = false;
1466 	}
1467 
1468 	if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) {
1469 		SourceItemType type;
1470 		switch (client->GetDownloadState()) {
1471 			case DS_DOWNLOADING:
1472 			case DS_ONQUEUE:
1473 				// We will send A4AF, which will be checked.
1474 				type = A4AF_SOURCE;
1475 				break;
1476 			default:
1477 				type = UNAVAILABLE_SOURCE;
1478 				break;
1479 		}
1480 
1481 		Notify_SourceCtrlUpdateSource(client->ECID(), type);
1482 	}
1483 
1484 	// Upload client
1485 	notified = false;
1486 	if (tag->UploadFile(fileID)) {
1487 		if (client->m_uploadingfile) {
1488 			client->m_uploadingfile->RemoveUploadingClient(client);	// this notifies
1489 			notified = true;
1490 			client->m_uploadingfile = NULL;
1491 		}
1492 		CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1493 		if (kf) {
1494 			client->m_uploadingfile = kf;
1495 			client->m_upPartStatus.setsize(kf->GetPartCount(), 0);
1496 			client->m_uploadingfile->AddUploadingClient(client);	// this notifies
1497 			notified = true;
1498 		}
1499 	}
1500 
1501 	// Part status
1502 	partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_UPLOAD_PART_STATUS);
1503 	if (partStatusTag) {
1504 		if (partStatusTag->GetTagDataLen() == client->m_upPartStatus.SizeBuffer()) {
1505 			client->m_upPartStatus.SetBuffer(partStatusTag->GetTagData());
1506 		}
1507 		notified = false;
1508 	}
1509 
1510 	if (!notified && client->m_uploadingfile
1511 		&& (client->m_uploadingfile->ShowPeers() || (client->m_nUploadState == US_UPLOADING))) {
1512 			// notify if KnowFile is selected, or if it's uploading (in case clients are in show uploading mode)
1513 		SourceItemType type;
1514 		switch (client->GetUploadState()) {
1515 			case US_UPLOADING:
1516 			case US_ONUPLOADQUEUE:
1517 				type = AVAILABLE_SOURCE;
1518 				break;
1519 			default:
1520 				type = UNAVAILABLE_SOURCE;
1521 				break;
1522 		}
1523 		Notify_SharedCtrlRefreshClient(client->ECID(), type);
1524 	}
1525 }
1526 
1527 
1528 /*
1529  * Download queue container: hold PartFiles with progress status
1530  *
1531  */
1532 
1533 
AddLink(const wxString & link,uint8 cat)1534 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1535 {
1536 	CECPacket req(EC_OP_ADD_LINK);
1537 	CECTag link_tag(EC_TAG_STRING, link);
1538 	link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1539 	req.AddTag(link_tag);
1540 
1541 	m_conn->SendPacket(&req);
1542 	return true;
1543 }
1544 
1545 
ResetCatParts(int cat)1546 void CDownQueueRem::ResetCatParts(int cat)
1547 {
1548 	// Called when category is deleted. Command will be performed on the remote side,
1549 	// but files still should be updated here right away, or drawing errors (colour not available)
1550 	// will happen.
1551 	for (iterator it = begin(); it != end(); ++it) {
1552 		CPartFile* file = it->second;
1553 		file->RemoveCategory(cat);
1554 	}
1555 }
1556 
1557 
1558 
ProcessItemUpdatePartfile(const CEC_PartFile_Tag * tag,CPartFile * file)1559 void CKnownFilesRem::ProcessItemUpdatePartfile(const CEC_PartFile_Tag *tag, CPartFile *file)
1560 {
1561 	//
1562 	// update status
1563 	//
1564 	tag->Speed(&file->m_kbpsDown);
1565 	file->kBpsDown = file->m_kbpsDown / 1024.0;
1566 
1567 	tag->SizeXfer(&file->transferred);
1568 	tag->SizeDone(&file->completedsize);
1569 	tag->SourceXferCount(&file->transferingsrc);
1570 	tag->SourceNotCurrCount(&file->m_notCurrentSources);
1571 	tag->SourceCount(&file->m_source_count);
1572 	tag->SourceCountA4AF(&file->m_a4af_source_count);
1573 	tag->FileStatus(&file->status);
1574 	tag->Stopped(&file->m_stopped);
1575 
1576 	tag->LastSeenComplete(&file->lastseencomplete);
1577 	tag->LastDateChanged(&file->m_lastDateChanged);
1578 	tag->DownloadActiveTime(&file->m_nDlActiveTime);
1579 	tag->AvailablePartCount(&file->m_availablePartsCount);
1580 	tag->Shared(&file->m_isShared);
1581 	tag->A4AFAuto(file->m_is_A4AF_auto);
1582 	tag->HashingProgress(file->m_hashingProgress);
1583 
1584 	tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1585 	tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1586 	tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1587 
1588 	tag->FileCat(&file->m_category);
1589 
1590 	tag->DownPrio(&file->m_iDownPriorityEC);
1591 	if ( file->m_iDownPriorityEC >= 10 ) {
1592 		file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1593 		file->m_bAutoDownPriority = true;
1594 	} else {
1595 		file->m_iDownPriority = file->m_iDownPriorityEC;
1596 		file->m_bAutoDownPriority = false;
1597 	}
1598 
1599 	file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1600 
1601 	//
1602 	// Copy part/gap status
1603 	//
1604 	const CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1605 	const CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1606 	const CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1607 	if (gaptag || parttag || reqtag) {
1608 		PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1609 
1610 		if (gaptag) {
1611 			ArrayOfUInts64 gaps;
1612 			encoder.DecodeGaps(gaptag, gaps);
1613 			int gap_size = gaps.size() / 2;
1614 			// clear gaplist
1615 			file->m_gaplist.Init(file->GetFileSize(), false);
1616 
1617 			// and refill it
1618 			for (int j = 0; j < gap_size; j++) {
1619 				file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1620 			}
1621 		}
1622 		if (parttag) {
1623 			encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1624 			// sanity check
1625 			wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1626 		}
1627 		if (reqtag) {
1628 			ArrayOfUInts64 reqs;
1629 			encoder.DecodeReqs(reqtag, reqs);
1630 			int req_size = reqs.size() / 2;
1631 			// clear reqlist
1632 			DeleteContents(file->m_requestedblocks_list);
1633 
1634 			// and refill it
1635 			for (int j = 0; j < req_size; j++) {
1636 				Requested_Block_Struct* block = new Requested_Block_Struct;
1637 				block->StartOffset = reqs[2*j];
1638 				block->EndOffset   = reqs[2*j+1];
1639 				file->m_requestedblocks_list.push_back(block);
1640 			}
1641 		}
1642 	}
1643 
1644 	// Get source names and counts
1645 	const CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1646 	if (srcnametag) {
1647 		SourcenameItemMap &map = file->GetSourcenameItemMap();
1648 		for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); ++it) {
1649 			uint32 key = it->GetInt();
1650 			int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1651 			if (count == 0) {
1652 				map.erase(key);
1653 			} else {
1654 				SourcenameItem &item = map[key];
1655 				item.count = count;
1656 				const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1657 				if (nametag) {
1658 					item.name = nametag->GetStringData();
1659 				}
1660 			}
1661 		}
1662 	}
1663 
1664 	// Get comments
1665 	const CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1666 	if (commenttag) {
1667 		file->ClearFileRatingList();
1668 		for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) {
1669 			wxString u = (it++)->GetStringData();
1670 			wxString f = (it++)->GetStringData();
1671 			int r = (it++)->GetInt();
1672 			wxString c = (it++)->GetStringData();
1673 			file->AddFileRatingList(u, f, r, c);
1674 		}
1675 		file->UpdateFileRatingCommentAvail();
1676 	}
1677 
1678 	// Update A4AF sources
1679 	ListOfUInts32 & clientIDs = file->GetA4AFClientIDs();
1680 	const CECTag *a4aftag = tag->GetTagByName(EC_TAG_PARTFILE_A4AF_SOURCES);
1681 	if (a4aftag) {
1682 		file->ClearA4AFList();
1683 		clientIDs.clear();
1684 		for (CECTag::const_iterator it = a4aftag->begin(); it != a4aftag->end(); ++it) {
1685 			if (it->GetTagName() != EC_TAG_ECID) {	// should always be this
1686 				continue;
1687 			}
1688 			uint32 id = it->GetInt();
1689 			CClientRef * src = theApp->clientlist->GetByID(id);
1690 			if (src) {
1691 				file->AddA4AFSource(src->GetClient());
1692 			} else {
1693 				// client wasn't transmitted yet, try it later
1694 				clientIDs.push_back(id);
1695 			}
1696 		}
1697 	} else if (!clientIDs.empty()) {
1698 		// Process clients from the last pass whose ids were still unknown then
1699 		for (ListOfUInts32::iterator it = clientIDs.begin(); it != clientIDs.end(); ) {
1700 			ListOfUInts32::iterator it1 = it++;
1701 			uint32 id = *it1;
1702 			CClientRef * src = theApp->clientlist->GetByID(id);
1703 			if (src) {
1704 				file->AddA4AFSource(src->GetClient());
1705 				clientIDs.erase(it1);
1706 			}
1707 		}
1708 	}
1709 
1710 	theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1711 
1712 	// If file is shared check if it is already listed in shared files.
1713 	// If not, add it and show it.
1714 	if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1715 		(*theApp->sharedfiles)[file->ECID()] = file;
1716 		theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1717 	}
1718 }
1719 
1720 
SendFileCommand(CPartFile * file,ec_tagname_t cmd)1721 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1722 {
1723 	CECPacket req(cmd);
1724 	req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1725 
1726 	m_conn->SendPacket(&req);
1727 }
1728 
1729 
Prio(CPartFile * file,uint8 prio)1730 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1731 {
1732 	CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1733 
1734 	CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1735 	hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1736 	req.AddTag(hashtag);
1737 
1738 	m_conn->SendPacket(&req);
1739 }
1740 
1741 
AutoPrio(CPartFile * file,bool flag)1742 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1743 {
1744 	CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1745 
1746 	CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1747 
1748 	hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1749 		(uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1750 	req.AddTag(hashtag);
1751 
1752 	m_conn->SendPacket(&req);
1753 }
1754 
1755 
Category(CPartFile * file,uint8 cat)1756 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1757 {
1758 	CECPacket req(EC_OP_PARTFILE_SET_CAT);
1759 	file->SetCategory(cat);
1760 
1761 	CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1762 	hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1763 	req.AddTag(hashtag);
1764 
1765 	m_conn->SendPacket(&req);
1766 }
1767 
1768 
AddSearchToDownload(CSearchFile * file,uint8 category)1769 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1770 {
1771 	CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1772 	CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1773 	hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1774 	req.AddTag(hashtag);
1775 
1776 	m_conn->SendPacket(&req);
1777 }
1778 
1779 
ClearCompleted(const ListOfUInts32 & ecids)1780 void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids)
1781 {
1782 	CECPacket req(EC_OP_CLEAR_COMPLETED);
1783 	for (ListOfUInts32::const_iterator it = ecids.begin(); it != ecids.end(); ++it) {
1784 		req.AddTag(CECTag(EC_TAG_ECID, *it));
1785 	}
1786 
1787 	m_conn->SendPacket(&req);
1788 }
1789 
1790 
1791 /*
1792  * List of friends.
1793  */
CFriendListRem(CRemoteConnect * conn)1794 CFriendListRem::CFriendListRem(CRemoteConnect *conn)
1795 :
1796 CRemoteContainer<CFriend, uint32, CEC_Friend_Tag>(conn, true)
1797 {
1798 }
1799 
1800 
HandlePacket(const CECPacket *)1801 void CFriendListRem::HandlePacket(const CECPacket *)
1802 {
1803 	wxFAIL;		// not needed
1804 }
1805 
1806 
CreateItem(const CEC_Friend_Tag * tag)1807 CFriend * CFriendListRem::CreateItem(const CEC_Friend_Tag * tag)
1808 {
1809 	CFriend * Friend = new CFriend(tag->ID());
1810 	ProcessItemUpdate(tag, Friend);
1811 	return Friend;
1812 }
1813 
1814 
DeleteItem(CFriend * Friend)1815 void CFriendListRem::DeleteItem(CFriend * Friend)
1816 {
1817 	Friend->UnLinkClient(false);
1818 	Notify_ChatRemoveFriend(Friend);
1819 }
1820 
1821 
GetItemID(CFriend * Friend)1822 uint32 CFriendListRem::GetItemID(CFriend * Friend)
1823 {
1824 	return Friend->ECID();
1825 }
1826 
1827 
ProcessItemUpdate(const CEC_Friend_Tag * tag,CFriend * Friend)1828 void CFriendListRem::ProcessItemUpdate(const CEC_Friend_Tag * tag, CFriend * Friend)
1829 {
1830 	if (!tag->HasChildTags()) {
1831 		return;
1832 	}
1833 	tag->Name(Friend->m_strName);
1834 	tag->UserHash(Friend->m_UserHash);
1835 	tag->IP(Friend->m_dwLastUsedIP);
1836 	tag->Port(Friend->m_nLastUsedPort);
1837 	uint32 clientID;
1838 	bool notified = false;
1839 	if (tag->Client(clientID)) {
1840 		if (clientID) {
1841 			CClientRef * client = theApp->clientlist->GetByID(clientID);
1842 			if (client) {
1843 				Friend->LinkClient(*client);	// this notifies
1844 				notified = true;
1845 			}
1846 		} else {
1847 			// Unlink
1848 			Friend->UnLinkClient(false);
1849 		}
1850 	}
1851 	if (!notified) {
1852 		Notify_ChatUpdateFriend(Friend);
1853 	}
1854 }
1855 
1856 
AddFriend(const CClientRef & toadd)1857 void CFriendListRem::AddFriend(const CClientRef& toadd)
1858 {
1859 	CECPacket req(EC_OP_FRIEND);
1860 
1861 	CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1862 	addtag.AddTag(CECTag(EC_TAG_CLIENT, toadd.ECID()));
1863 	req.AddTag(addtag);
1864 
1865 	m_conn->SendPacket(&req);
1866 }
1867 
1868 
AddFriend(const CMD4Hash & userhash,uint32 lastUsedIP,uint32 lastUsedPort,const wxString & name)1869 void CFriendListRem::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name)
1870 {
1871 	CECPacket req(EC_OP_FRIEND);
1872 
1873 	CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1874 	addtag.AddTag(CECTag(EC_TAG_FRIEND_HASH, userhash));
1875 	addtag.AddTag(CECTag(EC_TAG_FRIEND_IP, lastUsedIP));
1876 	addtag.AddTag(CECTag(EC_TAG_FRIEND_PORT, lastUsedPort));
1877 	addtag.AddTag(CECTag(EC_TAG_FRIEND_NAME, name));
1878 	req.AddTag(addtag);
1879 
1880 	m_conn->SendPacket(&req);
1881 }
1882 
1883 
RemoveFriend(CFriend * toremove)1884 void CFriendListRem::RemoveFriend(CFriend* toremove)
1885 {
1886 	CECPacket req(EC_OP_FRIEND);
1887 
1888 	CECEmptyTag removetag(EC_TAG_FRIEND_REMOVE);
1889 	removetag.AddTag(CECTag(EC_TAG_FRIEND, toremove->ECID()));
1890 	req.AddTag(removetag);
1891 
1892 	m_conn->SendPacket(&req);
1893 }
1894 
1895 
SetFriendSlot(CFriend * Friend,bool new_state)1896 void CFriendListRem::SetFriendSlot(CFriend* Friend, bool new_state)
1897 {
1898 	CECPacket req(EC_OP_FRIEND);
1899 
1900 	CECTag slottag(EC_TAG_FRIEND_FRIENDSLOT, new_state);
1901 	slottag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1902 	req.AddTag(slottag);
1903 
1904 	m_conn->SendPacket(&req);
1905 }
1906 
1907 
RequestSharedFileList(CFriend * Friend)1908 void CFriendListRem::RequestSharedFileList(CFriend* Friend)
1909 {
1910 	CECPacket req(EC_OP_FRIEND);
1911 
1912 	CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1913 	sharedtag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1914 	req.AddTag(sharedtag);
1915 
1916 	m_conn->SendPacket(&req);
1917 }
1918 
1919 
RequestSharedFileList(CClientRef & client)1920 void CFriendListRem::RequestSharedFileList(CClientRef& client)
1921 {
1922 	CECPacket req(EC_OP_FRIEND);
1923 
1924 	CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1925 	sharedtag.AddTag(CECTag(EC_TAG_CLIENT, client.ECID()));
1926 	req.AddTag(sharedtag);
1927 
1928 	m_conn->SendPacket(&req);
1929 }
1930 
1931 
1932 
1933 /*
1934  * Search results
1935  */
CSearchListRem(CRemoteConnect * conn)1936 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1937 {
1938 	m_curr_search = -1;
1939 }
1940 
1941 
StartNewSearch(uint32 * nSearchID,SearchType search_type,const CSearchList::CSearchParams & params)1942 wxString CSearchListRem::StartNewSearch(
1943 	uint32* nSearchID, SearchType search_type,
1944 	const CSearchList::CSearchParams& params)
1945 {
1946 	CECPacket search_req(EC_OP_SEARCH_START);
1947 	EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1948 	switch(search_type) {
1949 		case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1950 		case GlobalSearch: ec_search_type =  EC_SEARCH_GLOBAL; break;
1951 		case KadSearch: ec_search_type =  EC_SEARCH_KAD; break;
1952 	}
1953 	search_req.AddTag(
1954 		CEC_Search_Tag(params.searchString, ec_search_type,
1955 		params.typeText, params.extension, params.availability,
1956 		params.minSize, params.maxSize));
1957 
1958 	m_conn->SendPacket(&search_req);
1959 	m_curr_search = *(nSearchID); // No kad remote search yet.
1960 
1961 	Flush();
1962 
1963 	return wxEmptyString; // EC reply will have the error mesg is needed.
1964 }
1965 
1966 
StopSearch(bool)1967 void CSearchListRem::StopSearch(bool)
1968 {
1969 	if (m_curr_search != -1) {
1970 		CECPacket search_req(EC_OP_SEARCH_STOP);
1971 		m_conn->SendPacket(&search_req);
1972 	}
1973 }
1974 
1975 
HandlePacket(const CECPacket * packet)1976 void CSearchListRem::HandlePacket(const CECPacket *packet)
1977 {
1978 	if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1979 		CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt());
1980 	} else {
1981 		CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet);
1982 	}
1983 }
1984 
1985 
CSearchFile(const CEC_SearchFile_Tag * tag)1986 CSearchFile::CSearchFile(const CEC_SearchFile_Tag *tag)
1987 :
1988 CECID(tag->ID()),
1989 m_parent(NULL),
1990 m_showChildren(false),
1991 m_sourceCount(0),
1992 m_completeSourceCount(0),
1993 m_kademlia(false),
1994 m_downloadStatus(NEW),
1995 m_clientID(0),
1996 m_clientPort(0),
1997 m_kadPublishInfo(0)
1998 {
1999 	SetFileName(CPath(tag->FileName()));
2000 	m_abyFileHash = tag->FileHash();
2001 	SetFileSize(tag->SizeFull());
2002 
2003 	m_searchID = theApp->searchlist->m_curr_search;
2004 	uint32 parentID = tag->ParentID();
2005 	if (parentID) {
2006 		CSearchFile * parent = theApp->searchlist->GetByID(parentID);
2007 		if (parent) {
2008 			parent->AddChild(this);
2009 		}
2010 	}
2011 }
2012 
2013 
AddChild(CSearchFile * file)2014 void CSearchFile::AddChild(CSearchFile* file)
2015 {
2016 	m_children.push_back(file);
2017 	file->m_parent = this;
2018 }
2019 
2020 
2021 // dtor is virtual - must be implemented
~CSearchFile()2022 CSearchFile::~CSearchFile()
2023 {
2024 }
2025 
2026 
CreateItem(const CEC_SearchFile_Tag * tag)2027 CSearchFile *CSearchListRem::CreateItem(const CEC_SearchFile_Tag *tag)
2028 {
2029 	CSearchFile *file = new CSearchFile(tag);
2030 	ProcessItemUpdate(tag, file);
2031 
2032 	theApp->amuledlg->m_searchwnd->AddResult(file);
2033 
2034 	return file;
2035 }
2036 
2037 
DeleteItem(CSearchFile * file)2038 void CSearchListRem::DeleteItem(CSearchFile *file)
2039 {
2040 	delete file;
2041 }
2042 
2043 
GetItemID(CSearchFile * file)2044 uint32 CSearchListRem::GetItemID(CSearchFile *file)
2045 {
2046 	return file->ECID();
2047 }
2048 
2049 
ProcessItemUpdate(const CEC_SearchFile_Tag * tag,CSearchFile * file)2050 void CSearchListRem::ProcessItemUpdate(const CEC_SearchFile_Tag *tag, CSearchFile *file)
2051 {
2052 	uint32 sourceCount = file->m_sourceCount;
2053 	uint32 completeSourceCount = file->m_completeSourceCount;
2054 	CSearchFile::DownloadStatus status = file->m_downloadStatus;
2055 	tag->SourceCount(&file->m_sourceCount);
2056 	tag->CompleteSourceCount(&file->m_completeSourceCount);
2057 	tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
2058 
2059 	if (file->m_sourceCount != sourceCount
2060 			|| file->m_completeSourceCount != completeSourceCount
2061 			|| file->m_downloadStatus != status) {
2062 		if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
2063 			theApp->amuledlg->m_searchwnd->UpdateResult(file);
2064 		}
2065 	}
2066 }
2067 
2068 
Phase1Done(const CECPacket * WXUNUSED (reply))2069 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
2070 {
2071 	CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
2072 	m_conn->SendRequest(this, &progress_req);
2073 
2074 	return true;
2075 }
2076 
2077 
RemoveResults(long nSearchID)2078 void CSearchListRem::RemoveResults(long nSearchID)
2079 {
2080 	ResultMap::iterator it = m_results.find(nSearchID);
2081 	if (it != m_results.end()) {
2082 		CSearchResultList& list = it->second;
2083 		for (unsigned int i = 0; i < list.size(); ++i) {
2084 			delete list[i];
2085 		}
2086 		m_results.erase(it);
2087 	}
2088 }
2089 
2090 
GetSearchResults(long nSearchID)2091 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
2092 {
2093 	ResultMap::const_iterator it = m_results.find(nSearchID);
2094 	if (it != m_results.end()) {
2095 		return it->second;
2096 	}
2097 
2098 	// TODO: Should we assert in this case?
2099 	static CSearchResultList list;
2100 	return list;
2101 }
2102 
2103 
HandlePacket(const CECPacket * packet)2104 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
2105 {
2106 	theStats::UpdateStats(packet);
2107 	theApp->amuledlg->ShowTransferRate();
2108 	theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
2109 	// handle the connstate tag which is included in the stats packet
2110 	theApp->serverconnect->HandlePacket(packet);
2111 }
2112 
2113 
RequestSharedFileList()2114 void CUpDownClient::RequestSharedFileList()
2115 {
2116 	CClientRef ref = CCLIENTREF(this, wxEmptyString);
2117 	theApp->friendlist->RequestSharedFileList(ref);
2118 }
2119 
2120 
SwapToAnotherFile(bool WXUNUSED (bIgnoreNoNeeded),bool WXUNUSED (ignoreSuspensions),bool WXUNUSED (bRemoveCompletely),CPartFile * toFile)2121 bool CUpDownClient::SwapToAnotherFile(
2122 	bool WXUNUSED(bIgnoreNoNeeded),
2123 	bool WXUNUSED(ignoreSuspensions),
2124 	bool WXUNUSED(bRemoveCompletely),
2125 	CPartFile* toFile)
2126 {
2127 	CECPacket req(EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE);
2128 	req.AddTag(CECTag(EC_TAG_CLIENT, ECID()));
2129 	req.AddTag(CECTag(EC_TAG_PARTFILE, toFile->GetFileHash()));
2130 	theApp->m_connect->SendPacket(&req);
2131 
2132 	return true;
2133 }
2134 
2135 
GetString() const2136 wxString CAICHHash::GetString() const
2137 {
2138 	return EncodeBase32(m_abyBuffer, HASHSIZE);
2139 }
2140 
2141 
2142 //
2143 // Those functions are virtual. So even they don't get called they must
2144 // be defined so linker will be happy
2145 //
CreateSrcInfoPacket(const CUpDownClient *,uint8,uint16)2146 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2147 {
2148 	wxFAIL;
2149 	return 0;
2150 }
2151 
2152 
LoadFromFile(const class CFileDataIO *)2153 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
2154 {
2155 	wxFAIL;
2156 	return false;
2157 }
2158 
2159 
UpdatePartsInfo()2160 void CKnownFile::UpdatePartsInfo()
2161 {
2162 	wxFAIL;
2163 }
2164 
2165 
CreateSrcInfoPacket(CUpDownClient const *,uint8,uint16)2166 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2167 {
2168 	wxFAIL;
2169 	return 0;
2170 }
2171 
2172 
UpdatePartsInfo()2173 void CPartFile::UpdatePartsInfo()
2174 {
2175 	wxFAIL;
2176 }
2177 
2178 
2179 
UpdateFileRatingCommentAvail()2180 void CPartFile::UpdateFileRatingCommentAvail()
2181 {
2182 	bool prevComment = m_hasComment;
2183 	int prevRating = m_iUserRating;
2184 
2185 	m_hasComment = false;
2186 	m_iUserRating = 0;
2187 	int ratingCount = 0;
2188 
2189 	FileRatingList::iterator it = m_FileRatingList.begin();
2190 	for (; it != m_FileRatingList.end(); ++it) {
2191 		SFileRating& cur_rat = *it;
2192 
2193 		if (!cur_rat.Comment.IsEmpty()) {
2194 			m_hasComment = true;
2195 		}
2196 
2197 		uint8 rating = cur_rat.Rating;
2198 		if (rating) {
2199 			wxASSERT(rating <= 5);
2200 
2201 			ratingCount++;
2202 			m_iUserRating += rating;
2203 		}
2204 	}
2205 
2206 	if (ratingCount) {
2207 		m_iUserRating /= ratingCount;
2208 		wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
2209 	}
2210 
2211 	if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
2212 		UpdateDisplayedInfo();
2213 	}
2214 }
2215 
2216 
DoRequery()2217 void CStatTreeRem::DoRequery()
2218 {
2219 	CECPacket request(EC_OP_GET_STATSTREE);
2220 	if (thePrefs::GetMaxClientVersions() != 0) {
2221 		request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions()));
2222 	}
2223 	m_conn->SendRequest(this, &request);
2224 }
2225 
HandlePacket(const CECPacket * p)2226 void CStatTreeRem::HandlePacket(const CECPacket * p)
2227 {
2228 	const CECTag* treeRoot = p->GetTagByName(EC_TAG_STATTREE_NODE);
2229 	if (treeRoot) {
2230 		theApp->amuledlg->m_statisticswnd->RebuildStatTreeRemote(treeRoot);
2231 		theApp->amuledlg->m_statisticswnd->ShowStatistics();
2232 	}
2233 }
2234 
2235 CamuleRemoteGuiApp *theApp;
2236 
2237 //
2238 // since gui is not linked with amule.cpp - define events here
2239 //
2240 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
2241 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
2242 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
2243 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
2244 // File_checked_for_headers
2245