debian: fix build-deps for focal
[amule.git] / src / amule-remote-gui.cpp
blob724d7438ff16688e15fa2b0d8d7ed08580e49ed4
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.
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.
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
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
33 #include <common/Format.h>
34 #include <common/StringFunctions.h>
35 #include <common/MD5Sum.h>
38 #include <include/common/EventIDs.h>
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
70 CEConnectDlg::CEConnectDlg()
72 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
74 CoreConnect(this, true);
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);
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);
85 CentreOnParent();
89 wxString CEConnectDlg::PassHash()
91 return pwd_hash;
95 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
96 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
97 END_EVENT_TABLE()
100 void CEConnectDlg::OnOK(wxCommandEvent& evt)
102 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
103 port = StrToLong(s_port);
105 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
106 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
108 if (passwd != pwd_hash) {
109 pwd_hash = MD5Sum(passwd).GetHash();
111 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
112 evt.Skip();
116 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
119 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
120 // Core timer
121 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
123 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
124 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
126 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
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()
135 IMPLEMENT_APP(CamuleRemoteGuiApp)
138 int CamuleRemoteGuiApp::OnExit()
140 StopTickTimer();
142 wxSocketBase::Shutdown(); // needed because we also called Initialize() manually
144 return wxApp::OnExit();
148 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
150 static int request_step = 0;
151 static uint32 msPrevStats = 0;
153 if (m_connect->RequestFifoFull()) {
154 return;
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;
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);
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();
189 // Back to the roots
190 request_step = 0;
191 break;
192 default:
193 wxFAIL;
194 request_step = 0;
197 // Check for new links once per second.
198 static uint32 lastED2KLinkCheck = 0;
199 if (GetTickCount() - lastED2KLinkCheck >= 1000) {
200 AddLinksFromFile();
201 lastED2KLinkCheck = GetTickCount();
206 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
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();
216 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
218 // Stop the Core Timer
219 delete poll_timer;
220 poll_timer = NULL;
222 #ifdef ASIO_SOCKETS
223 m_AsioService->Stop();
224 delete m_AsioService;
225 m_AsioService = NULL;
226 #endif
228 // Destroy the EC socket
229 m_connect->Destroy();
230 m_connect = NULL;
233 if (amuledlg) {
234 amuledlg->DlgShutDown();
235 amuledlg->Destroy();
236 amuledlg = NULL;
238 delete m_allUploadingKnownFile;
239 delete stattree;
243 bool CamuleRemoteGuiApp::OnInit()
245 StartTickTimer();
246 amuledlg = NULL;
248 // Get theApp
249 theApp = &wxGetApp();
251 // Handle uncaught exceptions
252 InstallMuleExceptionHandler();
254 // Parse cmdline arguments.
255 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
256 return false;
259 // Initialize wx sockets (needed for http download in background with Asio sockets)
260 wxSocketBase::Initialize();
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();
269 m_connect = new CRemoteConnect(this);
271 #ifdef ASIO_SOCKETS
272 m_AsioService = new CAsioService;
273 #endif
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
280 InitCustomLanguages();
281 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
283 if (ShowConnectionDialog()) {
284 AddLogLineNS(_("Going to event loop..."));
285 return true;
288 return false;
292 bool CamuleRemoteGuiApp::CryptoAvailable() const
294 return thePrefs::IsSecureIdentEnabled(); // good enough
298 bool CamuleRemoteGuiApp::ShowConnectionDialog()
300 dialog = new CEConnectDlg;
302 if (m_skipConnectionDialog) {
303 wxCommandEvent evt;
304 dialog->OnOK(evt);
305 } else if (dialog->ShowModal() != wxID_OK) {
306 dialog->Destroy();
308 return false;
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);
316 return false;
319 return true;
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);
340 wxCloseEvent ev;
341 ShutDown(ev);
342 ExitMainLoop();
347 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
349 Startup();
353 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
355 evt.Notify();
359 void CamuleRemoteGuiApp::Startup() {
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());
366 dialog->Destroy();
367 dialog = NULL;
369 m_ConnState = 0;
370 m_clientID = 0;
372 serverconnect = new CServerConnectRem(m_connect);
373 m_statistics = new CStatistics(*m_connect);
374 stattree = new CStatTreeRem(m_connect);
376 clientlist = new CUpDownClientListRem(m_connect);
377 searchlist = new CSearchListRem(m_connect);
378 serverlist = new CServerListRem(m_connect);
379 friendlist = new CFriendListRem(m_connect);
382 sharedfiles = new CSharedFilesRem(m_connect);
383 knownfiles = new CKnownFilesRem(m_connect);
385 downloadqueue = new CDownQueueRem(m_connect);
386 ipfilter = new CIPFilterRem(m_connect);
388 m_allUploadingKnownFile = new CKnownFile;
390 // Create main dialog
391 InitGui(m_geometryEnabled, m_geometryString);
393 // Forward wxLog events to CLogger
394 wxLog::SetActiveTarget(new CLoggerTarget);
395 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
397 // Start the Poll Timer
398 poll_timer->Start(1000);
399 amuledlg->StartGuiTimer();
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();
406 #endif
410 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
412 return CamuleGuiBase::ShowAlert(msg, title, flags);
416 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
418 amuledlg->AddLogLine(line);
421 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
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;
430 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
432 return CamuleGuiBase::CopyTextToClipboard(strText);
436 uint32 CamuleRemoteGuiApp::GetPublicIP()
438 return 0;
442 wxString CamuleRemoteGuiApp::GetLog(bool reset)
444 if (reset) {
445 amuledlg->ResetLog(ID_LOGVIEW);
446 CECPacket req(EC_OP_RESET_LOG);
447 m_connect->SendPacket(&req);
449 return wxEmptyString;
453 wxString CamuleRemoteGuiApp::GetServerLog(bool)
455 return wxEmptyString;
459 bool CamuleRemoteGuiApp::AddServer(CServer * server, bool)
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);
466 return true;
470 bool CamuleRemoteGuiApp::IsFirewalled() const
472 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
473 return false;
476 return IsFirewalledKad();
480 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
481 return serverconnect && serverconnect->IsConnected();
485 void CamuleRemoteGuiApp::StartKad() {
486 m_connect->StartKad();
490 void CamuleRemoteGuiApp::StopKad() {
491 m_connect->StopKad();
495 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
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));
501 m_connect->SendPacket(&req);
505 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
507 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
508 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
510 m_connect->SendPacket(&req);
514 void CamuleRemoteGuiApp::DisconnectED2K() {
515 if (IsConnectedED2K()) {
516 m_connect->DisconnectED2K();
521 uint32 CamuleRemoteGuiApp::GetED2KID() const
523 return serverconnect ? serverconnect->GetClientID() : 0;
527 uint32 CamuleRemoteGuiApp::GetID() const
529 return m_clientID;
533 void CamuleRemoteGuiApp::ShowUserCount() {
534 wxString buffer;
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");
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");
549 Notify_ShowUserCount(buffer);
554 * Preferences: holds both local and remote settings.
556 * First, everything is loaded from local config file. Later, settings
557 * that are relevant on remote side only are loaded thru EC
559 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
561 m_conn = conn;
564 // Settings queried from remote side
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;
584 void CPreferencesRem::HandlePacket(const CECPacket *packet)
586 static_cast<const CEC_Prefs_Packet *>(packet)->Apply();
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);
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);
607 wxECInitDoneEvent event;
608 theApp->AddPendingEvent(event);
613 bool CPreferencesRem::LoadRemote()
616 // override local settings with remote
617 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
619 // bring categories too
620 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
622 m_conn->SendRequest(this, &req);
624 return true;
628 void CPreferencesRem::SendToRemote()
630 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
631 m_conn->SendPacket(&pref_packet);
635 class CCatHandler : public CECPacketHandlerBase {
636 virtual void HandlePacket(const CECPacket *packet);
640 void CCatHandler::HandlePacket(const CECPacket *packet)
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();
656 delete this;
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)
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);
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;
680 AddCat(category);
682 return true;
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)
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);
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;
706 return true;
710 void CPreferencesRem::RemoveCat(uint8 cat)
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);
721 // Container implementation
723 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
725 m_CurrServer = 0;
726 m_Conn = conn;
730 void CServerConnectRem::ConnectToAnyServer()
732 CECPacket req(EC_OP_SERVER_CONNECT);
733 m_Conn->SendPacket(&req);
737 void CServerConnectRem::StopConnectionTry()
739 // lfroen: isn't Disconnect the same ?
743 void CServerConnectRem::Disconnect()
745 CECPacket req(EC_OP_SERVER_DISCONNECT);
746 m_Conn->SendPacket(&req);
750 void CServerConnectRem::ConnectToServer(CServer *server)
752 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
756 void CServerConnectRem::HandlePacket(const CECPacket *packet)
758 const CEC_ConnState_Tag *tag = static_cast<const CEC_ConnState_Tag *>(packet->GetTagByName(EC_TAG_CONNSTATE));
759 if (!tag) {
760 return;
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);
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;
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;
784 if (tag->IsConnectedKademlia()) {
785 if (tag->IsKadFirewalled()) {
786 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
787 } else {
788 theApp->m_ConnState |= CONNECTED_KAD_OK;
790 } else {
791 if (tag->IsKadRunning()) {
792 theApp->m_ConnState |= CONNECTED_KAD_NOT;
796 theApp->amuledlg->ShowConnectionState();
801 * Server list: host list of ed2k servers.
803 CServerListRem::CServerListRem(CRemoteConnect *conn)
805 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, true)
810 void CServerListRem::HandlePacket(const CECPacket *)
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);
818 void CServerListRem::UpdateServerMetFromURL(wxString url)
820 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
821 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
823 m_conn->SendPacket(&req);
827 void CServerListRem::SetStaticServer(CServer* server, bool isStatic)
829 // update display right away
830 server->SetIsStaticMember(isStatic);
831 Notify_ServerRefresh(server);
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));
837 m_conn->SendPacket(&req);
841 void CServerListRem::SetServerPrio(CServer* server, uint32 prio)
843 // update display right away
844 server->SetPreference(prio);
845 Notify_ServerRefresh(server);
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));
851 m_conn->SendPacket(&req);
855 void CServerListRem::RemoveServer(CServer* server)
857 m_conn->RemoveServer(server->GetIP(),server->GetPort());
861 void CServerListRem::UpdateUserFileStatus(CServer *server)
863 if (server) {
864 m_TotalUser = server->GetUsers();
865 m_TotalFile = server->GetFiles();
870 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
872 // It's ok to return 0 for context where this code is used in remote gui
873 return 0;
876 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
878 // It's ok to return 0 for context where this code is used in remote gui
879 return 0;
882 CServer *CServerListRem::CreateItem(const CEC_Server_Tag *tag)
884 CServer * server = new CServer(tag);
885 ProcessItemUpdate(tag, server);
886 return server;
890 void CServerListRem::DeleteItem(CServer *in_srv)
892 CScopedPtr<CServer> srv(in_srv);
893 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
897 uint32 CServerListRem::GetItemID(CServer *server)
899 return server->ECID();
903 void CServerListRem::ProcessItemUpdate(const CEC_Server_Tag * tag, CServer * server)
905 if (!tag->HasChildTags()) {
906 return;
908 tag->ServerName(& server->listname);
909 tag->ServerDesc(& server->description);
910 tag->ServerVersion(& server->m_strVersion);
911 tag->GetMaxUsers(& server->maxusers);
913 tag->GetFiles(& server->files);
914 tag->GetUsers(& server->users);
916 tag->GetPrio(& server->preferences); // SRV_PR_NORMAL = 0, so it's ok
917 tag->GetStatic(& server->staticservermember);
919 tag->GetPing(& server->ping);
920 tag->GetFailed(& server->failedcount);
922 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(server);
926 CServer::CServer(const CEC_Server_Tag *tag) : CECID(tag->GetInt())
928 ip = tag->GetTagByNameSafe(EC_TAG_SERVER_IP)->GetInt();
929 port = tag->GetTagByNameSafe(EC_TAG_SERVER_PORT)->GetInt();
931 Init();
936 * IP filter
938 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
940 m_conn = conn;
944 void CIPFilterRem::Reload()
946 CECPacket req(EC_OP_IPFILTER_RELOAD);
947 m_conn->SendPacket(&req);
951 void CIPFilterRem::Update(wxString url)
953 CECPacket req(EC_OP_IPFILTER_UPDATE);
954 req.AddTag(CECTag(EC_TAG_STRING, url));
956 m_conn->SendPacket(&req);
961 * Shared files list
963 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
965 m_conn = conn;
969 void CSharedFilesRem::Reload(bool, bool)
971 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
973 m_conn->SendPacket(&req);
977 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
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();
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));
987 m_conn->SendPacket(&request);
989 return true;
993 void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating)
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));
1000 m_conn->SendPacket(&request);
1004 void CSharedFilesRem::CopyFileList(std::vector<CKnownFile*>& out_list) const
1006 out_list.reserve(size());
1007 for (const_iterator it = begin(); it != end(); ++it) {
1008 out_list.push_back(it->second);
1013 void CKnownFilesRem::DeleteItem(CKnownFile * file)
1015 uint32 id = file->ECID();
1016 if (theApp->sharedfiles->count(id)) {
1017 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
1018 theApp->sharedfiles->erase(id);
1020 if (theApp->downloadqueue->count(id)) {
1021 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile(static_cast<CPartFile *>(file));
1022 theApp->downloadqueue->erase(id);
1024 delete file;
1028 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
1030 return file->ECID();
1034 void CKnownFilesRem::ProcessItemUpdate(const CEC_SharedFile_Tag *tag, CKnownFile *file)
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];
1045 wxString fileName;
1046 if (tag->FileName(fileName)) {
1047 file->SetFileName(CPath(fileName));
1049 if (tag->FilePath(fileName)) {
1050 file->m_filePath = CPath(fileName);
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;
1069 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1070 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1071 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1073 tag->GetOnQueue(&file->m_queuedCount);
1075 tag->GetComment(file->m_strComment);
1076 tag->GetRating(file->m_iRating);
1078 requested += file->statistic.requested;
1079 transferred += file->statistic.transferred;
1080 accepted += file->statistic.transferred;
1082 if (!m_initialUpdate) {
1083 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1086 if (file->IsPartFile()) {
1087 ProcessItemUpdatePartfile(static_cast<const CEC_PartFile_Tag *>(tag), static_cast<CPartFile *>(file));
1091 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1093 CECPacket req(EC_OP_SHARED_SET_PRIO);
1095 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1096 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1098 req.AddTag(hashtag);
1100 m_conn->SendPacket(&req);
1103 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1105 requested = 0;
1106 transferred = 0;
1107 accepted = 0;
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);
1131 isNew = false;
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);
1150 AddItem(newFile);
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.
1169 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1171 requested = 0;
1172 transferred = 0;
1173 accepted = 0;
1174 m_initialUpdate = true;
1179 * List of uploading and waiting clients.
1181 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1183 CRemoteContainer<CClientRef, uint32, CEC_UpDownClient_Tag>(conn, true)
1188 CClientRef::CClientRef(const CEC_UpDownClient_Tag *tag)
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
1199 CUpDownClient::CUpDownClient(const CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
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;
1239 credits = new CClientCredits(new CreditStruct());
1242 #ifdef DEBUG_ZOMBIE_CLIENTS
1243 void CUpDownClient::Unlink(const wxString& from)
1245 std::multiset<wxString>::iterator it = m_linkedFrom.find(from);
1246 if (it != m_linkedFrom.end()) {
1247 m_linkedFrom.erase(it);
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);
1254 delete this;
1258 #else
1260 void CUpDownClient::Unlink()
1262 m_linked--;
1263 if (!m_linked) {
1264 delete this;
1267 #endif
1270 uint64 CUpDownClient::GetDownloadedTotal() const
1272 return credits->GetDownloadedTotal();
1276 uint64 CUpDownClient::GetUploadedTotal() const
1278 return credits->GetUploadedTotal();
1282 double CUpDownClient::GetScoreRatio() const
1284 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1287 /* End Warning */
1290 CUpDownClient::~CUpDownClient()
1292 delete credits;
1296 CClientRef *CUpDownClientListRem::CreateItem(const CEC_UpDownClient_Tag *tag)
1298 CClientRef *client = new CClientRef(tag);
1299 ProcessItemUpdate(tag, client);
1301 return client;
1305 void CUpDownClientListRem::DeleteItem(CClientRef *clientref)
1307 CUpDownClient* client = clientref->GetClient();
1308 if (client->m_reqfile) {
1309 client->m_reqfile->DelSource(client);
1310 client->m_reqfile = NULL;
1312 Notify_SourceCtrlRemoveSource(client->ECID(), (CPartFile*) NULL);
1314 if (client->m_uploadingfile) {
1315 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1316 client->m_uploadingfile = NULL;
1318 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client); // in case it vanished directly while uploading
1319 Notify_SharedCtrlRemoveClient(client->ECID(), (CKnownFile*) NULL);
1321 if (client->m_Friend) {
1322 client->m_Friend->UnLinkClient(); // this notifies
1323 client->m_Friend = NULL;
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;
1331 #endif
1333 delete clientref;
1337 uint32 CUpDownClientListRem::GetItemID(CClientRef *client)
1339 return client->ECID();
1343 void CUpDownClientListRem::ProcessItemUpdate(
1344 const CEC_UpDownClient_Tag *tag,
1345 CClientRef *clientref)
1347 if (!tag->HasChildTags()) {
1348 return; // speed exit for clients without any change
1350 CUpDownClient *client = clientref->GetClient();
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;
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;
1367 // User hash
1368 tag->UserHash(&client->m_UserHash);
1370 // User IP:Port
1371 tag->UserIP(client->m_dwUserIP);
1372 tag->UserPort(&client->m_nUserPort);
1374 // Server IP:Port
1375 tag->ServerIP(&client->m_dwServerIP);
1376 tag->ServerPort(&client->m_nServerPort);
1377 tag->ServerName(&client->m_ServerName);
1379 tag->KadPort(client->m_nKadPort);
1380 tag->FriendSlot(client->m_bFriendSlot);
1382 tag->GetCurrentIdentState(&client->m_identState);
1383 tag->ObfuscationStatus(client->m_obfuscationStatus);
1384 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
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);
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);
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;
1407 //tag->WaitTime(&client->m_WaitTime);
1408 //tag->XferTime(&client->m_UpStartTimeDelay);
1409 //tag->LastReqTime(&client->m_dwLastUpRequest);
1410 //tag->QueueTime(&client->m_WaitStartTime);
1412 CreditStruct *credit_struct = const_cast<CreditStruct *>(client->credits->GetDataStruct());
1413 tag->XferUp(&credit_struct->uploaded);
1414 tag->XferUpSession(&client->m_nTransferredUp);
1416 tag->XferDown(&credit_struct->downloaded);
1417 tag->XferDownSession(&client->m_nTransferredDown);
1419 tag->Score(&client->m_score);
1421 tag->NextRequestedPart(client->m_nextRequestedPart);
1422 tag->LastDownloadingPart(client->m_lastDownloadingPart);
1424 uint8 sourceFrom = 0;
1425 if (tag->GetSourceFrom(sourceFrom)) {
1426 client->m_nSourceFrom = (ESourceFrom)sourceFrom;
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);
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();
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;
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());
1465 notified = false;
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;
1481 Notify_SourceCtrlUpdateSource(client->ECID(), type);
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;
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;
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());
1507 notified = false;
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;
1523 Notify_SharedCtrlRefreshClient(client->ECID(), type);
1529 * Download queue container: hold PartFiles with progress status
1534 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
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);
1541 m_conn->SendPacket(&req);
1542 return true;
1546 void CDownQueueRem::ResetCatParts(int cat)
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);
1559 void CKnownFilesRem::ProcessItemUpdatePartfile(const CEC_PartFile_Tag *tag, CPartFile *file)
1562 // update status
1564 tag->Speed(&file->m_kbpsDown);
1565 file->kBpsDown = file->m_kbpsDown / 1024.0;
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);
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);
1584 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1585 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1586 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1588 tag->FileCat(&file->m_category);
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;
1599 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1602 // Copy part/gap status
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;
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);
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]);
1622 if (parttag) {
1623 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1624 // sanity check
1625 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
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);
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);
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();
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);
1675 file->UpdateFileRatingCommentAvail();
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;
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);
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);
1710 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
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);
1721 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1723 CECPacket req(cmd);
1724 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1726 m_conn->SendPacket(&req);
1730 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1732 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1734 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1735 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1736 req.AddTag(hashtag);
1738 m_conn->SendPacket(&req);
1742 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1744 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1746 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1748 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1749 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1750 req.AddTag(hashtag);
1752 m_conn->SendPacket(&req);
1756 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1758 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1759 file->SetCategory(cat);
1761 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1762 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1763 req.AddTag(hashtag);
1765 m_conn->SendPacket(&req);
1769 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
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);
1776 m_conn->SendPacket(&req);
1780 void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids)
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));
1787 m_conn->SendPacket(&req);
1792 * List of friends.
1794 CFriendListRem::CFriendListRem(CRemoteConnect *conn)
1796 CRemoteContainer<CFriend, uint32, CEC_Friend_Tag>(conn, true)
1801 void CFriendListRem::HandlePacket(const CECPacket *)
1803 wxFAIL; // not needed
1807 CFriend * CFriendListRem::CreateItem(const CEC_Friend_Tag * tag)
1809 CFriend * Friend = new CFriend(tag->ID());
1810 ProcessItemUpdate(tag, Friend);
1811 return Friend;
1815 void CFriendListRem::DeleteItem(CFriend * Friend)
1817 Friend->UnLinkClient(false);
1818 Notify_ChatRemoveFriend(Friend);
1822 uint32 CFriendListRem::GetItemID(CFriend * Friend)
1824 return Friend->ECID();
1828 void CFriendListRem::ProcessItemUpdate(const CEC_Friend_Tag * tag, CFriend * Friend)
1830 if (!tag->HasChildTags()) {
1831 return;
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;
1846 } else {
1847 // Unlink
1848 Friend->UnLinkClient(false);
1851 if (!notified) {
1852 Notify_ChatUpdateFriend(Friend);
1857 void CFriendListRem::AddFriend(const CClientRef& toadd)
1859 CECPacket req(EC_OP_FRIEND);
1861 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1862 addtag.AddTag(CECTag(EC_TAG_CLIENT, toadd.ECID()));
1863 req.AddTag(addtag);
1865 m_conn->SendPacket(&req);
1869 void CFriendListRem::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name)
1871 CECPacket req(EC_OP_FRIEND);
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);
1880 m_conn->SendPacket(&req);
1884 void CFriendListRem::RemoveFriend(CFriend* toremove)
1886 CECPacket req(EC_OP_FRIEND);
1888 CECEmptyTag removetag(EC_TAG_FRIEND_REMOVE);
1889 removetag.AddTag(CECTag(EC_TAG_FRIEND, toremove->ECID()));
1890 req.AddTag(removetag);
1892 m_conn->SendPacket(&req);
1896 void CFriendListRem::SetFriendSlot(CFriend* Friend, bool new_state)
1898 CECPacket req(EC_OP_FRIEND);
1900 CECTag slottag(EC_TAG_FRIEND_FRIENDSLOT, new_state);
1901 slottag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1902 req.AddTag(slottag);
1904 m_conn->SendPacket(&req);
1908 void CFriendListRem::RequestSharedFileList(CFriend* Friend)
1910 CECPacket req(EC_OP_FRIEND);
1912 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1913 sharedtag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1914 req.AddTag(sharedtag);
1916 m_conn->SendPacket(&req);
1920 void CFriendListRem::RequestSharedFileList(CClientRef& client)
1922 CECPacket req(EC_OP_FRIEND);
1924 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1925 sharedtag.AddTag(CECTag(EC_TAG_CLIENT, client.ECID()));
1926 req.AddTag(sharedtag);
1928 m_conn->SendPacket(&req);
1934 * Search results
1936 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1938 m_curr_search = -1;
1942 wxString CSearchListRem::StartNewSearch(
1943 uint32* nSearchID, SearchType search_type,
1944 const CSearchList::CSearchParams& params)
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;
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));
1958 m_conn->SendPacket(&search_req);
1959 m_curr_search = *(nSearchID); // No kad remote search yet.
1961 Flush();
1963 return wxEmptyString; // EC reply will have the error mesg is needed.
1967 void CSearchListRem::StopSearch(bool)
1969 if (m_curr_search != -1) {
1970 CECPacket search_req(EC_OP_SEARCH_STOP);
1971 m_conn->SendPacket(&search_req);
1976 void CSearchListRem::HandlePacket(const CECPacket *packet)
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);
1986 CSearchFile::CSearchFile(const CEC_SearchFile_Tag *tag)
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)
1999 SetFileName(CPath(tag->FileName()));
2000 m_abyFileHash = tag->FileHash();
2001 SetFileSize(tag->SizeFull());
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);
2014 void CSearchFile::AddChild(CSearchFile* file)
2016 m_children.push_back(file);
2017 file->m_parent = this;
2021 // dtor is virtual - must be implemented
2022 CSearchFile::~CSearchFile()
2027 CSearchFile *CSearchListRem::CreateItem(const CEC_SearchFile_Tag *tag)
2029 CSearchFile *file = new CSearchFile(tag);
2030 ProcessItemUpdate(tag, file);
2032 theApp->amuledlg->m_searchwnd->AddResult(file);
2034 return file;
2038 void CSearchListRem::DeleteItem(CSearchFile *file)
2040 delete file;
2044 uint32 CSearchListRem::GetItemID(CSearchFile *file)
2046 return file->ECID();
2050 void CSearchListRem::ProcessItemUpdate(const CEC_SearchFile_Tag *tag, CSearchFile *file)
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);
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);
2069 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
2071 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
2072 m_conn->SendRequest(this, &progress_req);
2074 return true;
2078 void CSearchListRem::RemoveResults(long nSearchID)
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];
2086 m_results.erase(it);
2091 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
2093 ResultMap::const_iterator it = m_results.find(nSearchID);
2094 if (it != m_results.end()) {
2095 return it->second;
2098 // TODO: Should we assert in this case?
2099 static CSearchResultList list;
2100 return list;
2104 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
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);
2114 void CUpDownClient::RequestSharedFileList()
2116 CClientRef ref = CCLIENTREF(this, wxEmptyString);
2117 theApp->friendlist->RequestSharedFileList(ref);
2121 bool CUpDownClient::SwapToAnotherFile(
2122 bool WXUNUSED(bIgnoreNoNeeded),
2123 bool WXUNUSED(ignoreSuspensions),
2124 bool WXUNUSED(bRemoveCompletely),
2125 CPartFile* toFile)
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);
2132 return true;
2136 wxString CAICHHash::GetString() const
2138 return EncodeBase32(m_abyBuffer, HASHSIZE);
2143 // Those functions are virtual. So even they don't get called they must
2144 // be defined so linker will be happy
2146 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2148 wxFAIL;
2149 return 0;
2153 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
2155 wxFAIL;
2156 return false;
2160 void CKnownFile::UpdatePartsInfo()
2162 wxFAIL;
2166 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2168 wxFAIL;
2169 return 0;
2173 void CPartFile::UpdatePartsInfo()
2175 wxFAIL;
2180 void CPartFile::UpdateFileRatingCommentAvail()
2182 bool prevComment = m_hasComment;
2183 int prevRating = m_iUserRating;
2185 m_hasComment = false;
2186 m_iUserRating = 0;
2187 int ratingCount = 0;
2189 FileRatingList::iterator it = m_FileRatingList.begin();
2190 for (; it != m_FileRatingList.end(); ++it) {
2191 SFileRating& cur_rat = *it;
2193 if (!cur_rat.Comment.IsEmpty()) {
2194 m_hasComment = true;
2197 uint8 rating = cur_rat.Rating;
2198 if (rating) {
2199 wxASSERT(rating <= 5);
2201 ratingCount++;
2202 m_iUserRating += rating;
2206 if (ratingCount) {
2207 m_iUserRating /= ratingCount;
2208 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
2211 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
2212 UpdateDisplayedInfo();
2217 void CStatTreeRem::DoRequery()
2219 CECPacket request(EC_OP_GET_STATSTREE);
2220 if (thePrefs::GetMaxClientVersions() != 0) {
2221 request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions()));
2223 m_conn->SendRequest(this, &request);
2226 void CStatTreeRem::HandlePacket(const CECPacket * p)
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();
2235 CamuleRemoteGuiApp *theApp;
2238 // since gui is not linked with amule.cpp - define events here
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