Logo Search packages:      
Sourcecode: sbnc version File versions  Download package

bool CClientConnection::ProcessBncCommand ( const char *  Subcommand,
int  argc,
const char **  argv,
bool  NoticeUser 
) [private]

ProcessBncCommand

Processes a bouncer command (i.e. /sbnc <command> or /msg -sBNC <command>).

Parameters:
Subcommand the command's name
argc number of parameters for the command
argv arguments for the command
NoticeUser whether to send replies as notices

SENDUSER

Sends the specified text to the user.

Parameters:
Text the text

Definition at line 188 of file ClientConnection.cpp.

References CCore::AddAdditionalListener(), CUser::AddClientCertificate(), CCore::AddHostAllow(), command_s::Category, CLog::Clear(), CCore::CreateUser(), CCore::DebugImpulse(), CUser::FormatTime(), CCore::GetAdditionalListeners(), CUser::GetAutoModes(), CCore::GetBouncerVersion(), CIRCConnection::GetChannels(), CUser::GetClientCertificates(), CUser::GetClientConnectionMultiplexer(), CUser::GetConfig(), CUser::GetConfigChannels(), CIRCConnection::GetCurrentNick(), CCore::GetDefaultVHost(), CUser::GetDropModes(), CCore::GetHostAllows(), CUser::GetIRCConnection(), CUser::GetLastSeen(), CVector< Type >::GetLength(), CCore::GetLog(), CUser::GetLog(), CCore::GetMainListener(), CCore::GetMainSSLListener(), CCore::GetModules(), CCore::GetMotd(), CUser::GetNick(), CObject< CClientConnection, CUser >::GetOwner(), CConnection::GetPeerCertificate(), GetPeerName(), CUser::GetPrimaryClientConnection(), CUser::GetRealname(), CConnection::GetRecvqSize(), CConnection::GetSendqSize(), CIRCConnection::GetServer(), CCore::GetUser(), CUser::GetUsername(), CCore::GetUsers(), CCore::GlobalNotice(), command_s::HelpText, CUser::IsAdmin(), CLog::IsEmpty(), CUser::IsLocked(), CConnection::IsSSL(), CCore::IsValidUsername(), CIRCConnection::Kill(), Kill(), CCore::LoadModule(), CUser::Lock(), CCore::Log(), m_CommandList, CUser::MarkQuitted(), hash_t< Type >::Name, ParseLine(), CLog::PlayToUser(), CCore::RemoveAdditionalListener(), CUser::RemoveClientCertificate(), CCore::RemoveHostAllow(), CCore::RemoveUser(), CUser::ScheduleReconnect(), CUser::SetAdmin(), CUser::SetAppendTimestamp(), CUser::SetAutoModes(), CUser::SetAwayMessage(), CUser::SetAwayNick(), CUser::SetAwayText(), CUser::SetConfigChannels(), CCore::SetDefaultVHost(), CUser::SetDropModes(), CUser::SetGmtOffset(), CUser::SetIPv6(), CUser::SetIRCConnection(), CCore::SetMotd(), CUser::SetPassword(), CUser::SetPort(), CUser::SetRealname(), CUser::SetServer(), CUser::SetServerPassword(), CUser::SetSSL(), CUser::SetSuspendReason(), CUser::SetSystemNotices(), CUser::SetUseQuitReason(), CUser::SetVHost(), CCore::Shutdown(), CUser::Simulate(), CCore::UnloadModule(), CUser::Unlock(), hash_t< Type >::Value, and CConnection::WriteLine().

