.. lots of changes ..

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@197 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-05-04 10:32:42 +00:00 committed by cras
commit d3dc9a1307
106 changed files with 4864 additions and 1597 deletions

View file

@ -55,7 +55,7 @@ char *ban_get_mask(CHANNEL_REC *channel, const char *nick)
host = strchr(++user, '@');
if (host == NULL) return str;
if ((int) (host-user) < 10) {
if ((int) (host-user) > 10) {
/* too long user mask */
user[9] = '*';
g_memmove(user+10, host, strlen(host)+1);
@ -112,7 +112,7 @@ void ban_set_type(const char *type)
void ban_set(CHANNEL_REC *channel, const char *bans)
{
GString *str;
char **ban, **banlist;
char **ban, **banlist, *realban;
g_return_if_fail(bans != NULL);
@ -121,19 +121,20 @@ void ban_set(CHANNEL_REC *channel, const char *bans)
for (ban = banlist; *ban != NULL; ban++) {
if (strchr(*ban, '!') != NULL) {
/* explicit ban */
g_string_sprintfa(str, " %s", *ban);
g_string_sprintfa(str, "%s ", *ban);
continue;
}
/* ban nick */
*ban = ban_get_mask(channel, *ban);
if (*ban != NULL) {
g_string_sprintfa(str, " %s", *ban);
g_free(*ban);
realban = ban_get_mask(channel, *ban);
if (realban != NULL) {
g_string_sprintfa(str, "%s ", realban);
g_free(realban);
}
}
g_strfreev(banlist);
g_string_truncate(str, str->len-1);
channel_set_singlemode(channel->server, channel->name, str->str, "+b");
g_string_free(str, TRUE);
}
@ -169,7 +170,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC
if (server == NULL || !server->connected || !irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
params = cmd_get_params(data, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
item, &channel, &nicks);
if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED);
if (*nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);

View file

@ -95,6 +95,27 @@ static void event_topic(const char *data, IRC_SERVER_REC *server)
g_free(params);
}
/* Find any unjoined channel that matches `channel'. Long channel names are
also a bit problematic, so find a channel where start of the name matches. */
static CHANNEL_REC *channel_find_unjoined(IRC_SERVER_REC *server, const char *channel)
{
GSList *tmp;
int len;
len = strlen(channel);
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *rec = tmp->data;
if (rec->joined) continue;
if (g_strncasecmp(channel, rec->name, len) == 0 &&
(len > 20 || rec->name[len] == '\0'))
return rec;
}
return NULL;
}
static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address)
{
char *params, *channel, *tmp;
@ -120,10 +141,8 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic
!channel here to !ABCDEchannel */
char *shortchan;
shortchan = g_strdup(channel);
sprintf(shortchan, "!%s", channel+6);
chanrec = channel_find(server, shortchan);
shortchan = g_strdup_printf("!%s", channel+6);
chanrec = channel_find_unjoined(server, shortchan);
if (chanrec != NULL) {
g_free(chanrec->name);
chanrec->name = g_strdup(channel);
@ -132,11 +151,16 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic
g_free(shortchan);
}
chanrec = channel_find(server, channel);
chanrec = channel_find_unjoined(server, channel);
if (chanrec == NULL) {
/* didn't get here with /join command.. */
chanrec = channel_create(server, channel, TRUE);
}
chanrec->joined = TRUE;
if (strcmp(chanrec->name, channel) != 0) {
g_free(chanrec->name);
chanrec->name = g_strdup(channel);
}
g_free(params);
}

View file

@ -232,7 +232,7 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
for (tmp = chans; tmp != NULL; tmp = tmp->next) {
chanrec = tmp->data;
server_redirect_event((SERVER_REC *) server, chanrec->name, 4,
server_redirect_event((SERVER_REC *) server, chanrec->name, 2,
"event 403", "chanquery mode abort", 1,
"event 349", "chanquery eban end", 1,
"event 348", "chanquery eban", 1, NULL);
@ -244,7 +244,7 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
for (tmp = chans; tmp != NULL; tmp = tmp->next) {
chanrec = tmp->data;
server_redirect_event((SERVER_REC *) server, chanrec->name, 4,
server_redirect_event((SERVER_REC *) server, chanrec->name, 2,
"event 403", "chanquery mode abort", 1,
"event 347", "chanquery ilist end", 1,
"event 346", "chanquery ilist", 1, NULL);

View file

@ -26,6 +26,7 @@
#include "nicklist.h"
#include "irc-server.h"
#include "server-setup.h"
#include "special-vars.h"
#include "lib-config/iconfig.h"
#include "settings.h"
@ -33,30 +34,52 @@
GSList *setupchannels;
#define ircnet_match(a, b) \
((a[0]) == '\0' || (b != NULL && g_strcasecmp(a, b) == 0))
((a) == NULL || (a[0]) == '\0' || (b != NULL && g_strcasecmp(a, b) == 0))
SETUP_CHANNEL_REC *channels_setup_find(const char *channel, IRC_SERVER_REC *server)
static void channel_config_add(SETUP_CHANNEL_REC *channel)
{
GSList *tmp;
CONFIG_NODE *node;
g_return_val_if_fail(channel != NULL, NULL);
g_return_val_if_fail(server != NULL, NULL);
node = iconfig_node_traverse("(channels", TRUE);
node = config_node_section(node, NULL, NODE_TYPE_BLOCK);
for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
SETUP_CHANNEL_REC *rec = tmp->data;
config_node_set_str(node, "name", channel->name);
config_node_set_str(node, "ircnet", channel->ircnet);
if (channel->autojoin)
config_node_set_bool(node, "autojoin", TRUE);
config_node_set_str(node, "password", channel->password);
config_node_set_str(node, "botmasks", channel->botmasks);
config_node_set_str(node, "autosendcmd", channel->autosendcmd);
config_node_set_str(node, "background", channel->background);
config_node_set_str(node, "font", channel->font);
}
if (g_strcasecmp(rec->name, channel) == 0 &&
ircnet_match(rec->ircnet, server->connrec->ircnet))
return rec;
static void channel_config_remove(SETUP_CHANNEL_REC *channel)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("channels", FALSE);
if (node != NULL) config_node_list_remove(node, g_slist_index(setupchannels, channel));
}
void channels_setup_create(SETUP_CHANNEL_REC *channel)
{
if (g_slist_find(setupchannels, channel) != NULL) {
channel_config_remove(channel);
setupchannels = g_slist_remove(setupchannels, channel);
}
setupchannels = g_slist_append(setupchannels, channel);
return NULL;
channel_config_add(channel);
}
void channels_setup_destroy(SETUP_CHANNEL_REC *channel)
{
g_return_if_fail(channel != NULL);
channel_config_remove(channel);
setupchannels = g_slist_remove(setupchannels, channel);
g_free(channel->name);
g_free(channel->ircnet);
g_free_not_null(channel->password);
@ -65,16 +88,30 @@ void channels_setup_destroy(SETUP_CHANNEL_REC *channel)
g_free_not_null(channel->background);
g_free_not_null(channel->font);
g_free(channel);
}
setupchannels = g_slist_remove(setupchannels, channel);
SETUP_CHANNEL_REC *channels_setup_find(const char *channel, const char *ircnet)
{
GSList *tmp;
g_return_val_if_fail(channel != NULL, NULL);
for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
SETUP_CHANNEL_REC *rec = tmp->data;
if (g_strcasecmp(rec->name, channel) == 0 &&
ircnet_match(rec->ircnet, ircnet))
return rec;
}
return NULL;
}
/* connected to server, autojoin to channels. */
static void event_connected(IRC_SERVER_REC *server)
{
GString *chans, *keys;
GString *chans;
GSList *tmp;
int use_keys;
g_return_if_fail(server != NULL);
@ -83,9 +120,6 @@ static void event_connected(IRC_SERVER_REC *server)
/* join to the channels marked with autojoin in setup */
chans = g_string_new(NULL);
keys = g_string_new(NULL);
use_keys = FALSE;
for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
SETUP_CHANNEL_REC *rec = tmp->data;
@ -93,21 +127,14 @@ static void event_connected(IRC_SERVER_REC *server)
continue;
g_string_sprintfa(chans, "%s,", rec->name);
g_string_sprintfa(keys, "%s,", rec->password == NULL ? "x" : rec->password);
if (rec->password != NULL)
use_keys = TRUE;
}
if (chans->len > 0) {
g_string_truncate(chans, chans->len-1);
g_string_truncate(keys, keys->len-1);
if (use_keys) g_string_sprintfa(chans, " %s", keys->str);
channels_join(server, chans->str, TRUE);
}
g_string_free(chans, TRUE);
g_string_free(keys, TRUE);
}
/* channel wholist received: send the auto send command */
@ -115,17 +142,17 @@ static void channel_wholist(CHANNEL_REC *channel)
{
SETUP_CHANNEL_REC *rec;
NICK_REC *nick;
char **bots, **bot, *str;
char **bots, **bot;
g_return_if_fail(channel != NULL);
rec = channels_setup_find(channel->name, channel->server);
rec = channels_setup_find(channel->name, channel->server->connrec->ircnet);
if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd)
return;
if (rec->botmasks == NULL || !*rec->botmasks) {
/* just send the command. */
signal_emit("send command", 3, rec->autosendcmd, channel->server, channel);
eval_special_string(rec->autosendcmd, "", channel->server, channel);
}
/* find first available bot.. */
@ -136,9 +163,7 @@ static void channel_wholist(CHANNEL_REC *channel)
continue;
/* got one! */
str = g_strdup_printf(rec->autosendcmd, nick->nick);
signal_emit("send command", 3, str, channel->server, channel);
g_free(str);
eval_special_string(rec->autosendcmd, nick->nick, channel->server, channel);
break;
}
g_strfreev(bots);

