summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/servers.h2
-rw-r--r--src/fe-common/irc/dcc/fe-dcc-chat.c2
-rw-r--r--src/fe-common/irc/dcc/fe-dcc-get.c5
-rw-r--r--src/fe-common/irc/fe-common-irc.c4
-rw-r--r--src/fe-common/irc/fe-ctcp.c8
-rw-r--r--src/fe-common/irc/fe-events-numeric.c4
-rw-r--r--src/fe-common/irc/fe-events.c13
-rw-r--r--src/fe-common/irc/fe-irc-channels.c47
-rw-r--r--src/fe-common/irc/fe-irc-channels.h10
-rw-r--r--src/fe-common/irc/fe-irc-messages.c59
-rw-r--r--src/fe-common/irc/fe-irc-queries.c2
-rw-r--r--src/fe-common/irc/fe-modes.c2
-rw-r--r--src/fe-common/irc/fe-netjoin.c2
-rw-r--r--src/fe-text/terminfo-core.c3
-rw-r--r--src/irc/core/bans.c2
-rw-r--r--src/irc/core/channel-rejoin.c2
-rw-r--r--src/irc/core/irc-channels.c4
-rw-r--r--src/irc/core/irc-commands.c2
-rw-r--r--src/irc/core/irc-nicklist.c2
-rw-r--r--src/irc/core/irc-queries.c4
-rw-r--r--src/irc/core/irc-servers.c70
-rw-r--r--src/irc/core/irc.h6
-rw-r--r--src/irc/core/modes.c6
-rw-r--r--src/irc/dcc/dcc-autoget.c2
-rw-r--r--src/irc/flood/flood.c4
-rw-r--r--src/irc/proxy/listen.c56
-rw-r--r--src/irc/proxy/proxy.c58
-rw-r--r--src/irc/proxy/proxy.h1
-rw-r--r--src/perl/irc/Irc.xs1
29 files changed, 270 insertions, 113 deletions
diff --git a/src/core/servers.h b/src/core/servers.h
index d6afbdf5..f39c650b 100644
--- a/src/core/servers.h
+++ b/src/core/servers.h
@@ -18,7 +18,7 @@
(SERVER_CONNECT(conn) ? TRUE : FALSE)
#define server_ischannel(server, channel) \
- (server)->ischannel(server, channel)
+ ((server)->ischannel(server, channel))
/* all strings should be either NULL or dynamically allocated */
/* address and nick are mandatory, rest are optional */
diff --git a/src/fe-common/irc/dcc/fe-dcc-chat.c b/src/fe-common/irc/dcc/fe-dcc-chat.c
index e2706ba3..5bcb3475 100644
--- a/src/fe-common/irc/dcc/fe-dcc-chat.c
+++ b/src/fe-common/irc/dcc/fe-dcc-chat.c
@@ -44,7 +44,7 @@ static void dcc_request(CHAT_DCC_REC *dcc)
if (!IS_DCC_CHAT(dcc)) return;
printformat(dcc->server, NULL, MSGLEVEL_DCC,
- ischannel(*dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL :
+ server_ischannel(SERVER(dcc->server), dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL :
IRCTXT_DCC_CHAT, dcc->id, dcc->addrstr,
dcc->port, dcc->target);
}
diff --git a/src/fe-common/irc/dcc/fe-dcc-get.c b/src/fe-common/irc/dcc/fe-dcc-get.c
index 451463f9..675cab65 100644
--- a/src/fe-common/irc/dcc/fe-dcc-get.c
+++ b/src/fe-common/irc/dcc/fe-dcc-get.c
@@ -21,6 +21,7 @@
#include "module.h"
#include "signals.h"
#include "levels.h"
+#include "servers.h"
#include "irc.h"
#include "dcc-file.h"
@@ -35,12 +36,12 @@ static void dcc_request(GET_DCC_REC *dcc)
{
char *sizestr;
- if (!IS_DCC_GET(dcc)) return;
+ if (!IS_DCC_GET(dcc)) return;
sizestr = dcc_get_size_str(dcc->size);
printformat(dcc->server, NULL, MSGLEVEL_DCC,
- ischannel(*dcc->target) ? IRCTXT_DCC_SEND_CHANNEL :
+ server_ischannel(SERVER(dcc->server), dcc->target) ? IRCTXT_DCC_SEND_CHANNEL :
IRCTXT_DCC_SEND, dcc->nick, dcc->addrstr,
dcc->port, dcc->arg, sizestr, dcc->target);
diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c
index 72606263..d6ab30ce 100644
--- a/src/fe-common/irc/fe-common-irc.c
+++ b/src/fe-common/irc/fe-common-irc.c
@@ -28,13 +28,11 @@
#include "themes.h"
#include "fe-irc-server.h"
+#include "fe-irc-channels.h"
void fe_irc_modules_init(void);
void fe_irc_modules_deinit(void);
-void fe_irc_channels_init(void);
-void fe_irc_channels_deinit(void);
-
void fe_irc_queries_init(void);
void fe_irc_queries_deinit(void);
diff --git a/src/fe-common/irc/fe-ctcp.c b/src/fe-common/irc/fe-ctcp.c
index 2321bb7a..cbb591ba 100644
--- a/src/fe-common/irc/fe-ctcp.c
+++ b/src/fe-common/irc/fe-ctcp.c
@@ -49,7 +49,7 @@ static void ctcp_default_msg(IRC_SERVER_REC *server, const char *data,
data = p+1;
}
- printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
+ printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
IRCTXT_CTCP_REQUESTED_UNKNOWN,
nick, addr, cmd, data, target);
g_free(cmd);
@@ -113,8 +113,8 @@ static void ctcp_default_reply(IRC_SERVER_REC *server, const char *data,
ctcpdata = ptr+1;
}
- printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
- ischannel(*target) ? IRCTXT_CTCP_REPLY_CHANNEL :
+ printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
+ server_ischannel(SERVER(server), target) ? IRCTXT_CTCP_REPLY_CHANNEL :
IRCTXT_CTCP_REPLY, ctcp, nick, ctcpdata, target);
g_free(ctcp);
}
@@ -137,7 +137,7 @@ static void ctcp_ping_reply(IRC_SERVER_REC *server, const char *data,
g_get_current_time(&tv);
usecs = get_timeval_diff(&tv, &tv2);
- printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
+ printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
IRCTXT_CTCP_PING_REPLY, nick, usecs/1000, usecs%1000);
}
diff --git a/src/fe-common/irc/fe-events-numeric.c b/src/fe-common/irc/fe-events-numeric.c
index ec7669ab..3eb124fc 100644
--- a/src/fe-common/irc/fe-events-numeric.c
+++ b/src/fe-common/irc/fe-events-numeric.c
@@ -400,7 +400,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data,
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &target);
- if (!ischannel(*target)) {
+ if (!server_ischannel(SERVER(server), target)) {
/* nick unavailable */
printformat(server, NULL, MSGLEVEL_CRAP,
IRCTXT_NICK_UNAVAILABLE, target);
@@ -583,7 +583,7 @@ static void print_event_received(IRC_SERVER_REC *server, const char *data,
return;
ptr++;
- if (ischannel(*data)) /* directed at channel */
+ if (server_ischannel(SERVER(server), data)) /* directed at channel */
target = g_strndup(data, (int)(ptr - data - 1));
else if (!target_param || *ptr == ':' || (ptr2 = strchr(ptr, ' ')) == NULL)
target = NULL;
diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c
index 5cde9e4b..3a01b9eb 100644
--- a/src/fe-common/irc/fe-events.c
+++ b/src/fe-common/irc/fe-events.c
@@ -41,6 +41,7 @@
#include "fe-queries.h"
#include "fe-windows.h"
#include "fe-irc-server.h"
+#include "fe-irc-channels.h"
static void event_privmsg(IRC_SERVER_REC *server, const char *data,
const char *nick, const char *addr)
@@ -52,15 +53,17 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data,
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (nick == NULL) nick = server->real_address;
if (addr == NULL) addr = "";
- if (*target == '@' && ischannel(target[1])) {
+
+ if (fe_channel_is_opchannel(server, target)) {
/* Hybrid 6 feature, send msg to all ops in channel */
- recoded = recode_in(SERVER(server), msg, target+1);
+ target = (char *)fe_channel_skip_prefix(server, target);
+ recoded = recode_in(SERVER(server), msg, target);
signal_emit("message irc op_public", 5,
server, recoded, nick, addr,
- get_visible_target(server, target+1));
+ get_visible_target(server, target));
} else {
- recoded = recode_in(SERVER(server), msg, ischannel(*target) ? target : nick);
- signal_emit(ischannel(*target) ?
+ recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick);
+ signal_emit(server_ischannel(SERVER(server), target) ?
"message public" : "message private", 5,
server, recoded, nick, addr,
get_visible_target(server, target));
diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c
index e884aef4..d5f17bd0 100644
--- a/src/fe-common/irc/fe-irc-channels.c
+++ b/src/fe-common/irc/fe-irc-channels.c
@@ -31,6 +31,51 @@
#include "fe-windows.h"
#include "window-items.h"
+int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target)
+{
+ const char *statusmsg;
+
+ /* Quick check */
+ if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
+ return FALSE;
+
+ statusmsg = g_hash_table_lookup(server->isupport, "statusmsg");
+ if (statusmsg == NULL)
+ statusmsg = "@+";
+
+ return strchr(statusmsg, *target) != NULL;
+}
+
+const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target)
+{
+ const char *statusmsg;
+
+ /* Quick check */
+ if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
+ return target;
+
+ /* Exit early if target doesn't name a channel */
+ if (server_ischannel(SERVER(server), target) == FALSE)
+ return FALSE;
+
+ statusmsg = g_hash_table_lookup(server->isupport, "statusmsg");
+
+ /* Hack: for bahamut 1.4 which sends neither STATUSMSG nor
+ * WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */
+ if (statusmsg == NULL && *target != '@')
+ return target;
+
+ if (statusmsg == NULL)
+ statusmsg = "@+";
+
+ /* Strip the leading statusmsg prefixes */
+ while (strchr(statusmsg, *target) != NULL) {
+ target++;
+ }
+
+ return target;
+}
+
static void sig_channel_rejoin(SERVER_REC *server, REJOIN_REC *rec)
{
g_return_if_fail(rec != NULL);
@@ -46,7 +91,7 @@ static void sig_event_forward(SERVER_REC *server, const char *data,
char *params, *from, *to;
params = event_get_params(data, 3, NULL, &from, &to);
- if (from != NULL && to != NULL && ischannel(*from) && ischannel(*to)) {
+ if (from != NULL && to != NULL && server_ischannel(server, from) && server_ischannel(server, to)) {
channel = irc_channel_find(server, from);
if (channel != NULL && irc_channel_find(server, to) == NULL) {
window_bind_add(window_item_window(channel),
diff --git a/src/fe-common/irc/fe-irc-channels.h b/src/fe-common/irc/fe-irc-channels.h
new file mode 100644
index 00000000..d05c91a5
--- /dev/null
+++ b/src/fe-common/irc/fe-irc-channels.h
@@ -0,0 +1,10 @@
+#ifndef __FE_IRC_CHANNELS_H
+#define __FE_IRC_CHANNELS_H
+
+int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target);
+const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target);
+
+void fe_irc_channels_init(void);
+void fe_irc_channels_deinit(void);
+
+#endif
diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c
index 94d1ad4a..11d158af 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -36,32 +36,7 @@
#include "fe-queries.h"
#include "window-items.h"
-
-static const char *skip_target(IRC_SERVER_REC *server, const char *target)
-{
- int i = 0;
- const char *val, *chars;
-
- /* Quick check */
- if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
- return target;
-
- /* Hack: for bahamut 1.4 which sends neither STATUSMSG nor
- * WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */
- val = g_hash_table_lookup(server->isupport, "STATUSMSG");
- if (val == NULL && *target != '@')
- return target;
- chars = val ? val : "@+";
- for(i = 0; target[i] != '\0'; i++) {
- if (strchr(chars, target[i]) == NULL)
- break;
- };
-
- if(ischannel(target[i]))
- target += i;
-
- return target;
-}
+#include "fe-irc-channels.h"
static void sig_message_own_public(SERVER_REC *server, const char *msg,
const char *target, const char *origtarget)
@@ -72,7 +47,7 @@ static void sig_message_own_public(SERVER_REC *server, const char *msg,
if (!IS_IRC_SERVER(server))
return;
oldtarget = target;
- target = skip_target(IRC_SERVER(server), target);
+ target = fe_channel_skip_prefix(IRC_SERVER(server), target);
if (target != oldtarget) {
/* Hybrid 6 / Bahamut feature, send msg to all
ops / ops+voices in channel */
@@ -135,8 +110,8 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
char *freemsg = NULL;
oldtarget = target;
- target = skip_target(IRC_SERVER(server), target);
- if (ischannel(*target))
+ target = fe_channel_skip_prefix(IRC_SERVER(server), target);
+ if (server_ischannel(SERVER(server), target))
item = irc_channel_find(server, target);
else
item = irc_query_find(server, target);
@@ -146,7 +121,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
printformat(server, target,
MSGLEVEL_ACTIONS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT |
- (ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS),
+ (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS),
item != NULL && oldtarget == target ? IRCTXT_OWN_ACTION : IRCTXT_OWN_ACTION_TARGET,
server->nick, msg, oldtarget);
g_free_not_null(freemsg);
@@ -163,10 +138,10 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
int own = FALSE;
oldtarget = target;
- target = skip_target(IRC_SERVER(server), target);
+ target = fe_channel_skip_prefix(IRC_SERVER(server), target);
level = MSGLEVEL_ACTIONS |
- (ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
+ (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
if (ignore_check(SERVER(server), nick, address, target, msg, level))
return;
@@ -175,7 +150,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
level | MSGLEVEL_NO_ACT))
level |= MSGLEVEL_NO_ACT;
- if (ischannel(*target)) {
+ if (server_ischannel(SERVER(server), target)) {
item = irc_channel_find(server, target);
} else {
own = (!g_strcmp0(nick, server->nick));
@@ -185,7 +160,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
if (settings_get_bool("emphasis"))
msg = freemsg = expand_emphasis(item, msg);
- if (ischannel(*target)) {
+ if (server_ischannel(SERVER(server), target)) {
/* channel action */
if (window_item_is_active(item) && target == oldtarget) {
/* message to active channel in window */
@@ -219,7 +194,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
static void sig_message_own_notice(IRC_SERVER_REC *server, const char *msg,
const char *target)
{
- printformat(server, skip_target(server, target), MSGLEVEL_NOTICES |
+ printformat(server, fe_channel_skip_prefix(server, target), MSGLEVEL_NOTICES |
MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
IRCTXT_OWN_NOTICE, target, msg);
}
@@ -232,7 +207,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
int level = MSGLEVEL_NOTICES;
oldtarget = target;
- target = skip_target(IRC_SERVER(server), target);
+ target = fe_channel_skip_prefix(IRC_SERVER(server), target);
if (address == NULL || *address == '\0') {
/* notice from server */
@@ -245,16 +220,16 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
}
if (ignore_check(server, nick, address,
- ischannel(*target) ? target : NULL,
+ server_ischannel(SERVER(server), target) ? target : NULL,
msg, level))
return;
if (ignore_check(server, nick, address,
- ischannel(*target) ? target : NULL,
+ server_ischannel(SERVER(server), target) ? target : NULL,
msg, level | MSGLEVEL_NO_ACT))
level |= MSGLEVEL_NO_ACT;
- if (ischannel(*target)) {
+ if (server_ischannel(SERVER(server), target)) {
/* notice in some channel */
printformat(server, target, level,
IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg);
@@ -270,7 +245,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
static void sig_message_own_ctcp(IRC_SERVER_REC *server, const char *cmd,
const char *data, const char *target)
{
- printformat(server, skip_target(server, target), MSGLEVEL_CTCPS |
+ printformat(server, fe_channel_skip_prefix(server, target), MSGLEVEL_CTCPS |
MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
IRCTXT_OWN_CTCP, target, cmd, data);
}
@@ -282,8 +257,8 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd,
const char *oldtarget;
oldtarget = target;
- target = skip_target(server, target);
- printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
+ target = fe_channel_skip_prefix(server, target);
+ printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
IRCTXT_CTCP_REQUESTED, nick, addr, cmd, data, oldtarget);
}
diff --git a/src/fe-common/irc/fe-irc-queries.c b/src/fe-common/irc/fe-irc-queries.c
index 0861c9e4..b2faefbc 100644
--- a/src/fe-common/irc/fe-irc-queries.c
+++ b/src/fe-common/irc/fe-irc-queries.c
@@ -63,7 +63,7 @@ static void event_privmsg(SERVER_REC *server, const char *data,
g_return_if_fail(data != NULL);
- if (nick == NULL || address == NULL || ischannel(*data) ||
+ if (nick == NULL || address == NULL || server_ischannel(server, data) ||
!settings_get_bool("query_track_nick_changes"))
return;
diff --git a/src/fe-common/irc/fe-modes.c b/src/fe-common/irc/fe-modes.c
index e5317c0f..53e56c97 100644
--- a/src/fe-common/irc/fe-modes.c
+++ b/src/fe-common/irc/fe-modes.c
@@ -168,7 +168,7 @@ static void sig_message_mode(IRC_SERVER_REC *server, const char *channel,
mode, MSGLEVEL_MODES))
return;
- if (!ischannel(*channel)) {
+ if (!server_ischannel(SERVER(server), channel)) {
/* user mode change */
printformat(server, NULL, MSGLEVEL_MODES,
IRCTXT_USERMODE_CHANGE, mode, channel);
diff --git a/src/fe-common/irc/fe-netjoin.c b/src/fe-common/irc/fe-netjoin.c
index 35c463e4..f5cb081e 100644
--- a/src/fe-common/irc/fe-netjoin.c
+++ b/src/fe-common/irc/fe-netjoin.c
@@ -400,7 +400,7 @@ static void msg_mode(IRC_SERVER_REC *server, const char *channel,
int show;
g_return_if_fail(data != NULL);
- if (!ischannel(*channel) || addr != NULL)
+ if (!server_ischannel(SERVER(server), channel) || addr != NULL)
return;
params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index 6339e6f4..60927f1a 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -502,6 +502,9 @@ static void terminfo_input_init(TERM_REC *term)
memcpy(&term->tio, &term->old_tio, sizeof(term->tio));
term->tio.c_lflag &= ~(ICANON | ECHO); /* CBREAK, no ECHO */
+ /* Disable the ICRNL flag to disambiguate ^J and Enter, also disable the
+ * software flow control to leave ^Q and ^S ready to be bound */
+ term->tio.c_iflag &= ~(ICRNL | IXON | IXOFF);
term->tio.c_cc[VMIN] = 1; /* read() is satisfied after 1 char */
term->tio.c_cc[VTIME] = 0; /* No timer */
diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c
index b60e681b..68dd45c0 100644
--- a/src/irc/core/bans.c
+++ b/src/irc/core/bans.c
@@ -186,7 +186,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server,
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
item, &channel, &nicks)) return;
- if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED);
+ if (!server_ischannel(SERVER(server), channel)) cmd_param_error(CMDERR_NOT_JOINED);
if (*nicks == '\0') {
if (g_strcmp0(data, "*") != 0)
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
diff --git a/src/irc/core/channel-rejoin.c b/src/irc/core/channel-rejoin.c
index 68a1dee1..154035ae 100644
--- a/src/irc/core/channel-rejoin.c
+++ b/src/irc/core/channel-rejoin.c
@@ -149,7 +149,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data)
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
- if (ischannel(*channel)) {
+ if (server_ischannel(SERVER(server), channel)) {
chanrec = irc_channel_find(server, channel);
if (chanrec != NULL && chanrec->joined) {
/* dalnet event - can't change nick while
diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c
index e38cb98b..add18acf 100644
--- a/src/irc/core/irc-channels.c
+++ b/src/irc/core/irc-channels.c
@@ -99,7 +99,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
tmp = chanlist;
for (;; tmp++) {
if (*tmp != NULL) {
- channel = ischannel(**tmp) ? g_strdup(*tmp) :
+ channel = server_ischannel(SERVER(server), *tmp) ? g_strdup(*tmp) :
g_strdup_printf("#%s", *tmp);
chanrec = irc_channel_find(server, channel);
@@ -134,7 +134,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
if (use_keys)
cmdlen += outkeys->len;
if (*tmpstr != NULL)
- cmdlen += ischannel(**tmpstr) ? strlen(*tmpstr) :
+ cmdlen += server_ischannel(SERVER(server), *tmpstr) ? strlen(*tmpstr) :
strlen(*tmpstr)+1;
if (*tmpkey != NULL)
cmdlen += strlen(*tmpkey);
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index e7fb5067..f2cd49c0 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -191,7 +191,7 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
return;
if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
- if (!ischannel(*channame)) cmd_param_error(CMDERR_NOT_JOINED);
+ if (!server_ischannel(SERVER(server), channame)) cmd_param_error(CMDERR_NOT_JOINED);
recoded = recode_out(SERVER(server), reason, channame);
g_string_printf(tmpstr, "KICK %s %s :%s", channame, nicks, recoded);
diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c
index 5438509e..667016aa 100644
--- a/src/irc/core/irc-nicklist.c
+++ b/src/irc/core/irc-nicklist.c
@@ -394,7 +394,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data)
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
- if (!ischannel(*channel)) {
+ if (!server_ischannel(SERVER(server), channel)) {
/* nick is unavailable. */
event_nick_in_use(server, data);
}
diff --git a/src/irc/core/irc-queries.c b/src/irc/core/irc-queries.c
index 72c17df1..12861744 100644
--- a/src/irc/core/irc-queries.c
+++ b/src/irc/core/irc-queries.c
@@ -60,8 +60,8 @@ static void check_query_changes(IRC_SERVER_REC *server, const char *nick,
{
QUERY_REC *query;
- if (ischannel(*target))
- return;
+ if (server_ischannel(SERVER(server), target))
+ return;
query = irc_query_find(server, nick);
if (query == NULL)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index ad4d09cc..82584382 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -34,6 +34,8 @@
#include "irc-servers.h"
#include "irc-cap.h"
#include "sasl.h"
+
+#include "channels-setup.h"
#include "channel-rejoin.h"
#include "servers-idle.h"
#include "servers-reconnect.h"
@@ -73,13 +75,20 @@ static int isnickflag_func(SERVER_REC *server, char flag)
static int ischannel_func(SERVER_REC *server, const char *data)
{
- if (*data == '@') {
- /* @#channel, @+#channel */
+ IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
+ char *chantypes, *statusmsg;
+
+ chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes");
+ if (chantypes == NULL)
+ chantypes = "#&!+"; /* normal, local, secure, modeless */
+ statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg");
+ if (statusmsg == NULL)
+ statusmsg = "@+";
+
+ while (strchr(statusmsg, *data) != NULL)
data++;
- if (*data == '+' && ischannel(data[1]))
- return 1;
- }
- return ischannel(*data);
+
+ return strchr(chantypes, *data) != NULL;
}
static char **split_line(const SERVER_REC *server, const char *line,
@@ -606,32 +615,59 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
GString *chans, *keys;
char *ret;
int use_keys;
+ char *rejoin_channels_mode;
g_return_val_if_fail(server != NULL, FALSE);
+ rejoin_channels_mode = g_strdup(settings_get_str("rejoin_channels_on_reconnect"));
+
+ if (rejoin_channels_mode == NULL ||
+ (g_ascii_strcasecmp(rejoin_channels_mode, "on") != 0 &&
+ g_ascii_strcasecmp(rejoin_channels_mode, "off") != 0 &&
+ g_ascii_strcasecmp(rejoin_channels_mode, "auto") != 0)) {
+ g_warning("Invalid value for 'rejoin_channels_on_reconnect', valid values are 'on', 'off', 'auto', using 'on' as default value.");
+ g_free(rejoin_channels_mode);
+ rejoin_channels_mode = g_strdup("on");
+ }
+
chans = g_string_new(NULL);
keys = g_string_new(NULL);
use_keys = FALSE;
+ /* do we want to rejoin channels in the first place? */
+ if(g_ascii_strcasecmp(rejoin_channels_mode, "off") == 0) {
+ g_string_free(chans, TRUE);
+ g_string_free(keys, TRUE);
+ g_free(rejoin_channels_mode);
+ return g_strdup("");
+ }
+
/* get currently joined channels */
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
-
- g_string_append_printf(chans, "%s,", channel->name);
- g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" :
- channel->key);
- if (channel->key != NULL)
- use_keys = TRUE;
+ CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet);
+ if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) ||
+ g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) {
+ g_string_append_printf(chans, "%s,", channel->name);
+ g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key);
+ if (channel->key != NULL)
+ use_keys = TRUE;
+ }
}
/* get also the channels that are in rejoin list */
for (tmp = server->rejoin_channels; tmp != NULL; tmp = tmp->next) {
REJOIN_REC *rec = tmp->data;
+ CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag);
+
+ if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) ||
+ g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) {
+ g_string_append_printf(chans, "%s,", rec->channel);
+ g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" :
+ rec->key);
- g_string_append_printf(chans, "%s,", rec->channel);
- g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" :
- rec->key);
- if (rec->key != NULL) use_keys = TRUE;
+ if (rec->key != NULL) use_keys = TRUE;
+ }
}
if (chans->len > 0) {
@@ -643,6 +679,7 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
ret = chans->str;
g_string_free(chans, FALSE);
g_string_free(keys, TRUE);
+ g_free(rejoin_channels_mode);
return ret;
}
@@ -988,6 +1025,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server)
void irc_servers_init(void)
{
+ settings_add_str("servers", "rejoin_channels_on_reconnect", "on");
settings_add_str("misc", "usermode", DEFAULT_USER_MODE);
settings_add_str("misc", "split_line_start", "");
settings_add_str("misc", "split_line_end", "");
diff --git a/src/irc/core/irc.h b/src/irc/core/irc.h
index de19e084..b5bd833a 100644
--- a/src/irc/core/irc.h
+++ b/src/irc/core/irc.h
@@ -22,12 +22,6 @@ typedef struct _REDIRECT_REC REDIRECT_REC;
#define isnickflag(server, a) \
(server->prefix[(int)(unsigned char) a] != '\0')
-#define ischannel(a) \
- ((a) == '#' || /* normal */ \
- (a) == '&' || /* local */ \
- (a) == '!' || /* secure */ \
- (a) == '+') /* modeless */
-
#define IS_IRC_ITEM(rec) (IS_IRC_CHANNEL(rec) || IS_IRC_QUERY(rec))
#define IRC_PROTOCOL (chat_protocol_lookup("IRC"))
diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c
index a812691c..32a0c169 100644
--- a/src/irc/core/modes.c
+++ b/src/irc/core/modes.c
@@ -488,7 +488,7 @@ static void event_mode(IRC_SERVER_REC *server, const char *data,
params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
&channel, &mode);
- if (!ischannel(*channel)) {
+ if (!server_ischannel(SERVER(server), channel)) {
/* user mode change */
parse_user_mode(server, mode);
} else {
@@ -536,7 +536,7 @@ static void sig_req_usermode_change(IRC_SERVER_REC *server, const char *data,
params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
&target, &mode);
- if (!ischannel(*target)) {
+ if (!server_ischannel(SERVER(server), target)) {
/* we requested a user mode change, save this */
mode = modes_join(NULL, server->wanted_usermode, mode, FALSE);
g_free_not_null(server->wanted_usermode);
@@ -856,7 +856,7 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server,
target = chanrec->name;
irc_send_cmdv(server, "MODE %s", target);
- } else if (ischannel(*target))
+ } else if (server_ischannel(SERVER(server), target))
channel_set_mode(server, target, mode);
else {
if (g_ascii_strcasecmp(target, server->nick) == 0) {
diff --git a/src/irc/dcc/dcc-autoget.c b/src/irc/dcc/dcc-autoget.c
index 38170c56..de23a5d1 100644
--- a/src/irc/dcc/dcc-autoget.c
+++ b/src/irc/dcc/dcc-autoget.c
@@ -51,7 +51,7 @@ static void sig_dcc_request(GET_DCC_REC *dcc, const char *nickaddr)
/* Unless specifically said in dcc_autoget_masks, don't do autogets
sent to channels. */
- if (*masks == '\0' && dcc->target != NULL && ischannel(*dcc->target))
+ if (*masks == '\0' && dcc->target != NULL && server_ischannel(SERVER(dcc->server), dcc->target))
return;
/* don't autoget files beginning with a dot, if download dir is
diff --git a/src/irc/flood/flood.c b/src/irc/flood/flood.c
index 29502ca6..0944a6eb 100644
--- a/src/irc/flood/flood.c
+++ b/src/irc/flood/flood.c
@@ -250,7 +250,7 @@ static void flood_privmsg(IRC_SERVER_REC *server, const char *data,
params = event_get_params(data, 2, &target, &text);
- level = ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS;
+ level = server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS;
if (addr != NULL && !ignore_check(SERVER(server), nick, addr, target, text, level))
flood_newmsg(server, level, nick, addr, target);
@@ -287,7 +287,7 @@ static void flood_ctcp(IRC_SERVER_REC *server, const char *data,
return;
level = g_ascii_strncasecmp(data, "ACTION ", 7) != 0 ? MSGLEVEL_CTCPS :
- (ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
+ (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
if (!ignore_check(SERVER(server), nick, addr, target, data, level))
flood_newmsg(server, level, nick, addr, target);
}
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 2b7c7bda..dcc94e6b 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -37,6 +37,8 @@ GSList *proxy_clients;
static GString *next_line;
static int ignore_next;
+static int enabled = FALSE;
+
static void remove_client(CLIENT_REC *rec)
{
g_return_if_fail(rec != NULL);
@@ -45,8 +47,8 @@ static void remove_client(CLIENT_REC *rec)
rec->listen->clients = g_slist_remove(rec->listen->clients, rec);
signal_emit("proxy client disconnected", 1, rec);
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client disconnected from %s", rec->host);
+ printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Client %s:%d disconnected", rec->host, rec->port);
g_free(rec->proxy_address);
net_sendbuffer_destroy(rec->handle, TRUE);
@@ -126,6 +128,10 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
/* client didn't send us PASS, kill it */
remove_client(client);
} else {
+ signal_emit("proxy client connected", 1, client);
+ printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Client %s:%d connected",
+ client->host, client->port);
client->connected = TRUE;
proxy_dump_data(client);
}
@@ -262,7 +268,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
ignore_next = TRUE;
if (*msg != '\001' || msg[strlen(msg)-1] != '\001') {
- signal_emit(ischannel(*target) ?
+ signal_emit(server_ischannel(SERVER(client->server), target) ?
"message own_public" : "message own_private", 4,
client->server, msg, target, target);
} else if (strncmp(msg+1, "ACTION ", 7) == 0) {
@@ -347,6 +353,7 @@ static void sig_listen(LISTEN_REC *listen)
rec->listen = listen;
rec->handle = sendbuf;
rec->host = g_strdup(host);
+ rec->port = port;
if (g_strcmp0(listen->ircnet, "*") == 0) {
rec->proxy_address = g_strdup("irc.proxy");
rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data);
@@ -361,9 +368,10 @@ static void sig_listen(LISTEN_REC *listen)
proxy_clients = g_slist_prepend(proxy_clients, rec);
rec->listen->clients = g_slist_prepend(rec->listen->clients, rec);
- signal_emit("proxy client connected", 1, rec);
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client connected from %s", rec->host);
+ signal_emit("proxy client connecting", 1, rec);
+ printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: New client %s:%d on port %d (%s)",
+ rec->host, rec->port, listen->port, listen->ircnet);
}
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
@@ -634,7 +642,8 @@ static void remove_listen(LISTEN_REC *rec)
static void read_settings(void)
{
LISTEN_REC *rec;
- GSList *remove_listens;
+ GSList *remove_listens = NULL;
+ GSList *add_listens = NULL;
char **ports, **tmp, *ircnet, *port;
int portnum;
@@ -653,17 +662,30 @@ static void read_settings(void)
continue;
rec = find_listen(ircnet, portnum);
- if (rec == NULL)
- add_listen(ircnet, portnum);
- else
+ if (rec == NULL) {
+ rec = g_new0(LISTEN_REC, 1);
+ rec->ircnet = ircnet; /* borrow */
+ rec->port = portnum;
+ add_listens = g_slist_prepend(add_listens, rec);
+ } else {
+ /* remove from the list of listens to remove == keep it */
remove_listens = g_slist_remove(remove_listens, rec);
+ }
}
- g_strfreev(ports);
while (remove_listens != NULL) {
- remove_listen(remove_listens->data);
+ remove_listen(remove_listens->data);
remove_listens = g_slist_remove(remove_listens, remove_listens->data);
}
+
+ while (add_listens != NULL) {
+ rec = add_listens->data;
+ add_listen(rec->ircnet, rec->port);
+ g_free(rec);
+ add_listens = g_slist_remove(add_listens, add_listens->data);
+ }
+
+ g_strfreev(ports);
}
static void sig_dump(CLIENT_REC *client, const char *data)
@@ -676,6 +698,11 @@ static void sig_dump(CLIENT_REC *client, const char *data)
void proxy_listen_init(void)
{
+ if (enabled) {
+ return;
+ }
+ enabled = TRUE;
+
next_line = g_string_new(NULL);
proxy_clients = NULL;
@@ -697,6 +724,11 @@ void proxy_listen_init(void)
void proxy_listen_deinit(void)
{
+ if (!enabled) {
+ return;
+ }
+ enabled = FALSE;
+
while (proxy_listens != NULL)
remove_listen(proxy_listens->data);
g_string_free(next_line, TRUE);
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index c8f47bdf..ce79e2b7 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -23,11 +23,60 @@
#include "settings.h"
#include "levels.h"
+#include "fe-common/core/printtext.h"
+
+/* SYNTAX: IRSSIPROXY STATUS */
+static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server)
+{
+ if (!settings_get_bool("irssiproxy")) {
+ printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy is currently disabled");
+ return;
+ }
+
+ GSList *tmp;
+
+ printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Currently connected clients: %d",
+ g_slist_length(proxy_clients));
+
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
+
+ printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
+ " %s:%d connect%s to %d (%s)",
+ rec->host, rec->port,
+ rec->connected ? "ed" : "ing",
+ rec->listen->port, rec->listen->ircnet);
+ }
+}
+
+/* SYNTAX: IRSSIPROXY */
+static void cmd_irssiproxy(const char *data, IRC_SERVER_REC *server, void *item)
+{
+ if (*data == '\0') {
+ cmd_irssiproxy_status(data, server);
+ return;
+ }
+
+ command_runsub("irssiproxy", data, server, item);
+}
+
+static void irc_proxy_setup_changed(void)
+{
+ if (settings_get_bool("irssiproxy")) {
+ proxy_listen_init();
+ } else {
+ proxy_listen_deinit();
+ }
+}
+
void irc_proxy_init(void)
{
settings_add_str("irssiproxy", "irssiproxy_ports", "");
settings_add_str("irssiproxy", "irssiproxy_password", "");
settings_add_str("irssiproxy", "irssiproxy_bind", "");
+ settings_add_bool("irssiproxy", "irssiproxy", TRUE);
if (*settings_get_str("irssiproxy_password") == '\0') {
/* no password - bad idea! */
@@ -43,7 +92,14 @@ void irc_proxy_init(void)
"... to set them.");
}
- proxy_listen_init();
+ command_bind("irssiproxy", NULL, (SIGNAL_FUNC) cmd_irssiproxy);
+ command_bind("irssiproxy status", NULL, (SIGNAL_FUNC) cmd_irssiproxy_status);
+
+ signal_add_first("setup changed", (SIGNAL_FUNC) irc_proxy_setup_changed);
+
+ if (settings_get_bool("irssiproxy")) {
+ proxy_listen_init();
+ }
settings_check();
module_register("proxy", "irc");
}
diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h
index 4ddc9da9..158b0675 100644
--- a/src/irc/proxy/proxy.h
+++ b/src/irc/proxy/proxy.h
@@ -19,6 +19,7 @@ typedef struct {
typedef struct {
char *nick, *host;
+ int port;
NET_SENDBUF_REC *handle;
int recv_tag;
char *proxy_address;
diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs
index 18665cb7..a245206c 100644
--- a/src/perl/irc/Irc.xs
+++ b/src/perl/irc/Irc.xs
@@ -149,6 +149,7 @@ static void perl_client_fill_hash(HV *hv, CLIENT_REC *client)
{
(void) hv_store(hv, "nick", 4, new_pv(client->nick), 0);
(void) hv_store(hv, "host", 4, new_pv(client->host), 0);
+ (void) hv_store(hv, "port", 4, newSViv(client->port), 0);
(void) hv_store(hv, "proxy_address", 13, new_pv(client->proxy_address), 0);
(void) hv_store(hv, "server", 6, iobject_bless(client->server), 0);
(void) hv_store(hv, "pass_sent", 9, newSViv(client->pass_sent), 0);