Referenced by ParseLineArgV().

                                                                                                              {
      char *Out;
      CUser *targUser = GetOwner();
      const CVector<CModule *> *Modules;
      bool latchedRetVal = true;

      Modules = g_Bouncer->GetModules();

/**
 * SENDUSER
 *
 * Sends the specified text to the user.
 *
 * @param Text the text
 */
#define SENDUSER(Text) \
      do { \
            if (NoticeUser) { \
                  RealNotice(Text); \
            } else { \
                  Privmsg(Text); \
            } \
      } while (0)

      if (argc < 1) {
            if (NoticeUser) {
                  SENDUSER("You need to specify a command. Try /sbnc help");
            } else {
                  SENDUSER("You need to specify a command. Try /msg -sBNC help");
            }

            return false;
      }

      if (strcasecmp(Subcommand, "help") == 0) {
            if (argc <= 1) {
                  SENDUSER("--The following commands are available to you--");
                  SENDUSER("--Used as '/sbnc <command>', or '/msg -sbnc <command>'");
            }

            FlushCommands(&m_CommandList);

            if (GetOwner()->IsAdmin()) {
                  AddCommand(&m_CommandList, "adduser", "Admin", "creates a new user",
                        "Syntax: adduser <username> [password]\nCreates a new user.");
                  AddCommand(&m_CommandList, "deluser", "Admin", "removes a user",
                        "Syntax: deluser <username>\nDeletes a user.");
                  AddCommand(&m_CommandList, "resetpass", "Admin", "sets a user's password",
                        "Syntax: resetpass <user> <password>\nResets another user's password.");
                  AddCommand(&m_CommandList, "who", "Admin", "shows users",
                        "Syntax: who\nShows a list of all users.\nFlags (which are displayed in front of the username):\n"
                        "@ user is an admin\n* user is currently logged in\n! user is suspended");
                  AddCommand(&m_CommandList, "admin", "Admin", "gives someone admin privileges",
                        "Syntax: admin <username>\nGives admin privileges to a user.");
                  AddCommand(&m_CommandList, "unadmin", "Admin", "removes someone's admin privileges",
                        "Syntax: unadmin <username>\nRemoves someone's admin privileges.");
                  AddCommand(&m_CommandList, "suspend", "Admin", "suspends a user",
                        "Syntax: suspend <username> [reason]\nSuspends an account. An optional reason can be specified.");
                  AddCommand(&m_CommandList, "unsuspend", "Admin", "unsuspends a user",
                        "Syntax: unsuspend <username>\nRemoves a suspension from the specified account.");
                  AddCommand(&m_CommandList, "lsmod", "Admin", "lists loaded modules",
                        "Syntax: lsmod\nLists all currently loaded modules.");
                  AddCommand(&m_CommandList, "insmod", "Admin", "loads a module",
                        "Syntax: insmod <filename>\nLoads a module.");
                  AddCommand(&m_CommandList, "rmmod", "Admin", "unloads a module",
                        "Syntax: rmmod <index>\nUnloads a module. Use the \"lsmod\" command to view a list of loaded modules.");
                  AddCommand(&m_CommandList, "simul", "Admin", "simulates a command on another user's connection",
                        "Syntax: simul <username> <command>\nExecutes a command in another user's context.");
                  AddCommand(&m_CommandList, "global", "Admin", "sends a global notice to all bouncer users",
                        "Syntax: global <text>\nSends a notice to all currently connected users.");
                  AddCommand(&m_CommandList, "kill", "Admin", "disconnects a user from the bouncer",
                        "Syntax: kill <username>\nDisconnects a user from the bouncer.");
                  AddCommand(&m_CommandList, "disconnect", "Admin", "disconnects a user from the irc server",
                        "Syntax: disconnect [username]\nDisconnects a user from the IRC server which he is currently connected to."
                        " If you don't specify a username, your own IRC connection will be closed.");
                  AddCommand(&m_CommandList, "playmainlog", "Admin", "plays the bouncer's log",
                        "Syntax: playmainlog\nDisplays the bouncer's log.");
                  AddCommand(&m_CommandList, "erasemainlog", "Admin", "erases the bouncer's log",
                        "Syntax: erasemainlog\nErases the bouncer's log.");
                  AddCommand(&m_CommandList, "gvhost", "Admin", "sets the default/global vhost",
                        "Syntax: gvhost <host>\nSets the bouncer's default vhost.");
                  AddCommand(&m_CommandList, "motd", "Admin", "sets the bouncer's motd",
                        "Syntax: motd [text]\nShows or modifies the motd.");
                  AddCommand(&m_CommandList, "die", "Admin", "terminates the bouncer",
                        "Syntax: die\nTerminates the bouncer.");
                  AddCommand(&m_CommandList, "hosts", "Admin", "lists all hostmasks, which are permitted to use this bouncer",
                        "Syntax: hosts\nLists all hosts which are permitted to use this bouncer.");
                  AddCommand(&m_CommandList, "hostadd", "Admin", "adds a hostmask",
                        "Syntax: hostadd <host>\nAdds a host to the bouncer's hostlist. E.g. *.tiscali.de");
                  AddCommand(&m_CommandList, "hostdel", "Admin", "removes a hostmask",
                        "Syntax: hostdel <host>\nRemoves a host from the bouncer's hostlist.");
                  AddCommand(&m_CommandList, "addlistener", "Admin", "creates an additional listener",
#ifdef USESSL
                        "Syntax: addlistener <port> [address] [ssl]\nCreates an additional listener which can be used by clients.");
#else
                        "Syntax: addlistener <port> [address]\nCreates an additional listener which can be used by clients.");
#endif

                  AddCommand(&m_CommandList, "dellistener", "Admin", "removes a listener",
                        "Syntax: dellistener <port>\nRemoves a listener.");
                  AddCommand(&m_CommandList, "listeners", "Admin", "lists all listeners",
                        "Syntax: listeners\nLists all listeners.");
            }

            AddCommand(&m_CommandList, "read", "User", "plays your message log",
                  "Syntax: read\nDisplays your private log.");
            AddCommand(&m_CommandList, "erase", "User", "erases your message log",
                  "Syntax: erase\nErases your private log.");
            AddCommand(&m_CommandList, "set", "User", "sets configurable options for your user",
                  "Syntax: set [option] [value]\nDisplays or changes configurable options for your user.");
            AddCommand(&m_CommandList, "unset", "User", "restores the default value of an option",
                  "Syntax: unset <option>\nRestores the default value of an option.");
            AddCommand(&m_CommandList, "jump", "User", "reconnects to the irc server",
                  "Syntax: jump\nReconnects to the irc server.");
            AddCommand(&m_CommandList, "partall", "User", "parts all channels and tells shroudBNC not to rejoin them when you reconnect to a server",
                  "Syntax: partall\nParts all channels and tells shroudBNC not to rejoin any channels when you reconnect to a"
                  " server.\nThis might be useful if you get disconnected due to an \"Max sendq exceeded\" error.");
            if (!GetOwner()->IsAdmin()) {
                  AddCommand(&m_CommandList, "disconnect", "User", "disconnects a user from the irc server",
                        "Syntax: disconnect\nDisconnects you from the irc server.");
            }
#ifdef USESSL
            AddCommand(&m_CommandList, "savecert", "User", "saves your current client certificate for use with public key authentication",
                  "Syntax: savecert\nSaves your current client certificate for use with public key authentication.\n"
                  "Once you have saved your certificate you can use it for logging in without a password.");
            AddCommand(&m_CommandList, "delcert", "User", "removes a certificate",
                  "Syntax: delcert <id>\nRemoves the specified certificate.");
            AddCommand(&m_CommandList, "showcert", "User", "shows information about your certificates",
                  "Syntax: showcert\nShows a list of certificates which can be used for logging in.");
#endif

            if (GetOwner()->IsAdmin()) {
                  AddCommand(&m_CommandList, "status", "User", "tells you the current status",
                        "Syntax: status\nDisplays information about your user. This command is used for debugging.");
            }

            AddCommand(&m_CommandList, "help", "User", "displays a list of commands or information about individual commands",
                  "Syntax: help [command]\nDisplays a list of commands or information about individual commands.");
      }

      for (unsigned int i = 0; i < Modules->GetLength(); i++) {
            if ((*Modules)[i]->InterceptClientCommand(this, Subcommand, argc, argv, NoticeUser)) {
                  latchedRetVal = false;
            }
      }

      if (strcasecmp(Subcommand, "help") == 0) {
            if (argc <= 1) {
                  // show help
                  hash_t<command_t *> *Hash;
                  hash_t<command_t *> *CommandList;
                  int i = 0;
                  size_t Align = 0, Len;

                  CommandList = (hash_t<command_t *> *)malloc(sizeof(hash_t<command_t *>) * m_CommandList->GetLength());

                  while ((Hash = m_CommandList->Iterate(i++)) != NULL) {
                        CommandList[i - 1] = *Hash;

                        Len = strlen(Hash->Name);

                        if (Len > Align) {
                              Align = Len;
                        }
                  }

                  qsort(CommandList, m_CommandList->GetLength(), sizeof(hash_t<command_t *>), CmpCommandT);

                  char *Category = NULL;
                  char *Format;

                  asprintf(&Format, "%%-%ds - %%s", Align);

                  for (unsigned int i = 0; i < m_CommandList->GetLength(); i++) {
                        if (Category == NULL || strcasecmp(CommandList[i].Value->Category, Category) != 0) {
                              if (Category) {
                                    SENDUSER("--");
                              }

                              Category = CommandList[i].Value->Category;

                              asprintf(&Out, "%s commands", Category);
                              SENDUSER(Out);
                              free(Out);
                        }

                        asprintf(&Out, Format, CommandList[i].Name, CommandList[i].Value->Description);
                        SENDUSER(Out);
                        free(Out);
                  }

                  free(Format);
                  free(CommandList);

                  SENDUSER("End of HELP.");
            } else {
                  command_t *Command = m_CommandList->Get(argv[1]);

                  if (Command == NULL) {
                        SENDUSER("There is no such command.");
                  } else if (Command && Command->HelpText == NULL) {
                        SENDUSER("No help is available for this command.");
                  } else {
                        char *Help = strdup(Command->HelpText);
                        char *HelpBase = Help;

                        while (true) {
                              char *NextLine = strstr(Help, "\n");

                              if (NextLine) {
                                    NextLine[0] = '\0';
                                    NextLine++;
                              }

                              SENDUSER(Help);

                              if (NextLine == NULL) {
                                    break;
                              } else {
                                    Help = NextLine;
                              }
                        }

                        free(HelpBase);
                  }
            }

            FlushCommands(&m_CommandList);

            return false;
      }

      if (!latchedRetVal) {
            return false;
      }

      if (strcasecmp(Subcommand, "lsmod") == 0 && GetOwner()->IsAdmin()) {
            for (unsigned int i = 0; i < Modules->GetLength(); i++) {
                  asprintf(&Out, "%d: %s", i + 1, (*Modules)[i]->GetFilename());

                  CHECK_ALLOC_RESULT(Out, asprintf) {
                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  SENDUSER(Out);
                  free(Out);
            }

            SENDUSER("End of MODULES.");

            return false;
      } else if (strcasecmp(Subcommand, "insmod") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: INSMOD module-path");
                  return false;
            }

            RESULT<CModule *> ModuleResult = g_Bouncer->LoadModule(argv[1]);

            if (!IsError(ModuleResult)) {
                  SENDUSER("Module was successfully loaded.");
            } else {
                  asprintf(&Out, "Module could not be loaded: %s", GETDESCRIPTION(ModuleResult));

                  CHECK_ALLOC_RESULT(Out, asprintf) {
                        SENDUSER("Module could not be loaded.");

                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  SENDUSER(Out);

                  free(Out);
            }

            return false;
      } else if (strcasecmp(Subcommand, "rmmod") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: RMMOD module-id");
                  return false;
            }

            unsigned int Index = atoi(argv[1]);

            if (Index == 0 || Index > Modules->GetLength()) {
                  SENDUSER("There is no such module.");
            } else {
                  CModule *Module = (*Modules)[Index - 1];

                  if (g_Bouncer->UnloadModule(Module)) {
                        SENDUSER("Done.");
                  } else {
                        SENDUSER("Failed to unload this module.");
                  }
            }

            return false;
      } else if (strcasecmp(Subcommand, "unset") == 0) {
            if (argc < 2) {
                  SENDUSER("Syntax: unset option");
            } else {
                  if (NoticeUser) {
                        asprintf(&Out, "SBNC SET %s :", argv[1]);
                  } else {
                        asprintf(&Out, "PRIVMSG -sBNC :SET %s :", argv[1]);
                  }

                  CHECK_ALLOC_RESULT(Out, asprintf) {} else {
                        ParseLine(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            }

            return false;
      } else if (strcasecmp(Subcommand, "set") == 0) {
            CConfig *Config = GetOwner()->GetConfig();

            if (argc < 3) {
                  SENDUSER("Configurable settings:");
                  SENDUSER("--");

                  SENDUSER("password - Set");

                  asprintf(&Out, "vhost - %s", GetOwner()->GetVHost() ? GetOwner()->GetVHost() : "Default");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  if (GetOwner()->GetServer() != NULL) {
                        asprintf(&Out, "server - %s:%d", GetOwner()->GetServer(), GetOwner()->GetPort());
                  } else {
                        Out = strdup("server - Not set");
                  }
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "serverpass - %s", GetOwner()->GetServerPassword() ? "Set" : "Not set");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "realname - %s", GetOwner()->GetRealname());
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "awaynick - %s", GetOwner()->GetAwayNick() ? GetOwner()->GetAwayNick() : "Not set");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "away - %s", GetOwner()->GetAwayText() ? GetOwner()->GetAwayText() : "Not set");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "awaymessage - %s", GetOwner()->GetAwayMessage() ? GetOwner()->GetAwayMessage() : "Not set");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "appendtimestamp - %s", GetOwner()->GetAppendTimestamp() ? "On" : "Off");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "usequitasaway - %s", GetOwner()->GetUseQuitReason() ? "On" : "Off");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

