Continue of previous commit.

* add help description for /mail and /ipban https://github.com/HarpyWar/pvpgn/issues/5
* refactoring: move /icon command to icons.cpp, move split_command() to common
This commit is contained in:
HarpyWar 2014-04-27 11:11:04 +04:00
parent d2fffcf408
commit 50e85312fa
9 changed files with 211 additions and 249 deletions

View file

@ -33,7 +33,6 @@
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include "compat/strcasecmp.h"
@ -361,7 +360,6 @@ namespace pvpgn
static int _handle_moderate_command(t_connection * c, char const * text);
static int _handle_clearstats_command(t_connection * c, char const * text);
static int _handle_tos_command(t_connection * c, char const * text);
static int _handle_icon_command(t_connection * c, char const * text);
static const t_command_table_row standard_command_table[] =
{
@ -482,59 +480,12 @@ namespace pvpgn
{ "/topic", _handle_topic_command },
{ "/moderate", _handle_moderate_command },
{ "/clearstats", _handle_clearstats_command },
{ "/icon", _handle_icon_command },
{ "/icon", handle_icon_command },
{ NULL, NULL }
};
/*
* Split text by spaces and return array of arguments.
* First text argument is a command name (index = 0)
* Last text argument always reads to end
*/
std::vector<std::string> split_command(char const * text, int args_count)
{
int count = 1 + args_count;
std::vector<std::string> result(count);
std::string s(text);
std::istringstream iss(s);
int i = 0;
std::string tmp = std::string(); // to end
do
{
std::string sub;
iss >> sub;
if (sub.empty())
continue;
// remove slash from the command
if (i == 0)
sub.erase(0,1);
if (i < args_count)
{
result[i] = sub;
i++;
}
else
{
if (!tmp.empty())
tmp += " ";
tmp += sub;
}
} while (iss);
// push remaining text at the end
if (tmp.length() > 0)
result[count-1] = tmp;
return result;
}
extern int handle_command(t_connection * c, char const * text)
{
@ -2554,7 +2505,10 @@ namespace pvpgn
t_account * account;
if (!(account = accountlist_find_account(username)))
message_send_text(c, message_type_info, c, "That account doesn't currently exist, banning anyway.");
{
message_send_text(c, message_type_info, c, "That account doesn't currently exist.");
return -1;
}
else if (account_get_auth_admin(account, NULL) == 1 || account_get_auth_admin(account, channel_get_name(channel)) == 1)
{
message_send_text(c, message_type_error, c, "You cannot ban administrators.");
@ -5002,91 +4956,5 @@ namespace pvpgn
return 0;
}
/* Set usericon */
static int _handle_icon_command(t_connection * c, char const *text)
{
t_account * user_account;
t_connection * user_c;
char const * username, *code, *usericon;
t_clienttag clienttag;
std::vector<std::string> args = split_command(text, 3);
if (args[1].empty())
{
describe_command(c, args[0].c_str());
return -1;
}
username = args[1].c_str(); // username
// find user account
if (!(user_account = accountlist_find_account(username)))
{
message_send_text(c, message_type_error, c, "Invalid user.");
return 0;
}
user_c = account_get_conn(user_account);
// if clienttag is in parameters
if (clienttag = tag_validate_client(args[3].c_str()))
{
// if user offline then replace last clienttag with given
if (!user_c)
account_set_ll_clienttag(user_account, clienttag);
}
else
{
if (user_c)
clienttag = conn_get_clienttag(user_c);
else // if user offline then retrieve last clienttag
clienttag = account_get_ll_clienttag(user_account);
}
// icon code
std::transform(args[2].begin(), args[2].end(), args[2].begin(), std::toupper); // to upper
code = args[2].c_str();
// output current usericon code
if (strlen(code) != 4)
{
if (usericon = account_get_user_icon(user_account, clienttag))
{
snprintf(msgtemp, sizeof(msgtemp), "%.64s has custom icon \"%.4s\" of %.128s", account_get_name(user_account), strreverse(xstrdup(usericon)), clienttag_get_title(clienttag));
message_send_text(c, message_type_error, c, msgtemp);
}
else
{
snprintf(msgtemp, sizeof(msgtemp), "Custom icon for %.64s currently not set of %.128s", account_get_name(user_account), clienttag_get_title(clienttag));
message_send_text(c, message_type_error, c, msgtemp);
}
return 0;
}
// unset value
if (strcasecmp(code, "null") == 0)
{
snprintf(msgtemp, sizeof(msgtemp), "Set default icon to %.64s of %.128s", account_get_name(user_account), clienttag_get_title(clienttag));
usericon = NULL;
}
else
{
snprintf(msgtemp, sizeof(msgtemp), "Set icon \"%.4s\" to %.64s of %.128s", code, account_get_name(user_account), clienttag_get_title(clienttag));
usericon = strreverse((char*)code);
}
message_send_text(c, message_type_error, c, msgtemp);
// set reversed
account_set_user_icon(user_account, clienttag, usericon);
// if user online then force him to rejoin channel
if (user_c)
{
conn_update_w3_playerinfo(user_c);
channel_rejoin(user_c);
}
}
}
}

