Upstream tarball 10063
[amule.git] / src / amule-remote-gui.cpp
blob0844d1eeef6d1863fe2534c873c8b86ae7461559
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2008 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.
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
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
32 #include <common/Format.h>
33 #include <common/StringFunctions.h>
34 #include <common/MD5Sum.h>
37 #include <include/common/EventIDs.h>
40 #include "amule.h" // Interface declarations.
41 #include "amuleDlg.h" // Needed for CamuleDlg
42 #include "ClientCredits.h"
43 #include "ClientListCtrl.h"
44 #include "DataToText.h" // Needed for GetSoftName()
45 #include "DownloadListCtrl.h" // Needed for CDownloadListCtrl
46 #include "GuiEvents.h"
47 #ifdef ENABLE_IP2COUNTRY
48 #include "IP2Country.h" // Needed for IP2Country
49 #endif
50 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
51 #include "Logger.h"
52 #include "muuli_wdr.h" // Needed for IDs
53 #include "PartFile.h" // Needed for CPartFile
54 #include "SearchDlg.h" // Needed for CSearchDlg
55 #include "Server.h" // Needed for GetListName
56 #include "ServerWnd.h" // Needed for CServerWnd
57 #include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl
58 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
59 #include "TransferWnd.h" // Needed for CTransferWnd
60 #include "updownclient.h"
61 #include "ServerListCtrl.h" // Needed for CServerListCtrl
62 #include "ScopedPtr.h"
65 CEConnectDlg::CEConnectDlg()
67 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
69 CoreConnect(this, true);
71 wxString pref_host, pref_port;
72 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
73 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
74 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
76 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
77 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
78 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
80 CentreOnParent();
84 wxString CEConnectDlg::PassHash()
86 return pwd_hash;
90 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
91 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
92 END_EVENT_TABLE()
95 void CEConnectDlg::OnOK(wxCommandEvent& evt)
97 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
98 port = StrToLong(s_port);
100 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
101 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
103 if (passwd != pwd_hash) {
104 pwd_hash = MD5Sum(passwd).GetHash();
106 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
107 evt.Skip();
111 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
114 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
115 // Core timer
116 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
118 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
119 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
121 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
123 #ifdef ENABLE_IP2COUNTRY
124 // HTTPDownload finished
125 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
126 #endif
127 END_EVENT_TABLE()
130 IMPLEMENT_APP(CamuleRemoteGuiApp)
133 int CamuleRemoteGuiApp::OnExit()
135 StopTickTimer();
137 return wxApp::OnExit();
141 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
143 static int request_step = 0;
145 if (m_connect->RequestFifoFull()) {
146 return;
149 switch (request_step) {
150 case 0:
151 serverconnect->ReQuery();
152 serverlist->UpdateUserFileStatus(serverconnect->GetCurrentServer());
153 request_step++;
154 break;
155 case 1: {
156 CECPacket stats_req(EC_OP_STAT_REQ);
157 m_connect->SendRequest(&m_stats_updater, &stats_req);
158 amuledlg->ShowTransferRate();
159 request_step++;
160 break;
162 case 2:
163 if (amuledlg->m_sharedfileswnd->IsShown()) {
164 // update both downloads and shared files
165 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
166 } else if (amuledlg->m_serverwnd->IsShown()) {
167 //serverlist->FullReload(EC_OP_GET_SERVER_LIST);
168 } else if (amuledlg->m_transferwnd->IsShown()) {
169 // update both downloads and shared files
170 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
171 switch(amuledlg->m_transferwnd->clientlistctrl->GetListView()) {
172 case vtUploading:
173 uploadqueue->ReQueryUp();
174 break;
175 case vtQueued:
176 uploadqueue->ReQueryWait();
177 break;
178 case vtClients:
179 break;
180 case vtNone:
181 break;
183 amuledlg->m_transferwnd->ShowQueueCount(theStats::GetWaitingUserCount());
184 } else if (amuledlg->m_searchwnd->IsShown()) {
185 if (searchlist->m_curr_search != -1) {
186 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
189 // Back to the roots
190 request_step = 0;
191 break;
192 default:
193 AddLogLineCS(wxT("WTF?")); // should not happen. :-)
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 #ifdef ENABLE_IP2COUNTRY
209 if (event.GetInt() == HTTP_GeoIP) {
210 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
211 // If we updated, the dialog is already up. Redraw it to show the flags.
212 amuledlg->Refresh();
214 #endif
218 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
220 // Stop the Core Timer
221 delete poll_timer;
222 poll_timer = NULL;
224 // Destroy the EC socket
225 m_connect->Destroy();
226 m_connect = NULL;
229 if (amuledlg) {
230 amuledlg->DlgShutDown();
231 amuledlg->Destroy();
232 amuledlg = NULL;
237 bool CamuleRemoteGuiApp::OnInit()
239 StartTickTimer();
240 amuledlg = NULL;
242 // Get theApp
243 theApp = &wxGetApp();
245 // Handle uncaught exceptions
246 InstallMuleExceptionHandler();
248 // Parse cmdline arguments.
249 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
250 return false;
253 // Create the polling timer
254 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
255 if (!poll_timer) {
256 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
257 OnExit();
260 m_connect = new CRemoteConnect(this);
262 glob_prefs = new CPreferencesRem(m_connect);
264 InitCustomLanguages();
265 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
267 if (ShowConnectionDialog()) {
268 AddLogLineNS(_("Going to event loop..."));
269 return true;
272 return false;
276 bool CamuleRemoteGuiApp::CryptoAvailable() const
278 return thePrefs::IsSecureIdentEnabled(); // good enough
282 bool CamuleRemoteGuiApp::ShowConnectionDialog()
284 dialog = new CEConnectDlg;
286 if (m_skipConnectionDialog) {
287 wxCommandEvent evt;
288 dialog->OnOK(evt);
289 } else if (dialog->ShowModal() != wxID_OK) {
290 dialog->Destroy();
292 return false;
294 AddLogLineNS(_("Connecting..."));
295 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
296 dialog->Login(), dialog->PassHash(),
297 wxT("amule-remote"), wxT("0x0001"))) {
298 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
300 return false;
303 return true;
307 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
308 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
309 AddLogLineNS(_("Remote GUI EC event handler"));
310 wxString reply = evt.GetServerReply();
311 AddLogLineM(true, reply);
312 if (evt.GetResult() == true) {
313 // Connected - go to next init step
314 glob_prefs->LoadRemote();
315 } else {
316 AddLogLineNS(_("Going down"));
317 if (dialog) { // connect failed
318 wxMessageBox(
319 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
320 _("ERROR"), wxOK);
321 } else { // server disconnected (probably terminated) later
322 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
324 ExitMainLoop();
329 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
331 Startup();
335 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
337 evt.Notify();
341 void CamuleRemoteGuiApp::Startup() {
343 if (dialog->SaveUserPass()) {
344 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
345 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
346 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
348 dialog->Destroy();
349 dialog = NULL;
351 m_ConnState = 0;
352 m_clientID = 0;
354 serverconnect = new CServerConnectRem(m_connect);
355 m_statistics = new CStatistics(*m_connect);
357 clientlist = new CClientListRem(m_connect);
358 searchlist = new CSearchListRem(m_connect);
359 serverlist = new CServerListRem(m_connect);
361 sharedfiles = new CSharedFilesRem(m_connect);
362 knownfiles = new CKnownFilesRem(m_connect);
364 // bugfix - do this before creating the uploadqueue
365 downloadqueue = new CDownQueueRem(m_connect);
366 uploadqueue = new CUpQueueRem(m_connect);
367 ipfilter = new CIPFilterRem(m_connect);
369 // Create main dialog
370 InitGui(m_geometryEnabled, m_geometryString);
372 // Forward wxLog events to CLogger
373 wxLog::SetActiveTarget(new CLoggerTarget);
374 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
375 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
377 // Start the Poll Timer
378 poll_timer->Start(1000);
379 amuledlg->StartGuiTimer();
381 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
382 #ifdef ENABLE_IP2COUNTRY
383 if (thePrefs::IsGeoIPEnabled()) {
384 amuledlg->m_IP2Country->Enable();
386 #endif
390 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
392 return CamuleGuiBase::ShowAlert(msg, title, flags);
396 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
398 amuledlg->AddLogLine(line);
401 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
403 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
404 SetTopWindow(amuledlg);
405 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
406 return 0;
410 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
412 return CamuleGuiBase::CopyTextToClipboard(strText);
416 uint32 CamuleRemoteGuiApp::GetPublicIP()
418 return 0;
422 wxString CamuleRemoteGuiApp::GetLog(bool)
424 return wxEmptyString;
428 wxString CamuleRemoteGuiApp::GetServerLog(bool)
430 return wxEmptyString;
434 bool CamuleRemoteGuiApp::AddServer(CServer *, bool)
436 // #warning TODO: Add remote command
437 return true;
441 bool CamuleRemoteGuiApp::IsFirewalled() const
443 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
444 return false;
447 return IsFirewalledKad();
451 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
452 return serverconnect && serverconnect->IsConnected();
456 void CamuleRemoteGuiApp::StartKad() {
457 m_connect->StartKad();
461 void CamuleRemoteGuiApp::StopKad() {
462 m_connect->StopKad();
466 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
468 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
469 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
470 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
472 m_connect->SendPacket(&req);
476 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
478 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
479 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
481 m_connect->SendPacket(&req);
485 void CamuleRemoteGuiApp::DisconnectED2K() {
486 if (IsConnectedED2K()) {
487 m_connect->DisconnectED2K();
492 uint32 CamuleRemoteGuiApp::GetED2KID() const
494 return serverconnect ? serverconnect->GetClientID() : 0;
498 uint32 CamuleRemoteGuiApp::GetID() const
500 return m_clientID;
504 void CamuleRemoteGuiApp::ShowUserCount() {
505 wxString buffer;
507 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
508 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
510 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
511 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
512 } else if (thePrefs::GetNetworkED2K()) {
513 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
514 } else if (thePrefs::GetNetworkKademlia()) {
515 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
516 } else {
517 buffer = _("No networks selected");
520 Notify_ShowUserCount(buffer);
525 * Preferences: holds both local and remote settings.
527 * First, everything is loaded from local config file. Later, settings
528 * that are relevant on remote side only are loaded thru EC
530 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
532 m_conn = conn;
535 // Settings queried from remote side
537 m_exchange_send_selected_prefs =
538 EC_PREFS_GENERAL |
539 EC_PREFS_CONNECTIONS |
540 EC_PREFS_MESSAGEFILTER |
541 EC_PREFS_ONLINESIG |
542 EC_PREFS_SERVERS |
543 EC_PREFS_FILES |
544 EC_PREFS_SRCDROP |
545 EC_PREFS_DIRECTORIES |
546 EC_PREFS_SECURITY |
547 EC_PREFS_CORETWEAKS |
548 EC_PREFS_REMOTECONTROLS |
549 EC_PREFS_KADEMLIA;
550 m_exchange_recv_selected_prefs =
551 m_exchange_send_selected_prefs |
552 EC_PREFS_CATEGORIES;
556 void CPreferencesRem::HandlePacket(const CECPacket *packet)
558 ((CEC_Prefs_Packet *)packet)->Apply();
560 if ( packet->GetTagByName(EC_TAG_PREFS_CATEGORIES) != 0 ) {
561 for (size_t i = 0; i < packet->GetTagByName(EC_TAG_PREFS_CATEGORIES)->GetTagCount(); i++) {
562 const CECTag *cat_tag = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES)->GetTagByIndex(i);
563 Category_Struct *cat = new Category_Struct;
564 cat->title = cat_tag->GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
565 cat->path = CPath(cat_tag->GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
566 cat->comment = cat_tag->GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
567 cat->color = cat_tag->GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
568 cat->prio = cat_tag->GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
569 theApp->glob_prefs->AddCat(cat);
571 } else {
572 Category_Struct *cat = new Category_Struct;
573 cat->title = _("All");
574 cat->color = 0;
575 cat->prio = PR_NORMAL;
576 theApp->glob_prefs->AddCat(cat);
578 wxECInitDoneEvent event;
579 theApp->AddPendingEvent(event);
584 bool CPreferencesRem::LoadRemote()
587 // override local settings with remote
588 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
590 // bring categories too
591 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
593 m_conn->SendRequest(this, &req);
595 return true;
599 void CPreferencesRem::SendToRemote()
601 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
602 m_conn->SendPacket(&pref_packet);
606 class CCatHandler : public CECPacketHandlerBase {
607 virtual void HandlePacket(const CECPacket *packet);
611 void CCatHandler::HandlePacket(const CECPacket *packet)
613 if (packet->GetOpCode() == EC_OP_FAILED) {
614 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
615 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
616 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
617 int cat = catTag->GetInt();
618 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
619 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
620 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
621 _("ERROR"), wxOK);
622 cs->path = CPath(pathTag->GetStringData());
623 theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
624 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
627 delete this;
631 bool CPreferencesRem::CreateCategory(
632 Category_Struct *& category,
633 const wxString& name,
634 const CPath& path,
635 const wxString& comment,
636 uint32 color,
637 uint8 prio)
639 CECPacket req(EC_OP_CREATE_CATEGORY);
640 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
641 req.AddTag(tag);
642 m_conn->SendRequest(new CCatHandler, &req);
644 category = new Category_Struct();
645 category->path = path;
646 category->title = name;
647 category->comment = comment;
648 category->color = color;
649 category->prio = prio;
651 AddCat(category);
653 return true;
657 bool CPreferencesRem::UpdateCategory(
658 uint8 cat,
659 const wxString& name,
660 const CPath& path,
661 const wxString& comment,
662 uint32 color,
663 uint8 prio)
665 CECPacket req(EC_OP_UPDATE_CATEGORY);
666 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
667 req.AddTag(tag);
668 m_conn->SendRequest(new CCatHandler, &req);
670 Category_Struct *category = m_CatList[cat];
671 category->path = path;
672 category->title = name;
673 category->comment = comment;
674 category->color = color;
675 category->prio = prio;
677 return true;
681 void CPreferencesRem::RemoveCat(uint8 cat)
683 CECPacket req(EC_OP_DELETE_CATEGORY);
684 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
685 req.AddTag(tag);
686 m_conn->SendPacket(&req);
687 CPreferences::RemoveCat(cat);
692 // Container implementation
694 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
696 m_CurrServer = 0;
697 m_Conn = conn;
701 void CServerConnectRem::ConnectToAnyServer()
703 CECPacket req(EC_OP_SERVER_CONNECT);
704 m_Conn->SendPacket(&req);
708 void CServerConnectRem::StopConnectionTry()
710 // lfroen: isn't Disconnect the same ?
714 void CServerConnectRem::Disconnect()
716 CECPacket req(EC_OP_SERVER_DISCONNECT);
717 m_Conn->SendPacket(&req);
721 void CServerConnectRem::ConnectToServer(CServer *server)
723 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
727 bool CServerConnectRem::ReQuery()
729 CECPacket stat_req(EC_OP_GET_CONNSTATE);
730 m_Conn->SendRequest(this, &stat_req);
732 return true;
736 void CServerConnectRem::HandlePacket(const CECPacket *packet)
738 CEC_ConnState_Tag *tag =
739 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
740 if (!tag) {
741 return;
744 theApp->m_ConnState = 0;
745 CServer *server;
746 m_ID = tag->GetEd2kId();
747 theApp->m_clientID = tag->GetClientId();
749 if (tag->IsConnectedED2K()) {
750 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
751 if (!srvtag) {
752 return;
754 server = theApp->serverlist->GetByID(srvtag->GetIPv4Data().IP());
755 if (m_CurrServer && (server != m_CurrServer)) {
756 theApp->amuledlg->m_serverwnd->serverlistctrl->
757 HighlightServer(m_CurrServer, false);
759 theApp->amuledlg->m_serverwnd->serverlistctrl->
760 HighlightServer(server, true);
761 m_CurrServer = server;
762 theApp->m_ConnState |= CONNECTED_ED2K;
763 } else {
764 if ( m_CurrServer ) {
765 theApp->amuledlg->m_serverwnd->serverlistctrl->
766 HighlightServer(m_CurrServer, false);
767 m_CurrServer = 0;
771 if (tag->IsConnectedKademlia()) {
772 if (tag->IsKadFirewalled()) {
773 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
774 } else {
775 theApp->m_ConnState |= CONNECTED_KAD_OK;
777 } else {
778 if (tag->IsKadRunning()) {
779 theApp->m_ConnState |= CONNECTED_KAD_NOT;
783 theApp->amuledlg->ShowConnectionState();
788 * Server list: host list of ed2k servers.
790 CServerListRem::CServerListRem(CRemoteConnect *conn)
792 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, false)
797 void CServerListRem::HandlePacket(const CECPacket *packet)
799 CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
800 ReloadControl();
804 void CServerListRem::UpdateServerMetFromURL(wxString url)
806 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
807 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
809 m_conn->SendPacket(&req);
813 void CServerListRem::SaveServerMet()
815 // lfroen: stub, nothing to do
819 void CServerListRem::FilterServers()
821 // FIXME: add code
822 //wxFAIL;
826 void CServerListRem::RemoveServer(CServer* server)
828 m_conn->RemoveServer(server->GetIP(),server->GetPort());
832 void CServerListRem::UpdateUserFileStatus(CServer *server)
834 if (server) {
835 m_TotalUser = server->GetUsers();
836 m_TotalFile = server->GetFiles();
841 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
843 // It's ok to return 0 for context where this code is used in remote gui
844 return 0;
847 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
849 // It's ok to return 0 for context where this code is used in remote gui
850 return 0;
853 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
855 return new CServer(tag);
859 void CServerListRem::DeleteItem(CServer *in_srv)
861 CScopedPtr<CServer> srv(in_srv);
862 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
866 uint32 CServerListRem::GetItemID(CServer *server)
868 return server->GetIP();
872 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag *, CServer *)
874 // server list is always realoaded from scratch
875 wxFAIL;
879 void CServerListRem::ReloadControl()
881 for(iterator it = begin(); it != end(); it++) {
882 CServer *srv = *it;
883 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(srv);
888 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
890 m_conn = conn;
894 void CIPFilterRem::Reload()
896 CECPacket req(EC_OP_IPFILTER_RELOAD);
897 m_conn->SendPacket(&req);
901 void CIPFilterRem::Update(wxString url)
903 CECPacket req(EC_OP_IPFILTER_UPDATE);
904 req.AddTag(CECTag(EC_TAG_STRING, url));
906 m_conn->SendPacket(&req);
911 * Shared files list
913 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
915 m_conn = conn;
919 void CSharedFilesRem::Reload(bool, bool)
921 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
923 m_conn->SendPacket(&req);
927 void CSharedFilesRem::AddFilesFromDirectory(const CPath& path)
929 CECPacket req(EC_OP_SHAREDFILES_ADD_DIRECTORY);
931 req.AddTag(CECTag(EC_TAG_PREFS_DIRECTORIES, path.GetRaw()));
933 m_conn->SendPacket(&req);
937 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
939 // We use the printable name, as the filename originated from user input,
940 // and the filesystem name might not be valid on the remote host.
941 const wxString strNewName = newName.GetPrintable();
943 CECPacket request(EC_OP_RENAME_FILE);
944 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
945 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
947 m_conn->SendPacket(&request);
949 return true;
953 void CKnownFilesRem::DeleteItem(CKnownFile * file)
955 uint32 id = file->ECID();
956 if (theApp->sharedfiles->count(id)) {
957 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
958 theApp->sharedfiles->erase(id);
960 if (theApp->downloadqueue->count(id)) {
961 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile((CPartFile *) file);
962 theApp->downloadqueue->erase(id);
964 delete file;
968 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
970 return file->ECID();
974 void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
976 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
977 if (parttag) {
978 const uint8 *data = file->m_partStatus.Decode(
979 (uint8 *)parttag->GetTagData(),
980 parttag->GetTagDataLen());
981 for(int i = 0; i < file->GetPartCount(); ++i) {
982 file->m_AvailPartFrequency[i] = data[i];
985 tag->GetRequests(&file->statistic.requested);
986 tag->GetAllRequests(&file->statistic.alltimerequested);
987 tag->GetAccepts(&file->statistic.accepted);
988 tag->GetAllAccepts(&file->statistic.alltimeaccepted);
989 tag->GetXferred(&file->statistic.transferred);
990 tag->GetAllXferred(&file->statistic.alltimetransferred);
991 tag->UpPrio(&file->m_iUpPriorityEC);
992 if (file->m_iUpPriorityEC >= 10) {
993 file->m_iUpPriority = file->m_iUpPriorityEC - 10;
994 file->m_bAutoUpPriority = true;
995 } else {
996 file->m_iUpPriority = file->m_iUpPriorityEC;
997 file->m_bAutoUpPriority = false;
999 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1000 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1001 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1003 tag->GetOnQueue(&file->m_queuedCount);
1005 requested += file->statistic.requested;
1006 transferred += file->statistic.transferred;
1007 accepted += file->statistic.transferred;
1009 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1011 if (file->IsPartFile()) {
1012 ProcessItemUpdatePartfile((CEC_PartFile_Tag *) tag, (CPartFile *) file);
1016 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1018 CECPacket req(EC_OP_SHARED_SET_PRIO);
1020 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1021 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1023 req.AddTag(hashtag);
1025 m_conn->SendPacket(&req);
1028 void CKnownFilesRem::ProcessUpdate(const CECPacket *reply, CECPacket *, int)
1030 requested = 0;
1031 transferred = 0;
1032 accepted = 0;
1034 std::set<uint32> core_files;
1035 for (size_t i = 0;i < reply->GetTagCount();i++) {
1036 CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *)reply->GetTagByIndex(i);
1037 uint32 id = tag->ID();
1038 core_files.insert(id);
1039 if ( m_items_hash.count(id) ) {
1040 // Item already known: update it
1041 ProcessItemUpdate(tag, m_items_hash[id]);
1042 } else {
1043 CKnownFile * newFile;
1044 if (tag->GetTagName() == EC_TAG_PARTFILE) {
1045 CPartFile *file = new CPartFile((CEC_PartFile_Tag *) tag);
1046 ProcessItemUpdate(tag, file);
1047 (*theApp->downloadqueue)[id] = file;
1048 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1049 newFile = file;
1050 } else {
1051 newFile = new CKnownFile(tag);
1052 ProcessItemUpdate(tag, newFile);
1053 (*theApp->sharedfiles)[id] = newFile;
1054 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1056 AddItem(newFile);
1059 // remove items no longer present
1060 for(iterator it = begin(); it != end();) {
1061 iterator it2 = it++;
1062 if (!core_files.count(GetItemID(*it2))) {
1063 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views.
1068 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1070 requested = 0;
1071 transferred = 0;
1072 accepted = 0;
1077 * List of uploading and waiting clients.
1079 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn, int viewtype)
1081 CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag>(conn, true)
1083 m_viewtype = viewtype;
1087 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1089 m_bRemoteQueueFull = false;
1090 m_nUserIDHybrid = tag->UserID();
1091 m_Username = tag->ClientName();
1092 m_clientSoft = tag->ClientSoftware();
1093 m_clientVersionString = GetSoftName(m_clientSoft);
1094 m_clientSoftString = m_clientVersionString;
1095 m_bEmuleProtocol = false;
1097 // The functions to retrieve m_clientVerString information are
1098 // currently in BaseClient.cpp, which is not linked in remote-gui app.
1099 // So, in the meantime, we use a tag sent from core.
1100 m_clientVerString = tag->SoftVerStr();
1101 m_strModVersion = wxEmptyString;
1102 wxString clientModString;
1103 if (!clientModString.IsEmpty()) {
1104 m_clientVerString += wxT(" - ") + clientModString;
1106 m_fullClientVerString = m_clientSoftString + wxT(" ") + m_clientVerString;
1108 // User hash
1109 m_UserHash = tag->UserHash();
1111 // User IP:Port
1112 m_nConnectIP = m_dwUserIP = tag->UserIP();
1113 m_nUserPort = tag->UserPort();
1114 m_FullUserIP = m_nConnectIP;
1116 // Server IP:Port
1117 m_dwServerIP = tag->ServerIP();
1118 m_nServerPort = tag->ServerPort();
1119 m_ServerName = tag->ServerName();
1121 m_Friend = 0;
1122 if (tag->HaveFile()) {
1123 m_uploadingfile = theApp->knownfiles->GetByID(tag->FileID());
1124 } else {
1125 m_uploadingfile = NULL;
1128 m_nCurSessionUp = 0;
1130 credits = new CClientCredits(new CreditStruct());
1133 uint16 CUpQueueRem::GetWaitingPosition(const CUpDownClient *client) const
1135 return client->GetWaitingPosition();
1138 /* Warning: do common base */
1141 bool CUpDownClient::IsIdentified() const
1143 return m_identState == IS_IDENTIFIED;
1147 bool CUpDownClient::IsBadGuy() const
1149 return m_identState == IS_IDBADGUY;
1153 bool CUpDownClient::SUIFailed() const
1155 return m_identState == IS_IDFAILED;
1159 bool CUpDownClient::SUINeeded() const
1161 return m_identState == IS_IDNEEDED;
1165 bool CUpDownClient::SUINotSupported() const
1167 return m_identState == IS_NOTAVAILABLE;
1171 uint64 CUpDownClient::GetDownloadedTotal() const
1173 return credits->GetDownloadedTotal();
1177 uint64 CUpDownClient::GetUploadedTotal() const
1179 return credits->GetUploadedTotal();
1183 double CUpDownClient::GetScoreRatio() const
1185 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1188 /* End Warning */
1191 CUpDownClient::~CUpDownClient()
1193 delete credits;
1197 CUpDownClient *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1199 CUpDownClient *client = new CUpDownClient(tag);
1200 ProcessItemUpdate(tag, client);
1202 theApp->amuledlg->m_transferwnd->clientlistctrl->InsertClient(client, (ViewType)m_viewtype);
1204 return client;
1208 void CUpDownClientListRem::DeleteItem(CUpDownClient *client)
1210 theApp->amuledlg->m_transferwnd->clientlistctrl->
1211 RemoveClient(client, (ViewType)m_viewtype);
1212 delete client;
1216 uint32 CUpDownClientListRem::GetItemID(CUpDownClient *client)
1218 return client->ECID();
1222 void CUpDownClientListRem::ProcessItemUpdate(
1223 CEC_UpDownClient_Tag *tag,
1224 CUpDownClient *client)
1226 tag->UserID(&client->m_nUserIDHybrid);
1227 tag->GetCurrentIdentState(&client->m_identState);
1228 tag->HasObfuscatedConnection(&client->m_hasbeenobfuscatinglately);
1229 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1231 tag->WaitingPosition(&client->m_waitingPosition);
1232 tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1233 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1234 tag->AskedCount(&client->m_cAsked);
1236 tag->ClientDownloadState(&client->m_nDownloadState);
1237 tag->ClientUploadState(&client->m_nUploadState);
1239 tag->SpeedUp(&client->m_nUpDatarate);
1240 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1241 tag->SpeedDown(&client->kBpsDown);
1242 } else {
1243 client->kBpsDown = 0;
1246 tag->WaitTime(&client->m_WaitTime);
1247 tag->XferTime(&client->m_UpStartTimeDelay);
1248 tag->LastReqTime(&client->m_dwLastUpRequest);
1249 tag->QueueTime(&client->m_WaitStartTime);
1251 CreditStruct *credit_struct =
1252 (CreditStruct *)client->credits->GetDataStruct();
1253 tag->XferUp(&credit_struct->uploaded);
1254 tag->XferUpSession(&client->m_nTransferredUp);
1256 tag->XferDown(&credit_struct->downloaded);
1257 tag->XferDownSession(&client->m_nTransferredDown);
1259 tag->Score(&client->m_score);
1260 tag->Rating(&client->m_rating);
1262 theApp->amuledlg->m_transferwnd->clientlistctrl->UpdateClient(client,
1263 theApp->amuledlg->m_transferwnd->clientlistctrl->GetListView()); // Fixme, Listview shouldn't be required as parameter
1267 CUpQueueRem::CUpQueueRem(CRemoteConnect *conn)
1269 m_up_list(conn, vtUploading), m_wait_list(conn, vtQueued)
1275 * Download queue container: hold PartFiles with progress status
1280 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1282 CECPacket req(EC_OP_ADD_LINK);
1283 CECTag link_tag(EC_TAG_STRING, link);
1284 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1285 req.AddTag(link_tag);
1287 m_conn->SendPacket(&req);
1288 return true;
1292 void CDownQueueRem::ResetCatParts(int cat)
1294 // Called when category is deleted. Command will be performed on the remote side,
1295 // but files still should be updated here right away, or drawing errors (colour not available)
1296 // will happen.
1297 for (iterator it = begin(); it != end(); it++) {
1298 CPartFile* file = it->second;
1300 if ( file->GetCategory() == cat ) {
1301 // Reset the category
1302 file->SetCategory( 0 );
1303 } else if ( file->GetCategory() > cat ) {
1304 // Set to the new position of the original category
1305 file->SetCategory( file->GetCategory() - 1 );
1312 void CKnownFilesRem::ProcessItemUpdatePartfile(CEC_PartFile_Tag *tag, CPartFile *file)
1315 // update status
1317 tag->Speed(&file->m_kbpsDown);
1318 file->kBpsDown = file->m_kbpsDown / 1024.0;
1320 tag->SizeXfer(&file->transferred);
1321 tag->SizeDone(&file->completedsize);
1322 tag->SourceXferCount(&file->transferingsrc);
1323 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1324 tag->SourceCount(&file->m_source_count);
1325 tag->SourceCountA4AF(&file->m_a4af_source_count);
1326 tag->FileStatus(&file->status);
1327 tag->Stopped(&file->m_stopped);
1329 tag->LastSeenComplete(&file->lastseencomplete);
1330 tag->LastDateChanged(&file->m_lastDateChanged);
1331 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1332 tag->AvailablePartCount(&file->m_availablePartsCount);
1333 tag->Shared(&file->m_isShared);
1335 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1336 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1337 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1339 tag->FileCat(&file->m_category);
1341 tag->DownPrio(&file->m_iDownPriorityEC);
1342 if ( file->m_iDownPriorityEC >= 10 ) {
1343 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1344 file->m_bAutoDownPriority = true;
1345 } else {
1346 file->m_iDownPriority = file->m_iDownPriorityEC;
1347 file->m_bAutoDownPriority = false;
1350 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1353 // Copy part/gap status
1355 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1356 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1357 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1358 if (gaptag || parttag || reqtag) {
1359 PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1361 if (gaptag) {
1362 ArrayOfUInts64 gaps;
1363 encoder.DecodeGaps(gaptag, gaps);
1364 int gap_size = gaps.size() / 2;
1365 // clear gaplist
1366 file->m_gaplist.Init(file->GetFileSize(), false);
1368 // and refill it
1369 for (int j = 0; j < gap_size; j++) {
1370 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1373 if (parttag) {
1374 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1375 // sanity check
1376 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1378 if (reqtag) {
1379 ArrayOfUInts64 reqs;
1380 encoder.DecodeReqs(reqtag, reqs);
1381 int req_size = reqs.size() / 2;
1382 // clear reqlist
1383 DeleteContents(file->m_requestedblocks_list);
1385 // and refill it
1386 for (int j = 0; j < req_size; j++) {
1387 Requested_Block_Struct* block = new Requested_Block_Struct;
1388 block->StartOffset = reqs[2*j];
1389 block->EndOffset = reqs[2*j+1];
1390 file->m_requestedblocks_list.push_back(block);
1395 // Get source names and counts
1396 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1397 if (srcnametag) {
1398 SourcenameItemMap &map = file->GetSourcenameItemMap();
1399 size_t max = srcnametag->GetTagCount();
1400 for (size_t i = 0; i < max; i++) {
1401 CECTag *ntag = srcnametag->GetTagByIndex(i);
1402 uint32 key = ntag->GetInt();
1403 int count = ntag->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1404 if (count == 0) {
1405 map.erase(key);
1406 } else {
1407 SourcenameItem &item = map[key];
1408 item.count = count;
1409 CECTag *nametag = ntag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1410 if (nametag) {
1411 item.name = nametag->GetStringData();
1417 // Get comments
1418 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1419 if (commenttag) {
1420 file->ClearFileRatingList();
1421 int max = commenttag->GetTagCount();
1422 for (int i = 0; i < max - 3; ) {
1423 wxString u = commenttag->GetTagByIndex(i++)->GetStringData();
1424 wxString f = commenttag->GetTagByIndex(i++)->GetStringData();
1425 int r = commenttag->GetTagByIndex(i++)->GetInt();
1426 wxString c = commenttag->GetTagByIndex(i++)->GetStringData();
1427 file->AddFileRatingList(u, f, r, c);
1429 file->UpdateFileRatingCommentAvail();
1432 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1434 // If file is shared check if it is already listed in shared files.
1435 // If not, add it and show it.
1436 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1437 (*theApp->sharedfiles)[file->ECID()] = file;
1438 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1443 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1445 CECPacket req(cmd);
1446 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1448 m_conn->SendPacket(&req);
1452 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1454 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1456 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1457 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1458 req.AddTag(hashtag);
1460 m_conn->SendPacket(&req);
1464 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1466 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1468 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1470 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1471 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1472 req.AddTag(hashtag);
1474 m_conn->SendPacket(&req);
1478 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1480 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1481 file->SetCategory(cat);
1483 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1484 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1485 req.AddTag(hashtag);
1487 m_conn->SendPacket(&req);
1491 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1493 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1494 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1495 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1496 req.AddTag(hashtag);
1498 m_conn->SendPacket(&req);
1502 // This is an ugly hack and to be deleted when GUI is unlocked!
1503 // (replacing iterate-by-index with iteration)
1504 // It will only work for linear iteration starting with 0 (as used in CTransferWnd::UpdateCategory)
1505 CPartFile* CDownQueueRem::GetFileByIndex(unsigned int idx)
1507 static CDownQueueRem::iterator it;
1508 if (idx == 0) {
1509 it = begin();
1511 if (it == end()) {
1512 return NULL;
1514 return (it++)->second;
1518 CClientListRem::CClientListRem(CRemoteConnect *conn)
1520 m_conn = conn;
1524 void CClientListRem::FilterQueues()
1526 // FIXME: add code
1527 //wxFAIL;
1531 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag>(conn, true)
1533 m_curr_search = -1;
1537 wxString CSearchListRem::StartNewSearch(
1538 uint32* nSearchID, SearchType search_type,
1539 const CSearchList::CSearchParams& params)
1541 CECPacket search_req(EC_OP_SEARCH_START);
1542 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1543 switch(search_type) {
1544 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1545 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1546 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1548 search_req.AddTag(
1549 CEC_Search_Tag(params.searchString, ec_search_type,
1550 params.typeText, params.extension, params.availability,
1551 params.minSize, params.maxSize));
1553 m_conn->SendPacket(&search_req);
1554 m_curr_search = *(nSearchID); // No kad remote search yet.
1556 Flush();
1558 return wxEmptyString; // EC reply will have the error mesg is needed.
1562 void CSearchListRem::StopGlobalSearch()
1564 if (m_curr_search != -1) {
1565 CECPacket search_req(EC_OP_SEARCH_STOP);
1566 m_conn->SendPacket(&search_req);
1571 void CSearchListRem::StopKadSearch()
1573 // FIXME implementation needed
1577 void CSearchListRem::HandlePacket(const CECPacket *packet)
1579 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1580 CoreNotify_Search_Update_Progress(packet->GetTagByIndex(0)->GetInt());
1581 } else {
1582 CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag>::HandlePacket(packet);
1587 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1589 m_parent(NULL),
1590 m_showChildren(false),
1591 m_sourceCount(0),
1592 m_completeSourceCount(0),
1593 m_kademlia(false),
1594 m_downloadStatus(NEW),
1595 m_clientID(0),
1596 m_clientPort(0)
1598 SetFileName(CPath(tag->FileName()));
1599 m_abyFileHash = tag->ID();
1600 SetFileSize(tag->SizeFull());
1602 m_searchID = theApp->searchlist->m_curr_search;
1607 // dtor is virtual - must be implemented
1608 CSearchFile::~CSearchFile()
1613 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
1615 CSearchFile *file = new CSearchFile(tag);
1616 ProcessItemUpdate(tag, file);
1618 theApp->amuledlg->m_searchwnd->AddResult(file);
1620 return file;
1624 void CSearchListRem::DeleteItem(CSearchFile *file)
1626 delete file;
1630 CMD4Hash CSearchListRem::GetItemID(CSearchFile *file)
1632 return file->GetFileHash();
1636 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
1638 uint32 sourceCount = file->m_sourceCount;
1639 uint32 completeSourceCount = file->m_completeSourceCount;
1640 CSearchFile::DownloadStatus status = file->m_downloadStatus;
1641 tag->SourceCount(&file->m_sourceCount);
1642 tag->CompleteSourceCount(&file->m_completeSourceCount);
1643 tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
1645 if (file->m_sourceCount != sourceCount
1646 || file->m_completeSourceCount != completeSourceCount
1647 || file->m_downloadStatus != status) {
1648 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
1649 theApp->amuledlg->m_searchwnd->UpdateResult(file);
1655 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
1657 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
1658 m_conn->SendRequest(this, &progress_req);
1660 return true;
1664 void CSearchListRem::RemoveResults(long nSearchID)
1666 ResultMap::iterator it = m_results.find(nSearchID);
1667 if (it != m_results.end()) {
1668 CSearchResultList& list = it->second;
1669 for (unsigned int i = 0; i < list.size(); ++i) {
1670 delete list[i];
1672 m_results.erase(it);
1677 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
1679 ResultMap::const_iterator it = m_results.find(nSearchID);
1680 if (it != m_results.end()) {
1681 return it->second;
1684 // TODO: Should we assert in this case?
1685 static CSearchResultList list;
1686 return list;
1690 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
1692 theStats::UpdateStats(packet);
1693 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
1697 bool CUpDownClient::IsBanned() const
1699 // FIXME: add code
1700 return false;
1705 // Those functions have different implementation in remote gui
1707 void CUpDownClient::Ban()
1709 // FIXME: add code
1710 wxFAIL;
1714 void CUpDownClient::UnBan()
1716 // FIXME: add code
1717 wxFAIL;
1721 void CUpDownClient::RequestSharedFileList()
1723 // FIXME: add code
1724 wxFAIL;
1728 void CKnownFile::SetFileComment(const wxString &)
1730 // FIXME: add code
1731 wxMessageBox(_("Comments and ratings are not supported on remote gui yet"), _("Information"), wxOK | wxICON_INFORMATION);
1735 void CKnownFile::SetFileRating(unsigned char)
1737 // FIXME: add code
1741 // I don't think it will be implemented - too match data transfer. But who knows ?
1742 wxString CUpDownClient::ShowDownloadingParts() const
1744 return wxEmptyString;
1748 bool CUpDownClient::SwapToAnotherFile(
1749 bool WXUNUSED(bIgnoreNoNeeded),
1750 bool WXUNUSED(ignoreSuspensions),
1751 bool WXUNUSED(bRemoveCompletely),
1752 CPartFile* WXUNUSED(toFile))
1754 // FIXME: add code
1755 wxFAIL;
1756 return false;
1761 // Those functions are virtual. So even they don't get called they must
1762 // be defined so linker will be happy
1764 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1766 wxFAIL;
1767 return 0;
1771 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
1773 wxFAIL;
1774 return false;
1778 void CKnownFile::UpdatePartsInfo()
1780 wxFAIL;
1784 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1786 wxFAIL;
1787 return 0;
1791 void CPartFile::UpdatePartsInfo()
1793 wxFAIL;
1797 void CPartFile::UpdateFileRatingCommentAvail()
1799 bool prevComment = m_hasComment;
1800 int prevRating = m_iUserRating;
1802 m_hasComment = false;
1803 m_iUserRating = 0;
1804 int ratingCount = 0;
1806 FileRatingList::iterator it = m_FileRatingList.begin();
1807 for (; it != m_FileRatingList.end(); ++it) {
1808 SFileRating& cur_rat = *it;
1810 if (!cur_rat.Comment.IsEmpty()) {
1811 m_hasComment = true;
1814 uint8 rating = cur_rat.Rating;
1815 if (rating) {
1816 wxASSERT(rating <= 5);
1818 ratingCount++;
1819 m_iUserRating += rating;
1823 if (ratingCount) {
1824 m_iUserRating /= ratingCount;
1825 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
1828 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
1829 UpdateDisplayedInfo();
1833 bool CPartFile::SavePartFile(bool)
1835 wxFAIL;
1836 return false;
1839 CamuleRemoteGuiApp *theApp;
1842 // since gui is not linked with amule.cpp - define events here
1844 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
1845 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
1846 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
1847 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
1848 // File_checked_for_headers