#ifdef USESSL
                  asprintf(&Out, "ssl - %s", GetOwner()->GetSSL() ? "On" : "Off");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
#endif

#ifdef IPV6
                  asprintf(&Out, "ipv6 - %s", GetOwner()->GetIPv6() ? "On" : "Off");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
#endif

                  asprintf(&Out, "timezone - %s%d", (GetOwner()->GetGmtOffset() > 0) ? "+" : "", GetOwner()->GetGmtOffset());
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  const char *AutoModes = GetOwner()->GetAutoModes();
                  bool ValidAutoModes = AutoModes && *AutoModes;
                  const char *DropModes = GetOwner()->GetDropModes();
                  bool ValidDropModes = DropModes && *DropModes;

                  const char *AutoModesPrefix = "+", *DropModesPrefix = "-";

                  if (!ValidAutoModes || (AutoModes && (*AutoModes == '+' || *AutoModes == '-'))) {
                        AutoModesPrefix = "";
                  }

                  if (!ValidDropModes || (DropModes && (*DropModes == '-' || *DropModes == '+'))) {
                        DropModesPrefix = "";
                  }

                  asprintf(&Out, "automodes - %s%s", AutoModesPrefix, ValidAutoModes ? AutoModes : "Not set");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  asprintf(&Out, "dropmodes - %s%s", DropModesPrefix, ValidDropModes ? DropModes : "Not set");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  if (GetOwner()->IsAdmin()) {
                        asprintf(&Out, "sysnotices - %s", GetOwner()->GetSystemNotices() ? "On" : "Off");
                        CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                              SENDUSER(Out);
                              free(Out);
                        } CHECK_ALLOC_RESULT_END;
                  }
            } else {
                  if (strcasecmp(argv[1], "server") == 0) {
                        if (argc > 3) {
                              GetOwner()->SetPort(atoi(argv[3]));
                              GetOwner()->SetServer(argv[2]);
                        } else if (argc > 2) {
                              // the order of the SetServer/SetPort had some importance
                              // i wonder what it was... hm
                              if (strlen(argv[2]) == 0) {
                                    GetOwner()->SetServer(NULL);
                                    GetOwner()->SetPort(6667);
                              } else {
                                    char *ServerStr = NULL;
                                    const char *PortStr = strchr(argv[2], ':');
                                    unsigned int Port = 6667;

                                    if (PortStr != NULL) {
                                          PortStr++;

                                          Port = atoi(PortStr);

                                          if (Port == 0) {
                                                Port = 6667;
                                          }

                                          ServerStr = strdup(argv[2]);

                                          if (ServerStr != NULL) {
                                                ServerStr[PortStr - argv[2] - 1] = '\0';
                                          }
                                    }

                                    GetOwner()->SetPort(Port);
                                    GetOwner()->SetServer((ServerStr != NULL) ? ServerStr : argv[2]);
                                    
                                    free(ServerStr);
                              }
                        } else {
                              SENDUSER("Syntax: /sbnc set server host port");

                              return false;
                        }
                  } else if (strcasecmp(argv[1], "realname") == 0) {
                        ArgRejoinArray(argv, 2);
                        GetOwner()->SetRealname(argv[2]);
                  } else if (strcasecmp(argv[1], "awaynick") == 0) {
                        GetOwner()->SetAwayNick(argv[2]);
                  } else if (strcasecmp(argv[1], "away") == 0) {
                        ArgRejoinArray(argv, 2);
                        GetOwner()->SetAwayText(argv[2]);
                  } else if (strcasecmp(argv[1], "awaymessage") == 0) {
                        ArgRejoinArray(argv, 2);
                        GetOwner()->SetAwayMessage(argv[2]);
                  } else if (strcasecmp(argv[1], "vhost") == 0) {
                        GetOwner()->SetVHost(argv[2]);
                  } else if (strcasecmp(argv[1], "serverpass") == 0) {
                        GetOwner()->SetServerPassword(argv[2]);
                  } else if (strcasecmp(argv[1], "password") == 0) {
                        if (strlen(argv[2]) < 6 || argc > 3 || strchr(argv[2], ':') != NULL) {
                              SENDUSER("Your password is too short or contains invalid characters.");
                              return false;
                        } else {
                              GetOwner()->SetPassword(argv[2]);
                        }
                  } else if (strcasecmp(argv[1], "appendtimestamp") == 0) {
                        if (strcasecmp(argv[2], "on") == 0) {
                              GetOwner()->SetAppendTimestamp(true);
                        } else if (strcasecmp(argv[2], "off") == 0) {
                              GetOwner()->SetAppendTimestamp(false);
                        } else {
                              SENDUSER("Value must be either 'on' or 'off'.");

                              return false;
                        }
                  } else if (strcasecmp(argv[1], "usequitasaway") == 0) {
                        if (strcasecmp(argv[2], "on") == 0) {
                              GetOwner()->SetUseQuitReason(true);
                        } else if (strcasecmp(argv[2], "off") == 0) {
                              GetOwner()->SetUseQuitReason(false);
                        } else {
                              SENDUSER("Value must be either 'on' or 'off'.");

                              return false;
                        }
                  } else if (strcasecmp(argv[1], "automodes") == 0) {
                        ArgRejoinArray(argv, 2);
                        GetOwner()->SetAutoModes(argv[2]);
                  } else if (strcasecmp(argv[1], "dropmodes") == 0) {
                        ArgRejoinArray(argv, 2);
                        GetOwner()->SetDropModes(argv[2]);
                  } else if (strcasecmp(argv[1], "ssl") == 0) {
                        if (strcasecmp(argv[2], "on") == 0) {
                              GetOwner()->SetSSL(true);
                        } else if (strcasecmp(argv[2], "off") == 0) {
                              GetOwner()->SetSSL(false);
                        } else {
                              SENDUSER("Value must be either 'on' or 'off'.");

                              return false;
                        }
#ifdef IPV6
                  } else if (strcasecmp(argv[1], "ipv6") == 0) {
                        if (strcasecmp(argv[2], "on") == 0) {
                              SENDUSER("Please keep in mind that IPv6 will only work if your server actually has IPv6 connectivity.");

                              GetOwner()->SetIPv6(true);
                        } else if (strcasecmp(argv[2], "off") == 0) {
                              GetOwner()->SetIPv6(false);
                        } else {
                              SENDUSER("Value must be either 'on' or 'off'.");

                              return false;
                        }
#endif
                  } else if (strcasecmp(argv[1], "timezone") == 0) {
                        GetOwner()->SetGmtOffset(atoi(argv[2]));
                  } else if (strcasecmp(argv[1], "sysnotices") == 0) {
                        if (strcasecmp(argv[2], "on") == 0) {
                              GetOwner()->SetSystemNotices(true);
                        } else if (strcasecmp(argv[2], "off") == 0) {
                              GetOwner()->SetSystemNotices(false);
                        } else {
                              SENDUSER("Value must be either 'on' or 'off'.");

                              return false;
                        }
                  } else {
                        SENDUSER("Unknown setting.");
                        return false;
                  }

                  SENDUSER("Done.");
            }

            return false;
