Upstream tarball 9707
[amule.git] / src / amule-remote-gui.cpp
blobbc33d95294c8db961251c28f934ba226ea6cb284
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 <wx/ipc.h>
30 #include <wx/cmdline.h> // Needed for wxCmdLineParser
31 #include <wx/config.h> // Do_not_auto_remove (win32)
32 #include <wx/fileconf.h> // Needed for wxFileConfig
35 #include <common/Format.h>
36 #include <common/StringFunctions.h>
37 #include <common/MD5Sum.h>
40 #include <include/common/EventIDs.h>
43 #include "amule.h" // Interface declarations.
44 #include "amuleDlg.h" // Needed for CamuleDlg
45 #include "ClientCredits.h"
46 #include "ClientListCtrl.h"
47 #include "DataToText.h" // Needed for GetSoftName()
48 #include "DownloadListCtrl.h" // Needed for CDownloadListCtrl
49 #include "GuiEvents.h"
50 #ifdef ENABLE_IP2COUNTRY
51 #include "IP2Country.h" // Needed for IP2Country
52 #endif
53 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
54 #include "Logger.h"
55 #include "muuli_wdr.h" // Needed for IDs
56 #include "PartFile.h" // Needed for CPartFile
57 #include "SearchDlg.h" // Needed for CSearchDlg
58 #include "Server.h" // Needed for GetListName
59 #include "ServerWnd.h" // Needed for CServerWnd
60 #include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl
61 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
62 #include "TransferWnd.h" // Needed for CTransferWnd
63 #include "updownclient.h"
64 #include "ServerListCtrl.h" // Needed for CServerListCtrl
65 #include "MagnetURI.h" // Needed for CMagnetURI
66 #include "ScopedPtr.h"
69 CEConnectDlg::CEConnectDlg()
71 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
73 CoreConnect(this, true);
75 wxString pref_host, pref_port;
76 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
77 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
78 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
80 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
81 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
82 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
84 CentreOnParent();
88 wxString CEConnectDlg::PassHash()
90 return pwd_hash;
94 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
95 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
96 END_EVENT_TABLE()
99 void CEConnectDlg::OnOK(wxCommandEvent& evt)
101 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
102 port = StrToLong(s_port);
104 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
105 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
107 if (passwd != pwd_hash) {
108 pwd_hash = MD5Sum(passwd).GetHash();
110 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
111 evt.Skip();
115 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
118 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
119 // Core timer
120 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
122 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
123 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
125 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
127 #ifdef ENABLE_IP2COUNTRY
128 // HTTPDownload finished
129 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
130 #endif
131 END_EVENT_TABLE()
134 IMPLEMENT_APP(CamuleRemoteGuiApp)
137 int CamuleRemoteGuiApp::OnExit()
139 StopTickTimer();
141 return wxApp::OnExit();
145 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
147 static int request_step = 0;
149 if (m_connect->RequestFifoFull()) {
150 return;
153 switch (request_step) {
154 case 0:
155 serverconnect->ReQuery();
156 serverlist->UpdateUserFileStatus(serverconnect->GetCurrentServer());
157 request_step++;
158 break;
159 case 1: {
160 CECPacket stats_req(EC_OP_STAT_REQ);
161 m_connect->SendRequest(&m_stats_updater, &stats_req);
162 amuledlg->ShowTransferRate();
163 request_step++;
164 break;
166 case 2:
167 if (amuledlg->m_sharedfileswnd->IsShown()) {
168 sharedfiles->DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE);
169 } else if (amuledlg->m_serverwnd->IsShown()) {
170 //serverlist->FullReload(EC_OP_GET_SERVER_LIST);
171 } else if (amuledlg->m_transferwnd->IsShown()) {
172 downloadqueue->DoRequery(EC_OP_GET_DLOAD_QUEUE, EC_TAG_PARTFILE);
173 switch(amuledlg->m_transferwnd->clientlistctrl->GetListView()) {
174 case vtUploading:
175 uploadqueue->ReQueryUp();
176 break;
177 case vtQueued:
178 uploadqueue->ReQueryWait();
179 break;
180 case vtClients:
181 break;
182 case vtNone:
183 break;
185 amuledlg->m_transferwnd->ShowQueueCount(theStats::GetWaitingUserCount());
186 } else if (amuledlg->m_searchwnd->IsShown()) {
187 if (searchlist->m_curr_search != -1) {
188 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
191 // Back to the roots
192 request_step = 0;
193 break;
194 default:
195 AddLogLineCS(wxT("WTF?")); // should not happen. :-)
196 request_step = 0;
201 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
203 #ifdef ENABLE_IP2COUNTRY
204 if (event.GetInt() == HTTP_GeoIP) {
205 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
206 // If we updated, the dialog is already up. Redraw it to show the flags.
207 amuledlg->Refresh();
209 #endif
213 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
215 // Stop the Core Timer
216 delete poll_timer;
217 poll_timer = NULL;
219 // Destroy the EC socket
220 m_connect->Destroy();
221 m_connect = NULL;
224 if (amuledlg) {
225 amuledlg->DlgShutDown();
226 amuledlg->Destroy();
227 amuledlg = NULL;
232 bool CamuleRemoteGuiApp::OnInit()
234 StartTickTimer();
235 amuledlg = NULL;
236 if ( !wxApp::OnInit() ) {
237 return false;
240 // Get theApp
241 theApp = &wxGetApp();
243 // Handle uncaught exceptions
244 InstallMuleExceptionHandler();
246 // Create the polling timer
247 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
248 if (!poll_timer) {
249 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
250 OnExit();
253 m_connect = new CRemoteConnect(this);
254 SetAppName(wxT("aMule"));
256 // Load Preferences
257 // This creates the CFG file we shall use
258 ConfigDir = GetConfigDir();
259 if (!wxDirExists(ConfigDir)) {
260 wxMkdir(ConfigDir);
263 wxConfig::Set(new wxFileConfig(wxEmptyString, wxEmptyString,
264 ConfigDir + wxT("remote.conf")));
266 glob_prefs = new CPreferencesRem(m_connect);
268 InitCustomLanguages();
269 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
271 bool result = ShowConnectionDialog();
273 AddLogLineNS(_("Going to event loop..."));
275 return result;
279 bool CamuleRemoteGuiApp::CryptoAvailable() const
281 return thePrefs::IsSecureIdentEnabled(); // good enough
285 bool CamuleRemoteGuiApp::ShowConnectionDialog() {
287 dialog = new CEConnectDlg;
289 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(sharedfiles);
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 // Parse cmdline arguments.
370 wxCmdLineParser cmdline(wxApp::argc, wxApp::argv);
371 cmdline.AddSwitch(wxT("v"), wxT("version"),
372 wxT("Displays the current version number."));
373 cmdline.AddSwitch(wxT("h"), wxT("help"),
374 wxT("Displays this information."));
375 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>]"));
376 cmdline.Parse();
378 bool geometry_enabled = false;
379 wxString geom_string;
380 if (cmdline.Found(wxT("geometry"), &geom_string)) {
381 geometry_enabled = true;
384 // Create main dialog
385 InitGui(0, geom_string);
387 // Forward wxLog events to CLogger
388 wxLog::SetActiveTarget(new CLoggerTarget);
389 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
390 sharedfiles->DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE);
392 // Start the Poll Timer
393 poll_timer->Start(1000);
394 amuledlg->StartGuiTimer();
396 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
397 #ifdef ENABLE_IP2COUNTRY
398 if (thePrefs::IsGeoIPEnabled()) {
399 amuledlg->m_IP2Country->Enable();
401 #endif
405 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
407 return CamuleGuiBase::ShowAlert(msg, title, flags);
411 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
413 amuledlg->AddLogLine(line);
416 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
418 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
419 SetTopWindow(amuledlg);
420 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
421 return 0;
425 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
427 return CamuleGuiBase::CopyTextToClipboard(strText);
431 uint32 CamuleRemoteGuiApp::GetPublicIP()
433 return 0;
437 wxString CamuleRemoteGuiApp::GetLog(bool)
439 return wxEmptyString;
443 wxString CamuleRemoteGuiApp::GetServerLog(bool)
445 return wxEmptyString;
449 wxString CamuleRemoteGuiApp::CreateMagnetLink(const CAbstractFile* f)
451 // TODO: Remove duplicate code (also in amule.cpp) ...
452 CMagnetURI uri;
454 uri.AddField(wxT("dn"), f->GetFileName().Cleanup(false).GetPrintable());
455 uri.AddField(wxT("xt"), wxString(wxT("urn:ed2k:")) + f->GetFileHash().Encode().Lower());
456 uri.AddField(wxT("xt"), wxString(wxT("urn:ed2khash:")) + f->GetFileHash().Encode().Lower());
457 uri.AddField(wxT("xl"), wxString::Format(wxT("%") wxLongLongFmtSpec wxT("u"), f->GetFileSize()));
459 return uri.GetLink();
462 wxString CamuleRemoteGuiApp::CreateED2kLink(const CAbstractFile* f, bool add_source, bool use_hostname, bool addcryptoptions)
464 // TODO: Avoid duplicate code (also in amule.cpp) ...
465 wxASSERT(!(!add_source && (use_hostname || addcryptoptions)));
466 // Construct URL like this: ed2k://|file|<filename>|<size>|<hash>|/
467 wxString strURL = CFormat(wxT("ed2k://|file|%s|%i|%s|/"))
468 % f->GetFileName().Cleanup(false)
469 % f->GetFileSize() % f->GetFileHash().Encode();
471 if (add_source && IsConnected() && !IsFirewalled()) {
472 // Create the first part of the URL
473 strURL << wxT("|sources,");
475 if (use_hostname) {
476 strURL << thePrefs::GetYourHostname();
477 } else {
478 uint32 clientID = GetID();
479 strURL << (uint8) clientID << wxT(".") <<
480 (uint8)(clientID >> 8) << wxT(".") <<
481 (uint8)(clientID >> 16) << wxT(".") <<
482 (uint8)(clientID >> 24);
485 strURL << wxT(":") <<
486 thePrefs::GetPort();
488 if (addcryptoptions) {
489 const uint8 uSupportsCryptLayer = thePrefs::IsClientCryptLayerSupported() ? 1 : 0;
490 const uint8 uRequestsCryptLayer = thePrefs::IsClientCryptLayerRequested() ? 1 : 0;
491 const uint8 uRequiresCryptLayer = thePrefs::IsClientCryptLayerRequired() ? 1 : 0;
492 const uint8 byCryptOptions = (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0) | (uSupportsCryptLayer ? 0x80 : 0x00);
494 strURL << wxT(":") << byCryptOptions;
496 if (byCryptOptions & 0x80) {
497 strURL << wxT(":") << thePrefs::GetUserHash().Encode();
501 strURL << wxT("|/");
502 } else if (add_source) {
503 AddLogLineM(true, _("WARNING: You can't add yourself as a source for an eD2k link while having a lowid."));
506 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|sources,[(<ip>|<hostname>):<port>[:cryptoptions[:hash]]]|/"
507 return strURL;
511 wxString CamuleRemoteGuiApp::CreateED2kAICHLink(const CKnownFile* f)
513 // TODO: Avoid duplicate code (also in amule.cpp) ...
514 // Create the first part of the URL
515 wxString strURL = CreateED2kLink(f);
516 // Append the AICH info
517 if (f->HasProperAICHHashSet()) {
518 strURL.RemoveLast(); // remove trailing '/'
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;
600 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
601 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
603 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
604 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
605 } else if (thePrefs::GetNetworkED2K()) {
606 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
607 } else if (thePrefs::GetNetworkKademlia()) {
608 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
609 } else {
610 buffer = _("No networks selected");
613 Notify_ShowUserCount(buffer);
618 * Preferences: holds both local and remote settings.
620 * First, everything is loaded from local config file. Later, settings
621 * that are relevant on remote side only are loaded thru EC
623 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
625 m_conn = conn;
627 CPreferences::BuildItemList(theApp->ConfigDir);
628 CPreferences::LoadAllItems(wxConfigBase::Get());
631 // Settings queried from remote side
633 m_exchange_send_selected_prefs =
634 EC_PREFS_GENERAL |
635 EC_PREFS_CONNECTIONS |
636 EC_PREFS_MESSAGEFILTER |
637 EC_PREFS_ONLINESIG |
638 EC_PREFS_SERVERS |
639 EC_PREFS_FILES |
640 EC_PREFS_SRCDROP |
641 EC_PREFS_SECURITY |
642 EC_PREFS_CORETWEAKS |
643 EC_PREFS_REMOTECONTROLS |
644 EC_PREFS_KADEMLIA;
645 m_exchange_recv_selected_prefs =
646 m_exchange_send_selected_prefs |
647 EC_PREFS_CATEGORIES;
651 void CPreferencesRem::HandlePacket(const CECPacket *packet)
653 ((CEC_Prefs_Packet *)packet)->Apply();
655 if ( packet->GetTagByName(EC_TAG_PREFS_CATEGORIES) != 0 ) {
656 for (size_t i = 0; i < packet->GetTagByName(EC_TAG_PREFS_CATEGORIES)->GetTagCount(); i++) {
657 const CECTag *cat_tag = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES)->GetTagByIndex(i);
658 Category_Struct *cat = new Category_Struct;
659 cat->title = cat_tag->GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
660 cat->path = CPath(cat_tag->GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
661 cat->comment = cat_tag->GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
662 cat->color = cat_tag->GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
663 cat->prio = cat_tag->GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
664 theApp->glob_prefs->AddCat(cat);
666 } else {
667 Category_Struct *cat = new Category_Struct;
668 cat->title = _("All");
669 cat->color = 0;
670 cat->prio = PR_NORMAL;
671 theApp->glob_prefs->AddCat(cat);
673 wxECInitDoneEvent event;
674 theApp->AddPendingEvent(event);
679 bool CPreferencesRem::LoadRemote()
682 // override local settings with remote
683 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
685 // bring categories too
686 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
688 m_conn->SendRequest(this, &req);
690 return true;
694 void CPreferencesRem::SendToRemote()
696 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
697 m_conn->SendPacket(&pref_packet);
701 Category_Struct *CPreferencesRem::CreateCategory(
702 const wxString& name,
703 const CPath& path,
704 const wxString& comment,
705 uint32 color,
706 uint8 prio)
708 CECPacket req(EC_OP_CREATE_CATEGORY);
709 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
710 req.AddTag(tag);
711 m_conn->SendPacket(&req);
713 Category_Struct *category = new Category_Struct();
714 category->path = path;
715 category->title = name;
716 category->comment = comment;
717 category->color = color;
718 category->prio = prio;
720 AddCat(category);
722 return category;
726 void CPreferencesRem::UpdateCategory(
727 uint8 cat,
728 const wxString& name,
729 const CPath& path,
730 const wxString& comment,
731 uint32 color,
732 uint8 prio)
734 CECPacket req(EC_OP_UPDATE_CATEGORY);
735 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
736 req.AddTag(tag);
737 m_conn->SendPacket(&req);
739 Category_Struct *category = m_CatList[cat];
740 category->path = path;
741 category->title = name;
742 category->comment = comment;
743 category->color = color;
744 category->prio = prio;
748 void CPreferencesRem::RemoveCat(uint8 cat)
750 CECPacket req(EC_OP_DELETE_CATEGORY);
751 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
752 req.AddTag(tag);
753 m_conn->SendPacket(&req);
754 CPreferences::RemoveCat(cat);
759 // Container implementation
761 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
763 m_CurrServer = 0;
764 m_Conn = conn;
768 void CServerConnectRem::ConnectToAnyServer()
770 CECPacket req(EC_OP_SERVER_CONNECT);
771 m_Conn->SendPacket(&req);
775 void CServerConnectRem::StopConnectionTry()
777 // lfroen: isn't Disconnect the same ?
781 void CServerConnectRem::Disconnect()
783 CECPacket req(EC_OP_SERVER_DISCONNECT);
784 m_Conn->SendPacket(&req);
788 void CServerConnectRem::ConnectToServer(CServer *server)
790 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
794 bool CServerConnectRem::ReQuery()
796 CECPacket stat_req(EC_OP_GET_CONNSTATE);
797 m_Conn->SendRequest(this, &stat_req);
799 return true;
803 void CServerConnectRem::HandlePacket(const CECPacket *packet)
805 CEC_ConnState_Tag *tag =
806 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
807 if (!tag) {
808 return;
811 theApp->m_ConnState = 0;
812 CServer *server;
813 m_ID = tag->GetEd2kId();
814 theApp->m_clientID = tag->GetClientId();
816 if (tag->IsConnectedED2K()) {
817 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
818 if (!srvtag) {
819 return;
821 server = theApp->serverlist->GetByID(srvtag->GetIPv4Data().IP());
822 if (m_CurrServer && (server != m_CurrServer)) {
823 theApp->amuledlg->m_serverwnd->serverlistctrl->
824 HighlightServer(m_CurrServer, false);
826 theApp->amuledlg->m_serverwnd->serverlistctrl->
827 HighlightServer(server, true);
828 m_CurrServer = server;
829 theApp->m_ConnState |= CONNECTED_ED2K;
830 } else {
831 if ( m_CurrServer ) {
832 theApp->amuledlg->m_serverwnd->serverlistctrl->
833 HighlightServer(m_CurrServer, false);
834 m_CurrServer = 0;
838 if (tag->IsConnectedKademlia()) {
839 if (tag->IsKadFirewalled()) {
840 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
841 } else {
842 theApp->m_ConnState |= CONNECTED_KAD_OK;
844 } else {
845 if (tag->IsKadRunning()) {
846 theApp->m_ConnState |= CONNECTED_KAD_NOT;
850 theApp->amuledlg->ShowConnectionState();
855 * Server list: host list of ed2k servers.
857 CServerListRem::CServerListRem(CRemoteConnect *conn)
859 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn)
864 void CServerListRem::HandlePacket(const CECPacket *packet)
866 CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
867 ReloadControl();
871 void CServerListRem::UpdateServerMetFromURL(wxString url)
873 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
874 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
876 m_conn->SendPacket(&req);
880 void CServerListRem::SaveServerMet()
882 // lfroen: stub, nothing to do
886 void CServerListRem::FilterServers()
888 // FIXME: add code
889 //wxFAIL;
893 void CServerListRem::RemoveServer(CServer* server)
895 m_conn->RemoveServer(server->GetIP(),server->GetPort());
899 void CServerListRem::UpdateUserFileStatus(CServer *server)
901 if (server) {
902 m_TotalUser = server->GetUsers();
903 m_TotalFile = server->GetFiles();
905 wxString buffer =
906 CFormat(_("Total Users: %s | Total Files: %s")) % CastItoIShort(m_TotalUser) % CastItoIShort(m_TotalFile);
908 Notify_ShowUserCount(buffer);
913 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
915 // It's ok to return 0 for context where this code is used in remote gui
916 return 0;
919 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
921 // It's ok to return 0 for context where this code is used in remote gui
922 return 0;
925 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
927 return new CServer(tag);
931 void CServerListRem::DeleteItem(CServer *in_srv)
933 CScopedPtr<CServer> srv(in_srv);
934 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
938 uint32 CServerListRem::GetItemID(CServer *server)
940 return server->GetIP();
944 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag *, CServer *)
946 // server list is always realoaded from scratch
947 wxFAIL;
951 void CServerListRem::ReloadControl()
953 for(uint32 i = 0;i < GetCount(); i++) {
954 CServer *srv = GetByIndex(i);
955 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(srv);
960 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
962 m_conn = conn;
966 void CIPFilterRem::Reload()
968 CECPacket req(EC_OP_IPFILTER_RELOAD);
969 m_conn->SendPacket(&req);
973 void CIPFilterRem::Update(wxString WXUNUSED(url))
975 // FIXME: add command
976 //wxFAIL;
981 * Shared files list
983 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn) : CRemoteContainer<CKnownFile, CMD4Hash, CEC_SharedFile_Tag>(conn, true)
985 m_rename_file = NULL;
989 void CSharedFilesRem::Reload(bool, bool)
991 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
993 m_conn->SendPacket(&req);
997 void CSharedFilesRem::AddFilesFromDirectory(const CPath& path)
999 CECPacket req(EC_OP_SHAREDFILES_ADD_DIRECTORY);
1001 req.AddTag(CECTag(EC_TAG_PREFS_DIRECTORIES, path.GetRaw()));
1003 m_conn->SendPacket(&req);
1007 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
1009 // We use the printable name, as the filename originated from user input,
1010 // and the filesystem name might not be valid on the remote host.
1011 const wxString strNewName = newName.GetPrintable();
1013 CECPacket request(EC_OP_RENAME_FILE);
1014 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
1015 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
1017 m_conn->SendRequest(this, &request);
1018 m_rename_file = file;
1019 m_new_name = strNewName;
1021 return true;
1025 void CSharedFilesRem::HandlePacket(const CECPacket *packet)
1027 if (m_rename_file && (packet->GetOpCode() == EC_OP_NOOP)) {
1028 m_rename_file->SetFileName(CPath(m_new_name));
1029 m_rename_file = NULL;
1030 } else if (packet->GetOpCode() != EC_OP_FAILED) {
1031 CRemoteContainer<CKnownFile, CMD4Hash, CEC_SharedFile_Tag>::HandlePacket(packet);
1036 CKnownFile *CSharedFilesRem::CreateItem(CEC_SharedFile_Tag *tag)
1038 CKnownFile *file = new CKnownFile(tag);
1040 m_enc_map[file->GetFileHash()] = RLE_Data(file->GetPartCount(), true);
1042 ProcessItemUpdate(tag, file);
1044 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1046 return file;
1050 void CSharedFilesRem::DeleteItem(CKnownFile *in_file)
1052 CScopedPtr<CKnownFile> file(in_file);
1054 m_enc_map.erase(file->GetFileHash());
1056 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file.get());
1060 CMD4Hash CSharedFilesRem::GetItemID(CKnownFile *file)
1062 return file->GetFileHash();
1066 void CSharedFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
1068 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1069 const unsigned char *data =
1070 m_enc_map[file->GetFileHash()].Decode(
1071 (unsigned char *)parttag->GetTagData(),
1072 parttag->GetTagDataLen());
1073 for(int i = 0; i < file->GetPartCount(); ++i) {
1074 file->m_AvailPartFrequency[i] = data[i];
1076 if (m_inc_tags) {
1077 tag->SetRequests(file->statistic.requested);
1078 tag->SetAllRequests(file->statistic.alltimerequested);
1079 tag->SetAccepts(file->statistic.accepted);
1080 tag->SetAllAccepts(file->statistic.alltimeaccepted);
1081 tag->SetXferred(file->statistic.transferred );
1082 tag->SetAllXferred(file->statistic.alltimetransferred);
1083 tag->SetPrio(file->m_iUpPriority);
1084 } else {
1085 file->statistic.requested = tag->GetRequests();
1086 file->statistic.alltimerequested = tag->GetAllRequests();
1087 file->statistic.accepted = tag->GetAccepts();
1088 file->statistic.alltimeaccepted = tag->GetAllAccepts();
1089 file->statistic.transferred = tag->GetXferred();
1090 file->statistic.alltimetransferred = tag->GetAllXferred();
1091 file->m_iUpPriority = tag->Prio();
1093 if (file->m_iUpPriority >= 10) {
1094 file->m_iUpPriority -= 10;
1095 file->m_bAutoUpPriority = true;
1096 } else {
1097 file->m_bAutoUpPriority = false;
1100 theApp->knownfiles->requested += file->statistic.requested;
1101 theApp->knownfiles->transferred += file->statistic.transferred;
1102 theApp->knownfiles->accepted += file->statistic.transferred;
1104 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1107 bool CSharedFilesRem::Phase1Done(const CECPacket *)
1109 theApp->knownfiles->requested = 0;
1110 theApp->knownfiles->transferred = 0;
1111 theApp->knownfiles->accepted = 0;
1113 return true;
1116 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1118 CECPacket req(EC_OP_SHARED_SET_PRIO);
1120 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1121 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1123 req.AddTag(hashtag);
1125 m_conn->SendPacket(&req);
1129 * List of uploading and waiting clients.
1131 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn, int viewtype)
1133 CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag>(conn)
1135 m_viewtype = viewtype;
1139 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag)
1141 m_bRemoteQueueFull = false;
1142 m_nUserIDHybrid = tag->ID();
1143 m_Username = tag->ClientName();
1144 m_score = tag->Score();
1145 m_clientSoft = tag->ClientSoftware();
1146 m_clientVersionString = GetSoftName(m_clientSoft);
1147 m_clientSoftString = m_clientVersionString;
1148 m_identState = tag->GetCurrentIdentState();
1149 m_hasbeenobfuscatinglately = tag->HasObfuscatedConnection();
1151 // The functions to retrieve m_clientVerString information are
1152 // currently in BaseClient.cpp, which is not linked in remote-gui app.
1153 // So, in the meantime, we use a tag sent from core.
1154 m_clientVerString = tag->SoftVerStr();
1155 m_strModVersion = wxEmptyString;
1156 wxString clientModString;
1157 if (!clientModString.IsEmpty()) {
1158 m_clientVerString += wxT(" - ") + clientModString;
1160 m_fullClientVerString = m_clientSoftString + wxT(" ") + m_clientVerString;
1162 // User hash
1163 m_UserHash = tag->UserID();
1165 // User IP:Port
1166 m_nConnectIP = m_dwUserIP = tag->UserIP();
1167 m_nUserPort = tag->UserPort();
1168 m_FullUserIP = m_nConnectIP;
1170 // Server IP:Port
1171 m_dwServerIP = tag->ServerIP();
1172 m_nServerPort = tag->ServerPort();
1173 m_ServerName = tag->ServerName();
1175 m_waitingPosition = tag->WaitingPosition();
1177 m_Friend = 0;
1178 if (tag->HaveFile()) {
1179 CMD4Hash filehash = tag->FileID();
1180 m_uploadingfile = theApp->sharedfiles->GetByID(filehash);
1181 if (!m_uploadingfile) {
1182 m_uploadingfile = theApp->downloadqueue->GetByID(filehash);
1184 } else {
1185 m_uploadingfile = NULL;
1188 m_nCurSessionUp = 0;
1190 credits = new CClientCredits(new CreditStruct());
1193 uint16 CUpQueueRem::GetWaitingPosition(const CUpDownClient *client) const
1195 return client->GetWaitingPosition();
1198 /* Warning: do common base */
1201 bool CUpDownClient::IsIdentified() const
1203 return m_identState == IS_IDENTIFIED;
1207 bool CUpDownClient::IsBadGuy() const
1209 return m_identState == IS_IDBADGUY;
1213 bool CUpDownClient::SUIFailed() const
1215 return m_identState == IS_IDFAILED;
1219 bool CUpDownClient::SUINeeded() const
1221 return m_identState == IS_IDNEEDED;
1225 bool CUpDownClient::SUINotSupported() const
1227 return m_identState == IS_NOTAVAILABLE;
1231 uint64 CUpDownClient::GetDownloadedTotal() const
1233 return credits->GetDownloadedTotal();
1237 uint64 CUpDownClient::GetUploadedTotal() const
1239 return credits->GetUploadedTotal();
1243 double CUpDownClient::GetScoreRatio() const
1245 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1248 /* End Warning */
1251 CUpDownClient::~CUpDownClient()
1253 delete credits;
1257 CUpDownClient *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1259 CUpDownClient *client = new CUpDownClient(tag);
1260 ProcessItemUpdate(tag, client);
1262 theApp->amuledlg->m_transferwnd->clientlistctrl->InsertClient(client, (ViewType)m_viewtype);
1264 return client;
1268 void CUpDownClientListRem::DeleteItem(CUpDownClient *client)
1270 theApp->amuledlg->m_transferwnd->clientlistctrl->
1271 RemoveClient(client, (ViewType)m_viewtype);
1272 delete client;
1276 uint32 CUpDownClientListRem::GetItemID(CUpDownClient *client)
1278 return client->GetUserIDHybrid();
1282 void CUpDownClientListRem::ProcessItemUpdate(
1283 CEC_UpDownClient_Tag *tag,
1284 CUpDownClient *client)
1286 uint16 state = tag->ClientState();
1288 client->m_nDownloadState = state & 0xff;
1289 client->m_nUploadState = (state >> 8) & 0xff;
1291 client->m_nUpDatarate = tag->SpeedUp();
1292 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1293 client->kBpsDown = tag->SpeedDown() / 1024.0;
1294 } else {
1295 client->kBpsDown = 0;
1298 client->m_WaitTime = tag->WaitTime();
1299 client->m_UpStartTimeDelay = tag->XferTime();
1300 client->m_dwLastUpRequest = tag->LastReqTime();
1301 client->m_WaitStartTime = tag->QueueTime();
1303 CreditStruct *credit_struct =
1304 (CreditStruct *)client->credits->GetDataStruct();
1305 credit_struct->uploaded = tag->XferUp();
1306 client->m_nTransferredUp = tag->XferUpSession();
1308 credit_struct->downloaded = tag->XferDown();
1309 client->m_nTransferredDown = tag->XferDownSession();
1311 client->m_score = tag->Score();
1312 client->m_rating = tag->Rating();
1316 CUpQueueRem::CUpQueueRem(CRemoteConnect *conn)
1318 m_up_list(conn, vtUploading), m_wait_list(conn, vtQueued)
1324 * Download queue container: hold PartFiles with progress status
1329 CDownQueueRem::CDownQueueRem(CRemoteConnect *conn)
1331 CRemoteContainer<CPartFile, CMD4Hash, CEC_PartFile_Tag>(conn, true)
1336 bool CDownQueueRem::AddLink(const wxString &link, int)
1338 CECPacket req(EC_OP_ADD_LINK);
1339 req.AddTag(CECTag(EC_TAG_STRING, link));
1341 m_conn->SendPacket(&req);
1342 return true;
1346 void CDownQueueRem::StopUDPRequests()
1348 // have no idea what is it about
1352 void CDownQueueRem::ResetCatParts(int)
1354 // called when category being deleted. Command will be performed on remote side
1358 bool CDownQueueRem::IsPartFile(const CKnownFile *) const
1360 // hope i understand it right
1361 return true;
1365 void CDownQueueRem::OnConnectionState(bool)
1370 CPartFile *CDownQueueRem::CreateItem(CEC_PartFile_Tag *tag)
1372 CPartFile *file = new CPartFile(tag);
1373 m_enc_map[file->GetFileHash()] = PartFileEncoderData(file->GetPartCount(), 10);
1374 ProcessItemUpdate(tag, file);
1376 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1377 return file;
1381 void CDownQueueRem::DeleteItem(CPartFile *in_file)
1383 CScopedPtr<CPartFile> file(in_file);
1385 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile(file.get());
1387 m_enc_map.erase(file->GetFileHash());
1391 CMD4Hash CDownQueueRem::GetItemID(CPartFile *file)
1393 return file->GetFileHash();
1397 void CDownQueueRem::ProcessItemUpdate(CEC_PartFile_Tag *tag, CPartFile *file)
1400 // update status
1402 tag->Speed(&file->m_kbpsDown);
1403 file->kBpsDown = file->m_kbpsDown / 1024.0;
1405 tag->SizeXfer(&file->transferred);
1406 tag->SizeDone(&file->completedsize);
1407 tag->SourceXferCount(&file->transferingsrc);
1408 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1409 tag->SourceCount(&file->m_source_count);
1410 tag->SourceCountA4AF(&file->m_a4af_source_count);
1411 tag->FileStatus(&file->status);
1412 tag->Stopped(&file->m_stopped);
1414 tag->LastSeenComplete(&file->lastseencomplete);
1415 tag->LastDateChanged(&file->m_lastDateChanged);
1416 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1418 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1419 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1420 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1422 tag->FileCat(&file->m_category);
1424 tag->Prio(&file->m_iDownPriorityEC);
1425 if ( file->m_iDownPriorityEC >= 10 ) {
1426 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1427 file->m_bAutoDownPriority = true;
1428 } else {
1429 file->m_iDownPriority = file->m_iDownPriorityEC;
1430 file->m_bAutoDownPriority = false;
1433 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1436 // Copy part/gap status
1438 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1439 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1440 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1441 if (gaptag && parttag && reqtag) {
1442 wxASSERT(m_enc_map.count(file->GetFileHash()));
1444 PartFileEncoderData &encoder = m_enc_map[file->GetFileHash()];
1445 encoder.Decode(
1446 (unsigned char *)gaptag->GetTagData(), gaptag->GetTagDataLen(),
1447 (unsigned char *)parttag->GetTagData(), parttag->GetTagDataLen());
1449 const uint64 *reqparts = (const uint64 *)reqtag->GetTagData();
1450 unsigned reqcount = reqtag->GetTagDataLen() / (2 * sizeof(uint64));
1452 unsigned gap_size = encoder.m_gap_status.Size() / (2 * sizeof(uint64));
1453 // clear gaplist
1454 file->m_gaplist.Init(file->GetFileSize(), false);
1456 // and refill it
1457 const uint64 *gap_info = (const uint64 *)encoder.m_gap_status.Buffer();
1458 for (unsigned j = 0; j < gap_size;j++) {
1459 file->m_gaplist.AddGap(ENDIAN_NTOHLL(gap_info[2*j]), ENDIAN_NTOHLL(gap_info[2*j+1]));
1462 // adjust size of requested block list
1463 while ( file->m_requestedblocks_list.size() > reqcount ) {
1464 delete file->m_requestedblocks_list.front();
1465 file->m_requestedblocks_list.pop_front();
1467 while ( file->m_requestedblocks_list.size() != reqcount ) {
1468 file->m_requestedblocks_list.push_front(new Requested_Block_Struct);
1471 std::list<Requested_Block_Struct*>::iterator it2 = file->m_requestedblocks_list.begin();
1472 for (unsigned i = 0; i < reqcount; ++i) {
1473 Requested_Block_Struct* block = *it2++;
1474 block->StartOffset = ENDIAN_NTOHLL(reqparts[2*i]);
1475 block->EndOffset = ENDIAN_NTOHLL(reqparts[2*i+1]);
1477 // copy parts frequency
1478 const unsigned char *part_info = encoder.m_part_status.Buffer();
1479 for(int i = 0; i < file->GetPartCount(); ++i) {
1480 file->m_SrcpartFrequency[i] = part_info[i];
1482 } else {
1483 AddLogLineNS(CFormat(wxT("ERROR: %X %X %X")) % (size_t)gaptag % (size_t)parttag % (size_t)reqtag);
1486 // Get source names
1487 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1488 if (srcnametag) {
1489 file->ClearSourcenameItemList();
1490 int max = srcnametag->GetTagCount();
1491 for (int i = 0; i < max - 1; ) {
1492 wxString name = srcnametag->GetTagByIndex(i++)->GetStringData();
1493 long count = srcnametag->GetTagByIndex(i++)->GetInt();
1494 file->AddSourcenameItemList(name, count);
1498 // Get comments
1499 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1500 if (commenttag) {
1501 file->ClearFileRatingList();
1502 int max = commenttag->GetTagCount();
1503 for (int i = 0; i < max - 3; ) {
1504 wxString u = commenttag->GetTagByIndex(i++)->GetStringData();
1505 wxString f = commenttag->GetTagByIndex(i++)->GetStringData();
1506 int r = commenttag->GetTagByIndex(i++)->GetInt();
1507 wxString c = commenttag->GetTagByIndex(i++)->GetStringData();
1508 file->AddFileRatingList(u, f, r, c);
1510 file->UpdateFileRatingCommentAvail();
1513 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1517 bool CDownQueueRem::Phase1Done(const CECPacket *)
1519 return true;
1523 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1525 CECPacket req(cmd);
1526 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1528 m_conn->SendPacket(&req);
1532 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1534 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1536 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1537 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1538 req.AddTag(hashtag);
1540 m_conn->SendPacket(&req);
1544 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1546 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1548 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1550 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1551 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1552 req.AddTag(hashtag);
1554 m_conn->SendPacket(&req);
1558 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1560 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1561 file->m_category = cat;
1563 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1564 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1565 req.AddTag(hashtag);
1567 m_conn->SendPacket(&req);
1571 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1573 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1574 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1575 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1576 req.AddTag(hashtag);
1578 m_conn->SendPacket(&req);
1582 CClientListRem::CClientListRem(CRemoteConnect *conn)
1584 m_conn = conn;
1588 void CClientListRem::FilterQueues()
1590 // FIXME: add code
1591 //wxFAIL;
1595 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag>(conn)
1597 m_curr_search = -1;
1601 wxString CSearchListRem::StartNewSearch(
1602 uint32* nSearchID, SearchType search_type,
1603 const CSearchList::CSearchParams& params)
1605 CECPacket search_req(EC_OP_SEARCH_START);
1606 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1607 switch(search_type) {
1608 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1609 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1610 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1612 search_req.AddTag(
1613 CEC_Search_Tag(params.searchString, ec_search_type,
1614 params.typeText, params.extension, params.availability,
1615 params.minSize, params.maxSize));
1617 m_conn->SendPacket(&search_req);
1618 m_curr_search = *(nSearchID); // No kad remote search yet.
1620 Flush();
1622 return wxEmptyString; // EC reply will have the error mesg is needed.
1626 void CSearchListRem::StopGlobalSearch()
1628 if (m_curr_search != -1) {
1629 CECPacket search_req(EC_OP_SEARCH_STOP);
1630 m_conn->SendPacket(&search_req);
1635 void CSearchListRem::HandlePacket(const CECPacket *packet)
1637 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1638 CoreNotify_Search_Update_Progress(packet->GetTagByIndex(0)->GetInt());
1639 } else {
1640 CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag>::HandlePacket(packet);
1645 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1647 m_parent(NULL),
1648 m_showChildren(false),
1649 m_sourceCount(0),
1650 m_completeSourceCount(0),
1651 m_kademlia(false),
1652 m_clientID(0),
1653 m_clientPort(0)
1655 SetFileName(CPath(tag->FileName()));
1656 m_abyFileHash = tag->ID();
1657 SetFileSize(tag->SizeFull());
1659 m_searchID = theApp->searchlist->m_curr_search;
1664 // dtor is virtual - must be implemented
1665 CSearchFile::~CSearchFile()
1670 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
1672 CSearchFile *file = new CSearchFile(tag);
1673 ProcessItemUpdate(tag, file);
1675 theApp->amuledlg->m_searchwnd->AddResult(file);
1677 return file;
1681 void CSearchListRem::DeleteItem(CSearchFile *file)
1683 delete file;
1687 CMD4Hash CSearchListRem::GetItemID(CSearchFile *file)
1689 return file->GetFileHash();
1693 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
1695 file->m_sourceCount = tag->SourceCount();
1696 file->m_completeSourceCount = tag->CompleteSourceCount();
1700 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
1702 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
1703 m_conn->SendRequest(this, &progress_req);
1705 return true;
1709 void CSearchListRem::RemoveResults(long nSearchID)
1711 ResultMap::iterator it = m_results.find(nSearchID);
1712 if (it != m_results.end()) {
1713 CSearchResultList& list = it->second;
1714 for (unsigned int i = 0; i < list.size(); ++i) {
1715 delete list[i];
1717 m_results.erase(it);
1722 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
1724 ResultMap::const_iterator it = m_results.find(nSearchID);
1725 if (it != m_results.end()) {
1726 return it->second;
1729 // TODO: Should we assert in this case?
1730 static CSearchResultList list;
1731 return list;
1735 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
1737 theStats::UpdateStats(packet);
1738 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
1742 bool CUpDownClient::IsBanned() const
1744 // FIXME: add code
1745 return false;
1750 // Those functions have different implementation in remote gui
1752 void CUpDownClient::Ban()
1754 // FIXME: add code
1755 wxFAIL;
1759 void CUpDownClient::UnBan()
1761 // FIXME: add code
1762 wxFAIL;
1766 void CUpDownClient::RequestSharedFileList()
1768 // FIXME: add code
1769 wxFAIL;
1773 void CKnownFile::SetFileComment(const wxString &)
1775 // FIXME: add code
1776 wxMessageBox(_("Comments and ratings are not supported on remote gui yet"), _("Information"), wxOK | wxICON_INFORMATION);
1780 void CKnownFile::SetFileRating(unsigned char)
1782 // FIXME: add code
1786 // I don't think it will be implemented - too match data transfer. But who knows ?
1787 wxString CUpDownClient::ShowDownloadingParts() const
1789 return wxEmptyString;
1793 bool CUpDownClient::SwapToAnotherFile(
1794 bool WXUNUSED(bIgnoreNoNeeded),
1795 bool WXUNUSED(ignoreSuspensions),
1796 bool WXUNUSED(bRemoveCompletely),
1797 CPartFile* WXUNUSED(toFile))
1799 // FIXME: add code
1800 wxFAIL;
1801 return false;
1806 // Those functions are virtual. So even they don't get called they must
1807 // be defined so linker will be happy
1809 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1811 wxFAIL;
1812 return 0;
1816 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
1818 wxFAIL;
1819 return false;
1823 void CKnownFile::UpdatePartsInfo()
1825 wxFAIL;
1829 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1831 wxFAIL;
1832 return 0;
1836 void CPartFile::UpdatePartsInfo()
1838 wxFAIL;
1842 void CPartFile::UpdateFileRatingCommentAvail()
1844 bool prevComment = m_hasComment;
1845 int prevRating = m_iUserRating;
1847 m_hasComment = false;
1848 m_iUserRating = 0;
1849 int ratingCount = 0;
1851 FileRatingList::iterator it = m_FileRatingList.begin();
1852 for (; it != m_FileRatingList.end(); ++it) {
1853 SFileRating& cur_rat = *it;
1855 if (!cur_rat.Comment.IsEmpty()) {
1856 m_hasComment = true;
1859 uint8 rating = cur_rat.Rating;
1860 if (rating) {
1861 wxASSERT(rating <= 5);
1863 ratingCount++;
1864 m_iUserRating += rating;
1868 if (ratingCount) {
1869 m_iUserRating /= ratingCount;
1870 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
1873 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
1874 UpdateDisplayedInfo();
1878 bool CPartFile::SavePartFile(bool)
1880 wxFAIL;
1881 return false;
1886 // since gui is not linked with amule.cpp - define events here
1888 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
1889 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
1890 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
1891 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
1892 // File_checked_for_headers