Bug Summary

File:rootdir/src/ExternalConnector.cpp
Warning:line 237, column 24
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ExternalConnector.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D USE_WX_EXTENSIONS -I /usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.2 -I /usr/include/wx-3.2 -D _FILE_OFFSET_BITS=64 -D WXUSINGDLL -D __WXGTK__ -D wxUSE_GUI=0 -I ./libs -I libs -I ./include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-register -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-14-142857-17216-1 -x c++ ExternalConnector.cpp
1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2004-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5//
6// Any parts of this program derived from the xMule, lMule or eMule project,
7// or contributed by third-party developers are copyrighted by their
8// respective authors.
9//
10// This program is free software; you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 2 of the License, or
13// (at your option) any later version.
14//
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
23//
24
25#include "ExternalConnector.h"
26#include "config.h" // Needed for VERSION and readline detection
27#include <common/Format.h> // Needed for CFormat
28#include <wx/tokenzr.h> // For wxStringTokenizer
29
30// For readline
31#ifdef HAVE_LIBREADLINE1
32 #if defined(HAVE_READLINE_READLINE_H1)
33 #include <readline/readline.h> // Do_not_auto_remove
34 #elif defined(HAVE_READLINE_H)
35 #include <readline.h> // Do_not_auto_remove
36 #endif /* !defined(HAVE_READLINE_H) */
37#endif /* HAVE_LIBREADLINE */
38
39// For history
40#ifdef HAVE_READLINE_HISTORY1
41 #if defined(HAVE_READLINE_HISTORY_H1)
42 #include <readline/history.h> // Do_not_auto_remove
43 #elif defined(HAVE_HISTORY_H)
44 #include <history.h> // Do_not_auto_remove
45 #endif /* defined(HAVE_READLINE_HISTORY_H) */
46#endif /* HAVE_READLINE_HISTORY */
47
48
49#include <ec/cpp/ECFileConfig.h> // Needed for CECFileConfig
50#include <common/MD5Sum.h>
51#include "OtherFunctions.h" // Needed for GetPassword()
52#include "MuleVersion.h" // Needed for GetMuleVersion()
53
54#ifdef _MSC_VER // silly warnings about deprecated functions
55#pragma warning(disable:4996)
56#endif
57
58//-------------------------------------------------------------------
59
60CaMuleExternalConnector* CCommandTree::m_app;
61
62CCommandTree::~CCommandTree()
63{
64 DeleteContents(m_subcommands);
65}
66
67
68CCommandTree* CCommandTree::AddCommand(CCommandTree* command)
69{
70 command->m_parent = this;
71 const wxString& cmd = command->m_command;
72 CmdPos_t it;
73 for (it = m_subcommands.begin(); it != m_subcommands.end(); ++it) {
74 if ((*it)->m_command > cmd) {
75 break;
76 }
77 }
78 m_subcommands.insert(it, command);
79 return command;
80}
81
82
83int CCommandTree::FindCommandId(const wxString& command, wxString& args, wxString& cmdstr) const
84{
85 wxString cmd = command.BeforeFirst(wxT(' ')L' ').Lower();
86 for (CmdPosConst_t it = m_subcommands.begin(); it != m_subcommands.end(); ++it) {
87 if ((*it)->m_command.Lower() == cmd) {
88 args = command.AfterFirst(wxT(' ')L' ').Trim(false);
89 return (*it)->FindCommandId(args, args, cmdstr);
90 }
91 }
92 cmdstr = GetFullCommand().Lower();
93 if (m_params == CMD_PARAM_ALWAYS && args.IsEmpty()) {
94 return CMD_ERR_MUST_HAVE_PARAM-6;
95 } else if (m_params == CMD_PARAM_NEVER && !args.IsEmpty()) {
96 return CMD_ERR_NO_PARAM-5;
97 } else {
98 if ((m_cmd_id >= 0) && (m_cmd_id & CMD_DEPRECATED0x1000)) {
99 m_app->Show(wxT('\n')L'\n' + m_verbose + wxT('\n')L'\n');
100 return m_cmd_id & ~CMD_DEPRECATED0x1000;
101 } else {
102 return m_cmd_id;
103 }
104 }
105}
106
107
108wxString CCommandTree::GetFullCommand() const
109{
110 wxString cmd = m_command;
111
112 const CCommandTree *parent = m_parent;
113 while (parent && parent->m_parent) {
114 cmd = parent->m_command + wxT(" ")L" " + cmd;
115 parent = parent->m_parent;
116 }
117
118 return cmd;
119}
120
121
122void CCommandTree::PrintHelpFor(const wxString& command) const
123{
124 wxString cmd = command.BeforeFirst(wxT(' ')L' ').Lower();
125 if (!cmd.IsEmpty()) {
126 for (CmdPosConst_t it = m_subcommands.begin(); it != m_subcommands.end(); ++it) {
127 if ((*it)->m_command.Lower() == cmd) {
128 (*it)->PrintHelpFor(command.AfterFirst(wxT(' ')L' ').Trim(false));
129 return;
130 }
131 }
132 if (m_parent) {
133 m_app->Show(CFormat(_("Unknown extension '%s' for the '%s' command.\n")wxGetTranslation(("Unknown extension '%s' for the '%s' command.\n"
))
) % command % GetFullCommand());
134 } else {
135 m_app->Show(CFormat(_("Unknown command '%s'.\n")wxGetTranslation(("Unknown command '%s'.\n"))) % command);
136 }
137 } else {
138 wxString fullcmd = GetFullCommand();
139 if (!fullcmd.IsEmpty()) {
140 m_app->Show(fullcmd.Upper() + wxT(": ")L": " + wxGetTranslation(m_short) + wxT("\n")L"\n");
141 if (!m_verbose.IsEmpty()) {
142 m_app->Show(wxT("\n")L"\n");
143 m_app->Show(wxGetTranslation(m_verbose));
144 }
145 }
146 if (m_params == CMD_PARAM_NEVER) {
147 m_app->Show(_("\nThis command cannot have an argument.\n")wxGetTranslation(("\nThis command cannot have an argument.\n"
))
);
148 } else if (m_params == CMD_PARAM_ALWAYS) {
149 m_app->Show(_("\nThis command must have an argument.\n")wxGetTranslation(("\nThis command must have an argument.\n")));
150 }
151 if (m_cmd_id == CMD_ERR_INCOMPLETE-8) {
152 m_app->Show(_("\nThis command is incomplete, you must use one of the extensions below.\n")wxGetTranslation(("\nThis command is incomplete, you must use one of the extensions below.\n"
))
);
153 }
154 if (!m_subcommands.empty()) {
155 CmdPosConst_t it;
156 int maxlen = 0;
157 if (m_parent) {
158 m_app->Show(_("\nAvailable extensions:\n")wxGetTranslation(("\nAvailable extensions:\n")));
159 } else {
160 m_app->Show(_("Available commands:\n")wxGetTranslation(("Available commands:\n")));
161 }
162 for (it = m_subcommands.begin(); it != m_subcommands.end(); ++it) {
163 if (!((*it)->m_cmd_id >= 0 && (*it)->m_cmd_id & CMD_DEPRECATED0x1000) || m_parent) {
164 int len = (*it)->m_command.Length();
165 if (len > maxlen) {
166 maxlen = len;
167 }
168 }
169 }
170 maxlen += 4;
171 for (it = m_subcommands.begin(); it != m_subcommands.end(); ++it) {
172 if (!((*it)->m_cmd_id >= 0 && (*it)->m_cmd_id & CMD_DEPRECATED0x1000) || m_parent) {
173 m_app->Show((*it)->m_command + wxString(wxT(' ')L' ', maxlen - (*it)->m_command.Length()) + wxGetTranslation((*it)->m_short) + wxT("\n")L"\n");
174 }
175 }
176 if (!m_parent) {
177 m_app->Show(CFormat(_("\nAll commands are case insensitive.\nType '%s <command>' to get detailed info on <command>.\n")wxGetTranslation(("\nAll commands are case insensitive.\nType '%s <command>' to get detailed info on <command>.\n"
))
) % wxT("help")L"help");
178 }
179 }
180 }
181 m_app->Show(wxT("\n")L"\n");
182}
183
184//-------------------------------------------------------------------
185
186#ifdef HAVE_LIBREADLINE1
187
188const CmdList_t* CCommandTree::GetSubCommandsFor(const wxString& command, bool mayRestart) const
189{
190 if (command.IsEmpty()) {
191 return &m_subcommands;
192 }
193
194 wxString cmd = command.BeforeFirst(wxT(' ')L' ').Lower();
195
196 if (mayRestart && cmd == wxT("help")L"help") {
197 return GetSubCommandsFor(command.AfterFirst(wxT(' ')L' '), false);
198 }
199
200 for (CmdPosConst_t it = m_subcommands.begin(); it != m_subcommands.end(); ++it) {
201 if ((*it)->m_command.Lower() == cmd) {
202 return (*it)->GetSubCommandsFor(command.AfterFirst(wxT(' ')L' ').Trim(false), mayRestart);
203 }
204 }
205
206 return NULL__null;
207}
208
209
210// Forward-declare the completion function to make sure it's declaration
211// matches the library requirements.
212rl_compentry_func_t command_completion;
213
214
215// File-scope pointer to the application's command set.
216static CCommandTree * theCommands;
217
218
219char *command_completion(const char *text, int state)
220{
221 static const CmdList_t* curCommands;
1
'curCommands' initialized to a null pointer value
222 static CmdPosConst_t nextCommand;
223
224 if (state == 0) {
2
Assuming 'state' is not equal to 0
3
Taking false branch
225 wxString lineBuffer(rl_line_buffer, *wxConvCurrent);
226 wxString prefix(lineBuffer.Left(rl_point).BeforeLast(wxT(' ')L' '));
227
228 curCommands = theCommands->GetSubCommandsFor(prefix);
229 if (curCommands) {
230 nextCommand = curCommands->begin();
231 } else {
232 return NULL__null;
233 }
234 }
235
236 wxString test(wxString(text, *wxConvCurrent).Lower());
237 while (nextCommand != curCommands->end()) {
4
Called C++ object pointer is null
238 wxString curTest = (*nextCommand)->GetCommand();
239 ++nextCommand;
240 if (curTest.Lower().StartsWith(test)) {
241 return strdup(static_cast<const char *>(unicode2char(curTest)));
242 }
243 }
244
245 return NULL__null;
246}
247
248
249#endif /* HAVE_LIBREADLINE */
250
251//-------------------------------------------------------------------
252
253CaMuleExternalConnector::CaMuleExternalConnector()
254 : m_configFile(NULL__null),
255 m_port(-1),
256 m_ZLIB(false),
257 m_KeepQuiet(false),
258 m_Verbose(false),
259 m_interactive(false),
260 m_commands(*this),
261 m_appname(NULL__null),
262 m_ECClient(NULL__null),
263 m_InputLine(NULL__null),
264 m_NeedsConfigSave(false),
265 m_locale(NULL__null),
266 m_strFullVersion(NULL__null),
267 m_strOSDescription(NULL__null)
268{
269 SetAppName(wxT("aMule")L"aMule"); // Do not change!
270}
271
272CaMuleExternalConnector::~CaMuleExternalConnector()
273{
274 delete m_configFile;
275 delete m_locale;
276 free(m_strFullVersion);
277 free(m_strOSDescription);
278}
279
280void CaMuleExternalConnector::OnInitCommandSet()
281{
282 m_commands.AddCommand(wxT("Quit")L"Quit", CMD_ID_QUIT-1, wxTRANSLATE("Exits from the application.")"Exits from the application.", wxEmptyString);
283 m_commands.AddCommand(wxT("Exit")L"Exit", CMD_ID_QUIT-1, wxTRANSLATE("Exits from the application.")"Exits from the application.", wxEmptyString);
284 m_commands.AddCommand(wxT("Help")L"Help", CMD_ID_HELP-2, wxTRANSLATE("Show help.")"Show help.",
285 /* TRANSLATORS:
286 Do not translate the word 'help', it is a command to the program! */
287 wxTRANSLATE("To get help on a command, type 'help <command>'.\nTo get the full command list type 'help'.\n")"To get help on a command, type 'help <command>'.\nTo get the full command list type 'help'.\n");
288}
289
290void CaMuleExternalConnector::Show(const wxString &s)
291{
292 if( !m_KeepQuiet ) {
293 printf("%s", (const char *)unicode2char(s));
294#ifdef __WINDOWS__
295 fflush(stdoutstdout);
296#endif
297 }
298}
299
300void CaMuleExternalConnector::ShowGreet()
301{
302 wxString text = GetGreetingTitle();
303 int len = text.Length();
304 Show(wxT('\n')L'\n' + wxString(wxT('-')L'-', 22 + len) + wxT('\n')L'\n');
305 Show(wxT('|')L'|' + wxString(wxT(' ')L' ', 10) + text + wxString(wxT(' ')L' ', 10) + wxT('|')L'|' + wxT('\n')L'\n');
306 Show(wxString(wxT('-')L'-', 22 + len) + wxT('\n')L'\n');
307 // Do not merge the line below, or translators could translate "Help"
308 Show(CFormat(_("\nUse '%s' for command list\n\n")wxGetTranslation(("\nUse '%s' for command list\n\n"))) % wxT("Help")L"Help");
309}
310
311void CaMuleExternalConnector::Process_Answer(const wxString& answer)
312{
313 wxStringTokenizer tokens(answer, wxT("\n")L"\n");
314 while ( tokens.HasMoreTokens() ) {
315 Show(wxT(" > ")L" > " + tokens.GetNextToken() + wxT("\n")L"\n");
316 }
317}
318
319bool CaMuleExternalConnector::Parse_Command(const wxString& buffer)
320{
321 wxString cmd;
322 wxStringTokenizer tokens(buffer);
323 while (tokens.HasMoreTokens()) {
324 cmd += tokens.GetNextToken() + wxT(' ')L' ';
325 }
326 cmd.Trim(false);
327 cmd.Trim(true);
328 if (cmd.IsEmpty()) {
329 return false;
330 }
331 int cmd_ID = GetIDFromString(cmd);
332 if ( cmd_ID >= 0 ) {
333 cmd_ID = ProcessCommand(cmd_ID);
334 }
335 wxString error;
336 switch (cmd_ID) {
337 case CMD_ID_HELP-2:
338 m_commands.PrintHelpFor(GetCmdArgs());
339 break;
340 case CMD_ERR_SYNTAX-3:
341 error = _("Syntax error!")wxGetTranslation(("Syntax error!"));
342 break;
343 case CMD_ERR_PROCESS_CMD-4:
344 Show(_("Error processing command - should never happen! Report bug, please\n")wxGetTranslation(("Error processing command - should never happen! Report bug, please\n"
))
);
345 break;
346 case CMD_ERR_NO_PARAM-5:
347 error = _("This command should not have any parameters.")wxGetTranslation(("This command should not have any parameters."
))
;
348 break;
349 case CMD_ERR_MUST_HAVE_PARAM-6:
350 error = _("This command must have a parameter.")wxGetTranslation(("This command must have a parameter."));
351 break;
352 case CMD_ERR_INVALID_ARG-7:
353 error = _("Invalid argument.")wxGetTranslation(("Invalid argument."));
354 break;
355 case CMD_ERR_INCOMPLETE-8:
356 error = _("This is an incomplete command.")wxGetTranslation(("This is an incomplete command."));
357 break;
358 }
359 if (!error.IsEmpty()) {
360 Show(error + wxT('\n')L'\n');
361 wxString helpStr(wxT("help")L"help");
362 if (!GetLastCmdStr().IsEmpty()) {
363 helpStr << wxT(' ')L' ' << GetLastCmdStr();
364 }
365 Show(CFormat(_("Type '%s' to get more help.\n")wxGetTranslation(("Type '%s' to get more help.\n"))) % helpStr);
366 }
367 return cmd_ID == CMD_ID_QUIT-1;
368}
369
370void CaMuleExternalConnector::GetCommand(const wxString &prompt, char* buffer, size_t buffer_size)
371{
372#ifdef HAVE_LIBREADLINE1
373 char *text = readline(unicode2char(prompt + wxT("$ ")L"$ "));
374 if (text && *text &&
375 (m_InputLine == 0 || strcmp(text,m_InputLine) != 0)) {
376 add_history (text);
377 }
378 if (m_InputLine)
379 free(m_InputLine);
380 m_InputLine = text;
381#else
382 Show(prompt + wxT("$ ")L"$ ");
383 const char *text = fgets(buffer, buffer_size, stdinstdin); // == buffer if ok, NULL if eof
384#endif /* HAVE_LIBREADLINE */
385 if ( text ) {
386 size_t len = strlen(text);
387 if (len > buffer_size - 1) {
388 len = buffer_size - 1;
389 }
390 if (buffer != text) {
391 strncpy(buffer, text, len);
392 }
393 buffer[len] = 0;
394 } else {
395 strncpy(buffer, "quit", buffer_size);
396 }
397}
398
399void CaMuleExternalConnector::TextShell(const wxString &prompt)
400{
401 char buffer[2048];
402 wxString buf;
403
404 bool The_End = false;
405 do {
406 GetCommand(prompt, buffer, sizeof buffer);
407 buf = char2unicode(buffer);
408 The_End = Parse_Command(buf);
409 } while ((!The_End) && (m_ECClient->IsSocketConnected()));
410}
411
412void CaMuleExternalConnector::ConnectAndRun(const wxString &ProgName, const wxString& ProgVersion)
413{
414 if (m_NeedsConfigSave) {
415 SaveConfigFile();
416 return;
417 }
418
419 #ifdef SVNDATE"rev. g3badf2c"
420 Show(CFormat(_("This is %s %s %s\n")wxGetTranslation(("This is %s %s %s\n"))) % wxString::FromAscii(m_appname) % wxT(VERSION)L"SVN" % wxT(SVNDATE)L"rev. g3badf2c");
421 #else
422 Show(CFormat(_("This is %s %s\n")wxGetTranslation(("This is %s %s\n"))) % wxString::FromAscii(m_appname) % wxT(VERSION)L"SVN");
423 #endif
424
425 // HostName, Port and Password
426 if ( m_password.IsEmpty() ) {
427 m_password = GetPassword(true);
428 // MD5 hash for an empty string, according to rfc1321.
429 if (m_password.Encode() == wxT("D41D8CD98F00B204E9800998ECF8427E")L"D41D8CD98F00B204E9800998ECF8427E") {
430 m_password.Clear();
431 }
432 }
433
434 if (!m_password.IsEmpty()) {
435
436 // Create the socket
437 Show(_("\nCreating client...\n")wxGetTranslation(("\nCreating client...\n")));
438 m_ECClient = new CRemoteConnect(NULL__null);
439 m_ECClient->SetCapabilities(m_ZLIB, true, false); // ZLIB, UTF8 numbers, notification
440
441 // ConnectToCore is blocking since m_ECClient was initialized with NULL
442 if (!m_ECClient->ConnectToCore(m_host, m_port, wxT("foobar")L"foobar", m_password.Encode(), ProgName, ProgVersion)) {
443 // no connection => close gracefully
444 if (!m_ECClient->GetServerReply().IsEmpty()) {
445 Show(CFormat(wxT("%s\n")L"%s\n") % m_ECClient->GetServerReply());
446 }
447 Show(CFormat(_("Connection Failed. Unable to connect to %s:%d\n")wxGetTranslation(("Connection Failed. Unable to connect to %s:%d\n"
))
) % m_host % m_port);
448 } else {
449 // Authenticate ourselves
450 // ConnectToCore() already authenticated for us.
451 //m_ECClient->ConnectionEstablished();
452 Show(m_ECClient->GetServerReply()+wxT("\n")L"\n");
453 if (m_ECClient->IsSocketConnected()) {
454 if (m_interactive) {
455 ShowGreet();
456 }
457 Pre_Shell();
458 TextShell(ProgName);
459 Post_Shell();
460 if (m_interactive) {
461 Show(CFormat(_("\nOk, exiting %s...\n")wxGetTranslation(("\nOk, exiting %s...\n"))) % ProgName);
462 }
463 }
464 }
465 m_ECClient->DestroySocket();
466 } else {
467 Show(_("Cannot connect with an empty password.\nYou must specify a password either in config file\nor on command-line, or enter one when asked.\n\nExiting...\n")wxGetTranslation(("Cannot connect with an empty password.\nYou must specify a password either in config file\nor on command-line, or enter one when asked.\n\nExiting...\n"
))
);
468 }
469}
470
471void CaMuleExternalConnector::OnInitCmdLine(wxCmdLineParser& parser, const char* appname)
472{
473 m_appname = appname;
474
475 parser.AddSwitch(wxEmptyString, wxT("help")L"help",
476 _("Show this help text.")wxGetTranslation(("Show this help text.")),
477 wxCMD_LINE_PARAM_OPTIONAL);
478 parser.AddOption(wxT("h")L"h", wxT("host")L"host",
479 _("Host where aMule is running. (default: localhost)")wxGetTranslation(("Host where aMule is running. (default: localhost)"
))
,
480 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
481 parser.AddOption(wxT("p")L"p", wxT("port")L"port",
482 _("aMule's port for External Connection. (default: 4712)")wxGetTranslation(("aMule's port for External Connection. (default: 4712)"
))
,
483 wxCMD_LINE_VAL_NUMBER, wxCMD_LINE_PARAM_OPTIONAL);
484 parser.AddOption(wxT("P")L"P", wxT("password")L"password",
485 _("External Connection password.")wxGetTranslation(("External Connection password.")),
486 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
487 parser.AddOption(wxT("f")L"f", wxT("config-file")L"config-file",
488 _("Read configuration from file.")wxGetTranslation(("Read configuration from file.")),
489 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
490 parser.AddSwitch(wxT("q")L"q", wxT("quiet")L"quiet",
491 _("Do not print any output to stdout.")wxGetTranslation(("Do not print any output to stdout.")),
492 wxCMD_LINE_PARAM_OPTIONAL);
493 parser.AddSwitch(wxT("v")L"v", wxT("verbose")L"verbose",
494 _("Be verbose - show also debug messages.")wxGetTranslation(("Be verbose - show also debug messages.")),
495 wxCMD_LINE_PARAM_OPTIONAL);
496 parser.AddOption(wxT("l")L"l", wxT("locale")L"locale",
497 _("Sets program locale (language).")wxGetTranslation(("Sets program locale (language).")),
498 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
499 parser.AddSwitch(wxT("w")L"w", wxT("write-config")L"write-config",
500 _("Write command line options to config file.")wxGetTranslation(("Write command line options to config file."
))
,
501 wxCMD_LINE_PARAM_OPTIONAL);
502 parser.AddOption(wxEmptyString, wxT("create-config-from")L"create-config-from",
503 _("Creates config file based on aMule's config file.")wxGetTranslation(("Creates config file based on aMule's config file."
))
,
504 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
505 parser.AddSwitch(wxEmptyString, wxT("version")L"version",
506 _("Print program version.")wxGetTranslation(("Print program version.")),
507 wxCMD_LINE_PARAM_OPTIONAL);
508}
509
510bool CaMuleExternalConnector::OnCmdLineParsed(wxCmdLineParser& parser)
511{
512 if (parser.Found(wxT("version")L"version")) {
513 printf("%s %s\n", m_appname, (const char *)unicode2char(GetMuleVersion()));
514 return false;
515 }
516
517 if (!parser.Found(wxT("config-file")L"config-file", &m_configFileName)) {
518 m_configFileName = wxT("remote.conf")L"remote.conf";
519 }
520 m_configDir = GetConfigDir(m_configFileName);
521 m_configFileName = m_configDir + m_configFileName;
522
523 wxString aMuleConfigFile;
524 if (parser.Found(wxT("create-config-from")L"create-config-from", &aMuleConfigFile)) {
525 aMuleConfigFile = FinalizeFilename(aMuleConfigFile);
526 if (!::wxFileExists(aMuleConfigFile)) {
527 fprintf(stderrstderr, "%s\n", (const char *)unicode2char(wxT("FATAL ERROR: File does not exist: ")L"FATAL ERROR: File does not exist: " + aMuleConfigFile));
528 exit(1);
529 }
530 CECFileConfig aMuleConfig(aMuleConfigFile);
531 LoadAmuleConfig(aMuleConfig);
532 SaveConfigFile();
533 m_configFile->Flush();
534 exit(0);
535 }
536
537 LoadConfigFile();
538
539 if ( !parser.Found(wxT("host")L"host", &m_host) ) {
540 if ( m_host.IsEmpty() ) {
541 m_host = wxT("localhost")L"localhost";
542 }
543 }
544
545 long port;
546 if (parser.Found(wxT("port")L"port", &port)) {
547 m_port = port;
548 }
549
550 wxString pass_plain;
551 if (parser.Found(wxT("password")L"password", &pass_plain)) {
552 if (!pass_plain.IsEmpty()) {
553 m_password.Decode(MD5Sum(pass_plain).GetHash());
554 } else {
555 m_password.Clear();
556 }
557 }
558
559 if (parser.Found(wxT("write-config")L"write-config")) {
560 m_NeedsConfigSave = true;
561 }
562
563 parser.Found(wxT("locale")L"locale", &m_language);
564
565 if (parser.Found(wxT("help")L"help")) {
566 parser.Usage();
567 return false;
568 }
569
570 m_KeepQuiet = parser.Found(wxT("quiet")L"quiet");
571 m_Verbose = parser.Found(wxT("verbose")L"verbose");
572
573 return true;
574}
575
576void CaMuleExternalConnector::LoadAmuleConfig(CECFileConfig& cfg)
577{
578 m_host = wxT("localhost")L"localhost";
579 m_port = cfg.Read(wxT("/ExternalConnect/ECPort")L"/ExternalConnect/ECPort", 4712l);
580 cfg.ReadHash(wxT("/ExternalConnect/ECPassword")L"/ExternalConnect/ECPassword", &m_password);
581 m_language = cfg.Read(wxT("/eMule/Language")L"/eMule/Language", wxEmptyString);
582}
583
584
585void CaMuleExternalConnector::LoadConfigFile()
586{
587 if (!m_configFile) {
588 m_configFile = new CECFileConfig(m_configFileName);
589 }
590 if (m_configFile) {
591 m_language = m_configFile->Read(wxT("/Locale")L"/Locale", wxEmptyString);
592 m_host = m_configFile->Read(wxT("/EC/Host")L"/EC/Host", wxEmptyString);
593 m_port = m_configFile->Read(wxT("/EC/Port")L"/EC/Port", 4712l);
594 m_configFile->ReadHash(wxT("/EC/Password")L"/EC/Password", &m_password);
595 m_ZLIB = m_configFile->Read(wxT("/EC/ZLIB")L"/EC/ZLIB", 1l) != 0;
596 }
597}
598
599void CaMuleExternalConnector::SaveConfigFile()
600{
601 if (!wxFileName::DirExists(m_configDir)) {
602 wxFileName::Mkdir(m_configDir);
603 }
604 if (!m_configFile) {
605 m_configFile = new CECFileConfig(m_configFileName);
606 }
607 if (m_configFile) {
608 m_configFile->Write(wxT("/Locale")L"/Locale", m_language);
609 m_configFile->Write(wxT("/EC/Host")L"/EC/Host", m_host);
610 m_configFile->Write(wxT("/EC/Port")L"/EC/Port", m_port);
611 m_configFile->WriteHash(wxT("/EC/Password")L"/EC/Password", m_password);
612 }
613}
614
615bool CaMuleExternalConnector::OnInit()
616{
617#ifndef __WINDOWS__
618 #if wxUSE_ON_FATAL_EXCEPTION1
619 // catch fatal exceptions
620 wxHandleFatalExceptions(true);
621 #endif
622#endif
623
624 // If we didn't know that OnInit is called only once when creating the
625 // object, it could cause a memory leak. The two pointers below should
626 // be free()'d before assigning the new value.
627 // cppcheck-suppress publicAllocationError
628 m_strFullVersion = strdup((const char *)unicode2char(GetMuleVersion()));
629 m_strOSDescription = strdup((const char *)unicode2char(wxGetOsDescription()));
630
631 // Handle uncaught exceptions
632 InstallMuleExceptionHandler();
633
634 bool retval = wxAppwxAppConsole::OnInit();
635 OnInitCommandSet();
636 InitCustomLanguages();
637 SetLocale(m_language);
638
639#ifdef HAVE_LIBREADLINE1
640 // Allow conditional parsing of the ~/.inputrc file.
641 //
642 // OnInitCmdLine() is called from wxApp::OnInit() above,
643 // thus m_appname is already set.
644 rl_readline_name = m_appname;
645
646 // Allow completion of our commands
647 theCommands = &m_commands;
648 rl_completion_entry_function = &command_completion;
649#endif
650
651 return retval;
652}
653
654wxString CaMuleExternalConnector::SetLocale(const wxString& language)
655{
656 if (!language.IsEmpty()) {
657 m_language = language;
658 if (m_locale) {
659 delete m_locale;
660 }
661 m_locale = new wxLocale;
662 InitLocale(*m_locale, StrLang2wx(language));
663 }
664
665 return m_locale == NULL__null ? wxString() : m_locale->GetCanonicalName();
666}
667
668
669#if wxUSE_ON_FATAL_EXCEPTION1
670// Gracefully handle fatal exceptions and print backtrace if possible
671void CaMuleExternalConnector::OnFatalException()
672{
673 /* Print the backtrace */
674 fprintf(stderrstderr, "\n--------------------------------------------------------------------------------\n");
675 fprintf(stderrstderr, "A fatal error has occurred and %s has crashed.\n", m_appname);
676 fprintf(stderrstderr, "Please assist us in fixing this problem by posting the backtrace below in our\n");
677 fprintf(stderrstderr, "'aMule Crashes' forum and include as much information as possible regarding the\n");
678 fprintf(stderrstderr, "circumstances of this crash. The forum is located here:\n");
679 fprintf(stderrstderr, " http://forum.amule.org/index.php?board=67.0\n");
680 fprintf(stderrstderr, "If possible, please try to generate a real backtrace of this crash:\n");
681 fprintf(stderrstderr, " http://wiki.amule.org/wiki/Backtraces\n\n");
682 fprintf(stderrstderr, "----------------------------=| BACKTRACE FOLLOWS: |=----------------------------\n");
683 fprintf(stderrstderr, "Current version is: %s %s\n", m_appname, m_strFullVersion);
684 fprintf(stderrstderr, "Running on: %s\n\n", m_strOSDescription);
685
686 print_backtrace(1); // 1 == skip this function.
687
688 fprintf(stderrstderr, "\n--------------------------------------------------------------------------------\n");
689}
690#endif
691
692#ifdef __WXDEBUG__
693void CaMuleExternalConnector::OnAssertFailure(const wxChar *file, int line, const wxChar *func, const wxChar *cond, const wxChar *msg)
694{
695#if !defined wxUSE_STACKWALKER1 || !wxUSE_STACKWALKER1
696 wxString errmsg = CFormat( wxT("%s:%s:%d: Assertion '%s' failed. %s")L"%s:%s:%d: Assertion '%s' failed. %s" ) % file % func % line % cond % ( msg ? msg : wxT("")L"" );
697
698 fprintf(stderrstderr, "Assertion failed: %s\n", (const char*)unicode2char(errmsg));
699
700 // Skip the function-calls directly related to the assert call.
701 fprintf(stderrstderr, "\nBacktrace follows:\n");
702 print_backtrace(3);
703 fprintf(stderrstderr, "\n");
704#else
705 wxAppwxAppConsole::OnAssertFailure(file, line, func, cond, msg);
706#endif
707}
708#endif
709// File_checked_for_headers