| File: | rootdir/src/ExternalConnector.cpp |
| Warning: | line 237, column 24 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | ||||
| 60 | CaMuleExternalConnector* CCommandTree::m_app; | |||
| 61 | ||||
| 62 | CCommandTree::~CCommandTree() | |||
| 63 | { | |||
| 64 | DeleteContents(m_subcommands); | |||
| 65 | } | |||
| 66 | ||||
| 67 | ||||
| 68 | CCommandTree* 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 | ||||
| 83 | int 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 | ||||
| 108 | wxString 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 | ||||
| 122 | void 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 | ||||
| 188 | const 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. | |||
| 212 | rl_compentry_func_t command_completion; | |||
| 213 | ||||
| 214 | ||||
| 215 | // File-scope pointer to the application's command set. | |||
| 216 | static CCommandTree * theCommands; | |||
| 217 | ||||
| 218 | ||||
| 219 | char *command_completion(const char *text, int state) | |||
| 220 | { | |||
| 221 | static const CmdList_t* curCommands; | |||
| ||||
| 222 | static CmdPosConst_t nextCommand; | |||
| 223 | ||||
| 224 | if (state == 0) { | |||
| 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()) { | |||
| ||||
| 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 | ||||
| 253 | CaMuleExternalConnector::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 | ||||
| 272 | CaMuleExternalConnector::~CaMuleExternalConnector() | |||
| 273 | { | |||
| 274 | delete m_configFile; | |||
| 275 | delete m_locale; | |||
| 276 | free(m_strFullVersion); | |||
| 277 | free(m_strOSDescription); | |||
| 278 | } | |||
| 279 | ||||
| 280 | void 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 | ||||
| 290 | void 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 | ||||
| 300 | void 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 | ||||
| 311 | void 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 | ||||
| 319 | bool 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 | ||||
| 370 | void 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 | ||||
| 399 | void 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 | ||||
| 412 | void CaMuleExternalConnector::ConnectAndRun(const wxString &ProgName, const wxString& ProgVersion) | |||
| 413 | { | |||
| 414 | if (m_NeedsConfigSave) { | |||
| 415 | SaveConfigFile(); | |||
| 416 | return; | |||
| 417 | } | |||
| 418 | ||||
| 419 | #ifdef SVNDATE"rev. gabd5271" | |||
| 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. gabd5271"); | |||
| 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 | ||||
| 471 | void 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 | ||||
| 510 | bool 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 | ||||
| 576 | void 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 | ||||
| 585 | void 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 | ||||
| 599 | void 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 | ||||
| 615 | bool 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 | ||||
| 654 | wxString 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 | |||
| 671 | void 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__ | |||
| 693 | void 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 |