+++ /dev/null
-/* cmd_neonserv_set.c - NeonServ v5.3
- * Copyright (C) 2011-2012 Philipp Kreil (pk910)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cmd_neonserv.h"
-
-typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *argument);
-static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-
-#define NS_VALID_FUNCTION 0x01
-#define NS_VALID_STRING 0x02
-#define NS_VALID_ACCESS 0x04
-#define NS_VALID_NO501 0x08
-#define NS_VALID_OPTIONS 0x10
-#define NS_VALID_NUMERIC 0x20
-#define NS_VALID_BOOLEAN 0x40
-#define NS_VALID_IF_HALFOP 0x80
-
-#define NS_HAS_OPT 0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */
-#define NS_HAS_HELP 0x200 /* help (SET_HELP_{NAME}) - only shown if help is requested */
-
-static const struct {
- const char *setting;
- const char *chanfield;
- unsigned int valid;
- void *parameter;
-} channel_settings[] = {
- {"TRIGGER", NULL, NS_VALID_FUNCTION, neonserv_cmd_set_trigger},
- {"DEFAULTTOPIC", "channel_defaulttopic", NS_VALID_STRING, NULL},
- {"TOPICMASK", "channel_topicmask", NS_VALID_STRING, NULL},
- {"ADVANCEDTOPIC", "channel_exttopic", NS_VALID_BOOLEAN | NS_HAS_OPT, NULL},
- {"GREETING", "channel_greeting", NS_VALID_STRING, NULL},
- {"USERGREETING", "channel_usergreeting", NS_VALID_STRING, NULL},
- {"USERINFO", "channel_userinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"WIPEINFO", "channel_wipeinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"MODES", "channel_modes", NS_VALID_FUNCTION, neonserv_cmd_set_modes},
- {"INVITEME", "channel_getinvite", NS_VALID_ACCESS, NULL},
- {"GIVEOPS", "channel_getop", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"GIVEHALFOPS", "channel_gethalfop", NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL},
- {"GIVEVOICE", "channel_getvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"ENFOPS", "channel_canop", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"ENFHALFOPS", "channel_canhalfop", NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL},
- {"ENFVOICE", "channel_canvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"KICK", "channel_cankick", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"BAN", "channel_canban", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"STATICBAN", "channel_staticban", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"PUBCMD", "channel_pubcmd", NS_VALID_ACCESS, NULL},
- {"ENFMODES", "channel_enfmodes", NS_VALID_ACCESS, NULL},
- {"ENFTOPIC", "channel_enftopic", NS_VALID_ACCESS, NULL},
- {"TOPICSNARF", "channel_topicsnarf", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"CHANGETOPIC", "channel_changetopic", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"SETTERS", "channel_setters", NS_VALID_ACCESS | NS_VALID_NO501 | NS_HAS_HELP, NULL},
- {"ADDUSER", "channel_canadd", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"DELUSER", "channel_candel", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"CLVL", "channel_canclvl", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"RESYNC", "channel_canresync", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"SUSPEND", "channel_cansuspend", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"NOTICEUSERS", "channel_notice", NS_VALID_ACCESS, NULL},
- {"NOTICEREACTION", "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
- {"CTCPUSERS", "channel_ctcp", NS_VALID_ACCESS, NULL},
- {"CTCPREACTION", "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
- {"PROTECT", "channel_protect", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
- {"TOYS", "channel_toys", NS_VALID_OPTIONS | NS_HAS_OPT, "3"},
- {"DYNLIMIT", "channel_dynlimit", NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit},
- {"NODELETE", "channel_nodelete", NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete},
- {NULL, NULL, 0, NULL}
-};
-
-#define MAX_QUERY_LEN 1024
-CMD_BIND(neonserv_cmd_set) {
- int i, j;
- if(argc && !strcmp(argv[0], "defaults")) {
- //reset channel settings
- int uaccess = getChannelAccess(user, chan);
- if(uaccess < 500) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name);
- return;
- }
- }
- int seed = 0;
- char *tmp;
- static char defaultskey[16];
- for(tmp = user->auth; *tmp; tmp++)
- seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
- for(tmp = chan->name; *tmp; tmp++)
- seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
- sprintf(defaultskey, "%08x", seed);
- if(argc > 1 && !strcmp(argv[1], defaultskey)) {
- char query[MAX_QUERY_LEN];
- int querypos = 0;
- i = 0;
- while(channel_settings[i].setting) {
- if(channel_settings[i].chanfield)
- querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield);
- i++;
- }
- if(querypos) {
- query[querypos-2] = '\0';
- }
- printf_mysql_query("UPDATE `channels` SET %s WHERE `channel_id` = '%d'", query, chan->channel_id);
- reply(getTextBot(), user, "NS_SET_DEFAULTS_DONE", chan->name);
- logEvent(event);
- } else {
- reply(getTextBot(), user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
- }
- } else if(argc && strcmp(argv[0], "help")) {
- //find the correct command
- i = 0;
- j = 0;
- char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
- int with_halfops = get_int_field("General.have_halfop");
- while(channel_settings[i].setting) {
- if(!stricmp(channel_settings[i].setting, argv[0]) && (!(channel_settings[i].valid & NS_VALID_IF_HALFOP) || with_halfops)) {
- //setting found
- if(channel_settings[i].valid & NS_VALID_FUNCTION) {
- neonserv_cmd_set_function *func = channel_settings[i].parameter;
- func(client, user, chan, event, channel_settings[i].setting, args);
- } else {
- neonserv_cmd_set_setting(client, user, chan, event, i, args);
- }
- j = 1;
- break;
- }
- i++;
- }
- if(j == 0) {
- //unknown setting
- reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]);
- }
- } else {
- char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64];
- int querypos = 0;
- MYSQL_RES *res, *defaults_res;
- MYSQL_ROW row, defaults;
- struct Table *table;
- char *content[2];
- int with_halfops = get_int_field("General.have_halfop");
- i = 0;
- j = 0;
- while(channel_settings[i].setting) {
- if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) {
- j++;
- i++;
- continue;
- }
- if(channel_settings[i].chanfield)
- querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield);
- i++;
- }
- table = table_init(2, i-j, 0);
- table_set_bold(table, 0, 1);
- printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query);
- defaults_res = mysql_use();
- defaults = mysql_fetch_row(defaults_res);
- printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- i = 0;
- j = 0;
- reply(getTextBot(), user, "NS_SET_HEADER", chan->name);
- while(channel_settings[i].setting) {
- if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) {
- i++;
- continue;
- }
- if(channel_settings[i].chanfield) {
- j++;
- org_value = (row[j] ? row[j] : defaults[j]);
- } else if(channel_settings[i].valid & NS_VALID_FUNCTION) {
- neonserv_cmd_set_function *func = channel_settings[i].parameter;
- org_value = func(client, user, chan, event, NULL, NULL);
- } else
- org_value = "0";
- value = org_value;
- if(channel_settings[i].valid & NS_VALID_BOOLEAN) {
- if(!strcmp(value, "0"))
- value = get_language_string(user, "NS_SET_OFF");
- else
- value = get_language_string(user, "NS_SET_ON");
- }
- strcpy(query, value);
- querypos = strlen(query);
- if(channel_settings[i].valid & NS_HAS_OPT) {
- sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value);
- tmp = get_language_string(user, nameBuf);
- if(tmp) {
- querypos += sprintf(query+querypos, " - %s", tmp);
- }
- }
- if(argc && channel_settings[i].valid & NS_HAS_HELP) {
- sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting);
- tmp = get_language_string(user, nameBuf);
- if(tmp) {
- querypos += sprintf(query+querypos, " - %s", tmp);
- }
- }
- content[0] = (char*)channel_settings[i].setting;
- content[1] = query;
- table_add(table, content);
- i++;
- }
- char **table_lines = table_end(table);
- for(i = 0; i < table->entrys; i++) {
- reply(getTextBot(), user, table_lines[i]);
- }
- table_free(table);
- }
-}
-
-static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *args) {
- char *value;
- char nameBuf[64];
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield);
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(args) {
- //change the channel setting
- //check the new argument
- int valid = channel_settings[setting].valid;
- if(valid & NS_VALID_STRING) {
- if(!strcmp(args, "*")) {
- args = "";
- }
- }
- if(valid & NS_VALID_ACCESS) {
- int caccess = atoi(args);
- int max = ((valid & NS_VALID_NO501) ? 500 : 501);
- if(caccess < 0 || caccess > max) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
- return;
- }
- int uaccess = getChannelAccess(user, chan);
- if(uaccess == 500) uaccess++;
- if(atoi(value) > uaccess) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_CANNOT_SET");
- return;
- }
- }
- if(caccess > uaccess) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_BADLEVEL");
- return;
- }
- }
- sprintf(nameBuf, "%d", caccess);
- args = nameBuf;
- }
- if(valid & NS_VALID_OPTIONS) {
- int options = atoi((char *) channel_settings[setting].parameter);
- int coption = atoi(args);
- if(coption < 0 || coption >= options) {
- reply(getTextBot(), user, "NS_SET_INVALID_OPTION", coption);
- int i;
- int nameBufPos = 0;
- if(valid & NS_HAS_OPT) {
- for(i = 0; i < options; i++) {
- sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i);
- reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf));
- }
- } else {
- for(i = 0; i < options; i++) {
- nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i);
- }
- if(nameBufPos) {
- nameBuf[nameBufPos-2] = '\0';
- reply(getTextBot(), user, nameBuf);
- }
- }
- return;
- }
- }
- if(valid & NS_VALID_NUMERIC) {
- sprintf(nameBuf, "%d", atoi(args));
- args = nameBuf;
- }
- if(valid & NS_VALID_BOOLEAN) {
- if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) {
- args = "0";
- } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) {
- args = "1";
- } else {
- reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args);
- return;
- }
- }
- //valid - set it
- value = args;
- printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, escape_string(value), chan->channel_id);
- logEvent(event);
- }
- if(channel_settings[setting].valid & NS_HAS_OPT) {
- sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[setting].setting, value);
- char *tmp = get_language_string(user, nameBuf);
- if(tmp)
- reply(getTextBot(), user, "\002%s\002 %s - %s", channel_settings[setting].setting, value, tmp);
- else
- reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value);
- } else
- reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value);
- if(channel_settings[setting].valid & NS_HAS_HELP) {
- sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting);
- reply(getTextBot(), user, " %s", get_language_string(user, nameBuf));
- }
-}
-
-static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *trigger;
- //get current trigger
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
- res = mysql_use();
- row = mysql_fetch_row(res);
- trigger = (row[0] ? row[0] : row[1]);
- if(argument) {
- int uaccess = getChannelAccess(user, chan);
- if(uaccess < 500) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name);
- return NULL;
- }
- }
- if(strlen(argument) > 15)
- argument[15] = '\0';
- printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid);
- trigger = argument;
- changeChannelTrigger(client->botid, chan, trigger);
- logEvent(event);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, trigger);
- }
- return trigger;
-}
-
-static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *value;
- char valueBuf[MAXLEN];
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(argument) {
- //change the channel setting
- struct ModeNode *modenode = createModeNode(NULL);
- parseModeString(modenode, argument);
- getFullModeString(modenode, valueBuf);
- value = valueBuf;
- printf_mysql_query("UPDATE `channels` SET `channel_modes` = '%s' WHERE `channel_id` = '%d'", escape_string(value), chan->channel_id);
- //TODO: set modelock
- freeModeNode(modenode);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, value);
- }
- return value;
-}
-
-static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *value;
- char tmp[64];
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(argument) {
- //change the channel setting
- sprintf(tmp, "%d", atoi(argument));
- argument = tmp;
- printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
- if(strcmp(argument, "0"))
- putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument)));
- else if(isModeSet(chan->modes, 'l'))
- putsock(client, "MODE %s -l", chan->name);
- value = argument;
- logEvent(event);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, value);
- }
- return value;
-}
-
-static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *value;
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(argument && isGodMode(user)) {
- //change the channel setting
- if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
- argument = "0";
- } else if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
- argument = "1";
- } else {
- reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
- return NULL;
- }
- printf_mysql_query("UPDATE `channels` SET `channel_nodelete` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
- event->flags |= CMDFLAG_OPLOG;
- value = argument;
- logEvent(event);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, value);
- }
- return value;
-}
-
-#undef MAX_QUERY_LEN