View file

@ -20,8 +20,9 @@ extern GSList *setupchannels;
void channels_setup_init(void);
void channels_setup_deinit(void);
void channels_setup_create(SETUP_CHANNEL_REC *channel);
void channels_setup_destroy(SETUP_CHANNEL_REC *channel);
SETUP_CHANNEL_REC *channels_setup_find(const char *channel, IRC_SERVER_REC *server);
SETUP_CHANNEL_REC *channels_setup_find(const char *channel, const char *ircnet);
#endif

View file

@ -156,10 +156,12 @@ char *channel_get_mode(CHANNEL_REC *channel)
void channels_join(IRC_SERVER_REC *server, const char *data, int automatic)
{
SETUP_CHANNEL_REC *schannel;
CHANNEL_REC *chanrec;
GString *outchans, *outkeys;
char *params, *channels, *keys;
char **chanlist, **keylist, **tmp, **tmpkey, *channel;
int use_keys;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected || !irc_server_check(server))
@ -174,19 +176,24 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic)
outchans = g_string_new(NULL);
outkeys = g_string_new(NULL);
use_keys = *keys != '\0';
tmpkey = keylist;
for (tmp = chanlist; *tmp != NULL; tmp++) {
channel = ischannel(**tmp) ? g_strdup(*tmp) :
g_strdup_printf("#%s", *tmp);
chanrec = channel_find(server, channel);
if (chanrec != NULL) {
/* already joined this channel */
signal_emit("gui channel open", 1, chanrec);
} else {
if (chanrec == NULL) {
schannel = channels_setup_find(channel, server->connrec->ircnet);
g_string_sprintfa(outchans, "%s,", channel);
if (*keys != '\0')
if (schannel == NULL || schannel->password == NULL)
g_string_sprintfa(outkeys, "%s,", get_join_key(*tmpkey));
else {
/* get password from setup record */
use_keys = TRUE;
g_string_sprintfa(outkeys, "%s,", schannel->password);
}
channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic);
}
@ -197,7 +204,7 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic)
}
if (outchans->len > 0) {
irc_send_cmdv(server, *keys == '\0' ? "JOIN %s" : "JOIN %s %s",
irc_send_cmdv(server, use_keys ? "JOIN %s %s" : "JOIN %s",
outchans->str, outkeys->str);
}

View file

@ -41,6 +41,7 @@ typedef struct {
int wholist:1; /* WHO list got */
int synced:1; /* Channel synced - all queries done */
int joined:1; /* Have we even received JOIN event for this channel? */
int left:1; /* You just left the channel */
int kicked:1; /* You just got kicked */
int destroying:1;

View file

@ -52,7 +52,7 @@ void ctcp_send_reply(IRC_SERVER_REC *server, const char *data)
if (g_slist_length(server->ctcpqueue) < settings_get_int("max_ctcp_queue")) {
/* Add to first in idle queue */
tag = server_idle_add_first(server, data, NULL, 0, NULL);
tag = server_idle_add(server, data, NULL, 0, NULL);
server->ctcpqueue = g_slist_append(server->ctcpqueue, GINT_TO_POINTER(tag));
}
}

View file

@ -251,6 +251,7 @@ static void read_ignores(void)
IGNORE_REC *rec;
CONFIG_NODE *node;
GSList *tmp;
char *str;
while (ignores != NULL)
ignore_destroy(ignores->data);
@ -269,8 +270,8 @@ static void read_ignores(void)
rec->mask = g_strdup(config_node_get_str(node, "mask", NULL));
rec->pattern = g_strdup(config_node_get_str(node, "pattern", NULL));
rec->level = level2bits(config_node_get_str(node, "level", 0));
rec->except_level = level2bits(config_node_get_str(node, "except_level", 0));
rec->level = level2bits(config_node_get_str(node, "level", ""));
rec->except_level = level2bits(config_node_get_str(node, "except_level", ""));
rec->regexp = config_node_get_bool(node, "regexp", FALSE);
rec->fullword = config_node_get_bool(node, "fullword", FALSE);

View file

@ -19,6 +19,7 @@
*/
#include "module.h"
#include "network.h"
#include "commands.h"
#include "misc.h"
#include "special-vars.h"
@ -46,23 +47,35 @@ static IRC_SERVER_REC *connect_server(const char *data)
{
IRC_SERVER_CONNECT_REC *conn;
IRC_SERVER_REC *server;
char *params, *addr, *portstr, *password, *nick;
int port;
char *params, *args, *ircnet, *host, *addr, *portstr, *password, *nick;
g_return_val_if_fail(data != NULL, NULL);
params = cmd_get_params(data, 4, &addr, &portstr, &password, &nick);
args = "ircnet host";
params = cmd_get_params(data, 7 | PARAM_FLAG_MULTIARGS,
&args, &ircnet, &host, &addr,
&portstr, &password, &nick);
if (*addr == '+') addr++;
if (*addr == '\0') return NULL;
if (strcmp(password, "-") == 0)
*password = '\0';
port = 6667;
if (*portstr != '\0')
sscanf(portstr, "%d", &port);
/* connect to server */
conn = irc_server_create_conn(addr, port, password, nick);
conn = irc_server_create_conn(addr, atoi(portstr), password, nick);
if (*ircnet != '\0') {
g_free_not_null(conn->ircnet);
conn->ircnet = g_strdup(ircnet);
}
if (*host != '\0') {
IPADDR ip;
if (net_gethostname(host, &ip) == 0) {
if (conn->own_ip == NULL)
conn->own_ip = g_new(IPADDR, 1);
memcpy(conn->own_ip, &ip, sizeof(IPADDR));
}
}
server = irc_server_connect(conn);
g_free(params);
@ -92,6 +105,9 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server)
if (server == NULL || !irc_server_check(server))
cmd_param_error(CMDERR_NOT_CONNECTED);
if (*msg == '\0') msg = (char *) settings_get_str("quit_message");
signal_emit("server quit", 2, server, msg);
ircserver = (IRC_SERVER_REC *) server;
if (ircserver->handle != -1 && ircserver->buffer != NULL) {
/* flush transmit queue */
@ -100,8 +116,6 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server)
ircserver->cmdqueue = NULL;
ircserver->cmdcount = 0;
/* then send quit message */
if (*msg == '\0') msg = (char *) settings_get_str("default_quit_message");
irc_send_cmdv(ircserver, "QUIT :%s", msg);
}
g_free(params);
@ -111,12 +125,20 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server)
static void cmd_server(const char *data, IRC_SERVER_REC *server)
{
char *params, *args, *ircnetarg, *hostarg, *addr;
char *channels, *away_reason, *usermode, *ircnet;
int no_old_server;
g_return_if_fail(data != NULL);
if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*data == '+' || server == NULL) {
args = "ircnet host";
params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS,
&args, &ircnetarg, &hostarg, &addr);
if (*addr == '\0' || strcmp(addr, "+") == 0)
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
no_old_server = server == NULL;
if (*addr == '+' || server == NULL) {
channels = away_reason = usermode = ircnet = NULL;
} else {
ircnet = g_strdup(server->connrec->ircnet);
@ -129,20 +151,21 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server)
cmd_disconnect("* Changing server", server);
}
server = connect_server(data + (*data == '+' ? 1 : 0));
if (*data == '+' || server == NULL ||
server = connect_server(data);
if (*addr == '+' || server == NULL ||
(ircnet != NULL && server->connrec->ircnet != NULL &&
g_strcasecmp(ircnet, server->connrec->ircnet) != 0)) {
g_free_not_null(channels);
g_free_not_null(usermode);
g_free_not_null(away_reason);
} else if (server != NULL) {
} else if (server != NULL && !no_old_server) {
server->connrec->reconnection = TRUE;
server->connrec->channels = channels;
server->connrec->usermode = usermode;
server->connrec->away_reason = away_reason;
}
g_free_not_null(ircnet);
g_free(params);
}
static void cmd_quit(const char *data)
@ -154,7 +177,7 @@ static void cmd_quit(const char *data)
g_return_if_fail(data != NULL);
quitmsg = *data != '\0' ? data :
settings_get_str("default_quit_message");
settings_get_str("quit_message");
/* disconnect from every server */
for (tmp = servers; tmp != NULL; tmp = next) {
@ -646,7 +669,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i
if (is_numeric(data, ' ')) {
/* first argument is the timeout */
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason);
timeleft = atol(timeoutstr);
timeleft = atoi(timeoutstr);
} else {
timeleft = 0;
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &reason);
@ -749,7 +772,7 @@ void irc_commands_init(void)
{
tmpstr = g_string_new(NULL);
settings_add_str("misc", "default_quit_message", "leaving");
settings_add_str("misc", "quit_message", "leaving");
settings_add_int("misc", "knockout_time", 300);
knockout_tag = g_timeout_add(KNOCKOUT_TIMECHECK, (GSourceFunc) knockout_timeout, NULL);

View file

@ -90,8 +90,8 @@ static void event_unaway(const char *data, IRC_SERVER_REC *server)
void irc_log_init(void)
{
settings_add_str("misc", "awaylog_file", "~/.irssi/away.log");
settings_add_str("misc", "awaylog_level", "msgs hilight");
settings_add_str("log", "awaylog_file", "~/.irssi/away.log");
settings_add_str("log", "awaylog_level", "msgs hilight");
signal_add("print text stripped", (SIGNAL_FUNC) sig_log);
signal_add("event 306", (SIGNAL_FUNC) event_away);

View file

@ -335,7 +335,7 @@ static int sig_set_user_mode(IRC_SERVER_REC *server)
if (g_slist_find(servers, server) == NULL)
return 0; /* got disconnected */
mode = settings_get_str("default_user_mode");
mode = settings_get_str("usermode");
newmode = server->usermode == NULL ? NULL :
modes_join(server->usermode, mode);
if (server->usermode == NULL || strcmp(newmode, server->usermode) != 0)
@ -369,7 +369,7 @@ static void event_connected(const char *data, IRC_SERVER_REC *server, const char
if (!server->connrec->reconnection) {
/* wait a second and then send the user mode */
mode = settings_get_str("default_user_mode");
mode = settings_get_str("usermode");
if (*mode != '\0')
g_timeout_add(1000, (GSourceFunc) sig_set_user_mode, server);
}
@ -414,7 +414,7 @@ static void event_empty(void)
void irc_servers_init(void)
{
settings_add_str("misc", "default_user_mode", DEFAULT_USER_MODE);
settings_add_str("misc", "usermode", DEFAULT_USER_MODE);
settings_add_int("flood", "cmd_queue_speed", DEFAULT_CMD_QUEUE_SPEED);
settings_add_int("flood", "cmds_max_at_once", DEFAULT_CMDS_MAX_AT_ONCE);

View file

@ -120,6 +120,7 @@ typedef struct {
GSList *lastmsgs; /* List of nicks who last send you msg */
GHashTable *splits; /* For keeping track of netsplits */
GSList *split_servers; /* Servers that are currently in split */
time_t lag_sent; /* 0 or time when last lag query was sent to server */
time_t lag_last_check; /* last time we checked lag */

View file

@ -48,6 +48,7 @@ static void cmd_send(IRC_SERVER_REC *server, const char *cmd, int send_now, int
/* just check that we don't send any longer commands than 512 bytes.. */
strncpy(str, cmd, 510);
len = strlen(cmd);
if (len > 510) len = 510;
str[len++] = 13; str[len++] = 10; str[len] = '\0';
ptr = str;

View file

@ -104,6 +104,7 @@ static void read_ircnets(void)
void ircnets_setup_init(void)
{
read_ircnets();
signal_add("setup reread", (SIGNAL_FUNC) read_ircnets);
}

View file

@ -20,7 +20,7 @@
#include "module.h"
#include "signals.h"
#include "common-setup.h"
#include "settings.h"
#include "channels.h"
#include "irc.h"
@ -28,6 +28,7 @@
#include "irc-server.h"
static int massjoin_tag;
static int massjoin_max_joins;
/* Massjoin support - really useful when trying to do things (like op/deop)
to people after netjoins. It sends
@ -210,7 +211,7 @@ static void server_check_massjoins(IRC_SERVER_REC *server, time_t max)
continue;
if (rec->massjoin_start < max || /* We've waited long enough */
rec->massjoins-5 < rec->last_massjoins) { /* Less than 5 joins since last check */
rec->massjoins-massjoin_max_joins < rec->last_massjoins) { /* Less than x joins since last check */
/* send them */
massjoin_send(rec);
} else {
@ -226,21 +227,30 @@ static int sig_massjoin_timeout(void)
GSList *tmp;
time_t max;
max = time(NULL)-MAX_MASSJOIN_WAIT;
max = time(NULL)-settings_get_int("massjoin_max_wait");
for (tmp = servers; tmp != NULL; tmp = tmp->next)
server_check_massjoins(tmp->data, max);
return 1;
}
static void read_settings(void)
{
massjoin_max_joins = settings_get_int("massjoin_max_joins");
}
void massjoin_init(void)
{
settings_add_int("misc", "massjoin_max_wait", 5000);
settings_add_int("misc", "massjoin_max_joins", 3);
massjoin_tag = g_timeout_add(1000, (GSourceFunc) sig_massjoin_timeout, NULL);
read_settings();
signal_add("event join", (SIGNAL_FUNC) event_join);
signal_add("event part", (SIGNAL_FUNC) event_part);
signal_add("event kick", (SIGNAL_FUNC) event_kick);
signal_add("event quit", (SIGNAL_FUNC) event_quit);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
void massjoin_deinit(void)
@ -251,4 +261,5 @@ void massjoin_deinit(void)
signal_remove("event part", (SIGNAL_FUNC) event_part);
signal_remove("event kick", (SIGNAL_FUNC) event_kick);
signal_remove("event quit", (SIGNAL_FUNC) event_quit);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}

View file

@ -103,7 +103,7 @@ void parse_channel_modes(CHANNEL_REC *channel, const char *setby, const char *mo
ptr = cmd_get_param(&modestr);
if (*ptr == '\0') break;
if (strcmp(channel->server->nick, ptr) == 0)
if (g_strcasecmp(channel->server->nick, ptr) == 0)
channel->chanop = type == '+' ? TRUE : FALSE;
nick_mode_change(channel, ptr, '@', type == '+');
break;
@ -297,6 +297,9 @@ void channel_set_singlemode(IRC_SERVER_REC *server, const char *channel, const c
nicklist = g_strsplit(nicks, " ", -1);
for (nick = nicklist; *nick != NULL; nick++) {
if (*nick == '\0')
continue;
if (num == 0)
{
g_string_sprintf(str, "MODE %s %s", channel, mode);
@ -373,28 +376,94 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel, const char *m
g_free(orig);
}
static void cmd_op(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
static char *get_nicks(WI_IRC_REC *item, const char *data, int op, int voice)
{
if (!irc_item_channel(item)) return;
channel_set_singlemode(server, item->name, data, "+o");
GString *str;
GSList *nicks, *tmp;
char **matches, **match, *ret;
str = g_string_new(NULL);
matches = g_strsplit(data, " ", -1);
for (match = matches; *match != NULL; match++) {
if (strchr(*match, '*') == NULL && strchr(*match, '?') == NULL) {
/* no wildcards */
g_string_sprintfa(str, "%s ", *match);
continue;
}
/* wildcards */
nicks = nicklist_find_multiple((CHANNEL_REC *) item, data);
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
NICK_REC *rec = tmp->data;
if ((op == 1 && !rec->op) || (op == 0 && rec->op) ||
(voice == 1 && !rec->voice) || (voice == 0 && rec->voice))
continue;
if (g_strcasecmp(rec->nick, item->server->nick) == 0)
continue;
g_string_sprintfa(str, "%s ", rec->nick);
}
g_slist_free(nicks);
}
g_string_truncate(str, str->len-1);
ret = str->str;
g_string_free(str, FALSE);
return ret;
}
static void cmd_op(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
char *nicks;
if (!irc_item_channel(item))
return;
nicks = get_nicks(item, data, 0, -1);
if (*nicks != '\0')
channel_set_singlemode(server, item->name, nicks, "+o");
g_free(nicks);
}
static void cmd_deop(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
if (!irc_item_channel(item)) return;
channel_set_singlemode(server, item->name, data, "-o");
char *nicks;
if (!irc_item_channel(item))
return;
nicks = get_nicks(item, data, 1, -1);
if (*nicks != '\0')
channel_set_singlemode(server, item->name, nicks, "-o");
g_free(nicks);
}
static void cmd_voice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
if (!irc_item_channel(item)) return;
channel_set_singlemode(server, item->name, data, "+v");
char *nicks;
if (!irc_item_channel(item))
return;
nicks = get_nicks(item, data, 0, 0);
if (*nicks != '\0')
channel_set_singlemode(server, item->name, nicks, "+v");
g_free(nicks);
}
static void cmd_devoice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
if (!irc_item_channel(item)) return;
channel_set_singlemode(server, item->name, data, "-v");
char *nicks;
if (!irc_item_channel(item))
return;
nicks = get_nicks(item, data, 0, 1);
if (*nicks != '\0')
channel_set_singlemode(server, item->name, nicks, "-v");
g_free(nicks);
}
static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)

View file

@ -29,6 +29,46 @@
static int split_tag;
static NETSPLIT_SERVER_REC *netsplit_server_find(IRC_SERVER_REC *server, const char *servername, const char *destserver)
{
GSList *tmp;
for (tmp = server->split_servers; tmp != NULL; tmp = tmp->next) {
NETSPLIT_SERVER_REC *rec = tmp->data;
if (g_strcasecmp(rec->server, servername) == 0 &&
g_strcasecmp(rec->destserver, destserver) == 0)
return rec;
}
return NULL;
}
static NETSPLIT_SERVER_REC *netsplit_server_create(IRC_SERVER_REC *server, const char *servername, const char *destserver)
{
NETSPLIT_SERVER_REC *rec;
rec = netsplit_server_find(server, servername, destserver);
if (rec != NULL) return rec;
rec = g_new0(NETSPLIT_SERVER_REC, 1);
rec->server = g_strdup(servername);
rec->destserver = g_strdup(destserver);
server->split_servers = g_slist_append(server->split_servers, rec);
signal_emit("netsplit new server", 1, rec);
return rec;
}
static void netsplit_destroy_server(IRC_SERVER_REC *server, NETSPLIT_SERVER_REC *rec)
{
server->split_servers = g_slist_remove(server->split_servers, rec);
g_free(rec->server);
g_free(rec->destserver);
g_free(rec);
}
static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, const char *address, const char *servers)
{
NETSPLIT_REC *rec;
@ -41,6 +81,7 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, cons
g_return_val_if_fail(nick != NULL, NULL);
g_return_val_if_fail(address != NULL, NULL);
/* get splitted servers */
dupservers = g_strdup(servers);
p = strchr(dupservers, ' ');
if (p == NULL) {
@ -54,9 +95,8 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, cons
rec->address = g_strdup(address);
rec->destroy = time(NULL)+NETSPLIT_MAX_REMEMBER;
/* get splitted servers */
rec->server = g_strdup(dupservers);
rec->destserver = g_strdup(p);
rec->server = netsplit_server_create(server, dupservers, p);
rec->server->count++;
g_free(dupservers);
/* copy the channel nick records.. */
@ -75,11 +115,12 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, cons
}
g_hash_table_insert(server->splits, rec->nick, rec);
signal_emit("netsplit add", 1, rec);
return rec;
}
static void netsplit_destroy(NETSPLIT_REC *rec)
static void netsplit_destroy(IRC_SERVER_REC *server, NETSPLIT_REC *rec)
{
GSList *tmp;
@ -93,16 +134,17 @@ static void netsplit_destroy(NETSPLIT_REC *rec)
g_free(rec);
}
g_free(rec->server);
g_free(rec->destserver);
if (--rec->server->count == 0)
netsplit_destroy_server(server, rec->server);
g_free(rec->nick);
g_free(rec->address);
g_free(rec);
}
static void netsplit_destroy_hash(gpointer key, NETSPLIT_REC *rec)
static void netsplit_destroy_hash(void *key, NETSPLIT_REC *rec, IRC_SERVER_REC *server)
{
netsplit_destroy(rec);
netsplit_destroy(server, rec);
}
NETSPLIT_REC *netsplit_find(IRC_SERVER_REC *server, const char *nick, const char *address)
@ -136,13 +178,15 @@ NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const
return NULL;
}
static int is_split(const char *msg)
int quitmsg_is_split(const char *msg)
{
char *params, *host1, *host2, *p;
int ok;
g_return_val_if_fail(msg != NULL, FALSE);
if (msg[strlen(msg)-1] == ' ') msg[strlen(msg)-1] = '\0'; /*FIXME: remove - for debugging!*/
/* must have only two words */
p = strchr(msg, ' ');
if (p == NULL || strchr(p+1, ' ') != NULL) return FALSE;
@ -171,19 +215,19 @@ static int is_split(const char *msg)
return ok;
}
static void split_set_timeout(gpointer key, NETSPLIT_REC *rec, NETSPLIT_REC *orig)
static void split_set_timeout(void *key, NETSPLIT_REC *rec, NETSPLIT_REC *orig)
{
if (rec == orig) {
/* original nick, destroy it in a few seconds.. */
rec->destroy = time(NULL)+4;
} else if (g_strcasecmp(rec->server, orig->server) == 0 &&
g_strcasecmp(rec->destserver, orig->destserver) == 0) {
} else if (g_strcasecmp(rec->server->server, orig->server->server) == 0 &&
g_strcasecmp(rec->server->destserver, orig->server->destserver) == 0) {
/* same servers -> split over -> destroy old records sooner.. */
rec->destroy = time(NULL)+60;
}
}
static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *address)
static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address)
{
NETSPLIT_REC *rec;
@ -202,7 +246,7 @@ static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *
} else {
/* back from different address.. just destroy it. */
g_hash_table_remove(server->splits, rec->nick);
netsplit_destroy(rec);
netsplit_destroy(server, rec);
}
}
@ -211,7 +255,7 @@ static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nic
g_return_if_fail(data != NULL);
if (*data == ':') data++;
if (g_strcasecmp(nick, server->nick) != 0 && is_split(data)) {
if (g_strcasecmp(nick, server->nick) != 0 && quitmsg_is_split(data)) {
/* netsplit! */
netsplit_add(server, nick, address, data);
}
@ -221,17 +265,17 @@ static void sig_disconnected(IRC_SERVER_REC *server)
{
g_return_if_fail(server != NULL);
g_hash_table_foreach(server->splits, (GHFunc) netsplit_destroy_hash, NULL);
g_hash_table_foreach(server->splits, (GHFunc) netsplit_destroy_hash, server);
g_hash_table_destroy(server->splits);
}
static int split_server_check(gpointer key, NETSPLIT_REC *rec, IRC_SERVER_REC *server)
static int split_server_check(void *key, NETSPLIT_REC *rec, IRC_SERVER_REC *server)
{
/* Check if this split record is too old.. */
if (rec->destroy > time(NULL))
return FALSE;
netsplit_destroy(rec);
netsplit_destroy(server, rec);
return TRUE;
}

View file

@ -4,10 +4,16 @@
#include "nicklist.h"
typedef struct {
char *nick;
char *address;
char *server;
char *destserver;
int count;
} NETSPLIT_SERVER_REC;
typedef struct {
NETSPLIT_SERVER_REC *server;
char *nick;
char *address;
GSList *channels;
time_t destroy;
@ -24,4 +30,6 @@ void netsplit_deinit(void);
NETSPLIT_REC *netsplit_find(IRC_SERVER_REC *server, const char *nick, const char *address);
NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const char *address, const char *channel);
int quitmsg_is_split(const char *msg);
#endif

View file

@ -87,6 +87,22 @@ static NICK_REC *nicklist_find_wildcards(CHANNEL_REC *channel, const char *mask)
return tmp == NULL ? NULL : nick;
}
GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask)
{
GSList *nicks, *tmp, *next;
nicks = nicklist_getnicks(channel);
for (tmp = nicks; tmp != NULL; tmp = next) {
NICK_REC *nick = tmp->data;
next = tmp->next;
if (!irc_mask_match_address(mask, nick->nick, nick->host == NULL ? "" : nick->host))
nicks = g_slist_remove(nicks, tmp->data);
}
return nicks;
}
/* Find nick record from list */
NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask)
{
@ -230,7 +246,7 @@ static void event_names_list(const char *data, IRC_SERVER_REC *server)
while (*names != '\0' && *names != ' ') names++;
if (*names != '\0') *names++ = '\0';
if (*ptr == '@' && strcmp(server->nick, ptr+1) == 0)
if (*ptr == '@' && g_strcasecmp(server->nick, ptr+1) == 0)
chanrec->chanop = TRUE;
nicklist_insert(chanrec, ptr+isnickflag(*ptr), *ptr == '@', *ptr == '+', FALSE);
@ -390,7 +406,8 @@ static void event_nick_in_use(const char *data, IRC_SERVER_REC *server)
}
/* nick already in use - need to change it .. */
if (strcmp(server->nick, server->connrec->nick) == 0) {
if (strcmp(server->nick, server->connrec->nick) == 0 &&
server->connrec->alternate_nick != NULL) {
/* first try, so try the alternative nick.. */
g_free(server->nick);
server->nick = g_strdup(server->connrec->alternate_nick);

View file

@ -25,6 +25,8 @@ NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, int op, int vo
void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick);
/* Find nick record from list */
NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask);
/* Get list of nicks that match the mask */
GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask);
/* Get list of nicks */
GSList *nicklist_getnicks(CHANNEL_REC *channel);
/* Get all the nick records of `nick'. Returns channel, nick, channel, ... */

