2011-02-23 22:14:30 -05:00
|
|
|
/* X-Chat
|
|
|
|
* Copyright (C) 1998 Peter Zelezny.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-12-23 14:36:54 -05:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2011-02-23 22:14:30 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define _GNU_SOURCE /* for memrchr */
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#define WANTSOCKET
|
|
|
|
#define WANTARPA
|
|
|
|
#include "inet.h"
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <sys/wait.h>
|
2011-12-11 11:34:02 -05:00
|
|
|
#include <unistd.h>
|
2011-02-23 22:14:30 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2012-10-24 15:33:02 -04:00
|
|
|
#include "hexchat.h"
|
2011-02-23 22:14:30 -05:00
|
|
|
#include "plugin.h"
|
|
|
|
#include "ignore.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "fe.h"
|
2012-10-30 06:35:39 -04:00
|
|
|
#include "cfgfiles.h" /* hexchat_fopen_file() */
|
2011-02-23 22:14:30 -05:00
|
|
|
#include "network.h" /* net_ip() */
|
|
|
|
#include "modes.h"
|
|
|
|
#include "notify.h"
|
|
|
|
#include "inbound.h"
|
|
|
|
#include "text.h"
|
2012-10-24 15:33:02 -04:00
|
|
|
#include "hexchatc.h"
|
2011-02-23 22:14:30 -05:00
|
|
|
#include "servlist.h"
|
|
|
|
#include "server.h"
|
|
|
|
#include "tree.h"
|
|
|
|
#include "outbound.h"
|
2012-07-21 08:26:19 -04:00
|
|
|
#include "chanopt.h"
|
2011-02-23 22:14:30 -05:00
|
|
|
|
|
|
|
#define TBUFSIZE 4096
|
|
|
|
|
|
|
|
static void help (session *sess, char *tbuf, char *helpcmd, int quiet);
|
|
|
|
static int cmd_server (session *sess, char *tbuf, char *word[], char *word_eol[]);
|
|
|
|
static void handle_say (session *sess, char *text, int check_spch);
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
notj_msg (struct session *sess)
|
|
|
|
{
|
|
|
|
PrintText (sess, _("No channel joined. Try /join #<channel>\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
notc_msg (struct session *sess)
|
|
|
|
{
|
|
|
|
PrintText (sess, _("Not connected. Try /server <host> [<port>]\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
random_line (char *file_name)
|
|
|
|
{
|
|
|
|
FILE *fh;
|
|
|
|
char buf[512];
|
|
|
|
int lines, ran;
|
|
|
|
|
|
|
|
if (!file_name[0])
|
|
|
|
goto nofile;
|
|
|
|
|
2012-10-30 06:35:39 -04:00
|
|
|
fh = hexchat_fopen_file (file_name, "r", 0);
|
2011-02-23 22:14:30 -05:00
|
|
|
if (!fh)
|
|
|
|
{
|
|
|
|
nofile:
|
|
|
|
/* reason is not a file, an actual reason! */
|
2014-12-28 06:37:25 -05:00
|
|
|
return g_strdup (file_name);
|
2011-02-23 22:14:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* count number of lines in file */
|
|
|
|
lines = 0;
|
|
|
|
while (fgets (buf, sizeof (buf), fh))
|
|
|
|
lines++;
|
|
|
|
|
|
|
|
if (lines < 1)
|
|
|
|
goto nofile;
|
|
|
|
|
|
|
|
/* go down a random number */
|
|
|
|
rewind (fh);
|
|
|
|
ran = RAND_INT (lines);
|
|
|
|
do
|
|
|
|
{
|
|
|
|
fgets (buf, sizeof (buf), fh);
|
|
|
|
lines--;
|
|
|
|
}
|
|
|
|
while (lines > ran);
|
|
|
|
fclose (fh);
|
2014-12-28 06:37:25 -05:00
|
|
|
return g_strdup (buf);
|
2011-02-23 22:14:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
server_sendpart (server * serv, char *channel, char *reason)
|
|
|
|
{
|
|
|
|
if (!reason)
|
|
|
|
{
|
2012-10-22 08:50:36 -04:00
|
|
|
reason = random_line (prefs.hex_irc_part_reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
serv->p_part (serv, channel, reason);
|
2014-12-28 06:37:25 -05:00
|
|
|
g_free (reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
} else
|
|
|
|
{
|
|
|
|
/* reason set by /quit, /close argument */
|
|
|
|
serv->p_part (serv, channel, reason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
server_sendquit (session * sess)
|
|
|
|
{
|
|
|
|
char *rea, *colrea;
|
|
|
|
|
|
|
|
if (!sess->quitreason)
|
|
|
|
{
|
2014-12-28 06:37:25 -05:00
|
|
|
colrea = g_strdup (prefs.hex_irc_quit_reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
check_special_chars (colrea, FALSE);
|
|
|
|
rea = random_line (colrea);
|
2014-12-28 06:37:25 -05:00
|
|
|
g_free (colrea);
|
2011-02-23 22:14:30 -05:00
|
|
|
sess->server->p_quit (sess->server, rea);
|
2014-12-28 06:37:25 -05:00
|
|
|
g_free (rea);
|
2011-02-23 22:14:30 -05:00
|
|
|
} else
|
|
|
|
{
|
|
|
|
/* reason set by /quit, /close argument */
|
|
|
|
sess->server->p_quit (sess->server, sess->quitreason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
process_data_init (char *buf, char *cmd, char *word[],
|
|
|
|
char *word_eol[], gboolean handle_quotes,
|
|
|
|
gboolean allow_escape_quotes)
|
|
|
|
{
|
|
|
|
int wordcount = 2;
|
|
|
|
int space = FALSE;
|
|
|
|
int quote = FALSE;
|
|
|
|
int j = 0;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
word[0] = "\000\000";
|
|
|
|
word_eol[0] = "\000\000";
|
|
|
|
word[1] = (char *)buf;
|
|
|
|
word_eol[1] = (char *)cmd;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
switch (*cmd)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
buf[j] = 0;
|
|
|
|
for (j = wordcount; j < PDIWORDS; j++)
|
|
|
|
{
|
|
|
|
word[j] = "\000\000";
|
|
|
|
word_eol[j] = "\000\000";
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
case '\042':
|
|
|
|
if (!handle_quotes)
|
|
|
|
goto def;
|
|
|
|
/* two quotes turn into 1 */
|
|
|
|
if (allow_escape_quotes && cmd[1] == '\042')
|
|
|
|
{
|
|
|
|
cmd++;
|
|
|
|
goto def;
|
|
|
|
}
|
|
|
|
if (quote)
|
|
|
|
{
|
|
|
|
quote = FALSE;
|
|
|
|
space = FALSE;
|
|
|
|
} else
|
|
|
|
quote = TRUE;
|
|
|
|
cmd++;
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
if (!quote)
|
|
|
|
{
|
|
|
|
if (!space)
|
|
|
|
{
|
|
|
|
buf[j] = 0;
|
|
|
|
j++;
|
|
|
|
|
|
|
|
if (wordcount < PDIWORDS)
|
|
|
|
{
|
|
|
|
word[wordcount] = &buf[j];
|
|
|
|
word_eol[wordcount] = cmd + 1;
|
|
|
|
wordcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
space = TRUE;
|
|
|
|
}
|
|
|
|
cmd++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
def:
|
|
|
|
space = FALSE;
|
|
|
|
len = g_utf8_skip[((unsigned char *)cmd)[0]];
|
|
|
|
if (len == 1)
|
|
|
|
{
|
|
|
|
buf[j] = *cmd;
|
|
|
|
j++;
|
|
|
|
cmd++;
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
/* skip past a multi-byte utf8 char */
|
|
|
|
memcpy (buf + j, cmd, len);
|
|
|
|
j += len;
|
|
|
|
cmd += len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_addbutton (struct session *sess, char *tbuf, char *word[],
|
|
|
|
char *word_eol[])
|
|
|
|
{
|
|
|
|
if (*word[2] && *word_eol[3])
|
|
|
|
{
|
|
|
|
if (sess->type == SESS_DIALOG)
|
|
|
|
{
|
|
|
|
list_addentry (&dlgbutton_list, word_eol[3], word[2]);
|
|
|
|
fe_dlgbuttons_update (sess);
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
list_addentry (&button_list, word_eol[3], word[2]);
|
|
|
|
fe_buttons_update (sess);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-10-13 00:03:14 -04:00
|
|
|
/* ADDSERVER <networkname> <serveraddress>, add a new network and server to the network list */
|
|
|
|
static int
|
|
|
|
cmd_addserver (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
ircnet *network;
|
|
|
|
|
|
|
|
/* do we have enough arguments given? */
|
|
|
|
if (*word[2] && *word_eol[3])
|
|
|
|
{
|
|
|
|
network = servlist_net_find (word[2], NULL, strcmp);
|
|
|
|
|
|
|
|
/* if the given network doesn't exist yet, add it */
|
|
|
|
if (!network)
|
|
|
|
{
|
|
|
|
network = servlist_net_add (word[2], "", TRUE);
|
2014-12-28 06:37:25 -05:00
|
|
|
network->encoding = g_strdup (IRC_DEFAULT_CHARSET);
|
2012-10-13 00:03:14 -04:00
|
|
|
}
|
|
|
|
/* if we had the network already, check if the given server already exists */
|
|
|
|
else if (servlist_server_find (network, word_eol[3], NULL))
|
|
|
|
{
|
|
|
|
PrintTextf (sess, _("Server %s already exists on network %s.\n"), word_eol[3], word[2]);
|
|
|
|
return TRUE; /* unsuccessful, but the syntax was correct so we don't want to show the help */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* server added to new or existing network, doesn't make any difference */
|
|
|
|
servlist_server_add (network, word_eol[3]);
|
|
|
|
PrintTextf (sess, _("Added server %s to network %s.\n"), word_eol[3], word[2]);
|
|
|
|
return TRUE; /* success */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE; /* print help */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-23 22:14:30 -05:00
|
|
|
static int
|
|
|
|
cmd_allchannels (session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
GSList *list = sess_list;
|
|
|
|
|
|
|
|
if (!*word_eol[2])
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
sess = list->data;
|
|
|
|
if (sess->type == SESS_CHANNEL && sess->channel[0] && sess->server->connected)
|
|
|
|
{
|
|
|
|
handle_command (sess, word_eol[2], FALSE);
|
|
|
|
}
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_allchannelslocal (session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
GSList *list = sess_list;
|
|
|
|
server *serv = sess->server;
|
|
|
|
|
|
|
|
if (!*word_eol[2])
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
sess = list->data;
|
|
|
|
if (sess->type == SESS_CHANNEL && sess->channel[0] &&
|
|
|
|
sess->server->connected && sess->server == serv)
|
|
|
|
{
|
|
|
|
handle_command (sess, word_eol[2], FALSE);
|
|
|
|
}
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_allservers (struct session *sess, char *tbuf, char *word[],
|
|
|
|
char *word_eol[])
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
server *serv;
|
|
|
|
|
|
|
|
if (!*word_eol[2])
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
list = serv_list;
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
serv = list->data;
|
|
|
|
if (serv->connected)
|
|
|
|
handle_command (serv->front_session, word_eol[2], FALSE);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
char *reason = word_eol[2];
|
|
|
|
|
|
|
|
if (!(*reason))
|
|
|
|
{
|
|
|
|
if (sess->server->is_away)
|
|
|
|
{
|
|
|
|
if (sess->server->last_away_reason)
|
|
|
|
PrintTextf (sess, _("Already marked away: %s\n"), sess->server->last_away_reason);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sess->server->reconnect_away)
|
|
|
|
reason = sess->server->last_away_reason;
|
|
|
|
else
|
|
|
|
/* must manage memory pointed to by random_line() */
|
2012-10-22 03:53:28 -04:00
|
|
|
reason = random_line (prefs.hex_away_reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
}
|
|
|
|
sess->server->p_set_away (sess->server, reason);
|
|
|
|
|
|
|
|
if (sess->server->last_away_reason != reason)
|
|
|
|
{
|
2014-12-28 06:37:25 -05:00
|
|
|
g_free (sess->server->last_away_reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
|
|
|
|
if (reason == word_eol[2])
|
2014-12-28 06:37:25 -05:00
|
|
|
sess->server->last_away_reason = g_strdup (reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
else
|
|
|
|
sess->server->last_away_reason = reason;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sess->server->connected)
|
|
|
|
sess->server->reconnect_away = 1;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_back (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
if (sess->server->is_away)
|
|
|
|
{
|
|
|
|
sess->server->p_set_back (sess->server);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PrintText (sess, _("Already marked back.\n"));
|
|
|
|
}
|
|
|
|
|
2014-12-28 06:37:25 -05:00
|
|
|
g_free (sess->server->last_away_reason);
|
2011-02-23 22:14:30 -05:00
|
|
|
sess->server->last_away_reason = NULL;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-06-07 08:24:13 -04:00
|
|
|
static char *
|
|
|
|
create_mask (session * sess, char *mask, char *mode, char *typestr, int deop)
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
2013-06-07 08:24:13 -04:00
|
|
|
int type;
|
2011-02-23 22:14:30 -05:00
|
|
|
struct User *user;
|
|
|
|
char *at, *dot, *lastdot;
|
2013-06-07 22:01:36 -04:00
|
|
|
char username[64], fullhost[128], domain[128], buf[512], *p2;
|
2011-02-23 22:14:30 -05:00
|
|
|
|
|
|
|
user = userlist_find (sess, mask);
|
|
|
|
if (user && user->hostname) /* it's a nickname, let's find a proper ban mask */
|
|
|
|
{
|
|
|
|
if (deop)
|
|
|
|
p2 = user->nick;
|
2013-06-07 08:24:13 -04:00
|
|
|
else
|
2011-02-23 22:14:30 -05:00
|
|
|
p2 = "";
|
|
|
|
|
|
|
|
mask = user->hostname;
|
|
|
|
|
|
|
|
at = strchr (mask, '@'); /* FIXME: utf8 */
|
|
|
|
if (!at)
|
2013-06-07 08:24:13 -04:00
|
|
|
return NULL; /* can't happen? */
|
2011-02-23 22:14:30 -05:00
|
|
|
*at = 0;
|
|
|
|
|
|
|
|
if (mask[0] == '~' || mask[0] == '+' ||
|
|
|
|
mask[0] == '=' || mask[0] == '^' || mask[0] == '-')
|
|
|
|
{
|
|
|
|
/* the ident is prefixed with something, we replace that sign with an * */
|
|
|
|
safe_strcpy (username+1, mask+1, sizeof (username)-1);
|
|
|
|
username[0] = '*';
|
|
|
|
} else if (at - mask < USERNAMELEN)
|
|
|
|
{
|
|
|
|
/* we just add an * in the begining of the ident */
|
|
|
|
safe_strcpy (username+1, mask, sizeof (username)-1);
|
|
|
|
username[0] = '*';
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
/* ident might be too long, we just ban what it gives and add an * in the end */
|
|
|
|
safe_strcpy (username, mask, sizeof (username));
|
|
|
|
}
|
|
|
|
*at = '@';
|
|
|
|
safe_strcpy (fullhost, at + 1, sizeof (fullhost));
|
|
|
|
|
|
|
|
dot = strchr (fullhost, '.');
|
|
|
|
if (dot)
|
|
|
|
{
|
|
|
|
safe_strcpy (domain, dot, sizeof (domain));
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
safe_strcpy (domain, fullhost, sizeof (domain));
|
|
|
|
}
|
|
|
|
|
2013-06-07 08:24:13 -04:00
|
|
|
if (*typestr)
|
|
|
|
type = atoi (typestr);
|
2011-02-23 22:14:30 -05:00
|
|
|
else
|
2013-06-07 08:24:13 -04:00
|
|
|
type = prefs.hex_irc_ban_type;
|
2011-02-23 22:14:30 -05:00
|
|
|
|
2013-06-07 22:01:36 -04:00
|
|
|
buf[0] = 0;
|
2011-02-23 22:14:30 -05:00
|
|
|
if (inet_addr (fullhost) != -1) /* "fullhost" is really a IP number */
|
|
|
|
{
|
|
|
|
lastdot = strrchr (fullhost, '.');
|
|
|
|
if (!lastdot)
|
2013-06-07 08:24:13 -04:00
|
|
|
return NULL; /* can't happen? */
|
2011-02-23 22:14:30 -05:00
|
|
|
|
|
|
|
*lastdot = 0;
|
|
|
|
strcpy (domain, fullhost);
|
|
|
|
*lastdot = '.';
|
|
|
|
|
2013-06-07 08:24:13 -04:00
|
|
|
switch (type)
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
case 0:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!*@%s.*", mode, p2, domain);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s.*", mode, p2, username, domain);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
{
|
2013-06-07 08:24:13 -04:00
|
|
|
switch (type)
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
case 0:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!*@*%s", mode, p2, domain);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!%s@*%s", mode, p2, username, domain);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
|
2011-02-23 22:14:30 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else
|
|
|
|
{
|
2014-12-17 18:49:59 -05:00
|
|
|
g_snprintf (buf, sizeof (buf), "%s %s", mode, mask);
|
2013-06-07 08:24:13 -04:00
|
|
|
}
|
|
|
|
|
2013-06-07 22:01:36 -04:00
|
|
|
return g_strdup (buf);
|
2013-06-07 08:24:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ban (session * sess, char *tbuf, char *mask, char *bantypestr, int deop)
|
|
|
|
{
|
|
|
|
char *banmask = create_mask (sess, mask, deop ? "-o+b" : "+b", bantypestr, deop);
|
|
|
|
server *serv = sess->server;
|
|
|
|
|
|
|
|
if (banmask)
|
|
|
|
{
|
|
|
|
serv->p_mode (serv, sess->channel, banmask);
|
|
|
|
g_free (banmask);
|
2011-02-23 22:14:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_ban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
char *mask = word[2];
|
|
|
|
|
|
|
|
if (*mask)
|
|
|
|
{
|
|
|
|
ban (sess, tbuf, mask, word[3], 0);
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
sess->server->p_mode (sess->server, sess->channel, "+b"); /* banlist */
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_unban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
/* Allow more than one mask in /unban -- tvk */
|
|
|
|
int i = 2;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (!*word[i])
|
|
|
|
{
|
|
|
|
if (i == 2)
|
|
|
|
return FALSE;
|
|
|
|
send_channel_modes (sess, tbuf, word, 2, i, '-', 'b', 0);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_chanopt (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
2013-06-06 19:16:50 -04:00
|
|
|
int ret;
|
|
|
|
|
2011-02-23 22:14:30 -05:00
|
|
|
/* chanopt.c */
|
2013-06-06 19:16:50 -04:00
|
|
|
ret = chanopt_command (sess, tbuf, word, word_eol);
|
|
|
|
chanopt_save_all ();
|
|
|
|
|
|
|
|
return ret;
|
2011-02-23 22:14:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
server *serv = sess->server;
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
if (strcmp (word[2], "-quiet") == 0)
|
|
|
|
offset++;
|
|
|
|
|
|
|
|
if (!word[2 + offset][0])
|
|
|
|
{
|
2015-01-18 05:55:32 -05:00
|
|
|
PrintTextf (sess, "Current charset: %s\n", serv->encoding);
|
2011-02-23 22:14:30 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (servlist_check_encoding (word[2 + offset]))
|
|
|
|
{
|
|
|
|
server_set_encoding (serv, word[2 + offset]);
|
|
|
|
if (offset < 1)
|
|
|
|
PrintTextf (sess, "Charset changed to: %s\n", word[2 + offset]);
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
PrintTextf (sess, "\0034Unknown charset:\017 %s\n", word[2 + offset]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_clear (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
GSList *list = sess_list;
|
|
|
|
char *reason = word_eol[2];
|
|
|
|
|
2012-06-16 07:01:47 -04:00
|
|
|
if (g_ascii_strcasecmp (reason, "HISTORY") == 0)
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
history_free (&sess->history);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-06-16 07:01:47 -04:00
|
|
|
if (g_ascii_strncasecmp (reason, "all", 3) == 0)
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
sess = list->data;
|
|
|
|
if (!sess->nick_said)
|
|
|
|
fe_text_clear (list->data, 0);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reason[0] != '-' && !isdigit (reason[0]) && reason[0] != 0)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
fe_text_clear (sess, atoi (reason));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_close (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
if (strcmp (word[2], "-m") == 0)
|
|
|
|
{
|
|
|
|
list = sess_list;
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
sess = list->data;
|
|
|
|
list = list->next;
|
|
|
|
if (sess->type == SESS_DIALOG)
|
|
|
|
fe_close_window (sess);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
if (*word_eol[2])
|
|
|
|
sess->quitreason = word_eol[2];
|
|
|
|
fe_close_window (sess);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_ctcp (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
int mbl;
|
|
|
|
char *to = word[2];
|
|
|
|
if (*to)
|
|
|
|
{
|
|
|
|
char *msg = word_eol[3];
|
|
|
|
if (*msg)
|
|
|
|
{
|
|
|
|
unsigned char *cmd = (unsigned char *)msg;
|
|
|
|
|
|
|
|
/* make the first word upper case (as per RFC) */
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (*cmd == ' ' || *cmd == 0)
|
|
|
|
break;
|
|
|
|
mbl = g_utf8_skip[*cmd];
|
|
|
|
if (mbl == 1)
|
|
|
|
*cmd = toupper (*cmd);
|
|
|
|
cmd += mbl;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess->server->p_ctcp (sess->server, to, msg);
|
|
|
|
|
|
|
|
EMIT_SIGNAL (XP_TE_CTCPSEND, sess, to, msg, NULL, NULL, 0);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_country (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
char *code = word[2];
|
|
|
|
if (*code)
|
|
|
|
{
|
|
|
|
/* search? */
|
|
|
|
if (strcmp (code, "-s") == 0)
|
|
|
|
{
|
|
|
|
country_search (word[3], sess, (void *)PrintTextf);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* search, but forgot the -s */
|
|
|
|
if (strchr (code, '*'))
|
|
|
|
{
|
|
|
|
country_search (code, sess, (void *)PrintTextf);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf (tbuf, "%s = %s\n", code, country (code));
|
|
|
|
PrintText (sess, tbuf);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_cycle (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
2013-09-23 17:17:35 -04:00
|
|
|
char *key = NULL;
|
2011-02-23 22:14:30 -05:00
|
|
|
char *chan = word[2];
|
2013-09-23 17:17:35 -04:00
|
|
|
session *chan_sess;
|
|
|
|
|
2011-02-23 22:14:30 -05:00
|
|
|
if (!*chan)
|
|
|
|
chan = sess->channel;
|
2013-09-23 17:17:35 -04:00
|
|
|
|
|
|
|
if (chan)
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
2013-09-23 17:17:35 -04:00
|
|
|
chan_sess = find_channel (sess->server, chan);
|
|
|
|
|
|
|
|
if (chan_sess && chan_sess->type == SESS_CHANNEL)
|
|
|
|
{
|
|
|
|
key = chan_sess->channelkey;
|
|
|
|
sess->server->p_cycle (sess->server, chan, key);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2011-02-23 22:14:30 -05:00
|
|
|
}
|
2013-09-23 17:17:35 -04:00
|
|
|
|
2011-02-23 22:14:30 -05:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_dcc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
int goodtype;
|
|
|
|
struct DCC *dcc = 0;
|
|
|
|
char *type = word[2];
|
|
|
|
if (*type)
|
|
|
|
{
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (type, "HELP"))
|
2011-02-23 22:14:30 -05:00
|
|
|
return FALSE;
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (type, "CLOSE"))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
if (*word[3] && *word[4])
|
|
|
|
{
|
|
|
|
goodtype = 0;
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (word[3], "SEND"))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
dcc = find_dcc (word[4], word[5], TYPE_SEND);
|
|
|
|
dcc_abort (sess, dcc);
|
|
|
|
goodtype = TRUE;
|
|
|
|
}
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (word[3], "GET"))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
dcc = find_dcc (word[4], word[5], TYPE_RECV);
|
|
|
|
dcc_abort (sess, dcc);
|
|
|
|
goodtype = TRUE;
|
|
|
|
}
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (word[3], "CHAT"))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
dcc = find_dcc (word[4], "", TYPE_CHATRECV);
|
|
|
|
if (!dcc)
|
|
|
|
dcc = find_dcc (word[4], "", TYPE_CHATSEND);
|
|
|
|
dcc_abort (sess, dcc);
|
|
|
|
goodtype = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!goodtype)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!dcc)
|
|
|
|
EMIT_SIGNAL (XP_TE_NODCC, sess, NULL, NULL, NULL, NULL, 0);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-06-16 07:01:47 -04:00
|
|
|
if ((!g_ascii_strcasecmp (type, "CHAT")) || (!g_ascii_strcasecmp (type, "PCHAT")))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
char *nick = word[3];
|
2012-06-16 07:01:47 -04:00
|
|
|
int passive = (!g_ascii_strcasecmp(type, "PCHAT")) ? 1 : 0;
|
2011-02-23 22:14:30 -05:00
|
|
|
if (*nick)
|
|
|
|
dcc_chat (sess, nick, passive);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (type, "LIST"))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
dcc_show_list (sess);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strcasecmp (type, "GET"))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
char *nick = word[3];
|
|
|
|
char *file = word[4];
|
|
|
|
if (!*file)
|
|
|
|
{
|
|
|
|
if (*nick)
|
|
|
|
dcc_get_nick (sess, nick);
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
dcc = find_dcc (nick, file, TYPE_RECV);
|
|
|
|
if (dcc)
|
|
|
|
dcc_get (dcc);
|
|
|
|
else
|
|
|
|
EMIT_SIGNAL (XP_TE_NODCC, sess, NULL, NULL, NULL, NULL, 0);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-06-16 07:01:47 -04:00
|
|
|
if ((!g_ascii_strcasecmp (type, "SEND")) || (!g_ascii_strcasecmp (type, "PSEND")))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
int i = 3, maxcps;
|
|
|
|
char *nick, *file;
|
2012-06-16 07:01:47 -04:00
|
|
|
int passive = (!g_ascii_strcasecmp(type, "PSEND")) ? 1 : 0;
|
2011-02-23 22:14:30 -05:00
|
|
|
|
|
|
|
nick = word[i];
|
|
|
|
if (!*nick)
|
|
|
|
return FALSE;
|
|
|
|
|
2012-10-22 06:10:55 -04:00
|
|
|
maxcps = prefs.hex_dcc_max_send_cps;
|
2012-06-16 07:01:47 -04:00
|
|
|
if (!g_ascii_strncasecmp(nick, "-maxcps=", 8))
|
2011-02-23 22:14:30 -05:00
|
|
|
{
|
|
|
|
maxcps = atoi(nick + 8);
|
|
|
|
i++;
|
|
|
|
nick = word[i];
|
|
|
|
if (!*nick)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
file = word[i];
|
|
|
|
if (!*file)
|
|
|
|
{
|
|
|
|
fe_dcc_send_filereq (sess, nick, maxcps, passive);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dcc_send (sess, nick, file, maxcps, passive);
|
|
|
|
i++;
|
|
|
|
file = word[i];
|
|
|
|
}
|
|
|
|
while (*file);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dcc_show_list (sess);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
struct session *s;
|
|
|
|
struct server *v;
|
|
|
|
GSList *list = sess_list;
|
|
|
|
|
|
|
|
PrintText (sess, "Session T Channel WaitChan WillChan Server\n");
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
s = (struct session *) list->data;
|
|
|
|
sprintf (tbuf, "%p %1x %-10.10s %-10.10s %-10.10s %p\n",
|
|
|
|
s, s->type, s->channel, s->waitchannel,
|
|
|
|
s->willjoinchannel, s->server);
|
|
|
|
PrintText (sess, tbuf);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = serv_list;
|
|
|
|
PrintText (sess, "Server Sock Name\n");
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
v = (struct server *) list->data;
|
|
|
|
sprintf (tbuf, "%p %-5d %s\n",
|
|
|
|
v, v->sok, v->servername);
|
|
|
|
PrintText (sess, tbuf);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf (tbuf,
|
|
|
|
"\nfront_session: %p\n"
|
|
|
|
"current_tab: %p\n\n",
|
|
|
|
sess->server->front_session, current_tab);
|
|
|
|
PrintText (sess, tbuf);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_delbutton (struct session *sess, char *tbuf, char *word[],
|
|
|
|
char *word_eol[])
|
|
|
|
{
|
|
|
|
if (*word[2])
|
|
|
|
{
|
|
|
|
if (sess->type == SESS_DIALOG)
|
|
|
|
{
|
|
|
|
if (list_delentry (&dlgbutton_list, word[2]))
|
|
|
|
fe_dlgbuttons_update (sess);
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
if (list_delentry (&button_list, word[2]))
|
|
|
|
fe_buttons_update (sess);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_dehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
int i = 2;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (!*word[i])
|
|
|
|
{
|
|
|
|
if (i == 2)
|
|
|
|
return FALSE;
|
|
|
|
send_channel_modes (sess, tbuf, word, 2, i, '-', 'h', 0);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_deop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
|
|
|
int i = 2;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (!*word[i])
|
|
|
|
{
|
|
|
|
if (i == 2)
|
|
|
|
return FALSE;
|
|
|
|
send_channel_modes (sess, tbuf, word, 2, i, '-', 'o', 0);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char **nicks;
|
|
|
|
int i;
|
|
|
|
session *sess;
|
|
|
|
char *reason;
|
|
|
|
char *tbuf;
|
|
|
|
} multidata;
|
|
|
|
|
|
|
|
static int
|
|
|
|
mdehop_cb (struct User *user, multidata *data)
|
|
|
|
{
|
|
|
|
if (user->hop && !user->me)
|
|
|
|
{
|
|
|
|
data->nicks[data->i] = user->nick;
|
|
|
|
data->i++;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmd_mdehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
|
|
|
{
|
2014-12-28 06:37:25 -05:00
|
|
|
char **nicks = g_new0 (char *, sess->hops);
|
2011-02-23 22:14:30 -05:00
|
|
|
multidata data;
|
|
|
|
|
|
|
|
data.nicks = nicks;
|
|
|
|
data.i = 0;
|
|
|
|
|