View file

@ -15,11 +15,14 @@
*/
#include "common/setup_before.h"
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <vector>
#include "compat/strcasecmp.h"
#include "compat/snprintf.h"
@ -38,6 +41,9 @@
#include "icons.h"
#include "account_wrap.h"
#include "common/setup_after.h"
#include "message.h"
#include "helpfile.h"
#include "channel.h"
namespace pvpgn
{
@ -56,6 +62,97 @@ namespace pvpgn
static char * _find_attr_key(char * clienttag);
/* Set usericon (command) */
extern int handle_icon_command(t_connection * c, char const *text)
{
t_account * user_account;
t_connection * user_c;
char const * username, *code, *usericon;
t_clienttag clienttag;
char msgtemp[MAX_MESSAGE_LEN];
std::vector<std::string> args = split_command(text, 3);
if (args[1].empty())
{
describe_command(c, args[0].c_str());
return -1;
}
username = args[1].c_str(); // username
// find user account
if (!(user_account = accountlist_find_account(username)))
{
message_send_text(c, message_type_error, c, "Invalid user.");
return 0;
}
user_c = account_get_conn(user_account);
// if clienttag is in parameters
if (clienttag = tag_validate_client(args[3].c_str()))
{
// if user offline then replace last clienttag with given
if (!user_c)
account_set_ll_clienttag(user_account, clienttag);
}
else
{
if (user_c)
clienttag = conn_get_clienttag(user_c);
else // if user offline then retrieve last clienttag
clienttag = account_get_ll_clienttag(user_account);
}
// icon code
std::transform(args[2].begin(), args[2].end(), args[2].begin(), std::toupper); // to upper
code = args[2].c_str();
// output current usericon code
if (strlen(code) != 4)
{
if (usericon = account_get_user_icon(user_account, clienttag))
{
snprintf(msgtemp, sizeof(msgtemp), "%.64s has custom icon \"%.4s\" of %.128s", account_get_name(user_account), strreverse(xstrdup(usericon)), clienttag_get_title(clienttag));
message_send_text(c, message_type_error, c, msgtemp);
}
else
{
snprintf(msgtemp, sizeof(msgtemp), "Custom icon for %.64s currently not set of %.128s", account_get_name(user_account), clienttag_get_title(clienttag));
message_send_text(c, message_type_error, c, msgtemp);
}
return 0;
}
// unset value
if (strcasecmp(code, "null") == 0)
{
snprintf(msgtemp, sizeof(msgtemp), "Set default icon to %.64s of %.128s", account_get_name(user_account), clienttag_get_title(clienttag));
usericon = NULL;
}
else
{
snprintf(msgtemp, sizeof(msgtemp), "Set icon \"%.4s\" to %.64s of %.128s", code, account_get_name(user_account), clienttag_get_title(clienttag));
usericon = strreverse((char*)code);
}
message_send_text(c, message_type_error, c, msgtemp);
// set reversed
account_set_user_icon(user_account, clienttag, usericon);
// if user online then force him to rejoin channel
if (user_c)
{
conn_update_w3_playerinfo(user_c);
channel_rejoin(user_c);
}
}
extern int prefs_get_custom_icons()
{
return enable_custom_icons;

View file

@ -63,6 +63,8 @@ namespace pvpgn
namespace bnetd
{
extern int handle_icon_command(t_connection * c, char const *text);
extern int prefs_get_custom_icons();
extern t_icon_info * get_custom_icon(t_account * account, t_clienttag clienttag);
extern const char * get_custom_stats_text(t_account * account, t_clienttag clienttag);

View file

@ -25,6 +25,7 @@
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <vector>
#include "compat/strsep.h"
#include "compat/strcasecmp.h"
@ -34,12 +35,14 @@
#include "common/eventlog.h"
#include "common/xalloc.h"
#include "common/field_sizes.h"
#include "common/xstring.h"
#include "message.h"
#include "server.h"
#include "prefs.h"
#include "connection.h"
#include "common/setup_after.h"
#include "helpfile.h"
namespace pvpgn
{
@ -498,27 +501,22 @@ namespace pvpgn
extern int handle_ipban_command(t_connection * c, char const * text)
{
char subcommand[MAX_FUNC_LEN];
char ipstr[MAX_IP_STR];
unsigned int i, j;
char const *subcommand, *ipstr, *time;
for (i = 0; text[i] != ' ' && text[i] != '\0'; i++); /* skip command */
for (; text[i] == ' '; i++);
for (j = 0; text[i] != ' ' && text[i] != '\0'; i++) /* get subcommand */
if (j < sizeof(subcommand)-1) subcommand[j++] = text[i];
subcommand[j] = '\0';
for (; text[i] == ' '; i++);
for (j = 0; text[i] != ' ' && text[i] != '\0'; i++) /* get ip address */
if (j < sizeof(ipstr)-1) ipstr[j++] = text[i];
ipstr[j] = '\0';
for (; text[i] == ' '; i++);
std::vector<std::string> args = split_command(text, 3);
if (args[1].empty())
{
describe_command(c, args[0].c_str());
return -1;
}
subcommand = args[1].c_str(); // subcommand
ipstr = args[2].c_str(); // ip address
time = args[3].c_str(); // username
switch (identify_ipban_function(subcommand))
{
case IPBAN_FUNC_ADD:
ipbanlist_add(c, ipstr, ipbanlist_str_to_time_t(c, &text[i]));
ipbanlist_add(c, ipstr, ipbanlist_str_to_time_t(c, time));
ipbanlist_save(prefs_get_ipbanfile());
break;
case IPBAN_FUNC_DEL:
@ -530,14 +528,9 @@ namespace pvpgn
break;
case IPBAN_FUNC_CHECK:
ipban_func_check(c, ipstr);
break;
case IPBAN_FUNC_HELP:
message_send_text(c, message_type_info, c, "The ipban command supports the following patterns.");
ipban_usage(c);
break;
break;
default:
message_send_text(c, message_type_info, c, "The command is incorect. Use one of the following patterns.");
ipban_usage(c);
describe_command(c, args[0].c_str());
}
return 0;
@ -554,8 +547,6 @@ namespace pvpgn
return IPBAN_FUNC_LIST;
if (strcasecmp(funcstr, "check") == 0 || strcasecmp(funcstr, "c") == 0)
return IPBAN_FUNC_CHECK;
if (strcasecmp(funcstr, "help") == 0 || strcasecmp(funcstr, "h") == 0)
return IPBAN_FUNC_HELP;
return IPBAN_FUNC_UNKNOWN;
}
@ -1036,22 +1027,6 @@ namespace pvpgn
}
static void ipban_usage(t_connection * c)
{
message_send_text(c, message_type_info, c, "to print this information:");
message_send_text(c, message_type_info, c, " /ipban h[elp]");
message_send_text(c, message_type_info, c, "to print all baned IPs");
message_send_text(c, message_type_info, c, " /ipban [l[ist]]");
message_send_text(c, message_type_info, c, "to erase ban:");
message_send_text(c, message_type_info, c, " /ipban d[el] <IP|index num>");
message_send_text(c, message_type_info, c, " (IP have to be entry accepted in bnban)");
message_send_text(c, message_type_info, c, "to add ban:");
message_send_text(c, message_type_info, c, " /ipban a[dd] IP");
message_send_text(c, message_type_info, c, " (IP have to be entry accepted in bnban)");
message_send_text(c, message_type_info, c, "to check is specified IP banned:");
message_send_text(c, message_type_info, c, " /ipban c[heck] IP");
}
}
}

View file

@ -31,8 +31,7 @@
#define IPBAN_FUNC_DEL 2
#define IPBAN_FUNC_LIST 3
#define IPBAN_FUNC_CHECK 4
#define IPBAN_FUNC_HELP 5
#define IPBAN_FUNC_UNKNOWN 6
#define IPBAN_FUNC_UNKNOWN 5
namespace pvpgn

View file

@ -27,17 +27,20 @@
#include <cstdlib>
#include <cerrno>
#include <algorithm>
#include <vector>
#include "compat/strcasecmp.h"
#include "compat/mkdir.h"
#include "compat/statmacros.h"
#include "common/eventlog.h"
#include "common/xalloc.h"
#include "common/xstring.h"
#include "account.h"
#include "message.h"
#include "prefs.h"
#include "connection.h"
#include "common/setup_after.h"
#include "helpfile.h"
namespace pvpgn
@ -48,9 +51,9 @@ namespace pvpgn
static int identify_mail_function(const std::string&);
static void mail_usage(t_connection*);
static void mail_func_send(t_connection*, std::istream&);
static void mail_func_read(t_connection*, std::istream&);
static void mail_func_delete(t_connection*, std::istream&);
static void mail_func_send(t_connection*, char const *, char const *);
static void mail_func_read(t_connection*, std::string);
static void mail_func_delete(t_connection*, std::string);
static unsigned get_mail_quota(t_account *);
/* Mail API */
@ -254,30 +257,38 @@ namespace pvpgn
std::istringstream istr(text);
std::string token;
/* stkip "/mail" */
istr >> token;
char const *subcommand;
/* get the mail function */
token.clear();
istr >> token;
std::vector<std::string> args = split_command(text, 3);
if (args[1].empty())
{
describe_command(c, args[0].c_str());
return -1;
}
subcommand = args[1].c_str(); // subcommand
switch (identify_mail_function(token.c_str())) {
switch (identify_mail_function(subcommand)) {
case MAIL_FUNC_SEND:
mail_func_send(c, istr);
if (args[3].empty())
{
describe_command(c, args[0].c_str());
return -1;
}
mail_func_send(c, args[2].c_str(), args[3].c_str());
break;
case MAIL_FUNC_READ:
mail_func_read(c, istr);
mail_func_read(c, args[2]);
break;
case MAIL_FUNC_DELETE:
mail_func_delete(c, istr);
break;
case MAIL_FUNC_HELP:
message_send_text(c, message_type_info, c, "The mail command supports the following patterns.");
mail_usage(c);
if (args[2].empty())
{
describe_command(c, args[0].c_str());
return -1;
}
mail_func_delete(c, args[2]);
break;
default:
message_send_text(c, message_type_error, c, "The command its incorrect. Use one of the following patterns.");
mail_usage(c);
describe_command(c, args[0].c_str());
}
return 0;
@ -291,8 +302,6 @@ namespace pvpgn
return MAIL_FUNC_SEND;
if (!strcasecmp(funcstr.c_str(), "delete") || !strcasecmp(funcstr.c_str(), "del"))
return MAIL_FUNC_DELETE;
if (!strcasecmp(funcstr.c_str(), "help") || !strcasecmp(funcstr.c_str(), "h"))
return MAIL_FUNC_HELP;
return MAIL_FUNC_UNKNOWN;
}
@ -312,31 +321,14 @@ namespace pvpgn
return quota;
}
static void mail_func_send(t_connection * c, std::istream& istr)
static void mail_func_send(t_connection * c, char const * receiver, char const * message)
{
if (!c) {
ERROR0("got NULL connection");
return;
}
std::string dest;
istr >> dest;
if (dest.empty()) {
message_send_text(c, message_type_error, c, "You must specify the receiver");
message_send_text(c, message_type_error, c, "Syntax: /mail send <receiver> <message>");
return;
}
std::string message;
std::getline(istr, message);
std::string::size_type pos(message.find_first_not_of(" \t"));
if (pos == std::string::npos) {
message_send_text(c, message_type_error, c, "Your message is empty!");
message_send_text(c, message_type_error, c, "Syntax: /mail send <receiver> <message>");
return;
}
t_account * recv = accountlist_find_account(dest.c_str());
t_account * recv = accountlist_find_account(receiver);
if (!recv) {
message_send_text(c, message_type_error, c, "Receiver UNKNOWN!");
return;
@ -349,7 +341,7 @@ namespace pvpgn
}
try {
mbox.deliver(conn_get_username(c), message.substr(pos));
mbox.deliver(conn_get_username(c), message);
message_send_text(c, message_type_info, c, "Your mail has been sent successfully.");
}
catch (const Mailbox::DeliverError&) {
@ -363,16 +355,13 @@ namespace pvpgn
return false;
}
static void mail_func_read(t_connection * c, std::istream& istr)
static void mail_func_read(t_connection * c, std::string token)
{
if (!c) {
ERROR0("got NULL connection");
return;
}
std::string token;
istr >> token;
t_account * user = conn_get_account(c);
Mailbox mbox(account_get_uid(user));
@ -427,16 +416,13 @@ namespace pvpgn
}
}
static void mail_func_delete(t_connection * c, std::istream& istr)
static void mail_func_delete(t_connection * c, std::string token)
{
if (!c) {
ERROR0("got NULL connection");
return;
}
std::string token;
istr >> token;
if (token.empty()) {
message_send_text(c, message_type_error, c, "Please specify which message to delete. Use the following syntax: /mail delete {<index>|all} .");
return;
@ -460,24 +446,6 @@ namespace pvpgn
}
}
static void mail_usage(t_connection * c)
{
message_send_text(c, message_type_info, c, "to print this information:");
message_send_text(c, message_type_info, c, " /mail help");
message_send_text(c, message_type_info, c, "to print an index of you messages:");
message_send_text(c, message_type_info, c, " /mail [read]");
message_send_text(c, message_type_info, c, "to send a message:");
message_send_text(c, message_type_info, c, " /mail send <receiver> <message>");
message_send_text(c, message_type_info, c, "to read a message:");
message_send_text(c, message_type_info, c, " /mail read <index num>");
message_send_text(c, message_type_info, c, "to delete a message:");
message_send_text(c, message_type_info, c, " /mail delete {<index>|all}");
message_send_text(c, message_type_info, c, "Commands may be abbreviated as follows:");
message_send_text(c, message_type_info, c, " help: h");
message_send_text(c, message_type_info, c, " read: r");
message_send_text(c, message_type_info, c, " send: s");
message_send_text(c, message_type_info, c, " delete: del");
}
extern unsigned check_mail(t_connection const * c)
{

View file

@ -28,8 +28,7 @@
#define MAIL_FUNC_SEND 1
#define MAIL_FUNC_READ 2
#define MAIL_FUNC_DELETE 3
#define MAIL_FUNC_HELP 4
#define MAIL_FUNC_UNKNOWN 5
#define MAIL_FUNC_UNKNOWN 4
#include <string>

View file

@ -22,6 +22,8 @@
#include <cctype>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>
#include "compat/strdup.h"
#include "common/xalloc.h"
@ -315,4 +317,52 @@ namespace pvpgn
return result;
}
/*
* Split text by spaces and return array of arguments.
* First text argument is a command name (index = 0)
* Last text argument always reads to end
*/
extern std::vector<std::string> split_command(char const * text, int args_count)
{
int count = 1 + args_count;
std::vector<std::string> result(count);
std::string s(text);
std::istringstream iss(s);
int i = 0;
std::string tmp = std::string(); // to end
do
{
std::string sub;
iss >> sub;
if (sub.empty())
continue;
// remove slash from the command
if (i == 0)
sub.erase(0, 1);
if (i < args_count)
{
result[i] = sub;
i++;
}
else
{
if (!tmp.empty())
tmp += " ";
tmp += sub;
}
} while (iss);
// push remaining text at the end
if (tmp.length() > 0)
result[count - 1] = tmp;
return result;
}
}

View file

@ -18,6 +18,10 @@
#ifndef INCLUDED_XSTRING_H
#define INCLUDED_XSTRING_H
#include <string>
#include <vector>
namespace pvpgn
{
@ -29,7 +33,7 @@ namespace pvpgn
extern char * arraytostr(char * * array, char const * delim, int count);
extern char * str_strip_affix(char * str, char const * affix);
extern const char *str_replace(char *orig, char *rep, char *with);
extern std::vector<std::string> split_command(char const * text, int args_count);
}