2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 Angel Vidal (Kry) ( kry@amule.org / http://www.amule.org )
5 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "config.h" // Needed for VERSION
32 #include <unistd.h> // Do_not_auto_remove
35 #include "TextClient.h"
37 //-------------------------------------------------------------------
40 //-------------------------------------------------------------------
42 #include <ec/cpp/ECSpecialTags.h>
44 #include <wx/tokenzr.h>
46 #include <common/Format.h> // Needed for CFormat
47 #include "OtherFunctions.h"
48 #include "KnownFile.h" // Needed for Priority Levels
49 #include "DataToText.cpp" // Needed for PriorityToStr
51 #define APP_INIT_SIZE_X 640
52 #define APP_INIT_SIZE_Y 480
54 #define theApp (*((CamulecmdApp*)wxTheApp))
56 //-------------------------------------------------------------------
63 CMD_ID_PRIORITY_NORMAL
,
71 CMD_ID_DISCONNECT_ED2K
,
72 CMD_ID_DISCONNECT_KAD
,
74 CMD_ID_RELOAD_IPFILTER
,
75 CMD_ID_SET_IPFILTER_ON
,
76 CMD_ID_SET_IPFILTER_OFF
,
77 CMD_ID_SET_IPFILTER_CLIENTS_ON
,
78 CMD_ID_SET_IPFILTER_CLIENTS_OFF
,
79 CMD_ID_SET_IPFILTER_SERVERS_ON
,
80 CMD_ID_SET_IPFILTER_SERVERS_OFF
,
81 CMD_ID_SET_IPFILTER_LEVEL
,
83 CMD_ID_GET_IPFILTER_STATE
,
84 CMD_ID_GET_IPFILTER_STATE_CLIENTS
,
85 CMD_ID_GET_IPFILTER_STATE_SERVERS
,
86 CMD_ID_GET_IPFILTER_LEVEL
,
95 CMD_ID_SET_BWLIMIT_UP
,
96 CMD_ID_SET_BWLIMIT_DOWN
,
100 CMD_ID_SEARCH_GLOBAL
,
103 CMD_ID_SEARCH_RESULTS
,
104 CMD_ID_SEARCH_PROGRESS
,
106 // IDs for deprecated commands
111 // method to create a SearchFile
112 SearchFile::SearchFile(CEC_SearchFile_Tag
*tag
)
114 nHash
= tag
->FileHash();
115 sHash
= nHash
.Encode();
116 sFileName
= tag
->FileName();
117 lFileSize
= tag
->SizeFull();
118 lSourceCount
= tag
->SourceCount();
119 bPresent
= tag
->AlreadyHave();
122 //-------------------------------------------------------------------
123 IMPLEMENT_APP (CamulecmdApp
)
124 //-------------------------------------------------------------------
126 void CamulecmdApp::OnInitCmdLine(wxCmdLineParser
& parser
)
128 CaMuleExternalConnector::OnInitCmdLine(parser
);
129 parser
.AddOption(wxT("c"), wxT("command"),
130 _("Execute <str> and exit."),
131 wxCMD_LINE_VAL_STRING
, wxCMD_LINE_PARAM_OPTIONAL
);
134 bool CamulecmdApp::OnCmdLineParsed(wxCmdLineParser
& parser
)
136 m_HasCmdOnCmdLine
= parser
.Found(wxT("command"), &m_CmdString
);
137 return CaMuleExternalConnector::OnCmdLineParsed(parser
);
140 void CamulecmdApp::TextShell(const wxString
& prompt
)
142 if (m_HasCmdOnCmdLine
)
143 Parse_Command(m_CmdString
);
145 CaMuleExternalConnector::TextShell(prompt
);
148 int CamulecmdApp::ProcessCommand(int CmdId
)
150 wxString args
= GetCmdArgs();
151 CECPacket
*request
= 0;
152 std::list
<CECPacket
*> request_list
;
154 EC_SEARCH_TYPE search_type
= EC_SEARCH_KAD
;
156 // Implementation of the deprecated command 'SetIPFilter'.
157 if (CmdId
== CMD_ID_SET_IPFILTER
) {
158 if ( ! args
.IsEmpty() ) {
159 if (args
.IsSameAs(wxT("ON"), false)) {
160 CmdId
= CMD_ID_SET_IPFILTER_ON
;
161 } else if (args
.IsSameAs(wxT("OFF"), false)) {
162 CmdId
= CMD_ID_SET_IPFILTER_OFF
;
164 return CMD_ERR_INVALID_ARG
;
167 CmdId
= CMD_ID_GET_IPFILTER_STATE
;
173 request_list
.push_back(new CECPacket(EC_OP_STAT_REQ
, EC_DETAIL_CMD
));
176 case CMD_ID_SHUTDOWN
:
177 request_list
.push_back(new CECPacket(EC_OP_SHUTDOWN
));
181 if ( !args
.IsEmpty() ) {
184 // Not much we can do against this unicode2char.
185 int result
= sscanf(unicode2char(args
), "%d.%d.%d.%d:%d", &ip
[0], &ip
[1], &ip
[2], &ip
[3], &port
);
187 // Try to resolve DNS -- good for dynamic IP servers
188 wxString
serverName(args
.BeforeFirst(wxT(':')));
190 bool ok
= args
.AfterFirst(wxT(':')).ToLong(&lPort
);
191 port
= (unsigned int)lPort
;
193 a
.Hostname(serverName
);
195 result
= sscanf(unicode2char(a
.IPAddress()), "%d.%d.%d.%d", &ip
[0], &ip
[1], &ip
[2], &ip
[3]);
196 if (serverName
.IsEmpty() || !ok
|| (result
!= 4)) {
197 Show(_("Invalid IP format. Use xxx.xxx.xxx.xxx:xxxx\n"));
202 addr
.m_ip
[0] = ip
[0];
203 addr
.m_ip
[1] = ip
[1];
204 addr
.m_ip
[2] = ip
[2];
205 addr
.m_ip
[3] = ip
[3];
207 request
= new CECPacket(EC_OP_SERVER_CONNECT
);
208 request
->AddTag(CECTag(EC_TAG_SERVER
, addr
));
209 request_list
.push_back(request
);
211 request_list
.push_back(new CECPacket(EC_OP_CONNECT
));
215 case CMD_ID_CONNECT_ED2K
:
216 request_list
.push_back(new CECPacket(EC_OP_SERVER_CONNECT
));
219 case CMD_ID_CONNECT_KAD
:
220 request_list
.push_back(new CECPacket(EC_OP_KAD_START
));
223 case CMD_ID_DISCONNECT
:
224 request_list
.push_back(new CECPacket(EC_OP_DISCONNECT
));
227 case CMD_ID_DISCONNECT_ED2K
:
228 request_list
.push_back(new CECPacket(EC_OP_SERVER_DISCONNECT
));
231 case CMD_ID_DISCONNECT_KAD
:
232 request_list
.push_back(new CECPacket(EC_OP_KAD_STOP
));
235 case CMD_ID_RELOAD_SHARED
:
236 request_list
.push_back(new CECPacket(EC_OP_SHAREDFILES_RELOAD
));
239 case CMD_ID_RELOAD_IPFILTER
:
240 request_list
.push_back(new CECPacket(EC_OP_IPFILTER_RELOAD
));
243 case CMD_ID_SET_IPFILTER_ON
:
244 case CMD_ID_SET_IPFILTER_CLIENTS_ON
:
245 case CMD_ID_SET_IPFILTER_SERVERS_ON
:
247 case CMD_ID_SET_IPFILTER_OFF
:
248 case CMD_ID_SET_IPFILTER_CLIENTS_OFF
:
249 case CMD_ID_SET_IPFILTER_SERVERS_OFF
:
251 if (CmdId
== CMD_ID_SET_IPFILTER_CLIENTS_ON
| CmdId
== CMD_ID_SET_IPFILTER_CLIENTS_OFF
) {
252 CmdId
= CMD_ID_GET_IPFILTER_STATE_CLIENTS
;
253 } else if (CmdId
== CMD_ID_SET_IPFILTER_SERVERS_ON
|| CmdId
== CMD_ID_SET_IPFILTER_SERVERS_OFF
) {
254 CmdId
= CMD_ID_GET_IPFILTER_STATE_SERVERS
;
256 CmdId
= CMD_ID_GET_IPFILTER_STATE
;
259 request
= new CECPacket(EC_OP_SET_PREFERENCES
);
260 CECEmptyTag
prefs(EC_TAG_PREFS_SECURITY
);
261 if (CmdId
!= CMD_ID_GET_IPFILTER_STATE_SERVERS
) {
262 prefs
.AddTag(CECTag(EC_TAG_IPFILTER_CLIENTS
, (uint8
)tmp_int
));
264 if (CmdId
!= CMD_ID_GET_IPFILTER_STATE_CLIENTS
) {
265 prefs
.AddTag(CECTag(EC_TAG_IPFILTER_SERVERS
, (uint8
)tmp_int
));
267 request
->AddTag(prefs
);
268 request_list
.push_back(request
);
270 case CMD_ID_GET_IPFILTER
:
271 case CMD_ID_GET_IPFILTER_STATE
:
272 case CMD_ID_GET_IPFILTER_STATE_CLIENTS
:
273 case CMD_ID_GET_IPFILTER_STATE_SERVERS
:
274 request
= new CECPacket(EC_OP_GET_PREFERENCES
);
275 request
->AddTag(CECTag(EC_TAG_SELECT_PREFS
, (uint32
)EC_PREFS_SECURITY
));
276 request_list
.push_back(request
);
279 case CMD_ID_SET_IPFILTER_LEVEL
:
280 if (!args
.IsEmpty()) // This 'if' must stay as long as we support the deprecated 'IPLevel' command.
282 unsigned long int level
= 0;
283 if (args
.ToULong(&level
) == true && level
< 256) {
284 request
= new CECPacket(EC_OP_SET_PREFERENCES
);
285 CECEmptyTag
prefs(EC_TAG_PREFS_SECURITY
);
286 prefs
.AddTag(CECTag(EC_TAG_IPFILTER_LEVEL
, (uint8
)level
));
287 request
->AddTag(prefs
);
288 request_list
.push_back(request
);
290 return CMD_ERR_INVALID_ARG
;
293 CmdId
= CMD_ID_GET_IPFILTER_LEVEL
;
294 case CMD_ID_GET_IPFILTER_LEVEL
:
295 request
= new CECPacket(EC_OP_GET_PREFERENCES
);
296 request
->AddTag(CECTag(EC_TAG_SELECT_PREFS
, (uint32
)EC_PREFS_SECURITY
));
297 request_list
.push_back(request
);
304 if ( args
.IsEmpty() ) {
305 Show(_("This command requires an argument. Valid arguments: 'all', filename, or a number.\n"));
308 wxStringTokenizer
argsTokenizer(args
);
312 // Grab the entire dl queue right away
313 CECPacket
request_all(EC_OP_GET_DLOAD_QUEUE
, EC_DETAIL_CMD
);
314 const CECPacket
*reply_all
= SendRecvMsg_v2(&request_all
);
319 request
= new CECPacket(EC_OP_PARTFILE_PAUSE
); break;
321 request
= new CECPacket(EC_OP_PARTFILE_DELETE
); break;
323 request
= new CECPacket(EC_OP_PARTFILE_RESUME
); break;
324 default: wxASSERT(0);
327 // We loop through all the arguments
328 while(argsTokenizer
.HasMoreTokens()) {
329 token
=argsTokenizer
.GetNextToken();
331 // If the user requested all, then we select all files and exit the loop
332 // since there is little point to add anything more to "everything"
333 if( token
== wxT("all") ) {
334 for(int i
= 0;i
< reply_all
->GetTagCount();i
++) {
335 const CECTag
*tag
= reply_all
->GetTagByIndex(i
);
337 request
->AddTag(CECTag(EC_TAG_PARTFILE
, tag
->GetMD4Data()));
341 } else if ( hash
.Decode(token
.Trim(false).Trim(true)) ) {
342 if ( !hash
.IsEmpty() ) {
343 Show(_("Processing by hash: "+token
+wxT("\n")));
344 request
->AddTag(CECTag(EC_TAG_PARTFILE
, hash
));
347 // Go through the dl queue and look at each filename
348 for(int i
= 0; i
< reply_all
->GetTagCount(); i
++) {
349 CEC_PartFile_Tag
*tag
= (CEC_PartFile_Tag
*)reply_all
->GetTagByIndex(i
);
351 wxString partmetname
= tag
->PartMetName();
353 // We check for filename, XXX.pat.met, XXX.part, XXX
354 if( tag
->FileName() == token
||
355 partmetname
== token
||
356 partmetname
.Truncate(partmetname
.Len()-4) == token
||
357 partmetname
.Truncate(partmetname
.Len()-5) == token
) {
358 Show(_("Processing by filename: "+token
+wxT("\n")));
359 request
->AddTag(CECTag(EC_TAG_PARTFILE
, tag
->GetMD4Data()));
363 } // End of filename check else
364 } // End of argument token loop
366 request_list
.push_back(request
);
370 } // End of dl queue processing
372 } // end of command processing
376 case CMD_ID_PRIORITY_LOW
:
377 case CMD_ID_PRIORITY_NORMAL
:
378 case CMD_ID_PRIORITY_HIGH
:
379 case CMD_ID_PRIORITY_AUTO
:
380 if ( args
.IsEmpty() ) {
381 Show(_("This command requires an argument. Valid arguments: a file hash.\n"));
385 if (hash
.Decode(args
.Trim(false).Trim(true))) {
386 if (!hash
.IsEmpty()) {
387 request
= new CECPacket(EC_OP_PARTFILE_PRIO_SET
);
388 CECTag
hashtag(EC_TAG_PARTFILE
, hash
);
390 case CMD_ID_PRIORITY_LOW
:
391 hashtag
.AddTag(CECTag(EC_TAG_PARTFILE_PRIO
, (uint8
)PR_LOW
));
393 case CMD_ID_PRIORITY_NORMAL
:
394 hashtag
.AddTag(CECTag(EC_TAG_PARTFILE_PRIO
, (uint8
)PR_NORMAL
));
396 case CMD_ID_PRIORITY_HIGH
:
397 hashtag
.AddTag(CECTag(EC_TAG_PARTFILE_PRIO
, (uint8
)PR_HIGH
));
399 case CMD_ID_PRIORITY_AUTO
:
400 hashtag
.AddTag(CECTag(EC_TAG_PARTFILE_PRIO
, (uint8
)PR_AUTO
));
402 default: wxASSERT(0);
404 request
->AddTag(hashtag
);
405 request_list
.push_back(request
);
407 Show(_("Not a valid number\n"));
411 Show(_("Not a valid hash (length should be exactly 32 chars)\n"));
418 request_list
.push_back(new CECPacket(EC_OP_GET_ULOAD_QUEUE
));
422 request_list
.push_back(new CECPacket(EC_OP_GET_DLOAD_QUEUE
));
425 case CMD_ID_SHOW_LOG
:
426 request_list
.push_back(new CECPacket(EC_OP_GET_LOG
));
429 case CMD_ID_SHOW_SERVERS
:
430 request_list
.push_back(new CECPacket(EC_OP_GET_SERVER_LIST
, EC_DETAIL_CMD
));
433 case CMD_ID_RESET_LOG
:
434 request_list
.push_back(new CECPacket(EC_OP_RESET_LOG
));
438 if (args
.compare(0, 7, wxT("ed2k://")) == 0) {
439 //aMule doesn't like AICH links without |/| in front of h=
440 if (args
.Find(wxT("|h=")) > -1 && args
.Find(wxT("|/|h=")) == -1) {
441 args
.Replace(wxT("|h="),wxT("|/|h="));
444 request
= new CECPacket(EC_OP_ADD_LINK
);
445 request
->AddTag(CECTag(EC_TAG_STRING
, args
));
446 request_list
.push_back(request
);
449 case CMD_ID_SET_BWLIMIT_UP
:
450 tmp_int
= EC_TAG_CONN_MAX_UL
- EC_TAG_CONN_MAX_DL
;
451 case CMD_ID_SET_BWLIMIT_DOWN
:
452 tmp_int
+= EC_TAG_CONN_MAX_DL
;
454 unsigned long int limit
;
455 if (args
.ToULong(&limit
)) {
456 request
= new CECPacket(EC_OP_SET_PREFERENCES
);
457 CECEmptyTag
prefs(EC_TAG_PREFS_CONNECTIONS
);
458 prefs
.AddTag(CECTag(tmp_int
, (uint16
)limit
));
459 request
->AddTag(prefs
);
460 request_list
.push_back(request
);
462 return CMD_ERR_INVALID_ARG
;
465 case CMD_ID_GET_BWLIMITS
:
466 request
= new CECPacket(EC_OP_GET_PREFERENCES
);
467 request
->AddTag(CECTag(EC_TAG_SELECT_PREFS
, (uint32
)EC_PREFS_CONNECTIONS
));
468 request_list
.push_back(request
);
471 case CMD_ID_STATTREE
:
472 request
= new CECPacket(EC_OP_GET_STATSTREE
);
473 if (!args
.IsEmpty()) {
474 unsigned long int max_versions
;
475 if (args
.ToULong(&max_versions
)) {
476 if (max_versions
< 256) {
477 request
->AddTag(CECTag(EC_TAG_STATTREE_CAPPING
, (uint8
)max_versions
));
480 return CMD_ERR_INVALID_ARG
;
484 return CMD_ERR_INVALID_ARG
;
487 request_list
.push_back(request
);
489 case CMD_ID_SEARCH_GLOBAL
:
490 search_type
= EC_SEARCH_GLOBAL
;
491 case CMD_ID_SEARCH_LOCAL
:
492 if (search_type
!= EC_SEARCH_GLOBAL
){
493 search_type
= EC_SEARCH_LOCAL
;
495 case CMD_ID_SEARCH_KAD
:
496 if (search_type
!= EC_SEARCH_GLOBAL
&& search_type
!= EC_SEARCH_LOCAL
){
497 search_type
= EC_SEARCH_KAD
;
501 wxString search
= args
;
502 wxString type
= wxT("");
503 wxString extention
= wxT("");
508 request
= new CECPacket(EC_OP_SEARCH_START
);
509 request
->AddTag(CEC_Search_Tag (search
, search_type
, type
, extention
, avail
, min_size
, max_size
));
510 request_list
.push_back(request
);
514 printf("No search type defined.\nType 'help search' to get more help.\n");
518 case CMD_ID_SEARCH_RESULTS
:
519 request_list
.push_back(new CECPacket(EC_OP_SEARCH_RESULTS
, EC_DETAIL_FULL
));
522 case CMD_ID_SEARCH_PROGRESS
:
523 request_list
.push_back(new CECPacket(EC_OP_SEARCH_PROGRESS
));
526 case CMD_ID_DOWNLOAD
:
529 unsigned long int id
= 0;
530 if (args
.ToULong(&id
) == true && id
< m_Results_map
.size()) {
532 SearchFile
* file
= m_Results_map
[id
];
533 printf("Download File: %lu %s\n", id
, (const char*)unicode2char(file
->sFileName
));
534 request
= new CECPacket(EC_OP_DOWNLOAD_SEARCH_RESULT
);
535 // get with id the hash and category=0
537 CECTag
hashtag(EC_TAG_PARTFILE
, file
->nHash
);
538 hashtag
.AddTag(CECTag(EC_TAG_PARTFILE_CAT
, category
));
539 request
->AddTag(hashtag
);
540 request_list
.push_back(request
);
542 return CMD_ERR_INVALID_ARG
;
548 return CMD_ERR_PROCESS_CMD
;
551 m_last_cmd_id
= CmdId
;
553 if ( ! request_list
.empty() ) {
554 std::list
<CECPacket
*>::iterator it
= request_list
.begin();
555 while ( it
!= request_list
.end() ) {
556 CECPacket
*curr
= *it
++;
557 const CECPacket
*reply
= SendRecvMsg_v2(curr
);
560 Process_Answer_v2(reply
);
564 request_list
.resize(0);
567 if (CmdId
== CMD_ID_SHUTDOWN
)
574 * Method to show the results in the console
576 void CamulecmdApp::ShowResults(CResultMap results_map
)
578 unsigned int name_max
= 80;
579 unsigned int mb_max
= 5;
580 unsigned int nr_max
= 5;
581 unsigned long int id
= 0;
582 wxString output
, name
, sources
, mb
, kb
;
584 printf("Nr. Filename: Size(MB): Sources: \n");
585 printf("-----------------------------------------------------------------------------------------------------------\n");
587 for( std::map
<unsigned long int,SearchFile
*>::iterator iter
= results_map
.begin(); iter
!= results_map
.end(); iter
++ ) {
589 SearchFile
* file
= (*iter
).second
;
591 output
.Printf(wxT("%i. "), id
);
592 output
= output
.SubString(0, nr_max
).Append(file
->sFileName
).Append(' ', name_max
);
593 mb
.Printf(wxT(" %d"), file
->lFileSize
/1024/1024);
594 kb
.Printf(wxT(".%d"), file
->lFileSize
/1024%1024);
595 output
= output
.SubString(0, nr_max
+ name_max
+ mb_max
- mb
.Length() ).Append(mb
).Append(kb
);
596 printf("%s %ld\n",(const char*)unicode2char(output
), file
->lSourceCount
);
601 // Formats a statistics (sub)tree to text
602 wxString
StatTree2Text(CEC_StatTree_Node_Tag
*tree
, int depth
)
605 return wxEmptyString
;
607 wxString result
= wxString(wxChar(' '), depth
) + tree
->GetDisplayString() + wxT("\n");
608 for (int i
= 0; i
< tree
->GetTagCount(); ++i
) {
609 CEC_StatTree_Node_Tag
*tmp
= (CEC_StatTree_Node_Tag
*)tree
->GetTagByIndex(i
);
610 if (tmp
->GetTagName() == EC_TAG_STATTREE_NODE
) {
611 result
+= StatTree2Text(tmp
, depth
+ 1);
618 * Format EC packet into text form for output to console
620 void CamulecmdApp::Process_Answer_v2(const CECPacket
*response
)
623 wxString
msgFailedUnknown(_("Request failed with an unknown error."));
625 switch (response
->GetOpCode()) {
627 s
<< _("Operation was successful.");
630 if (response
->GetTagCount()) {
631 const CECTag
*tag
= response
->GetTagByIndex(0);
633 s
<< CFormat(_("Request failed with the following error: %s")) % wxGetTranslation(tag
->GetStringData());
635 s
<< msgFailedUnknown
;
638 s
<< msgFailedUnknown
;
641 case EC_OP_SET_PREFERENCES
:
643 const CECTag
*tab
= response
->GetTagByNameSafe(EC_TAG_PREFS_SECURITY
);
644 const CECTag
*ipfilterLevel
= tab
->GetTagByName(EC_TAG_IPFILTER_LEVEL
);
646 if (m_last_cmd_id
== CMD_ID_GET_IPFILTER
||
647 m_last_cmd_id
== CMD_ID_GET_IPFILTER_STATE
||
648 m_last_cmd_id
== CMD_ID_GET_IPFILTER_STATE_CLIENTS
) {
649 s
<< wxString::Format(_("IP filtering for clients is %s.\n"),
650 (tab
->GetTagByName(EC_TAG_IPFILTER_CLIENTS
) == NULL
) ? _("OFF") : _("ON"));
652 if (m_last_cmd_id
== CMD_ID_GET_IPFILTER
||
653 m_last_cmd_id
== CMD_ID_GET_IPFILTER_STATE
||
654 m_last_cmd_id
== CMD_ID_GET_IPFILTER_STATE_SERVERS
) {
655 s
<< wxString::Format(_("IP filtering for servers is %s.\n"),
656 (tab
->GetTagByName(EC_TAG_IPFILTER_SERVERS
) == NULL
) ? _("OFF") : _("ON"));
658 if (m_last_cmd_id
== CMD_ID_GET_IPFILTER
||
659 m_last_cmd_id
== CMD_ID_GET_IPFILTER_LEVEL
) {
660 s
<< wxString::Format(_("Current IPFilter Level is %d.\n"),
661 ipfilterLevel
->GetInt());
664 tab
= response
->GetTagByNameSafe(EC_TAG_PREFS_CONNECTIONS
);
665 const CECTag
*connMaxUL
= tab
->GetTagByName(EC_TAG_CONN_MAX_UL
);
666 const CECTag
*connMaxDL
= tab
->GetTagByName(EC_TAG_CONN_MAX_DL
);
667 if (connMaxUL
&& connMaxDL
) {
668 s
<< wxString::Format(_("Bandwidth Limits: Up: %u kB/s, Down: %u kB/s.\n"),
669 (uint16
)connMaxUL
->GetInt(),
670 (uint16
)connMaxDL
->GetInt());
675 for (int i
= 0; i
< response
->GetTagCount(); ++i
) {
676 const CECTag
*tag
= response
->GetTagByIndex(i
);
678 s
<< tag
->GetStringData() << wxT("\n");
684 CEC_ConnState_Tag
*connState
= (CEC_ConnState_Tag
*)response
->GetTagByName(EC_TAG_CONNSTATE
);
686 s
<< _("ED2K") << wxT(": ");
687 if (connState
->IsConnectedED2K()) {
688 CECTag
*server
= connState
->GetTagByName(EC_TAG_SERVER
);
689 CECTag
*serverName
= server
? server
->GetTagByName(EC_TAG_SERVER_NAME
) : NULL
;
690 if (server
&& serverName
) {
691 s
<< CFormat(_("Connected to %s %s %s")) %
692 serverName
->GetStringData() %
693 server
->GetIPv4Data().StringIP() %
694 (connState
->HasLowID() ? _("with LowID") : _("with HighID"));
696 } else if (connState
->IsConnectingED2K()) {
697 s
<< _("Now connecting");
699 s
<< _("Not connected");
701 s
<< wxT('\n') << _("Kad") << wxT(": ");
702 if (connState
->IsKadRunning()) {
703 if (connState
->IsConnectedKademlia()) {
704 s
<< _("Connected") << wxT(" (");
705 if (connState
->IsKadFirewalled()) {
706 s
<< _("firewalled");
712 s
<< _("Not connected");
715 s
<< _("Not running");
719 const CECTag
*tmpTag
;
720 if ((tmpTag
= response
->GetTagByName(EC_TAG_STATS_DL_SPEED
)) != 0) {
721 s
<< CFormat(_("\nDownload:\t%s")) % CastItoSpeed(tmpTag
->GetInt());
723 if ((tmpTag
= response
->GetTagByName(EC_TAG_STATS_UL_SPEED
)) != 0) {
724 s
<< CFormat(_("\nUpload:\t%s")) % CastItoSpeed(tmpTag
->GetInt());
726 if ((tmpTag
= response
->GetTagByName(EC_TAG_STATS_UL_QUEUE_LEN
)) != 0) {
727 s
<< wxString::Format(_("\nClients in queue:\t%d\n"), tmpTag
->GetInt());
729 if ((tmpTag
= response
->GetTagByName(EC_TAG_STATS_TOTAL_SRC_COUNT
)) != 0) {
730 s
<< wxString::Format(_("\nTotal sources:\t%d\n"), tmpTag
->GetInt());
734 case EC_OP_DLOAD_QUEUE
:
735 for(int i
= 0; i
< response
->GetTagCount(); ++i
) {
736 CEC_PartFile_Tag
*tag
=
737 (CEC_PartFile_Tag
*)response
->GetTagByIndex(i
);
739 uint64 filesize
, donesize
;
740 filesize
= tag
->SizeFull();
741 donesize
= tag
->SizeDone();
742 s
<< tag
->FileHashString() << wxT(" ") <<
744 wxString::Format(wxT("\n\t [%.1f%%] %4i/%4i "),
745 ((float)donesize
) / ((float)filesize
)*100.0,
746 (int)tag
->SourceCount() - (int)tag
->SourceNotCurrCount(),
747 (int)tag
->SourceCount()) <<
748 ((int)tag
->SourceCountA4AF() ? wxString::Format(wxT("+%2.2i "),(int)tag
->SourceCountA4AF()) : wxString(wxT(" "))) <<
749 ((int)tag
->SourceXferCount() ? wxString::Format(wxT("(%2.2i) - "),(int)tag
->SourceXferCount()) : wxString(wxT(" - "))) <<
750 tag
->GetFileStatusString();
751 s
<< wxT(" - ") << tag
->PartMetName();
752 if (tag
->Prio() < 10) {
753 s
<< wxT(" - ") << PriorityToStr((int)tag
->Prio(), 0);
755 s
<< wxT(" - ") << PriorityToStr((tag
->Prio() - 10), 1);
757 if ( tag
->SourceXferCount() > 0) {
758 s
<< wxT(" - ") + CastItoSpeed(tag
->Speed());
764 case EC_OP_ULOAD_QUEUE
:
765 for(int i
= 0; i
< response
->GetTagCount(); ++i
) {
766 const CECTag
*tag
= response
->GetTagByIndex(i
);
767 const CECTag
*clientName
= tag
? tag
->GetTagByName(EC_TAG_CLIENT_NAME
) : NULL
;
768 const CECTag
*partfileName
= tag
? tag
->GetTagByName(EC_TAG_PARTFILE_NAME
) : NULL
;
769 const CECTag
*partfileSizeXfer
= tag
? tag
->GetTagByName(EC_TAG_PARTFILE_SIZE_XFER
) : NULL
;
770 const CECTag
*partfileSpeed
= tag
? tag
->GetTagByName(EC_TAG_CLIENT_UP_SPEED
) : NULL
;
771 if (tag
&& clientName
&& partfileName
&& partfileSizeXfer
&& partfileSpeed
) {
773 wxString::Format(wxT("%10u "), tag
->GetInt()) <<
774 clientName
->GetStringData() << wxT(" ") <<
775 partfileName
->GetStringData() << wxT(" ") <<
776 CastItoXBytes(partfileSizeXfer
->GetInt()) << wxT(" ") <<
777 CastItoSpeed(partfileSpeed
->GetInt());
782 for (int i
= 0; i
< response
->GetTagCount(); ++i
) {
783 const CECTag
*tag
= response
->GetTagByIndex(i
);
785 s
<< tag
->GetStringData() << wxT("\n");
790 case EC_OP_SERVER_LIST
:
791 for(int i
= 0; i
< response
->GetTagCount(); i
++) {
792 const CECTag
*tag
= response
->GetTagByIndex(i
);
793 const CECTag
*serverName
= tag
? tag
->GetTagByName(EC_TAG_SERVER_NAME
) : NULL
;
794 if (tag
&& serverName
) {
795 wxString ip
= tag
->GetIPv4Data().StringIP();
796 ip
.Append(' ', 24 - ip
.Length());
797 s
<< ip
<< serverName
->GetStringData() << wxT("\n");
801 case EC_OP_STATSTREE
:
802 s
<< StatTree2Text((CEC_StatTree_Node_Tag
*)response
->GetTagByName(EC_TAG_STATTREE_NODE
), 0);
805 case EC_OP_SEARCH_RESULTS
:
806 m_Results_map
.clear();
807 s
<< wxString::Format(_("Number of search results: %i\n"),response
->GetTagCount());
808 for (int i
= 0;i
< response
->GetTagCount();i
++) {
809 CEC_SearchFile_Tag
*tag
= (CEC_SearchFile_Tag
*)response
->GetTagByIndex(i
);
810 //printf("Tag FileName: %s \n",(const char*)unicode2char(tag->FileName()));
812 m_Results_map
[i
] = new SearchFile(tag
);
813 //const CECTag *tag = response->GetTagByIndex(i);
816 ShowResults(m_Results_map
);
819 case EC_OP_SEARCH_PROGRESS
:
820 s
<< _("TODO - show progress of a search");
821 // gives compilation error!!
822 // const CECTag *tab = response->GetTagByNameSafe(EC_TAG_SEARCH_STATUS);
823 //s << wxString::Format(_("Search progress: %u %% \n"),(const char*)unicode2char(tab->GetStringData()));
826 s
<< wxString::Format(_("Received an unknown reply from the server, OpCode = %#x."), response
->GetOpCode());
831 void CamulecmdApp::OnInitCommandSet()
837 CaMuleExternalConnector::OnInitCommandSet();
839 m_commands
.AddCommand(wxT("Status"), CMD_ID_STATUS
, wxTRANSLATE("Show short status information."),
840 wxTRANSLATE("Show connection status, current up/download speeds, etc.\n"), CMD_PARAM_NEVER
);
842 m_commands
.AddCommand(wxT("Statistics"), CMD_ID_STATTREE
, wxTRANSLATE("Show full statistics tree."),
843 wxTRANSLATE("Optionally, a number in the range 0-255 can be passed as an argument to this\n"
844 "command, which tells how many entries of the client version subtrees should be\n"
845 "shown. Passing 0 or omitting it means 'unlimited'.\n"
847 "Example: 'statistics 5' will show only the top 5 versions for each client type.\n"));
849 m_commands
.AddCommand(wxT("Shutdown"), CMD_ID_SHUTDOWN
, wxTRANSLATE("Shutdown aMule."),
850 wxTRANSLATE("Shutdown the remote running core (amule/amuled).\n"
851 "This will also shut down the text client, since it is unusable without a\n"
852 "running core.\n"), CMD_PARAM_NEVER
);
854 tmp
= m_commands
.AddCommand(wxT("Reload"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Reloads the given object."), wxEmptyString
, CMD_PARAM_NEVER
);
855 tmp
->AddCommand(wxT("Shared"), CMD_ID_RELOAD_SHARED
, wxTRANSLATE("Reloads shared files list."), wxEmptyString
, CMD_PARAM_NEVER
);
856 tmp
->AddCommand(wxT("IPFilter"), CMD_ID_RELOAD_IPFILTER
, wxTRANSLATE("Reloads IP Filter table from file."), wxEmptyString
, CMD_PARAM_NEVER
);
858 tmp
= m_commands
.AddCommand(wxT("Connect"), CMD_ID_CONNECT
, wxTRANSLATE("Connect to the network."),
859 wxTRANSLATE("This will connect to all networks that are enabled in Preferences.\n"
860 "You may also optionally specify a server address in IP:Port form, to connect to\n"
861 "that server only. The IP must be a dotted decimal IPv4 address,\n"
862 "or a resolvable DNS name."), CMD_PARAM_OPTIONAL
);
863 tmp
->AddCommand(wxT("ED2K"), CMD_ID_CONNECT_ED2K
, wxTRANSLATE("Connect to ED2K only."), wxEmptyString
, CMD_PARAM_NEVER
);
864 tmp
->AddCommand(wxT("Kad"), CMD_ID_CONNECT_KAD
, wxTRANSLATE("Connect to Kad only."), wxEmptyString
, CMD_PARAM_NEVER
);
866 tmp
= m_commands
.AddCommand(wxT("Disconnect"), CMD_ID_DISCONNECT
, wxTRANSLATE("Disconnect from the network."),
867 wxTRANSLATE("This will disconnect from all networks that are currently connected.\n"), CMD_PARAM_NEVER
);
868 tmp
->AddCommand(wxT("ED2K"), CMD_ID_DISCONNECT_ED2K
, wxTRANSLATE("Disconnect from ED2K only."), wxEmptyString
, CMD_PARAM_NEVER
);
869 tmp
->AddCommand(wxT("Kad"), CMD_ID_DISCONNECT_KAD
, wxTRANSLATE("Disconnect from Kad only."), wxEmptyString
, CMD_PARAM_NEVER
);
871 m_commands
.AddCommand(wxT("Add"), CMD_ID_ADDLINK
, wxTRANSLATE("Adds an ed2k or magnet link to core."),
872 wxTRANSLATE("The ed2k link to be added can be:\n"
873 "*) a file link (ed2k://|file|...), it will be added to the download queue,\n"
874 "*) a server link (ed2k://|server|...), it will be added to the server list,\n"
875 "*) or a serverlist link, in which case all servers in the list will be added to the\n"
878 "The magnet link must contain the ed2k hash and file length.\n"), CMD_PARAM_ALWAYS
);
880 tmp
= m_commands
.AddCommand(wxT("Set"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Set a preference value."),
881 wxEmptyString
, CMD_PARAM_NEVER
);
883 tmp2
= tmp
->AddCommand(wxT("IPFilter"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Set IPFilter preferences."), wxEmptyString
, CMD_PARAM_NEVER
);
884 tmp2
->AddCommand(wxT("On"), CMD_ID_SET_IPFILTER_ON
, wxTRANSLATE("Turn IP filtering on for both clients and servers."), wxEmptyString
, CMD_PARAM_NEVER
);
885 tmp2
->AddCommand(wxT("Off"), CMD_ID_SET_IPFILTER_OFF
, wxTRANSLATE("Turn IP filtering off for both clients and servers."), wxEmptyString
, CMD_PARAM_NEVER
);
886 tmp3
= tmp2
->AddCommand(wxT("Clients"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Enable/Disable IP filtering for clients."), wxEmptyString
, CMD_PARAM_NEVER
);
887 tmp3
->AddCommand(wxT("On"), CMD_ID_SET_IPFILTER_CLIENTS_ON
, wxTRANSLATE("Turn IP filtering on for clients."), wxEmptyString
, CMD_PARAM_NEVER
);
888 tmp3
->AddCommand(wxT("Off"), CMD_ID_SET_IPFILTER_CLIENTS_OFF
, wxTRANSLATE("Turn IP filtering off for clients."), wxEmptyString
, CMD_PARAM_NEVER
);
889 tmp3
= tmp2
->AddCommand(wxT("Servers"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Enable/Disable IP filtering for servers."), wxEmptyString
, CMD_PARAM_NEVER
);
890 tmp3
->AddCommand(wxT("On"), CMD_ID_SET_IPFILTER_SERVERS_ON
, wxTRANSLATE("Turn IP filtering on for servers."), wxEmptyString
, CMD_PARAM_NEVER
);
891 tmp3
->AddCommand(wxT("Off"), CMD_ID_SET_IPFILTER_SERVERS_OFF
, wxTRANSLATE("Turn IP filtering off for servers."), wxEmptyString
, CMD_PARAM_NEVER
);
892 tmp2
->AddCommand(wxT("Level"), CMD_ID_SET_IPFILTER_LEVEL
, wxTRANSLATE("Select IP filtering level."),
893 wxTRANSLATE("Valid filtering levels are in the range 0-255, and it's default (initial)\n"
894 "value is 127.\n"), CMD_PARAM_ALWAYS
);
896 tmp2
= tmp
->AddCommand(wxT("BwLimit"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Set bandwidth limits."),
897 wxTRANSLATE("The value given to these commands has to be in kilobytes/sec.\n"), CMD_PARAM_NEVER
);
898 tmp2
->AddCommand(wxT("Up"), CMD_ID_SET_BWLIMIT_UP
, wxTRANSLATE("Set upload bandwidth limit."),
899 wxT("The given value must be in kilobytes/sec.\n"), CMD_PARAM_ALWAYS
);
900 tmp2
->AddCommand(wxT("Down"), CMD_ID_SET_BWLIMIT_DOWN
, wxTRANSLATE("Set download bandwidth limit."),
901 wxT("The given value must be in kilobytes/sec.\n"), CMD_PARAM_ALWAYS
);
903 tmp
= m_commands
.AddCommand(wxT("Get"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Get and display a preference value."),
904 wxEmptyString
, CMD_PARAM_NEVER
);
906 tmp2
= tmp
->AddCommand(wxT("IPFilter"), CMD_ID_GET_IPFILTER
, wxTRANSLATE("Get IPFilter preferences."), wxEmptyString
, CMD_PARAM_NEVER
);
907 tmp3
= tmp2
->AddCommand(wxT("State"), CMD_ID_GET_IPFILTER_STATE
, wxTRANSLATE("Get IPFilter state for both clients and servers."), wxEmptyString
, CMD_PARAM_NEVER
);
908 tmp3
->AddCommand(wxT("Clients"), CMD_ID_GET_IPFILTER_STATE_CLIENTS
, wxTRANSLATE("Get IPFilter state for clients only."), wxEmptyString
, CMD_PARAM_NEVER
);
909 tmp3
->AddCommand(wxT("Servers"), CMD_ID_GET_IPFILTER_STATE_SERVERS
, wxTRANSLATE("Get IPFilter state for servers only."), wxEmptyString
, CMD_PARAM_NEVER
);
910 tmp2
->AddCommand(wxT("Level"), CMD_ID_GET_IPFILTER_LEVEL
, wxTRANSLATE("Get IPFilter level."), wxEmptyString
, CMD_PARAM_NEVER
);
912 tmp
->AddCommand(wxT("BwLimits"), CMD_ID_GET_BWLIMITS
, wxTRANSLATE("Get bandwidth limits."), wxEmptyString
, CMD_PARAM_NEVER
);
914 tmp
= m_commands
.AddCommand(wxT("Search"), CMD_ID_SEARCH
, wxTRANSLATE("Makes a search."),
915 wxTRANSLATE("A search type has to be specified by giving the type:\n"
919 "Example: 'search kad file' will execute a kad search for \"file\".\n"), CMD_PARAM_ALWAYS
);
920 tmp
->AddCommand(wxT("global"), CMD_ID_SEARCH_GLOBAL
, wxTRANSLATE("Executes a global search."), wxEmptyString
, CMD_PARAM_ALWAYS
);
921 tmp
->AddCommand(wxT("local"), CMD_ID_SEARCH_LOCAL
, wxTRANSLATE("Executes a local search"), wxEmptyString
, CMD_PARAM_ALWAYS
);
922 tmp
->AddCommand(wxT("kad"), CMD_ID_SEARCH_KAD
, wxTRANSLATE("Executes a kad search"), wxEmptyString
, CMD_PARAM_ALWAYS
);
924 m_commands
.AddCommand(wxT("Results"), CMD_ID_SEARCH_RESULTS
, wxTRANSLATE("Shows the results of the last search."),
925 wxTRANSLATE("Returns the results of the previous search.\n"), CMD_PARAM_NEVER
);
927 m_commands
.AddCommand(wxT("Progress"), CMD_ID_SEARCH_PROGRESS
, wxTRANSLATE("Shows the progress of a search."),
928 wxTRANSLATE("Shows the progress of a search.\n"), CMD_PARAM_NEVER
);
930 m_commands
.AddCommand(wxT("Download"), CMD_ID_DOWNLOAD
, wxTRANSLATE("Start downloading a file"),
931 wxTRANSLATE("The number of a file from the last search has to be given.\n"
932 "Example: 'download 12' will start to download the file with the number 12 of the previous search.\n"), CMD_PARAM_ALWAYS
);
936 // TODO: These commands below need implementation and/or rewrite!
939 m_commands
.AddCommand(wxT("Pause"), CMD_ID_PAUSE
, wxTRANSLATE("Pause download."),
940 wxEmptyString
, CMD_PARAM_ALWAYS
);
942 m_commands
.AddCommand(wxT("Resume"), CMD_ID_RESUME
, wxTRANSLATE("Resume download."),
943 wxEmptyString
, CMD_PARAM_ALWAYS
);
945 m_commands
.AddCommand(wxT("Cancel"), CMD_ID_CANCEL
, wxTRANSLATE("Cancel download."),
946 wxEmptyString
, CMD_PARAM_ALWAYS
);
948 tmp
= m_commands
.AddCommand(wxT("Priority"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Set download priority."),
949 wxTRANSLATE("Set priority of a download to Low, Normal, High or Auto.\n"), CMD_PARAM_ALWAYS
);
950 tmp
->AddCommand(wxT("Low"), CMD_ID_PRIORITY_LOW
, wxTRANSLATE("Set priority to low."), wxEmptyString
, CMD_PARAM_ALWAYS
);
951 tmp
->AddCommand(wxT("Normal"), CMD_ID_PRIORITY_NORMAL
, wxTRANSLATE("Set priority to normal."), wxEmptyString
, CMD_PARAM_ALWAYS
);
952 tmp
->AddCommand(wxT("High"), CMD_ID_PRIORITY_HIGH
, wxTRANSLATE("Set priority to high."), wxEmptyString
, CMD_PARAM_ALWAYS
);
953 tmp
->AddCommand(wxT("Auto"), CMD_ID_PRIORITY_AUTO
, wxTRANSLATE("Set priority to auto."), wxEmptyString
, CMD_PARAM_ALWAYS
);
955 tmp
= m_commands
.AddCommand(wxT("Show"), CMD_ERR_INCOMPLETE
, wxTRANSLATE("Show queues/lists."),
956 wxTRANSLATE("Shows upload/download queue, server list or shared files list.\n"), CMD_PARAM_NEVER
);
957 tmp
->AddCommand(wxT("UL"), CMD_ID_SHOW_UL
, wxTRANSLATE("Show upload queue."), wxEmptyString
, CMD_PARAM_NEVER
);
958 tmp
->AddCommand(wxT("DL"), CMD_ID_SHOW_DL
, wxTRANSLATE("Show download queue."), wxEmptyString
, CMD_PARAM_NEVER
);
959 tmp
->AddCommand(wxT("Log"), CMD_ID_SHOW_LOG
, wxTRANSLATE("Show log."), wxEmptyString
, CMD_PARAM_NEVER
);
960 tmp
->AddCommand(wxT("Servers"), CMD_ID_SHOW_SERVERS
, wxTRANSLATE("Show servers list."), wxEmptyString
, CMD_PARAM_NEVER
);
961 // tmp->AddCommand(wxT("Shared"), CMD_ID_SHOW_SHARED, wxTRANSLATE("Show shared files list."), wxEmptyString, CMD_PARAM_NEVER);
963 m_commands
.AddCommand(wxT("Reset"), CMD_ID_RESET_LOG
, wxTRANSLATE("Reset log."), wxEmptyString
, CMD_PARAM_NEVER
);
966 // Deprecated commands, kept for backwards compatibility only.
969 #define DEPRECATED(OLDCMD, ID, NEWCMD, PARAM) \
970 m_commands.AddCommand(wxT(OLDCMD), CMD_ID_##ID | CMD_DEPRECATED, CFormat(wxTRANSLATE("Deprecated command, now '%s'.")) % wxT(NEWCMD), \
971 CFormat(wxTRANSLATE("This is a deprecated command, and may be removed in the future.\n" \
972 "Use '%s' instead.\n")) % wxT(NEWCMD), CMD_PARAM_##PARAM)
974 DEPRECATED("Stats", STATUS
, "Status", NEVER
);
975 DEPRECATED("SetIPFilter", SET_IPFILTER
, "Set IPFilter", OPTIONAL
);
976 DEPRECATED("GetIPLevel", GET_IPFILTER_LEVEL
, "Get IPFilter Level", NEVER
);
977 DEPRECATED("SetIPLevel", SET_IPFILTER_LEVEL
, "Set IPFilter Level", ALWAYS
);
978 DEPRECATED("IPLevel", SET_IPFILTER_LEVEL
, "Get/Set IPFilter Level", OPTIONAL
);
979 DEPRECATED("Servers", SHOW_SERVERS
, "Show Servers", NEVER
);
980 DEPRECATED("GetBWLimits", GET_BWLIMITS
, "Get BwLimits", NEVER
);
981 DEPRECATED("SetUpBWLimit", SET_BWLIMIT_UP
, "Set BwLimit Up", ALWAYS
);
982 DEPRECATED("SetDownBWLimit", SET_BWLIMIT_DOWN
, "Set BwLimit Down", ALWAYS
);
985 int CamulecmdApp::OnRun()
987 ConnectAndRun(wxT("aMulecmd"), wxT(VERSION
));
990 // File_checked_for_headers