Upstream tarball 9408
[amule.git] / src / amule-remote-gui.cpp
blobe086838c4a84e19aaf4e5eaa77ff1dc2e4380a06
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 #define AMULE_REMOTE_GUI_CPP
29 #include <memory> // Needed for auto_ptr
30 using std::auto_ptr;
33 #include <wx/ipc.h>
34 #include <wx/cmdline.h> // Needed for wxCmdLineParser
35 #include <wx/config.h> // Do_not_auto_remove (win32)
36 #include <wx/fileconf.h> // Needed for wxFileConfig
39 #include <common/Format.h>
40 #include <common/StringFunctions.h>
41 #include <common/MD5Sum.h>
44 #include <include/common/EventIDs.h>
47 #include "amule.h" // Interface declarations.
48 #include "amuleDlg.h" // Needed for CamuleDlg
49 #include "ClientCredits.h"
50 #include "ClientListCtrl.h"
51 #include "DataToText.h" // Needed for GetSoftName()
52 #include "DownloadListCtrl.h" // Needed for CDownloadListCtrl
53 #include "GuiEvents.h"
54 #ifdef ENABLE_IP2COUNTRY
55 #include "IP2Country.h" // Needed for IP2Country
56 #endif
57 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
58 #include "Logger.h"
59 #include "muuli_wdr.h" // Needed for IDs
60 #include "PartFile.h" // Needed for CPartFile
61 #include "SearchDlg.h" // Needed for CSearchDlg
62 #include "Server.h" // Needed for GetListName
63 #include "ServerWnd.h" // Needed for CServerWnd
64 #include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl
65 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
66 #include "TransferWnd.h" // Needed for CTransferWnd
67 #include "updownclient.h"
68 #include "ServerListCtrl.h" // Needed for CServerListCtrl
69 #include "MagnetURI.h" // Needed for CMagnetURI
72 CEConnectDlg::CEConnectDlg()
74 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
76 CoreConnect(this, true);
78 wxString pref_host, pref_port;
79 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
80 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
81 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
83 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
84 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
85 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
87 CentreOnParent();
91 wxString CEConnectDlg::PassHash()
93 return pwd_hash;
97 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
98 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
99 END_EVENT_TABLE()
102 void CEConnectDlg::OnOK(wxCommandEvent& evt)
104 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
105 port = StrToLong(s_port);
107 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
108 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
110 if (passwd != pwd_hash) {
111 pwd_hash = MD5Sum(passwd).GetHash();
113 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
114 evt.Skip();
118 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
121 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
122 // Core timer
123 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
125 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
126 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
128 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
130 #ifdef ENABLE_IP2COUNTRY
131 // HTTPDownload finished
132 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
133 #endif
134 END_EVENT_TABLE()
137 IMPLEMENT_APP(CamuleRemoteGuiApp)
140 int CamuleRemoteGuiApp::OnExit()
142 StopTickTimer();
144 return wxApp::OnExit();
148 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
150 static int request_step = 0;
152 if (m_connect->RequestFifoFull()) {
153 return;
156 switch (request_step) {
157 case 0:
158 serverconnect->ReQuery();
159 serverlist->UpdateUserFileStatus(serverconnect->GetCurrentServer());
160 request_step++;
161 break;
162 case 1: {
163 CECPacket stats_req(EC_OP_STAT_REQ);
164 m_connect->SendRequest(&m_stats_updater, &stats_req);
165 amuledlg->ShowTransferRate();
166 request_step++;
167 break;
169 case 2:
170 if (amuledlg->m_sharedfileswnd->IsShown()) {
171 sharedfiles->DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE);
172 } else if (amuledlg->m_serverwnd->IsShown()) {
173 //serverlist->FullReload(EC_OP_GET_SERVER_LIST);
174 } else if (amuledlg->m_transferwnd->IsShown()) {
175 static bool firstcall = true;
176 downloadqueue->DoRequery(
177 theApp->m_FileDetailDialogActive || firstcall ?
178 EC_OP_GET_DLOAD_QUEUE_DETAIL : EC_OP_GET_DLOAD_QUEUE,
179 EC_TAG_PARTFILE);
180 firstcall = false;
181 switch(amuledlg->m_transferwnd->clientlistctrl->GetListView()) {
182 case vtUploading:
183 uploadqueue->ReQueryUp();
184 break;
185 case vtQueued:
186 uploadqueue->ReQueryWait();
187 break;
188 case vtClients:
189 break;
190 case vtNone:
191 break;
193 amuledlg->m_transferwnd->ShowQueueCount(theStats::GetWaitingUserCount());
194 } else if (amuledlg->m_searchwnd->IsShown()) {
195 if (searchlist->m_curr_search != -1) {
196 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
199 // Back to the roots
200 request_step = 0;
201 break;
202 default:
203 AddLogLineCS(wxT("WTF?")); // should not happen. :-)
204 request_step = 0;
209 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
211 #ifdef ENABLE_IP2COUNTRY
212 if (event.GetInt() == HTTP_GeoIP) {
213 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
214 // If we updated, the dialog is already up. Redraw it to show the flags.
215 amuledlg->Refresh();
217 #endif
221 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
223 // Stop the Core Timer
224 delete poll_timer;
225 poll_timer = NULL;
227 // Destroy the EC socket
228 m_connect->Destroy();
229 m_connect = NULL;
232 if (amuledlg) {
233 amuledlg->DlgShutDown();
234 amuledlg->Destroy();
235 amuledlg = NULL;
240 bool CamuleRemoteGuiApp::OnInit()
242 StartTickTimer();
243 amuledlg = NULL;
244 if ( !wxApp::OnInit() ) {
245 return false;
248 // Get theApp
249 theApp = &wxGetApp();
251 // Handle uncaught exceptions
252 InstallMuleExceptionHandler();
254 // Create the polling timer
255 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
256 if (!poll_timer) {
257 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
258 OnExit();
261 m_connect = new CRemoteConnect(this);
262 SetAppName(wxT("aMule"));
264 // Load Preferences
265 // This creates the CFG file we shall use
266 ConfigDir = GetConfigDir();
267 if (!wxDirExists(ConfigDir)) {
268 wxMkdir(ConfigDir);
271 wxConfig::Set(new wxFileConfig(wxEmptyString, wxEmptyString,
272 ConfigDir + wxT("remote.conf")));
274 glob_prefs = new CPreferencesRem(m_connect);
276 InitCustomLanguages();
277 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
279 bool result = ShowConnectionDialog();
281 AddLogLineNS(_("Going to event loop..."));
283 return result;
287 bool CamuleRemoteGuiApp::CryptoAvailable() const
289 return clientcredits && clientcredits->CryptoAvailable();
293 bool CamuleRemoteGuiApp::ShowConnectionDialog() {
295 dialog = new CEConnectDlg;
297 if (dialog->ShowModal() != wxID_OK) {
298 dialog->Destroy();
300 return false;
302 AddLogLineNS(_("Connecting..."));
303 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
304 dialog->Login(), dialog->PassHash(),
305 wxT("amule-remote"), wxT("0x0001"))) {
306 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
308 return false;
311 return true;
315 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
316 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
317 AddLogLineNS(_("Remote GUI EC event handler"));
318 AddLogLineM(true,evt.GetServerReply());
319 if (evt.GetResult() == true) {
320 // Connected - go to next init step
321 glob_prefs->LoadRemote();
322 } else {
323 AddLogLineNS(_("Going down"));
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();
350 m_ConnState = 0;
351 m_clientID = 0;
353 serverconnect = new CServerConnectRem(m_connect);
354 m_statistics = new CStatistics(*m_connect);
356 clientlist = new CClientListRem(m_connect);
357 searchlist = new CSearchListRem(m_connect);
358 serverlist = new CServerListRem(m_connect);
360 sharedfiles = new CSharedFilesRem(m_connect);
361 knownfiles = new CKnownFilesRem(sharedfiles);
363 clientcredits = new CClientCreditsRem();
365 // bugfix - do this before creating the uploadqueue
366 downloadqueue = new CDownQueueRem(m_connect);
367 uploadqueue = new CUpQueueRem(m_connect);
368 ipfilter = new CIPFilterRem(m_connect);
370 // Parse cmdline arguments.
371 wxCmdLineParser cmdline(wxApp::argc, wxApp::argv);
372 cmdline.AddSwitch(wxT("v"), wxT("version"),
373 wxT("Displays the current version number."));
374 cmdline.AddSwitch(wxT("h"), wxT("help"),
375 wxT("Displays this information."));
376 cmdline.AddOption(wxT("geometry"), wxEmptyString, wxT("Sets the geometry of the app.\n\t\t\t<str> uses the same format as standard X11 apps:\n\t\t\t[=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]"));
377 cmdline.Parse();
379 bool geometry_enabled = false;
380 wxString geom_string;
381 if (cmdline.Found(wxT("geometry"), &geom_string)) {
382 geometry_enabled = true;
385 // Create main dialog
386 InitGui(0, geom_string);
388 // Forward wxLog events to CLogger
389 wxLog::SetActiveTarget(new CLoggerTarget);
390 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
391 sharedfiles->DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE);
393 // Start the Poll Timer
394 poll_timer->Start(1000);
395 amuledlg->StartGuiTimer();
397 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
398 #ifdef ENABLE_IP2COUNTRY
399 if (thePrefs::IsGeoIPEnabled()) {
400 amuledlg->m_IP2Country->Enable();
402 #endif
406 void CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
408 CamuleGuiBase::ShowAlert(msg, title, flags);
412 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
414 amuledlg->AddLogLine(line);
417 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
419 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
420 SetTopWindow(amuledlg);
421 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
422 return 0;
426 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
428 return CamuleGuiBase::CopyTextToClipboard(strText);
432 uint32 CamuleRemoteGuiApp::GetPublicIP()
434 return 0;
438 wxString CamuleRemoteGuiApp::GetLog(bool)
440 return wxEmptyString;
444 wxString CamuleRemoteGuiApp::GetServerLog(bool)
446 return wxEmptyString;
450 wxString CamuleRemoteGuiApp::CreateMagnetLink(const CAbstractFile* f)
452 // TODO: Remove duplicate code (also in amule.cpp) ...
453 CMagnetURI uri;
455 uri.AddField(wxT("dn"), f->GetFileName().Cleanup(false).GetPrintable());
456 uri.AddField(wxT("xt"), wxString(wxT("urn:ed2k:")) + f->GetFileHash().Encode().Lower());
457 uri.AddField(wxT("xt"), wxString(wxT("urn:ed2khash:")) + f->GetFileHash().Encode().Lower());
458 uri.AddField(wxT("xl"), wxString::Format(wxT("%") wxLongLongFmtSpec wxT("u"), f->GetFileSize()));
460 return uri.GetLink();
463 wxString CamuleRemoteGuiApp::CreateED2kLink(const CAbstractFile* f, bool add_source, bool use_hostname, bool addcryptoptions)
465 // TODO: Avoid duplicate code (also in amule.cpp) ...
466 wxASSERT(!(!add_source && (use_hostname || addcryptoptions)));
467 // Construct URL like this: ed2k://|file|<filename>|<size>|<hash>|/
468 wxString strURL = CFormat(wxT("ed2k://|file|%s|%i|%s|/"))
469 % f->GetFileName().Cleanup(false)
470 % f->GetFileSize() % f->GetFileHash().Encode();
472 if (add_source && IsConnected() && !IsFirewalled()) {
473 // Create the first part of the URL
474 strURL << wxT("|sources,");
476 if (use_hostname) {
477 strURL << thePrefs::GetYourHostname();
478 } else {
479 uint32 clientID = GetID();
480 strURL << (uint8) clientID << wxT(".") <<
481 (uint8)(clientID >> 8) << wxT(".") <<
482 (uint8)(clientID >> 16) << wxT(".") <<
483 (uint8)(clientID >> 24);
486 strURL << wxT(":") <<
487 thePrefs::GetPort();
489 if (addcryptoptions) {
490 const uint8 uSupportsCryptLayer = thePrefs::IsClientCryptLayerSupported() ? 1 : 0;
491 const uint8 uRequestsCryptLayer = thePrefs::IsClientCryptLayerRequested() ? 1 : 0;
492 const uint8 uRequiresCryptLayer = thePrefs::IsClientCryptLayerRequired() ? 1 : 0;
493 const uint8 byCryptOptions = (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0) | (uSupportsCryptLayer ? 0x80 : 0x00);
495 strURL << wxT(":") << byCryptOptions;
497 if (byCryptOptions & 0x80) {
498 strURL << wxT(":") << thePrefs::GetUserHash().Encode();
502 strURL << wxT("|/");
503 } else if (add_source) {
504 AddLogLineM(true, _("WARNING: You can't add yourself as a source for an eD2k link while having a lowid."));
507 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|sources,[(<ip>|<hostname>):<port>[:cryptoptions[:hash]]]|/"
508 return strURL;
512 wxString CamuleRemoteGuiApp::CreateED2kAICHLink(const CKnownFile* f)
514 // TODO: Avoid duplicate code (also in amule.cpp) ...
515 // Create the first part of the URL
516 wxString strURL = CreateED2kLink(f);
517 // Append the AICH info
518 if (f->HasProperAICHHashSet()) {
519 strURL << wxT("|h=") << f->GetAICHMasterHash() << wxT("|/");
522 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|h=<AICH master hash>|/"
523 return strURL;
527 bool CamuleRemoteGuiApp::AddServer(CServer *, bool)
529 // #warning TODO: Add remote command
530 return true;
534 bool CamuleRemoteGuiApp::IsFirewalled() const
536 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
537 return false;
540 return IsFirewalledKad();
544 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
545 return serverconnect && serverconnect->IsConnected();
549 void CamuleRemoteGuiApp::StartKad() {
550 m_connect->StartKad();
554 void CamuleRemoteGuiApp::StopKad() {
555 m_connect->StopKad();
559 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
561 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
562 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
563 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
565 m_connect->SendPacket(&req);
569 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
571 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
572 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
574 m_connect->SendPacket(&req);
578 void CamuleRemoteGuiApp::DisconnectED2K() {
579 if (IsConnectedED2K()) {
580 m_connect->DisconnectED2K();
585 uint32 CamuleRemoteGuiApp::GetED2KID() const
587 return serverconnect ? serverconnect->GetClientID() : 0;
591 uint32 CamuleRemoteGuiApp::GetID() const
593 return m_clientID;
597 void CamuleRemoteGuiApp::ShowUserCount() {
598 wxString buffer =
599 CFormat(_("Users: E: %s K: %s | Files E: %s K: %s")) % CastItoIShort(theStats::GetED2KUsers()) %
600 CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
602 Notify_ShowUserCount(buffer);
607 * Preferences: holds both local and remote settings.
609 * First, everything is loaded from local config file. Later, settings
610 * that are relevant on remote side only are loaded thru EC
612 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
614 m_conn = conn;
616 CPreferences::BuildItemList(theApp->ConfigDir);
617 CPreferences::LoadAllItems(wxConfigBase::Get());
620 // Settings queried from remote side
622 m_exchange_send_selected_prefs =
623 EC_PREFS_GENERAL |
624 EC_PREFS_CONNECTIONS |
625 EC_PREFS_MESSAGEFILTER |
626 EC_PREFS_ONLINESIG |
627 EC_PREFS_SERVERS |
628 EC_PREFS_FILES |
629 EC_PREFS_SRCDROP |
630 EC_PREFS_SECURITY |
631 EC_PREFS_CORETWEAKS |
632 EC_PREFS_REMOTECONTROLS |
633 EC_PREFS_KADEMLIA;
634 m_exchange_recv_selected_prefs =
635 m_exchange_send_selected_prefs |
636 EC_PREFS_CATEGORIES;
640 void CPreferencesRem::HandlePacket(const CECPacket *packet)
642 ((CEC_Prefs_Packet *)packet)->Apply();
644 if ( packet->GetTagByName(EC_TAG_PREFS_CATEGORIES) != 0 ) {
645 for (size_t i = 0; i < packet->GetTagByName(EC_TAG_PREFS_CATEGORIES)->GetTagCount(); i++) {
646 const CECTag *cat_tag = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES)->GetTagByIndex(i);
647 Category_Struct *cat = new Category_Struct;
648 cat->title = cat_tag->GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
649 cat->path = CPath(cat_tag->GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
650 cat->comment = cat_tag->GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
651 cat->color = cat_tag->GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
652 cat->prio = cat_tag->GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
653 theApp->glob_prefs->AddCat(cat);
655 } else {
656 Category_Struct *cat = new Category_Struct;
657 cat->title = _("All");
658 cat->color = 0;
659 cat->prio = PR_NORMAL;
660 theApp->glob_prefs->AddCat(cat);
662 wxECInitDoneEvent event;
663 theApp->AddPendingEvent(event);
668 bool CPreferencesRem::LoadRemote()
671 // override local settings with remote
672 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
674 // bring categories too
675 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
677 m_conn->SendRequest(this, &req);
679 return true;
683 void CPreferencesRem::SendToRemote()
685 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
686 m_conn->SendPacket(&pref_packet);
690 Category_Struct *CPreferencesRem::CreateCategory(
691 const wxString& name,
692 const CPath& path,
693 const wxString& comment,
694 uint32 color,
695 uint8 prio)
697 CECPacket req(EC_OP_CREATE_CATEGORY);
698 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
699 req.AddTag(tag);
700 m_conn->SendPacket(&req);
702 Category_Struct *category = new Category_Struct();
703 category->path = path;
704 category->title = name;
705 category->comment = comment;
706 category->color = color;
707 category->prio = prio;
709 AddCat(category);
711 return category;
715 void CPreferencesRem::UpdateCategory(
716 uint8 cat,
717 const wxString& name,
718 const CPath& path,
719 const wxString& comment,
720 uint32 color,
721 uint8 prio)
723 CECPacket req(EC_OP_UPDATE_CATEGORY);
724 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
725 req.AddTag(tag);
726 m_conn->SendPacket(&req);
728 Category_Struct *category = m_CatList[cat];
729 category->path = path;
730 category->title = name;
731 category->comment = comment;
732 category->color = color;
733 category->prio = prio;
737 void CPreferencesRem::RemoveCat(uint8 cat)
739 CECPacket req(EC_OP_DELETE_CATEGORY);
740 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
741 req.AddTag(tag);
742 m_conn->SendPacket(&req);
743 CPreferences::RemoveCat(cat);
748 // Container implementation
750 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
752 m_CurrServer = 0;
753 m_Conn = conn;
757 void CServerConnectRem::ConnectToAnyServer()
759 CECPacket req(EC_OP_SERVER_CONNECT);
760 m_Conn->SendPacket(&req);
764 void CServerConnectRem::StopConnectionTry()
766 // lfroen: isn't Disconnect the same ?
770 void CServerConnectRem::Disconnect()
772 CECPacket req(EC_OP_SERVER_DISCONNECT);
773 m_Conn->SendPacket(&req);
777 void CServerConnectRem::ConnectToServer(CServer *server)
779 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
783 bool CServerConnectRem::ReQuery()
785 CECPacket stat_req(EC_OP_GET_CONNSTATE);
786 m_Conn->SendRequest(this, &stat_req);
788 return true;
792 void CServerConnectRem::HandlePacket(const CECPacket *packet)
794 CEC_ConnState_Tag *tag =
795 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
796 if (!tag) {
797 return;
800 theApp->m_ConnState = 0;
801 CServer *server;
802 m_ID = tag->GetEd2kId();
803 theApp->m_clientID = tag->GetClientId();
805 if (tag->IsConnectedED2K()) {
806 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
807 if (!srvtag) {
808 return;
810 server = theApp->serverlist->GetByID(srvtag->GetIPv4Data().IP());
811 if (m_CurrServer && (server != m_CurrServer)) {
812 theApp->amuledlg->m_serverwnd->serverlistctrl->
813 HighlightServer(m_CurrServer, false);
815 theApp->amuledlg->m_serverwnd->serverlistctrl->
816 HighlightServer(server, true);
817 m_CurrServer = server;
818 theApp->m_ConnState |= CONNECTED_ED2K;
819 } else {
820 if ( m_CurrServer ) {
821 theApp->amuledlg->m_serverwnd->serverlistctrl->
822 HighlightServer(m_CurrServer, false);
823 m_CurrServer = 0;
827 if (tag->IsConnectedKademlia()) {
828 if (tag->IsKadFirewalled()) {
829 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
830 } else {
831 theApp->m_ConnState |= CONNECTED_KAD_OK;
833 } else {
834 if (tag->IsKadRunning()) {
835 theApp->m_ConnState |= CONNECTED_KAD_NOT;
839 theApp->amuledlg->ShowConnectionState();
844 * Server list: host list of ed2k servers.
846 CServerListRem::CServerListRem(CRemoteConnect *conn)
848 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn)
853 void CServerListRem::HandlePacket(const CECPacket *packet)
855 CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
856 ReloadControl();
860 void CServerListRem::UpdateServerMetFromURL(wxString url)
862 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
863 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
865 m_conn->SendPacket(&req);
869 void CServerListRem::SaveServerMet()
871 // lfroen: stub, nothing to do
875 void CServerListRem::FilterServers()
877 // FIXME: add code
878 //wxASSERT(0);
882 void CServerListRem::RemoveServer(CServer* server)
884 m_conn->RemoveServer(server->GetIP(),server->GetPort());
888 void CServerListRem::UpdateUserFileStatus(CServer *server)
890 if (server) {
891 m_TotalUser = server->GetUsers();
892 m_TotalFile = server->GetFiles();
894 wxString buffer =
895 CFormat(_("Total Users: %s | Total Files: %s")) % CastItoIShort(m_TotalUser) % CastItoIShort(m_TotalFile);
897 Notify_ShowUserCount(buffer);
902 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
904 // It's ok to return 0 for context where this code is used in remote gui
905 return 0;
908 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
910 // It's ok to return 0 for context where this code is used in remote gui
911 return 0;
914 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
916 return new CServer(tag);
920 void CServerListRem::DeleteItem(CServer *in_srv)
922 auto_ptr<CServer> srv(in_srv);
923 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
927 uint32 CServerListRem::GetItemID(CServer *server)
929 return server->GetIP();
933 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag *, CServer *)
935 // server list is always realoaded from scratch
936 wxASSERT(0);
940 void CServerListRem::ReloadControl()
942 for(uint32 i = 0;i < GetCount(); i++) {
943 CServer *srv = GetByIndex(i);
944 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(srv);
949 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
951 m_conn = conn;
955 void CIPFilterRem::Reload()
957 CECPacket req(EC_OP_IPFILTER_RELOAD);
958 m_conn->SendPacket(&req);
962 void CIPFilterRem::Update(wxString WXUNUSED(url))
964 // FIXME: add command
965 //wxASSERT(0);
970 * Shared files list
972 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn) : CRemoteContainer<CKnownFile, CMD4Hash, CEC_SharedFile_Tag>(conn, true)
974 m_rename_file = NULL;
978 void CSharedFilesRem::Reload(bool, bool)
980 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
982 m_conn->SendPacket(&req);
986 void CSharedFilesRem::AddFilesFromDirectory(const CPath& path)
988 CECPacket req(EC_OP_SHAREDFILES_ADD_DIRECTORY);
990 req.AddTag(CECTag(EC_TAG_PREFS_DIRECTORIES, path.GetRaw()));
992 m_conn->SendPacket(&req);
996 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
998 // We use the printable name, as the filename originated from user input,
999 // and the filesystem name might not be valid on the remote host.
1000 const wxString strNewName = newName.GetPrintable();
1002 CECPacket request(EC_OP_RENAME_FILE);
1003 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
1004 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
1006 m_conn->SendRequest(this, &request);
1007 m_rename_file = file;
1008 m_new_name = strNewName;
1010 return true;
1014 void CSharedFilesRem::HandlePacket(const CECPacket *packet)
1016 if (m_rename_file && (packet->GetOpCode() == EC_OP_NOOP)) {
1017 m_rename_file->SetFileName(CPath(m_new_name));
1018 m_rename_file = NULL;
1019 } else if (packet->GetOpCode() != EC_OP_FAILED) {
1020 CRemoteContainer<CKnownFile, CMD4Hash, CEC_SharedFile_Tag>::HandlePacket(packet);
1025 CKnownFile *CSharedFilesRem::CreateItem(CEC_SharedFile_Tag *tag)
1027 CKnownFile *file = new CKnownFile(tag);
1029 m_enc_map[file->GetFileHash()] = RLE_Data(file->GetPartCount(), true);
1031 ProcessItemUpdate(tag, file);
1033 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1035 return file;
1039 void CSharedFilesRem::DeleteItem(CKnownFile *in_file)
1041 auto_ptr<CKnownFile> file(in_file);
1043 m_enc_map.erase(file->GetFileHash());
1045 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file.get());
1049 CMD4Hash CSharedFilesRem::GetItemID(CKnownFile *file)
1051 return file->GetFileHash();
1055 void CSharedFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
1057 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1058 const unsigned char *data =
1059 m_enc_map[file->GetFileHash()].Decode(
1060 (unsigned char *)parttag->GetTagData(),
1061 parttag->GetTagDataLen());
1062 for(int i = 0; i < file->GetPartCount(); ++i) {
1063 file->m_AvailPartFrequency[i] = data[i];
1065 if (m_inc_tags) {
1066 tag->SetRequests(file->statistic.requested);
1067 tag->SetAllRequests(file->statistic.alltimerequested);
1068 tag->SetAccepts(file->statistic.accepted);
1069 tag->SetAllAccepts(file->statistic.alltimeaccepted);
1070 tag->SetXferred(file->statistic.transferred );
1071 tag->SetAllXferred(file->statistic.alltimetransferred);
1072 tag->SetPrio(file->m_iUpPriority);
1073 } else {
1074 file->statistic.requested = tag->GetRequests();
1075 file->statistic.alltimerequested = tag->GetAllRequests();
1076 file->statistic.accepted = tag->GetAccepts();
1077 file->statistic.alltimeaccepted = tag->GetAllAccepts();
1078 file->statistic.transferred = tag->GetXferred();
1079 file->statistic.alltimetransferred = tag->GetAllXferred();
1080 file->m_iUpPriority = tag->Prio();
1082 if (file->m_iUpPriority >= 10) {
1083 file->m_iUpPriority -= 10;
1084 file->m_bAutoUpPriority = true;
1085 } else {
1086 file->m_bAutoUpPriority = false;
1089 theApp->knownfiles->requested += file->statistic.requested;
1090 theApp->knownfiles->transferred += file->statistic.transferred;
1091 theApp->knownfiles->accepted += file->statistic.transferred;
1093 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1096 bool CSharedFilesRem::Phase1Done(const CECPacket *)
1098 theApp->knownfiles->requested = 0;
1099 theApp->knownfiles->transferred = 0;
1100 theApp->knownfiles->accepted = 0;
1102 return true;
1105 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1107 CECPacket req(EC_OP_SHARED_SET_PRIO);
1109 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1110 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1112 req.AddTag(hashtag);
1114 m_conn->SendPacket(&req);
1118 * List of uploading and waiting clients.
1120 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn, int viewtype)
1122 CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag>(conn)
1124 m_viewtype = viewtype;
1128 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag)
1130 m_bRemoteQueueFull = false;
1131 m_nUserIDHybrid = tag->ID();
1132 m_Username = tag->ClientName();
1133 m_score = tag->Score();
1134 m_clientSoft = tag->ClientSoftware();
1135 m_clientVersionString = GetSoftName(m_clientSoft);
1136 m_clientSoftString = m_clientVersionString;
1138 // The functions to retrieve m_clientVerString information are
1139 // currently in BaseClient.cpp, which is not linked in remote-gui app.
1140 // So, in the meantime, we use a tag sent from core.
1141 m_clientVerString = tag->SoftVerStr();
1142 m_strModVersion = wxEmptyString;
1143 wxString clientModString;
1144 if (!clientModString.IsEmpty()) {
1145 m_clientVerString += wxT(" - ") + clientModString;
1147 m_fullClientVerString = m_clientSoftString + wxT(" ") + m_clientVerString;
1149 // User hash
1150 m_UserHash = tag->UserID();
1152 // User IP:Port
1153 m_nConnectIP = m_dwUserIP = tag->UserIP();
1154 m_nUserPort = tag->UserPort();
1155 m_FullUserIP = m_nConnectIP;
1157 // Server IP:Port
1158 m_dwServerIP = tag->ServerIP();
1159 m_nServerPort = tag->ServerPort();
1160 m_ServerName = tag->ServerName();
1162 m_waitingPosition = tag->WaitingPosition();
1164 m_Friend = 0;
1165 if (tag->HaveFile()) {
1166 CMD4Hash filehash = tag->FileID();
1167 m_uploadingfile = theApp->sharedfiles->GetByID(filehash);
1168 if (!m_uploadingfile) {
1169 m_uploadingfile = theApp->downloadqueue->GetByID(filehash);
1171 } else {
1172 m_uploadingfile = NULL;
1175 m_nCurSessionUp = 0;
1177 credits = new CClientCredits(new CreditStruct());
1180 uint16 CUpQueueRem::GetWaitingPosition(const CUpDownClient *client) const
1182 return client->GetWaitingPosition();
1185 /* Warning: do common base */
1188 bool CUpDownClient::IsIdentified() const
1190 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDENTIFIED);
1194 bool CUpDownClient::IsBadGuy() const
1196 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDBADGUY);
1200 bool CUpDownClient::SUIFailed() const
1202 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDFAILED);
1206 bool CUpDownClient::SUINeeded() const
1208 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDNEEDED);
1212 bool CUpDownClient::SUINotSupported() const
1214 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_NOTAVAILABLE);
1218 uint64 CUpDownClient::GetDownloadedTotal() const
1220 return credits ? credits->GetDownloadedTotal() : 0;
1224 uint64 CUpDownClient::GetUploadedTotal() const
1226 return credits ? credits->GetUploadedTotal() : 0;
1230 double CUpDownClient::GetScoreRatio() const
1232 return credits ? credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable()) : 0;
1235 /* End Warning */
1238 CUpDownClient::~CUpDownClient()
1240 if (credits) {
1241 delete credits;
1246 CUpDownClient *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1248 CUpDownClient *client = new CUpDownClient(tag);
1249 ProcessItemUpdate(tag, client);
1251 theApp->amuledlg->m_transferwnd->clientlistctrl->InsertClient(client, (ViewType)m_viewtype);
1253 return client;
1257 void CUpDownClientListRem::DeleteItem(CUpDownClient *client)
1259 theApp->amuledlg->m_transferwnd->clientlistctrl->
1260 RemoveClient(client, (ViewType)m_viewtype);
1261 delete client;
1265 uint32 CUpDownClientListRem::GetItemID(CUpDownClient *client)
1267 return client->GetUserIDHybrid();
1271 void CUpDownClientListRem::ProcessItemUpdate(
1272 CEC_UpDownClient_Tag *tag,
1273 CUpDownClient *client)
1275 uint16 state = tag->ClientState();
1277 client->m_nDownloadState = state & 0xff;
1278 client->m_nUploadState = (state >> 8) & 0xff;
1280 client->m_nUpDatarate = tag->SpeedUp();
1281 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1282 client->kBpsDown = tag->SpeedDown() / 1024.0;
1283 } else {
1284 client->kBpsDown = 0;
1287 client->m_WaitTime = tag->WaitTime();
1288 client->m_UpStartTimeDelay = tag->XferTime();
1289 client->m_dwLastUpRequest = tag->LastReqTime();
1290 client->m_WaitStartTime = tag->QueueTime();
1292 CreditStruct *credit_struct =
1293 (CreditStruct *)client->credits->GetDataStruct();
1294 credit_struct->uploaded = tag->XferUp();
1295 client->m_nTransferredUp = tag->XferUpSession();
1297 credit_struct->downloaded = tag->XferDown();
1301 CUpQueueRem::CUpQueueRem(CRemoteConnect *conn)
1303 m_up_list(conn, vtUploading), m_wait_list(conn, vtQueued)
1309 * Download queue container: hold PartFiles with progress status
1314 CDownQueueRem::CDownQueueRem(CRemoteConnect *conn)
1316 CRemoteContainer<CPartFile, CMD4Hash, CEC_PartFile_Tag>(conn, true)
1321 bool CDownQueueRem::AddLink(const wxString &link, int)
1323 CECPacket req(EC_OP_ADD_LINK);
1324 req.AddTag(CECTag(EC_TAG_STRING, link));
1326 m_conn->SendPacket(&req);
1327 return true;
1331 void CDownQueueRem::StopUDPRequests()
1333 // have no idea what is it about
1337 void CDownQueueRem::ResetCatParts(int)
1339 // called when category being deleted. Command will be performed on remote side
1343 bool CDownQueueRem::IsPartFile(const CKnownFile *) const
1345 // hope i understand it right
1346 return true;
1350 void CDownQueueRem::OnConnectionState(bool)
1355 CPartFile *CDownQueueRem::CreateItem(CEC_PartFile_Tag *tag)
1357 CPartFile *file = new CPartFile(tag);
1358 m_enc_map[file->GetFileHash()] = PartFileEncoderData(file->GetPartCount(), 10);
1359 ProcessItemUpdate(tag, file);
1361 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1362 return file;
1366 void CDownQueueRem::DeleteItem(CPartFile *in_file)
1368 auto_ptr<CPartFile> file(in_file);
1370 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile(file.get());
1372 m_enc_map.erase(file->GetFileHash());
1376 CMD4Hash CDownQueueRem::GetItemID(CPartFile *file)
1378 return file->GetFileHash();
1382 void CDownQueueRem::ProcessItemUpdate(CEC_PartFile_Tag *tag, CPartFile *file)
1385 // update status
1387 if (m_inc_tags) {
1388 uint32 tmpval = (uint32)(file->kBpsDown * 1024);
1389 tag->SetSpeed(tmpval);
1390 file->kBpsDown = tmpval / 1024.0;
1392 tag->SetSizeXfer(file->transferred);
1393 tag->SetSizeDone(file->completedsize);
1394 tag->SetSourceXferCount(file->transferingsrc);
1395 tag->SetSourceNotCurrCount(file->m_notCurrentSources);
1396 tag->SetSourceCount(file->m_source_count);
1397 tag->SetSourceCountA4AF(file->m_a4af_source_count);
1398 tag->SetFileStatus(file->status);
1400 tag->SetLastSeenComplete(file->lastseencomplete);
1402 tag->SetFileCat(file->m_category);
1404 tag->SetPrio(file->m_iDownPriority);
1405 } else {
1406 file->kBpsDown = tag->Speed() / 1024.0;
1408 if ( file->kBpsDown > 0 ) {
1409 file->transferred = tag->SizeXfer();
1410 file->SetCompletedSize(tag->SizeDone());
1413 file->transferingsrc = tag->SourceXferCount();
1414 file->m_notCurrentSources = tag->SourceNotCurrCount();
1415 file->m_source_count = tag->SourceCount();
1416 file->m_a4af_source_count = tag->SourceCountA4AF();
1417 file->status = tag->FileStatus();
1419 file->lastseencomplete = tag->LastSeenComplete();
1421 file->m_category = tag->FileCat();
1423 file->m_iDownPriority = tag->Prio();
1424 if ( file->m_iDownPriority >= 10 ) {
1425 file->m_iDownPriority-= 10;
1426 file->m_bAutoDownPriority = true;
1427 } else {
1428 file->m_bAutoDownPriority = false;
1431 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1432 if ( file->m_iDownPriority >= 10 ) {
1433 file->m_iDownPriority -= 10;
1434 file->m_bAutoUpPriority = true;
1435 } else {
1436 file->m_bAutoUpPriority = false;
1440 // Copy part/gap status
1442 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1443 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1444 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1445 if (gaptag && parttag && reqtag) {
1446 wxASSERT(m_enc_map.count(file->GetFileHash()));
1448 PartFileEncoderData &encoder = m_enc_map[file->GetFileHash()];
1449 encoder.Decode(
1450 (unsigned char *)gaptag->GetTagData(), gaptag->GetTagDataLen(),
1451 (unsigned char *)parttag->GetTagData(), parttag->GetTagDataLen());
1453 const uint64 *reqparts = (const uint64 *)reqtag->GetTagData();
1454 unsigned reqcount = reqtag->GetTagDataLen() / (2 * sizeof(uint64));
1456 unsigned gap_size = encoder.m_gap_status.Size() / (2 * sizeof(uint64));
1457 // clear gaplist
1458 file->m_gaplist.Init(file->GetFileSize(), false);
1460 // and refill it
1461 const uint64 *gap_info = (const uint64 *)encoder.m_gap_status.Buffer();
1462 for (unsigned j = 0; j < gap_size;j++) {
1463 file->m_gaplist.AddGap(ENDIAN_NTOHLL(gap_info[2*j]), ENDIAN_NTOHLL(gap_info[2*j+1]));
1466 // adjust size of requested block list
1467 while ( file->m_requestedblocks_list.size() > reqcount ) {
1468 delete file->m_requestedblocks_list.front();
1469 file->m_requestedblocks_list.pop_front();
1471 while ( file->m_requestedblocks_list.size() != reqcount ) {
1472 file->m_requestedblocks_list.push_front(new Requested_Block_Struct);
1475 std::list<Requested_Block_Struct*>::iterator it2 = file->m_requestedblocks_list.begin();
1476 for (unsigned i = 0; i < reqcount; ++i) {
1477 Requested_Block_Struct* block = *it2++;
1478 block->StartOffset = ENDIAN_NTOHLL(reqparts[2*i]);
1479 block->EndOffset = ENDIAN_NTOHLL(reqparts[2*i+1]);
1481 // copy parts frequency
1482 const unsigned char *part_info = encoder.m_part_status.Buffer();
1483 for(int i = 0; i < file->GetPartCount(); ++i) {
1484 file->m_SrcpartFrequency[i] = part_info[i];
1486 } else {
1487 AddLogLineNS(CFormat(wxT("ERROR: %X %X %X")) % (size_t)gaptag % (size_t)parttag % (size_t)reqtag);
1490 // Get source names
1491 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1492 if (srcnametag) {
1493 file->ClearSourcenameItemList();
1494 int max = srcnametag->GetTagCount();
1495 for (int i = 0; i < max - 1; ) {
1496 wxString name = srcnametag->GetTagByIndex(i++)->GetStringData();
1497 long count = srcnametag->GetTagByIndex(i++)->GetInt();
1498 file->AddSourcenameItemList(name, count);
1502 // Get comments
1503 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1504 if (commenttag) {
1505 file->ClearFileRatingList();
1506 int max = commenttag->GetTagCount();
1507 for (int i = 0; i < max - 3; ) {
1508 wxString u = commenttag->GetTagByIndex(i++)->GetStringData();
1509 wxString f = commenttag->GetTagByIndex(i++)->GetStringData();
1510 int r = commenttag->GetTagByIndex(i++)->GetInt();
1511 wxString c = commenttag->GetTagByIndex(i++)->GetStringData();
1512 file->AddFileRatingList(u, f, r, c);
1514 file->UpdateFileRatingCommentAvail();
1517 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1521 bool CDownQueueRem::Phase1Done(const CECPacket *)
1523 return true;
1527 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1529 CECPacket req(cmd);
1530 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1532 m_conn->SendPacket(&req);
1536 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1538 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1540 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1541 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1542 req.AddTag(hashtag);
1544 m_conn->SendPacket(&req);
1548 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1550 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1552 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1554 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1555 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1556 req.AddTag(hashtag);
1558 m_conn->SendPacket(&req);
1562 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1564 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1565 file->m_category = cat;
1567 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1568 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1569 req.AddTag(hashtag);
1571 m_conn->SendPacket(&req);
1575 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1577 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1578 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1579 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1580 req.AddTag(hashtag);
1582 m_conn->SendPacket(&req);
1586 CClientListRem::CClientListRem(CRemoteConnect *conn)
1588 m_conn = conn;
1592 void CClientListRem::FilterQueues()
1594 // FIXME: add code
1595 //wxASSERT(0);
1599 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag>(conn)
1601 m_curr_search = -1;
1605 wxString CSearchListRem::StartNewSearch(
1606 uint32* nSearchID, SearchType search_type,
1607 const CSearchList::CSearchParams& params)
1609 CECPacket search_req(EC_OP_SEARCH_START);
1610 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1611 switch(search_type) {
1612 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1613 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1614 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1616 search_req.AddTag(
1617 CEC_Search_Tag(params.searchString, ec_search_type,
1618 params.typeText, params.extension, params.availability,
1619 params.minSize, params.maxSize));
1621 m_conn->SendPacket(&search_req);
1622 m_curr_search = *(nSearchID); // No kad remote search yet.
1624 Flush();
1626 return wxEmptyString; // EC reply will have the error mesg is needed.
1630 void CSearchListRem::StopGlobalSearch()
1632 if (m_curr_search != -1) {
1633 CECPacket search_req(EC_OP_SEARCH_STOP);
1634 m_conn->SendPacket(&search_req);
1639 void CSearchListRem::HandlePacket(const CECPacket *packet)
1641 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1642 CoreNotify_Search_Update_Progress(packet->GetTagByIndex(0)->GetInt());
1643 } else {
1644 CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag>::HandlePacket(packet);
1649 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1651 m_parent(NULL),
1652 m_showChildren(false),
1653 m_sourceCount(0),
1654 m_completeSourceCount(0),
1655 m_kademlia(false),
1656 m_clientID(0),
1657 m_clientPort(0)
1659 SetFileName(CPath(tag->FileName()));
1660 m_abyFileHash = tag->ID();
1661 SetFileSize(tag->SizeFull());
1663 m_searchID = theApp->searchlist->m_curr_search;
1668 // dtor is virtual - must be implemented
1669 CSearchFile::~CSearchFile()
1674 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
1676 CSearchFile *file = new CSearchFile(tag);
1677 ProcessItemUpdate(tag, file);
1679 theApp->amuledlg->m_searchwnd->AddResult(file);
1681 return file;
1685 void CSearchListRem::DeleteItem(CSearchFile *file)
1687 delete file;
1691 CMD4Hash CSearchListRem::GetItemID(CSearchFile *file)
1693 return file->GetFileHash();
1697 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
1699 file->m_sourceCount = tag->SourceCount();
1700 file->m_completeSourceCount = tag->CompleteSourceCount();
1704 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
1706 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
1707 m_conn->SendRequest(this, &progress_req);
1709 return true;
1713 void CSearchListRem::RemoveResults(long nSearchID)
1715 ResultMap::iterator it = m_results.find(nSearchID);
1716 if (it != m_results.end()) {
1717 CSearchResultList& list = it->second;
1718 for (unsigned int i = 0; i < list.size(); ++i) {
1719 delete list[i];
1721 m_results.erase(it);
1726 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
1728 ResultMap::const_iterator it = m_results.find(nSearchID);
1729 if (it != m_results.end()) {
1730 return it->second;
1733 // TODO: Should we assert in this case?
1734 static CSearchResultList list;
1735 return list;
1739 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
1741 theStats::UpdateStats(packet);
1742 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
1746 bool CUpDownClient::IsBanned() const
1748 // FIXME: add code
1749 return false;
1754 // Those functions have different implementation in remote gui
1756 void CUpDownClient::Ban()
1758 // FIXME: add code
1759 wxASSERT(0);
1763 void CUpDownClient::UnBan()
1765 // FIXME: add code
1766 wxASSERT(0);
1770 void CUpDownClient::RequestSharedFileList()
1772 // FIXME: add code
1773 wxASSERT(0);
1777 void CKnownFile::SetFileComment(const wxString &)
1779 // FIXME: add code
1780 wxASSERT(0);
1784 void CKnownFile::SetFileRating(unsigned char)
1786 // FIXME: add code
1787 wxASSERT(0);
1791 // I don't think it will be implemented - too match data transfer. But who knows ?
1792 wxString CUpDownClient::ShowDownloadingParts() const
1794 return wxEmptyString;
1798 bool CUpDownClient::SwapToAnotherFile(
1799 bool WXUNUSED(bIgnoreNoNeeded),
1800 bool WXUNUSED(ignoreSuspensions),
1801 bool WXUNUSED(bRemoveCompletely),
1802 CPartFile* WXUNUSED(toFile))
1804 // FIXME: add code
1805 wxASSERT(0);
1806 return false;
1811 // Those functions are virtual. So even they don't get called they must
1812 // be defined so linker will be happy
1814 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1816 wxASSERT(0);
1817 return 0;
1821 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
1823 wxASSERT(0);
1824 return false;
1828 void CKnownFile::UpdatePartsInfo()
1830 wxASSERT(0);
1834 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1836 wxASSERT(0);
1837 return 0;
1841 void CPartFile::UpdatePartsInfo()
1843 wxASSERT(0);
1847 void CPartFile::UpdateFileRatingCommentAvail()
1849 bool prevComment = m_hasComment;
1850 int prevRating = m_iUserRating;
1852 m_hasComment = false;
1853 m_iUserRating = 0;
1854 int ratingCount = 0;
1856 FileRatingList::iterator it = m_FileRatingList.begin();
1857 for (; it != m_FileRatingList.end(); ++it) {
1858 SFileRating& cur_rat = *it;
1860 if (!cur_rat.Comment.IsEmpty()) {
1861 m_hasComment = true;
1864 uint8 rating = cur_rat.Rating;
1865 if (rating) {
1866 wxASSERT(rating <= 5);
1868 ratingCount++;
1869 m_iUserRating += rating;
1873 if (ratingCount) {
1874 m_iUserRating /= ratingCount;
1875 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
1878 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
1879 UpdateDisplayedInfo();
1883 bool CPartFile::SavePartFile(bool)
1885 wxASSERT(0);
1886 return false;
1891 // since gui is not linked with amule.cpp - define events here
1893 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
1894 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
1895 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
1896 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
1897 // File_checked_for_headers