#ifdef USESSL
      } else if (strcasecmp(Subcommand, "savecert") == 0) {
            if (!IsSSL()) {
                  SENDUSER("Error: You are not using an SSL-encrypted connection.");
            } else if (GetPeerCertificate() == NULL) {
                  SENDUSER("Error: You are not using a client certificate.");
            } else {
                  GetOwner()->AddClientCertificate(GetPeerCertificate());

                  SENDUSER("Your certificate was stored and will be used for public key authentication.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "showcert") == 0) {
            int i = 0;
            char Buffer[300];
            const CVector<X509 *> *Certificates;
            X509_NAME *name;
            bool First = true;

            Certificates = GetOwner()->GetClientCertificates();

            for (unsigned int i = 0; i < Certificates->GetLength(); i++) {
                  X509 *Certificate = (*Certificates)[i];

                  if (First == false) {
                        SENDUSER("---");
                  } else {
                        First = false;
                  }

                  asprintf(&Out, "Client Certificate #%d", i + 1);
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  name = X509_get_issuer_name(Certificate);
                  X509_NAME_oneline(name, Buffer, sizeof(Buffer));

                  asprintf(&Out, "issuer: %s", Buffer);
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  name = X509_get_subject_name(Certificate);
                  X509_NAME_oneline(name, Buffer, sizeof(Buffer));

                  asprintf(&Out, "subject: %s", Buffer);
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            }

            SENDUSER("End of CERTIFICATES.");

            return false;
      } else if (strcasecmp(Subcommand, "delcert") == 0) {
            unsigned int id;

            if (argc < 2) {
                  SENDUSER("Syntax: delcert ID");
                  
                  return false;
            }

            id = atoi(argv[1]);

            X509 *Certificate;
            const CVector<X509 *> *Certificates = GetOwner()->GetClientCertificates();

            if (id == 0 || id > Certificates->GetLength()) {
                  Certificate = NULL;
            } else {
                  Certificate = (*Certificates)[id - 1];
            }

            if (Certificate != NULL) {
                  if (GetOwner()->RemoveClientCertificate(Certificate)) {
                        SENDUSER("Done.");
                  } else {
                        SENDUSER("An error occured while removing the certificate.");
                  }
            } else {
                  SENDUSER("The ID you specified is not valid. Use the SHOWCERT command to get a list of valid IDs.");
            }

            return false;
#endif
      } else if (strcasecmp(Subcommand, "die") == 0 && GetOwner()->IsAdmin()) {
            g_Bouncer->Log("Shutdown requested by %s", GetOwner()->GetUsername());
            g_Bouncer->Shutdown();

            return false;
      } else if (strcasecmp(Subcommand, "adduser") == 0 && GetOwner()->IsAdmin()) {
            const char *Password;

            if (argc < 2) {
                  SENDUSER("Syntax: ADDUSER username [password]");
                  return false;
            } else if (argc < 3) {
                  char RandomPassword[10];
                  const char RandomPasswordChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

                  RandomPassword[9] = '\0';

                  for (unsigned int i = 0; i < 9; i++) {
                        RandomPassword[i] = RandomPasswordChars[rand() % (sizeof(RandomPasswordChars) - 1)];
                  }

                  Password = RandomPassword;
            } else {
                  Password = argv[2];
            }

            if (g_Bouncer->GetUser(argv[1]) != NULL) {
                  SENDUSER("The specified username is already in use.");

                  return false;
            }

            if (!g_Bouncer->IsValidUsername(argv[1])) {
                  SENDUSER("Could not create user: The username must be alpha-numeric.");

                  return false;
            }

            g_Bouncer->CreateUser(argv[1], Password);

            if (argc < 3) {
                  asprintf(&Out, "The new user's password is \"%s\".", Password);

                  CHECK_ALLOC_RESULT(Out, asprintf) {
                        return false;
                  } CHECK_ALLOC_RESULT_END;

                  SENDUSER(Out);

                  free(Out);
            }

            SENDUSER("Done.");

            return false;
      } else if (strcasecmp(Subcommand, "deluser") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: DELUSER username");
                  return false;
            }

            if (strcasecmp(argv[1], GetOwner()->GetUsername()) == 0) {
                  SENDUSER("You cannot remove yourself.");

                  return false;
            }

            RESULT<bool> Result = g_Bouncer->RemoveUser(argv[1]);

            if (IsError(Result)) {
                  SENDUSER(GETDESCRIPTION(Result));
            } else {
                  SENDUSER("Done.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "simul") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 3) {
                  SENDUSER("Syntax: SIMUL username :command");
                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);

            if (User) {
                  ArgRejoinArray(argv, 2);
                  User->Simulate(argv[2], this);

                  SENDUSER("Done.");
            } else {
                  asprintf(&Out, "No such user: %s", argv[1]);
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            }

            return false;
      } else if (strcasecmp(Subcommand, "direct") == 0) {
            if (argc < 2) {
                  SENDUSER("Syntax: DIRECT :command");
                  return false;
            }

            CIRCConnection *IRC = GetOwner()->GetIRCConnection();

            ArgRejoinArray(argv, 1);
            IRC->WriteLine("%s", argv[1]);

            return false;
      } else if (strcasecmp(Subcommand, "gvhost") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  const char *Ip = g_Bouncer->GetDefaultVHost();

                  asprintf(&Out, "Current global VHost: %s", Ip ? Ip : "(none)");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            } else {
                  g_Bouncer->SetDefaultVHost(argv[1]);
                  SENDUSER("Done.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "motd") == 0) {
            if (argc < 2) {
                  const char *Motd = g_Bouncer->GetMotd();

                  asprintf(&Out, "Current MOTD: %s", Motd ? Motd : "(none)");
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  if (Motd != NULL && GetOwner()->IsAdmin()) {
                        if (NoticeUser) {
                              SENDUSER("Use /sbnc motd remove to remove the motd.");
                        } else {
                              SENDUSER("Use /msg -sBNC motd remove to remove the motd.");
                        }
                  }
            } else if (GetOwner()->IsAdmin()) {
                  ArgRejoinArray(argv, 1);

                  if (strcasecmp(argv[1], "remove") == 0) {
                        g_Bouncer->SetMotd(NULL);
                  } else {
                        g_Bouncer->SetMotd(argv[1]);
                  }

                  SENDUSER("Done.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "global") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: GLOBAL :text");
                  return false;
            }

            ArgRejoinArray(argv, 1);
            g_Bouncer->GlobalNotice(argv[1]);
            return false;
      } else if (strcasecmp(Subcommand, "kill") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: KILL username [reason]");
                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);

            const char *Reason = "No reason specified.";

            if (argc >= 3) {
                  ArgRejoinArray(argv, 2);
                  Reason = argv[2];
            }

            asprintf(&Out, "You were disconnected from the bouncer. (Requested by %s: %s)", GetOwner()->GetUsername(), Reason);

            CHECK_ALLOC_RESULT(Out, asprintf) {
                  return false;
            } CHECK_ALLOC_RESULT_END;

            if (User != NULL && User->GetClientConnectionMultiplexer() != NULL) {
                  User->GetClientConnectionMultiplexer()->Kill(Out);
                  SENDUSER("Done.");
            } else {
                  SENDUSER("There is no such user or that user is not currently logged in.");
            }

            free(Out);

            return false;
      } else if (strcasecmp(Subcommand, "disconnect") == 0) {
            CUser *User;

            if (GetOwner()->IsAdmin() && argc >= 2) {
                  User = g_Bouncer->GetUser(argv[1]);
            } else {
                  User = GetOwner();
            }

            if (User == NULL) {
                  SENDUSER("There is no such user.");
                  return false;
            }

            CIRCConnection *IRC = User->GetIRCConnection();

            User->MarkQuitted(true);

            if (IRC == NULL) {
                  if (User == GetOwner()) {
                        SENDUSER("You are not connected to a server.");
                  } else {
                        SENDUSER("The user is not connected to a server.");
                  }

                  return false;
            }

            IRC->Kill("Requested.");

            SENDUSER("Done.");

            return false;
      } else if (strcasecmp(Subcommand, "jump") == 0) {
            if (GetOwner()->GetIRCConnection()) {
                  GetOwner()->GetIRCConnection()->Kill("Reconnecting");

                  GetOwner()->SetIRCConnection(NULL);
            }

            if (GetOwner()->GetServer() == NULL) {
                  SENDUSER("Cannot reconnect: You haven't set a server yet.");
            } else {
                  GetOwner()->ScheduleReconnect(5);
            }

            return false;
      } else if (strcasecmp(Subcommand, "status") == 0) {
            asprintf(&Out, "Username: %s", GetOwner()->GetUsername());
            CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;

            asprintf(&Out, "This is shroudBNC %s", g_Bouncer->GetBouncerVersion());
            CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;

            if (GetOwner()->IsAdmin()) {
                  asprintf(&Out, "Using module %s", sbncGetModulePath());
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            }

            asprintf(&Out, "You are %san admin.", GetOwner()->IsAdmin() ? "" : "not ");
            CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;

            asprintf(&Out, "Client: sendq: %d, recvq: %d", GetSendqSize(), GetRecvqSize());
            CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;

            CIRCConnection *IRC = GetOwner()->GetIRCConnection();

            if (IRC) {
                  asprintf(&Out, "IRC: sendq: %d, recvq: %d", IRC->GetSendqSize(), IRC->GetRecvqSize());
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;

                  SENDUSER("Channels:");

                  int a = 0;

                  while (hash_t<CChannel *> *Chan = IRC->GetChannels()->Iterate(a++)) {
                        SENDUSER(Chan->Name);
                  }

                  SENDUSER("End of CHANNELS.");
            }

            asprintf(&Out, "Uptime: %d seconds", GetOwner()->GetIRCUptime());
            CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;

            return false;
      } else if (strcasecmp(Subcommand, "impulse") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: impulse command");

                  return false;
            }

            const char *Reply = g_Bouncer->DebugImpulse(atoi(argv[1]));

            if (Reply != NULL) {
                  SENDUSER(Reply);
            } else {
                  SENDUSER("No return value.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "who") == 0 && GetOwner()->IsAdmin()) {
            char **Keys = g_Bouncer->GetUsers()->GetSortedKeys();
            int Count = g_Bouncer->GetUsers()->GetLength();

            for (int i = 0; i < Count; i++) {
                  const char *Server, *ClientAddr;
                  CUser *User = g_Bouncer->GetUser(Keys[i]);

                  if (User == NULL) {
                        continue;
                  }

                  if (User->GetIRCConnection()) {
                        Server = User->GetIRCConnection()->GetServer();
                  } else {
                        Server = NULL;
                  }

                  if (User->GetPrimaryClientConnection() != NULL) {
                        ClientAddr = User->GetPrimaryClientConnection()->GetPeerName();
                  } else {
                        ClientAddr = NULL;
                  }

                  const char *LastSeen;

                  if (User->GetLastSeen() == 0) {
                        LastSeen = "Never";
                  } else if (User->GetPrimaryClientConnection() != NULL) {
                        LastSeen = "Now";
                  } else {
                        LastSeen = GetOwner()->FormatTime(User->GetLastSeen());
                  }

                  asprintf(&Out, "%s%s%s%s(%s)@%s [%s] [Last seen: %s] :%s",
                        User->IsLocked() ? "!" : "",
                        User->IsAdmin() ? "@" : "",
                        ClientAddr ? "*" : "",
                        User->GetUsername(),
                        User->GetIRCConnection() ? (User->GetIRCConnection()->GetCurrentNick() ? User->GetIRCConnection()->GetCurrentNick() : "<none>") : User->GetNick(),
                        ClientAddr ? ClientAddr : "",
                        Server ? Server : "",
                        LastSeen,
                        User->GetRealname());
                  CHECK_ALLOC_RESULT(Out, asprintf) { } else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            }

            free(Keys);

            SENDUSER("End of USERS.");

            return false;
      } else if (strcasecmp(Subcommand, "addlistener") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
#ifdef USESSL
                  SENDUSER("Syntax: addlistener <port> [address] [ssl]");
#else
                  SENDUSER("Syntax: addlistener <port> [address]");
#endif

                  return false;
            }

            unsigned int Port = atoi(argv[1]);

            if (Port <= 1024 || Port >= 65534) {
                  SENDUSER("You did not specify a valid port.");

                  return false;
            }

            const char *Address = NULL;

            if (argc > 2) {
                  Address = argv[2];
            }

            bool SSL = false;

#ifdef USESSL
            if (argc > 3) {
                  if (atoi(argv[3]) != 0 || strcasecmp(argv[3], "ssl") == 0) {
                        SSL = true;
                  }
            }
#endif

            RESULT<bool> Result = g_Bouncer->AddAdditionalListener(Port, Address, SSL);

            if (IsError(Result)) {
                  SENDUSER(GETDESCRIPTION(Result));

                  return false;
            }

            SENDUSER("Done.");

            return false;
      } else if (strcasecmp(Subcommand, "dellistener") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: dellistener <port>");

                  return false;
            }

            RESULT<bool> Result = g_Bouncer->RemoveAdditionalListener(atoi(argv[1]));

            if (Result) {
                  SENDUSER("Done.");
            } else {
                  SENDUSER("There is no such listener.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "listeners") == 0 && GetOwner()->IsAdmin()) {
            if (g_Bouncer->GetMainListener() != NULL) {
                  asprintf(&Out, "Main listener: port %d", g_Bouncer->GetMainListener()->GetPort());
            } else {
                  Out = strdup("Main listener: none");
            }

            CHECK_ALLOC_RESULT(&Out, asprintf) {} else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;

#ifdef USESSL
            if (g_Bouncer->GetMainSSLListener() != NULL) {
                  asprintf(&Out, "Main SSL listener: port %d", g_Bouncer->GetMainSSLListener()->GetPort());
            } else {
                  Out = strdup("Main SSL listener: none");
            }

            CHECK_ALLOC_RESULT(&Out, asprintf) {} else {
                  SENDUSER(Out);
                  free(Out);
            } CHECK_ALLOC_RESULT_END;
#endif

            SENDUSER("---");
            SENDUSER("Additional listeners:");

            CVector<additionallistener_t> *Listeners = g_Bouncer->GetAdditionalListeners();

            for (unsigned int i = 0; i < Listeners->GetLength(); i++) {
#ifdef USESSL
                  if ((*Listeners)[i].SSL) {
                        if ((*Listeners)[i].BindAddress != NULL) {
                              asprintf(&Out, "Port: %d (SSL, bound to %s)", (*Listeners)[i].Port, (*Listeners)[i].BindAddress);
                        } else {
                              asprintf(&Out, "Port: %d (SSL)", (*Listeners)[i].Port);
                        }
                  } else {
#endif
                        if ((*Listeners)[i].BindAddress != NULL) {
                              asprintf(&Out, "Port: %d (bound to %s)", (*Listeners)[i].Port, (*Listeners)[i].BindAddress);
                        } else {
                              asprintf(&Out, "Port: %d", (*Listeners)[i].Port);
                        }
#ifdef USESSL
                  }
#endif
                  CHECK_ALLOC_RESULT(Out, asprintf) {} else {
                        SENDUSER(Out);
                        free(Out);
                  } CHECK_ALLOC_RESULT_END;
            }

            SENDUSER("End of LISTENERS.");

            return false;
      } else if (strcasecmp(Subcommand, "read") == 0) {
            GetOwner()->GetLog()->PlayToUser(this, NoticeUser);

            if (!GetOwner()->GetLog()->IsEmpty()) {
                  if (NoticeUser) {
                        RealNotice("End of LOG. Use '/sbnc erase' to remove this log.");
                  } else {
                        Privmsg("End of LOG. Use '/msg -sBNC erase' to remove this log.");
                  }
            } else {
                  SENDUSER("Your personal log is empty.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "erase") == 0) {
            if (GetOwner()->GetLog()->IsEmpty()) {
                  SENDUSER("Your personal log is empty.");
            } else {
                  GetOwner()->GetLog()->Clear();
                  SENDUSER("Done.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "playmainlog") == 0 && GetOwner()->IsAdmin()) {
            g_Bouncer->GetLog()->PlayToUser(this, NoticeUser);

            if (!g_Bouncer->GetLog()->IsEmpty()) {
                  if (NoticeUser) {
                        RealNotice("End of LOG. Use /sbnc erasemainlog to remove this log.");
                  } else {
                        Privmsg("End of LOG. Use /msg -sBNC erasemainlog to remove this log.");
                  }
            } else {
                  SENDUSER("The main log is empty.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "erasemainlog") == 0 && GetOwner()->IsAdmin()) {
            g_Bouncer->GetLog()->Clear();
            g_Bouncer->Log("User %s erased the main log", GetOwner()->GetUsername());
            SENDUSER("Done.");

            return false;
      } else if (strcasecmp(Subcommand, "hosts") == 0 && GetOwner()->IsAdmin()) {
            const CVector<char *> *Hosts = g_Bouncer->GetHostAllows();

            SENDUSER("Hostmasks");
            SENDUSER("---------");

            for (unsigned int i = 0; i < Hosts->GetLength(); i++) {
                  SENDUSER((*Hosts)[i]);
            }

            if (Hosts->GetLength() == 0) {
                  SENDUSER("*");
            }

            SENDUSER("End of HOSTS.");

            return false;
      } else if (strcasecmp(Subcommand, "hostadd") == 0 && GetOwner()->IsAdmin()) {
            RESULT<bool> Result;

            if (argc <= 1) {
                  SENDUSER("Syntax: HOSTADD hostmask");

                  return false;
            }

            Result = g_Bouncer->AddHostAllow(argv[1]);

            if (IsError(Result)) {
                  SENDUSER(GETDESCRIPTION(Result));
            } else {
                  SENDUSER("Done.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "hostdel") == 0 && GetOwner()->IsAdmin()) {
            RESULT<bool> Result;

            if (argc <= 1) {
                  SENDUSER("Syntax: HOSTDEL hostmask");

                  return false;
            }

            Result = g_Bouncer->RemoveHostAllow(argv[1]);

            if (IsError(Result)) {
                  SENDUSER(GETDESCRIPTION(Result));
            } else {
                  SENDUSER("Done.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "admin") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: ADMIN username");

                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);

            if (User) {
                  User->SetAdmin(true);

                  SENDUSER("Done.");
            } else {
                  SENDUSER("There's no such user.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "unadmin") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: UNADMIN username");

                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);
            
            if (User) {
                  User->SetAdmin(false);

                  SENDUSER("Done.");
            } else {
                  SENDUSER("There's no such user.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "suspend") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: SUSPEND username :reason");

                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);

            if (User) {
                  User->Lock();

                  if (User->GetClientConnectionMultiplexer() != NULL) {
                        User->GetClientConnectionMultiplexer()->Kill("Your account has been suspended.");
                  }

                  if (User->GetIRCConnection() != NULL) {
                        User->GetIRCConnection()->Kill("Requested.");
                  }

                  User->MarkQuitted(true);

                  if (argc > 2) {
                        ArgRejoinArray(argv, 2);
                        User->SetSuspendReason(argv[2]);
                  } else {
                        User->SetSuspendReason("Suspended.");
                  }

                  g_Bouncer->Log("User %s has been suspended.", User->GetUsername());

                  SENDUSER("Done.");
            } else {
                  SENDUSER("There's no such fnord.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "unsuspend") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 2) {
                  SENDUSER("Syntax: UNSUSPEND username");

                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);
            
            if (User) {
                  User->Unlock();

                  g_Bouncer->Log("User %s has been unsuspended.", User->GetUsername());

                  User->SetSuspendReason(NULL);

                  SENDUSER("Done.");
            } else {
                  SENDUSER("There's no such user.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "resetpass") == 0 && GetOwner()->IsAdmin()) {
            if (argc < 3) {
                  SENDUSER("Syntax: RESETPASS username new-password");

                  return false;
            }

            CUser *User = g_Bouncer->GetUser(argv[1]);
            
            if (User) {
                  User->SetPassword(argv[2]);

                  SENDUSER("Done.");
            } else {
                  SENDUSER("There's no such user.");
            }

            return false;
      } else if (strcasecmp(Subcommand, "partall") == 0) {
            if (GetOwner()->GetIRCConnection()) {
                  const char *Channels = GetOwner()->GetConfigChannels();

                  if (Channels != NULL) {
                        GetOwner()->GetIRCConnection()->WriteLine("PART %s", Channels);
                  }
            }

            GetOwner()->SetConfigChannels(NULL);

            SENDUSER("Done.");

            return false;
      } else if (strcasecmp(Subcommand, "dumptree") == 0 && GetOwner()->IsAdmin()) {
            DumpTree(this, NULL);

            return false;
      }

      if (NoticeUser) {
            RealNotice("Unknown command. Try /sbnc help");
      } else {
            Privmsg("Unknown command. Try /msg -sBNC help");
      }

      return false;
}


Generated by  Doxygen 1.6.0   Back to index