#ifdef RCS
static char rcsid[]="$Id: command.c,v 1.2 2001/03/13 05:04:47 holsta Exp $";
#endif
/******************************************************************************
* Internetting Cooperating Programmers
* ----------------------------------------------------------------------------
*
* ____ PROJECT
* | _ \ __ _ _ __ ___ ___ _ __
* | | | |/ _` | '_ \ / __/ _ \ '__|
* | |_| | (_| | | | | (_| __/ |
* |____/ \__,_|_| |_|\___\___|_| the IRC bot
*
* All files in this archive are subject to the GNU General Public License.
*
* $Source: /cvsroot/dancer/dancer/src/command.c,v $
* $Revision: 1.2 $
* $Date: 2001/03/13 05:04:47 $
* $Author: holsta $
* $State: Exp $
* $Locker: $
*
* ---------------------------------------------------------------------------
*****************************************************************************/
#include "dancer.h"
#include "trio.h"
#include "strio.h"
#include "function.h"
#include "user.h"
#include "bans.h"
#include "explain.h"
#include "seen.h"
#include "country.h"
#include "bans.h"
#include "transfer.h"
#include "command.h"
#include "server.h"
#include "parse.h"
#include "flood.h"
#include "link.h"
#include "servfunc.h"
#include "convert.h"
#include "news.h"
#include "netstuff.h" /* for the OUT* stuff */
#ifdef HAVE_LIBFPL
# include "fplrun.h"
#else
# define runfpl(x,y,z)
#endif
/* --- Global ----------------------------------------------------- */
extern time_t now;
extern bool nickflag, lockmode, lockkey, avalance;
extern char channel[], cmodes[], ckey[], chankey[], nickname[], staticnick[];
extern char servername[];
extern char rulesmsg[], findfilename[], nameserver[];
extern char cmdvrfy[], cmdhost[], cmdfinger[];
extern char cmdspell[];
extern char userfile[];
extern itemuser *userHead;
extern itemguest *guestHead;
extern itemclient *clientHead;
extern itemlink *linkHead;
extern int serverSocket;
extern itemopt option;
extern int defbantime;
extern int serverport;
extern char serverpasswd[];
extern bool floodmode;
extern bool netsplitmode; /* deop server ops of users who are not users */
extern bool uppercheck; /* check users for uppercase violations! */
extern bool beepcheck; /* check users for beep violations! */
extern bool colourcheck; /* check users for colour-code violations! */
extern bool nickflood; /* kick on nick floods */
extern bool talkative; /* start in talkative mode */
extern bool saymode; /* allow SAY / ME */
extern bool xdccmode; /* kick xdccers */
extern bool deopprotect;
extern bool repeatmode; /* check for repeaters */
extern bool multimode; /* prevent too many users */
extern bool ctcpmode; /* CTCP flood checks */
extern bool reportban;
extern bool autojoin;
extern bool autoop;
extern bool dispcomment;
extern bool invitable;
extern bool masterflood;
extern bool kickbans; /* kick banned users if they still join */
extern bool helpsyntax; /* automatically show syntax info after help */
extern bool identprotect;
extern bool mute;
extern int floodtime, floodrate, floodrepeatrate, floodrepeattime;
extern int floodbeeps;
extern bool botop; /* bot operates as channel operator? */
extern bool shuttingdown;
extern time_t shutdowntime;
extern char shutdownreason[];
extern char shutdownby[];
extern char botmatch[];
extern long numofbotmodes; /* number of mode changes done by me */
extern long modecount[11];
extern long levels[];
extern int pubbantime;
extern char defaultpasswd[];
bool moderateflag = FALSE;
char *errfrom; /* this is like stderr, only for nicks */
time_t lastpost = 0;
int servedmsgcmd = 0;
int servedpubcmd = 0;
int serveddcccmd = 0;
extern itemclient *client;
bool chat; /* dcc chat command */
bool public; /* public command */
char cmdchar = '.'; /* Command char */
char ccmdchar = '!'; /* Command char for chat */
/* Identification of person who issued the current command */
itemident *current = NULL;
static void InviteMe(char *from, itemuser *u, char *passwd);
/* ---------------------------------------------------------------- */
#ifdef FUNCS_HACK
char *msg_help_funcadd[] = {
"enAdd a new alias to dancer.funcs, see parse.c for more info",
NULL
};
char *msg_help_funcdel[] = {
"enDelete an alias",
NULL
};
char *msg_help_funclist[] = {
"enShow a list of aliases",
NULL
};
#endif
/* Command must be grouped in ascending levels to make the CMD
* produce a nice output.
*/
struct Command cmds[] =
{
/***********************************************************************
Explanations of the Command struct fields inited in here:
=========================================================
Name - name of the command, if aliases are wanted they should be entered
like "NAME1\0NAME2 NAME3 NANE4" and a switch below must be set to
TRUE (the 'aliases')
Function - called upon usage of the command
Level - internal defined level required to use the command
Showable - (switch) Output can be redirected to another person
Needpass - (switch) Password protected
needcomma - (switch) Comma is part of argument, not argument seperator
aliases - (switch) Aliases exist for this command
public - (switch) Command can be used in public
hide - (switch) Don't show the command line in the logfile or spylink
remote - (switch) Can be executed from remote link
Syntax - plain text description of how to use the command
Help - pointer to helptext for the command
Flags - Used for command-specific run-time switches
***********************************************************************/
/* --- Unknown users --- */
{"HELP\0INFO ? HELLO HI ", CmdHelp,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE,
"[<cmd>]",
msg_help_help, CMD_NONE},
{"SYNTAX\0MAN ", CmdSyntax,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
"<cmd>",
msg_help_syntax, CMD_NONE},
{"EXPLAIN\0FAQ DESCRIBE WHATIS ", CmdExplain,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"[-S] <subject[*]>",
msg_help_explain, CMD_NONE},
{"RULES", CmdRules,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_rules, CMD_NONE},
{"SEEN\0SAW ", CmdSeen,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE,
"[ -M | -A | -R ] <nick/pattern>",
msg_help_seen, CMD_NONE},
{"SVIEW\0WHOIS ", CmdSview,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"[-S] [-A] [-R] [nick]",
msg_help_sview, CMD_NONE},
{"CMD\0COMMANDS ", CmdCmd,
LEVEL_ANYBODY, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[pattern]",
msg_help_cmd, CMD_NONE},
{"UPTIME", CmdUptime,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_uptime, CMD_NONE},
{"SPLIT\0NETSPLIT ", CmdSplit,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"",
msg_help_split, CMD_NONE},
{"TELLME", CmdTellme,
LEVEL_ANYBODY, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[-A]",
msg_help_tellme, CMD_NONE},
{"ALIAS", CmdAlias,
LEVEL_ANYBODY, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<cmd>",
msg_help_alias, CMD_NONE},
{"WHOLEFT", CmdWholeft,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[-A]",
msg_help_wholeft, CMD_NONE},
{"SHOW", CmdNone,
LEVEL_ANYBODY, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<nick> <command> [<arguments>]",
msg_help_show, CMD_NONE},
{"IDENT", CmdIdent,
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE,
"<password> [registered nick]",
msg_help_ident, CMD_NONE | CMD_IDENT},
#ifdef BAGDER
{"FILEGET", CmdFileGet,
LEVEL_ANYBODY, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<filename>",
NULL, CMD_NONE},
#endif
/* --- Recognized users --- */
{"PASS", CmdPass,
LEVEL_RECOG, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE,
"<password>",
msg_help_pass, CMD_NONE},
{"COMMENT", CmdComment,
LEVEL_RECOG, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"[-N <nickname>] <comment>",
msg_help_comment, CMD_NONE},
{"CONVERT", CmdConvert,
LEVEL_RECOG, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<value> <unit> [ # of decimals ]",
msg_help_convert, CMD_NONE},
{"TZ\0TIME CLOCK ", CmdTz,
LEVEL_RECOG, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"[<time>/now/list] <country #1> [country #2]",
msg_help_tz, CMD_NONE},
{"SPELL", CmdSpell,
LEVEL_RECOG, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<word(s)>",
msg_help_spell, CMD_NONE},
{"NEWPASS\0SETPASS CHPASS ", CmdNewPass,
LEVEL_RECOG, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE,
"<password>",
msg_help_newpass, CMD_NONE},
{"MYNICK", CmdIdentify,
LEVEL_RECOG, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<nick>",
msg_help_mynick, CMD_NONE},
{"FIND", CmdFind,
LEVEL_RECOG, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<regex> [<matches>]",
msg_help_find, CMD_NONE},
{"COUNTRY\0WHEREIS ", CmdCountry,
LEVEL_RECOG, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"[ <nick> | .<id> ]",
msg_help_country, CMD_NONE},
{"CALC", CmdCalc,
LEVEL_RECOG, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<expression>",
msg_help_calc, CMD_NONE},
{"TELL\0TELLADD ", CmdTelladd,
LEVEL_RECOG, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE,
"<who> <msg>",
msg_help_tell, CMD_NONE},
{"TELLDEL", CmdTelldel,
LEVEL_RECOG, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE,
"[ <who> | <tell id> ]",
msg_help_telldel, CMD_NONE},
{"TELLLIST\0TLIST ", CmdTelllist,
LEVEL_RECOG, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE,
"",
msg_help_telllist, CMD_NONE},
{"TOP\0TOPLIST ", CmdToplist,
LEVEL_RECOG, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"<joined/joins/idle/talk/country/continent/command/kick/kicker/banner/mode>",
msg_help_toplist, CMD_NONE},
{"CUT", CmdCut,
LEVEL_RECOG, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[<nick>]",
msg_help_cut, CMD_NONE},
{"INVITE", CmdInvite,
LEVEL_RECOG, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE,
"<password>",
msg_help_invite, CMD_NONE},
{"CLIENT", CmdClient,
LEVEL_RECOG, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE,
"",
msg_help_client, CMD_NONE},
{"EMAIL", CmdEmail,
LEVEL_RECOG, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<user>",
msg_help_email, CMD_NONE},
{"SETEMAIL", CmdSetEmail,
LEVEL_RECOG, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[-N <nickname>] <email>",
msg_help_setemail, CMD_NONE},
{"EXCHANGE", CmdExchange,
LEVEL_RECOG, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<amount> <from currency> <to currency>",
msg_help_exchange, CMD_NONE},
{"LANGUAGE", CmdLanguage,
LEVEL_RECOG, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<language>",
msg_help_language, CMD_NONE},
{"NEWSLIST", CmdNewsList,
LEVEL_RECOG, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE,
"[number of items]",
msg_help_newslist, CMD_NONE},
{"VOICE", CmdVoice,
LEVEL_RECOG, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE,
"[<password>]",
msg_help_voice, CMD_NONE},
{"DEVOICE\0UNVOICE ", CmdDeVoice,
LEVEL_RECOG, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE,
"[<password>]",
msg_help_devoice, CMD_NONE},
#ifdef NICKSERV
{"BOTOP", CmdBotop,
LEVEL_RECOG, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_op, CMD_NONE},
#endif
/* --- Chanop --- */
{"TOPIC", CmdTopic,
LEVEL_CHANOP, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
"[<topic>]",
msg_help_topic, CMD_NONE},
{"OP\0OPS OPME CHANOP ", CmdOp,
/* passwd checked in code */
LEVEL_CHANOP, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE,
"[<password>]",
msg_help_op, CMD_NONE},
{"USERLIST\0ULIST USERS ", CmdUserlist,
LEVEL_CHANOP, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[-V] [-X lines] [-N nick] [-C changed] [-P host pattern]"
" [-A last done] [-F flags] [-L levelrange] [-T age range]"
" [-M age since modified range]",
msg_help_userlist, CMD_NONE},
{"SAY", CmdSay,
LEVEL_CHANOP, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE,
"<phrase>",
msg_help_say, CMD_NONE},
{"ME\0ACTION ", CmdMe,
LEVEL_CHANOP, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE,
"<phrase>",
msg_help_me, CMD_NONE},
{"TALK", CmdTalk,
LEVEL_CHANOP, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_talk, CMD_NONE},
{"QUIET\0SILENT SHUTUP ", CmdQuiet,
LEVEL_CHANOP, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
"",
msg_help_quiet, CMD_NONE},
{"LAG", CmdLag,
LEVEL_CHANOP, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_lag, CMD_NONE},
{"REPORTADD", CmdReportadd,
LEVEL_CHANOP, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"",
msg_help_reportadd, CMD_NONE},
{"REPORTDEL", CmdReportdel,
LEVEL_CHANOP, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"",
msg_help_reportdel, CMD_NONE},
{"KICKLIST\0KLIST ", CmdKicklist,
LEVEL_CHANOP, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE,
"[match]",
msg_help_kicklist, CMD_NONE},
{"WARNLIST\0WLIST ", CmdWarnlist,
LEVEL_CHANOP, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[-A] [-B] [match]",
msg_help_warnlist, CMD_NONE},
/* --- Trusted users --- */
{"BAN\0KB ", CmdBan,
LEVEL_TRUST, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE,
"[-E] [-K] [*]<nick> [time] [reason]",
msg_help_ban, CMD_NONE},
{"KICK", CmdKick,
LEVEL_TRUST, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"[-K] [*]<nick> [reason]",
msg_help_kick, CMD_NONE},
{"UNBAN", CmdUnban,
LEVEL_TRUST, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<ID/nick/pattern>",
msg_help_unban, CMD_NONE},
{"BANLIST\0BLIST ", CmdBanlist,
LEVEL_TRUST, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[-A] [-U] [match]",
msg_help_banlist, CMD_NONE},
{"CHBAN", CmdChban,
LEVEL_TRUST, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[ -E | -U | -R ] <nick/banid> [new time/reason]",
msg_help_chban, CMD_NONE},
{"VRFY\0VERIFY ", CmdVrfy,
LEVEL_TRUST, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[ <nick> | <user@host> ]",
msg_help_vrfy, CMD_NONE},
{"HOST", CmdHost,
LEVEL_TRUST, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[ <nick> | <host> ]",
msg_help_host, CMD_NONE},
{"FINGER", CmdFinger,
LEVEL_TRUST, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[ <nick> | <host> ]",
msg_help_finger, CMD_NONE},
{"CHAT", CmdChat,
LEVEL_TRUST, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"",
msg_help_chat, CMD_NONE},
{"NEWSADD", CmdNewsAdd,
LEVEL_TRUST, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE,
"[-P pattern] [-U] [-E expire] <level> <news>",
msg_help_newsadd, CMD_NONE},
{"NEWSDEL", CmdNewsDel,
LEVEL_TRUST, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE,
"[id]",
msg_help_newsdel, CMD_NONE},
/* --- Expert users --- */
{"LEAVE\0PART ", CmdLeave,
LEVEL_EXPERT, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"",
msg_help_leave, CMD_NONE},
{"JOIN", CmdJoin,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"<channel> [<key>]",
msg_help_join, CMD_NONE},
{"STATUS\0STATS ", CmdStatus,
LEVEL_EXPERT, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[-A]",
msg_help_status, CMD_NONE},
{"CMODE", CmdCmode,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[<modes>]",
msg_help_cmode, CMD_NONE},
{"CKEY", CmdCkey,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[ <key> | - ]",
msg_help_ckey, CMD_NONE},
{"NICK", CmdNick,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[ <newnick> | + ]",
msg_help_nick, CMD_NONE},
{"SET", CmdSet,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[<label> [<value>]]",
msg_help_set, CMD_NONE},
{"MUTE", CmdMute,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_mute, CMD_NONE},
{"WARNADD", CmdWarnadd,
LEVEL_EXPERT, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"[-B] [*]<nick>/<pattern> <description>",
msg_help_warnadd, CMD_NONE},
{"WARNDEL", CmdWarndel,
LEVEL_EXPERT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<nick/warnID/pattern>",
msg_help_warndel, CMD_NONE},
{"CLIENTLIST\0CLIST ", CmdClientlist,
/* Further level checks in code */
LEVEL_EXPERT, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
"",
msg_help_clientlist, CMD_NONE},
{"GUESTLIST\0GLIST ", CmdNames,
LEVEL_EXPERT, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[match]",
msg_help_names, CMD_NONE},
/* --- Maintainer --- */
{"BACKLOG\0LASTLOG ", CmdBacklog,
LEVEL_BOT, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"[entries]",
msg_help_backlog, CMD_NONE},
#ifdef CONFMODE
{"CONF". CmdConf,
LEVEL_BOT, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE,
"<INIT TOPIC/END/PAUSE/CONT>",
NULL, CMD_NONE},
#endif
{"DO", CmdDo,
LEVEL_BOT, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE,
"<raw irc cmd>",
msg_help_do, CMD_NONE},
{"EXPADD\0EXPLAINADD FAQADD ", CmdExpAdd,
LEVEL_BOT, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE,
"<word>=<explaination>",
msg_help_expadd, CMD_NONE},
{"EXPDEL\0EXPLAINDEL FAQDEL ", CmdExpDel,
LEVEL_BOT, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE,
"<word>",
msg_help_expdel, CMD_NONE},
{"USERADD", CmdUserAdd,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[-Q] [-P <pattern>] [-N <password>] [-R <regged nick>] <nick> <level> [email/real name]",
msg_help_useradd, CMD_NONE},
{"USERDEL", CmdUserDel,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[-Q] [ -U | -F ] [-R] <nick>",
msg_help_userdel, CMD_NONE},
{"USERMOD", CmdUserMod,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[-Q] [-P <pattern>] [-D <pattern or pattern number>] [-N <password>] [-C <comment>] [-E <email>] [-F <+-flags>] [-R <regged nick>] <nick> [level]",
msg_help_usermod, CMD_NONE},
{"DEFPASS", CmdDefPass,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"<nick>",
msg_help_defpass, CMD_NONE},
{"SPYADD", CmdSpyadd,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_spyadd, CMD_NONE},
{"SPYDEL", CmdSpydel,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_spydel, CMD_NONE},
{"DEBUGADD", CmdDebugadd,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_debugadd, CMD_NONE},
{"DEBUGDEL", CmdDebugdel,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_debugdel, CMD_NONE},
{"SERVERADD", CmdServerAdd,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<name> [port] [password]",
msg_help_serveradd, CMD_NONE},
{"SERVERLIST", CmdServerList,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_serverlist, CMD_NONE},
{"SERVERDEL", CmdServerDel,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<name/ID>",
msg_help_serverdel, CMD_NONE},
{"SERVERSTAT", CmdServerStat,
LEVEL_BOT, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[-D] [server]",
msg_help_serverstat, CMD_NONE},
/* --- Owner --- */
{"USED", CmdUsed,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<nick>",
msg_help_used, CMD_NONE},
#ifdef BREESE
{"LINK", CmdLink,
LEVEL_OWNER, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"<nick>",
msg_help_link, CMD_NONE},
{"LINKLIST\0LLIST ", CmdLinklist,
LEVEL_OWNER, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"",
msg_help_linklist, CMD_NONE},
{"REMOTE\0ON ", CmdRemote,
LEVEL_OWNER, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,
"<linkbot> <cmd> [<args>]",
NULL, CMD_NONE},
#endif
{"RELOAD", CmdReload,
LEVEL_OWNER, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"[<userfile>]",
msg_help_reload, CMD_NONE},
{"WALL", CmdWall,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE,
"<msg>",
msg_help_wall, CMD_NONE},
{"SHUTDOWN", CmdShutdown,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"[ -C | <time> [<reason>] ]",
msg_help_shutdown, CMD_NONE},
{"QUIT", CmdQuit,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"[<reason>]",
msg_help_quit, CMD_NONE},
{"SERVER", CmdServer,
LEVEL_OWNER, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"<server> [port] [password] or '+' or <server ID>",
msg_help_server, CMD_NONE},
{"MODERATE", CmdModerate,
LEVEL_OWNER, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"[ ON | OFF ]",
msg_help_moderate, CMD_NONE},
{"CHGCMDLEV", CmdChgCmdLev,
LEVEL_OWNER, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
"<command> <level/->",
msg_help_chgcmdlev, CMD_NONE},
#ifdef BREESE
{"WEBSTER\0DICT ", CmdWebster,
LEVEL_OWNER, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
"<word>",
msg_help_webster, CMD_NONE},
#endif
{"LOG", CmdLog,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"ALL | NONE | [-]<type>, where <type> = JOIN | KICK | NICK | MODE | TOPIC | CMD | MSG | CTCP | CLIENT | WARN | SPLIT | DEBUG | INIT | PUB",
msg_help_log, CMD_NONE},
#ifdef FUNCS_HACK
{"FUNCADD", CmdFuncAdd,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<flags> <name/string> <action>",
msg_help_funcadd, CMD_NONE},
{"FUNCDEL", CmdFuncDel,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"<id/match>",
msg_help_funcdel, CMD_NONE},
{"FUNCLIST", CmdFuncList,
LEVEL_OWNER, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
"",
msg_help_funclist, CMD_NONE},
#endif
#ifdef CONFMODE
/* Conference commands only available and visible only while in CONF MODE.
The CMD_CONFOPER commands should be visible to CONFOPERS.
The CMD_VICTIM commands are visible to VICTIMS.
*/
{"ASK", CmdAsk,
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
"<question>",
msg_help_ask, CMD_CONF},
{"ASKME", CmdAskMe, /* Only available for CONFOPERS and VICTIMS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"",
msg_help_askme, CMD_CONFOPER | CMD_VICTIM},
{"ASKINFO", CmdAskInfo,
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
"",
msg_help_askinfo, CMD_CONF},
{"ASKLIST", CmdAskList,
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
"[-<start id>] [number of questions]",
msg_help_asklist, CMD_CONF},
{"CONFINFO", CmdConfInfo,
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
"",
msg_help_confinfo, CMD_CONF},
{"CONFHELP", CmdConfHelp,
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
"",
msg_help_confhelp, CMD_CONF},
{"CONFVICT", CmdConfVict, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"[-D] <nick> [description]",
msg_help_confvict, CMD_CONFOPER},
{"CONFOPER", CmdConfOper, /* Only available for CONFOPERS (or 200+ users
if there is no CONFOPERS) */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"[-D] <nick>",
msg_help_confoper, CMD_CONFOPER},
{"QHALT", CmdQHalt, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"[-U] <id>",
msg_help_qhalt, CMD_CONFOPER},
{"QDEL", CmdQDel, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"<id>",
msg_help_qdel, CMD_CONFOPER},
{"QREV", CmdQRev, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"<id> <question>",
msg_help_qrev, CMD_CONFOPER},
{"QPRIO", CmdQPrio, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"<id> <+/-><steps>",
msg_help_qprio, CMD_CONFOPER},
{"QBAN", CmdQBan, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"[ [+/-]<nick/pattern> [reason] ]",
msg_help_qban, CMD_CONFOPER},
{"QSNOOP", CmdQSnoop, /* Only available for CONFOPERS */
LEVEL_ANYBODY, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE,
"",
msg_help_qsnoop, CMD_CONFOPER},
#endif
{NULL, (void(*)())(NULL),
0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
NULL,
NULL, 0}
};
const long numCmds = sizeof(cmds)/sizeof(cmds[0]);
typedef struct {
struct Header h;
char name[32];
int count;
} topitem;
/* --- CommandInit ------------------------------------------------ */
void CommandInit(void)
{
int i;
snapshot;
for (i=0; cmds[i].name; i++) {
cmds[i].orglevel = cmds[i].level;
cmds[i].level = levels[ cmds[i].level ];
}
}
/* --- FindCommand ------------------------------------------------ */
char *checkaliases(char *name, char *aliases)
{
char *p1, *p2;
int len;
snapshot;
len = StrLength(name);
p1 = StrIndex(aliases, (char)0) + 1;
while (p2 = StrIndex(p1, ' ')) {
/* fprintf(stderr, "%d=%d %s\n", len, p2 - p1, p1); */
if ((p2 - p1) == len) {
if (StrEqualMax(name, len, p1))
return p1;
}
p1 = p2 + 1;
}
return NULL;
}
struct Command *FindCommand(char *name)
{
int i;
#ifdef HAVE_LIBFPL
itemfplcmd *f;
#endif
snapshot;
#ifdef HAVE_LIBFPL
f = fCmdFind(name);
if (f) {
return &(f->command);
}
#endif
for (i=0; cmds[i].name; i++) {
if (StrEqual(cmds[i].name, name) ||
(cmds[i].aliases && checkaliases(name, cmds[i].name))) {
return &cmds[i]; /* Match */
}
}
return NULL;
}
/* --- ParseCommand ----------------------------------------------- */
bool ParseCommand(char *from, char *line, bool oktorun)
{
char *cmd, *param, *to;
char *nextline, *nextparam;
bool showto = FALSE;
bool result = TRUE;
struct Command *command;
snapshot;
if (from && StrEqual(from, nickname))
Log(LOG, "Ignored message from myself");
else if (line && *line) {
do {
/*
* <<< From version 4.4 >>>
*
* We (might) switch language here. Do note that if the 'current' isn't
* the one that receives the output, CHANGE language back to
* 'defaultlang'.
*/
if (current->user)
uselang = current->user->language;
else
uselang = defaultlang;
if (shuttingdown && !chat) {
Send(errfrom, GetText(msg_shutdown_in_progress));
result = FALSE;
break;
}
nextline = line;
do {
cmd = nextline;
nextline = StrIndex(nextline, '\n');
if (nextline)
*nextline++ = (char)0;
while (iswhite(*cmd))
cmd++;
if (NIL == *cmd) {
result = FALSE;
break;
}
/* Skip command */
param = cmd;
while (*param && !iswhite(*param))
param++;
if (*param) {
*param++ = (char)0;
while (iswhite(*param))
param++;
}
SnoopCommand(from, cmd, param);
if (*param) {
if (StrEqual(cmd, "SHOW")) {
if (client)
errfrom = client->ident->nick;
client = NULL; /* no client to send command output to, the
errors still go to errfrom though, which still
go to the person doing the SHOW - Bagder */
chat = FALSE; /* not sent to chat */
to = cmd = param;
while (*cmd && !iswhite(*cmd))
cmd++;
if (*cmd) {
*cmd++ = (char)0;
while (iswhite(*cmd))
cmd++;
}
if (NIL == *cmd) {
result = FALSE;
break;
}
param = cmd;
while (*param && !iswhite(*param))
param++;
if (*param)
*param++ = (char)0;
public = IsChannel(to);
if (public) {
if (current->level < LEVELCHANOP ) {
Send(errfrom, GetText(msg_need_higher_level));
result = FALSE;
break;
}
}
showto = TRUE;
}
}
command = FindCommand(cmd);
if (command && (command->level > current->level) && !oktorun) {
if (showto)
Send(errfrom, GetText(msg_nothing_shown));
result = FALSE;
break;
}
else if (command && !oktorun) {
if (command->needpass && !current->passed) {
if (StrEqual(command->name, "NEWPASS") && current->user &&
CheckPassword(defaultpasswd, current->user->passwd))
;
else {
if (StrEqual(command->name, "CUT") && client && (client->lasttime < now))
SendNick(current->nick, GetText(msg_use_pass_first));
else
Send(errfrom, GetText(msg_use_pass_first));
result = FALSE;
break;
}
}
if (public && !command->public) {
if (showto)
Send(errfrom, GetText(msg_nothing_shown));
else
Send(errfrom, GetText(msg_cant_use_in_public));
result = FALSE;
break;
}
}
else if (NULL == command) {
/* Alias system checks */
line = FuncRun(from, cmd, param, current->level,
((chat ? FUNC_DCC : 0) | (public ? FUNC_PUBLIC : 0) |
(current->passed ? FUNC_PWD : 0)),
oktorun);
if (line) {
cmd = line;
while (iswhite(*cmd))
cmd++;
if (NIL == *cmd) {
result = FALSE;
break;
}
/* Skip command */
param = cmd;
while (*param && !iswhite(*param))
param++;
if (*param) {
*param++ = (char)0;
while (iswhite(*param))
param++;
}
command = FindCommand(cmd);
if (NULL == command) {
result = FALSE;
break;
}
}
else {
result = FALSE;
break;
}
}
if (showto) {
if (command->showable)
from = to;
else {
Send(errfrom, GetText(msg_cant_show));
result = FALSE;
break;
}
}
nextparam = NULL;
do {
if (!command->needcomma && (nextparam = StrIndex(param, ',')))
*nextparam++ = (char)0;
/* What was started as a privately invoked command in another
language has to be set to the default language in case it is
shown to another user or even to the public */
if (showto || public)
uselang = defaultlang;
command->counter++;
if (command->function)
command->function(from, param);
#ifdef HAVE_LIBFPL
else {
itemfplcmd *f;
f = fCmdFind(command->name);
if (f)
fplrunner(f->fpl, param);
}
#endif
param = nextparam;
} while (param && *param);
} while (result && nextline); /* possibly get the next one */
} while (0); /* never loop! */
}
uselang = defaultlang;
return result;
}
/* --- CmdChgCmdLev ----------------------------------------------- */
void CmdChgCmdLev(char *from, char *line)
{
char cmd[MINIBUFFER];
char levelbuf[10];
int level;
struct Command *command;
snapshot;
if (2 == StrScan(line, "%"MINIBUFFERTXT"s %9s", cmd, levelbuf)) {
level = atoi(levelbuf);
command = FindCommand(cmd);
if (command) {
if (command->level > current->level) {
Send(from, GetText(msg_permission_denied));
}
else {
if ('-' == levelbuf[0]) {
Sendf(from, GetText(msg_command_restored), command->name,
command->level, levels[command->orglevel]);
command->level = levels[command->orglevel];
command->flags &= ~CMD_CHANGED;
}
else if ((level >= LEVELANYBODY) && (level <= LEVELOWNER)) {
Sendf(from, GetText(msg_changed_command_level), command->name,
command->level, level);
command->level = level;
command->flags |= CMD_CHANGED;
}
SaveSettings();
}
}
}
else
CmdSyntax(errfrom, "CHGCMDLEV");
}
/* --- OutCommand ------------------------------------------------- */
/* This is just a dirty hack which is bound to cause problems later on */
void OutCommand(char *from, char *userhost, char *line)
{
char buffer[MIDBUFFER];
itemuser *u;
snapshot;
#ifdef HAVE_LIBFPL
if (runfpl(RUN_OFFMSG, line, FPLRUN_PRE))
return;
#endif
u = FindUser(from, userhost);
if (u && (u->level >= LEVELRECOG)) {
if (1 == StrScan(line, "%*[iI]%*[nN]%*[vV]%*[iI]%*[tT]%*[eE] %"MIDBUFFERTXT"s", buffer)) {
InviteMe(from, u, buffer);
Logf(LOGMSG, "INVITE request by %s (%s)", from, userhost);
}
#if 0 /* Crashes because Outgoing() uses current */
else if (1 == StrScan(line, "%*[cC]%*[lL]%*[iI]%*[eE]%*[nN]%*[tT] %"MIDBUFFERTXT"s", buffer)) {
CmdClient(from, buffer);
Logf(LOGMSG, "CLIENT request by %s (%s)", from, userhost);
}
#endif
}
else {
Multicastf(SPYCAST, GetDefaultText(msg_spycast_outofchannel),
line, from, userhost);
Logf(LOGMSG, "\"%s\" received from %s (%s)", line, from, userhost);
}
runfpl(RUN_OFFMSG, line, FPLRUN_POST);
}
/* --- Command ---------------------------------------------------- */
#define MAX_BACKLOG 20
struct LogItem {
char *line;
time_t timestamp;
};
struct LogItem backlog[MAX_BACKLOG];
int backlognow = 0; /* index of current position */
int backlogamount = 0; /* amount of data used */
void Backlog(char *line)
{
snapshot;
if (backlog[ backlognow ].line)
/* free previous allocation */
StrFree(backlog[ backlognow ].line);
backlog[ backlognow ].line = StrDuplicate(line);
backlog[ backlognow ].timestamp = now; /* time */
if (++backlognow == MAX_BACKLOG)
backlognow = 0;
if (backlogamount < MAX_BACKLOG)
backlogamount++;
}
void LogCommand(char *from, char *uhost, char *cmdline, bool private)
{
char temp[MAXLINE+256];
char cmd[10];
struct Command *command;
int type = private ? LOGCMD : LOGPCMD;
bool hide = FALSE;
snapshot;
if (1 == StrScan(cmdline, " %9s", cmd)) {
if (command = FindCommand(cmd)) {
if (command->hide) {
hide = TRUE;
}
}
}
if (hide) {
Logf(type, "\"%s\" used by %s (%s) [snoop prevented]", cmd, from, uhost);
StrFormatMax(temp, sizeof(temp), GetDefaultText(msg_snoop_hidden),
cmd, from, uhost, GetDefaultText(msg_snoop_prevented));
}
else {
Logf(type, "\"%s\" by %s (%s)", cmdline, from, uhost);
StrFormatMax(temp, sizeof(temp), GetDefaultText(msg_snoop_line),
cmdline, from, uhost);
}
Backlog(temp);
}
void Command(char *from, char *userhost, char *line)
{
itemguest *g;
snapshot;
if (cmdchar == line[0])
line++;
g = FindNick(from);
if (g) {
LogCommand(from, userhost, line, TRUE);
current = g->ident;
client = current->client;
if (client) { /* Reply through dcc chat if possible */
chat = TRUE;
from = errfrom = NULL;
}
servedmsgcmd++;
ParseCommand(from, line, FALSE);
}
else {
/* Received a message from outside the channel */
current = NULL;
OutCommand(from, userhost, line);
}
}
/* --- DccCommand ------------------------------------------------- */
void DccCommand(char *line)
{
snapshot;
StrTokenize(line, "\r\n");
current = client->ident;
client->lasttime = now;
errfrom = NULL;
chat = TRUE;
public = FALSE;
if ((client->flags & CHATCAST) && (*line != cmdchar)) {
if (*line == ccmdchar) {
line++;
/* we use the good old slash to detect CHAT mode commands */
if (StrEqualMax(line, 4, "HELP")) {
Sendf(NULL, GetText(msg_chat_mode_cmd),
ccmdchar, ccmdchar, ccmdchar, ccmdchar, ccmdchar, cmdchar);
}
else if (StrEqualMax(line, 4, "QUIT")) {
client->flags &= ~CHATCAST;
Send(NULL, GetText(msg_chat_mode_off));
Multicastf(CHATCAST, GetText(msg_left_chat), current->nick);
}
else if (StrEqualMax(line, 4, "ECHO")) {
client->chatecho ^= TRUE;
Sendf(NULL, GetText(msg_echo_has_been_turned),
OnOff(client->chatecho));
}
else if (StrEqualMax(line, 5, "NAMES")) {
itemclient *p;
for (p = First(clientHead); p; p = Next(p)) {
if (p->flags & CHATCAST)
Sendf(NULL, "*** %s (%s)", p->ident->nick, p->ident->host);
}
}
else if (StrEqualMax(line, 2, "ME")) {
Multicastf(CHATCAST, "* %s%s", current->nick, line+2);
}
else
Send(NULL, GetText(msg_unknown_command));
}
else {
Multicastf(CHATCAST, "<%s> %s", current->nick, line);
}
return;
}
serveddcccmd++;
if (*line == cmdchar) line++;
LogCommand(client->ident->nick, "DCC Chat", line, TRUE);
ParseCommand(NULL, line, FALSE);
}
/* --- PubCommand ------------------------------------------------- */
void PubCommand(char *from, char *userhost, char *line)
{
char tonick[NICKLEN+1];
char *param;
char start;
itemguest *g;
snapshot;
g = FindNick(from);
if (g) {
current = g->ident;
runfpl(RUN_PUBLIC, line, FPLRUN_PRE);
if (floodmode && !masterflood)
FloodCheck(g);
Check(g, line);
if (repeatmode)
RepeatCheck(g, line);
g->posttime = now;
g->posts++;
if (current->user && ((current->level >= LEVELPUB) ||
(g->flags.chanop && (current->level >= LEVELPUBX))) &&
(2 <= StrScan(line, "%"NICKLENTXT"[^ :,>;!]%*[ :,>;!]%c",
tonick, &start)) &&
(StrEqualMax(tonick, MAX(StrLength(tonick), 4), nickname) ||
StrEqualMax(tonick, MAX(StrLength(tonick), 4), staticnick))) {
param = StrIndex(&line[StrLength(tonick)], start);
if (param) {
LogCommand(from, userhost, param, FALSE);
if (ParseCommand(channel, param, FALSE))
servedpubcmd++;
}
}
else {
Logf(LOGPUB, "<%s> %s", from, line);
if (talkative && !mute) {
line = FuncMatch(from, line, current->level, 0);
if (line) {
/* We got a command line to perform */
errfrom = NULL; /* Pipe "error messages" to eternety */
ParseCommand(channel, line, TRUE);
}
}
}
}
#if 0
else { /* Someone from outside channel, when channel mode is -n */
}
#endif
lastpost = now;
}
/* --- CmdNone ---------------------------------------------------- */
void CmdNone(char *from, char *line)
{
snapshot;
Send(errfrom, GetText(msg_not_implemented));
}
/* --- CmdHelp ---------------------------------------------------- */
void CmdHelp(char *from, char *line)
{
char *bufcmd, *bufarg, *ptr;
struct Command *cmd;
snapshot;
bufcmd = NextWord(line);
if (bufcmd) {
bufarg = NextWord(line);
if (bufarg) {
if (StrEqual(bufcmd, "SET") && (current->level >= LEVELEXPERT)) {
HelpSet(from, bufarg);
return;
}
}
cmd = FindCommand(bufcmd);
if (cmd) {
if (cmd->function) {
ptr = StrFormatAlloc(GetText(cmd->help), defaultpasswd);
if (ptr) {
SendMulti(from, "%s: %s.", bufcmd, ptr);
StrFree(ptr);
}
}
#ifdef HAVE_LIBFPL
else {
itemfplcmd *f;
f = fCmdFind(bufcmd);
if (f)
SendMulti(from, "%s: %s.", bufcmd, f->help);
}
#endif
if (helpsyntax)
SendMulti(from, GetText(msg_usage), bufcmd, cmd->syntax);
}
else
Sendf(errfrom, GetText(msg_no_such_alias), bufcmd);
}
else
Sendf(from, GetText(msg_help_short), VERSIONMSG, nickname);
}
/* --- CmdBacklog ----------------------------------------------------- */
void CmdBacklog(char *from, char *line)
{
int amount = 5;
int index;
snapshot;
StrScan(line, "%d", &amount);
amount = abs(amount);
if (amount > backlogamount)
amount = backlogamount;
index = backlognow;
while (amount--) {
if (--index < 0)
index = MAX_BACKLOG-1;
Sendf(from, GetText(msg_backlog_entry), TimeAgo(backlog[index].timestamp),
backlog[index].line);
}
}
/* --- CmdLanguage ------------------------------------------------ */
void CmdLanguage(char *from, char *line)
{
char buffer[MINIBUFFER];
snapshot;
if (current->user) {
if (1 == StrScan(line, "%"MINIBUFFERTXT"s", buffer)) {
current->user->language = LanguageNum(buffer);
Sendf(from, GetText(msg_language_set_to),
LanguageLocal(current->user->language));
return;
}
else
LanguageList(from);
}
CmdSyntax(errfrom, "LANGUAGE");
}
/* --- CmdSyntax -------------------------------------------------- */
void CmdSyntax(char *from, char *line)
{
char *msg;
struct Command *cmd;
snapshot;
msg = NextWord(line);
if (msg) {
cmd = FindCommand(msg);
if (cmd)
Sendf(from, GetText(msg_usage), msg, cmd->syntax);
else
Sendf(errfrom, GetText(msg_no_such_alias), msg);
}
else
CmdSyntax(errfrom, "SYNTAX");
}
/* --- CmdCmd ----------------------------------------------------- */
static bool cmdlistadd(struct Command *cmd, int level, int *nextlevel,
struct Command **cmdptr)
{
snapshot;
if ((cmd->level > level) && (cmd->level < *nextlevel))
*nextlevel = cmd->level;
if (cmd->level == level) {
*cmdptr = cmd;
return TRUE;
}
return FALSE;
}
int comparecmd(struct Command **cmd1, struct Command **cmd2)
{
snapshot;
return (strcasecmp((*cmd1)->name, (*cmd2)->name));
}
void CmdCmd(char *from, char *line)
{
int i;
char buffer[MIDBUFFER];
char onecmd[MINIBUFFER];
char somebytes[8];
int level=0, nextlevel;
char *bufp;
char pattern[MINIBUFFER]="*";
int amount;
int len;
#if !defined(AMIGA) || defined(__GNUC__)
struct Command *listofcmds[numCmds];
#else
struct Command **listofcmds = malloc(numCmds * sizeof(struct Command *));
snapshot;
if (NULL == listofcmds)
return;
#endif
StrScan(line, "%"MINIBUFFERTXT"s", pattern);
Send(from, GetText(msg_available_commands));
/* Sort commands as there is chgcmdlev which can change command levels */
/* FPL added commands taken into consideration too... =) */
do {
nextlevel = 999999999;
amount=0;
for (i=0; cmds[i].name ; i++) {
if(cmds[i].flags&CMD_IDENT && identprotect)
continue;
if(Match(cmds[i].name, pattern)) {
if(cmdlistadd(&cmds[i], level, &nextlevel, &listofcmds[amount])) {
amount++;
}
}
}
#ifdef HAVE_LIBFPL
{
extern itemfplcmd *fcmdHead;
itemfplcmd *f;
for (f = First(fcmdHead); f; f = Next(f)) {
if (Match(f->command.name, pattern)) {
if (cmdlistadd(&(f->command), level, &nextlevel, &listofcmds[amount]))
amount++;
}
}
}
#endif
if (amount) {
/* Sort the array of commands, and output accordingly */
StrFormatMax(buffer, sizeof(buffer), "%s %d", GetText(msg_level), level);
len = StrLength(buffer);
bufp = buffer + len;
qsort(&listofcmds[0], amount, sizeof(struct Command *),
(int (*)(const void *, const void *))comparecmd);
for (i=0; i < amount; i++) {
struct Command *cmd = listofcmds[i];
if (cmd->showable || cmd->needpass || cmd->public )
StrFormatMax(somebytes, sizeof(somebytes), "[%s%s%s]",
cmd->needpass ? "*" : "",
cmd->public ? "P" : "",
cmd->showable ? "S" : "");
else
somebytes[0] = (char)0;
StrFormatMax(onecmd, sizeof(onecmd), " %s%s", cmd->name, somebytes);
if ((len + StrLength(onecmd)) > MIDBUFFER) {
Send(from, buffer);
bufp = buffer;
len = 0;
}
StrCopy(bufp, onecmd);
len += StrLength(onecmd);
bufp += StrLength(onecmd);
}
Send(from, buffer);
}
level = nextlevel;
} while (level <= current->level);
#if defined(AMIGA) && !defined(__GNUC__)
free(listofcmds);
#endif
}
/* --- CmdExchange ------------------------------------------------ */
void CmdExchange(char *from, char *line)
{
snapshot;
Exchange(from, line);
}
/* --- CmdRules --------------------------------------------------- */
void CmdRules(char *from, char *line)
{
snapshot;
Send(from, rulesmsg);
}
/* --- CmdExpAdd -------------------------------------------------- */
void CmdExpAdd(char *from, char *line)
{
snapshot;
ExplainAdd(from, line);
}
/* --- CmdExpDel -------------------------------------------------- */
void CmdExpDel(char *from, char *line)
{
snapshot;
ExplainDel(from, line);
}
/* --- CmdExplain ------------------------------------------------- */
void CmdExplain(char *from, char *line)
{
snapshot;
Explain(from, line);
}
/* --- CmdUptime -------------------------------------------------- */
void CmdUptime(char *from, char *line)
{
extern time_t uptime;
char buffer[BIGBUFFER];
snapshot;
#if 1
strftime(buffer, sizeof(buffer), "%B %d. %H:%M:%S", localtime(&uptime));
#else
strftime(buffer, sizeof(buffer), "%x %X", localtime(&uptime));
#endif
Sendf(from, GetText(msg_uptime_result), TimeAgo(uptime), buffer);
}
/* --- CmdWhois --------------------------------------------------- */
void ReportAccounts(char *from, itemuser *u)
{
char buffer[MIDBUFFER] = "";
char single[MIDBUFFER];
int number = 0;
itemlist *t;
snapshot;
for (t = First(u->domainhead); t; t = Next(t)) {
StrFormatMax(single, sizeof(single), "%d: <%s> ", ++number, (char *)t->pointer);
if ((StrLength(buffer) + StrLength(single)) >= sizeof(buffer)) {
Send(from, buffer);
buffer[0] = (char)0;
}
StrAppend(buffer, single);
}
if (buffer[0])
Send(from, buffer);
}
void ReportWhois(char *from, itemuser *u, bool all, bool notme)
{
char level[MINIBUFFER];
char *flags;
snapshot;
if (notme && (current->level <= u->level))
StrCopyMax(level, sizeof(level), GetText(msg_yours_or_higher));
else
StrFormatMax(level, sizeof(level), "%s %d", GetText(msg_level), u->level);
Sendf(from, GetText(msg_report_level), u->nick, u->realname, level);
flags = VerboseFlags(&u->flags);
if (flags) {
Send(from, flags);
}
if (u->stat_bywhom) {
Sendf(from, GetText(msg_sview_who_did_what),
(u->stat_lastdone == USER_ADDED) ? GetText(msg_added) :
(u->stat_lastdone == USER_RAISED) ? GetText(msg_raised) :
GetText(msg_lowered),
u->stat_bywhom, TimeAgo(u->stat_lastchange));
}
if (u->comment) {
Sendf(from, GetText(msg_comment), u->comment);
}
}
/* --- CmdSview -------------------------------------------------- */
#define SV_NOTME (1<<0) /* display another user */
#define SV_ALL (1<<1) /* show all accounts */
#define SV_SMALL (1<<2) /* small output format */
#define SV_REGED (1<<3) /* show registered user instead of any user in the
channel using that nick */
void Sview(char *to, itemident *p, int mystatus, int flags)
{
char buffer[BIGBUFFER];
char *pointer;
float postspermin;
float minson;
snapshot;
if ((flags & SV_NOTME) && (p->level >= mystatus))
StrCopyMax(buffer, sizeof(buffer), GetText(msg_yours_or_higher));
else
StrFormatMax(buffer, sizeof(buffer), "%d", p->level);
Sendf(to, GetText(msg_sview_user),
(p->level >= LEVELCHANOP) ? (p->passed ? GetText(msg_confirmed) : "") : "",
p->nick, p->userdomain, buffer,
p->guest ? (p->guest->flags.chanop ? GetText(msg_sview_op) : "") :
GetText(msg_sview_dcc));
if (p->user && !(flags & SV_SMALL)) {
buffer[0] = (char)0;
if (p->user->realname) {
StrFormatAppendMax(buffer, sizeof(buffer), GetText(msg_email),
p->user->realname);
}
if (!IRCEqual(p->user->nick, p->nick)) {
StrFormatAppendMax(buffer, sizeof(buffer), "%s%s %s",
buffer[0] ? ", " : "",
GetText(msg_regged_nick),
p->user->nick);
}
if (p->user->language != defaultlang) {
StrFormatAppendMax(buffer, sizeof(buffer), "%s%s %s",
buffer[0] ? ", " : "",
GetText(msg_language),
LanguageLocal(p->user->language));
}
if (buffer[0]) {
Send(to, buffer);
buffer[0] = (char)0;
}
pointer = VerboseFlags(&p->user->flags);
if (pointer) {
StrAppendMax(buffer, sizeof(buffer), pointer);
}
if (p->user->comment) {
if (buffer[0]) {
StrAppendMax(buffer, sizeof(buffer), ", ");
}
StrFormatAppendMax(buffer, sizeof(buffer), GetText(msg_comment),
p->user->comment);
}
if (buffer[0]) {
Send(to, buffer);
}
}
if (p->guest && !(flags & SV_SMALL)) {
/* only if joined and not small output*/
itemguest *pc = p->guest;
Sendf(to, GetText(msg_sview_joins), pc->joins, TimeAgo(pc->jointime));
if (pc->warnings)
Sendf(to, GetText(msg_warnings), pc->warnings);
if (pc->posttime) {
minson = (float)(now - pc->jointime)/60;
postspermin = (float)pc->posts / minson;
Sendf(to, GetText(msg_last_talked),
TimeAgo(pc->posttime), postspermin);
}
else
Send(to, GetText(msg_hasnt_said_anything));
if (pc->msgs)
Sendf(to, GetText(msg_messages), pc->msgs);
if (pc->flags.split)
Send(to, GetText(msg_netsplit));
}
}
void static whodidwhat(char *from, itemuser *u, int flags)
{
snapshot;
if (u->stat_bywhom && (flags & SV_NOTME)) {
Sendf(from, GetText(msg_sview_who_did_what),
(u->stat_lastdone == USER_ADDED) ? GetText(msg_added) :
(u->stat_lastdone == USER_RAISED) ? GetText(msg_raised) :
GetText(msg_lowered),
u->stat_bywhom, TimeAgo(u->stat_lastchange));
}
}
void CmdSview(char *from, char *line)
{
char nick[NICKLEN+1];
int flags = 0;
itemguest *g;
itemident *p = current;
itemclient *k = NULL;
itemuser *u = NULL;
snapshot;
while (GetOption(line)) {
switch(toupper(option.copt)) {
case 'A':
flags |= SV_ALL;
break;
case 'S':
flags |= SV_SMALL;
break;
case 'R':
flags |= SV_REGED;
break;
}
line = option.newpos;
}
if ((current->level >= LEVELCHANOP) &&
(1 == StrScan(line, "%"NICKLENTXT"s", nick))) {
if (flags & SV_REGED) {
u = FindUserByNick(nick);
}
if (u || (!(g=FindNick(nick)) &&
!(g=FindSplitNick(nick)) &&
!(k=FindClientByNick(nick)))) {
/* Not joined, split or DCC chatting, search for registered nick */
u = FindUserByNick(nick);
if (u) {
ReportWhois(from, u, flags & SV_ALL, !IRCEqual(current->nick, u->nick));
if (flags & SV_ALL) {
whodidwhat(from, u, flags);
ReportAccounts(from, u);
}
return;
}
Sendf(errfrom, GetText(msg_nick_not_found), nick);
return;
}
if (k) {
/* Target user is only on DCC */
if (k->ident != current) {
flags |= SV_NOTME;
p = k->ident;
}
}
else if (g->ident != current) {
flags |= SV_NOTME;
p = g->ident;
}
}
Sview(from, p, current->level, flags);
if (p->user && (flags & SV_ALL)) {
whodidwhat(from, p->user, flags);
ReportAccounts(from, p->user);
}
}
/* --- CmdSplit --------------------------------------------------- */
void CmdSplit(char *from, char *line)
{
extern itemsplit *splitHead;
extern time_t lastsplittime;
extern time_t uptime;
itemsplit *p;
int count=0;
snapshot;
if (NULL == from)
from = current->nick;
for (p = First(splitHead); p; p = Next(p)) {
count++;
Sendf(from, GetText(msg_split_ago),
p->servers, TimeAgo(p->splittime),
p->heal ? GetText(msg_split_partly_healed) : "");
}
if(0 == count) {
if(lastsplittime)
Sendf(from, GetText(msg_last_netsplit), TimeAgo(lastsplittime));
else {
Sendf(from, GetText(msg_no_netsplits), TimeAgo(uptime));
}
}
}
/* --- CmdUserlist ------------------------------------------------ */
#ifndef USEOLDINSTEAD
/************************************************************************
userlist -n regged nick pattern
-p host pattern
-c changed-by pattern
-a lastdone ("added", "lowered" or "raised")
-f flagpattern
-l (range)level
-t (range)age
-m (range)age-since-modified
-v Verbose
-x Max number of users displayed (default 20)
range-fields = '[digits][-][digits]'
examples
"10-" 10 and greater
"10" exact match 10
"10-20" between 10 and 20
"-20" 20 and lower
"-" everything
(octals and hexadecimals work too, preceed with 0 or 0x)
***********************************************************************/
struct UserRange {
long lowest;
long highest;
};
int ScanRange(char *string, struct UserRange *range)
{
long num = 0;
long num2 = 0;
int mode = -1;
char operator;
char *newstring;
snapshot;
if ('-' != string[0])
num = StrToLong(string, &newstring, 0);
else
newstring = string;
if ('-' == *newstring) {
string = ++newstring;
num2 = StrToLong(string, &newstring, 0);
if (string == newstring)
num2 = INT_MAX;
mode = 1;
}
switch(mode) {
case -1:
range->lowest = range->highest = num;
break;
case 1:
range->lowest = ((num > num2) ? num2 : num);
range->highest = ((num > num2) ? num : num2);
}
return 0;
}
#ifdef TEST
int main(int argc, char **argv)
{
struct UserRange user;
if (argc < 1) {
printf("dump\n");
return 0;
}
if (ScanRange(argv[1], &user))
printf("error\n");
else
printf("%d - %d\n", user.lowest, user.highest);
}
#endif
struct UserOptions {
bool nick;
bool host;
bool changed;
bool flag;
bool lastdone;
bool level;
bool age;
bool age_since_modified;
};
void CmdUserlist(char *from, char *line)
{
char nickpattern[NICKLEN+1]="";
char hostpattern[MIDBUFFER]="";
char changedpattern[MIDBUFFER]="";
char flagpattern[MIDBUFFER]="";
char lastdone[MINIBUFFER]="";
char temp[MINIBUFFER]="";
char s_level[5];
bool all = FALSE;
int conds = 0;
int written = 0;
int maxlines = 20; /* Just a default to prevent the [poor] user to get drowned
by the result */
struct UserRange level;
struct UserRange age;
struct UserRange age_since_modified;
struct UserOptions check;
itemuser *u;
snapshot;
memset(&check, 0, sizeof(struct UserOptions));
while(GetOption(line)) {
char opt = toupper(option.copt);
line = option.newpos;
switch(opt) {
case 'V': /* verbose details */
all = TRUE;
break;
case 'X': /* max number of users to display */
if (1 == StrScan(line, "%"MINIBUFFERTXT"s", temp)) {
line += StrLength(temp);
maxlines = atoi(temp);
}
break;
case 'N': /* nick pattern */
conds++;
check.nick = TRUE;
StrScan(line, "%"NICKLENTXT"s", nickpattern);
line += StrLength(nickpattern);
break;
case 'P': /* host pattern */
conds++;
check.host = TRUE;
StrScan(line, "%"MIDBUFFERTXT"s", hostpattern);
line += StrLength(hostpattern);
break;
case 'C': /* changed */
conds++;
check.changed = TRUE;
StrScan(line, "%"MIDBUFFERTXT"s", changedpattern);
line += StrLength(changedpattern);
break;
case 'F': /* flags */
conds++;
check.flag = TRUE;
StrScan(line, "%"MIDBUFFERTXT"s", flagpattern);
line += StrLength(flagpattern);
break;
case 'A': /* last done */
conds++;
check.lastdone = TRUE;
StrScan(line, "%"MINIBUFFERTXT"s", lastdone);
line += StrLength(lastdone);
break;
case 'L': /* level */
conds++;
check.level = TRUE;
StrScan(line, "%"MINIBUFFERTXT"s", temp);
ScanRange(temp, &level);
line += StrLength(temp);
break;
case 'T': /* age */
conds++;
check.age = TRUE;
StrScan(line, "%"MINIBUFFERTXT"s", temp);
ScanRange(temp, &age);
line += StrLength(temp);
break;
case 'M': /* age since modified */
conds++;
check.age_since_modified = TRUE;
StrScan(line, "%"MINIBUFFERTXT"s", temp);
ScanRange(temp, &age_since_modified);
line += StrLength(temp);
break;
}
while (iswhite(*line))
line++;
}
for (u = First(userHead); u; u = Next(u)) {
if (u->level > current->level)
StrCopy(s_level, "XXX");
else
StrFormatMax(s_level, sizeof(s_level), "%3d", u->level);
if(conds) {
/* we have a condition check here */
if (check.nick && !Match(u->nick, nickpattern))
continue;
if (check.host) {
char *compare = hostpattern;
char *host;
itemlist *t;
for (t = First(u->domainhead); t; t = Next(t)) {
host = (char *)t->pointer;
if (Match(host, compare))
break;
if (IsPrefix(host)) {
host++;
if ( Match(host, compare) )
break;
}
if ( IsPrefix(compare) ) {
compare++;
if ( Match(host, compare) )
break;
}
}
if(NULL == t)
continue;
}
if (check.changed) {
if ((NULL == u->stat_bywhom) || !Match(u->stat_bywhom, changedpattern))
continue;
}
if (check.flag) {
char *flags = VerboseFlags(&u->flags);
if (NULL == flags)
continue;
flags = StrIndex(flags, ':') + 1; /* skip everything before the : */
if (!Match(flags, flagpattern))
continue;
}
if (check.lastdone) {
switch (u->stat_lastdone) {
case USER_ADDED:
if (!StrEqual(lastdone, "ADDED"))
continue;
break;
case USER_LOWERED:
if (!StrEqual(lastdone, "LOWERED"))
continue;
break;
case USER_RAISED:
if (!StrEqual(lastdone, "RAISED"))
continue;
break;
default:
continue;
}
}
if (check.level) {
if ((u->level < level.lowest) || (u->level > level.highest))
continue;
}
if (check.age) {
long days = now - u->created;
days /= (3600*24); /* convert seconds to days */
if(days<age.lowest ||
days>age.highest)
continue;
}
if(check.age_since_modified) {
long days = now - u->modified;
days /= (3600*24); /* convert seconds to days */
if(days<age_since_modified.lowest ||
days>age_since_modified.highest)
continue;
}
}
if (--maxlines >= 0) {
written++;
Sendf(from, "> %-9s [%s] %s", u->nick, s_level, u->realname);
if (all)
ReportAccounts(from, u);
}
else {
Send(from, GetText(msg_userlist_aborted));
return;
}
}
if(!written)
Send(from, GetText(msg_no_user_matched));
}
#else
void CmdUserlist(char *from, char *line)
{
char s_level[5];
bool all = FALSE;
itemuser *u;
snapshot;
all = (GetOption(line) && (toupper(option.copt) == 'A'));
line = option.newpos;
for (u = First(userHead); u; u = Next(u)) {
if (u->level > current->level)
StrCopy(s_level, "XXX");
else
StrFormatMax(s_level, sizeof(s_level), "%3d", u->level);
Sendf(from, "> %-9s [%s] %s", u->nick, s_level, u->realname);
if (all)
ReportAccounts(from, u);
}
}
#endif /* USEOLDINSTEAD */
/* --- CmdClientlist ---------------------------------------------- */
void CmdClientlist(char *from, char *line)
{
char buffer[MINIBUFFER];
itemclient *k;
snapshot;
k = First(clientHead);
if (k) {
while (k) {
if (CL_NONE == k->status) {
continue;
}
else if (CL_CONNECTED == k->status) {
StrFormatMax(buffer, sizeof(buffer), "%s%s%s%s%s",
((k->flags & WALLCAST) && current->level >= LEVELRECOG) ? "Wall " : "",
((k->flags & REPORTCAST) && current->level >= LEVELPUB) ? "Report " : "",
((k->flags & CHATCAST) && current->level >= LEVELTRUST) ? "Chat " : "",
((k->flags & SPYCAST) && current->level >= LEVELBOT) ? "Spy " : "",
((k->flags & DEBUGCAST) && current->level >= LEVELBOT) ? "Debug " : "");
}
else if (CL_CONNECTING == k->status) {
StrFormatMax(buffer, sizeof(buffer), "Connecting");
}
else if (CL_LISTENING == k->status) {
StrFormatMax(buffer, sizeof(buffer), "Listening");
}
else {
StrFormatMax(buffer, sizeof(buffer), "Dead?");
}
Sendf(from, "%-9s [%4d] %s. %s", k->ident->nick, k->socket,
TimeAgo(k->lasttime), buffer);
k = Next(k);
}
}
else
Send(from, GetText(msg_no_dcc_clients));
}
/* --- CmdSeen ---------------------------------------------------- */
void CmdSeen(char *from, char *line)
{
snapshot;
Seen(from, line);
}
/* --- CmdFind ---------------------------------------------------- */
void CmdFind(char *from, char *line)
{
char search[BIGBUFFER];
char *end;
int matches;
#ifdef HAVE_NO_GREP
char linebuffer[BIGBUFFER];
int count;
FILE *searchFP;
#endif
snapshot;
if (line && *line) {
if (FileExist(findfilename)) {
if (('\"' == *line) && (end = StrIndexLast(line + 1, '\"'))) {
memcpy(search, line + 1, end - line);
search[end - line - 1] = (char)0;
line = end + 1;
}
else {
#ifdef HAVE_N_IN_SCANF
int col;
StrScan(line, "%"BIGBUFFERTXT"s %n", search, &col);
line = &line[col];
#else
StrCopyMax(search, sizeof(search), StrTokenize(line," "));
#endif
}
matches = line ? atoi(line) : 0;
if (0 == matches)
matches = 3;
else if (public && (matches > 5))
matches = 5;
else if (matches > 20)
matches = 20;
#ifndef HAVE_NO_GREP
Execute(from, "grep -i \"%s\" %s | head -%d | awk 'BEGIN {a=0} " \
"{a++; print $0} END {if (a==0) print \"No match " \
"found, %s\" }'", search, findfilename, matches,
current->nick);
#else
searchFP = fopen(findfilename,"r");
count = 0;
while (!feof(searchFP) && (count < matches)) {
fgets(&linebuffer,100,searchFP);
if (StrSubstring(linebuffer, search)) {
Send(errfrom, linebuffer);
count++;
}
}
fclose(searchFP);
if (0 == count)
Sendf(errfrom, GetText(msg_find_no_match_found), current->nick);
#endif
}
else
Send(errfrom, GetText(msg_find_no_index));
}
else
CmdSyntax(errfrom, "FIND");
}
/* --- CmdCalc ---------------------------------------------------- */
void CmdCalc(char *from, char *line)
{
snapshot;
if (line && *line)
Execute(from, "echo \"%s\" | bc -l | head -3", line);
else
CmdSyntax(errfrom, "CALC");
}
/* --- CmdCountry ------------------------------------------------- */
void CmdCountry(char *from, char *line)
{
snapshot;
Country(from, line);
}
/* --- CmdVrfy ---------------------------------------------------- */
void CmdVrfy(char *from, char *line)
{
itemguest *pc;
char *xs, *ys;
snapshot;
if (line && *line && cmdvrfy[0]) {
ys = line;
xs = StrIndexLast(line, ' ');
if (NULL == xs) {
xs = line;
ys = NULL;
}
else
*xs++ = NIL;
if (StrIndex(xs, '@')) {
Execute(from, "%s %s%s%s\"%s\" 2>&1", cmdvrfy, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), xs);
}
else {
pc = FindNick(xs);
if (pc) {
char *host = pc->ident->host;
if (BadUsername(pc->ident->pname)) {
Sendf(from, GetText(msg_silly_username), xs, pc->ident->pname);
return;
}
else if (IsPrefix(host))
host++;
Execute(from, "%s %s%s%s%s 2>&1", cmdvrfy, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), host);
}
else
Send(errfrom, GetText(msg_not_found));
}
}
else
CmdSyntax(errfrom, "VRFY");
}
/* --- CmdHost ---------------------------------------------------- */
void CmdHost(char *from, char *line)
{
itemguest *pc;
char *xs, *ys;
snapshot;
if (line && *line && cmdhost[0]) {
ys = line;
xs = StrIndexLast(line, ' ');
if (NULL == xs) {
xs = line;
ys = NULL;
}
else
*xs++ = NIL;
if (StrIndex(xs, '.')) {
if (nameserver[0])
Execute(from, "%s %s%s%s-P %s \"%s\" 2>&1", cmdhost, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), nameserver, xs);
else
Execute(from, "%s %s%s%s\"%s\" 2>&1", cmdhost, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), xs);
}
else {
if ( (pc=FindNick(xs)) && (xs = StrIndex(pc->ident->host, '@')) ) {
xs++;
if (*nameserver)
Execute(from, "%s %s%s%s-P %s \"%s\" 2>&1", cmdhost, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), nameserver, xs);
else
Execute(from, "%s %s%s%s\"%s\" 2>&1", cmdhost, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), xs);
} else
Send(errfrom, GetText(msg_not_found));
}
}
}
/* --- CmdFinger -------------------------------------------------- */
void CmdFinger(char *from, char *line)
{
itemguest *pc;
char *xs, *ys;
snapshot;
if (line && *line) {
ys = line;
xs = StrIndexLast(line, ' ');
if (NULL == xs) {
xs = line;
ys = NULL;
}
else
*xs++ = NIL;
if (StrIndex(xs, '@')) {
Execute(from, "%s %s%s%s\"%s\" 2>&1", cmdfinger, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), xs);
}
else {
if ( pc=FindNick(xs) ) {
char *host = pc->ident->host;
if(BadUsername(pc->ident->pname)) {
Sendf(from, GetText(msg_silly_username),
xs, pc->ident->pname);
return;
}
else if(IsPrefix(host))
host++;
Execute(from, "%s %s%s%s%s 2>&1", cmdfinger, (ys ? "\"" : ""),
(ys ? ys : ""), (ys ? "\" " : ""), host);
}
else
Send(errfrom, GetText(msg_not_found));
}
}
else
CmdSyntax(errfrom, "FINGER");
}
/* --- CmdOp ------------------------------------------------------ */
bool Pass(itemident *, char *);
void CmdOp(char *from, char *line)
{
snapshot;
if (!current->passed) {
if (line && *line) {
if (!Pass(current, line)) {
Send(current->nick, GetText(msg_invalid_password));
return;
}
}
else {
Send(errfrom, GetText(msg_use_pass_first));
return;
}
}
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (current->guest) {
if (current->guest->flags.split) {
if (client && (client->status == CL_CONNECTED))
Sendf(errfrom, GetText(msg_cannot_x_beyond_split),
GetText(msg_give_op));
}
else
Mode("+o %s", current->nick);
}
else
Send(errfrom, GetText(msg_cant_op));
}
/* --- CmdVoice --------------------------------------------------- */
void CmdVoice(char *from, char *line)
{
snapshot;
if (!current->passed) {
if (line && *line) {
if (!Pass(current, line)) {
Send(current->nick, GetText(msg_invalid_password));
return;
}
}
else {
Send(errfrom, GetText(msg_use_pass_first));
return;
}
}
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (current->guest) {
if (current->guest->flags.split) {
if (client && (client->status == CL_CONNECTED))
Sendf(errfrom, GetText(msg_cannot_x_beyond_split),
GetText(msg_give_voice));
}
else
Mode("+v %s", current->nick);
}
else
Send(errfrom, GetText(msg_cant_op));
}
/* --- CmdDeVoice ------------------------------------------------- */
void CmdDeVoice(char *from, char *line)
{
snapshot;
if ( !current->passed ) {
if (line && *line) {
if (!Pass(current, line)) {
Send(current->nick, GetText(msg_invalid_password));
return;
}
}
else {
Send(errfrom, GetText(msg_use_pass_first));
return;
}
}
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (current->guest) {
if (current->guest->flags.split) {
if (client && (client->status == CL_CONNECTED))
Sendf(errfrom, GetText(msg_cannot_x_beyond_split),
GetText(msg_remove_voice));
}
else
Mode("-v %s", current->nick);
}
else
Send(errfrom, GetText(msg_cant_op));
}
/* --- CmdJoin ---------------------------------------------------- */
void CmdJoin(char *from, char *line)
{
char chan[MIDBUFFER], key[MIDBUFFER];
char *pchan;
snapshot;
if (1 <= StrScan(line, "%"MIDBUFFERTXT"s %"MIDBUFFERTXT"s",
chan, key)) {
pchan = IsChannel(chan) ? chan + 1 : chan;
CmdLeave(from, channel);
WriteServer("JOIN #%s %s", pchan, (key ? key : chankey));
}
else
CmdSyntax(errfrom, "JOIN");
}
/* --- CmdLeave --------------------------------------------------- */
void CmdLeave(char *from, char *line)
{
snapshot;
/* Ban and guest lists are removed in OnPart() in server.c */
WriteServer("PART %s", channel);
}
/* --- CmdUnban --------------------------------------------------- */
void CmdUnban(char *from, char *line)
{
char buffer[MIDBUFFER];
snapshot;
if (NULL == from)
from = current->nick;
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (line && (1 == StrScan(line, "%"MIDBUFFERTXT"s", buffer))) {
if (!UnBan(from, buffer))
Sendf(errfrom, GetText(msg_no_user_to_unban), buffer);
}
else
CmdSyntax(errfrom, "UNBAN");
}
/* --- CmdChban -------------------------------------------------- */
void CmdChban(char *from, char *line)
{
char nickpattern[MINIBUFFER];
int secs=-1;
char pattern[MINIBUFFER];
char buf[MINIBUFFER]="";
char flag=0;
int num;
snapshot;
if (NULL == from)
from = current->nick;
if(GetOption(line)) {
if (toupper(option.copt) == 'E')
flag = CHBAN_ENFORCE;
if (toupper(option.copt) == 'U')
flag = CHBAN_UNENFORCE;
if (toupper(option.copt) == 'R')
flag = CHBAN_REASON; /* this is a change-reason invoke */
line = option.newpos;
}
if (line && *line) {
num = StrScan(line, "%"MINIBUFFERTXT"s %"MINIBUFFERTXT"[^\n]",
nickpattern, buf);
if (flag != CHBAN_REASON) {
if (2 == num)
secs = ToSeconds(buf);
}
if(!num || !ChangeInBanList(current->nick, nickpattern,
secs, pattern, flag, buf)) {
/* not found */
Send(errfrom, GetText(msg_no_such_ban));
return;
}
else if (reportban && !mute)
Sayf("%s changed the %s ban", from, pattern);
Sendf(from, GetText(msg_changed_the_ban),
pattern, nickpattern);
}
else
CmdSyntax(errfrom, "CHBAN");
}
/* --- CmdBan ----------------------------------------------------- */
bool NickToPattern(char *nick, char *buffer, bool siteban)
{
char parseduser[USERLEN+1], parsedhost[BIGBUFFER], parseddomain[BIGBUFFER];
char *username, *userhost;
itemguest *g;
itemaux *pa;
snapshot;
if ('*'== nick[0]) {
siteban = TRUE;
nick++;
}
g = FindNick(nick);
if (g) {
userhost = g->ident->host;
StrCopyMax(parseduser, sizeof(parseduser), g->ident->pname);
StrCopyMax(parsedhost, sizeof(parsedhost), g->ident->phost);
StrCopyMax(parseddomain, sizeof(parseddomain), g->ident->puserdomain);
}
else {
pa = SeenRecentNick(nick);
if (pa) {
userhost = pa->root->host;
if (SplitHost(userhost, parsedhost, parseddomain, parseduser))
return FALSE;
}
else
return FALSE; /* Couldn't find nick */
}
username = parseduser;
if (HostISP(userhost))
/* Is this a host-ban only ISP? I.e where we ban the machine name only and
not the site on sitebans.
We set siteban TRUE to make the username part '*' and since this is a
hostisp already the right-hand 'parseddomain' part does contain the
complete string without wildcard characters. */
siteban = TRUE;
else if (DontSiteBan(userhost))
siteban = FALSE;
else if (BadUsername(username)) {
/* Username part contains crap characters */
char sitepattern[MIDBUFFER];
int number;
StrFormatMax(sitepattern, sizeof(sitepattern), "*!*@%s", parseddomain);
/* NOTE NOTE
The fact that the check below is put in this particular routine is NOT
a nice solution. This routine should always return the same pattern for
the same user. The judgement below should be put in the BAN command
section and not in this general nick->pattern function.
- Bagder 970730 */
/* Only use this siteban if there is no previous bans on this site.
If a previous ban is there, use the odd characters anyway. */
if (!IsMatchBan(sitepattern, &number))
siteban = TRUE;
}
if (siteban) {
StrFormat(buffer, "*@%s", parseddomain);
}
else {
if (IsPrefix(username))
username++;
else if (StrLength(username) > 9) {
username[8] = '*';
username[9] = (char)0;
}
StrFormat(buffer, "*%s@%s", username, parseddomain);
}
return TRUE;
}
void CmdBan(char *from, char *line)
{
char bnick[MIDBUFFER];
char snick[NICKLEN+2];
char buffer[MIDBUFFER];
char banbuffer[MIDBUFFER];
char timebuf[MINIBUFFER];
char why[MINIBUFFER] = "";
char *nick, *reason;
char *removeban = NULL;
bool siteban = FALSE;
bool enforce = FALSE;
bool kickall = FALSE;
bool banned = FALSE;
int num;
long secs;
snapshot;
if (line && *line) {
while (GetOption(line)) {
switch (toupper(option.copt)) {
case 'E':
enforce = TRUE;
break;
case 'K':
kickall = TRUE;
break;
}
line = option.newpos;
}
num = StrScan(line, "%"MIDBUFFERTXT"s %"MINIBUFFERTXT"s %"MINIBUFFERTXT"[^\n]",
bnick, timebuf, why);
secs = defbantime;
if (num > 1) {
if (isdigit(timebuf[0])) {
secs = ToSeconds(timebuf);
}
else
StrScan(line, "%*s %"MINIBUFFERTXT"[^\n]", why);
}
if (NULL == from)
from = current->nick;
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (3 == StrScan(bnick, "%"NICKLENTXT"[^!]!%"MIDBUFFERTXT"[^@]@%"MIDBUFFERTXT"s",
snick, banbuffer, buffer)) {
nick = NULL;
StrFormatAppendMax(banbuffer, sizeof(banbuffer), "@%s", buffer);
}
else {
nick = bnick;
if ('*' == nick[0]) {
siteban = TRUE;
nick++;
}
if (!NickToPattern(nick, banbuffer, siteban)) {
Sendf(errfrom, GetText(msg_nick_not_found), nick);
return;
}
}
StrFormatMax(buffer, sizeof(buffer), "*!%s", banbuffer);
if (Match(botmatch, buffer)) {
Send(errfrom, GetText(msg_pattern_would_include_myself));
return;
}
else if ((current->level < LEVELBOT) && IllegalBan(buffer)) {
Send(errfrom, GetText(msg_cant_ban_banprotected));
return;
}
reason = why[0] ? why : GetText(msg_kickmsg);
if (siteban) {
int number = 0;
removeban = IsMatchBan(buffer, &number); /* Check for several bans */
if (number > 1)
banned = TRUE;
else if (number && StrEqual(removeban, buffer))
banned = TRUE;
}
if (!banned &&
!(AddToBanList(BAN_SENTBAN|(enforce?BAN_ENFORCE:0),
current->nick,
nick, buffer, secs, reason)&BANISTHERE) ) {
BanKick(nick, buffer, reason, removeban);
if (reportban && !mute && !public) {
if (secs)
Sayf(GetText(msg_ban_report_timed),
nick ? nick : buffer,
siteban ? "site" : "",
current->nick, secs, reason);
else
Sayf(GetText(msg_ban_report),
nick ? nick : buffer,
siteban ? "site" : "",
current->nick, reason);
}
}
else {
if (nick)
Kick(nick, reason);
Sendf(errfrom, GetText(msg_banned_already), nick ? nick : buffer);
}
if (kickall || siteban) {
KickAll(banbuffer, reason);
}
}
else
CmdSyntax(errfrom, "BAN");
}
/* --- CmdKick ---------------------------------------------------- */
void CmdKick(char *from, char *line)
{
char bnick[MIDBUFFER];
char snick[NICKLEN+2];
char buffer[BIGBUFFER];
char banbuffer[MIDBUFFER];
char why[MINIBUFFER] = "";
char *nick, *reason;
bool siteban = FALSE;
bool kickall = FALSE;
itemguest *g;
snapshot;
if (line && *line) {
while (GetOption(line)) {
switch (toupper(option.copt)) {
case 'K':
kickall = TRUE;
break;
}
line = option.newpos;
}
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (1 <= StrScan(line, "%"MIDBUFFERTXT"s %"MINIBUFFERTXT"[^\n]",
bnick, why)) {
if (NULL == from)
from = current->nick;
nick = bnick;
reason = why[0] ? why : GetText(msg_kickmsg);
if (current->level >= LEVELTRUST) {
if (3 == StrScan(bnick, "%"NICKLENTXT"[^!]!%"MIDBUFFERTXT"[^@]@%"MIDBUFFERTXT"s",
snick, banbuffer, buffer)) {
nick = snick;
StrFormatAppendMax(banbuffer, sizeof(banbuffer), "@%s", buffer);
}
else {
if ('*' == nick[0]) {
siteban = TRUE;
nick++;
}
if (!NickToPattern(nick, banbuffer, siteban)) {
Sendf(errfrom, GetText(msg_nick_not_found), nick);
return;
}
}
StrFormatMax(buffer, sizeof(buffer), "*!%s", banbuffer);
if (Match(botmatch, buffer)) {
Send(errfrom, GetText(msg_pattern_would_include_myself));
return;
}
else if ((current->level < LEVELBOT) && IllegalBan(buffer)) {
Send(errfrom, GetText(msg_cant_ban_banprotected));
return;
}
KickAll(banbuffer, reason);
}
else {
if (IRCEqual(nick, nickname))
/* This is _me_, give it back */
Kick(current->nick, reason);
else if (g = FindNick(nick)) {
if (g->ident->level < current->level)
/* Only allowed to kick lower levelers */
Kick(nick, reason);
else
Send(errfrom, GetText(msg_not_allowed_target));
}
}
}
}
else
CmdSyntax(errfrom, "KICK");
}
/* --- CmdKicklist ------------------------------------------------ */
void CmdKicklist(char *from, char *line)
{
snapshot;
KickList(from, line);
}
/* --- CmdBanlist ------------------------------------------------- */
void CmdBanlist(char *from, char *line)
{
char matching[MINIBUFFER];
bool all = FALSE;
bool unbanned = FALSE; /* Whether to display unbanned info too */
snapshot;
while (GetOption(line)) {
switch (toupper(option.copt)) {
case 'A':
all = TRUE;
break;
case 'U':
unbanned = TRUE;
break;
}
line = option.newpos;
}
if (line) {
if (1 > StrScan(line, "%"MINIBUFFERTXT"s", matching))
StrCopy(matching, "*");
}
if(!BanList(from, all, unbanned, matching)) {
/* no bans in the channel */
Send(from, GetText(msg_no_bans_set));
}
}
/* Different levels */
/* THRES(HOLD) - FLOOD[REPEAT]RATE, FLOOD[REPEAT]TIME, FLOODBEEPS
* FLOOD(ING) - BEEP, FLOOD, UPPER, NICK, XDCC, MULTI, REPEAT, CTCP, KICKBAN, BOMB
* VERBOSE - COMMENT, WELCOME, TALK, SAY, WARN, REPORTBAN
* MISC - MODE, KEY, AUTOOP, AUTOJOIN, NETSPLIT, DEOP, INVITE, CMODE, CKEY, HELPSYNTAX
*/
/* set flood.beep on */
void CmdSet(char *from, char *line)
{
snapshot;
SetSet(from, line);
}
/* --- CmdCmode --------------------------------------------------- */
void CmdCmode(char *from, char *modes)
{
int pflag, sflag, iflag, tflag, nflag, mflag;
int i=0, j=0;
char c;
char nomode[16];
snapshot;
if (modes && *modes) {
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
pflag = sflag = iflag = tflag = nflag = mflag = FALSE;
while (c = *modes++) {
switch (c) {
case 'p': pflag = TRUE; break;
case 's': sflag = TRUE; break;
case 'i': iflag = TRUE; break;
case 't': tflag = TRUE; break;
case 'n': nflag = TRUE; break;
case 'm': mflag = TRUE; break;
}
}
if (sflag)
cmodes[i++] = 's';
else
nomode[j++] = 's';
if (pflag)
cmodes[i++] = 'p';
else
nomode[j++] = 'p';
if (mflag)
cmodes[i++] = 'm';
else
nomode[j++] = 'm';
if (nflag)
cmodes[i++] = 'n';
else
nomode[j++] = 'n';
if (tflag)
cmodes[i++] = 't';
else
nomode[j++] = 't';
if (iflag)
cmodes[i++] = 'i';
else
nomode[j++] = 'i';
cmodes[i] = NIL;
nomode[j] = NIL;
Mode("+%s-%s", cmodes, nomode);
}
if (*cmodes)
Sendf(from, GetText(msg_channel_modes),
cmodes);
else
Send(from, GetText(msg_no_channel_modes));
}
/* --- CmdCkey ---------------------------------------------------- */
void CmdCkey(char *from, char *line)
{
snapshot;
if (line && *line) {
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (!StrEqualCase(line, "-"))
StrCopy(ckey, line);
else
ckey[0] = (char)0;
Mode("-k %s", chankey);
Mode("+k %s", ckey);
}
else
Sendf(from, GetText(msg_channel_key), chankey, ckey);
}
/* --- CmdStatus -------------------------------------------------- */
void CmdStatus(char *from, char *line)
{
extern time_t ctcptimeout;
extern int numUsers, numGuests, numSplitGuests, numClients;
extern int numExplains, numSeenHosts, numSeenNicks;
bool all;
int servedtotal;
int opguests = 0;
itemguest *g;
snapshot;
/* Scan the guestlist to count split and opped guests */
for (g = First(guestHead); g; g = Next(g)) {
opguests += g->flags.chanop ? 1 : 0;
}
all = (GetOption(line) && (toupper(option.copt) == 'A'));
line = option.newpos;
servedtotal = servedmsgcmd + servedpubcmd + serveddcccmd;
CmdUptime(from, NULL);
Sendf(from, GetText(msg_sview_users),
(botop ? "Chanop. " : ""),
numUsers,
numGuests, opguests, numSplitGuests,
numClients, numExplains,
numSeenHosts, numSeenNicks);
if (current->level >= LEVELEXPERT) {
Sendf(from, GetText(msg_sview_commands),
servedtotal,
100*(float)servedpubcmd/(float)servedtotal,
100*(float)serveddcccmd/(float)servedtotal,
numofbotmodes);
Sendf(from, GetText(msg_sview_bans),
CountBans(BAN_ACTUAL), CountBans(BAN_ENFORCE),
CountWarns(0), CountWarns(WARNF_KICKBAN));
}
if (now < ctcptimeout)
Sendf(from, GetText(msg_sview_ignoring_ctcp),
TimeAgo(ctcptimeout));
if (all)
ShowSetAll(from);
}
/* --- CmdQuit ---------------------------------------------------- */
void CmdQuit(char *from, char *line)
{
snapshot;
Quit((from ? from :
(client->ident->user ? client->ident->nick : GetDefaultText(msg_unknown))),
((line && *line) ? line : "Quit"));
}
/* --- CmdShutdown ------------------------------------------------ */
void CmdShutdown(char *from, char *line)
{
char timebuf[MINIBUFFER];
int secs, index;
snapshot;
if (line && *line) {
if (shuttingdown) {
if (GetOption(line) && (toupper(option.copt) == 'C')) {
shuttingdown = FALSE;
shutdowntime = 0;
Multicast(WALLCAST, GetText(msg_shutdown_canceled));
}
else
Send(from, GetText(msg_shutdown_already_in_progress));
}
else {
#ifdef HAVE_N_IN_SCANF
if (1 <= StrScan(line, "%"MINIBUFFERTXT"s %n", timebuf, &index)) {
#else
if (1 == StrScan(line, "%"MINIBUFFERTXT"s", timebuf)) {
index = StrLength(timebuf);
while (iswhite(line[index]))
index++;
#endif
if (isdigit(timebuf[0])) {
secs = ToSeconds(timebuf);
}
else {
index = 0;
secs = 10; /* By default */
}
StrFormatMax(shutdownreason, MIDBUFFER, "%s", line[index] ? &line[index] : NOREASON);
StrCopy(shutdownby, from ? from : current->nick);
shutdowntime = now + secs;
Multicastf(WALLCAST, "Shutdown in %s. \"%s\"", TimeAgo(shutdowntime),
shutdownreason);
shuttingdown = TRUE;
}
else
CmdSyntax(errfrom, "SHUTDOWN");
}
}
else {
if (shuttingdown) {
Sendf(from, GetText(msg_shutdown_in_progress_left),
TimeAgo(shutdowntime));
}
else
Send(from, GetText(msg_no_shutdown));
}
}
/* --- CmdNick ---------------------------------------------------- */
void CmdNick(char *from, char *line)
{
snapshot;
if (line && *line) {
if ('+' == line[0]) {
NewNick();
WriteServer("NICK %s", nickname);
}
else {
nickflag = TRUE;
WriteServer("NICK %s", line);
}
}
else
CmdSyntax(errfrom, "NICK");
}
/* --- CmdReload -------------------------------------------------- */
void CmdReload(char *from, char *line)
{
extern char expfile[];
extern char funcfile[];
snapshot;
UserReload((line && *line) ? line : userfile);
ExplainReload(expfile);
FuncReload(funcfile);
Send(from, GetText(msg_reload_done));
}
/* --- CmdDo ------------------------------------------------------ */
void CmdDo(char *from, char *line)
{
char cmd[16];
snapshot;
if (1 == StrScan(line, " %15s", cmd)) {
if (StrEqual(cmd, "QUIT"))
Send(errfrom, GetText(msg_dont_send_raw));
else
WriteServer("%s", line);
}
else
CmdSyntax(errfrom, "DO");
}
/* --- CmdServer -------------------------------------------------- */
void CmdServer(char *from, char *line)
{
char name[MINIBUFFER];
char passwd[MINIBUFFER] = "";
int port = IRCPORT;
int tmpSocket = -1;
itemserv *serv = NULL;
snapshot;
if (1 <= StrScan(line, "%"MINIBUFFERTXT"s %d %"MINIBUFFERTXT"s",
name, &port, passwd)) {
int num = atoi(name);
if ('+' == name[0])
/* If the current server isn't in the list, then the first
server in the list will be returned - Bagder */
serv = NextServ();
else
/* Try to find the server from the list, this way we support server
number instead of server name too (if wanted) */
serv = FindServ(name, port);
if (num && !serv) {
/* we got a number, but we don't know a server with that ID */
Sendf(errfrom, GetText(msg_unknown_server), num);
return;
}
if (serv) {
/* the specified server exists in the list */
StrCopyMax(name, sizeof(name), serv->s.name);
StrCopyMax(passwd, sizeof(passwd), serv->s.passwd ? serv->s.passwd : "");
port = serv->s.port;
}
if ((tmpSocket = OpenServerConnection(name, port)) != -1) {
CloseConnection(serverSocket);
DisconnectServ("%s changed server to %s", current->nick, name);
serverSocket = tmpSocket;
BanDisable();
DeleteGuests();
StrCopy(servername, name);
serverport = port;
StrCopy(serverpasswd, passwd);
Hello(serv);
}
else
Sendf(errfrom, GetText(msg_server_cannot_connect_to_port), name, port);
}
else
Sendf(from, GetText(msg_im_on_server), servername);
}
/* --- CmdPass ---------------------------------------------------- */
bool Pass(itemident *p, char *line)
{
char buffer[BIGBUFFER];
snapshot;
if (p->user && p->user->passwd) {
if (line && CheckPassword(line, p->user->passwd)) {
if (CheckPassword(defaultpasswd, p->user->passwd))
Send(p->nick, GetText(msg_ident_defpass));
p->passed = TRUE;
return TRUE;
}
else {
StrFormatMax(buffer, sizeof(buffer), GetText(msg_spy_auth_failed), p->nick);
Log(LOG, buffer);
Multicast(SPYCAST, buffer);
}
}
return FALSE;
}
void CmdPass(char *from, char *line)
{
snapshot;
if (line && *line) {
if (Pass(current, line)) {
Send(from, GetText(msg_password_ok));
}
else
Send(from, GetText(msg_invalid_password));
}
else
CmdSyntax(errfrom, "PASS");
}
/* --- CmdNewPass ------------------------------------------------- */
void CmdNewPass(char *from, char *line)
{
char *passwd;
itemuser *u;
snapshot;
passwd = NextWord(line);
if (passwd) {
u = current->user;
if (u) {
if (u->passwd)
StrFree(u->passwd);
u->passwd = MakePassword(passwd);
u->passwdtime = u->modified = now;
Sendf(from, GetText(msg_passwd_changed), passwd);
UserSave();
if (!current->passed && !CheckPassword(defaultpasswd, u->passwd))
/* We were using default passwd when calling CmdNewPass() */
current->passed = TRUE;
}
else
Send(errfrom, GetText(msg_youre_not_registered));
}
else
CmdSyntax(errfrom, "NEWPASS");
}
/* --- CmdIdent --------------------------------------------------- */
void CmdIdent(char *from, char *line)
{
char passwd[MINIBUFFER];
char nick[NICKLEN+1] = "";
itemuser *u;
snapshot;
if (identprotect) {
/* IDENT is not allowed */
Send(errfrom, GetText(msg_ident_forbidden));
return;
}
else if (current->user) {
/* User is already IDENTed, say stop */
Send(errfrom, GetText(msg_ident_already_known));
return;
}
/* USAGE:
/MSG <botnick> IDENT <password> [nickname]
This will let the bot recognize you from a new site.
you MUST use your password (the one you set with PASS)
so the bot knows it's really you. if you're using a
different nickname than you were when you registered,
you'll have to give your original nickname too.
*/
if (1 <= StrScan(line, "%"MINIBUFFERTXT"s %"NICKLENTXT"s", passwd, nick)) {
if (nick[0])
u = FindUserByNick(nick);
else if (from)
u = FindUserByNick(from);
else
return; /* Can't continue */
if (NULL == u) {
Sendf(errfrom, GetText(msg_nick_not_found), nick[0] ? nick : from);
}
else {
if (StrEqualCase(passwd, defaultpasswd)) { /* Ident authentication tried with
the default password */
Send(from, GetText(msg_ident_noauth));
}
else if (CheckPassword(passwd, u->passwd)) {
AddDomain(u, current->userdomain); /* add pattern */
Logf(LOGMSG, "IDENT used to add pattern %s to user %s",
current->userdomain, u->nick);
u->modified = now; /* mark as modified */
current->passed = TRUE;
UserSave();
UserReload(userfile);
Send(from, GetText(msg_password_ok)); /* say ok */
}
else
Send(from, GetText(msg_invalid_password));
}
}
else
CmdSyntax(errfrom, "IDENT");
}
/* --- CmdDefPass ------------------------------------------------- */
void CmdDefPass(char *from, char *line)
{
itemguest *g;
itemuser *u;
snapshot;
if (line && *line) {
g = FindNick(line);
if (g)
u = g->ident->user;
else
u = FindUserByNick(line);
if (u) {
if (u->passwd)
StrFree(u->passwd);
u->passwd = MakePassword(defaultpasswd);
u->passwdtime = u->modified = now;
Sendf(errfrom, GetText(msg_defpass_done), line);
if (g)
SendNickf(g->ident->nick, GetText(msg_defpass_inform), defaultpasswd);
UserSave();
}
else
Sendf(errfrom, GetText(msg_nick_not_found), line);
}
else
CmdSyntax(errfrom, "DEFPASS");
}
/* --- CmdComment ------------------------------------------------- */
void DispComment(itemguest *g)
{
snapshot;
if (g->ident->user && g->ident->user->comment)
Sayf("\002[%s]\002 %s", g->ident->user->nick, g->ident->user->comment);
}
void CmdComment(char *from, char *line)
{
char nick[NICKLEN+1] = "";
char comment[MIDBUFFER] = "";
itemguest *g;
itemuser *u = current->user;
snapshot;
if (GetOption(line)) {
switch(toupper(option.copt)) {
case 'N': /* nick */
if (current->level >= LEVELEXPERT) {
StrScan(option.newpos, "%"NICKLENTXT"s", nick);
line = option.newpos + StrLength(nick);
g = FindNick(nick);
if (g)
u = g->ident->user;
else
u = FindUserByNick(nick);
if (NULL == u) {
Sendf(errfrom, GetText(msg_no_registered_user), nick);
return;
}
}
else {
Send(errfrom, GetText(msg_need_higher_level));
return;
}
break;
}
while (iswhite(*line))
line++;
}
if (line && (1 == StrScan(line, "%"MIDBUFFERTXT"[^\n]", comment))) {
if (u) {
if (u->comment)
StrFree(u->comment);
if (StrEqual(comment, "NONE")) {
u->comment = NULL;
Sendf(from, GetText(msg_comment_removed), u->nick);
}
else {
u->comment = StrDuplicate(comment);
Sendf(from, GetText(msg_comment_set), u->nick, u->comment);
}
u->modified = now;
UserSave();
}
else
Send(errfrom, GetText(msg_youre_not_registered));
}
else
CmdSyntax(errfrom, "COMMENT");
}
/* --- CmdConvert ------------------------------------------------- */
void CmdConvert(char *from, char *line)
{
snapshot;
Convert(from, line);
}
/* --- CmdSpell --------------------------------------------------- */
void CmdSpell(char *from, char *line)
{
snapshot;
if (line && *line)
Execute(from, "echo \"%s\" | %s", line, cmdspell);
else
CmdSyntax(errfrom, "SPELL");
}
/* --- CmdTz ------------------------------------------------------ */
void CmdTz(char *from, char *line)
{
snapshot;
TimeZone(from, line);
}
/* --- CmdModerate ------------------------------------------------ */
void CmdModerate(char *from, char *line)
{
itemguest *g, *gs[2];
int num = 0;
snapshot;
if (line && *line) {
if (!botop) {
Send(errfrom, GetText(msg_notop));
return;
}
if (StrEqual(line, "ON")) {
moderateflag = TRUE;
for (g = First(guestHead); g; g = Next(g)) {
if (!g->flags.chanop && !g->flags.voice) {
if (num < 2)
gs[num++] = g;
else {
Mode("+vvv %s %s %s", gs[0]->ident->nick, gs[1]->ident->nick,
g->ident->nick);
num = 0;
}
}
}
if (num > 0)
Mode("+vvv %s %s %s", gs[0]->ident->nick,
(num > 1) ? gs[1]->ident->nick : "",
(num > 2) ? g->ident->nick : "");
Mode("+m");
}
else if (StrEqual(line, "OFF")) {
moderateflag = FALSE;
Mode("-m");
for (g = First(guestHead); g; g = Next(g)) {
if (g->flags.voice) {
if (num < 2)
gs[num++] = g;
else {
Mode("-vvv %s %s %s", gs[0]->ident->nick, gs[1]->ident->nick,
g->ident->nick);
num = 0;
}
}
}
if (num > 0)
Mode("-vvv %s %s %s", gs[0]->ident->nick,
(num > 1) ? gs[1]->ident->nick : "",
(num > 2) ? g->ident->nick : "");
}
}
else
Sendf(from, GetText(msg_moderate_is), OnOff(moderateflag));
}
/* --- CmdNames --------------------------------------------------- */
void CmdNames(char *from, char *line)
{
extern itemident *identHead;
char match[MIDBUFFER] = "*";
itemguest *g;
itemident *qq;
snapshot;
StrScan(line, "%"MIDBUFFERTXT"s", match);
GetOption(line);
line = option.newpos;
if (('I' == toupper(option.copt)) && (current->level >= LEVELOWNER)) {
for (qq = First(identHead); qq; qq = Next(qq)) {
Sendf(from, "%-1s%-9s [%3d] (%s)%s%p %p %p",
qq->guest ?
(qq->guest->flags.chanop ? "@" :
(qq->guest->flags.voice ? "+" : "")) : "",
qq->nick, qq->level, qq->host,
qq->passed ? " Passed " : " ",
qq->user, qq->guest, qq->client);
}
}
else {
char s_level[5];
int counter = 0;
for (g = First(guestHead); g; g = Next(g)) {
if (Match(g->ident->host, match)) {
counter++;
if (g->ident->level >= current->level)
StrCopyMax(s_level, sizeof(s_level), "XXX");
else
StrFormatMax(s_level, sizeof(s_level), "%3d", g->ident->level);
Sendf(from, "%-1s%-9s [%s] (%s)%s",
g->flags.chanop ? "@" : (g->flags.voice ? "+" : ""),
g->ident->nick, s_level, g->ident->host,
g->flags.split ? " Split" : "");
}
}
if (0 == counter) {
Send(errfrom, GetText(msg_no_user_matched));
}
}
}
/* --- CmdMe ------------------------------------------------------ */
void CmdMe(char *from, char *line)
{
snapshot;
if (line && *line) {
if (saymode || (current->level >= LEVELBOT))
Action(line);
else
Send(errfrom, GetText(msg_say_is_off));
}
else
CmdSyntax(errfrom, "ME");
}
/* --- CmdSay ----------------------------------------------------- */
void CmdSay(char *from, char *line)
{
snapshot;
if (line && *line) {
if (saymode || (current->level >= LEVELBOT))
Say(line);
else
Send(errfrom, GetText(msg_say_is_off));
}
else
CmdSyntax(errfrom, "SAY");
}
/* --- CmdTalk ---------------------------------------------------- */
void CmdTalk(char *from, char *line)
{
snapshot;
if (!mute) {
if (!talkative) {
talkative = TRUE;
if (!from)
from = current->nick;
Sayf(GetText(msg_talk_on), IsChannel(from) ? errfrom : from);
}
else
Send(errfrom, GetText(msg_talk_already));
}
else
Send(current->nick, GetText(msg_mute_is_on));
}
/* --- CmdQuiet --------------------------------------------------- */
void CmdQuiet(char *from, char *line)
{
snapshot;
if (!mute) {
if (talkative) {
talkative = FALSE;
if (!from)
from = current->nick;
Sayf(GetText(msg_quiet_on), IsChannel(from) ? errfrom : from);
}
else
Send(errfrom, GetText(msg_quiet_already));
}
else
Send(current->nick, GetText(msg_mute_is_on));
}
/* --- CmdMute ---------------------------------------------------- */
void CmdMute(char *from, char *line)
{
snapshot;
if (!mute) {
mute = TRUE;
if (talkative)
Sayf(GetText(msg_mute_talkative));
else
Send(from, GetText(msg_mute_grave));
}
else {
mute = FALSE;
Send(current->nick, GetText(msg_mute_is_off));
}
}
/* --- CmdWall ---------------------------------------------------- */
void CmdWall(char *from, char *line)
{
snapshot;
if (line && *line)
Multicastf(WALLCAST, "WALL from %s: %s", from ? from : current->nick, line);
else
CmdSyntax(errfrom, "WALL");
}
/* --- CmdTellme -------------------------------------------------- */
void CmdTellme(char *from, char *line)
{
char *host = NULL;
bool all;
snapshot;
all = (GetOption(line) && (toupper(option.copt) == 'A'));
line = option.newpos;
host = current->userdomain;
if (host)
TellMe(from, host, (current->level >= LEVELPUB) ? all : FALSE);
}
/* --- CmdTelladd ------------------------------------------------- */
void CmdTelladd(char *from, char *line)
{
char recv[NICKLEN+1];
char msg[BIGBUFFER];
char sendr[MIDBUFFER];
char *host = current->host;
char *to = NULL;
itemguest *g;
itemuser *u;
itemaux *pa;
snapshot;
if (host && (2 <= StrScan(line, "%"NICKLENTXT"s %"BIGBUFFERTXT"[^\n]", recv, msg))) {
if ((g = FindNick(recv)) && !g->flags.split) {
Sendf(from, GetText(msg_tell_already_here), recv);
return;
}
else if (u = FindUserByNick(recv)) {
itemlist *l = First(u->domainhead);
to = (char *)(l ? l->pointer : NULL);
}
else if (pa = SeenMostNick(recv)) {
to = pa->root->host;
}
if (to) {
StrFormatMax(sendr, sizeof(sendr), "%s!%s", from ? from : current->nick, host);
if (StrLength(msg) > (BIGBUFFER - 100)) {
int cutpos = BIGBUFFER/2;
while (msg[cutpos] && !iswhite(msg[cutpos]))
cutpos++;
msg[cutpos] = (char)0; /* Split the message in two parts */
/* add both parts */
TellAdd(from, sendr, to, msg);
TellAdd(from, sendr, to, &msg[cutpos+1]);
}
else
TellAdd(from, sendr, to, msg);
}
else
Sendf(errfrom, GetText(msg_tell_no_information), recv);
}
else
CmdSyntax(errfrom, "TELL");
}
/* --- CmdTelldel ------------------------------------------------- */
void CmdTelldel(char *from, char *line)
{
snapshot;
if (current->host)
TellDel(from, current->host, line);
}
/* --- CmdTelllist ------------------------------------------------ */
void CmdTelllist(char *from, char *line)
{
snapshot;
if (current->host)
TellList(from, current->host);
}
/* --- Warnings --------------------------------------------------- */
void CmdWarnlist(char *from, char *line)
{
char warnmatch[MINIBUFFER] = "*";
int flags = 0;
snapshot;
if (NULL == from)
from = current->nick;
while(GetOption(line)) {
switch(toupper(option.copt)) {
case 'A':
flags |= WLIST_ALL;
break;
case 'B':
flags |= WLIST_BAN;
break;
}
line = option.newpos;
}
StrScan(line, "%"MINIBUFFERTXT"s", warnmatch);
if (!WarnList(from, warnmatch, flags))
Send(from, GetText(msg_warnlist_no_match));
}
void CmdWarndel(char *from, char *line)
{
char warndelete[MIDBUFFER];
snapshot;
if (NULL == from)
from = current->nick;
if (1 == StrScan(line, "%"MIDBUFFERTXT"s", warndelete))
WarnDel(from, warndelete);
else
CmdSyntax(errfrom, "WARNDEL");
}
void CmdWarnadd(char *from, char *line)
{
char warnnick[MIDBUFFER];
char warnmessage[MINIBUFFER];
char warnbuffer[MIDBUFFER];
char nickpattern[NICKLEN+1];
char userpattern[USERLEN+1];
char hostpattern[MIDBUFFER];
char *nick;
int flags = 0;
snapshot;
if (GetOption(line) && ('B' == toupper(option.copt))) {
flags |= WARNF_KICKBAN;
line = option.newpos;
}
if (2 == StrScan(line, "%"MIDBUFFERTXT"s %"MINIBUFFERTXT"[^\n]",
warnnick, warnmessage)) {
if (3 == StrScan(warnnick, "%"NICKLENTXT"[^!]!%"USERLENTXT"[^@]@%"MIDBUFFERTXT"s",
nickpattern, userpattern, hostpattern)) {
StrFormatMax(warnbuffer, sizeof(warnbuffer), "%s@%s", userpattern, hostpattern);
nick = NULL; /* disable the nick part */
}
else {
StrCopy(nickpattern, "*");
nick = warnnick;
if ('*' == nick[0])
nick++;
if (!NickToPattern(warnnick, warnbuffer, FALSE)) {
Sendf(errfrom, GetText(msg_warnadd_could_not_find), nick);
return;
}
}
if (Match(botmatch, warnbuffer) && Match(nickname, nickpattern)) {
Send(errfrom, GetText(msg_warnadd_include_me));
return;
}
if (WarnAdd(nick, warnbuffer, nickpattern, warnmessage, current->host, flags)) {
Sendf(from, GetText(msg_warnadd_added), nick ? nick : "warning",
nickpattern, warnbuffer);
}
else
Send(errfrom, GetText(msg_warnadd_not_added));
}
else
CmdSyntax(errfrom, "WARNADD");
}
/* --- CmdTopic --------------------------------------------------- */
extern time_t topictime;
extern char topic[], topicwho[];
void CmdTopic(char *from, char *line)
{
snapshot;
if (line && *line)
WriteServer("TOPIC %s :[%s]:%s", channel, current->nick, line);
else if (topictime) {
Sendf(from, GetText(msg_topic_set),
topic, topicwho, TimeAgo(topictime));
}
else
Send(from, GetText(msg_topic_not_set));
}
/* --- CmdLag ----------------------------------------------------- */
#ifdef PING_IN_SEC
extern int pingdelay;
#else
extern struct timeval delayval;
#endif
void CmdLag(char *from, char *line)
{
snapshot;
Sendf(from, GetText(msg_lag), servername, delayval.tv_sec,
delayval.tv_usec/(MILLION/1000));
}
/* --- CmdReportadd/del ------------------------------------------- */
void CmdReportadd(char *from, char *line)
{
itemclient *k;
snapshot;
k = client;
if (k) {
if (!(k->flags & REPORTCAST)) {
k->flags |= REPORTCAST;
Send(from, GetText(msg_report_on));
}
else
Send(from, GetText(msg_report_already_on));
}
else
Send(errfrom, GetText(msg_use_chat));
}
void CmdReportdel(char *from, char *line)
{
itemclient *k;
snapshot;
k = client;
if (k) {
if (k->flags & REPORTCAST) {
k->flags &= ~REPORTCAST;
Send(from, GetText(msg_report_off));
}
else
Send(from, GetText(msg_report_already_off));
}
else
Send(errfrom, GetText(msg_use_chat));
}
/* --- CmdSpyadd/del ---------------------------------------------- */
void CmdSpyadd(char *from, char *line)
{
itemclient *k;
snapshot;
if (k=client) {
if ( !(k->flags & SPYCAST) ) {
k->flags |= SPYCAST;
Send(from, GetText(msg_spy_on));
} else
Send(from, GetText(msg_spy_already_on));
} else
Send(errfrom, GetText(msg_use_chat));
}
void CmdSpydel(char *from, char *line)
{
itemclient *k;
snapshot;
if (k=client) {
if ( k->flags & SPYCAST ) {
k->flags &= ~SPYCAST;
Send(from, GetText(msg_spy_off));
} else
Send(from, GetText(msg_spy_already_off));
} else
Send(errfrom, GetText(msg_use_chat));
}
/* --- CmdDebugadd/del -------------------------------------------- */
void CmdDebugadd(char *from, char *line)
{
itemclient *k;
snapshot;
if (k=client) {
if ( !(k->flags & DEBUGCAST) ) {
k->flags |= DEBUGCAST;
Send(from, GetText(msg_debug_on));
} else
Send(from, GetText(msg_debug_already_on));
} else
Send(errfrom, GetText(msg_use_chat));
}
void CmdDebugdel(char *from, char *line)
{
itemclient *k;
snapshot;
if (k=client) {
if ( k->flags & DEBUGCAST ) {
k->flags &= ~DEBUGCAST;
Send(from, GetText(msg_debug_off));
} else
Send(from, GetText(msg_debug_already_off));
} else
Send(errfrom, GetText(msg_use_chat));
}
/* --- CmdAlias --------------------------------------------------- */
void CmdAlias(char *from, char *line)
{
struct Command *command;
snapshot;
if (line && *line) {
StrTokenize(line, " ");
if ( (command=FindCommand(line)) &&
(command->level <= current->level) /*&&
(!command->needpass || current->passed)*/ ) {
if (command->aliases)
Sendf(from, GetText(msg_alias_aliases),
command->name, StrIndex(command->name, NIL) + 1);
else
Sendf(from, GetText(msg_alias_no_aliases), command->name);
} else
Sendf(errfrom, GetText(msg_alias_command_not_found), line);
} else
CmdSyntax(errfrom, "ALIAS");
}
/* --- CmdWholeft ------------------------------------------------- */
void CmdWholeft(char *from, char *line)
{
extern itemsplit *splitHead;
char buffer[MIDBUFFER];
char single[MIDBUFFER];
bool all;
itemguest *g;
itemsplit *p;
snapshot;
all = (GetOption(line) && ('A' == toupper(option.copt)) && chat);
line = option.newpos;
for (p = First(splitHead); p; p = Next(p)) {
StrFormatMax(buffer, sizeof(buffer), "Between %s: ", p->servers);
for (g = First(p->wholeft); g; g = Next(g)) {
StrFormatMax(single, sizeof(single), "%s%s%s%s%s ",
g->flags.chanop ? "@" :
g->flags.voice ? "+" : "",
g->ident->nick,
all ? " (" : "",
all ? g->ident->host : "",
all ? ") " : "");
if ((StrLength(buffer) + StrLength(single)) >= sizeof(buffer)) {
Send(from, buffer);
buffer[0] = (char)0;
}
StrAppend(buffer, single);
}
if (buffer[0])
Send(from, buffer);
}
}
/* --- CmdIdentify ------------------------------------------------ */
void FreeIdent(void *);
void CmdIdentify(char *from, char *line)
{
extern itemident *identHead;
char *nick;
itemguest *w;
snapshot;
if (line && *line) {
if (chat) {
nick = NextWord(line);
if (nick && (w = FindNick(nick))) {
if (w->ident->client != client) {
if (!w->ident->client) {
if ((w->ident->user == client->ident->user) &&
StrEqual(w->ident->host, client->ident->host)) {
w->ident->passed |= client->ident->passed;
w->ident->client = client->ident->client;
client->ident->client = NULL;
DeleteEntry(identHead, client->ident, FreeIdent);
client->ident = w->ident;
}
else
Send(errfrom, GetText(msg_identify_no_match));
}
else
Sendf(errfrom, GetText(msg_identify_already_linked), w->ident->nick);
}
else
Send(errfrom, GetText(msg_identify_already_unified));
}
else
Sendf(errfrom, GetText(msg_identify_no_nick), nick, channel);
}
else
Send(errfrom, GetText(msg_identify_only_dcc));
}
else
CmdSyntax(errfrom, "MYNICK");
}
/* --- CmdCut ----------------------------------------------------- */
void CmdCut(char *from, char *line)
{
itemclient *k;
char *nick;
snapshot;
nick = NextWord(line);
if (nick && (LEVELBOT <= current->level)) {
k = FindClientByNick(nick);
if (k) {
SendNickf(nick, GetDefaultText(msg_cut_closed_by), current->nick);
/* CloseConnection(k->socket); done in RemoveClient() */
RemoveClient(k);
}
else
Sendf(errfrom, GetText(msg_cut_no_client), nick);
}
else if (client) {
SendNick(current->nick, GetText(msg_cut_closed));
/* CloseConnection(client->socket); done in RemoveClient() */
RemoveClient(client);
client = NULL;
}
else
CmdSyntax(errfrom, "CUT");
}
enum {
TOP_NOTHING,
TOP_JOINED,
TOP_JOINS,
TOP_IDLE,
TOP_TALK,
TOP_RATE,
TOP_COUNTRY,
TOP_CONTINENT,
TOP_COMMAND,
TOP_KICKER,
TOP_BANNER,
TOP_LAST
};
void TopCommands( char* from )
{
int i;
snapshot;
InitTop();
for (i=0; cmds[i].name; i++)
AddToTop(cmds[i].name, cmds[i].counter);
Send(from, PresentTop());
}
void TopModes( char* from )
{
static char* modes[11] = {
"Op", "Ban", "Key", "Limit", "Voice", "Private", "Secret",
"Invite", "Topic", "NoMsg", "Moderated" };
int i;
snapshot;
InitTop();
for (i=0; i<11; i++)
AddToTop( modes[i], modecount[i] );
Send(from, PresentTop());
}
void TopKicks(char *from)
{
itemkick *p;
snapshot;
InitTop();
for (p = First(kickHead); p; p = Next(p))
AddToTop(p->nick, p->totkicks);
Send(from, PresentTop());
}
void CmdToplist(char *from, char *line)
{
char kind[MINIBUFFER];
int what = TOP_NOTHING;
int value;
itemguest *g;
topitem *countryHead;
snapshot;
if (1 == StrScan(line, "%"MINIBUFFERTXT"s", kind)) {
if (StrEqual(kind, "JOINED"))
what = TOP_JOINED;
else if (StrEqual(kind, "JOINS"))
what = TOP_JOINS;
else if (StrEqual(kind, "IDLE"))
what = TOP_IDLE;
else if (StrEqual(kind, "TALK"))
what = TOP_TALK;
else if (StrEqual(kind, "COUNTRY"))
what = TOP_COUNTRY;
else if (StrEqual(kind, "CONTINENT"))
what = TOP_CONTINENT;
else if (StrEqual(kind, "KICKER"))
what = TOP_KICKER;
else if (StrEqual(kind, "BANNER"))
what = TOP_BANNER;
else if (StrEqual(kind, "COMMAND")) {
TopCommands(from);
return;
}
else if (StrEqual(kind, "MODE")) {
TopModes( from );
return;
}
else if (StrEqual(kind, "KICK")) {
TopKicks( from );
return;
}
if (TOP_NOTHING == what) {
Send(errfrom, GetText(msg_top_unknown));
return;
}
/* Some special handling for country & continent toplists */
if ((TOP_COUNTRY == what) || (TOP_CONTINENT == what))
countryHead = NewList(topitem);
InitTop();
for (g = First(guestHead); g; g = Next(g)) {
char *ptr;
land *n;
if (g->flags.bot || IRCEqual(g->ident->nick, nickname)) {
/* "we are the robots" (Kraftwerk) */
continue;
}
if (TOP_COUNTRY == what) {
ptr = StrIndexLast(g->ident->host, '.');
if (ptr && (n = FindByCode(++ptr))) {
topitem *cntr;
topitem *new;
for (cntr = First(countryHead); cntr; cntr = Next(cntr)) {
if (StrEqualCase(cntr->name, n->country))
break;
}
if (cntr) {
cntr->count++;
}
else {
new = NewEntry(topitem);
if (new) {
InsertLast(countryHead, new);
StrCopy(new->name, n->country);
new->count = 1;
}
}
}
}
else if (TOP_CONTINENT == what) {
ptr = StrIndexLast(g->ident->host, '.');
if (ptr && (n = FindByCode(++ptr))) {
topitem *cntr;
topitem *new;
char cont = n->continent;
#if 0
/* What's this? -gr8ron (17.04.1999) */
if (cont > 6) {
printf("%s has continent number #%d!\n", n->country, cont );
continue;
}
#endif
for (cntr = First(countryHead); cntr; cntr = Next(cntr)) {
if (StrEqualCase(cntr->name, continents[cont]))
break;
}
if (cntr) {
cntr->count++;
}
else {
new = NewEntry(topitem);
if (new) {
InsertLast(countryHead, new);
StrCopy(new->name, continents[cont]);
new->count = 1;
}
}
}
}
/* All other toplists */
else {
switch(what) {
case TOP_JOINS:
value = g->joins;
break;
case TOP_JOINED:
value = (now - g->jointime)/60;
break;
case TOP_IDLE:
value = (now - (g->posttime ? g->posttime : g->jointime))/60;
break;
case TOP_TALK:
value = g->posts;
break;
case TOP_KICKER:
value = g->kicks;
break;
case TOP_BANNER:
value = g->bans;
break;
}
AddToTop(g->ident->nick, value);
}
}
if ((TOP_COUNTRY == what) || (TOP_CONTINENT == what)) {
topitem *cntr;
for (cntr = First(countryHead); cntr; cntr = Next(cntr)) {
AddToTop(cntr->name, cntr->count);
}
DeleteList(countryHead, NULL);
}
Send(from, PresentTop());
}
}
/* --- CmdInvite -------------------------------------------------- */
extern char chanmodes[];
static void InviteMe(char *from, itemuser *u, char *passwd)
{
snapshot;
if (NULL == from)
from = current->nick;
if (!FindNick(from)) {
/* Uncomment when chanmodes is properly updated again
if (StrIndex(chanmodes, 'i')) { */
if (u->passwd && CheckPassword(passwd, u->passwd))
Invite(from);
/* }
else
Send(from, GetText(msg_channel_not_invite_only)); */
}
else
Send(errfrom, GetText(msg_invite_already_here));
}
void CmdInvite(char *from, char *line)
{
snapshot;
InviteMe(from, current->user, line);
}
char *VarInfo(int arg)
{
snapshot;
switch(arg) {
case VAR_NICKNAME:
return current->nick;
case VAR_CHANNEL:
return channel;
case VAR_BOTNAME:
return nickname;
}
return NULL;
}
/* --- CmdWebster ------------------------------------------------- */
#ifdef BREESE
void CmdWebster(char *from, char *line)
{
char *word;
snapshot;
if (chat) {
word = NextWord(line);
if (word) {
Execute(from, "webster \"%s\" 2>&1", word);
}
else
CmdSyntax(errfrom, "WEBSTER");
}
else
Send(errfrom, GetText(msg_use_chat));
}
#endif
/* --- CmdLog ----------------------------------------------------- */
extern ulong activelog;
void CmdLog(char *from, char *line)
{
char buffer[BIGBUFFER] = "";
char *word;
snapshot;
if (line && *line) {
while (word = NextWord(line)) {
if (StrEqual(word, "ALL"))
activelog = -1;
else if (StrEqual(word, "NONE"))
activelog = 0;
else if (StrEqual(word, "JOIN"))
activelog |= 1<<LOGJOIN | 1<<LOGPART | 1<<LOGQUIT | 1<<LOGKILL;
else if (StrEqual(word, "-JOIN"))
activelog &= ~(1<<LOGJOIN) & ~(1<<LOGPART) & ~(1<<LOGQUIT) & ~(1<<LOGKILL);
else if (StrEqual(word, "KICK"))
activelog |= 1<<LOGKICK;
else if (StrEqual(word, "-KICK"))
activelog &= ~(1<<LOGKICK);
else if (StrEqual(word, "NICK"))
activelog |= 1<<LOGNICK;
else if (StrEqual(word, "-NICK"))
activelog &= ~(1<<LOGNICK);
else if (StrEqual(word, "MODE"))
activelog |= 1<<LOGMODE;
else if (StrEqual(word, "-MODE"))
activelog &= ~(1<<LOGMODE);
else if (StrEqual(word, "TOPIC"))
activelog |= 1<<LOGTOPIC;
else if (StrEqual(word, "-TOPIC"))
activelog &= ~(1<<LOGTOPIC);
else if (StrEqual(word, "CMD"))
activelog |= 1<<LOGCMD | 1<<LOGPCMD;
else if (StrEqual(word, "-CMD"))
activelog &= ~(1<<LOGCMD) & ~(1<<LOGPCMD);
else if (StrEqual(word, "MSG"))
activelog |= 1<<LOGMSG;
else if (StrEqual(word, "-MSG"))
activelog &= ~(1<<LOGMSG);
else if (StrEqual(word, "CTCP"))
activelog |= 1<<LOGCTCP;
else if (StrEqual(word, "-CTCP"))
activelog &= ~(1<<LOGCTCP);
else if (StrEqual(word, "CLIENT"))
activelog |= 1<<LOGCLIENT;
else if (StrEqual(word, "-CLIENT"))
activelog &= ~(1<<LOGCLIENT);
else if (StrEqual(word, "WARN"))
activelog |= 1<<LOGWARN;
else if (StrEqual(word, "-WARN"))
activelog &= ~(1<<LOGWARN);
else if (StrEqual(word, "SPLIT"))
activelog |= 1<<LOGSPLIT | 1<<LOGNJOIN | 1<<LOGNHEAL;
else if (StrEqual(word, "-SPLIT"))
activelog &= ~(1<<LOGSPLIT) & ~(1<<LOGNJOIN) & ~(1<<LOGNHEAL);
else if (StrEqual(word, "DEBUG"))
activelog |= 1<<LOGDEBUG | 1<<LOGDBUG;
else if (StrEqual(word, "-DEBUG"))
activelog &= ~(1<<LOGDEBUG) & ~(1<<LOGDBUG);
else if (StrEqual(word, "INIT"))
activelog |= 1<<LOGINIT;
else if (StrEqual(word, "-INIT"))
activelog &= ~(1<<LOGINIT);
else if (StrEqual(word, "PUB"))
activelog |= 1<<LOGPUB;
else if (StrEqual(word, "-PUB"))
activelog &= ~(1<<LOGPUB);
}
}
if (0 == activelog)
StrCopyMax(buffer, sizeof(buffer), "Nothing");
else if (LOGALLMASK == (activelog & ~LOGALLMASK))
StrCopyMax(buffer, sizeof(buffer), "Everything");
else {
if (activelog & (1<<LOGJOIN | 1<<LOGPART | 1<<LOGQUIT | 1<<LOGKILL))
StrAppendMax(buffer, sizeof(buffer), "Joins/Parts/Quits/Kills, ");
if (activelog & 1<<LOGKICK)
StrAppendMax(buffer, sizeof(buffer), "Kicks, ");
if (activelog & 1<<LOGNICK)
StrAppendMax(buffer, sizeof(buffer), "Nick Changes, ");
if (activelog & 1<<LOGMODE)
StrAppendMax(buffer, sizeof(buffer), "Mode Changes, ");
if (activelog & 1<<LOGTOPIC)
StrAppendMax(buffer, sizeof(buffer), "Topic changes, ");
if (activelog & (1<<LOGCMD | 1<<LOGPCMD))
StrAppendMax(buffer, sizeof(buffer), "Commands, ");
if (activelog & 1<<LOGMSG)
StrAppendMax(buffer, sizeof(buffer), "Messages, ");
if (activelog & 1<<LOGCTCP)
StrAppendMax(buffer, sizeof(buffer), "CTCP, ");
if (activelog & 1<<LOGCLIENT)
StrAppendMax(buffer, sizeof(buffer), "Client Connections, ");
if (activelog & 1<<LOGWARN)
StrAppendMax(buffer, sizeof(buffer), "Warnings, ");
if (activelog & (1<<LOGSPLIT | 1<<LOGNJOIN | 1<<LOGNHEAL))
StrAppendMax(buffer, sizeof(buffer), "Netsplits, ");
if (activelog & (1<<LOGDEBUG | 1<<LOGDBUG))
StrAppendMax(buffer, sizeof(buffer), "Debug Info, ");
if (activelog & 1<<LOGINIT)
StrAppendMax(buffer, sizeof(buffer), "Init, ");
if (activelog & 1<<LOGPUB)
StrAppendMax(buffer, sizeof(buffer), "Public, ");
}
if (buffer[0])
Sendf(from, GetText(msg_log_logging), buffer);
else
Send(from, GetText(msg_log_nothing));
}
void CmdUserAdd(char *from, char *line)
{
/*
* USERADD [-r <regnick>] [-p <pattern>]
* <nick> <level> [email - real name]
*/
char nick[NICKLEN+1] = "";
char regnick[NICKLEN+1] = "";
char hostpattern[MIDBUFFER] = "";
char passwd[MINIBUFFER] = "";
char email[BIGBUFFER];
char dump[BIGBUFFER];
bool quiet = FALSE;
int level = 0;
itemguest *g;
itemuser *u;
snapshot;
while (GetOption(line)) {
line = option.newpos;
switch(toupper(option.copt)) {
case 'R':
StrScan(line, "%"NICKLENTXT"s", regnick);
line += StrLength(regnick); /* to avoid %n */
break;
case 'P':
StrScan(line, "%"MIDBUFFERTXT"s", hostpattern);
line += StrLength(hostpattern); /* to avoid %n */
break;
case 'N':
StrScan(line, "%"MINIBUFFERTXT"s", passwd);
line += StrLength(passwd); /* to avoid %n */
break;
case 'Q':
quiet = TRUE;
break;
default:
CmdSyntax(errfrom, "USERADD");
return;
}
while (iswhite(*line))
line++;
}
StrCopyMax(email, sizeof(email), GetDefaultText(msg_unknown));
if (isdigit(*line)) {
/* This is no nick on line */
StrScan(line, "%d %"SEMIBUFFERTXT"[^\n]", &level, email);
}
else
StrScan(line, "%"NICKLENTXT"s %d %"SEMIBUFFERTXT"[^\n]", nick, &level, email);
if (NIL == regnick[0])
StrCopy(regnick, nick);
if (!regnick[0] || isdigit(regnick[0])) {
Send(errfrom, GetText(msg_i_need_a_nick));
return;
}
g = FindNick(nick);
if (NULL == g) {
/* Not found, off-channel add in progress */
if (NIL == hostpattern[0]) {
Send(errfrom, GetText(msg_need_pattern_offchannel));
return;
}
}
else {
if (NIL == hostpattern[0]) {
/* Nothing fancy requested */
char *hostp = g->ident->userdomain;
if (IsPrefix(hostp))
hostp++;
StrCopyMax(hostpattern, sizeof(hostpattern), hostp);
}
}
u = FindUserByNick(regnick); /* regnick is the nick to add */
if (u) {
Sendf(errfrom, GetText(msg_another_nick_added), regnick);
return;
}
if (g && g->ident->user) {
Sendf(errfrom, GetText(msg_already_added), nick);
return;
}
if (!StrIndex(hostpattern, '@')) {
Sendf(errfrom, GetText(msg_illegal_pattern), hostpattern);
return;
}
if (level >= current->level)
level = current->level - 1;
StrFormatMax(dump, sizeof(dump), "%s %d (%s)\n", regnick, level, email);
u = AddUser(dump);
if (u) {
AddDomain(u, hostpattern);
u->passwd = MakePassword(passwd[0] ? passwd : defaultpasswd);
StrFormatMax(dump, sizeof(dump), "%s!%s %d %d\n",
current->nick, current->host, now, USER_ADDED);
AddMoreInfo(u, dump);
u->language = defaultlang;
u->modified = u->created = u->passwdtime = now;
}
UserSave();
UserReload(userfile);
if (g && !quiet)
SendNickf(nick, GetDefaultText(msg_added_inform),
level, hostpattern, passwd[0]?passwd:defaultpasswd);
Sendf(from, GetText(msg_user_added),
regnick, level, hostpattern,
passwd[0] ? GetText(msg_with_nondefault_password) : "",
(g && !quiet) ? GetText(msg_and_informed) : "");
}
void CmdUserDel(char *from, char *line)
{
/*
* USERDEL [-q] [-u] [-f] [-r] <nick>
*/
char nick[NICKLEN+1] = "";
char regnick[NICKLEN+1] = "";
bool quiet = FALSE;
bool undo = FALSE; /* is this a userdel undo? */
bool force = FALSE; /* force userdel immediately */
itemuser *u = NULL;
itemguest *g = NULL;
snapshot;
while (GetOption(line)) {
line = option.newpos;
switch(toupper(option.copt)) {
case 'R':
StrScan(line, "%"NICKLENTXT"s", regnick);
line += StrLength(regnick); /* to avoid %n */
break;
case 'Q':
quiet = TRUE;
break;
case 'U':
undo = TRUE;
break;
case 'F':
force = TRUE;
break;
default:
CmdSyntax(errfrom, "USERDEL");
return;
}
while (iswhite(*line))
line++;
}
StrScan(line, "%"NICKLENTXT"s", nick);
if ((char)0 == regnick[0]) {
if ((char)0 == nick[0]) {
Send(errfrom, GetText(msg_no_nick));
return;
}
StrCopy(regnick, nick);
g = FindNick(nick);
if (g)
u = g->ident->user;
}
if (NULL == u)
u = FindUserByNick(regnick); /* regnick is the user to delete */
if (NULL == u) {
Sendf(errfrom, GetText(msg_no_registered_user), regnick);
return;
}
if (undo) {
/*
* UNDO was selected with the -U switch
*/
if (!u->flags.delete) {
Send(errfrom, GetText(msg_cant_undo_delete));
return;
}
u->flags.delete = FALSE;
u->modified = now; /* remember when this was done */
Sendf(from, GetText(msg_no_longer_deleted), regnick);
}
else {
if (force) {
/*
* FORCE userdel immediately, -F switch
*/
DeleteEntry(userHead, u, FreeUser);
}
else {
/*
* This is a real mark-user-to-get-deleted action.
*/
if (u->flags.delete) {
Send(errfrom, GetText(msg_already_deleted));
return;
}
u->flags.delete = TRUE; /* mark for deletion */
u->modified = now; /* remember when this was done */
}
if (g && !quiet)
SendNickf(nick, force ? GetDefaultText(msg_userdel_inform_real) : GetDefaultText(msg_userdel_inform),
current->nick);
Sendf(from, force ? GetText(msg_userdel_done_real) : GetText(msg_userdel_done),
regnick, (g && !quiet) ? GetText(msg_and_informed) : "");
}
UserSave();
if (force)
UserReload(userfile);
}
void CmdUserMod(char *from, char *line)
{
/*
USERMOD
[-q] - quiet
[-p <pattern>] - add pattern
[-d <pattern num>] - delete pattern
[-n <password>] - change password
[-c "<comment>"] - change comment
[-e "<email>"] - change email
[-f -+<flags>] - set remove flags
[-r <new nick>] - change regged nick
<nick> [level]
*/
char nick[NICKLEN+1] = "";
char pattern[MIDBUFFER] = "";
char delpattern[MIDBUFFER] = "";
char password[MIDBUFFER] = "";
char email[MIDBUFFER] = "";
char comment[MIDBUFFER] = "";
char newnick[MIDBUFFER] = "";
char buffer[BIGBUFFER];
bool quiet = FALSE;
bool changed = FALSE;
int level = -1;
int patnum = -1;
int banprot = -1;
int autoop = -1;
int linkbot = -1;
int regularbot = -1;
int stealth = -1;
itemuser *u = NULL;
itemguest *g = NULL;
snapshot;
while (GetOption(line)) {
line = option.newpos;
switch(toupper(option.copt)) {
case 'Q':
quiet = TRUE; /* don't tell the lemming about this */
break;
case 'P':
StrScan(line, "%"MIDBUFFERTXT"s", pattern);
line += StrLength(pattern); /* to avoid %n */
break;
case 'D':
{
char *newline;
patnum = StrToLong(line, &newline, 10);
StrScan(line, "%"MIDBUFFERTXT"s", delpattern);
line += StrLength(delpattern);
}
break;
case 'N':
StrScan(line, "%"MIDBUFFERTXT"s", password);
line += StrLength(password); /* to avoid %n */
break;
case 'C':
if ('\"' == *line) {
StrScan(++line, "%"MIDBUFFERTXT"[^\"]", comment);
line += StrLength(comment); /* to avoid %n */
if ('\"' == *line)
line++;
}
else {
StrScan(line, "%"MIDBUFFERTXT"s", comment);
line += StrLength(comment); /* to avoid %n */
}
break;
case 'E':
if ('\"' == *line) {
StrScan(++line, "%"MIDBUFFERTXT"[^\"]", email);
line += StrLength(email); /* to avoid %n */
if ('\"' == *line)
line++;
}
else {
StrScan(line, "%"MIDBUFFERTXT"s", email);
line += StrLength(email); /* to avoid %n */
}
break;
case 'F':
{
#define FLAG_ADD 1
#define FLAG_DEL 0
int adddel = FLAG_ADD;
bool cut = FALSE;
while (*line) {
switch(toupper(*line)) {
case '+':
adddel = FLAG_ADD;
break;
case '-':
adddel = FLAG_DEL;
break;
case 'B':
banprot = adddel;
break;
case 'A':
autoop = adddel;
break;
case 'L':
linkbot = adddel;
break;
case 'R':
regularbot = adddel;
break;
case 'S':
if (current->level >= LEVELOWNER)
stealth = adddel;
break;
default:
cut = TRUE;
break;
}
if (cut)
break;
line++;
}
}
break;
case 'R':
StrScan(line, "%"MIDBUFFERTXT"s", newnick);
line += StrLength(newnick); /* to avoid %n */
if (StrLength(newnick) > NICKLEN) {
newnick[NICKLEN] = (char)0; /* Trim nick to make sure it is not longer than the acceptible nick length */
}
if (isdigit(newnick[0])) { /* lets not allow nicks that start with a digit */
Send(errfrom, GetText(msg_i_need_a_nick));
return;
}
break;
default:
CmdSyntax(errfrom, "USERMOD");
return;
}
while (iswhite(*line))
line++;
}
if (1 > StrScan(line, "%"NICKLENTXT"s %d", nick, &level)) {
if ((char)0 == newnick[0]) {
CmdSyntax(errfrom, "USERMOD");
return;
}
}
if (newnick[0] && (((char)0 == nick[0]) || isdigit(nick[0]))) {
if (isdigit(nick[0]))
level = atoi(nick);
StrCopyMax(nick, sizeof(nick), newnick);
newnick[0] = (char)0;
}
else {
g = FindNick(nick);
if (g && g->ident->user)
u = g->ident->user;
}
if (NULL == u) {
u = FindUserByNick(nick);
if (NULL == u) {
Sendf(errfrom, GetText(msg_no_registered_user), nick);
return;
}
}
if (level >= 0) {
if (u->level >= current->level) {
Send(errfrom, GetText(msg_cant_change_higher_user));
return;
}
}
if (pattern[0]) {
/* add this pattern, - adds current */
if (('-' == pattern[0]) && (NULL == g)) {
Send(errfrom, GetText(msg_cant_add_current_to_offline));
}
else {
itemguest *clone;
char *hostp;
clone = FindNick(pattern);
if (clone) {
/*
* The specified pattern was a nick found in the channel.
* Get and use the pattern from the specified user.
*/
hostp = clone->ident->userdomain;
if (IsPrefix(hostp))
hostp++;
StrCopyMax(pattern, sizeof(pattern), hostp);
}
if ('-' == pattern[0]) {
hostp = g->ident->userdomain;
if (IsPrefix(hostp))
/* remove prefix from prefixed patterns */
hostp++;
StrCopyMax(pattern, sizeof(pattern), hostp);
}
if (NULL == StrIndex(pattern, '@')) {
Sendf(errfrom, GetText(msg_illegal_pattern), pattern);
return;
}
AddDomain(u, pattern);
changed = TRUE;
/*
* If the pattern matches guest's userdomain we will inform
* the guest, otherwise not
*/
if (g && (g->ident->user != u)) {
hostp = g->ident->host;
if (IsPrefix(hostp))
hostp++;
if (StrIndex(pattern, '!')) {
StrFormatMax(buffer, sizeof(buffer), "%s!%s", g->ident->nick, hostp);
hostp = buffer;
}
if (!Match(hostp, pattern))
g = NULL;
}
}
}
else if (g && (g->ident->user != u)) {
g = NULL;
}
if (level >= 0) {
if (u->level >= current->level) {
Send(errfrom, GetText(msg_cant_change_higher_user));
return;
}
if (level >= current->level)
level = current->level - 1;
if (level != u->level) {
StrFormatMax(buffer, sizeof(buffer), "%s!%s", current->nick, current->host);
if (u->stat_bywhom)
StrFree(u->stat_bywhom);
u->stat_bywhom = StrDuplicate(buffer);
u->stat_lastdone = (level > u->level) ? USER_RAISED : USER_LOWERED;
u->stat_lastchange = now;
u->level = level;
changed = TRUE;
}
else
Sendf(errfrom, GetText(msg_user_already_level), nick, level);
}
if (newnick[0]) {
/* new regged nick */
if (NULL == FindUserByNick(newnick)) {
StrFree(u->nick);
u->nick = StrDuplicate(newnick);
changed = TRUE;
}
else
Sendf(errfrom, GetText(msg_nick_in_use), newnick);
}
if (password[0]) {
/* new password */
if (u->passwd)
StrFree(u->passwd);
u->passwd = MakePassword(password);
u->passwdtime = now;
changed = TRUE;
}
if (comment[0]) {
/* this is the new comment */
if (u->comment)
StrFree(u->comment);
if (StrEqual(comment, "NONE"))
u->comment = NULL;
else
u->comment = StrDuplicate(comment);
changed = TRUE;
}
if (email[0]) {
/* this is the new realname/email */
StrFree(u->realname);
u->realname = StrDuplicate(email);
changed = TRUE;
}
if (delpattern[0]) {
bool patmatch = FALSE;
int n;
itemlist *t;
for (n = 1, t = First(u->domainhead); t; t = Next(t), n++) {
if ((n == patnum) || StrEqual(t->pointer, delpattern)) {
patmatch = TRUE;
changed = TRUE;
DeleteEntry(u->domainhead, t, FreeList);
break;
}
}
if (!patmatch)
Sendf(errfrom, GetText(msg_nick_no_pattern), delpattern, nick);
}
if (banprot>=0 || autoop>=0 || linkbot >=0 || regularbot >=0 ||
stealth>=0) {
changed = TRUE;
if (banprot>=0)
u->flags.banprotect = banprot ? TRUE : FALSE;
if (autoop>=0)
u->flags.autoop = autoop ? TRUE : FALSE;
if (linkbot>=0)
u->flags.linkbot = linkbot ? TRUE : FALSE;
if (regularbot>=0)
u->flags.regularbot = regularbot ? TRUE : FALSE;
if (stealth>=0)
u->flags.stealth = stealth ? TRUE : FALSE;
}
if (changed) {
u->modified = now;
UserSave();
UserReload(userfile);
if (g && !quiet) {
/* inform the user if not done quietly */
if (g->ident != current)
/* just don't inform ourselves, it looks silly */
SendNickf(g->ident->nick, GetDefaultText(msg_modified_inform),
current->nick);
}
Sendf(from, GetText(msg_user_modified),
nick, (g && !quiet && g->ident!=current) ?
GetText(msg_and_informed) : "!");
}
else
Send(from, GetText(msg_no_change_done));
}
/* --- CmdClient -------------------------------------------- */
void CmdClient(char *from, char *line)
{
snapshot;
if (!chat)
Outgoing(from, OUT_CHAT, NULL);
else
Send(errfrom, GetText(msg_already_client));
}
/* --- CmdChat ---------------------------------------------- */
void CmdChat(char *from, char *line)
{
char buf[BIGBUFFER];
snapshot;
if (chat && current->client) {
current->client->flags ^= CHATCAST;
if ( current->client->flags & CHATCAST ) {
Sendf(from, GetText(msg_chat_mode_on),
cmdchar, cmdchar, ccmdchar);
Multicastf(CHATCAST, GetText(msg_joined_chat), current->nick);
} else {
Send(buf, GetText(msg_chat_mode_off));
Multicastf(CHATCAST, GetText(msg_left_chat), current->nick);
}
} else
Send(errfrom, GetText(msg_use_chat));
}
/* --- CmdLink ---------------------------------------------- */
void CmdLink(char *from, char *line)
{
char *to;
snapshot;
to = NextWord(line);
if (NULL == to)
to = from;
if (!IRCEqual(to, nickname))
Outgoing(to, OUT_LINK, NULL);
else
Send(errfrom, "Cannot link to myself");
}
char *NameBot(int bottype)
{
snapshot;
switch (bottype) {
case IBCP_BOT_DANCER:
return "Dancer";
default:
return UNKNOWN;
}
}
void CmdLinklist(char *from, char *line)
{
itemlink *r;
itemmsg *m;
int msgs;
snapshot;
for (r = First(linkHead); r; r = Next(r)) {
/* Count messages in queue */
for (m = First(&r->RemoteHead), msgs = 0; m; m = Next(m), msgs++);
/* Show info */
Sendf(from, "%s (%s) at %s port %04d. %d msg in queue. Last used %s ago",
r->name, NameBot(r->bottype),
MakeIP(r->addr.sin_addr.s_addr), r->addr.sin_port,
msgs, TimeAgo(r->lasttime));
Sendf(from, " rtt: %f srtt: %f dev: %f",
(double)r->rtt_rtt, (double)r->rtt_srtt, (double)r->rtt_rttdev);
}
}
void CmdRemote(char *from, char *line)
{
itemlink *r;
char name[MINIBUFFER];
char buf[BIGBUFFER];
snapshot;
if (2 == StrScan(line, "%"MINIBUFFERTXT"s %"SEMIBUFFERTXT"[^\n]", name, buf)) {
if (r = FindLinkByNick(name))
SendLink(r, IBCP_REMOTE_CMD, "%s %s", from ? from : current->nick, buf);
}
}
/* ---- CmdEmail -------------------------------------------------- */
void CmdEmail(char *from, char *line)
{
char nick[MIDBUFFER];
itemguest *g = NULL;
itemuser *u = NULL;
itemclient *c = NULL;
snapshot;
if (1 == StrScan(line, "%"MIDBUFFERTXT"s", nick)) {
if (!(g = FindNick(nick)) &&
!(g = FindSplitNick(nick)) &&
!(u = FindUserByNick(nick)) &&
!(c = FindClientByNick(nick))) {
/* Not joined, split, DCC-only or registered nick */
Send(errfrom, GetText(msg_unknown_user));
}
else {
if (g)
u = g->ident->user;
else if (c)
u = c->ident->user;
if (u)
Sendf(from, GetText(msg_email_address), nick, u->realname);
else
Send(errfrom, GetText(msg_no_information));
}
}
else if (current->user) {
Sendf(from, GetText(msg_email_address), current->nick,
current->user->realname);
}
else
CmdSyntax(errfrom, "EMAIL");
}
/* ---- CmdSetEmail ------------------------------------------ */
void CmdSetEmail(char *from, char *line)
{
char nick[NICKLEN+1] = "";
char email[MIDBUFFER] = "";
itemguest *g;
itemuser *u = current->user;
snapshot;
if (GetOption(line)) {
switch(toupper(option.copt)) {
case 'N': /* nick */
if (current->level >= LEVELEXPERT) {
StrScan(option.newpos, "%"NICKLENTXT"s", nick);
line = option.newpos + StrLength(nick);
g = FindNick(nick);
if (g)
u = g->ident->user;
else
u = FindUserByNick(nick);
if (NULL == u) {
Sendf(errfrom, GetText(msg_no_registered_user), nick);
return;
}
}
else {
Send(errfrom, GetText(msg_need_higher_level));
return;
}
break;
}
while (iswhite(*line))
line++;
}
if (line && (1 == StrScan(line, "%"MIDBUFFERTXT"[^\n]", email))) {
if (u) {
if (u->realname)
StrFree(u->realname);
if (StrEqual(email, "NONE"))
StrFormatMax(email, sizeof(email), "(%s)", GetDefaultText(msg_unknown));
u->realname = StrDuplicate(email);
u->modified = now;
UserSave();
Sendf(from, GetText(msg_email_set), u->nick, u->realname);
}
else
Send(errfrom, GetText(msg_youre_not_registered));
}
else
CmdSyntax(errfrom, "SETEMAIL");
}
/* --- Server ----------------------------------------------------- */
void CmdServerAdd(char *from, char *line)
{
char who[BIGBUFFER];
char server[BIGBUFFER];
char passwd[MIDBUFFER] = "";
int port = IRCPORT;
snapshot;
if (1<= StrScan(line, "%"SEMIBUFFERTXT"s %d %"MIDBUFFERTXT"s",
server, &port, passwd)) {
StrFormatMax(who, sizeof(who), "%s!%s", current->nick, current->host);
if (!ManAddServ(server, port, passwd[0]?passwd:NULL, who, 0)) {
Sendf(from, GetText(msg_serveradd_added), server);
SaveServ();
}
else
Sendf(errfrom, GetText(msg_serveradd_already_added), server);
}
else
CmdSyntax(errfrom, "SERVERADD");
}
void CmdServerList(char *from, char *line)
{
snapshot;
ListServ(from, line);
}
void CmdServerDel(char *from, char *line)
{
snapshot;
if (ManDelServ(from, line))
CmdSyntax(errfrom, "SERVERDEL");
}
void CmdServerStat(char *from, char *line)
{
char server[MIDBUFFER] = "";
long port = IRCPORT;
int flags = 0;
snapshot;
while (GetOption(line)) {
switch(toupper(option.copt)) {
case 'D':
flags |= SERV_DISABLED;
break;
case 'E':
flags |= SERV_ENABLED;
break;
}
line = option.newpos;
}
StrScan(line, "%"MIDBUFFERTXT"s %d", server, &port);
StatServ(from, flags, server, port);
}
void CmdUsed(char *from, char *line)
{
char nick[NICKLEN+1];
snapshot;
if (1 == StrScan(line, "%"NICKLENTXT"s", nick))
NickReport(from, nick);
else
NickReport(from, current->nick);
}
void CmdNewsAdd(char *from, char *line)
{
extern long newsexpire;
char match[MIDBUFFER] = "*";
char news[BIGBUFFER] = "";
char author[BIGBUFFER];
long flags = 0;
long level = 0;
long expire = newsexpire;
itemnews *n;
snapshot;
while (GetOption(line)) {
switch (toupper(option.copt)) {
case 'U': /* urgent */
flags |= NEWS_URGENT;
break;
case 'P': /* pattern */
StrScan(option.newpos, "%"MIDBUFFERTXT"s", match);
line = option.newpos + StrLength(match);
continue;
case 'E': /* expire */
expire = StrToLong(option.newpos, &line, 10);
continue;
}
line = option.newpos;
}
if (2 > StrScan(line, "%d %"SEMIBUFFERTXT"[^\n]", &level, news)) {
level = 0;
if (1 > StrScan(line, "%"SEMIBUFFERTXT"[^\n]", news)) {
CmdSyntax(errfrom, "NEWSADD");
return;
}
}
StrFormatMax(author, sizeof(author), "%s!%s", current->nick, current->host);
n = NewsAddItem(author, level, NewsID(), now, flags, expire, match, news);
if (n) {
Sendf(from, GetText(msg_news_added), n->id);
NewsSave(); /* Save it since it succeeded */
}
else
Send(errfrom, GetText(msg_failed_to_send_news));
}
void CmdNewsDel(char *from, char *line)
{
long id;
snapshot;
id = StrToLong(line, NULL, 10);
if (id) {
if(NewsDelete(id, 0))
Sendf(errfrom, GetText(msg_could_not_delete_news), id);
else {
Sendf(from, GetText(msg_news_removed), id);
NewsSave();
}
}
else
CmdSyntax(errfrom, "NEWSDEL");
}
void CmdNewsList(char *from, char *line)
{
long lines;
snapshot;
lines = StrToLong(line, NULL, 10);
if (0 == lines)
lines = 5;
NewsList(from, lines);
}
#ifdef CONFMODE
/************************* CONF MODE COMMANDS *****************************/
void CmdConf(char *from, char *line)
{
snapshot;
if (!Conf(from, line))
CmdSyntax(errfrom, "CONF");
}
void CmdConfA(char *from, char *line)
{
snapshot;
}
#endif
#ifdef BAGDER
void CmdFileGet(char *from, char *line)
{
char getwhat[SEMIBUFFER];
snapshot;
if (1 == StrScan(line, "%"SEMIBUFFERTXT"s", getwhat))
Outgoing(from, OUT_SEND, getwhat);
else
CmdSyntax(errfrom, "FILEGET");
}
#endif
/* --- CmdBotop --------------------------------------------------- */
#ifdef NICKSERV
void CmdBotop(char *from, char *line)
{
extern char nickpasswd[];
snapshot;
WriteServer("NICKSERV identify %s", nickpasswd);
WriteServer("CHANSERV op %s %s", channel, nickname);
}
#endif
#ifdef FUNCS_HACK
/* --- CmdFuncAdd ------------------------------------------------- */
void CmdFuncAdd(char *from, char *line)
{
snapshot;
FuncAdd(from, line);
}
/* --- CmdFuncDel ------------------------------------------------- */
void CmdFuncDel(char *from, char *line)
{
snapshot;
FuncDel(from, line);
}
/* --- CmdFuncList ------------------------------------------------ */
void CmdFuncList(char *from, char *line)
{
snapshot;
FuncList(from, line);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1