View file

@ -85,7 +85,7 @@ static int server_reconnect_timeout(void)
static void sserver_connect(SETUP_SERVER_REC *rec, IRC_SERVER_CONNECT_REC *conn)
{
conn->address = g_strdup(rec->server);
conn->address = g_strdup(rec->address);
conn->port = rec->port;
conn->password = rec->password == NULL ? NULL :
g_strdup(rec->password);
@ -143,7 +143,6 @@ static void sig_reconnect(IRC_SERVER_REC *server)
return;
conn = g_new0(IRC_SERVER_CONNECT_REC, 1);
conn->reconnection = TRUE;
server_connect_copy_skeleton(conn, server->connrec);
/* save the server status */
@ -152,6 +151,7 @@ static void sig_reconnect(IRC_SERVER_REC *server)
conn->away_reason = g_strdup(server->connrec->away_reason);
conn->usermode = g_strdup(server->connrec->usermode);
} else {
conn->reconnection = TRUE;
conn->channels = irc_server_get_channels(server);
conn->away_reason = !server->usermode_away ? NULL :
g_strdup(server->away_reason);
@ -213,7 +213,7 @@ static void sig_reconnect(IRC_SERVER_REC *server)
for (tmp = setupservers; tmp != NULL; ) {
SETUP_SERVER_REC *rec = tmp->data;
if (!found && g_strcasecmp(rec->server, server->connrec->address) == 0 &&
if (!found && g_strcasecmp(rec->address, server->connrec->address) == 0 &&
server->connrec->port == rec->port)
found = TRUE;
else if (found && rec->ircnet != NULL && g_strcasecmp(conn->ircnet, rec->ircnet) == 0) {
@ -286,24 +286,36 @@ static RECONNECT_REC *reconnect_find_tag(int tag)
}
/* Try to reconnect immediately */
static void cmd_reconnect(const char *data)
static void cmd_reconnect(const char *data, IRC_SERVER_REC *server)
{
IRC_SERVER_CONNECT_REC *conn;
RECONNECT_REC *rec;
char *str;
int tag;
if (*data == '\0') {
/* reconnect back to same server */
if (server == NULL) cmd_return_error(CMDERR_NOT_CONNECTED);
str = g_strdup_printf("%s %d %s %s", server->connrec->address,
server->connrec->port, server->connrec->password,
server->connrec->nick);
signal_emit("command server", 2, str, server);
g_free(str);
return;
}
if (g_strncasecmp(data, "RECON-", 6) == 0)
data += 6;
rec = sscanf(data, "%d", &tag) == 1 && tag > 0 ?
reconnect_find_tag(tag) : NULL;
tag = atoi(data);
rec = tag <= 0 ? NULL : reconnect_find_tag(tag);
if (rec == NULL)
signal_emit("server reconnect not found", 1, data);
else {
conn = rec->conn;
server_reconnect_destroy(rec, FALSE);
irc_server_connect(rec->conn);
irc_server_connect(conn);
}
}

View file

@ -74,7 +74,7 @@ create_addr_conn(const char *address, int port, const char *password,
conn->realname = g_strdup(settings_get_str("real_name"));
/* proxy settings */
if (settings_get_bool("toggle_use_ircproxy")) {
if (settings_get_bool("use_ircproxy")) {
conn->proxy = g_strdup(settings_get_str("proxy_address"));
conn->proxy_port = settings_get_int("proxy_port");
conn->proxy_string = g_strdup(settings_get_str("proxy_string"));
@ -91,6 +91,25 @@ create_addr_conn(const char *address, int port, const char *password,
sserver = server_setup_find(address, -1);
if (sserver == NULL) return conn;
if (sserver->own_ip != NULL) {
/* use already resolved IP */
if (conn->own_ip == NULL)
conn->own_ip = g_new(IPADDR, 1);
memcpy(conn->own_ip, sserver->own_ip, sizeof(IPADDR));
} else if (sserver->own_host != NULL) {
/* resolve the IP and use it */
IPADDR ip;
if (net_gethostname(sserver->own_host, &ip) == 0) {
if (conn->own_ip == NULL)
conn->own_ip = g_new(IPADDR, 1);
memcpy(conn->own_ip, &ip, sizeof(IPADDR));
sserver->own_ip = g_new(IPADDR, 1);
memcpy(sserver->own_ip, &ip, sizeof(IPADDR));
}
}
sserver->last_connect = time(NULL);
if (sserver->ircnet) conn->ircnet = g_strdup(sserver->ircnet);
@ -151,7 +170,7 @@ irc_server_create_conn(const char *dest, int port, const char *password, const c
continue;
if (n == 1 || !rec->last_failed || rec->last_connect < now-FAILED_RECONNECT_WAIT)
return create_addr_conn(rec->server, port, password, nick);
return create_addr_conn(rec->address, port, password, nick);
}
}
@ -168,7 +187,7 @@ SETUP_SERVER_REC *server_setup_find(const char *address, int port)
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
SETUP_SERVER_REC *rec = tmp->data;
if (g_strcasecmp(rec->server, address) == 0 &&
if (g_strcasecmp(rec->address, address) == 0 &&
(port == -1 || rec->port == port)) return rec;
}
@ -223,19 +242,88 @@ static void init_userinfo(void)
iconfig_set_str("settings", "alternate_nick", str);
g_free(str);
}
/* host name */
set = settings_get_str("hostname");
if (set == NULL || *set == '\0') {
str = g_getenv("IRCHOST");
if (str != NULL) {
iconfig_set_str("settings", "hostname", str);
g_free(str);
}
}
}
static SETUP_SERVER_REC *setupserver_add(CONFIG_NODE *node)
void setupserver_config_add(SETUP_SERVER_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("(servers", TRUE);
node = config_node_section(node, NULL, NODE_TYPE_BLOCK);
config_node_set_str(node, "address", rec->address);
config_node_set_str(node, "ircnet", rec->ircnet);
config_node_set_int(node, "port", rec->port);
config_node_set_str(node, "password", rec->password);
config_node_set_str(node, "own_host", rec->own_host);
if (rec->autoconnect)
config_node_set_bool(node, "autoconnect", TRUE);
if (rec->max_cmds_at_once > 0)
config_node_set_int(node, "cmds_max_at_once", rec->max_cmds_at_once);
if (rec->cmd_queue_speed > 0)
config_node_set_int(node, "cmd_queue_speed", rec->cmd_queue_speed);
}
void setupserver_config_remove(SETUP_SERVER_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("servers", FALSE);
if (node != NULL) config_node_list_remove(node, g_slist_index(setupservers, rec));
}
static void setupserver_destroy(SETUP_SERVER_REC *rec)
{
setupservers = g_slist_remove(setupservers, rec);
g_free_not_null(rec->own_host);
g_free_not_null(rec->own_ip);
g_free(rec->ircnet);
g_free(rec->address);
g_free(rec->password);
g_free(rec);
}
void server_setup_add(SETUP_SERVER_REC *rec)
{
if (g_slist_find(setupservers, rec) != NULL) {
setupserver_config_remove(rec);
setupservers = g_slist_append(setupservers, rec);
}
setupservers = g_slist_append(setupservers, rec);
setupserver_config_add(rec);
}
void server_setup_remove(SETUP_SERVER_REC *rec)
{
setupserver_config_remove(rec);
setupserver_destroy(rec);
}
static SETUP_SERVER_REC *setupserver_add_node(CONFIG_NODE *node)
{
SETUP_SERVER_REC *rec;
char *ircnet, *server;
char *server;
int port;
g_return_val_if_fail(node != NULL, NULL);
ircnet = config_node_get_str(node, "ircnet", NULL);
server = config_node_get_str(node, "server", NULL);
if (ircnet == NULL || server == NULL) return NULL;
server = config_node_get_str(node, "address", NULL);
if (server == NULL) return NULL;
port = config_node_get_int(node, "port", 6667);
if (server_setup_find(server, port) != NULL) {
@ -245,28 +333,19 @@ static SETUP_SERVER_REC *setupserver_add(CONFIG_NODE *node)
}
rec = g_new0(SETUP_SERVER_REC, 1);
rec->ircnet = g_strdup(ircnet);
rec->server = g_strdup(server);
rec->password = g_strdup(config_node_get_str(node, "password", ""));
rec->ircnet = g_strdup(config_node_get_str(node, "ircnet", NULL));
rec->address = g_strdup(server);
rec->password = g_strdup(config_node_get_str(node, "password", NULL));
rec->port = port;
rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE);
rec->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0);
rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0);
rec->own_host = g_strdup(config_node_get_str(node, "own_host", 0));
setupservers = g_slist_append(setupservers, rec);
return rec;
}
static void setupserver_destroy(SETUP_SERVER_REC *rec)
{
setupservers = g_slist_remove(setupservers, rec);
g_free(rec->ircnet);
g_free(rec->server);
g_free(rec->password);
g_free(rec);
}
static void read_servers(void)
{
CONFIG_NODE *node;
@ -276,10 +355,10 @@ static void read_servers(void)
setupserver_destroy(setupservers->data);
/* Read servers */
node = iconfig_node_traverse("(setupservers", FALSE);
node = iconfig_node_traverse("servers", FALSE);
if (node != NULL) {
for (tmp = node->value; tmp != NULL; tmp = tmp->next)
setupserver_add(tmp->data);
setupserver_add_node(tmp->data);
}
}
@ -290,14 +369,14 @@ void servers_setup_init(void)
settings_add_int("server", "server_reconnect_time", 300);
settings_add_str("server", "hostname", "");
settings_add_bool("server", "toggle_skip_motd", FALSE);
settings_add_bool("server", "skip_motd", FALSE);
settings_add_str("server", "default_nick", NULL);
settings_add_str("server", "alternate_nick", NULL);
settings_add_str("server", "user_name", NULL);
settings_add_str("server", "real_name", NULL);
settings_add_bool("ircproxy", "toggle_use_ircproxy", FALSE);
settings_add_bool("ircproxy", "use_ircproxy", FALSE);
settings_add_str("ircproxy", "proxy_address", "");
settings_add_int("ircproxy", "proxy_port", 6667);
settings_add_str("ircproxy", "proxy_string", "CONNECT %s %d");

View file

@ -5,7 +5,7 @@
/* servers */
typedef struct {
char *server;
char *address;
int port;
char *ircnet;
@ -14,8 +14,8 @@ typedef struct {
int max_cmds_at_once; /* override the default if > 0 */
int cmd_queue_speed; /* override the default if > 0 */
char *own_address; /* address to use when connecting this server */
IPADDR *own_ip; /* resolved own_address or full of zeros */
char *own_host; /* address to use when connecting this server */
IPADDR *own_ip; /* resolved own_address if not NULL */
time_t last_connect; /* to avoid reconnecting too fast.. */
int last_failed; /* if last connection attempt failed */
@ -31,6 +31,9 @@ extern gboolean source_host_ok; /* Use source_host_ip .. */
IRC_SERVER_CONNECT_REC *
irc_server_create_conn(const char *dest, int port, const char *password, const char *nick);
void server_setup_add(SETUP_SERVER_REC *rec);
void server_setup_remove(SETUP_SERVER_REC *rec);
/* Find matching server from setup. Set port to -1 if you don't care about it */
SETUP_SERVER_REC *server_setup_find(const char *address, int port);

View file

@ -9,6 +9,4 @@ libirc_dcc_la_SOURCES = \
dcc-files.c
noinst_HEADERS = \
dcc.h \
dcc-chat.h \
dcc-files.h
dcc.h

View file

@ -307,7 +307,7 @@ static void cmd_dcc_chat(gchar *data, IRC_SERVER_REC *server)
if (server == NULL || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
if (!net_getsockname(server->handle, &addr, NULL))
if (net_getsockname(server->handle, &addr, NULL) == -1)
cmd_return_error(CMDERR_GETSOCKNAME);
port = settings_get_int("dcc_port");

View file

@ -1,7 +0,0 @@
#ifndef __DCC_CHAT_H
#define __DCC_CHAT_H
void dcc_chat_init(void);
void dcc_chat_deinit(void);
#endif

View file

@ -432,7 +432,7 @@ static void dcc_send_init(DCC_REC *dcc)
g_source_remove(dcc->tagread);
close(dcc->handle);
dcc->fastsend = settings_get_bool("toggle_dcc_fast_send");
dcc->fastsend = settings_get_bool("dcc_fast_send");
dcc->handle = handle;
memcpy(&dcc->addr, &addr, sizeof(IPADDR));
net_ip2host(&dcc->addr, dcc->addrstr);

View file

@ -1,7 +0,0 @@
#ifndef __DCC_FILES_H
#define __DCC_FILES_H
void dcc_files_init(void);
void dcc_files_deinit(void);
#endif

View file

@ -30,6 +30,12 @@
#include "dcc.h"
void dcc_chat_init(void);
void dcc_chat_deinit(void);
void dcc_files_init(void);
void dcc_files_deinit(void);
#define DCC_TYPES 5
static gchar *dcc_types[] =
@ -55,7 +61,7 @@ DCC_REC *dcc_create(gint type, gint handle, gchar *nick, gchar *arg, IRC_SERVER_
dcc = g_new0(DCC_REC, 1);
dcc->type = type == DCC_TYPE_CHAT ? module_get_uniq_id("IRC", WI_IRC_DCC_CHAT) : -1;
dcc->mirc_ctcp = settings_get_bool("toggle_dcc_mirc_ctcp");
dcc->mirc_ctcp = settings_get_bool("dcc_mirc_ctcp");
dcc->created = time(NULL);
dcc->chat = chat;
dcc->dcc_type = type;
@ -307,7 +313,7 @@ static void dcc_ctcp_msg(gchar *data, IRC_SERVER_REC *server, gchar *sender, gch
case DCC_TYPE_GET:
cstr = settings_get_str("dcc_autoget_masks");
/* check that autoget masks match */
if (settings_get_bool("toggle_dcc_autoget") && (*cstr == '\0' || irc_masks_match(cstr, sender, sendaddr)) &&
if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || irc_masks_match(cstr, sender, sendaddr)) &&
/* check file size limit, FIXME: it's possible to send a bogus file size and then just send what ever sized file.. */
(settings_get_int("dcc_max_autoget_size") <= 0 || (settings_get_int("dcc_max_autoget_size") > 0 && size <= settings_get_int("dcc_max_autoget_size")*1024)))
{
@ -507,19 +513,19 @@ void dcc_init(void)
dcc_conns = NULL;
dcc_timeouttag = g_timeout_add(1000, (GSourceFunc) dcc_timeout_func, NULL);
settings_add_bool("dcc", "toggle_dcc_autorename", FALSE);
settings_add_bool("dcc", "toggle_dcc_autogete", FALSE);
settings_add_bool("dcc", "dcc_autorename", FALSE);
settings_add_bool("dcc", "dcc_autoget", FALSE);
settings_add_int("dcc", "dcc_max_autoget_size", 1000);
settings_add_str("dcc", "dcc_download_path", "~");
settings_add_int("dcc", "dcc_file_create_mode", 644);
settings_add_str("dcc", "dcc_autoget_masks", "");
settings_add_str("dcc", "dcc_autochat_masks", "");
settings_add_bool("dcc", "toggle_dcc_fast_send", TRUE);
settings_add_bool("dcc", "dcc_fast_send", TRUE);
settings_add_str("dcc", "dcc_upload_path", "~");
settings_add_bool("dcc", "toggle_dcc_mirc_ctcp", FALSE);
settings_add_bool("dcc", "toggle_dcc_autodisplay_dialog", TRUE);
settings_add_bool("dcc", "dcc_mirc_ctcp", FALSE);
settings_add_bool("dcc", "dcc_autodisplay_dialog", TRUE);
settings_add_int("dcc", "dcc_block_size", 2048);
settings_add_int("dcc", "dcc_port", 0);
settings_add_int("dcc", "dcc_timeout", 300);
@ -531,10 +537,16 @@ void dcc_init(void)
command_bind("dcc", NULL, (SIGNAL_FUNC) cmd_dcc);
command_bind("dcc close", NULL, (SIGNAL_FUNC) cmd_dcc_close);
signal_add("event 401", (SIGNAL_FUNC) event_no_such_nick);
dcc_chat_init();
dcc_files_init();
}
void dcc_deinit(void)
{
dcc_chat_deinit();
dcc_files_deinit();
signal_remove("server connected", (SIGNAL_FUNC) dcc_server_connected);
signal_remove("server disconnected", (SIGNAL_FUNC) dcc_server_disconnected);
signal_remove("ctcp reply dcc", (SIGNAL_FUNC) dcc_ctcp_reply);

View file

@ -217,11 +217,11 @@ int autoignore_remove(IRC_SERVER_REC *server, const char *mask, int level)
return FALSE;
}
static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host, const char *levelstr)
static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host, gpointer levelp)
{
int level, check_level;
level = level2bits(levelstr);
level = GPOINTER_TO_INT(levelp);
check_level = level2bits(settings_get_str("autoignore_levels"));
if (level & check_level)

View file

@ -1,8 +1,7 @@
/*
flood.c : Flood protection
flood.c : Flood protection (see also ctcp.c)
Copyright (C) 1999 Timo Sirainen
Copyright (C) 1999-2000 Timo Sirainen
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
@ -32,36 +31,59 @@
#include "ignore.h"
typedef struct {
char *nick;
char *target;
int level;
int msgcount;
time_t first;
} FLOOD_ITEM_REC;
typedef struct {
char *nick;
GSList *items;
} FLOOD_REC;
static int flood_tag;
static int flood_max_msgs;
static int flood_max_msgs, flood_timecheck;
static int flood_hash_deinit(const char *key, FLOOD_REC *rec)
static int flood_hash_deinit(const char *key, FLOOD_REC *flood, gpointer nowp)
{
g_return_val_if_fail(key != NULL, FALSE);
g_return_val_if_fail(rec != NULL, FALSE);
GSList *tmp, *next;
time_t now;
g_free(rec->nick);
g_free(rec);
g_return_val_if_fail(key != NULL, FALSE);
g_return_val_if_fail(flood != NULL, FALSE);
now = (time_t) GPOINTER_TO_INT(nowp);
for (tmp = flood->items; tmp != NULL; tmp = next) {
FLOOD_ITEM_REC *rec = tmp->data;
next = tmp->next;
if (now-rec->first >= flood_timecheck)
flood->items = g_slist_remove(flood->items, rec);
}
if (flood->items != NULL)
return FALSE;
g_free(flood->nick);
g_free(flood);
return TRUE;
}
/* timeout function: flood protection */
static int flood_timeout(void)
{
MODULE_SERVER_REC *mserver;
GSList *tmp;
time_t now;
/* remove everyone from flood list */
/* remove the old people from flood lists */
now = time(NULL);
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
IRC_SERVER_REC *rec = tmp->data;
mserver = MODULE_DATA(rec);
g_hash_table_foreach_remove(mserver->floodlist, (GHRFunc) flood_hash_deinit, NULL);
g_hash_table_foreach_remove(mserver->floodlist, (GHRFunc) flood_hash_deinit, GINT_TO_POINTER((int) now));
}
return 1;
}
@ -88,6 +110,8 @@ static void flood_deinit_server(IRC_SERVER_REC *server)
mserver = MODULE_DATA(server);
if (mserver != NULL && mserver->floodlist != NULL) {
flood_timecheck = 0;
g_hash_table_freeze(mserver->floodlist);
g_hash_table_foreach(mserver->floodlist, (GHFunc) flood_hash_deinit, NULL);
g_hash_table_thaw(mserver->floodlist);
@ -96,34 +120,55 @@ static void flood_deinit_server(IRC_SERVER_REC *server)
g_free(mserver);
}
static FLOOD_ITEM_REC *flood_find(FLOOD_REC *flood, int level, const char *target)
{
GSList *tmp;
for (tmp = flood->items; tmp != NULL; tmp = tmp->next) {
FLOOD_ITEM_REC *rec = tmp->data;
if (rec->level == level && g_strcasecmp(rec->target, target) == 0)
return rec;
}
return NULL;
}
/* All messages should go through here.. */
static void flood_newmsg(IRC_SERVER_REC *server, int level, const char *nick, const char *host, const char *target)
{
MODULE_SERVER_REC *mserver;
FLOOD_REC *rec;
char *levelstr;
FLOOD_REC *flood;
FLOOD_ITEM_REC *rec;
g_return_if_fail(server != NULL);
g_return_if_fail(nick != NULL);
mserver = MODULE_DATA(server);
rec = g_hash_table_lookup(mserver->floodlist, nick);
flood = g_hash_table_lookup(mserver->floodlist, nick);
rec = flood == NULL ? NULL : flood_find(flood, level, target);
if (rec != NULL) {
if (++rec->msgcount > flood_max_msgs) {
/* flooding! */
levelstr = bits2level(rec->level);
signal_emit("flood", 5, server, nick, host, levelstr, target);
g_free(levelstr);
signal_emit("flood", 5, server, nick, host, GINT_TO_POINTER(rec->level), target);
}
return;
}
rec = g_new(FLOOD_REC, 1);
rec->level = level;
rec->msgcount = 1;
rec->nick = g_strdup(nick);
if (flood == NULL) {
flood = g_new0(FLOOD_REC, 1);
flood->nick = g_strdup(nick);
g_hash_table_insert(mserver->floodlist, flood->nick, flood);
}
g_hash_table_insert(mserver->floodlist, rec->nick, rec);
rec = g_new0(FLOOD_ITEM_REC, 1);
rec->level = level;
rec->first = time(NULL);
rec->msgcount = 1;
rec->target = g_strdup(target);
flood->items = g_slist_append(flood->items, rec);
}
static void flood_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr)
@ -141,7 +186,7 @@ static void flood_privmsg(const char *data, IRC_SERVER_REC *server, const char *
params = event_get_params(data, 2, &target, &text);
if (*text == 1) {
if (*text == 1 && g_strncasecmp(text+1, "ACTION", 6) != 0) {
/* CTCP */
if (!ignore_check(server, nick, addr, target, text, MSGLEVEL_CTCPS))
flood_newmsg(server, MSGLEVEL_CTCPS, nick, addr, target);
@ -176,24 +221,37 @@ static void flood_notice(const char *data, IRC_SERVER_REC *server, const char *n
static void read_settings(void)
{
if (flood_tag != -1) g_source_remove(flood_tag);
flood_tag = g_timeout_add(settings_get_int("flood_timecheck"), (GSourceFunc) flood_timeout, NULL);
int time;
flood_timecheck = settings_get_int("flood_timecheck");
flood_max_msgs = settings_get_int("flood_max_msgs");
time = flood_timecheck > 500 ? 500 :
(flood_timecheck > 0 && flood_timecheck < 100) ? 100 :
flood_timecheck;
if (flood_tag != -1) {
g_source_remove(flood_tag);
flood_tag = -1;
}
if (time > 0 && flood_max_msgs > 0) {
flood_tag = g_timeout_add(time, (GSourceFunc) flood_timeout, NULL);
signal_add("event privmsg", (SIGNAL_FUNC) flood_privmsg);
signal_add("event notice", (SIGNAL_FUNC) flood_notice);
}
}
void flood_init(void)
{
settings_add_int("flood", "flood_timecheck", 1000);
settings_add_int("flood", "flood_max_msgs", 5);
settings_add_int("flood", "flood_timecheck", 5000);
settings_add_int("flood", "flood_max_msgs", 4);
flood_tag = -1;
read_settings();
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
signal_add_first("server connected", (SIGNAL_FUNC) flood_init_server);
signal_add("server disconnected", (SIGNAL_FUNC) flood_deinit_server);
signal_add("event privmsg", (SIGNAL_FUNC) flood_privmsg);
signal_add("event notice", (SIGNAL_FUNC) flood_notice);
autoignore_init();
}
@ -202,11 +260,13 @@ void flood_deinit(void)
{
autoignore_deinit();
if (flood_tag != -1) g_source_remove(flood_tag);
if (flood_tag != -1) {
g_source_remove(flood_tag);
signal_remove("event privmsg", (SIGNAL_FUNC) flood_privmsg);
signal_remove("event notice", (SIGNAL_FUNC) flood_notice);
}
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("server connected", (SIGNAL_FUNC) flood_init_server);
signal_remove("server disconnected", (SIGNAL_FUNC) flood_deinit_server);
signal_remove("event privmsg", (SIGNAL_FUNC) flood_privmsg);
signal_remove("event notice", (SIGNAL_FUNC) flood_notice);
}

View file

@ -42,7 +42,7 @@ static void cmd_notify(gchar *data)
if (stristr(args, "-idle") == NULL)
idle_check_time = 0;
else {
idle_check_time = is_numeric(idletime, 0) ? (atol(idletime)*60) :
idle_check_time = is_numeric(idletime, 0) ? (atoi(idletime)*60) :
(settings_get_int("notify_idle_time")*60);
}

View file

@ -78,7 +78,7 @@ static void event_whois_idle(const char *data, IRC_SERVER_REC *server)
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &nick, &secstr);
secs = atol(secstr);
secs = atoi(secstr);
notify = notifylist_find(nick, server->connrec->ircnet);
nickrec = notify_nick_find(server, nick);