From d27c54486f3e5656445b43affd37f17d1338a6ce Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Tue, 24 Jun 2014 23:01:06 -0700
Subject: [PATCH 01/82] Change around connection signals in proxy module
Change "proxy client connected" to "proxy client connecting" to avoid being confused by clients that have connected but not necessarily authenticated. Emit "proxy client connected" once authenticated, keeping the name for backwards compatibility.
---
src/irc/proxy/listen.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 33392285..8f8ebe99 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -126,6 +126,9 @@ 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(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Client finished connecting from %s", client->host);
client->connected = TRUE;
proxy_dump_data(client);
}
@@ -361,9 +364,9 @@ 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);
+ signal_emit("proxy client connecting", 1, rec);
printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client connected from %s", rec->host);
+ "Proxy: Client connecting from %s", rec->host);
}
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
From aaa0f73eac88316978c65fb0f0c8b5d23d1dc100 Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Tue, 24 Jun 2014 23:45:35 -0700
Subject: [PATCH 02/82] Make proxy messages include more detail and add status
command
---
src/irc/proxy/listen.c | 15 +++++++++------
src/irc/proxy/proxy.c | 34 ++++++++++++++++++++++++++++++++++
src/irc/proxy/proxy.h | 1 +
3 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 8f8ebe99..df0d7479 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -45,8 +45,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);
@@ -127,8 +127,9 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
remove_client(client);
} else {
signal_emit("proxy client connected", 1, client);
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client finished connecting from %s", client->host);
+ printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Client %s:%d connected",
+ client->host, client->port);
client->connected = TRUE;
proxy_dump_data(client);
}
@@ -350,6 +351,7 @@ static void sig_listen(LISTEN_REC *listen)
rec->listen = listen;
rec->handle = sendbuf;
rec->host = g_strdup(host);
+ rec->port = port;
if (strcmp(listen->ircnet, "*") == 0) {
rec->proxy_address = g_strdup("irc.proxy");
rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data);
@@ -365,8 +367,9 @@ static void sig_listen(LISTEN_REC *listen)
rec->listen->clients = g_slist_prepend(rec->listen->clients, rec);
signal_emit("proxy client connecting", 1, rec);
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client connecting from %s", rec->host);
+ 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)
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index c8f47bdf..75da112c 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -23,6 +23,37 @@
#include "settings.h"
#include "levels.h"
+#include "fe-common/core/printtext.h"
+
+static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server)
+{
+ 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);
+ }
+}
+
+static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item)
+{
+ if (*data == '\0') {
+ cmd_proxy_status(data, server);
+ return;
+ }
+
+ command_runsub("proxy", data, server, item);
+}
+
void irc_proxy_init(void)
{
settings_add_str("irssiproxy", "irssiproxy_ports", "");
@@ -43,6 +74,9 @@ void irc_proxy_init(void)
"... to set them.");
}
+ command_bind("proxy", NULL, (SIGNAL_FUNC) cmd_proxy);
+ command_bind("proxy status", NULL, (SIGNAL_FUNC) cmd_proxy_status);
+
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;
From 6a28bad81440290e799c4d4985f31bea6493f58b Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Wed, 25 Jun 2014 22:29:05 -0700
Subject: [PATCH 03/82] Add boolean toggle for irssiproxy being enabled
---
src/irc/proxy/listen.c | 12 ++++++++++++
src/irc/proxy/proxy.c | 22 +++++++++++++++++++++-
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index df0d7479..a5772301 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);
@@ -682,6 +684,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;
@@ -703,6 +710,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 75da112c..1cc8aebe 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -27,6 +27,12 @@
static void cmd_proxy_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,
@@ -54,11 +60,21 @@ static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item)
command_runsub("proxy", 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! */
@@ -77,7 +93,11 @@ void irc_proxy_init(void)
command_bind("proxy", NULL, (SIGNAL_FUNC) cmd_proxy);
command_bind("proxy status", NULL, (SIGNAL_FUNC) cmd_proxy_status);
- proxy_listen_init();
+ 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");
}
From ee3f059e6d895cda94bee0a2df7136108012b910 Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Wed, 25 Jun 2014 22:38:03 -0700
Subject: [PATCH 04/82] Update proxy documentation with changes
---
docs/proxy.txt | 22 ++++++++++++++++++++++
docs/signals.txt | 1 +
2 files changed, 23 insertions(+)
diff --git a/docs/proxy.txt b/docs/proxy.txt
index 41875aab..759ef1dc 100644
--- a/docs/proxy.txt
+++ b/docs/proxy.txt
@@ -12,6 +12,11 @@ In irssi, say:
/LOAD proxy
+If you want the proxy to be loaded automatically at startup, add the
+load command to ~/.irssi/startup:
+
+ echo "load proxy" >> ~/.irssi/startup
+
You really should set some password for the proxy with:
/SET irssiproxy_password secret
@@ -24,3 +29,20 @@ something like:
There we have 3 different irc networks answering in 3 ports. Note that
you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to
make it work properly.
+
+By default, the proxy binds to all available interfaces. To make it
+only listen on (for example) the loopback address:
+
+ /SET irssiproxy_bind 127.0.0.1
+
+Note that bind address changes won't take effect until the proxy is
+disabled and then reenabled.
+
+Once everything is set up, you can enable / disable the proxy:
+
+ /TOGGLE irssiproxy
+
+When the proxy is configured and running, the following command will
+show all the currently connected clients:
+
+ /PROXY status
diff --git a/docs/signals.txt b/docs/signals.txt
index f0860d3e..bd5849f1 100644
--- a/docs/signals.txt
+++ b/docs/signals.txt
@@ -220,6 +220,7 @@ notifylist.c:
proxy/listen.c:
+ "proxy client connecting", CLIENT_REC
"proxy client connected", CLIENT_REC
"proxy client disconnected", CLIENT_REC
"proxy client command", CLIENT_REC, char *args, char *data
From 178d595c96dafe36a7041864a00e1e45375dab76 Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Tue, 1 Jul 2014 21:21:03 -0700
Subject: [PATCH 05/82] Add port to proxy client struct for Perl scripts
---
src/perl/irc/Irc.xs | 1 +
1 file changed, 1 insertion(+)
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);
From bbf404b6112aac5cde9732d893e440d9bf363565 Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Mon, 15 Dec 2014 18:41:45 -0800
Subject: [PATCH 06/82] Fix whitespace
---
src/irc/proxy/listen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index a5772301..a1cda250 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -368,7 +368,7 @@ 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 connecting", 1, rec);
+ 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);
From 7beffbdcc5d9ca7433f6617a652ed0b2feca3677 Mon Sep 17 00:00:00 2001
From: Hans Nielsen
Date: Tue, 24 Feb 2015 19:46:59 -0800
Subject: [PATCH 07/82] Add help files for proxy module
---
docs/help/in/proxy.in | 14 ++++++++++++++
src/irc/proxy/proxy.c | 2 ++
2 files changed, 16 insertions(+)
create mode 100644 docs/help/in/proxy.in
diff --git a/docs/help/in/proxy.in b/docs/help/in/proxy.in
new file mode 100644
index 00000000..2dc61f43
--- /dev/null
+++ b/docs/help/in/proxy.in
@@ -0,0 +1,14 @@
+
+@SYNTAX:proxy@
+
+%9Description:%9
+
+ Displays the list of clients connected to the proxy.
+
+%9Examples:%9
+
+ /PROXY
+ /PROXY STATUS
+
+%9See also:%9 LOAD PROXY, SET irssiproxy
+
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index 1cc8aebe..65c778d1 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -25,6 +25,7 @@
#include "fe-common/core/printtext.h"
+/* SYNTAX: PROXY STATUS */
static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server)
{
if (!settings_get_bool("irssiproxy")) {
@@ -50,6 +51,7 @@ static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server)
}
}
+/* SYNTAX: PROXY */
static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item)
{
if (*data == '\0') {
From 16c71cf1fbc1e7987fdde821813005b87237e951 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 15 May 2015 16:42:51 +0200
Subject: [PATCH 08/82] Implement CHANTYPES support
---
src/core/servers.h | 2 +-
src/fe-common/irc/dcc/fe-dcc-chat.c | 2 +-
src/fe-common/irc/dcc/fe-dcc-get.c | 5 +++--
src/fe-common/irc/fe-ctcp.c | 8 ++++----
src/fe-common/irc/fe-events-numeric.c | 4 ++--
src/fe-common/irc/fe-events.c | 6 +++---
src/fe-common/irc/fe-irc-channels.c | 2 +-
src/fe-common/irc/fe-irc-messages.c | 20 ++++++++++----------
src/fe-common/irc/fe-irc-queries.c | 2 +-
src/fe-common/irc/fe-modes.c | 2 +-
src/fe-common/irc/fe-netjoin.c | 2 +-
src/irc/core/bans.c | 2 +-
src/irc/core/channel-rejoin.c | 2 +-
src/irc/core/irc-channels.c | 4 ++--
src/irc/core/irc-commands.c | 2 +-
src/irc/core/irc-nicklist.c | 2 +-
src/irc/core/irc-queries.c | 4 ++--
src/irc/core/irc-servers.c | 21 ++++++++++++++-------
src/irc/core/irc.h | 6 ------
src/irc/core/modes.c | 6 +++---
src/irc/dcc/dcc-autoget.c | 2 +-
src/irc/flood/flood.c | 4 ++--
src/irc/proxy/listen.c | 2 +-
23 files changed, 57 insertions(+), 55 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-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..ad5e7559 100644
--- a/src/fe-common/irc/fe-events.c
+++ b/src/fe-common/irc/fe-events.c
@@ -52,15 +52,15 @@ 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 (*target == '@' && server_ischannel(SERVER(server), &target[1])) {
/* Hybrid 6 feature, send msg to all ops in channel */
recoded = recode_in(SERVER(server), msg, target+1);
signal_emit("message irc op_public", 5,
server, recoded, nick, addr,
get_visible_target(server, target+1));
} 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..9129e451 100644
--- a/src/fe-common/irc/fe-irc-channels.c
+++ b/src/fe-common/irc/fe-irc-channels.c
@@ -46,7 +46,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-messages.c b/src/fe-common/irc/fe-irc-messages.c
index 94d1ad4a..780c0b7e 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -57,7 +57,7 @@ static const char *skip_target(IRC_SERVER_REC *server, const char *target)
break;
};
- if(ischannel(target[i]))
+ if(server_ischannel(SERVER(server), &target[i]))
target += i;
return target;
@@ -136,7 +136,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
oldtarget = target;
target = skip_target(IRC_SERVER(server), target);
- if (ischannel(*target))
+ if (server_ischannel(SERVER(server), target))
item = irc_channel_find(server, target);
else
item = irc_query_find(server, target);
@@ -146,7 +146,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);
@@ -166,7 +166,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
target = skip_target(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 +175,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 +185,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 */
@@ -245,16 +245,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);
@@ -283,7 +283,7 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd,
oldtarget = target;
target = skip_target(server, target);
- printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
+ 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/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 d7122eae..c04c4318 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -71,13 +71,20 @@ static int isnickflag_func(SERVER_REC *server, char flag)
static int ischannel_func(SERVER_REC *server, const char *data)
{
- if (*data == '@') {
- /* @#channel, @+#channel */
- data++;
- if (*data == '+' && ischannel(data[1]))
- return 1;
- }
- return ischannel(*data);
+ IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
+ char *chantypes;
+
+ chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes");
+ if (chantypes == NULL)
+ chantypes = "#&!+"; /* normal, local, secure, modeless */
+
+ /* @#channel, @+#channel */
+ if (data[0] == '@' && data[1] == '+')
+ data += 2;
+ else if (data[0] == '@')
+ data += 1;
+
+ return strchr(chantypes, *data) != NULL;
}
static char **split_line(const SERVER_REC *server, const char *line,
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 4c3bcf68..c334e698 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -262,7 +262,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) {
From e480b9b16579a0434dba61c58dec362511062cb8 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 31 May 2015 15:30:21 +0200
Subject: [PATCH 09/82] Improve ischannel_func (#253)
The function now skips all the leading characters that are in the STATUSMSG. If
the server didn't send the STATUSMSG option then it's assumed to be "@+" for
compatibility with bahamut 2.4 (sic).
---
src/irc/core/irc-servers.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index c04c4318..31ba397b 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -72,17 +72,17 @@ static int isnickflag_func(SERVER_REC *server, char flag)
static int ischannel_func(SERVER_REC *server, const char *data)
{
IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
- char *chantypes;
+ 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 = "@+";
- /* @#channel, @+#channel */
- if (data[0] == '@' && data[1] == '+')
- data += 2;
- else if (data[0] == '@')
- data += 1;
+ while (strchr(statusmsg, *data) != NULL)
+ data++;
return strchr(chantypes, *data) != NULL;
}
From a47f45b5b7438209177d76f3efde559e61e5bdb7 Mon Sep 17 00:00:00 2001
From: dequis
Date: Sun, 14 Jun 2015 11:57:11 -0300
Subject: [PATCH 10/82] Rename /proxy command to /irssiproxy for clarity
---
docs/help/in/irssiproxy.in | 14 ++++++++++++++
docs/help/in/proxy.in | 14 --------------
docs/proxy.txt | 2 +-
src/irc/proxy/proxy.c | 16 ++++++++--------
4 files changed, 23 insertions(+), 23 deletions(-)
create mode 100644 docs/help/in/irssiproxy.in
delete mode 100644 docs/help/in/proxy.in
diff --git a/docs/help/in/irssiproxy.in b/docs/help/in/irssiproxy.in
new file mode 100644
index 00000000..79d75b91
--- /dev/null
+++ b/docs/help/in/irssiproxy.in
@@ -0,0 +1,14 @@
+
+@SYNTAX:irssiproxy@
+
+%9Description:%9
+
+ Displays the list of clients connected to irssiproxy.
+
+%9Examples:%9
+
+ /IRSSIPROXY
+ /IRSSIPROXY STATUS
+
+%9See also:%9 LOAD PROXY, SET irssiproxy
+
diff --git a/docs/help/in/proxy.in b/docs/help/in/proxy.in
deleted file mode 100644
index 2dc61f43..00000000
--- a/docs/help/in/proxy.in
+++ /dev/null
@@ -1,14 +0,0 @@
-
-@SYNTAX:proxy@
-
-%9Description:%9
-
- Displays the list of clients connected to the proxy.
-
-%9Examples:%9
-
- /PROXY
- /PROXY STATUS
-
-%9See also:%9 LOAD PROXY, SET irssiproxy
-
diff --git a/docs/proxy.txt b/docs/proxy.txt
index 759ef1dc..e6360a82 100644
--- a/docs/proxy.txt
+++ b/docs/proxy.txt
@@ -45,4 +45,4 @@ Once everything is set up, you can enable / disable the proxy:
When the proxy is configured and running, the following command will
show all the currently connected clients:
- /PROXY status
+ /IRSSIPROXY status
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index 65c778d1..ce79e2b7 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -25,8 +25,8 @@
#include "fe-common/core/printtext.h"
-/* SYNTAX: PROXY STATUS */
-static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server)
+/* 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,
@@ -51,15 +51,15 @@ static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server)
}
}
-/* SYNTAX: PROXY */
-static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item)
+/* SYNTAX: IRSSIPROXY */
+static void cmd_irssiproxy(const char *data, IRC_SERVER_REC *server, void *item)
{
if (*data == '\0') {
- cmd_proxy_status(data, server);
+ cmd_irssiproxy_status(data, server);
return;
}
- command_runsub("proxy", data, server, item);
+ command_runsub("irssiproxy", data, server, item);
}
static void irc_proxy_setup_changed(void)
@@ -92,8 +92,8 @@ void irc_proxy_init(void)
"... to set them.");
}
- command_bind("proxy", NULL, (SIGNAL_FUNC) cmd_proxy);
- command_bind("proxy status", NULL, (SIGNAL_FUNC) cmd_proxy_status);
+ 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);
From 51496cd09f5d2f2da0a4ae678663c66e2ceae17c Mon Sep 17 00:00:00 2001
From: dequis
Date: Sun, 14 Jun 2015 16:41:52 -0300
Subject: [PATCH 11/82] Fix 'address already in use' when changing
irssiproxy_ports
When changing the value of irssiproxy_ports to use a different network
name in a port that was already bound (so like changing from asd=6667 to
sdf=6667) it would throw "address already in use".
This fixes it by delaying the add_listen() calls after all the
remove_listen() were called.
---
src/irc/proxy/listen.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index a560801d..dc354c30 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -642,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;
@@ -661,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)
From 8e71d6ec739ec74fbb5c712e9341d4319a17d8f5 Mon Sep 17 00:00:00 2001
From: kyak
Date: Sun, 19 Jul 2015 09:45:50 +0300
Subject: [PATCH 12/82] Add expandos for hostname
See http://bugs.irssi.org/index.php?do=details&task_id=829
---
src/irc/core/irc-expandos.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index 5d2de503..cc46ece5 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -76,6 +76,29 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
return g_strconcat(username, "@", hostname, NULL);;
}
+/* your hostname address (host) */
+static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
+{
+ IRC_SERVER_REC *ircserver;
+ char hostname[100];
+ char **list;
+
+ ircserver = IRC_SERVER(server);
+
+ /* prefer the _real_ /userhost reply */
+ if (ircserver != NULL && ircserver->userhost != NULL) {
+ list = g_strsplit(ircserver->userhost, "@", -1);
+ return list[1];
+ }
+
+ /* haven't received userhost reply yet. guess something */
+ *free_ret = TRUE;
+
+ if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
+ strcpy(hostname, "??");
+ return g_strconcat(hostname, NULL);
+}
+
/* user mode in active server */
static char *expando_usermode(SERVER_REC *server, void *item, int *free_ret)
{
@@ -136,6 +159,9 @@ void irc_expandos_init(void)
expando_create("X", expando_userhost,
"window changed", EXPANDO_ARG_NONE,
"window server changed", EXPANDO_ARG_WINDOW, NULL);
+ expando_create("x", expando_hostname,
+ "window changed", EXPANDO_ARG_NONE,
+ "window server changed", EXPANDO_ARG_WINDOW, NULL);
expando_create("usermode", expando_usermode,
"window changed", EXPANDO_ARG_NONE,
"window server changed", EXPANDO_ARG_WINDOW,
@@ -164,6 +190,7 @@ void irc_expandos_deinit(void)
expando_destroy("H", expando_server_numeric);
expando_destroy("S", expando_servername);
expando_destroy("X", expando_userhost);
+ expando_destroy("x", expando_hostname);
expando_destroy("usermode", expando_usermode);
expando_destroy("cumode", expando_cumode);
From 0435331912f5d975c4cbef9b018bb89c07e610eb Mon Sep 17 00:00:00 2001
From: kyak
Date: Wed, 26 Aug 2015 09:34:48 +0300
Subject: [PATCH 13/82] Clean up in hostname expando before return
Clean up the vector resulting from g_strsplit before
returning from expando_hostname(). Also, use g_strdup()
instead of g_strconcat() to return the pointer to hostname.
---
src/irc/core/irc-expandos.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index cc46ece5..f26c9699 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -82,13 +82,16 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
IRC_SERVER_REC *ircserver;
char hostname[100];
char **list;
+ char *hostname_split;
ircserver = IRC_SERVER(server);
/* prefer the _real_ /userhost reply */
if (ircserver != NULL && ircserver->userhost != NULL) {
list = g_strsplit(ircserver->userhost, "@", -1);
- return list[1];
+ hostname_split = g_strdup(list[1]);
+ g_strfreev(list);
+ return hostname_split;
}
/* haven't received userhost reply yet. guess something */
@@ -96,7 +99,7 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
strcpy(hostname, "??");
- return g_strconcat(hostname, NULL);
+ return g_strdup(hostname);
}
/* user mode in active server */
From 19760679eb141baf3bff2110ee03aec90c653a2a Mon Sep 17 00:00:00 2001
From: kyak
Date: Sat, 29 Aug 2015 15:29:57 +0300
Subject: [PATCH 14/82] In expando_hostname, set *free_ret to TRUE
*free_ret must be set to TRUE in both cases, since we return
some newly initialised memory
---
src/irc/core/irc-expandos.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index f26c9699..4aa50c52 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -86,6 +86,8 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
ircserver = IRC_SERVER(server);
+ *free_ret = TRUE;
+
/* prefer the _real_ /userhost reply */
if (ircserver != NULL && ircserver->userhost != NULL) {
list = g_strsplit(ircserver->userhost, "@", -1);
@@ -95,8 +97,6 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
}
/* haven't received userhost reply yet. guess something */
- *free_ret = TRUE;
-
if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
strcpy(hostname, "??");
return g_strdup(hostname);
From b7d82ecdcee3224ca5280977d0ffd7b5e0fb07d2 Mon Sep 17 00:00:00 2001
From: kyak
Date: Sat, 29 Aug 2015 15:32:22 +0300
Subject: [PATCH 15/82] Use "(none)" as fallback for hostname and userhost
expandos
Use "(none)" instead of "??" for hostname and userhost expandos
when these can't be reliably detected.
---
src/irc/core/irc-expandos.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index 4aa50c52..df0326a2 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -72,7 +72,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
username = ircserver->connrec->username;
if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
- strcpy(hostname, "??");
+ strcpy(hostname, "(none)");
return g_strconcat(username, "@", hostname, NULL);;
}
@@ -98,7 +98,7 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
/* haven't received userhost reply yet. guess something */
if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
- strcpy(hostname, "??");
+ strcpy(hostname, "(none)");
return g_strdup(hostname);
}
From b065f2a0112fe733878c17375d16cf12a3457e09 Mon Sep 17 00:00:00 2001
From: kyak
Date: Sat, 29 Aug 2015 15:36:05 +0300
Subject: [PATCH 16/82] Use HOST_NAME_MAX for userhost and hostname expandos
Use HOST_NAME_MAX instead of hardcoded 100 for userhost
and hostname expandos.
---
src/irc/core/irc-expandos.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index df0326a2..9604c625 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -56,7 +56,8 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
{
IRC_SERVER_REC *ircserver;
const char *username;
- char hostname[100];
+ char hostname[HOST_NAME_MAX];
+
ircserver = IRC_SERVER(server);
@@ -80,7 +81,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
{
IRC_SERVER_REC *ircserver;
- char hostname[100];
+ char hostname[HOST_NAME_MAX];
char **list;
char *hostname_split;
From 2f9cca8ec6e491759583c1de3bd74fbef0d6e2a1 Mon Sep 17 00:00:00 2001
From: kyak
Date: Sat, 29 Aug 2015 15:40:17 +0300
Subject: [PATCH 17/82] Remove extra line break
How did this extra break cripple in here?
---
src/irc/core/irc-expandos.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index 9604c625..5d8150f0 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -58,7 +58,6 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
const char *username;
char hostname[HOST_NAME_MAX];
-
ircserver = IRC_SERVER(server);
/* prefer the _real_ /userhost reply */
From 35d30c19a1fa5413a26a04885ed6cb05af4e2565 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 2 Sep 2015 20:24:47 +0200
Subject: [PATCH 18/82] Whitespace fix
---
src/irc/proxy/listen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index c334e698..ebbbdcfa 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -262,7 +262,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(server_ischannel(SERVER(client->server), 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) {
From 57d645f24603e8c7d2cfe7098b3dbb1359cd8d22 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 2 Sep 2015 21:50:40 +0200
Subject: [PATCH 19/82] Introduce some more chantypes awareness
---
src/fe-common/irc/fe-events.c | 11 ++++--
src/fe-common/irc/fe-irc-messages.c | 57 +++++++++++++++++++----------
2 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c
index ad5e7559..7f5a8c26 100644
--- a/src/fe-common/irc/fe-events.c
+++ b/src/fe-common/irc/fe-events.c
@@ -42,6 +42,9 @@
#include "fe-windows.h"
#include "fe-irc-server.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);
+
static void event_privmsg(IRC_SERVER_REC *server, const char *data,
const char *nick, const char *addr)
{
@@ -52,12 +55,14 @@ 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 == '@' && server_ischannel(SERVER(server), &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, server_ischannel(SERVER(server), target) ? target : nick);
signal_emit(server_ischannel(SERVER(server), target) ?
diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c
index 780c0b7e..e8cdb2c4 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -37,28 +37,47 @@
#include "fe-queries.h"
#include "window-items.h"
-static const char *skip_target(IRC_SERVER_REC *server, const char *target)
+int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target)
{
- int i = 0;
- const char *val, *chars;
+ 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) */
- val = g_hash_table_lookup(server->isupport, "STATUSMSG");
- if (val == NULL && *target != '@')
+ if (statusmsg == NULL && *target != '@')
return target;
- chars = val ? val : "@+";
- for(i = 0; target[i] != '\0'; i++) {
- if (strchr(chars, target[i]) == NULL)
- break;
- };
- if(server_ischannel(SERVER(server), &target[i]))
- target += i;
+ if (statusmsg == NULL)
+ statusmsg = "@+";
+
+ /* Strip the leading statusmsg prefixes */
+ while (strchr(statusmsg, *target) != NULL) {
+ target++;
+ }
return target;
}
@@ -72,7 +91,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,7 +154,7 @@ 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);
+ target = fe_channel_skip_prefix(IRC_SERVER(server), target);
if (server_ischannel(SERVER(server), target))
item = irc_channel_find(server, target);
else
@@ -163,7 +182,7 @@ 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 |
(server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
@@ -219,7 +238,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 +251,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 */
@@ -270,7 +289,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,7 +301,7 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd,
const char *oldtarget;
oldtarget = target;
- target = skip_target(server, target);
+ 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);
}
From 21c1e4e9f80409b81cb3b8243c904ccf74d8d529 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 2 Sep 2015 22:40:10 +0200
Subject: [PATCH 20/82] Fix two minor issues outlined in the PR#222
irc-cap.c has now a licence header.
A minor style fix in misc.c
---
src/core/misc.c | 2 +-
src/irc/core/irc-cap.c | 19 +++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index 395e47ad..88c27255 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -215,7 +215,7 @@ void gslist_free_full (GSList *list, GDestroyNotify free_func)
{
GSList *tmp;
- if (!list)
+ if (list == NULL)
return;
for (tmp = list; tmp != NULL; tmp = tmp->next)
diff --git a/src/irc/core/irc-cap.c b/src/irc/core/irc-cap.c
index c5bf4e67..cd3ae677 100644
--- a/src/irc/core/irc-cap.c
+++ b/src/irc/core/irc-cap.c
@@ -1,3 +1,22 @@
+/* irc-cap.c : irssi
+
+ Copyright (C) 2015 The Lemon Man
+
+ 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 Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
#include "module.h"
#include "signals.h"
#include "misc.h"
From b5b73cb471e5dff6f8c872071c7cb8678e4142ea Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 6 Sep 2015 15:47:08 +0200
Subject: [PATCH 21/82] Send smkx/rmkx sequence at terminal init
Enter the "application" mode when setting up the terminal, this improves the
compatiblity with the standards; as a side effect now DEL key works ootb when
irssi is run in the suckless's st terminal.
---
src/fe-text/terminfo-core.c | 107 ++++++++++++++++++++----------------
src/fe-text/terminfo-core.h | 4 ++
2 files changed, 63 insertions(+), 48 deletions(-)
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index 0516cc5f..6339e6f4 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -50,62 +50,66 @@ TERM_REC *current_term;
/* Define only what we might need */
static TERMINFO_REC tcaps[] = {
- /* Terminal size */
- { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) },
- { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) },
+ /* Terminal size */
+ { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) },
+ { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) },
- /* Cursor movement */
- { "smcup", "ti", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smcup) },
- { "rmcup", "te", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmcup) },
- { "cup", "cm", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cup) },
- { "hpa", "ch", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_hpa) },
- { "vpa", "vh", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_vpa) },
- { "cub1", "le", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cub1) },
- { "cuf1", "nd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cuf1) },
- { "civis", "vi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_civis) },
- { "cnorm", "ve", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cnorm) },
+ /* Cursor movement */
+ { "smcup", "ti", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smcup) },
+ { "rmcup", "te", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmcup) },
+ { "cup", "cm", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cup) },
+ { "hpa", "ch", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_hpa) },
+ { "vpa", "vh", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_vpa) },
+ { "cub1", "le", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cub1) },
+ { "cuf1", "nd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cuf1) },
+ { "civis", "vi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_civis) },
+ { "cnorm", "ve", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cnorm) },
- /* Scrolling */
- { "csr", "cs", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_csr) },
- { "wind", "wi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_wind) },
- { "ri", "sr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ri) },
- { "rin", "SR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rin) },
- { "ind", "sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ind) },
- { "indn", "SF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_indn) },
- { "il", "AL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il) },
- { "il1", "al", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il1) },
- { "dl", "DL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl) },
- { "dl1", "dl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl1) },
+ /* Scrolling */
+ { "csr", "cs", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_csr) },
+ { "wind", "wi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_wind) },
+ { "ri", "sr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ri) },
+ { "rin", "SR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rin) },
+ { "ind", "sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ind) },
+ { "indn", "SF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_indn) },
+ { "il", "AL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il) },
+ { "il1", "al", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il1) },
+ { "dl", "DL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl) },
+ { "dl1", "dl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl1) },
/* Clearing screen */
- { "clear", "cl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_clear) },
- { "ed", "cd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ed) },
+ { "clear", "cl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_clear) },
+ { "ed", "cd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ed) },
- /* Clearing to end of line */
- { "el", "ce", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_el) },
+ /* Clearing to end of line */
+ { "el", "ce", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_el) },
- /* Repeating character */
- { "rep", "rp", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rep) },
+ /* Repeating character */
+ { "rep", "rp", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rep) },
/* Colors */
- { "colors", "Co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, TI_colors) },
- { "sgr0", "me", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sgr0) },
- { "smul", "us", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smul) },
- { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) },
- { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) },
- { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) },
- { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) },
- { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) },
- { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) },
- { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) },
- { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) },
- { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) },
- { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) },
- { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) },
- { "setb", "Sb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setb) },
+ { "colors", "Co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, TI_colors) },
+ { "sgr0", "me", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sgr0) },
+ { "smul", "us", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smul) },
+ { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) },
+ { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) },
+ { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) },
+ { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) },
+ { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) },
+ { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) },
+ { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) },
+ { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) },
+ { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) },
+ { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) },
+ { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) },
+ { "setb", "Sb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setb) },
- /* Beep */
- { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) },
+ /* Beep */
+ { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) },
+
+ /* Keyboard-transmit mode */
+ { "smkx", "ks", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smkx) },
+ { "rmkx", "ke", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmkx) },
};
/* Move cursor (cursor_address / cup) */
@@ -523,7 +527,11 @@ static void terminfo_input_deinit(TERM_REC *term)
void terminfo_cont(TERM_REC *term)
{
if (term->TI_smcup)
- tput(tparm(term->TI_smcup));
+ tput(tparm(term->TI_smcup));
+
+ if (term->TI_smkx)
+ tput(tparm(term->TI_smkx));
+
terminfo_input_init(term);
}
@@ -538,6 +546,9 @@ void terminfo_stop(TERM_REC *term)
if (term->TI_rmcup)
tput(tparm(term->TI_rmcup));
+ if (term->TI_rmkx)
+ tput(tparm(term->TI_rmkx));
+
/* reset input settings */
terminfo_input_deinit(term);
fflush(term->out);
diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h
index 6ab4637d..21398791 100644
--- a/src/fe-text/terminfo-core.h
+++ b/src/fe-text/terminfo-core.h
@@ -88,6 +88,10 @@ struct _TERM_REC {
/* Beep */
char *TI_bel;
+
+ /* Keyboard-transmit mode */
+ const char *TI_smkx;
+ const char *TI_rmkx;
};
extern TERM_REC *current_term;
From 4346c2a6d479b9c4d94fabc35ade324fdbe0e0d0 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 9 Sep 2015 23:55:00 +0200
Subject: [PATCH 22/82] Move the function prototypes in a separate header
---
src/fe-common/irc/fe-common-irc.c | 4 +--
src/fe-common/irc/fe-events.c | 3 --
src/fe-common/irc/fe-irc-channels.c | 47 ++++++++++++++++++++++++++++-
src/fe-common/irc/fe-irc-channels.h | 10 ++++++
src/fe-common/irc/fe-irc-messages.c | 45 ---------------------------
5 files changed, 57 insertions(+), 52 deletions(-)
create mode 100644 src/fe-common/irc/fe-irc-channels.h
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-events.c b/src/fe-common/irc/fe-events.c
index 7f5a8c26..068ee543 100644
--- a/src/fe-common/irc/fe-events.c
+++ b/src/fe-common/irc/fe-events.c
@@ -42,9 +42,6 @@
#include "fe-windows.h"
#include "fe-irc-server.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);
-
static void event_privmsg(IRC_SERVER_REC *server, const char *data,
const char *nick, const char *addr)
{
diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c
index 9129e451..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 && server_ischannel(server, *from) && server_ischannel(server, *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 e8cdb2c4..b2736a2c 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -37,51 +37,6 @@
#include "fe-queries.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_message_own_public(SERVER_REC *server, const char *msg,
const char *target, const char *origtarget)
{
From b8d3301d34f383f039071214872570385de1bb59 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Thu, 10 Sep 2015 01:02:44 +0200
Subject: [PATCH 23/82] SASL support
The only supported methods are PLAIN and EXTERNAL, the latter is untested as of
now.
The code gets the values from the keys named sasl_{mechanism,username,password}
specified for each chatnet.
---
src/core/server-setup-rec.h | 3 +
src/irc/core/Makefile.am | 2 +
src/irc/core/irc-chatnets.c | 6 +-
src/irc/core/irc-chatnets.h | 9 ++-
src/irc/core/irc-core.c | 5 +-
src/irc/core/irc-servers-setup.c | 24 ++++++
src/irc/core/irc-servers.c | 4 +
src/irc/core/irc-servers.h | 4 +
src/irc/core/sasl.c | 134 +++++++++++++++++++++++++++++++
src/irc/core/sasl.h | 14 ++++
10 files changed, 200 insertions(+), 5 deletions(-)
create mode 100644 src/irc/core/sasl.c
create mode 100644 src/irc/core/sasl.h
diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h
index ecdde3f3..2c9614c7 100644
--- a/src/core/server-setup-rec.h
+++ b/src/core/server-setup-rec.h
@@ -8,6 +8,9 @@ char *address;
int port;
char *password;
+int sasl_mechanism;
+char *sasl_password;
+
char *ssl_cert;
char *ssl_pkey;
char *ssl_pass;
diff --git a/src/irc/core/Makefile.am b/src/irc/core/Makefile.am
index 7d885d20..20caaeb1 100644
--- a/src/irc/core/Makefile.am
+++ b/src/irc/core/Makefile.am
@@ -27,6 +27,7 @@ libirc_core_a_SOURCES = \
irc-servers-setup.c \
irc-session.c \
irc-cap.c \
+ sasl.c \
lag.c \
massjoin.c \
modes.c \
@@ -50,6 +51,7 @@ pkginc_irc_core_HEADERS = \
irc-servers.h \
irc-servers-setup.h \
irc-cap.h \
+ sasl.h \
modes.h \
mode-lists.h \
module.h \
diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index d757bf8d..cfb7deec 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -48,6 +48,10 @@ static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
rec->max_msgs = config_node_get_int(node, "max_msgs", 0);
rec->max_modes = config_node_get_int(node, "max_modes", 0);
rec->max_whois = config_node_get_int(node, "max_whois", 0);
+
+ rec->sasl_mechanism = config_node_get_str(node, "sasl_mechanism", NULL);
+ rec->sasl_username = config_node_get_str(node, "sasl_username", NULL);
+ rec->sasl_password = config_node_get_str(node, "sasl_password", NULL);
}
static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
@@ -78,7 +82,7 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec)
{
if (IS_IRC_CHATNET(rec))
- g_free(rec->usermode);
+ g_free(rec->usermode);
}
diff --git a/src/irc/core/irc-chatnets.h b/src/irc/core/irc-chatnets.h
index 22da90c5..2bb10fa9 100644
--- a/src/irc/core/irc-chatnets.h
+++ b/src/irc/core/irc-chatnets.h
@@ -17,12 +17,15 @@
struct _IRC_CHATNET_REC {
#include "chatnet-rec.h"
- char *usermode;
+ char *usermode;
+
+ char *sasl_mechanism;
+ char *sasl_username;
+ char *sasl_password;
int max_cmds_at_once;
int cmd_queue_speed;
- int max_query_chans; /* when syncing, max. number of channels to
- put in one MODE/WHO command */
+ int max_query_chans; /* when syncing, max. number of channels to put in one MODE/WHO command */
/* max. number of kicks/msgs/mode/whois per command */
int max_kicks, max_msgs, max_modes, max_whois;
diff --git a/src/irc/core/irc-core.c b/src/irc/core/irc-core.c
index e3ceeeef..a9221e02 100644
--- a/src/irc/core/irc-core.c
+++ b/src/irc/core/irc-core.c
@@ -27,6 +27,7 @@
#include "irc-channels.h"
#include "irc-queries.h"
#include "irc-cap.h"
+#include "sasl.h"
#include "irc-servers-setup.h"
#include "channels-setup.h"
@@ -119,6 +120,7 @@ void irc_core_init(void)
netsplit_init();
irc_expandos_init();
cap_init();
+ sasl_init();
settings_check();
module_register("core", "irc");
@@ -128,6 +130,7 @@ void irc_core_deinit(void)
{
signal_emit("chat protocol deinit", 1, chat_protocol_find("IRC"));
+ sasl_deinit();
cap_deinit();
irc_expandos_deinit();
netsplit_deinit();
@@ -140,7 +143,7 @@ void irc_core_deinit(void)
irc_irc_deinit();
irc_servers_deinit();
irc_chatnets_deinit();
- irc_session_deinit();
+ irc_session_deinit();
chat_protocol_unregister("IRC");
}
diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index 5659991b..9a9a8347 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -28,6 +28,7 @@
#include "irc-chatnets.h"
#include "irc-servers-setup.h"
#include "irc-servers.h"
+#include "sasl.h"
/* Fill information to connection from server setup record */
static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
@@ -79,6 +80,29 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
conn->cmd_queue_speed = ircnet->cmd_queue_speed;
if (ircnet->max_query_chans > 0)
conn->max_query_chans = ircnet->max_query_chans;
+
+ /* Validate the SASL parameters filled by sig_chatnet_read() */
+ conn->sasl_mechanism = SASL_MECHANISM_NONE;
+
+ if (ircnet->sasl_mechanism != NULL) {
+ if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "plain")) {
+ /* The PLAIN method needs both the username and the password */
+ if (ircnet->sasl_username != NULL && *ircnet->sasl_username &&
+ ircnet->sasl_password != NULL && *ircnet->sasl_password) {
+ conn->sasl_mechanism = SASL_MECHANISM_PLAIN;
+ conn->sasl_username = ircnet->sasl_username;
+ conn->sasl_password = ircnet->sasl_password;
+ } else
+ g_warning("The fields sasl_username and sasl_password are either undefined or empty");
+ }
+ else if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "external")) {
+ conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL;
+ conn->sasl_username = NULL;
+ conn->sasl_password = NULL;
+ }
+ else
+ g_warning("Unsupported SASL mechanism \"%s\" selected", ircnet->sasl_mechanism);
+ }
}
static void init_userinfo(void)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index e9920d91..ad4d09cc 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -33,6 +33,7 @@
#include "irc-servers-setup.h"
#include "irc-servers.h"
#include "irc-cap.h"
+#include "sasl.h"
#include "channel-rejoin.h"
#include "servers-idle.h"
#include "servers-reconnect.h"
@@ -215,6 +216,9 @@ static void server_init(IRC_SERVER_REC *server)
g_free(cmd);
}
+ if (conn->sasl_mechanism != SASL_MECHANISM_NONE)
+ cap_toggle(server, "sasl", TRUE);
+
irc_send_cmd_now(server, "CAP LS");
if (conn->password != NULL && *conn->password != '\0') {
diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h
index f809fab5..41c4b9c2 100644
--- a/src/irc/core/irc-servers.h
+++ b/src/irc/core/irc-servers.h
@@ -27,6 +27,10 @@ struct _IRC_SERVER_CONNECT_REC {
char *usermode;
char *alternate_nick;
+ int sasl_mechanism;
+ char *sasl_username;
+ char *sasl_password;
+
int max_cmds_at_once;
int cmd_queue_speed;
int max_query_chans;
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
new file mode 100644
index 00000000..8bffc3d9
--- /dev/null
+++ b/src/irc/core/sasl.c
@@ -0,0 +1,134 @@
+#include "module.h"
+#include "misc.h"
+#include "settings.h"
+
+#include "irc-cap.h"
+#include "irc-servers.h"
+#include "sasl.h"
+
+#define SASL_TIMEOUT (20 * 1000) // ms
+
+static gboolean sasl_timeout (IRC_SERVER_REC *server)
+{
+ /* The authentication timed out, we can't do much beside terminating it */
+ g_critical("The authentication timed out, try increasing the timeout and check your connection "
+ "to the network.");
+ irc_send_cmd_now(server, "AUTHENTICATE *");
+ cap_finish_negotiation(server);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *from)
+{
+ IRC_SERVER_CONNECT_REC *conn;
+
+ conn = server->connrec;
+
+ switch (conn->sasl_mechanism) {
+ case SASL_MECHANISM_PLAIN:
+ irc_send_cmd_now(server, "AUTHENTICATE PLAIN");
+ break;
+
+ case SASL_MECHANISM_EXTERNAL:
+ irc_send_cmd_now(server, "AUTHENTICATE EXTERNAL");
+ break;
+ }
+ server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server);
+}
+
+static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from)
+{
+ /* Stop any pending timeout, if any */
+ g_source_remove(server->sasl_timeout);
+
+ g_critical("Authentication failed, make sure your credentials are correct and that the mechanism "
+ "you have selected is supported by this server.");
+
+ /* Terminate the negotiation */
+ cap_finish_negotiation(server);
+}
+
+static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from)
+{
+ g_source_remove(server->sasl_timeout);
+
+ /* We're already authenticated, do nothing */
+ cap_finish_negotiation(server);
+}
+
+static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from)
+{
+ g_source_remove(server->sasl_timeout);
+
+ /* The authentication succeeded, time to finish the CAP negotiation */
+ g_warning("SASL authentication succeeded");
+ cap_finish_negotiation(server);
+}
+
+static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *from)
+{
+ IRC_SERVER_CONNECT_REC *conn;
+ GString *req;
+ char *enc_req;
+
+ conn = server->connrec;
+
+ /* Stop the timer */
+ g_source_remove(server->sasl_timeout);
+
+ switch (conn->sasl_mechanism) {
+ case SASL_MECHANISM_PLAIN:
+ /* At this point we assume that conn->{username, password} are non-NULL.
+ * The PLAIN mechanism expects a NULL-separated string composed by the authorization identity, the
+ * authentication identity and the password.
+ * The authorization identity field is optional and can be omitted, the server will derive the
+ * identity by looking at the credentials provided.
+ * The whole request is then encoded in base64. */
+
+ req = g_string_new(NULL);
+
+ g_string_append_c(req, '\0');
+ g_string_append(req, conn->sasl_username);
+ g_string_append_c(req, '\0');
+ g_string_append(req, conn->sasl_password);
+
+ enc_req = g_base64_encode((const guchar *)req->str, req->len);
+
+ irc_send_cmdv(server, "AUTHENTICATE %s", enc_req);
+
+ g_free(enc_req);
+ g_string_free(req, TRUE);
+ break;
+
+ case SASL_MECHANISM_EXTERNAL:
+ /* Empty response */
+ irc_send_cmdv(server, "+");
+ break;
+ }
+
+ /* We expect a response within a reasonable time */
+ server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server);
+}
+
+void sasl_init(void)
+{
+ signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
+ signal_add_first("event authenticate", (SIGNAL_FUNC) sasl_step);
+ signal_add_first("event 900", (SIGNAL_FUNC) sasl_success);
+ signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail);
+ signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail);
+ signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail);
+ signal_add_first("event 907", (SIGNAL_FUNC) sasl_already);
+}
+
+void sasl_deinit(void)
+{
+ signal_remove("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
+ signal_remove("event authenticate", (SIGNAL_FUNC) sasl_step);
+ signal_remove("event 900", (SIGNAL_FUNC) sasl_success);
+ signal_remove("event 902", (SIGNAL_FUNC) sasl_fail);
+ signal_remove("event 904", (SIGNAL_FUNC) sasl_fail);
+ signal_remove("event 905", (SIGNAL_FUNC) sasl_fail);
+ signal_remove("event 907", (SIGNAL_FUNC) sasl_already);
+}
diff --git a/src/irc/core/sasl.h b/src/irc/core/sasl.h
new file mode 100644
index 00000000..fcf87e16
--- /dev/null
+++ b/src/irc/core/sasl.h
@@ -0,0 +1,14 @@
+#ifndef __SASL_H
+#define __SASL_H
+
+enum {
+ SASL_MECHANISM_NONE = 0,
+ SASL_MECHANISM_PLAIN,
+ SASL_MECHANISM_EXTERNAL,
+ SASL_MECHANISM_MAX
+};
+
+void sasl_init(void);
+void sasl_deinit(void);
+
+#endif
From c90c7deac37bea6754c9c2715230429fd49e8e81 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 00:58:01 +0200
Subject: [PATCH 24/82] Address all the points outlined in the first review
Replace G_SOURCE_REMOVE with FALSE for the compatibility sake.
Zero the timeout id after g_source_remove and when exipred.
Save the sasl_* options in sig_chatnet_saved().
---
src/irc/core/irc-chatnets.c | 9 ++++++++-
src/irc/core/sasl.c | 24 +++++++++++++++++++-----
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index cfb7deec..b9b221b8 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -60,7 +60,7 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
return;
if (rec->usermode != NULL)
- iconfig_node_set_str(node, "usermode", rec->usermode);
+ iconfig_node_set_str(node, "usermode", rec->usermode);
if (rec->max_cmds_at_once > 0)
iconfig_node_set_int(node, "cmdmax", rec->max_cmds_at_once);
@@ -77,6 +77,13 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
iconfig_node_set_int(node, "max_modes", rec->max_modes);
if (rec->max_whois > 0)
iconfig_node_set_int(node, "max_whois", rec->max_whois);
+
+ if (rec->sasl_mechanism != NULL)
+ iconfig_node_set_str(node, "sasl_mechanism", rec->sasl_mechanism);
+ if (rec->sasl_username != NULL)
+ iconfig_node_set_str(node, "sasl_username", rec->sasl_username);
+ if (rec->sasl_password != NULL)
+ iconfig_node_set_str(node, "sasl_password", rec->sasl_password);
}
static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 8bffc3d9..4b221176 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -16,7 +16,9 @@ static gboolean sasl_timeout (IRC_SERVER_REC *server)
irc_send_cmd_now(server, "AUTHENTICATE *");
cap_finish_negotiation(server);
- return G_SOURCE_REMOVE;
+ server->sasl_timeout = -1;
+
+ return FALSE;
}
static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *from)
@@ -40,7 +42,10 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr
static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from)
{
/* Stop any pending timeout, if any */
- g_source_remove(server->sasl_timeout);
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
g_critical("Authentication failed, make sure your credentials are correct and that the mechanism "
"you have selected is supported by this server.");
@@ -51,7 +56,10 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro
static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from)
{
- g_source_remove(server->sasl_timeout);
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
/* We're already authenticated, do nothing */
cap_finish_negotiation(server);
@@ -59,7 +67,10 @@ static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *
static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from)
{
- g_source_remove(server->sasl_timeout);
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
/* The authentication succeeded, time to finish the CAP negotiation */
g_warning("SASL authentication succeeded");
@@ -75,7 +86,10 @@ static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *fro
conn = server->connrec;
/* Stop the timer */
- g_source_remove(server->sasl_timeout);
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
switch (conn->sasl_mechanism) {
case SASL_MECHANISM_PLAIN:
From 171b67441d64a85a23daf5018159f167eb7fe583 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 01:17:18 +0200
Subject: [PATCH 25/82] Replace spaces with tabs
---
src/irc/core/sasl.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 4b221176..0e343299 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -16,7 +16,7 @@ static gboolean sasl_timeout (IRC_SERVER_REC *server)
irc_send_cmd_now(server, "AUTHENTICATE *");
cap_finish_negotiation(server);
- server->sasl_timeout = -1;
+ server->sasl_timeout = -1;
return FALSE;
}
@@ -42,10 +42,10 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr
static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from)
{
/* Stop any pending timeout, if any */
- if (server->sasl_timeout != -1) {
- g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
- }
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
g_critical("Authentication failed, make sure your credentials are correct and that the mechanism "
"you have selected is supported by this server.");
@@ -56,10 +56,10 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro
static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from)
{
- if (server->sasl_timeout != -1) {
- g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
- }
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
/* We're already authenticated, do nothing */
cap_finish_negotiation(server);
@@ -67,10 +67,10 @@ static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *
static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from)
{
- if (server->sasl_timeout != -1) {
- g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
- }
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
/* The authentication succeeded, time to finish the CAP negotiation */
g_warning("SASL authentication succeeded");
@@ -86,10 +86,10 @@ static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *fro
conn = server->connrec;
/* Stop the timer */
- if (server->sasl_timeout != -1) {
- g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
- }
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
switch (conn->sasl_mechanism) {
case SASL_MECHANISM_PLAIN:
From 6645d0d38dc4627a9553235a98df4f4717a1fc6f Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 22:09:47 +0200
Subject: [PATCH 26/82] Explicitly set the authorization id during the PLAIN
handshake
On error show the user the message sent by the server.
---
src/irc/core/sasl.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 0e343299..4d52e3c0 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -47,8 +47,7 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro
server->sasl_timeout = -1;
}
- g_critical("Authentication failed, make sure your credentials are correct and that the mechanism "
- "you have selected is supported by this server.");
+ g_critical("Authentication failed with reason \"%s\"", data);
/* Terminate the negotiation */
cap_finish_negotiation(server);
@@ -93,15 +92,15 @@ static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *fro
switch (conn->sasl_mechanism) {
case SASL_MECHANISM_PLAIN:
- /* At this point we assume that conn->{username, password} are non-NULL.
+ /* At this point we assume that conn->sasl_{username, password} are non-NULL.
* The PLAIN mechanism expects a NULL-separated string composed by the authorization identity, the
* authentication identity and the password.
- * The authorization identity field is optional and can be omitted, the server will derive the
- * identity by looking at the credentials provided.
+ * The authorization identity field is explicitly set to the user provided username.
* The whole request is then encoded in base64. */
req = g_string_new(NULL);
+ g_string_append(req, conn->sasl_username);
g_string_append_c(req, '\0');
g_string_append(req, conn->sasl_username);
g_string_append_c(req, '\0');
From 55387dd93df4cff349c5696ab1bcb87801f4443f Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 22:23:38 +0200
Subject: [PATCH 27/82] Handle event 906 and 908
---
src/irc/core/sasl.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 4d52e3c0..bf13dd21 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -132,7 +132,9 @@ void sasl_init(void)
signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail);
+ signal_add_first("event 906", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 907", (SIGNAL_FUNC) sasl_already);
+ signal_add_first("event 908", (SIGNAL_FUNC) sasl_fail);
}
void sasl_deinit(void)
@@ -143,5 +145,7 @@ void sasl_deinit(void)
signal_remove("event 902", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 904", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 905", (SIGNAL_FUNC) sasl_fail);
+ signal_remove("event 906", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 907", (SIGNAL_FUNC) sasl_already);
+ signal_remove("event 908", (SIGNAL_FUNC) sasl_fail);
}
From 1f114d75c6db16726bcb930044b7312e4c851eaa Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 23:17:46 +0200
Subject: [PATCH 28/82] Consider the SASL handshake successful on 903
---
src/irc/core/sasl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index bf13dd21..8f3b823f 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -128,7 +128,7 @@ void sasl_init(void)
{
signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
signal_add_first("event authenticate", (SIGNAL_FUNC) sasl_step);
- signal_add_first("event 900", (SIGNAL_FUNC) sasl_success);
+ signal_add_first("event 903", (SIGNAL_FUNC) sasl_success);
signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail);
@@ -141,7 +141,7 @@ void sasl_deinit(void)
{
signal_remove("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
signal_remove("event authenticate", (SIGNAL_FUNC) sasl_step);
- signal_remove("event 900", (SIGNAL_FUNC) sasl_success);
+ signal_remove("event 903", (SIGNAL_FUNC) sasl_success);
signal_remove("event 902", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 904", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 905", (SIGNAL_FUNC) sasl_fail);
From 49c4ea5fd94c9eee17dc5a8e0691ba1da9bf33b7 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 23:20:07 +0200
Subject: [PATCH 29/82] Parse the error string received by the server
So that in case of SASL failure the user sees a nice error message.
---
src/irc/core/sasl.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 8f3b823f..874b67f3 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -41,16 +41,22 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr
static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from)
{
+ char *params, *error;
+
/* Stop any pending timeout, if any */
if (server->sasl_timeout != -1) {
g_source_remove(server->sasl_timeout);
server->sasl_timeout = -1;
}
- g_critical("Authentication failed with reason \"%s\"", data);
+ params = event_get_params(data, 2, NULL, &error);
+
+ g_critical("Authentication failed with reason \"%s\"", error);
/* Terminate the negotiation */
cap_finish_negotiation(server);
+
+ g_free(params);
}
static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from)
From 24d32c28ee2d5dbd001cbe29fa5d90077c6be107 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 11 Sep 2015 23:21:33 +0200
Subject: [PATCH 30/82] Don't handle 908 as a critical failure
"if the mechanism is unknown, 908 is optional, 904 (or equivalent error condition) is required"
---
src/irc/core/sasl.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 874b67f3..56e80f48 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -140,7 +140,6 @@ void sasl_init(void)
signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 906", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 907", (SIGNAL_FUNC) sasl_already);
- signal_add_first("event 908", (SIGNAL_FUNC) sasl_fail);
}
void sasl_deinit(void)
@@ -153,5 +152,4 @@ void sasl_deinit(void)
signal_remove("event 905", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 906", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 907", (SIGNAL_FUNC) sasl_already);
- signal_remove("event 908", (SIGNAL_FUNC) sasl_fail);
}
From 54a2fafbde593f63811da711c6a5f95ba58c818a Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Fri, 18 Sep 2015 23:33:52 +0200
Subject: [PATCH 31/82] Update perl.txt
---
docs/perl.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/docs/perl.txt b/docs/perl.txt
index 79ab5820..560fcaec 100644
--- a/docs/perl.txt
+++ b/docs/perl.txt
@@ -1185,3 +1185,11 @@ Client->{}
connected - whether the client is connected and ready
want_ctcp - whether the client wants to receive CTCPs
ircnet - network tag of the network we proxy
+
+
+
+
+ Bugs and Limitations
+ --------------------
+* Calling die in 'script error' handler causes segfault (#101)
+* Storing and later using any Irssi object may result in use-after-free related crash
From f37f6ac0edadf12476fba962d582bc43876f0be6 Mon Sep 17 00:00:00 2001
From: dequis
Date: Fri, 18 Sep 2015 23:56:17 -0300
Subject: [PATCH 32/82] Add two missing #include "fe-irc-channels.h"
Fixes #285
---
src/fe-common/irc/fe-events.c | 1 +
src/fe-common/irc/fe-irc-messages.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c
index 068ee543..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)
diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c
index b2736a2c..11d158af 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -36,6 +36,7 @@
#include "fe-queries.h"
#include "window-items.h"
+#include "fe-irc-channels.h"
static void sig_message_own_public(SERVER_REC *server, const char *msg,
const char *target, const char *origtarget)
From 061fb347502bd0b98f4587cfdce6612808d0c989 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 16 Sep 2015 15:31:51 +0200
Subject: [PATCH 33/82] Modify the terminal initialization sequence
We disable the ICRNL flag to make Enter independent from ^J from the
keybinding point of view since the former will now send ^M, leaving the
user free to remap ^J without trapping itself into the irssi session
because of a broken Enter key.
Also disable the software flow control because we don't expect anyone to
run irssi over a serial console; we gain some more freedom by having ^Q
and ^S freely mappable by the user.
---
src/fe-text/terminfo-core.c | 3 +++
1 file changed, 3 insertions(+)
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 */
From 9586766d87820bdfa9e7cbe805f5ed4b7b0378e5 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Sat, 19 Sep 2015 18:27:48 -0300
Subject: [PATCH 34/82] Add setting to configure rejoin on reconnect behaviour
Closes #169
---
src/irc/core/irc-servers.c | 50 ++++++++++++++++++++++++++++++--------
1 file changed, 40 insertions(+), 10 deletions(-)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index b2718ae1..fdc5187f 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -33,6 +33,7 @@
#include "irc-servers-setup.h"
#include "irc-servers.h"
#include "irc-cap.h"
+#include "channels-setup.h"
#include "channel-rejoin.h"
#include "servers-idle.h"
#include "servers-reconnect.h"
@@ -609,32 +610,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);
- 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 ((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);
+
+ if (rec->key != NULL) use_keys = TRUE;
+ }
}
if (chans->len > 0) {
@@ -646,6 +674,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;
}
@@ -991,6 +1020,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", "");
From ca363efe00a05682acf9de828d55e991657b9e4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 21:01:25 +0200
Subject: [PATCH 35/82] Use g_string_append() instead of g_string_append_c()
for string.
---
src/irc/proxy/dump.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c
index 455a2fe3..05059360 100644
--- a/src/irc/proxy/dump.c
+++ b/src/irc/proxy/dump.c
@@ -169,7 +169,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
NICK_REC *nick = tmp->data;
if (str->len >= 500) {
- g_string_append_c(str, '\r\n');
+ g_string_append(str, "\r\n");
proxy_outdata(client, "%s", str->str);
create_names_start(str, channel, client);
first = TRUE;
From 1079ad46d21198b26649c2a81a692781e22336aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 21:12:07 +0200
Subject: [PATCH 36/82] Use g_string_append() instead of g_string_append_c()
for string.
---
src/irc/proxy/dump.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c
index 05059360..e39c21a6 100644
--- a/src/irc/proxy/dump.c
+++ b/src/irc/proxy/dump.c
@@ -186,7 +186,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
}
g_slist_free(nicks);
- g_string_append_c(str, '\r\n');
+ g_string_append(str, "\r\n");
proxy_outdata(client, "%s", str->str);
g_string_free(str, TRUE);
From be977bf1b795c93dbff4fa52f04b5d425a3f3648 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 21:21:40 +0200
Subject: [PATCH 37/82] Fix warning.
---
src/irc/core/irc.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/irc.c b/src/irc/core/irc.c
index 509418b7..4dce3fcf 100644
--- a/src/irc/core/irc.c
+++ b/src/irc/core/irc.c
@@ -212,8 +212,12 @@ void irc_send_cmd_split(IRC_SERVER_REC *server, const char *cmd,
count = 0;
if (nickstr->len > 0)
g_string_truncate(nickstr, nickstr->len-1);
- irc_send_cmdv(server, post == NULL ? "%s %s" : "%s %s %s",
- pre, nickstr->str, post);
+
+ if (post == NULL)
+ irc_send_cmdv(server, "%s %s", pre, nickstr->str);
+ else
+ irc_send_cmdv(server, "%s %s %s", pre, nickstr->str, post);
+
g_string_truncate(nickstr, 0);
if (*tmp == NULL || tmp[1] == NULL)
From 29cf546ee4d5c1af1042d6fbeaae150ecc545d4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 20:54:29 +0200
Subject: [PATCH 38/82] Remove Garbage Collection support.
GC support was never enabled by default and nobody in the current
development team seems to care about it.
---
NEWS | 2 ++
acconfig.h | 3 ---
configure.ac | 32 --------------------------------
src/common.h | 4 ----
src/fe-text/irssi.c | 23 -----------------------
5 files changed, 2 insertions(+), 62 deletions(-)
diff --git a/NEWS b/NEWS
index d92f22e8..511f495a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,6 @@
v0.8.18-head 2014-XX-YY The Irssi team
+ + Garbage Collection support has been removed. This will hardly have any
+ effect for anyone given that it has been unsupported for several years.
+ Disable SSLv3 due to the POODLE vulnerability.
+ Try to split long lines on spaces to avoid words being splitted. Adds
a new option: 'split_line_on_space' which defaults to on.
diff --git a/acconfig.h b/acconfig.h
index cfe62381..9ace70d8 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -3,9 +3,6 @@
#undef HAVE_SOCKS_H
#undef HAVE_STATIC_PERL
#undef HAVE_GMODULE
-#undef HAVE_GC_H
-#undef HAVE_GC_GC_H
-#undef USE_GC
/* macros/curses checks */
#undef HAS_CURSES
diff --git a/configure.ac b/configure.ac
index c312d065..e33b8c1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,15 +83,6 @@ if test "x$prefix" != "xNONE"; then
perl_prefix_note=yes
fi
-AC_ARG_WITH(gc,
-[ --with-gc Use garbage collector],
- if test x$withval = xno; then
- want_gc=no
- else
- want_gc=yes
- fi,
- want_gc=no)
-
AC_ARG_WITH(perl-staticlib,
[ --with-perl-staticlib Specify that we want to link perl libraries
statically in irssi, default is no],
@@ -322,28 +313,6 @@ if test "$enable_ssl" = "yes"; then
fi
fi
-dnl **
-dnl ** Garbage Collector
-dnl **
-have_gc=no
-if test "x$want_gc" = xyes; then
- AC_CHECK_LIB(gc, GC_malloc, [
- AC_CHECK_HEADER(gc/gc.h, [
- AC_DEFINE(HAVE_GC_GC_H)
- AC_DEFINE(USE_GC)
- LIBS="$LIBS -lgc"
- have_gc=yes
- ], [
- AC_CHECK_HEADER(gc.h, [
- AC_DEFINE(HAVE_GC_H)
- AC_DEFINE(USE_GC)
- LIBS="$LIBS -lgc"
- have_gc=yes
- ])
- ])
- ])
-fi
-
dnl **
dnl ** curses checks
dnl **
@@ -782,7 +751,6 @@ if test "x$have_openssl" = "xno" -a "x$enable_ssl" = "xyes"; then
fi
fi
echo "Building with 64bit DCC support .. : $offt_64bit"
-echo "Building with garbage collector .. : $have_gc"
echo "Building with DANE support ....... : $have_dane"
echo "Building with true color support.. : $want_truecolor"
diff --git a/src/common.h b/src/common.h
index 1b99753b..e9073925 100644
--- a/src/common.h
+++ b/src/common.h
@@ -56,10 +56,6 @@
#define g_strcmp0(a, b) (!a ? -(a != b) : (!b ? (a != b) : strcmp(a, b)))
#endif
-#ifdef USE_GC
-# define g_free(x) G_STMT_START { (x) = NULL; } G_STMT_END
-#endif
-
#if defined (UOFF_T_INT)
typedef unsigned int uoff_t;
#elif defined (UOFF_T_LONG)
diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c
index 6d5b9b13..b1fa5e22 100644
--- a/src/fe-text/irssi.c
+++ b/src/fe-text/irssi.c
@@ -286,22 +286,6 @@ static void winsock_init(void)
}
#endif
-#ifdef USE_GC
-#ifdef HAVE_GC_H
-# include
-#else
-# include
-#endif
-
-GMemVTable gc_mem_table = {
- GC_malloc,
- GC_realloc,
- GC_free,
-
- NULL, NULL, NULL
-};
-#endif
-
int main(int argc, char **argv)
{
static int version = 0;
@@ -312,10 +296,6 @@ int main(int argc, char **argv)
};
int loglev;
-#ifdef USE_GC
- g_mem_set_vtable(&gc_mem_table);
-#endif
-
core_register_options();
fe_common_core_register_options();
args_register(options);
@@ -369,9 +349,6 @@ int main(int argc, char **argv)
/* Does the same as g_main_run(main_loop), except we
can call our dirty-checker after each iteration */
while (!quitting) {
-#ifdef USE_GC
- GC_collect_a_little();
-#endif
if (!dummy) term_refresh_freeze();
g_main_iteration(TRUE);
if (!dummy) term_refresh_thaw();
From 519955ebe4a421e8027c3dd09af9ea76d949d259 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 21:45:33 +0200
Subject: [PATCH 39/82] Fix warning.
Add comment on the use of ??) in C, since that string isn't entirely
obvious to people who are reading the code.
---
src/fe-text/statusbar-items.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c
index 044c2fa0..e3e0c2a6 100644
--- a/src/fe-text/statusbar-items.c
+++ b/src/fe-text/statusbar-items.c
@@ -347,10 +347,14 @@ static void item_lag(SBAR_ITEM_REC *item, int get_size_only)
last_lag_unknown = lag_unknown;
if (lag_unknown) {
- g_snprintf(str, sizeof(str), "%d (?""?)", lag/100);
+ // "??)" in C becomes ']'
+ // See: https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C
+ g_snprintf(str, sizeof(str), "%d (?""?)", lag / 100);
} else {
- g_snprintf(str, sizeof(str),
- lag%100 == 0 ? "%d" : "%d.%02d", lag/100, lag%100);
+ if (lag % 100 == 0)
+ g_snprintf(str, sizeof(str), "%d", lag / 100);
+ else
+ g_snprintf(str, sizeof(str), "%d.%02d", lag / 100, lag % 100);
}
statusbar_item_default_handler(item, get_size_only,
From 6c9dcffb5ef6b0f024f5ab6d335b69ef79e4daa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 22:51:13 +0200
Subject: [PATCH 40/82] Fix formatting warnings.
---
src/irc/core/irc-commands.c | 40 ++++++++++++++++++++++++++-----------
1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index f2cd49c0..47644753 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -170,8 +170,11 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server,
if (*msg != '\0')
recoded = recode_out(SERVER(server), msg, channame);
- irc_send_cmdv(server, ! recoded ? "PART %s" : "PART %s :%s",
- channame, recoded);
+
+ if (recoded == NULL)
+ irc_send_cmdv(server, "PART %s", channame);
+ else
+ irc_send_cmdv(server, "PART %s :%s", channame, recoded);
g_free(recoded);
cmd_params_free(free_arg);
@@ -219,8 +222,12 @@ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *ite
if (*topic != '\0' || g_hash_table_lookup(optlist, "delete") != NULL)
recoded = recode_out(SERVER(server), topic, channame);
- irc_send_cmdv(server, recoded == NULL ? "TOPIC %s" : "TOPIC %s :%s",
- channame, recoded);
+
+ if (recoded == NULL)
+ irc_send_cmdv(server, "TOPIC %s", channame);
+ else
+ irc_send_cmdv(server, "TOPIC %s :%s", channame, recoded);
+
g_free(recoded);
cmd_params_free(free_arg);
@@ -279,14 +286,14 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
char *channel, *rest;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channel, &rest))
return;
if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
if (!IS_IRC_CHANNEL(item))
- cmd_param_error(CMDERR_NOT_JOINED);
+ cmd_param_error(CMDERR_NOT_JOINED);
channel = IRC_CHANNEL(item)->name;
}
@@ -295,8 +302,11 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
*channel = '\0';
}
- irc_send_cmdv(server, *rest == '\0' ? "WHO %s" : "WHO %s %s",
- channel, rest);
+ if (rest[0] == '\0')
+ irc_send_cmdv(server, "WHO %s", channel);
+ else
+ irc_send_cmdv(server, "WHO %s %s", channel, rest);
+
cmd_params_free(free_arg);
}
@@ -502,8 +512,11 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
if (free_nick) g_free(nicks_redir);
server->whowas_found = FALSE;
- irc_send_cmdv(server, *rest == '\0' ? "WHOWAS %s" :
- "WHOWAS %s %s", nicks, rest);
+
+ if (rest[0] == '\0')
+ irc_send_cmdv(server, "WHOWAS %s", nicks);
+ else
+ irc_send_cmdv(server, "WHOWAS %s %s", nicks, rest);
cmd_params_free(free_arg);
}
@@ -913,9 +926,12 @@ static void cmd_unsilence(const char *data, IRC_SERVER_REC *server)
static void command_self(const char *data, IRC_SERVER_REC *server)
{
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
- irc_send_cmdv(server, *data == '\0' ? "%s" : "%s %s", current_command, data);
+ if (data[0] == '\0')
+ irc_send_cmdv(server, "%s", current_command);
+ else
+ irc_send_cmdv(server, "%s %s", current_command, data);
}
static void command_1self(const char *data, IRC_SERVER_REC *server)
From 5c3ef84a0ba3cde0d9e2586fcb618d81851776f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 23:02:51 +0200
Subject: [PATCH 41/82] Undefine PACKAGE_VERSION before overwriting it.
---
irssi-version.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/irssi-version.sh b/irssi-version.sh
index 1e9eae34..1fc6a558 100755
--- a/irssi-version.sh
+++ b/irssi-version.sh
@@ -22,6 +22,7 @@ if echo "${VERSION}" | grep -q -- -head; then
# Because the git tag won't yet include the next release we modify the git
# describe output using the version defined from configure.ac.
version="${new_version}-$(echo "${git_version}" | sed 's/^.*-[0-9]\+-//')"
+ echo "#undef PACKAGE_VERSION"
echo "#define PACKAGE_VERSION \"${version}\""
fi
fi
From a44c4b82de44af9aec59c542f3212795ecc52b57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sun, 20 Sep 2015 23:11:39 +0200
Subject: [PATCH 42/82] More format warnings removed.
---
src/fe-common/core/fe-common-core.c | 7 +++++--
src/irc/core/irc-channels.c | 12 +++++++-----
src/irc/core/servers-redirect.c | 8 +++++---
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c
index a475f056..341902df 100644
--- a/src/fe-common/core/fe-common-core.c
+++ b/src/fe-common/core/fe-common-core.c
@@ -326,8 +326,11 @@ static void autoconnect_servers(void)
if (autocon_server != NULL) {
/* connect to specified server */
- str = g_strdup_printf(autocon_password == NULL ? "%s %d" : "%s %d %s",
- autocon_server, autocon_port, autocon_password);
+ if (autocon_password == NULL)
+ str = g_strdup_printf("%s %d", autocon_server, autocon_port);
+ else
+ str = g_strdup_printf("%s %d %s", autocon_server, autocon_port, autocon_password);
+
signal_emit("command connect", 1, str);
g_free(str);
return;
diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c
index add18acf..682be4c2 100644
--- a/src/irc/core/irc-channels.c
+++ b/src/irc/core/irc-channels.c
@@ -146,11 +146,13 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
continue;
}
if (outchans->len > 0) {
- g_string_truncate(outchans, outchans->len-1);
- g_string_truncate(outkeys, outkeys->len-1);
- irc_send_cmdv(IRC_SERVER(server),
- use_keys ? "JOIN %s %s" : "JOIN %s",
- outchans->str, outkeys->str);
+ g_string_truncate(outchans, outchans->len - 1);
+ g_string_truncate(outkeys, outkeys->len - 1);
+
+ if (use_keys)
+ irc_send_cmdv(IRC_SERVER(server), "JOIN %s %s", outchans->str, outkeys->str);
+ else
+ irc_send_cmdv(IRC_SERVER(server), "JOIN %s", outchans->str);
}
cmdlen = 0;
g_string_truncate(outchans,0);
diff --git a/src/irc/core/servers-redirect.c b/src/irc/core/servers-redirect.c
index f0a285df..aeb9c010 100644
--- a/src/irc/core/servers-redirect.c
+++ b/src/irc/core/servers-redirect.c
@@ -433,9 +433,11 @@ static void redirect_abort(IRC_SERVER_REC *server, REDIRECT_REC *rec)
if (rec->aborted || !rec->destroyed) {
/* emit the failure signal */
- str = g_strdup_printf(rec->failure_signal != NULL ?
- "FAILED %s: %s" : "FAILED %s",
- rec->cmd->name, rec->failure_signal);
+ if (rec->failure_signal != NULL)
+ str = g_strdup_printf("FAILED %s: %s", rec->cmd->name, rec->failure_signal);
+ else
+ str = g_strdup_printf("FAILED %s", rec->cmd->name);
+
rawlog_redirect(server->rawlog, str);
g_free(str);
From 203c00938acad1da4a91a2c21afdac4ede08572a Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 20 Sep 2015 23:13:43 +0200
Subject: [PATCH 43/82] Use formats instead of g_warning
Add some copyright headers here and there too.
---
docs/signals.txt | 4 +++
src/fe-common/irc/Makefile.am | 1 +
src/fe-common/irc/fe-common-irc.c | 5 ++++
src/fe-common/irc/fe-sasl.c | 48 ++++++++++++++++++++++++++++++
src/fe-common/irc/module-formats.c | 2 ++
src/fe-common/irc/module-formats.h | 2 ++
src/irc/core/irc-servers-setup.c | 2 +-
src/irc/core/sasl.c | 43 +++++++++++++++++++-------
src/irc/core/sasl.h | 20 +++++++++++++
9 files changed, 116 insertions(+), 11 deletions(-)
create mode 100644 src/fe-common/irc/fe-sasl.c
diff --git a/docs/signals.txt b/docs/signals.txt
index 5c40ce77..8b71fd95 100644
--- a/docs/signals.txt
+++ b/docs/signals.txt
@@ -136,6 +136,10 @@ irc-cap.c
"server cap nak ", SERVER_REC
"server cap end", SERVER_REC
+sasl.c
+ "server sasl failure", SERVER_REC, char *reason
+ "server sasl success", SERVER_REC
+
irc.c:
"server event", SERVER_REC, char *data, char *sender_nick, char *sender_address
diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am
index 463f145c..a5dd4c77 100644
--- a/src/fe-common/irc/Makefile.am
+++ b/src/fe-common/irc/Makefile.am
@@ -26,6 +26,7 @@ real_sources = \
fe-netsplit.c \
fe-common-irc.c \
fe-whois.c \
+ fe-sasl.c \
irc-completion.c \
module-formats.c
diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c
index d6ab30ce..4a3ef1d3 100644
--- a/src/fe-common/irc/fe-common-irc.c
+++ b/src/fe-common/irc/fe-common-irc.c
@@ -69,6 +69,9 @@ void fe_netjoin_deinit(void);
void fe_whois_init(void);
void fe_whois_deinit(void);
+void fe_sasl_init(void);
+void fe_sasl_deinit(void);
+
void irc_completion_init(void);
void irc_completion_deinit(void);
@@ -91,6 +94,7 @@ void fe_common_irc_init(void)
fe_netsplit_init();
fe_netjoin_init();
fe_whois_init();
+ fe_sasl_init();
irc_completion_init();
settings_check();
@@ -116,6 +120,7 @@ void fe_common_irc_deinit(void)
fe_netsplit_deinit();
fe_netjoin_deinit();
fe_whois_deinit();
+ fe_sasl_deinit();
irc_completion_deinit();
theme_unregister();
diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c
new file mode 100644
index 00000000..331b38b0
--- /dev/null
+++ b/src/fe-common/irc/fe-sasl.c
@@ -0,0 +1,48 @@
+/*
+ fe-sasl.c : irssi
+
+ Copyright (C) 2015 The Lemon Man
+
+ 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 Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "module.h"
+#include "module-formats.h"
+#include "signals.h"
+#include "levels.h"
+
+#include "printtext.h"
+
+static void sig_sasl_success(IRC_SERVER_REC *server)
+{
+ printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_SUCCESS);
+}
+
+static void sig_sasl_failure(IRC_SERVER_REC *server, const char *reason)
+{
+ printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_ERROR, reason);
+}
+
+void fe_sasl_init(void)
+{
+ signal_add("server sasl success", (SIGNAL_FUNC) sig_sasl_success);
+ signal_add("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure);
+}
+
+void fe_sasl_deinit(void)
+{
+ signal_remove("server sasl success", (SIGNAL_FUNC) sig_sasl_success);
+ signal_remove("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure);
+}
diff --git a/src/fe-common/irc/module-formats.c b/src/fe-common/irc/module-formats.c
index 6eaf18e8..f7b074ec 100644
--- a/src/fe-common/irc/module-formats.c
+++ b/src/fe-common/irc/module-formats.c
@@ -44,6 +44,8 @@ FORMAT_REC fecommon_irc_formats[] = {
{ "setupserver_header", "%#Server Port Network Settings", 0 },
{ "setupserver_line", "%#%|$[!20]0 $[5]1 $[10]2 $3", 4, { 0, 1, 0, 0 } },
{ "setupserver_footer", "", 0 },
+ { "sasl_success", "SASL authentication succeeded", 0 },
+ { "sasl_error", "Cannot authenticate via SASL ($0)", 1, { 0 } },
/* ---- */
{ NULL, "Channels", 0 },
diff --git a/src/fe-common/irc/module-formats.h b/src/fe-common/irc/module-formats.h
index 34dd3efc..c45f4562 100644
--- a/src/fe-common/irc/module-formats.h
+++ b/src/fe-common/irc/module-formats.h
@@ -22,6 +22,8 @@ enum {
IRCTXT_SETUPSERVER_HEADER,
IRCTXT_SETUPSERVER_LINE,
IRCTXT_SETUPSERVER_FOOTER,
+ IRCTXT_SASL_SUCCESS,
+ IRCTXT_SASL_ERROR,
IRCTXT_FILL_2,
diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index 9a9a8347..f5e4f8f4 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -93,7 +93,7 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
conn->sasl_username = ircnet->sasl_username;
conn->sasl_password = ircnet->sasl_password;
} else
- g_warning("The fields sasl_username and sasl_password are either undefined or empty");
+ g_warning("The fields sasl_username and sasl_password are either missing or empty");
}
else if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "external")) {
conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL;
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 56e80f48..a04eaf45 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -1,3 +1,23 @@
+/*
+ fe-sasl.c : irssi
+
+ Copyright (C) 2015 The Lemon Man
+
+ 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 Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
#include "module.h"
#include "misc.h"
#include "settings.h"
@@ -8,20 +28,20 @@
#define SASL_TIMEOUT (20 * 1000) // ms
-static gboolean sasl_timeout (IRC_SERVER_REC *server)
+static gboolean sasl_timeout(IRC_SERVER_REC *server)
{
/* The authentication timed out, we can't do much beside terminating it */
- g_critical("The authentication timed out, try increasing the timeout and check your connection "
- "to the network.");
irc_send_cmd_now(server, "AUTHENTICATE *");
cap_finish_negotiation(server);
server->sasl_timeout = -1;
+ signal_emit("server sasl failure", 2, server, "The authentication timed out");
+
return FALSE;
}
-static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *from)
+static void sasl_start(IRC_SERVER_REC *server, const char *data, const char *from)
{
IRC_SERVER_CONNECT_REC *conn;
@@ -39,7 +59,7 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr
server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server);
}
-static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from)
+static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from)
{
char *params, *error;
@@ -51,7 +71,7 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro
params = event_get_params(data, 2, NULL, &error);
- g_critical("Authentication failed with reason \"%s\"", error);
+ signal_emit("server sasl fail", 2, server, error);
/* Terminate the negotiation */
cap_finish_negotiation(server);
@@ -59,30 +79,33 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro
g_free(params);
}
-static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from)
+static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *from)
{
if (server->sasl_timeout != -1) {
g_source_remove(server->sasl_timeout);
server->sasl_timeout = -1;
}
+ signal_emit("server sasl success", 1, server);
+
/* We're already authenticated, do nothing */
cap_finish_negotiation(server);
}
-static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from)
+static void sasl_success(IRC_SERVER_REC *server, const char *data, const char *from)
{
if (server->sasl_timeout != -1) {
g_source_remove(server->sasl_timeout);
server->sasl_timeout = -1;
}
+ signal_emit("server sasl success", 1, server);
+
/* The authentication succeeded, time to finish the CAP negotiation */
- g_warning("SASL authentication succeeded");
cap_finish_negotiation(server);
}
-static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *from)
+static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from)
{
IRC_SERVER_CONNECT_REC *conn;
GString *req;
diff --git a/src/irc/core/sasl.h b/src/irc/core/sasl.h
index fcf87e16..0693989d 100644
--- a/src/irc/core/sasl.h
+++ b/src/irc/core/sasl.h
@@ -1,3 +1,23 @@
+/*
+ fe-sasl.c : irssi
+
+ Copyright (C) 2015 The Lemon Man
+
+ 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 Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
#ifndef __SASL_H
#define __SASL_H
From ffaa890e99e2176ff3d2dec0ab5a8136e1e946ff Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 21 Sep 2015 13:54:13 +0200
Subject: [PATCH 44/82] Initial work to make irssi respect the resolved ip
order
Ip's aren't selected using random() anymore, also select the ip version
by using getaddrinfo and some proper hints.
---
src/core/chat-commands.c | 6 +--
src/core/chatnet-rec.h | 2 +-
src/core/net-nonblock.c | 38 ++++---------
src/core/net-nonblock.h | 4 +-
src/core/network.c | 98 ++++++----------------------------
src/core/network.h | 2 +-
src/core/server-connect-rec.h | 2 +-
src/core/server-setup-rec.h | 2 +-
src/core/servers-reconnect.c | 10 ++--
src/core/servers-setup.c | 67 +++++++----------------
src/core/servers-setup.h | 2 +-
src/core/servers.c | 66 +++++++----------------
src/core/servers.h | 3 +-
src/fe-common/core/fe-server.c | 4 +-
src/fe-common/irc/fe-ircnet.c | 4 +-
src/irc/dcc/dcc.c | 4 +-
src/irc/proxy/listen.c | 9 ++--
17 files changed, 87 insertions(+), 236 deletions(-)
diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c
index 8e881679..9c28a1fc 100644
--- a/src/core/chat-commands.c
+++ b/src/core/chat-commands.c
@@ -128,10 +128,10 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
host = g_hash_table_lookup(optlist, "host");
if (host != NULL && *host != '\0') {
- IPADDR ip4, ip6;
+ IPADDR ip;
- if (net_gethostbyname(host, &ip4, &ip6) == 0)
- server_connect_own_ip_save(conn, &ip4, &ip6);
+ if (net_gethostbyname(host, &ip) == 0)
+ server_connect_own_ip_save(conn, &ip);
}
cmd_params_free(free_arg);
diff --git a/src/core/chatnet-rec.h b/src/core/chatnet-rec.h
index e3ed8aa0..3044643a 100644
--- a/src/core/chatnet-rec.h
+++ b/src/core/chatnet-rec.h
@@ -9,4 +9,4 @@ char *realname;
char *own_host; /* address to use when connecting this server */
char *autosendcmd; /* command to send after connecting to this ircnet */
-IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
+IPADDR *own_ip; /* resolved own_address if not NULL */
diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c
index e637e673..bc8c4b96 100644
--- a/src/core/net-nonblock.c
+++ b/src/core/net-nonblock.c
@@ -103,15 +103,12 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
srand(time(NULL));
memset(&rec, 0, sizeof(rec));
- rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6);
+ rec.error = net_gethostbyname(addr, &rec.ip);
if (rec.error == 0) {
errorstr = NULL;
if (reverse_lookup) {
/* reverse lookup the IP, ignore any error */
- if (rec.ip4.family != 0)
- net_gethostbyaddr(&rec.ip4, &rec.host4);
- if (rec.ip6.family != 0)
- net_gethostbyaddr(&rec.ip6, &rec.host6);
+ net_gethostbyaddr(&rec.ip, &rec.host);
}
} else {
errorstr = net_gethosterror(rec.error);
@@ -122,18 +119,11 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
if (rec.errlen != 0)
g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen);
else {
- if (rec.host4) {
- len = strlen(rec.host4) + 1;
+ if (rec.host) {
+ len = strlen(rec.host) + 1;
g_io_channel_write_block(pipe, (void *) &len,
sizeof(int));
- g_io_channel_write_block(pipe, (void *) rec.host4,
- len);
- }
- if (rec.host6) {
- len = strlen(rec.host6) + 1;
- g_io_channel_write_block(pipe, (void *) &len,
- sizeof(int));
- g_io_channel_write_block(pipe, (void *) rec.host6,
+ g_io_channel_write_block(pipe, (void *) rec.host,
len);
}
}
@@ -154,8 +144,7 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
rec->error = -1;
rec->errorstr = NULL;
- rec->host4 = NULL;
- rec->host6 = NULL;
+ rec->host = NULL;
#ifndef WIN32
fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK);
@@ -174,15 +163,10 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
rec->errorstr = g_malloc0(rec->errlen+1);
g_io_channel_read_block(pipe, rec->errorstr, rec->errlen);
} else {
- if (rec->host4) {
+ if (rec->host) {
g_io_channel_read_block(pipe, &len, sizeof(int));
- rec->host4 = g_malloc0(len);
- g_io_channel_read_block(pipe, rec->host4, len);
- }
- if (rec->host6) {
- g_io_channel_read_block(pipe, &len, sizeof(int));
- rec->host6 = g_malloc0(len);
- g_io_channel_read_block(pipe, rec->host6, len);
+ rec->host = g_malloc0(len);
+ g_io_channel_read_block(pipe, rec->host, len);
}
}
@@ -227,7 +211,6 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
{
RESOLVED_IP_REC iprec;
GIOChannel *handle;
- IPADDR *ip;
g_return_if_fail(rec != NULL);
@@ -241,9 +224,8 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
g_io_channel_shutdown(rec->pipes[1], TRUE, NULL);
g_io_channel_unref(rec->pipes[1]);
- ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6;
handle = iprec.error == -1 ? NULL :
- net_connect_ip(ip, rec->port, rec->my_ip);
+ net_connect_ip(&iprec.ip, rec->port, rec->my_ip);
g_free_not_null(rec->my_ip);
diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h
index af5968c8..581536b3 100644
--- a/src/core/net-nonblock.h
+++ b/src/core/net-nonblock.h
@@ -4,12 +4,12 @@
#include "network.h"
typedef struct {
- IPADDR ip4, ip6; /* resolved ip addresses */
+ IPADDR ip; /* resolved ip address */
int error; /* error, 0 = no error, -1 = error: */
int errlen; /* error text length */
char *errorstr; /* error string - dynamically allocated, you'll
need to free() it yourself unless it's NULL */
- char *host4, *host6; /* dito */
+ char *host; /* dito */
} RESOLVED_IP_REC;
typedef struct {
diff --git a/src/core/network.c b/src/core/network.c
index bfaa47fb..303483c6 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -137,35 +137,14 @@ static int sin_get_port(union sockaddr_union *so)
/* Connect to socket */
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
{
- IPADDR ip4, ip6, *ip;
+ IPADDR ip;
g_return_val_if_fail(addr != NULL, NULL);
- if (net_gethostbyname(addr, &ip4, &ip6) == -1)
+ if (net_gethostbyname(addr, &ip) == -1)
return NULL;
- if (my_ip == NULL) {
- /* prefer IPv4 addresses */
- ip = ip4.family != 0 ? &ip4 : &ip6;
- } else if (IPADDR_IS_V6(my_ip)) {
- /* my_ip is IPv6 address, use it if possible */
- if (ip6.family != 0)
- ip = &ip6;
- else {
- my_ip = NULL;
- ip = &ip4;
- }
- } else {
- /* my_ip is IPv4 address, use it if possible */
- if (ip4.family != 0)
- ip = &ip4;
- else {
- my_ip = NULL;
- ip = &ip6;
- }
- }
-
- return net_connect_ip(ip, port, my_ip);
+ return net_connect_ip(&ip, port, my_ip);
}
/* Connect to socket with ip address */
@@ -413,82 +392,35 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
-int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
+int net_gethostbyname(const char *addr, IPADDR *ip)
{
-#ifdef HAVE_IPV6
union sockaddr_union *so;
- struct addrinfo hints, *ai, *ailist;
- int ret, count_v4, count_v6, use_v4, use_v6;
-#else
- struct hostent *hp;
- int count;
-#endif
+ struct addrinfo hints, *ailist;
+ int ret;
g_return_val_if_fail(addr != NULL, -1);
- memset(ip4, 0, sizeof(IPADDR));
- memset(ip6, 0, sizeof(IPADDR));
+ memset(ip, 0, sizeof(IPADDR));
-#ifdef HAVE_IPV6
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM;
+#ifdef HAVE_IPV6
+ hints.ai_family = AF_UNSPEC;
+#else
+ hints.ai_family = AF_INET;
+#endif
+ hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
/* save error to host_error for later use */
ret = getaddrinfo(addr, NULL, &hints, &ailist);
if (ret != 0)
return ret;
- /* count IPs */
- count_v4 = count_v6 = 0;
- for (ai = ailist; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_family == AF_INET)
- count_v4++;
- else if (ai->ai_family == AF_INET6)
- count_v6++;
- }
-
- if (count_v4 == 0 && count_v6 == 0)
- return HOST_NOT_FOUND; /* shouldn't happen? */
-
- /* if there are multiple addresses, return random one */
- use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4;
- use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6;
-
- count_v4 = count_v6 = 0;
- for (ai = ailist; ai != NULL; ai = ai->ai_next) {
- so = (union sockaddr_union *) ai->ai_addr;
-
- if (ai->ai_family == AF_INET) {
- if (use_v4 == count_v4)
- sin_get_ip(so, ip4);
- count_v4++;
- } else if (ai->ai_family == AF_INET6) {
- if (use_v6 == count_v6)
- sin_get_ip(so, ip6);
- count_v6++;
- }
- }
+ so = (const union sockaddr_union *)ailist->ai_addr;
+ sin_get_ip(so, ip);
freeaddrinfo(ailist);
- return 0;
-#else
- hp = gethostbyname(addr);
- if (hp == NULL)
- return h_errno;
-
- /* count IPs */
- count = 0;
- while (hp->h_addr_list[count] != NULL)
- count++;
-
- if (count == 0)
- return HOST_NOT_FOUND; /* shouldn't happen? */
-
- /* if there are multiple addresses, return random one */
- ip4->family = AF_INET;
- memcpy(&ip4->ip, hp->h_addr_list[rand() % count], 4);
return 0;
-#endif
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
diff --git a/src/core/network.h b/src/core/network.h
index fa7e9675..ea8b3055 100644
--- a/src/core/network.h
+++ b/src/core/network.h
@@ -71,7 +71,7 @@ int net_transmit(GIOChannel *handle, const char *data, int len);
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
-int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6);
+int net_gethostbyname(const char *addr, IPADDR *ip);
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name);
diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h
index 80c5761b..3f24e7d8 100644
--- a/src/core/server-connect-rec.h
+++ b/src/core/server-connect-rec.h
@@ -16,7 +16,7 @@ char *address;
int port;
char *chatnet;
-IPADDR *own_ip4, *own_ip6;
+IPADDR *own_ip;
char *password;
char *nick;
diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h
index 2c9614c7..fbf49b2c 100644
--- a/src/core/server-setup-rec.h
+++ b/src/core/server-setup-rec.h
@@ -19,7 +19,7 @@ char *ssl_capath;
char *ssl_ciphers;
char *own_host; /* address to use when connecting this server */
-IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
+IPADDR *own_ip; /* resolved own_address if not NULL */
time_t last_connect; /* to avoid reconnecting too fast.. */
diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c
index ae97ecd2..3ba18ad0 100644
--- a/src/core/servers-reconnect.c
+++ b/src/core/servers-reconnect.c
@@ -177,13 +177,9 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
dest->username = g_strdup(src->username);
dest->realname = g_strdup(src->realname);
- if (src->own_ip4 != NULL) {
- dest->own_ip4 = g_new(IPADDR, 1);
- memcpy(dest->own_ip4, src->own_ip4, sizeof(IPADDR));
- }
- if (src->own_ip6 != NULL) {
- dest->own_ip6 = g_new(IPADDR, 1);
- memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR));
+ if (src->own_ip != NULL) {
+ dest->own_ip = g_new(IPADDR, 1);
+ memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR));
}
dest->channels = g_strdup(src->channels);
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 90a447d4..e8506f0f 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -33,32 +33,22 @@ GSList *setupservers;
static char *old_source_host;
int source_host_ok; /* Use source_host_ip .. */
-IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
+IPADDR source_host_ip; /* Resolved address */
-static void save_ips(IPADDR *ip4, IPADDR *ip6,
- IPADDR **save_ip4, IPADDR **save_ip6)
+static void save_ips(IPADDR *ip, IPADDR **save_ip)
{
- if (ip4->family == 0)
- g_free_and_null(*save_ip4);
+ if (ip->family == 0)
+ g_free_and_null(*save_ip);
else {
- if (*save_ip4 == NULL)
- *save_ip4 = g_new(IPADDR, 1);
- memcpy(*save_ip4, ip4, sizeof(IPADDR));
- }
-
- if (ip6->family == 0)
- g_free_and_null(*save_ip6);
- else {
- if (*save_ip6 == NULL)
- *save_ip6 = g_new(IPADDR, 1);
- memcpy(*save_ip6, ip6, sizeof(IPADDR));
+ if (*save_ip == NULL)
+ *save_ip = g_new(IPADDR, 1);
+ memcpy(*save_ip, ip, sizeof(IPADDR));
}
}
static void get_source_host_ip(void)
{
const char *hostname;
- IPADDR ip4, ip6;
if (source_host_ok)
return;
@@ -66,28 +56,21 @@ static void get_source_host_ip(void)
/* FIXME: This will block! */
hostname = settings_get_str("hostname");
source_host_ok = *hostname != '\0' &&
- net_gethostbyname(hostname, &ip4, &ip6) == 0;
-
- if (source_host_ok)
- save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6);
- else {
- g_free_and_null(source_host_ip4);
- g_free_and_null(source_host_ip6);
- }
+ net_gethostbyname(hostname, &source_host_ip) == 0;
}
static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host,
- IPADDR **own_ip4, IPADDR **own_ip6)
+ IPADDR **own_ip)
{
- IPADDR ip4, ip6;
+ IPADDR ip;
- if (*own_ip4 == NULL && *own_ip6 == NULL) {
+ if (*own_ip == NULL) {
/* resolve the IP */
- if (net_gethostbyname(own_host, &ip4, &ip6) == 0)
- save_ips(&ip4, &ip6, own_ip4, own_ip6);
+ if (net_gethostbyname(own_host, &ip) == 0)
+ save_ips(&ip, own_ip);
}
- server_connect_own_ip_save(conn, *own_ip4, *own_ip6);
+ server_connect_own_ip_save(conn, *own_ip);
}
/* Fill information to connection from server setup record */
@@ -98,8 +81,7 @@ void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
g_return_if_fail(IS_SERVER_SETUP(sserver));
if (sserver->own_host != NULL) {
- conn_set_ip(conn, sserver->own_host,
- &sserver->own_ip4, &sserver->own_ip6);
+ conn_set_ip(conn, sserver->own_host, &sserver->own_ip);
}
if (sserver->chatnet != NULL && conn->chatnet == NULL)
@@ -139,13 +121,9 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn,
}
/* source IP */
- if (source_host_ip4 != NULL) {
- conn->own_ip4 = g_new(IPADDR, 1);
- memcpy(conn->own_ip4, source_host_ip4, sizeof(IPADDR));
- }
- if (source_host_ip6 != NULL) {
- conn->own_ip6 = g_new(IPADDR, 1);
- memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR));
+ if (source_host_ok) {
+ conn->own_ip = g_new(IPADDR, 1);
+ memcpy(conn->own_ip, &source_host_ip, sizeof(IPADDR));
}
signal_emit("server setup fill connect", 1, conn);
@@ -206,8 +184,7 @@ static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn,
conn->realname = g_strdup(chatnet->realname);;
}
if (chatnet->own_host != NULL) {
- conn_set_ip(conn, chatnet->own_host,
- &chatnet->own_ip4, &chatnet->own_ip6);
+ conn_set_ip(conn, chatnet->own_host, &chatnet->own_ip);
}
signal_emit("server setup fill chatnet", 2, conn, chatnet);
@@ -481,8 +458,7 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec)
signal_emit("server setup destroyed", 1, rec);
g_free_not_null(rec->own_host);
- g_free_not_null(rec->own_ip4);
- g_free_not_null(rec->own_ip6);
+ g_free_not_null(rec->own_ip);
g_free_not_null(rec->chatnet);
g_free_not_null(rec->password);
g_free_not_null(rec->ssl_cert);
@@ -556,7 +532,6 @@ void servers_setup_init(void)
settings_add_str("proxy", "proxy_password", "");
setupservers = NULL;
- source_host_ip4 = source_host_ip6 = NULL;
old_source_host = NULL;
read_settings();
@@ -567,8 +542,6 @@ void servers_setup_init(void)
void servers_setup_deinit(void)
{
- g_free_not_null(source_host_ip4);
- g_free_not_null(source_host_ip6);
g_free_not_null(old_source_host);
while (setupservers != NULL)
diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h
index f7601a68..c4878094 100644
--- a/src/core/servers-setup.h
+++ b/src/core/servers-setup.h
@@ -16,7 +16,7 @@ struct _SERVER_SETUP_REC {
extern GSList *setupservers;
-extern IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
+extern IPADDR source_host_ip; /* Resolved address */
extern int source_host_ok; /* Use source_host_ip .. */
/* Fill reconnection specific information to connection
diff --git a/src/core/servers.c b/src/core/servers.c
index 3342304e..e18f8d9c 100644
--- a/src/core/servers.c
+++ b/src/core/servers.c
@@ -218,7 +218,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
return;
if (ip != NULL) {
- own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4;
+ own_ip = server->connrec->own_ip;
port = server->connrec->proxy != NULL ?
server->connrec->proxy_port : server->connrec->port;
handle = server->connrec->use_ssl ?
@@ -280,30 +280,15 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
server->connect_pipe[0] = NULL;
server->connect_pipe[1] = NULL;
- /* figure out if we should use IPv4 or v6 address */
- if (iprec.error != 0) {
- /* error */
- ip = NULL;
- } else if (server->connrec->family == AF_INET) {
- /* force IPv4 connection */
- ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4;
- servername = iprec.host4;
- } else if (server->connrec->family == AF_INET6) {
- /* force IPv6 connection */
- ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6;
- servername = iprec.host6;
- } else {
- /* pick the one that was found, or if both do it like
- /SET resolve_prefer_ipv6 says. */
- if (iprec.ip4.family == 0 ||
- (iprec.ip6.family != 0 &&
- settings_get_bool("resolve_prefer_ipv6"))) {
- ip = &iprec.ip6;
- servername = iprec.host6;
- } else {
- ip = &iprec.ip4;
- servername = iprec.host4;
- }
+ ip = NULL;
+
+ if (iprec.error == 0) {
+ // FIXME : REMOVE THIS BEFORE MERGE
+ if (server->connrec->family)
+ g_assert(server->connrec->family == iprec.ip.family);
+
+ ip = &iprec.ip;
+ servername = iprec.host;
}
if (ip != NULL) {
@@ -337,8 +322,7 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
}
g_free(iprec.errorstr);
- g_free(iprec.host4);
- g_free(iprec.host6);
+ g_free(iprec.host);
}
SERVER_REC *server_connect(SERVER_CONNECT_REC *conn)
@@ -623,8 +607,7 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
g_free_not_null(conn->address);
g_free_not_null(conn->chatnet);
- g_free_not_null(conn->own_ip4);
- g_free_not_null(conn->own_ip6);
+ g_free_not_null(conn->own_ip);
g_free_not_null(conn->password);
g_free_not_null(conn->nick);
@@ -654,26 +637,15 @@ void server_change_nick(SERVER_REC *server, const char *nick)
}
/* Update own IPv4 and IPv6 records */
-void server_connect_own_ip_save(SERVER_CONNECT_REC *conn,
- IPADDR *ip4, IPADDR *ip6)
+void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip)
{
- if (ip4 == NULL || ip4->family == 0)
- g_free_and_null(conn->own_ip4);
- if (ip6 == NULL || ip6->family == 0)
- g_free_and_null(conn->own_ip6);
+ if (ip == NULL || ip->family == 0)
+ g_free_and_null(conn->own_ip);
- if (ip4 != NULL && ip4->family != 0) {
- /* IPv4 address was found */
- if (conn->own_ip4 == NULL)
- conn->own_ip4 = g_new0(IPADDR, 1);
- memcpy(conn->own_ip4, ip4, sizeof(IPADDR));
- }
-
- if (ip6 != NULL && ip6->family != 0) {
- /* IPv6 address was found */
- if (conn->own_ip6 == NULL)
- conn->own_ip6 = g_new0(IPADDR, 1);
- memcpy(conn->own_ip6, ip6, sizeof(IPADDR));
+ if (ip != NULL && ip->family != 0) {
+ if (conn->own_ip == NULL)
+ conn->own_ip = g_new0(IPADDR, 1);
+ memcpy(conn->own_ip, ip, sizeof(IPADDR));
}
}
diff --git a/src/core/servers.h b/src/core/servers.h
index f39c650b..314faa32 100644
--- a/src/core/servers.h
+++ b/src/core/servers.h
@@ -67,8 +67,7 @@ void server_connect_failed(SERVER_REC *server, const char *msg);
void server_change_nick(SERVER_REC *server, const char *nick);
/* Update own IPv4 and IPv6 records */
-void server_connect_own_ip_save(SERVER_CONNECT_REC *conn,
- IPADDR *ip4, IPADDR *ip6);
+void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip);
/* `optlist' should contain only one unknown key - the server tag.
returns NULL if there was unknown -option */
diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c
index 429e6dac..f8558ad1 100644
--- a/src/fe-common/core/fe-server.c
+++ b/src/fe-common/core/fe-server.c
@@ -138,7 +138,7 @@ static void cmd_server_add(const char *data)
if (*password != '\0') g_free_and_null(rec->password);
if (g_hash_table_lookup(optlist, "host")) {
g_free_and_null(rec->own_host);
- rec->own_ip4 = rec->own_ip6 = NULL;
+ rec->own_ip = NULL;
}
}
@@ -193,7 +193,7 @@ static void cmd_server_add(const char *data)
value = g_hash_table_lookup(optlist, "host");
if (value != NULL && *value != '\0') {
rec->own_host = g_strdup(value);
- rec->own_ip4 = rec->own_ip6 = NULL;
+ rec->own_ip = NULL;
}
signal_emit("server add fill", 2, rec, optlist);
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 6618edd7..4071f367 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -108,7 +108,7 @@ static void cmd_network_add(const char *data)
if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname);
if (g_hash_table_lookup(optlist, "host")) {
g_free_and_null(rec->own_host);
- rec->own_ip4 = rec->own_ip6 = NULL;
+ rec->own_ip = NULL;
}
if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode);
if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd);
@@ -140,7 +140,7 @@ static void cmd_network_add(const char *data)
value = g_hash_table_lookup(optlist, "host");
if (value != NULL && *value != '\0') {
rec->own_host = g_strdup(value);
- rec->own_ip4 = rec->own_ip6 = NULL;
+ rec->own_ip = NULL;
}
value = g_hash_table_lookup(optlist, "usermode");
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index 17f6c477..7fef2ae5 100644
--- a/src/irc/dcc/dcc.c
+++ b/src/irc/dcc/dcc.c
@@ -264,12 +264,12 @@ GIOChannel *dcc_connect_ip(IPADDR *ip, int port)
}
if (own_ip == NULL)
- own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4;
+ own_ip = &source_host_ip;
handle = net_connect_ip(ip, port, own_ip);
if (handle == NULL && errno == EADDRNOTAVAIL && own_ip != NULL) {
/* dcc_own_ip is external address */
- own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4;
+ own_ip = &source_host_ip;
handle = net_connect_ip(ip, port, own_ip);
}
return handle;
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index dcc94e6b..16950c79 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -585,7 +585,7 @@ static LISTEN_REC *find_listen(const char *ircnet, int port)
static void add_listen(const char *ircnet, int port)
{
LISTEN_REC *rec;
- IPADDR ip4, ip6, *my_ip;
+ IPADDR ip, *my_ip;
if (port <= 0 || *ircnet == '\0')
return;
@@ -593,16 +593,13 @@ static void add_listen(const char *ircnet, int port)
/* bind to specific host/ip? */
my_ip = NULL;
if (*settings_get_str("irssiproxy_bind") != '\0') {
- if (net_gethostbyname(settings_get_str("irssiproxy_bind"),
- &ip4, &ip6) != 0) {
+ if (net_gethostbyname(settings_get_str("irssiproxy_bind"), &ip) != 0) {
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
"Proxy: can not resolve '%s' - aborting",
settings_get_str("irssiproxy_bind"));
return;
}
-
- my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 ||
- settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4;
+ my_ip = &ip;
}
rec = g_new0(LISTEN_REC, 1);
From 564829610de20f75ec667f1943524c3a49b9ea3f Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 21 Sep 2015 14:38:10 +0200
Subject: [PATCH 45/82] Ding dong the switch is dead
---
docs/help/in/toggle.in | 2 +-
docs/manual.txt | 3 ---
src/core/servers.c | 1 -
3 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/docs/help/in/toggle.in b/docs/help/in/toggle.in
index f87a6462..71f5c8f4 100644
--- a/docs/help/in/toggle.in
+++ b/docs/help/in/toggle.in
@@ -15,7 +15,7 @@
%9Examples:%9
- /TOGGLE resolve_prefer_ipv6
+ /TOGGLE resolve_reverse_lookup
/TOGGLE channels_rejoin_unavailable ON
%9See also:%9 SET
diff --git a/docs/manual.txt b/docs/manual.txt
index b2d0de14..12d8031e 100644
--- a/docs/manual.txt
+++ b/docs/manual.txt
@@ -429,9 +429,6 @@
After connected to server, Irssi can automatically change your user
mode. You can set it with /SET usermode , default is +i.
- /SET resolve_prefer_ipv6 - If ON, prefer IPv6 for hosts that
- have both v4 and v6 addresses.
-
5.5 Automatic reconnecting
If you get disconnected from server, Irssi will try to reconnect
diff --git a/src/core/servers.c b/src/core/servers.c
index e18f8d9c..66060a7f 100644
--- a/src/core/servers.c
+++ b/src/core/servers.c
@@ -710,7 +710,6 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto)
void servers_init(void)
{
- settings_add_bool("server", "resolve_prefer_ipv6", FALSE);
settings_add_bool("server", "resolve_reverse_lookup", FALSE);
lookup_servers = servers = NULL;
From f39723f6510bf57c5d21d62d55be6eefb6305078 Mon Sep 17 00:00:00 2001
From: dequis
Date: Thu, 17 Sep 2015 00:55:31 -0300
Subject: [PATCH 46/82] Fix FS#905, mangled text when pasted line length
exceeds 400
http://bugs.irssi.org/index.php?do=details&task_id=905
Not using the patch from that ticket, the issue turned out to be that
(dest - last_lf_pos) returned number of unichr, not bytes, so that's 4
times less than what the size parameter of memmove() should be.
---
src/fe-text/gui-readline.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index edc4c55d..ec61e317 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -237,7 +237,7 @@ static void paste_buffer_join_lines(GArray *buf)
last_lf = FALSE;
if (++line_len >= 400 && last_lf_pos != NULL) {
memmove(last_lf_pos+1, last_lf_pos,
- dest - last_lf_pos);
+ (dest - last_lf_pos) * sizeof(unichar));
*last_lf_pos = '\n'; last_lf_pos = NULL;
line_len = 0;
dest++;
From 0823289fd9c6a2eec7ff04581426856d1dbb15e5 Mon Sep 17 00:00:00 2001
From: dequis
Date: Mon, 21 Sep 2015 22:53:53 -0300
Subject: [PATCH 47/82] Limit recursion depth of key/combo expansion in
key_states_scan()
Fixes FS#817 - "SegFault when executing bind command", which provides
the test case "/bind cleft key meta", which is stupid but now it doesn't
break things.
The limit of 100 is arbitrary, it means roughly 140 stack frames total.
The flyspray ticket mentions it crashes at 512, in my system it goes all
the way to 149677 stack frames.
http://bugs.irssi.org/index.php?do=details&task_id=817
---
src/fe-common/core/keyboard.c | 37 ++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c
index f138d4e2..fed7f9cb 100644
--- a/src/fe-common/core/keyboard.c
+++ b/src/fe-common/core/keyboard.c
@@ -31,6 +31,8 @@
#include "fe-windows.h"
#include "printtext.h"
+#define MAX_EXPAND_RECURSION 100
+
GSList *keyinfos;
static GHashTable *keys, *default_keys;
@@ -171,7 +173,7 @@ KEYINFO_REC *key_info_find(const char *id)
return NULL;
}
-static int expand_key(const char *key, GSList **out);
+static int expand_key(const char *key, GSList **out, int *limit);
#define expand_out_char(out, c) \
{ \
@@ -188,13 +190,17 @@ static int expand_key(const char *key, GSList **out);
g_slist_free(out); out = NULL; \
}
-static int expand_combo(const char *start, const char *end, GSList **out)
+static int expand_combo(const char *start, const char *end, GSList **out, int *limit)
{
KEY_REC *rec;
KEYINFO_REC *info;
GSList *tmp, *tmp2, *list, *copy, *newout;
char *str, *p;
+ if ((*limit)-- < 0) {
+ return FALSE;
+ }
+
if (start == end) {
/* single key */
expand_out_char(*out, *start);
@@ -229,7 +235,7 @@ static int expand_combo(const char *start, const char *end, GSList **out)
/* only one way to generate the combo, good */
rec = list->data;
g_slist_free(list);
- return expand_key(rec->key, out);
+ return expand_key(rec->key, out, limit);
}
/* multiple ways to generate the combo -
@@ -244,7 +250,11 @@ static int expand_combo(const char *start, const char *end, GSList **out)
copy = g_slist_append(copy, g_string_new(str->str));
}
- if (!expand_key(rec->key, ©)) {
+ if (!expand_key(rec->key, ©, limit)) {
+ if (*limit < 0) {
+ return FALSE;
+ }
+
/* illegal key combo, remove from list */
expand_out_free(copy);
} else {
@@ -254,7 +264,11 @@ static int expand_combo(const char *start, const char *end, GSList **out)
rec = list->data;
g_slist_free(list);
- if (!expand_key(rec->key, out)) {
+ if (!expand_key(rec->key, out, limit)) {
+ if (*limit < 0) {
+ return FALSE;
+ }
+
/* illegal key combo, remove from list */
expand_out_free(*out);
}
@@ -264,12 +278,16 @@ static int expand_combo(const char *start, const char *end, GSList **out)
}
/* Expand key code - returns TRUE if successful. */
-static int expand_key(const char *key, GSList **out)
+static int expand_key(const char *key, GSList **out, int *limit)
{
GSList *tmp;
const char *start;
int last_hyphen;
+ if ((*limit)-- < 0) {
+ return FALSE;
+ }
+
/* meta-^W^Gf -> ^[-^W-^G-f */
start = NULL; last_hyphen = TRUE;
for (; *key != '\0'; key++) {
@@ -279,7 +297,7 @@ static int expand_key(const char *key, GSList **out)
continue;
}
- if (!expand_combo(start, key-1, out))
+ if (!expand_combo(start, key-1, out, limit))
return FALSE;
expand_out_char(*out, '-');
start = NULL;
@@ -332,7 +350,7 @@ static int expand_key(const char *key, GSList **out)
}
if (start != NULL)
- return expand_combo(start, key-1, out);
+ return expand_combo(start, key-1, out, limit);
for (tmp = *out; tmp != NULL; tmp = tmp->next) {
GString *str = tmp->data;
@@ -346,12 +364,13 @@ static int expand_key(const char *key, GSList **out)
static void key_states_scan_key(const char *key, KEY_REC *rec)
{
GSList *tmp, *out;
+ int limit = MAX_EXPAND_RECURSION;
if (g_strcmp0(rec->info->id, "key") == 0)
return;
out = g_slist_append(NULL, g_string_new(NULL));
- if (expand_key(key, &out)) {
+ if (expand_key(key, &out, &limit)) {
for (tmp = out; tmp != NULL; tmp = tmp->next) {
GString *str = tmp->data;
From bf36f71b99b18401dbc6105509b0285146b37286 Mon Sep 17 00:00:00 2001
From: dequis
Date: Tue, 22 Sep 2015 00:01:04 -0300
Subject: [PATCH 48/82] Fix #291, "/msg +#channel incorrectly shows up as
Nick:@#channel"
Just passing the full target to the "message irc op_public" signal
handler and letting it do the cleanup.
The fe_channel_skip_prefix() call in event_privmsg() is kept because
recode_in() needs a real channel name, but
There was similar code in sig_message_own_wall(), but that one is
correct - the /wall command always sends NOTICE @#chan, so I added a
comment down there to make it clear.
---
src/fe-common/irc/fe-events.c | 10 ++++++----
src/fe-common/irc/fe-irc-messages.c | 22 +++++++++++++++++-----
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c
index 3a01b9eb..850174c5 100644
--- a/src/fe-common/irc/fe-events.c
+++ b/src/fe-common/irc/fe-events.c
@@ -56,11 +56,13 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data,
if (fe_channel_is_opchannel(server, target)) {
/* Hybrid 6 feature, send msg to all ops in channel */
- target = (char *)fe_channel_skip_prefix(server, target);
- recoded = recode_in(SERVER(server), msg, target);
+ const char *cleantarget = fe_channel_skip_prefix(server, target);
+ recoded = recode_in(SERVER(server), msg, cleantarget);
+
+ /* pass the original target to the signal, with the @+ here
+ * the other one is only needed for recode_in*/
signal_emit("message irc op_public", 5,
- server, recoded, nick, addr,
- get_visible_target(server, target));
+ server, recoded, nick, addr, target);
} else {
recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick);
signal_emit(server_ischannel(SERVER(server), target) ?
diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c
index 11d158af..110fb29a 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -37,6 +37,7 @@
#include "fe-queries.h"
#include "window-items.h"
#include "fe-irc-channels.h"
+#include "fe-irc-server.h"
static void sig_message_own_public(SERVER_REC *server, const char *msg,
const char *target, const char *origtarget)
@@ -70,18 +71,28 @@ static void sig_message_irc_op_public(SERVER_REC *server, const char *msg,
const char *nick, const char *address,
const char *target)
{
- char *nickmode, *optarget;
+ char *nickmode, *optarget, *prefix;
+ const char *cleantarget;
+
+ /* only skip here so the difference can be stored in prefix */
+ cleantarget = fe_channel_skip_prefix(IRC_SERVER(server), target);
+ prefix = g_strndup(target, cleantarget - target);
+
+ /* and clean the rest here */
+ cleantarget = get_visible_target(IRC_SERVER(server), cleantarget);
nickmode = channel_get_nickmode(channel_find(server, target),
nick);
- optarget = g_strconcat("@", target, NULL);
- printformat_module("fe-common/core", server, target,
+ optarget = g_strconcat(prefix, cleantarget, NULL);
+
+ printformat_module("fe-common/core", server, cleantarget,
MSGLEVEL_PUBLIC,
TXT_PUBMSG_CHANNEL,
nick, optarget, msg, nickmode);
g_free(nickmode);
- g_free(optarget);
+ g_free(optarget);
+ g_free(prefix);
}
static void sig_message_own_wall(SERVER_REC *server, const char *msg,
@@ -92,7 +103,8 @@ static void sig_message_own_wall(SERVER_REC *server, const char *msg,
nickmode = channel_get_nickmode(channel_find(server, target),
server->nick);
- optarget = g_strconcat("@", target, NULL);
+ /* this is always @, skip_prefix is not needed here */
+ optarget = g_strconcat("@", target, NULL);
printformat_module("fe-common/core", server, target,
MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
MSGLEVEL_NO_ACT,
From 99f074b0db2d723c3a1ddbdc5226f54f24b01989 Mon Sep 17 00:00:00 2001
From: dequis
Date: Tue, 22 Sep 2015 01:17:15 -0300
Subject: [PATCH 49/82] fe_channel_skip_prefix: fix return value (FALSE/NULL
isn't valid)
The return value is a char*, and here it was false which is 0 which is
more or less the same as null.
That could have been a crash somewhere, the functions that call this
don't expect null ever.
---
src/fe-common/irc/fe-irc-channels.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c
index d5f17bd0..a2737fc3 100644
--- a/src/fe-common/irc/fe-irc-channels.c
+++ b/src/fe-common/irc/fe-irc-channels.c
@@ -56,7 +56,7 @@ const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target)
/* Exit early if target doesn't name a channel */
if (server_ischannel(SERVER(server), target) == FALSE)
- return FALSE;
+ return target;
statusmsg = g_hash_table_lookup(server->isupport, "statusmsg");
From f5f3d7cc98f24799f562e8d3126ea1c2786a6547 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 22 Sep 2015 21:59:17 +0200
Subject: [PATCH 50/82] Revert "Network and IPv{4,6} related changes"
---
docs/help/in/toggle.in | 2 +-
docs/manual.txt | 3 ++
src/core/chat-commands.c | 6 +--
src/core/chatnet-rec.h | 2 +-
src/core/net-nonblock.c | 38 +++++++++----
src/core/net-nonblock.h | 4 +-
src/core/network.c | 98 ++++++++++++++++++++++++++++------
src/core/network.h | 2 +-
src/core/server-connect-rec.h | 2 +-
src/core/server-setup-rec.h | 2 +-
src/core/servers-reconnect.c | 10 ++--
src/core/servers-setup.c | 67 ++++++++++++++++-------
src/core/servers-setup.h | 2 +-
src/core/servers.c | 67 ++++++++++++++++-------
src/core/servers.h | 3 +-
src/fe-common/core/fe-server.c | 4 +-
src/fe-common/irc/fe-ircnet.c | 4 +-
src/irc/dcc/dcc.c | 4 +-
src/irc/proxy/listen.c | 9 ++--
19 files changed, 241 insertions(+), 88 deletions(-)
diff --git a/docs/help/in/toggle.in b/docs/help/in/toggle.in
index 71f5c8f4..f87a6462 100644
--- a/docs/help/in/toggle.in
+++ b/docs/help/in/toggle.in
@@ -15,7 +15,7 @@
%9Examples:%9
- /TOGGLE resolve_reverse_lookup
+ /TOGGLE resolve_prefer_ipv6
/TOGGLE channels_rejoin_unavailable ON
%9See also:%9 SET
diff --git a/docs/manual.txt b/docs/manual.txt
index 12d8031e..b2d0de14 100644
--- a/docs/manual.txt
+++ b/docs/manual.txt
@@ -429,6 +429,9 @@
After connected to server, Irssi can automatically change your user
mode. You can set it with /SET usermode , default is +i.
+ /SET resolve_prefer_ipv6 - If ON, prefer IPv6 for hosts that
+ have both v4 and v6 addresses.
+
5.5 Automatic reconnecting
If you get disconnected from server, Irssi will try to reconnect
diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c
index 9c28a1fc..8e881679 100644
--- a/src/core/chat-commands.c
+++ b/src/core/chat-commands.c
@@ -128,10 +128,10 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
host = g_hash_table_lookup(optlist, "host");
if (host != NULL && *host != '\0') {
- IPADDR ip;
+ IPADDR ip4, ip6;
- if (net_gethostbyname(host, &ip) == 0)
- server_connect_own_ip_save(conn, &ip);
+ if (net_gethostbyname(host, &ip4, &ip6) == 0)
+ server_connect_own_ip_save(conn, &ip4, &ip6);
}
cmd_params_free(free_arg);
diff --git a/src/core/chatnet-rec.h b/src/core/chatnet-rec.h
index 3044643a..e3ed8aa0 100644
--- a/src/core/chatnet-rec.h
+++ b/src/core/chatnet-rec.h
@@ -9,4 +9,4 @@ char *realname;
char *own_host; /* address to use when connecting this server */
char *autosendcmd; /* command to send after connecting to this ircnet */
-IPADDR *own_ip; /* resolved own_address if not NULL */
+IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c
index bc8c4b96..e637e673 100644
--- a/src/core/net-nonblock.c
+++ b/src/core/net-nonblock.c
@@ -103,12 +103,15 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
srand(time(NULL));
memset(&rec, 0, sizeof(rec));
- rec.error = net_gethostbyname(addr, &rec.ip);
+ rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6);
if (rec.error == 0) {
errorstr = NULL;
if (reverse_lookup) {
/* reverse lookup the IP, ignore any error */
- net_gethostbyaddr(&rec.ip, &rec.host);
+ if (rec.ip4.family != 0)
+ net_gethostbyaddr(&rec.ip4, &rec.host4);
+ if (rec.ip6.family != 0)
+ net_gethostbyaddr(&rec.ip6, &rec.host6);
}
} else {
errorstr = net_gethosterror(rec.error);
@@ -119,11 +122,18 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
if (rec.errlen != 0)
g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen);
else {
- if (rec.host) {
- len = strlen(rec.host) + 1;
+ if (rec.host4) {
+ len = strlen(rec.host4) + 1;
g_io_channel_write_block(pipe, (void *) &len,
sizeof(int));
- g_io_channel_write_block(pipe, (void *) rec.host,
+ g_io_channel_write_block(pipe, (void *) rec.host4,
+ len);
+ }
+ if (rec.host6) {
+ len = strlen(rec.host6) + 1;
+ g_io_channel_write_block(pipe, (void *) &len,
+ sizeof(int));
+ g_io_channel_write_block(pipe, (void *) rec.host6,
len);
}
}
@@ -144,7 +154,8 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
rec->error = -1;
rec->errorstr = NULL;
- rec->host = NULL;
+ rec->host4 = NULL;
+ rec->host6 = NULL;
#ifndef WIN32
fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK);
@@ -163,10 +174,15 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
rec->errorstr = g_malloc0(rec->errlen+1);
g_io_channel_read_block(pipe, rec->errorstr, rec->errlen);
} else {
- if (rec->host) {
+ if (rec->host4) {
g_io_channel_read_block(pipe, &len, sizeof(int));
- rec->host = g_malloc0(len);
- g_io_channel_read_block(pipe, rec->host, len);
+ rec->host4 = g_malloc0(len);
+ g_io_channel_read_block(pipe, rec->host4, len);
+ }
+ if (rec->host6) {
+ g_io_channel_read_block(pipe, &len, sizeof(int));
+ rec->host6 = g_malloc0(len);
+ g_io_channel_read_block(pipe, rec->host6, len);
}
}
@@ -211,6 +227,7 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
{
RESOLVED_IP_REC iprec;
GIOChannel *handle;
+ IPADDR *ip;
g_return_if_fail(rec != NULL);
@@ -224,8 +241,9 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
g_io_channel_shutdown(rec->pipes[1], TRUE, NULL);
g_io_channel_unref(rec->pipes[1]);
+ ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6;
handle = iprec.error == -1 ? NULL :
- net_connect_ip(&iprec.ip, rec->port, rec->my_ip);
+ net_connect_ip(ip, rec->port, rec->my_ip);
g_free_not_null(rec->my_ip);
diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h
index 581536b3..af5968c8 100644
--- a/src/core/net-nonblock.h
+++ b/src/core/net-nonblock.h
@@ -4,12 +4,12 @@
#include "network.h"
typedef struct {
- IPADDR ip; /* resolved ip address */
+ IPADDR ip4, ip6; /* resolved ip addresses */
int error; /* error, 0 = no error, -1 = error: */
int errlen; /* error text length */
char *errorstr; /* error string - dynamically allocated, you'll
need to free() it yourself unless it's NULL */
- char *host; /* dito */
+ char *host4, *host6; /* dito */
} RESOLVED_IP_REC;
typedef struct {
diff --git a/src/core/network.c b/src/core/network.c
index 303483c6..bfaa47fb 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -137,14 +137,35 @@ static int sin_get_port(union sockaddr_union *so)
/* Connect to socket */
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
{
- IPADDR ip;
+ IPADDR ip4, ip6, *ip;
g_return_val_if_fail(addr != NULL, NULL);
- if (net_gethostbyname(addr, &ip) == -1)
+ if (net_gethostbyname(addr, &ip4, &ip6) == -1)
return NULL;
- return net_connect_ip(&ip, port, my_ip);
+ if (my_ip == NULL) {
+ /* prefer IPv4 addresses */
+ ip = ip4.family != 0 ? &ip4 : &ip6;
+ } else if (IPADDR_IS_V6(my_ip)) {
+ /* my_ip is IPv6 address, use it if possible */
+ if (ip6.family != 0)
+ ip = &ip6;
+ else {
+ my_ip = NULL;
+ ip = &ip4;
+ }
+ } else {
+ /* my_ip is IPv4 address, use it if possible */
+ if (ip4.family != 0)
+ ip = &ip4;
+ else {
+ my_ip = NULL;
+ ip = &ip6;
+ }
+ }
+
+ return net_connect_ip(ip, port, my_ip);
}
/* Connect to socket with ip address */
@@ -392,35 +413,82 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
-int net_gethostbyname(const char *addr, IPADDR *ip)
+int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{
+#ifdef HAVE_IPV6
union sockaddr_union *so;
- struct addrinfo hints, *ailist;
- int ret;
+ struct addrinfo hints, *ai, *ailist;
+ int ret, count_v4, count_v6, use_v4, use_v6;
+#else
+ struct hostent *hp;
+ int count;
+#endif
g_return_val_if_fail(addr != NULL, -1);
- memset(ip, 0, sizeof(IPADDR));
+ memset(ip4, 0, sizeof(IPADDR));
+ memset(ip6, 0, sizeof(IPADDR));
+#ifdef HAVE_IPV6
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM;
-#ifdef HAVE_IPV6
- hints.ai_family = AF_UNSPEC;
-#else
- hints.ai_family = AF_INET;
-#endif
- hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
/* save error to host_error for later use */
ret = getaddrinfo(addr, NULL, &hints, &ailist);
if (ret != 0)
return ret;
- so = (const union sockaddr_union *)ailist->ai_addr;
- sin_get_ip(so, ip);
+ /* count IPs */
+ count_v4 = count_v6 = 0;
+ for (ai = ailist; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET)
+ count_v4++;
+ else if (ai->ai_family == AF_INET6)
+ count_v6++;
+ }
+
+ if (count_v4 == 0 && count_v6 == 0)
+ return HOST_NOT_FOUND; /* shouldn't happen? */
+
+ /* if there are multiple addresses, return random one */
+ use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4;
+ use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6;
+
+ count_v4 = count_v6 = 0;
+ for (ai = ailist; ai != NULL; ai = ai->ai_next) {
+ so = (union sockaddr_union *) ai->ai_addr;
+
+ if (ai->ai_family == AF_INET) {
+ if (use_v4 == count_v4)
+ sin_get_ip(so, ip4);
+ count_v4++;
+ } else if (ai->ai_family == AF_INET6) {
+ if (use_v6 == count_v6)
+ sin_get_ip(so, ip6);
+ count_v6++;
+ }
+ }
freeaddrinfo(ailist);
+ return 0;
+#else
+ hp = gethostbyname(addr);
+ if (hp == NULL)
+ return h_errno;
+
+ /* count IPs */
+ count = 0;
+ while (hp->h_addr_list[count] != NULL)
+ count++;
+
+ if (count == 0)
+ return HOST_NOT_FOUND; /* shouldn't happen? */
+
+ /* if there are multiple addresses, return random one */
+ ip4->family = AF_INET;
+ memcpy(&ip4->ip, hp->h_addr_list[rand() % count], 4);
return 0;
+#endif
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
diff --git a/src/core/network.h b/src/core/network.h
index ea8b3055..fa7e9675 100644
--- a/src/core/network.h
+++ b/src/core/network.h
@@ -71,7 +71,7 @@ int net_transmit(GIOChannel *handle, const char *data, int len);
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
-int net_gethostbyname(const char *addr, IPADDR *ip);
+int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6);
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name);
diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h
index 3f24e7d8..80c5761b 100644
--- a/src/core/server-connect-rec.h
+++ b/src/core/server-connect-rec.h
@@ -16,7 +16,7 @@ char *address;
int port;
char *chatnet;
-IPADDR *own_ip;
+IPADDR *own_ip4, *own_ip6;
char *password;
char *nick;
diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h
index fbf49b2c..2c9614c7 100644
--- a/src/core/server-setup-rec.h
+++ b/src/core/server-setup-rec.h
@@ -19,7 +19,7 @@ char *ssl_capath;
char *ssl_ciphers;
char *own_host; /* address to use when connecting this server */
-IPADDR *own_ip; /* resolved own_address if not NULL */
+IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
time_t last_connect; /* to avoid reconnecting too fast.. */
diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c
index 3ba18ad0..ae97ecd2 100644
--- a/src/core/servers-reconnect.c
+++ b/src/core/servers-reconnect.c
@@ -177,9 +177,13 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
dest->username = g_strdup(src->username);
dest->realname = g_strdup(src->realname);
- if (src->own_ip != NULL) {
- dest->own_ip = g_new(IPADDR, 1);
- memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR));
+ if (src->own_ip4 != NULL) {
+ dest->own_ip4 = g_new(IPADDR, 1);
+ memcpy(dest->own_ip4, src->own_ip4, sizeof(IPADDR));
+ }
+ if (src->own_ip6 != NULL) {
+ dest->own_ip6 = g_new(IPADDR, 1);
+ memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR));
}
dest->channels = g_strdup(src->channels);
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index e8506f0f..90a447d4 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -33,22 +33,32 @@ GSList *setupservers;
static char *old_source_host;
int source_host_ok; /* Use source_host_ip .. */
-IPADDR source_host_ip; /* Resolved address */
+IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
-static void save_ips(IPADDR *ip, IPADDR **save_ip)
+static void save_ips(IPADDR *ip4, IPADDR *ip6,
+ IPADDR **save_ip4, IPADDR **save_ip6)
{
- if (ip->family == 0)
- g_free_and_null(*save_ip);
+ if (ip4->family == 0)
+ g_free_and_null(*save_ip4);
else {
- if (*save_ip == NULL)
- *save_ip = g_new(IPADDR, 1);
- memcpy(*save_ip, ip, sizeof(IPADDR));
+ if (*save_ip4 == NULL)
+ *save_ip4 = g_new(IPADDR, 1);
+ memcpy(*save_ip4, ip4, sizeof(IPADDR));
+ }
+
+ if (ip6->family == 0)
+ g_free_and_null(*save_ip6);
+ else {
+ if (*save_ip6 == NULL)
+ *save_ip6 = g_new(IPADDR, 1);
+ memcpy(*save_ip6, ip6, sizeof(IPADDR));
}
}
static void get_source_host_ip(void)
{
const char *hostname;
+ IPADDR ip4, ip6;
if (source_host_ok)
return;
@@ -56,21 +66,28 @@ static void get_source_host_ip(void)
/* FIXME: This will block! */
hostname = settings_get_str("hostname");
source_host_ok = *hostname != '\0' &&
- net_gethostbyname(hostname, &source_host_ip) == 0;
+ net_gethostbyname(hostname, &ip4, &ip6) == 0;
+
+ if (source_host_ok)
+ save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6);
+ else {
+ g_free_and_null(source_host_ip4);
+ g_free_and_null(source_host_ip6);
+ }
}
static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host,
- IPADDR **own_ip)
+ IPADDR **own_ip4, IPADDR **own_ip6)
{
- IPADDR ip;
+ IPADDR ip4, ip6;
- if (*own_ip == NULL) {
+ if (*own_ip4 == NULL && *own_ip6 == NULL) {
/* resolve the IP */
- if (net_gethostbyname(own_host, &ip) == 0)
- save_ips(&ip, own_ip);
+ if (net_gethostbyname(own_host, &ip4, &ip6) == 0)
+ save_ips(&ip4, &ip6, own_ip4, own_ip6);
}
- server_connect_own_ip_save(conn, *own_ip);
+ server_connect_own_ip_save(conn, *own_ip4, *own_ip6);
}
/* Fill information to connection from server setup record */
@@ -81,7 +98,8 @@ void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
g_return_if_fail(IS_SERVER_SETUP(sserver));
if (sserver->own_host != NULL) {
- conn_set_ip(conn, sserver->own_host, &sserver->own_ip);
+ conn_set_ip(conn, sserver->own_host,
+ &sserver->own_ip4, &sserver->own_ip6);
}
if (sserver->chatnet != NULL && conn->chatnet == NULL)
@@ -121,9 +139,13 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn,
}
/* source IP */
- if (source_host_ok) {
- conn->own_ip = g_new(IPADDR, 1);
- memcpy(conn->own_ip, &source_host_ip, sizeof(IPADDR));
+ if (source_host_ip4 != NULL) {
+ conn->own_ip4 = g_new(IPADDR, 1);
+ memcpy(conn->own_ip4, source_host_ip4, sizeof(IPADDR));
+ }
+ if (source_host_ip6 != NULL) {
+ conn->own_ip6 = g_new(IPADDR, 1);
+ memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR));
}
signal_emit("server setup fill connect", 1, conn);
@@ -184,7 +206,8 @@ static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn,
conn->realname = g_strdup(chatnet->realname);;
}
if (chatnet->own_host != NULL) {
- conn_set_ip(conn, chatnet->own_host, &chatnet->own_ip);
+ conn_set_ip(conn, chatnet->own_host,
+ &chatnet->own_ip4, &chatnet->own_ip6);
}
signal_emit("server setup fill chatnet", 2, conn, chatnet);
@@ -458,7 +481,8 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec)
signal_emit("server setup destroyed", 1, rec);
g_free_not_null(rec->own_host);
- g_free_not_null(rec->own_ip);
+ g_free_not_null(rec->own_ip4);
+ g_free_not_null(rec->own_ip6);
g_free_not_null(rec->chatnet);
g_free_not_null(rec->password);
g_free_not_null(rec->ssl_cert);
@@ -532,6 +556,7 @@ void servers_setup_init(void)
settings_add_str("proxy", "proxy_password", "");
setupservers = NULL;
+ source_host_ip4 = source_host_ip6 = NULL;
old_source_host = NULL;
read_settings();
@@ -542,6 +567,8 @@ void servers_setup_init(void)
void servers_setup_deinit(void)
{
+ g_free_not_null(source_host_ip4);
+ g_free_not_null(source_host_ip6);
g_free_not_null(old_source_host);
while (setupservers != NULL)
diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h
index c4878094..f7601a68 100644
--- a/src/core/servers-setup.h
+++ b/src/core/servers-setup.h
@@ -16,7 +16,7 @@ struct _SERVER_SETUP_REC {
extern GSList *setupservers;
-extern IPADDR source_host_ip; /* Resolved address */
+extern IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
extern int source_host_ok; /* Use source_host_ip .. */
/* Fill reconnection specific information to connection
diff --git a/src/core/servers.c b/src/core/servers.c
index 66060a7f..3342304e 100644
--- a/src/core/servers.c
+++ b/src/core/servers.c
@@ -218,7 +218,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
return;
if (ip != NULL) {
- own_ip = server->connrec->own_ip;
+ own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4;
port = server->connrec->proxy != NULL ?
server->connrec->proxy_port : server->connrec->port;
handle = server->connrec->use_ssl ?
@@ -280,15 +280,30 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
server->connect_pipe[0] = NULL;
server->connect_pipe[1] = NULL;
- ip = NULL;
-
- if (iprec.error == 0) {
- // FIXME : REMOVE THIS BEFORE MERGE
- if (server->connrec->family)
- g_assert(server->connrec->family == iprec.ip.family);
-
- ip = &iprec.ip;
- servername = iprec.host;
+ /* figure out if we should use IPv4 or v6 address */
+ if (iprec.error != 0) {
+ /* error */
+ ip = NULL;
+ } else if (server->connrec->family == AF_INET) {
+ /* force IPv4 connection */
+ ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4;
+ servername = iprec.host4;
+ } else if (server->connrec->family == AF_INET6) {
+ /* force IPv6 connection */
+ ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6;
+ servername = iprec.host6;
+ } else {
+ /* pick the one that was found, or if both do it like
+ /SET resolve_prefer_ipv6 says. */
+ if (iprec.ip4.family == 0 ||
+ (iprec.ip6.family != 0 &&
+ settings_get_bool("resolve_prefer_ipv6"))) {
+ ip = &iprec.ip6;
+ servername = iprec.host6;
+ } else {
+ ip = &iprec.ip4;
+ servername = iprec.host4;
+ }
}
if (ip != NULL) {
@@ -322,7 +337,8 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
}
g_free(iprec.errorstr);
- g_free(iprec.host);
+ g_free(iprec.host4);
+ g_free(iprec.host6);
}
SERVER_REC *server_connect(SERVER_CONNECT_REC *conn)
@@ -607,7 +623,8 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
g_free_not_null(conn->address);
g_free_not_null(conn->chatnet);
- g_free_not_null(conn->own_ip);
+ g_free_not_null(conn->own_ip4);
+ g_free_not_null(conn->own_ip6);
g_free_not_null(conn->password);
g_free_not_null(conn->nick);
@@ -637,15 +654,26 @@ void server_change_nick(SERVER_REC *server, const char *nick)
}
/* Update own IPv4 and IPv6 records */
-void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip)
+void server_connect_own_ip_save(SERVER_CONNECT_REC *conn,
+ IPADDR *ip4, IPADDR *ip6)
{
- if (ip == NULL || ip->family == 0)
- g_free_and_null(conn->own_ip);
+ if (ip4 == NULL || ip4->family == 0)
+ g_free_and_null(conn->own_ip4);
+ if (ip6 == NULL || ip6->family == 0)
+ g_free_and_null(conn->own_ip6);
- if (ip != NULL && ip->family != 0) {
- if (conn->own_ip == NULL)
- conn->own_ip = g_new0(IPADDR, 1);
- memcpy(conn->own_ip, ip, sizeof(IPADDR));
+ if (ip4 != NULL && ip4->family != 0) {
+ /* IPv4 address was found */
+ if (conn->own_ip4 == NULL)
+ conn->own_ip4 = g_new0(IPADDR, 1);
+ memcpy(conn->own_ip4, ip4, sizeof(IPADDR));
+ }
+
+ if (ip6 != NULL && ip6->family != 0) {
+ /* IPv6 address was found */
+ if (conn->own_ip6 == NULL)
+ conn->own_ip6 = g_new0(IPADDR, 1);
+ memcpy(conn->own_ip6, ip6, sizeof(IPADDR));
}
}
@@ -710,6 +738,7 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto)
void servers_init(void)
{
+ settings_add_bool("server", "resolve_prefer_ipv6", FALSE);
settings_add_bool("server", "resolve_reverse_lookup", FALSE);
lookup_servers = servers = NULL;
diff --git a/src/core/servers.h b/src/core/servers.h
index 314faa32..f39c650b 100644
--- a/src/core/servers.h
+++ b/src/core/servers.h
@@ -67,7 +67,8 @@ void server_connect_failed(SERVER_REC *server, const char *msg);
void server_change_nick(SERVER_REC *server, const char *nick);
/* Update own IPv4 and IPv6 records */
-void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip);
+void server_connect_own_ip_save(SERVER_CONNECT_REC *conn,
+ IPADDR *ip4, IPADDR *ip6);
/* `optlist' should contain only one unknown key - the server tag.
returns NULL if there was unknown -option */
diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c
index f8558ad1..429e6dac 100644
--- a/src/fe-common/core/fe-server.c
+++ b/src/fe-common/core/fe-server.c
@@ -138,7 +138,7 @@ static void cmd_server_add(const char *data)
if (*password != '\0') g_free_and_null(rec->password);
if (g_hash_table_lookup(optlist, "host")) {
g_free_and_null(rec->own_host);
- rec->own_ip = NULL;
+ rec->own_ip4 = rec->own_ip6 = NULL;
}
}
@@ -193,7 +193,7 @@ static void cmd_server_add(const char *data)
value = g_hash_table_lookup(optlist, "host");
if (value != NULL && *value != '\0') {
rec->own_host = g_strdup(value);
- rec->own_ip = NULL;
+ rec->own_ip4 = rec->own_ip6 = NULL;
}
signal_emit("server add fill", 2, rec, optlist);
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 4071f367..6618edd7 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -108,7 +108,7 @@ static void cmd_network_add(const char *data)
if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname);
if (g_hash_table_lookup(optlist, "host")) {
g_free_and_null(rec->own_host);
- rec->own_ip = NULL;
+ rec->own_ip4 = rec->own_ip6 = NULL;
}
if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode);
if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd);
@@ -140,7 +140,7 @@ static void cmd_network_add(const char *data)
value = g_hash_table_lookup(optlist, "host");
if (value != NULL && *value != '\0') {
rec->own_host = g_strdup(value);
- rec->own_ip = NULL;
+ rec->own_ip4 = rec->own_ip6 = NULL;
}
value = g_hash_table_lookup(optlist, "usermode");
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index 7fef2ae5..17f6c477 100644
--- a/src/irc/dcc/dcc.c
+++ b/src/irc/dcc/dcc.c
@@ -264,12 +264,12 @@ GIOChannel *dcc_connect_ip(IPADDR *ip, int port)
}
if (own_ip == NULL)
- own_ip = &source_host_ip;
+ own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4;
handle = net_connect_ip(ip, port, own_ip);
if (handle == NULL && errno == EADDRNOTAVAIL && own_ip != NULL) {
/* dcc_own_ip is external address */
- own_ip = &source_host_ip;
+ own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4;
handle = net_connect_ip(ip, port, own_ip);
}
return handle;
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 16950c79..dcc94e6b 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -585,7 +585,7 @@ static LISTEN_REC *find_listen(const char *ircnet, int port)
static void add_listen(const char *ircnet, int port)
{
LISTEN_REC *rec;
- IPADDR ip, *my_ip;
+ IPADDR ip4, ip6, *my_ip;
if (port <= 0 || *ircnet == '\0')
return;
@@ -593,13 +593,16 @@ static void add_listen(const char *ircnet, int port)
/* bind to specific host/ip? */
my_ip = NULL;
if (*settings_get_str("irssiproxy_bind") != '\0') {
- if (net_gethostbyname(settings_get_str("irssiproxy_bind"), &ip) != 0) {
+ if (net_gethostbyname(settings_get_str("irssiproxy_bind"),
+ &ip4, &ip6) != 0) {
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
"Proxy: can not resolve '%s' - aborting",
settings_get_str("irssiproxy_bind"));
return;
}
- my_ip = &ip;
+
+ my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 ||
+ settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4;
}
rec = g_new0(LISTEN_REC, 1);
From 5a4be0f4f5f36787e98215d87b88a50a5f7e7e01 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Tue, 22 Sep 2015 22:39:44 +0200
Subject: [PATCH 51/82] Add new setting to optionally modify behaviour of
hilight_nick_matches
Fix indentation
Remove unused variables that crept into the nick_match_msg_everywhere function
---
src/core/nicklist.c | 9 +++++++++
src/core/nicklist.h | 1 +
src/fe-common/core/fe-messages.c | 5 ++++-
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/core/nicklist.c b/src/core/nicklist.c
index a96b8a9e..c88f5d6d 100644
--- a/src/core/nicklist.c
+++ b/src/core/nicklist.c
@@ -21,6 +21,7 @@
#include "module.h"
#include "signals.h"
#include "misc.h"
+#include "settings.h"
#include "servers.h"
#include "channels.h"
@@ -571,6 +572,14 @@ int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick)
}
}
+int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char *nick)
+{
+ g_return_val_if_fail(nick != NULL, FALSE);
+ g_return_val_if_fail(msg != NULL, FALSE);
+
+ return stristr_full(msg, nick);
+}
+
void nicklist_init(void)
{
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
diff --git a/src/core/nicklist.h b/src/core/nicklist.h
index 55dfd5ef..5e0f4f75 100644
--- a/src/core/nicklist.h
+++ b/src/core/nicklist.h
@@ -55,6 +55,7 @@ int nicklist_compare(NICK_REC *p1, NICK_REC *p2, const char *nick_prefix);
/* Check is `msg' is meant for `nick'. */
int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick);
+int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char *nick);
void nicklist_init(void);
void nicklist_deinit(void);
diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c
index 3bd2b666..d09c1b0b 100644
--- a/src/fe-common/core/fe-messages.c
+++ b/src/fe-common/core/fe-messages.c
@@ -183,7 +183,9 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
nickrec = nicklist_find(chanrec, nick);
for_me = !settings_get_bool("hilight_nick_matches") ? FALSE :
- nick_match_msg(chanrec, msg, server->nick);
+ !settings_get_bool("hilight_nick_matches_everywhere") ?
+ nick_match_msg(chanrec, msg, server->nick) :
+ nick_match_msg_everywhere(chanrec, msg, server->nick);
hilight = for_me ? NULL :
hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
color = (hilight == NULL) ? NULL : hilight_get_color(hilight);
@@ -694,6 +696,7 @@ void fe_messages_init(void)
(GCompareFunc) g_direct_equal);
settings_add_bool("lookandfeel", "hilight_nick_matches", TRUE);
+ settings_add_bool("lookandfeel", "hilight_nick_matches_everywhere", FALSE);
settings_add_bool("lookandfeel", "emphasis", TRUE);
settings_add_bool("lookandfeel", "emphasis_replace", FALSE);
settings_add_bool("lookandfeel", "emphasis_multiword", FALSE);
From b5c3e90802e926e35ad9a4f1f02403578a3ff392 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Tue, 22 Sep 2015 23:09:55 +0200
Subject: [PATCH 52/82] Fix return value from nick_match_msg_everywhere
---
src/core/nicklist.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/core/nicklist.c b/src/core/nicklist.c
index c88f5d6d..160deb6a 100644
--- a/src/core/nicklist.c
+++ b/src/core/nicklist.c
@@ -577,7 +577,12 @@ int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char
g_return_val_if_fail(nick != NULL, FALSE);
g_return_val_if_fail(msg != NULL, FALSE);
- return stristr_full(msg, nick);
+ char *ret = stristr_full(msg, nick);
+
+ if (ret != NULL)
+ return TRUE;
+
+ return FALSE;
}
void nicklist_init(void)
From 3f2eaf1d3a67eddd42dd88eccb39402d45297fcb Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Tue, 22 Sep 2015 23:16:41 +0200
Subject: [PATCH 53/82] Fix return value from nick_match_msg_everywhere, remove
#include 'settings.h'
---
src/core/nicklist.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/core/nicklist.c b/src/core/nicklist.c
index 160deb6a..770b0afc 100644
--- a/src/core/nicklist.c
+++ b/src/core/nicklist.c
@@ -21,7 +21,6 @@
#include "module.h"
#include "signals.h"
#include "misc.h"
-#include "settings.h"
#include "servers.h"
#include "channels.h"
@@ -577,12 +576,7 @@ int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char
g_return_val_if_fail(nick != NULL, FALSE);
g_return_val_if_fail(msg != NULL, FALSE);
- char *ret = stristr_full(msg, nick);
-
- if (ret != NULL)
- return TRUE;
-
- return FALSE;
+ return stristr_full(msg, nick) != NULL;
}
void nicklist_init(void)
From f247a43b97731cd1d58ec765dd2d10f885ef66dc Mon Sep 17 00:00:00 2001
From: dequis
Date: Tue, 22 Sep 2015 19:35:10 -0300
Subject: [PATCH 54/82] sig_message_irc_op_public: fix nickmode lookup, use
cleantarget instead
---
src/fe-common/irc/fe-irc-messages.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c
index 110fb29a..40ca306d 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -81,7 +81,7 @@ static void sig_message_irc_op_public(SERVER_REC *server, const char *msg,
/* and clean the rest here */
cleantarget = get_visible_target(IRC_SERVER(server), cleantarget);
- nickmode = channel_get_nickmode(channel_find(server, target),
+ nickmode = channel_get_nickmode(channel_find(server, cleantarget),
nick);
optarget = g_strconcat(prefix, cleantarget, NULL);
From 7ae742293926dde06be5563efb5acd19dc2c3a75 Mon Sep 17 00:00:00 2001
From: dequis
Date: Wed, 23 Sep 2015 03:17:29 -0300
Subject: [PATCH 55/82] Add multi-prefix to list of capabilities to request
Turns out event_names_list() in irc-nicklist.c already handles this.
event_who() just ignores it, which is probably a good idea since some of
the irc servers I tested this with have a bug that results in sending
multiple prefixes in the NAMES reply but not in the WHO one (they were
forks of ircd-hybrid before 7.3.0)
And NAMES always happens, anyway. WHO is omitted sometimes for huge
channels.
---
src/irc/core/irc-servers.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index 82584382..81f0c269 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -228,6 +228,8 @@ static void server_init(IRC_SERVER_REC *server)
if (conn->sasl_mechanism != SASL_MECHANISM_NONE)
cap_toggle(server, "sasl", TRUE);
+ cap_toggle(server, "multi-prefix", TRUE);
+
irc_send_cmd_now(server, "CAP LS");
if (conn->password != NULL && *conn->password != '\0') {
From d3df165e0b067461e49d7f065f3820739e9ba229 Mon Sep 17 00:00:00 2001
From: Ailin Nemui
Date: Sun, 12 Jul 2015 19:03:58 +0200
Subject: [PATCH 56/82] Improve the WINDOW help
Properly describe the window command.
Make help sort order deterministic.
---
docs/help/in/window.in | 84 +++++++++++++++++++++---------------------
syntax.pl | 2 +-
2 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/docs/help/in/window.in b/docs/help/in/window.in
index c965d3fb..6dde6c50 100644
--- a/docs/help/in/window.in
+++ b/docs/help/in/window.in
@@ -5,49 +5,49 @@
%9Parameters:%9
- LOG: Modifies the logging status.
- LOGFILE: Modifies the location to the log file.
- NEW: Creates a new window.
- CLOSE: Closes a window.
- REFNUM: Go to the window with the given number.
- GOTO: Go to the window with the given nickname, channel or number.
- NEXT: Go to the next window.
- LAST: Go to the last window.
- PREVIOUS: Go to the previous window.
- LEVEL: Modifies the text levels to display in the window.
- IMMORTAL: Modifies the window mortality status.
- SERVER: Set the active server of the window.
- ITEM PREV: Go to the previous item in the window.
- ITEM NEXT: Go to the next item in the window.
- ITEM GOTO: Go to the specified nickname, channel or window item number.
- ITEM MOVE: Move the active window item to another window.
- NUMBER: Move the active window to another position.
- NAME: Give the window a name.
- HISTORY: Clears the window history buffer.
- MOVE PREV: Move the window down.
- MOVE NEXT: Move the window up.
- MOVE FIRST: Move the window to the first position.
- MOVE LAST: Move the window to the last position.
- MOVE: Move the window.
- LIST: List all the windows.
- THEME: Applies a theme to the windows.
- GROW: Increase the window size when using split windows.
- SHRINK: Decrease the window size when using split windows.
- SIZE: Modify the window size when using split windows.
- BALANCE: Balance the window locations when using split windows.
- HIDE: Hide the window when using split windows.
- SHOW: Show the window when using split windows.
- UP: Go to the window above when using split windows.
- DOWN: Go to the window below when using split windows.
- LEFT: Go to the previous window.
- RIGHT: Go to the next window.
- STICK: Make the window sticky.
- MOVE LEFT: Move the window to the previous location.
- MOVE RIGHT: Move the window to the next location.
- MOVE UP: Move the window up when using split windows.
- MOVE DOWN: Move the window down when using split windows.
+ LOG: %|Turn on or off logging of the active window, optionally specifying the log file to use.
+ LOGFILE: %|Sets the location of the log file to use for window logging without starting to log.
+ NEW: %|Creates a new hidden or split window.
+ CLOSE: %|Closes the current window, the specified one or all windows in the given range.
+ REFNUM: %|Go to the window with the given number.
+ GOTO: %|Go to the window with activity, with the given nickname, channel or with the specified number.
+ NEXT: %|Go to the next window numerically.
+ LAST: %|Go to the previously active window.
+ PREVIOUS: %|Go to the previous window numerically.
+ LEVEL: %|Changes the text levels to display in the window, or query the current level.
+ IMMORTAL: %|Modifies or queries the window mortality status. Immortal windows have an extra protection against WINDOW CLOSE.
+ SERVER: %|Change the active server of the window or the server stickyness. If the server is sticky, it cannot be cycled with next_window_item/previous_window_item
+ ITEM PREV: %|Make the previous item in this window active.
+ ITEM NEXT: %|Make the next item in this window active.
+ ITEM GOTO: %|Change to the query with the specified nickname, channel with the given name or window item number.
+ ITEM MOVE: %|Move the active window item to another window, or move the channel or query item specified by their name to the current window.
+ NUMBER: %|Change the active window number to the specified number, swapping the window already in that place if required. With -sticky, protect the window number from renumbering done by windows_auto_renumber. (To re-set the sticky attribute, use WINDOW NUMBER again without -sticky.)
+ NAME: %|Change or clear the window name. Window names must be unique.
+ HISTORY: %|Set or clear a specific named history to use for this window. All windows with the same named history will share a history.
+ MOVE PREV: %|Move the window to the place of the numerically previous window. At the first position, move the window to the end and renumber the consecutive block that it was part of.
+ MOVE NEXT: %|Move the window to the place of the numerically next window. At the last position, move the window to the first position and renumber the consecutive block at first position (if any)
+ MOVE FIRST: %|Move the window to the first position. Any windows inbetween are moved to their numerically next positions.
+ MOVE LAST: %|Move the window to the last position. Any windows inbetween are moved to their numerically previous positions.
+ MOVE: %|Move the window to the specified number or the first number that is in use when moving the window in the direction of the specified position. Any windows inbetween are shifted towards the old position of the window (unused positions remain empty)
+ LIST: %|List all the windows.
+ THEME: %|Applies or removes a per-window theme.
+ GROW: %|Increase the size of the active split window by the specified number of lines.
+ SHRINK: %|Decrease the size of the active split window by the specified number of lines.
+ SIZE: %|Set the current split window size to the specified numer of lines.
+ BALANCE: %|Balance the heights of all split windows.
+ HIDE: %|Hides the current split window, or the split window specified by number or item name.
+ SHOW: %|Show the window specified by number or item name as a new split windows. It is made sticky when autostick_split_windows is turned on.
+ UP: %|Set the split window above the current one active. At the top, wraps to the bottom.
+ DOWN: %|Set the split window below the current one active. At the bottom, wraps to the top.
+ LEFT: %|Go to the previous window numerically that is part of the current sticky group (or not part of any sticky group).
+ RIGHT: %|Go to the next window numerically that is part of the current sticky group (or not part of any sticky group).
+ STICK: %|Make the currently active window sticky, or stick the window specified by number to the currently visible split window. Or turn off stickyness of the currently active window or the window specified by number.
+ MOVE LEFT: %|Move the window to the numerically previous location inside the current sticky group.
+ MOVE RIGHT: %|Move the window to the numerically next location inside the current sticky group.
+ MOVE UP: %|Move the current window to the sticky group of the split window above. If no sticky group remains, the split window collapses.
+ MOVE DOWN: %|Move the current window to the sticky group of the split window below. If no sticky group remains, the split window collapses.
- Add the required arguments for the given command.
+ %|Add the required arguments for the given command. Without arguments, the details (size, immortality, levels, server, name and sticky group) of the currently active window are displayed. If used with a number as argument, same as WINDOW REFNUM.
%9Description:%9
diff --git a/syntax.pl b/syntax.pl
index bf10451f..33bd12b4 100755
--- a/syntax.pl
+++ b/syntax.pl
@@ -10,7 +10,7 @@
# Remember to include the asterisk ('*').
$SRC_PATH='src';
-@files = `find src -name '*.c'`;
+@files = sort `find src -name '*.c'`;
foreach $file (@files) {
open (FILE, "$file");
From c9be1a7a80974858a21fc74191198189030df40b Mon Sep 17 00:00:00 2001
From: dequis
Date: Wed, 23 Sep 2015 13:37:14 -0300
Subject: [PATCH 57/82] Revert "Revert "Bug fix - docdir is ignored during
installation.""
This reverts commit d222c11f74a5662df59e00e7ae6c8105179a804e.
---
docs/Makefile.am | 2 --
1 file changed, 2 deletions(-)
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 5e222564..861a2ca4 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -1,5 +1,3 @@
-docdir = $(datadir)/doc/irssi
-
man_MANS = \
irssi.1
From e833521cefdedcdbc0e4382715a36ea5f8276a86 Mon Sep 17 00:00:00 2001
From: dequis
Date: Wed, 23 Sep 2015 13:39:07 -0300
Subject: [PATCH 58/82] Bump glib2 requirement from 2.6 to 2.16
This drops support for rhel/centos 5 (18 months left of its 10 year
support cycle)
Keeps support for debian 5.0 (lenny) and ubuntu 8.04 LTS, both of
which are unsupported, so bumping up to glib 2.24 wouldn't be a problem,
but it's not needed atm.
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index e33b8c1d..7bcd3fe7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -261,7 +261,7 @@ for try in 1 2; do
echo "*** trying without -lgmodule"
glib_modules=
fi
- AM_PATH_GLIB_2_0(2.6.0,,, $glib_modules)
+ AM_PATH_GLIB_2_0(2.16.0,,, $glib_modules)
if test "$GLIB_LIBS"; then
if test $glib_modules = gmodule; then
AC_DEFINE(HAVE_GMODULE)
From 9da445ab86740be13f47da7eb540fb9e4b962085 Mon Sep 17 00:00:00 2001
From: dequis
Date: Wed, 23 Sep 2015 13:42:00 -0300
Subject: [PATCH 59/82] Drop some glib version checks that are not needed
anymore
The g_strcmp0 fallback in particular was broken since it was used in a
few places as a GCompareFunc, and macros don't work that way.
Yes, that one was my fault, but nobody complained :D
---
src/common.h | 13 -------------
src/fe-common/core/fe-common-core.c | 11 -----------
2 files changed, 24 deletions(-)
diff --git a/src/common.h b/src/common.h
index e9073925..86a079fe 100644
--- a/src/common.h
+++ b/src/common.h
@@ -43,19 +43,6 @@
# include
#endif
-#if !GLIB_CHECK_VERSION(2,10,0)
-#define g_slice_alloc(size) g_malloc(size)
-#define g_slice_alloc0(size) g_malloc0(size)
-#define g_slice_free1(size, mem) g_free(mem)
-#define g_slice_new(type) g_new(type, 1)
-#define g_slice_new0(type) g_new0(type, 1)
-#define g_slice_free(type, mem) g_free(mem)
-#endif
-
-#if !GLIB_CHECK_VERSION(2,16,0)
-#define g_strcmp0(a, b) (!a ? -(a != b) : (!b ? (a != b) : strcmp(a, b)))
-#endif
-
#if defined (UOFF_T_INT)
typedef unsigned int uoff_t;
#elif defined (UOFF_T_LONG)
diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c
index 341902df..a15850e2 100644
--- a/src/fe-common/core/fe-common-core.c
+++ b/src/fe-common/core/fe-common-core.c
@@ -450,18 +450,7 @@ void fe_common_core_finish_init(void)
signal_add_first("setup changed", (SIGNAL_FUNC) sig_setup_changed);
/* _after_ windows are created.. */
-#if GLIB_CHECK_VERSION(2,6,0)
g_log_set_default_handler((GLogFunc) glog_func, NULL);
-#else
- g_log_set_handler(G_LOG_DOMAIN,
- (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL |
- G_LOG_LEVEL_WARNING),
- (GLogFunc) glog_func, NULL);
- g_log_set_handler("GLib",
- (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL |
- G_LOG_LEVEL_WARNING),
- (GLogFunc) glog_func, NULL); /* send glib errors to the same place */
-#endif
if (setup_changed)
signal_emit("setup changed", 0);
From b984f1fa250fd87b2808bed6826f17386ddb30ce Mon Sep 17 00:00:00 2001
From: Robert C Jensen
Date: Wed, 23 Sep 2015 23:39:37 -0300
Subject: [PATCH 60/82] dcc-get: close() the temp fd so we don't get ETXTBSY in
ntfs mounts
Patch from debian bug 696963 [1]
Fixes github bug #220 and flyspray bug 867 [2]
[1]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=696963
[2]: http://bugs.irssi.org/index.php?do=details&task_id=867
---
src/irc/dcc/dcc-get.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c
index 1208b5c5..a8b1c967 100644
--- a/src/irc/dcc/dcc-get.c
+++ b/src/irc/dcc/dcc-get.c
@@ -226,6 +226,8 @@ void sig_dccget_connected(GET_DCC_REC *dcc)
else
ret = fchmod(temphandle, dcc_file_create_mode);
+ close(temphandle);
+
if (ret != -1) {
ret = link(tempfname, dcc->file);
@@ -249,7 +251,6 @@ void sig_dccget_connected(GET_DCC_REC *dcc)
/* close/remove the temp file */
ret_errno = errno;
- close(temphandle);
unlink(tempfname);
g_free(tempfname);
From a2277e84bd390b9eaca906541f32e5d60e529f7f Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Thu, 24 Sep 2015 11:59:18 +0200
Subject: [PATCH 61/82] Added functionality to create dir if dir specified in
rawlog filename
---
src/core/rawlog.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/core/rawlog.c b/src/core/rawlog.c
index 2fa6b850..875c0ef2 100644
--- a/src/core/rawlog.c
+++ b/src/core/rawlog.c
@@ -32,6 +32,7 @@
static int rawlog_lines;
static int signal_rawlog;
static int log_file_create_mode;
+static int log_dir_create_mode;
RAWLOG_REC *rawlog_create(void)
{
@@ -145,9 +146,13 @@ void rawlog_close(RAWLOG_REC *rawlog)
void rawlog_save(RAWLOG_REC *rawlog, const char *fname)
{
- char *path;
+ char *path, *dir;
int f;
+ dir = g_path_get_dirname(fname);
+ mkpath(dir, log_dir_create_mode);
+ g_free(dir);
+
path = convert_home(fname);
f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode);
g_free(path);
@@ -165,6 +170,11 @@ static void read_settings(void)
{
rawlog_set_size(settings_get_int("rawlog_lines"));
log_file_create_mode = octal2dec(settings_get_int("log_create_mode"));
+ log_dir_create_mode = log_file_create_mode;
+ if (log_file_create_mode & 0400) log_dir_create_mode |= 0100;
+ if (log_file_create_mode & 0040) log_dir_create_mode |= 0010;
+ if (log_file_create_mode & 0004) log_dir_create_mode |= 0001;
+
}
static void cmd_rawlog(const char *data, SERVER_REC *server, void *item)
From 1a2c479bc04cdb6758ca9f1976e235b092cc83fb Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 26 Sep 2015 18:53:10 +0200
Subject: [PATCH 62/82] Allow the user to set and modify the SASL parameters
The /NETWORK ADD command now is able to modify the SASL mechanism, the
username and the password on a chatnet basis.
---
docs/help/in/network.in | 6 ++++++
src/fe-common/irc/fe-ircnet.c | 24 +++++++++++++++++++-----
src/irc/core/irc-chatnets.c | 12 ++++++++----
src/irc/core/irc-servers-setup.c | 2 +-
4 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/docs/help/in/network.in b/docs/help/in/network.in
index 046d9feb..2918f6ae 100644
--- a/docs/help/in/network.in
+++ b/docs/help/in/network.in
@@ -32,6 +32,12 @@
additional commands to the server.
-cmdmax: Specifies the maximum number of commands to perform before
starting the internal flood protection.
+ -sasl_mechanism Specifies the mechanism to use for the SASL authentication.
+ At the moment irssi only supports the 'plain' and the
+ 'external' mechanisms.
+ -sasl_username Specifies the username to use during the SASL authentication.
+ -sasl_password Specifies the password to use during the SASL authentication.
+
The name of the network to add, edit or remove; if no parameter is given,
the list of networks will be displayed.
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 6618edd7..dab6f57f 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -82,10 +82,12 @@ static void cmd_network_list(void)
}
/* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ]
- [-host ] [-usermode ] [-autosendcmd ]
- [-querychans ] [-whois ] [-msgs ]
- [-kicks ] [-modes ]
- [-cmdspeed ] [-cmdmax ] */
+ [-host ] [-usermode ] [-autosendcmd ]
+ [-querychans ] [-whois ] [-msgs ]
+ [-kicks ] [-modes ] [-cmdspeed ]
+ [-cmdmax ] [-sasl_mechanism ]
+ [-sasl_username ] [-sasl_password ]
+ */
static void cmd_network_add(const char *data)
{
GHashTable *optlist;
@@ -112,6 +114,9 @@ static void cmd_network_add(const char *data)
}
if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode);
if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd);
+ if (g_hash_table_lookup(optlist, "sasl_mechanism")) g_free_and_null(rec->sasl_mechanism);
+ if (g_hash_table_lookup(optlist, "sasl_username")) g_free_and_null(rec->sasl_username);
+ if (g_hash_table_lookup(optlist, "sasl_password")) g_free_and_null(rec->sasl_password);
}
value = g_hash_table_lookup(optlist, "kicks");
@@ -148,6 +153,14 @@ static void cmd_network_add(const char *data)
value = g_hash_table_lookup(optlist, "autosendcmd");
if (value != NULL && *value != '\0') rec->autosendcmd = g_strdup(value);
+ /* the validity of the parameters is checked in sig_server_setup_fill_chatnet */
+ value = g_hash_table_lookup(optlist, "sasl_mechanism");
+ if (value != NULL && *value != '\0') rec->sasl_mechanism = g_strdup(value);
+ value = g_hash_table_lookup(optlist, "sasl_username");
+ if (value != NULL && *value != '\0') rec->sasl_username = g_strdup(value);
+ value = g_hash_table_lookup(optlist, "sasl_password");
+ if (value != NULL && *value != '\0') rec->sasl_password = g_strdup(value);
+
ircnet_create(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_ADDED, name);
@@ -186,7 +199,8 @@ void fe_ircnet_init(void)
command_bind("network add", NULL, (SIGNAL_FUNC) cmd_network_add);
command_bind("network remove", NULL, (SIGNAL_FUNC) cmd_network_remove);
- command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed -cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode");
+ command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed "
+ "-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password");
}
void fe_ircnet_deinit(void)
diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index b9b221b8..d72f71dd 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -49,9 +49,9 @@ static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
rec->max_modes = config_node_get_int(node, "max_modes", 0);
rec->max_whois = config_node_get_int(node, "max_whois", 0);
- rec->sasl_mechanism = config_node_get_str(node, "sasl_mechanism", NULL);
- rec->sasl_username = config_node_get_str(node, "sasl_username", NULL);
- rec->sasl_password = config_node_get_str(node, "sasl_password", NULL);
+ rec->sasl_mechanism = g_strdup(config_node_get_str(node, "sasl_mechanism", NULL));
+ rec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL));
+ rec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
}
static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
@@ -88,8 +88,12 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec)
{
- if (IS_IRC_CHATNET(rec))
+ if (IS_IRC_CHATNET(rec)) {
g_free(rec->usermode);
+ g_free(rec->sasl_mechanism);
+ g_free(rec->sasl_username);
+ g_free(rec->sasl_password);
+ }
}
diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index f5e4f8f4..bf1d2ddf 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -81,7 +81,7 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
if (ircnet->max_query_chans > 0)
conn->max_query_chans = ircnet->max_query_chans;
- /* Validate the SASL parameters filled by sig_chatnet_read() */
+ /* Validate the SASL parameters filled by sig_chatnet_read() or cmd_network_add */
conn->sasl_mechanism = SASL_MECHANISM_NONE;
if (ircnet->sasl_mechanism != NULL) {
From 6f9fc5d5230f6d094130bd4f0ce659b740ed2a54 Mon Sep 17 00:00:00 2001
From: dequis
Date: Sun, 27 Sep 2015 02:15:14 -0300
Subject: [PATCH 63/82] INSTALL: mention local::lib for home directory
installations
I had problems installing this and this file didn't have the answer.
So I'm adding what nei told me to do.
---
INSTALL | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/INSTALL b/INSTALL
index 719369de..a83a6c76 100644
--- a/INSTALL
+++ b/INSTALL
@@ -94,6 +94,10 @@ things that can go wrong:
- If configure complains that it doesn't find some perl stuff, you're
probably missing libperl.so or libperl.a. In debian, you'll need to do
apt-get install libperl-dev
+ - For unprivileged home directory installations, using the local::lib CPAN
+ module is recommended. Read its docs, bootstrap it if needed, ensure that
+ the environment variables are set before running the configure script, and
+ append "--with-perl-lib=site" to the configure parameters to use it.
You can verify that the perl module is loaded and working with "/LOAD"
command. It should print something like:
From 0f066aac11e9a56f394330a8d7dab3428594a623 Mon Sep 17 00:00:00 2001
From: Chirag Aggarwal
Date: Mon, 28 Sep 2015 08:54:19 +0530
Subject: [PATCH 64/82] Remove Typo from FAQs
---
docs/startup-HOWTO.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html
index 30caf657..deff3116 100644
--- a/docs/startup-HOWTO.html
+++ b/docs/startup-HOWTO.html
@@ -391,7 +391,7 @@ messages window.
the connection into some window. IRSSI DOES NOT. There is no required
relationship between window and server. You can connect to 10 servers
and manage them all in just one window, or join channel in each one of
-them to one sigle window if you really want to. That being said, here's
+them to one single window if you really want to. That being said, here's
how you do connect to new server without closing the old connection:
From cff536ab7091e79747352ff1f1d1d832870b2fb4 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Tue, 29 Sep 2015 10:39:49 +0200
Subject: [PATCH 65/82] Add sasl info to /network list output if available
---
src/fe-common/irc/fe-ircnet.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index dab6f57f..c341081a 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -56,6 +56,11 @@ static void cmd_network_list(void)
g_string_append_printf(str, "autosendcmd: %s, ", rec->autosendcmd);
if (rec->usermode != NULL)
g_string_append_printf(str, "usermode: %s, ", rec->usermode);
+ if (rec->sasl_username != NULL) {
+ g_string_append_printf(str, "sasl_mechanism: %s, ", rec->sasl_mechanism);
+ g_string_append_printf(str, "sasl_username: %s, ", rec->sasl_username);
+ g_string_append_printf(str, "sasl_password: (pass), ");
+ }
if (rec->cmd_queue_speed > 0)
g_string_append_printf(str, "cmdspeed: %d, ", rec->cmd_queue_speed);
From b04b5f0f1d03be6282f7ba835b8a4f29b18b9c69 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Tue, 29 Sep 2015 11:44:11 +0200
Subject: [PATCH 66/82] Make sure sasl settings are defined before printing
them out
---
src/fe-common/irc/fe-ircnet.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index c341081a..bb0af313 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -56,12 +56,12 @@ static void cmd_network_list(void)
g_string_append_printf(str, "autosendcmd: %s, ", rec->autosendcmd);
if (rec->usermode != NULL)
g_string_append_printf(str, "usermode: %s, ", rec->usermode);
- if (rec->sasl_username != NULL) {
+ if (rec->sasl_mechanism != NULL)
g_string_append_printf(str, "sasl_mechanism: %s, ", rec->sasl_mechanism);
+ if (rec->sasl_username != NULL)
g_string_append_printf(str, "sasl_username: %s, ", rec->sasl_username);
+ if (rec->sasl_password != NULL)
g_string_append_printf(str, "sasl_password: (pass), ");
- }
-
if (rec->cmd_queue_speed > 0)
g_string_append_printf(str, "cmdspeed: %d, ", rec->cmd_queue_speed);
if (rec->max_cmds_at_once > 0)
From 00176dbff5af1a649a1f45972c45d661912aa8be Mon Sep 17 00:00:00 2001
From: Jellyfrog
Date: Tue, 29 Sep 2015 17:34:35 +0200
Subject: [PATCH 67/82] Switch to modern Travis CI infrastructure
Fixes #310
---
.travis.yml | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 35226645..aa807a7b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,4 @@
+sudo: false
language: perl
perl:
- "5.20-shrplib"
@@ -7,19 +8,22 @@ env:
- CC=clang
- CC=gcc
+addons:
+ apt:
+ packages:
+ - libperl-dev
+ - elinks
+
before_install:
- - sudo apt-get update -qq
- perl -V
- - sudo apt-get build-dep -qq irssi
- - sudo apt-get install -qq lynx
install: true
script:
- - ./autogen.sh --with-proxy --with-bot --with-perl=module
+ - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build --enable-silent-rules
- cat config.log
- make
- - sudo make install
+ - make install
notifications:
irc:
From a475d57183bcbfd6e540dba5cd7894d8c38b53b7 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Thu, 1 Oct 2015 22:25:40 +0200
Subject: [PATCH 68/82] Save the sasl state in the session
This is seemingly required to have irssi re-authenticate after a
restart.
---
src/irc/core/irc-session.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/irc/core/irc-session.c b/src/irc/core/irc-session.c
index ea65d8a5..18e8e5c7 100644
--- a/src/irc/core/irc-session.c
+++ b/src/irc/core/irc-session.c
@@ -28,6 +28,8 @@
#include "irc-channels.h"
#include "irc-nicklist.h"
+#include "sasl.h"
+
struct _isupport_data { CONFIG_REC *config; CONFIG_NODE *node; };
static void session_isupport_foreach(char *key, char *value, struct _isupport_data *data)
@@ -65,6 +67,10 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
config_node_set_str(config, node, "away_reason", server->away_reason);
config_node_set_bool(config, node, "emode_known", server->emode_known);
+ config_node_set_int(config, node, "sasl_mechanism", server->connrec->sasl_mechanism);
+ config_node_set_str(config, node, "sasl_username", server->connrec->sasl_username);
+ config_node_set_str(config, node, "sasl_password", server->connrec->sasl_password);
+
config_node_set_bool(config, node, "isupport_sent", server->isupport_sent);
isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
isupport_data.config = config;
@@ -90,6 +96,15 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
server->emode_known = config_node_get_bool(node, "emode_known", FALSE);
server->isupport_sent = config_node_get_bool(node, "isupport_sent", FALSE);
+ server->connrec->sasl_mechanism = config_node_get_int(node, "sasl_mechanism", SASL_MECHANISM_NONE);
+ /* The fields below might have been filled when loading the chatnet
+ * description from the config and we favor the content that's been saved
+ * in the session file over that. */
+ g_free(server->connrec->sasl_username);
+ server->connrec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL));
+ g_free(server->connrec->sasl_password);
+ server->connrec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
+
if (server->isupport == NULL) {
server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
(GCompareFunc) g_istr_equal);
From cfff402fe677316d286ce6663b8afeee4be95526 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 11:25:30 +0200
Subject: [PATCH 69/82] Don't set the usermode field if blank
Fixes FS#919
---
src/irc/core/irc-chatnets.c | 5 ++++-
src/irc/core/irc-servers-setup.c | 12 +++++++++---
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index d72f71dd..0796e0cb 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -35,10 +35,13 @@ void ircnet_create(IRC_CHATNET_REC *rec)
static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
{
+ char *value;
+
if (!IS_IRC_CHATNET(rec))
return;
- rec->usermode = g_strdup(config_node_get_str(node, "usermode", NULL));
+ value = config_node_get_str(node, "usermode", NULL);
+ rec->usermode = (value != NULL && *value != '\0') ? g_strdup(value) : NULL;
rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0);
rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0);
diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index bf1d2ddf..f425b587 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -48,12 +48,18 @@ static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn)
{
+ const char *value;
+
if (!IS_IRC_SERVER_CONNECT(conn))
return;
- conn->alternate_nick = *settings_get_str("alternate_nick") != '\0' ?
- g_strdup(settings_get_str("alternate_nick")) : NULL;
- conn->usermode = g_strdup(settings_get_str("usermode"));
+ value = settings_get_str("alternate_nick");
+ conn->alternate_nick = (value != NULL && *value != '\0') ?
+ g_strdup(value) : NULL;
+
+ value = settings_get_str("usermode");
+ conn->usermode = (value != NULL && *value != '\0') ?
+ g_strdup(value) : NULL;
}
static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
From b545bc96a9e1a875beb50d9202161864ca8164d8 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 12:39:08 +0200
Subject: [PATCH 70/82] Fix a memory leak.
g_get_current_dir() returns a heap-allocated string.
---
src/core/core.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/core/core.c b/src/core/core.c
index b9debbb5..879d346f 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -156,11 +156,17 @@ static void sig_init_finished(void)
static char *fix_path(const char *str)
{
char *new_str = convert_home(str);
+
if (!g_path_is_absolute(new_str)) {
char *tmp_str = new_str;
- new_str = g_strdup_printf("%s/%s", g_get_current_dir(), tmp_str);
+ char *current_dir = g_get_current_dir();
+
+ new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str);
+
+ g_free(current_dir);
g_free(tmp_str);
}
+
return new_str;
}
From 2e860abd2b8b3a30f74005450830c34a318b64a3 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 14:04:04 +0200
Subject: [PATCH 71/82] Fix the display of utf8 sequences in the gui
term_addstr() had a long-standing fixme that suggested it didn't
take into account the string encoding when calculating the string
length.
The BIG5 code path is untested.
---
src/fe-common/core/utf8.h | 2 ++
src/fe-text/gui-printtext.c | 7 +++--
src/fe-text/term-terminfo.c | 53 ++++++++++++++++++++++++++++++++++---
src/fe-text/term.h | 2 +-
4 files changed, 55 insertions(+), 9 deletions(-)
diff --git a/src/fe-common/core/utf8.h b/src/fe-common/core/utf8.h
index 3c15dc7d..70b44d7e 100644
--- a/src/fe-common/core/utf8.h
+++ b/src/fe-common/core/utf8.h
@@ -8,6 +8,8 @@
#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE)
#define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo))
+int strlen_big5(const unsigned char *str);
+
/* Returns width for character (0-2). */
int mk_wcwidth(unichar c);
diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c
index 547d39c9..d8272df5 100644
--- a/src/fe-text/gui-printtext.c
+++ b/src/fe-text/gui-printtext.c
@@ -220,16 +220,15 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
get_colors(flags, &fg, &bg, &attr);
if (window == NULL) {
- g_return_if_fail(next_xpos != -1);
+ g_return_if_fail(next_xpos != -1);
term_set_color2(root_window, attr, fg, bg);
term_move(root_window, next_xpos, next_ypos);
if (flags & GUI_PRINT_FLAG_CLRTOEOL)
term_clrtoeol(root_window);
- term_addstr(root_window, str);
- next_xpos += strlen(str); /* FIXME utf8 or big5 */
- return;
+ next_xpos += term_addstr(root_window, str);
+ return;
}
lineinfo.level = dest == NULL ? 0 : dest->level;
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index ded79c28..8c95bc0d 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -522,15 +522,60 @@ void term_add_unichar(TERM_WINDOW *window, unichar chr)
}
}
-void term_addstr(TERM_WINDOW *window, const char *str)
+int term_addstr(TERM_WINDOW *window, const char *str)
{
- int len;
+ int i, len, raw_len;
+ unichar *tmp;
+ const char *ptr;
if (vcmove) term_move_real();
- len = strlen(str); /* FIXME utf8 or big5 */
+
+ raw_len = strlen(str);
+
+ /* The string length depends on the terminal encoding */
+ switch (term_type) {
+ case TERM_TYPE_BIG5:
+ len = strlen_big5((const unsigned char *)str);
+ break;
+ case TERM_TYPE_UTF8:
+ len = g_utf8_strlen(str, -1);
+ break;
+ default:
+ len = strlen(str);
+ break;
+ }
+
+ tmp = calloc(len, sizeof(unichar));
+ if (tmp == NULL)
+ return 0;
+
+ switch (term_type) {
+ case TERM_TYPE_BIG5:
+ big5_to_unichars(str, tmp);
+ break;
+ case TERM_TYPE_UTF8:
+ ptr = str;
+ for (i = 0; i < len; i++) {
+ tmp[i] = g_utf8_get_char(ptr);
+ ptr = g_utf8_next_char(ptr);
+ }
+ break;
+ default:
+ for (i = 0; i < len; i++)
+ tmp[i] = str[i];
+ }
+
+ for (len = i = 0; i < len; i++)
+ len += unichar_isprint(tmp[i]) ? mk_wcwidth(tmp[i]) : 1;
+
+ free(tmp);
+
term_printed_text(len);
- fwrite(str, 1, len, window->term->out);
+ /* Use strlen() here since we need the number of raw bytes */
+ fwrite(str, 1, raw_len, window->term->out);
+
+ return len;
}
void term_clrtoeol(TERM_WINDOW *window)
diff --git a/src/fe-text/term.h b/src/fe-text/term.h
index cdcc787a..f0a76c42 100644
--- a/src/fe-text/term.h
+++ b/src/fe-text/term.h
@@ -83,7 +83,7 @@ void term_set_color(TERM_WINDOW *window, int col);
void term_move(TERM_WINDOW *window, int x, int y);
void term_addch(TERM_WINDOW *window, char chr);
void term_add_unichar(TERM_WINDOW *window, unichar chr);
-void term_addstr(TERM_WINDOW *window, const char *str);
+int term_addstr(TERM_WINDOW *window, const char *str);
void term_clrtoeol(TERM_WINDOW *window);
void term_move_cursor(int x, int y);
From c351c448b8dd2b9759e46c0c6e73ed5ead936ffc Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 15:02:43 +0200
Subject: [PATCH 72/82] Rework the logic to avoid allocating memory
---
src/fe-text/term-terminfo.c | 52 ++++++++++++++-----------------------
1 file changed, 19 insertions(+), 33 deletions(-)
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 8c95bc0d..2ee69a1c 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -524,52 +524,38 @@ void term_add_unichar(TERM_WINDOW *window, unichar chr)
int term_addstr(TERM_WINDOW *window, const char *str)
{
- int i, len, raw_len;
- unichar *tmp;
+ int len, raw_len;
+ unichar tmp;
const char *ptr;
if (vcmove) term_move_real();
+ len = 0;
raw_len = strlen(str);
/* The string length depends on the terminal encoding */
- switch (term_type) {
- case TERM_TYPE_BIG5:
- len = strlen_big5((const unsigned char *)str);
- break;
- case TERM_TYPE_UTF8:
- len = g_utf8_strlen(str, -1);
- break;
- default:
- len = strlen(str);
- break;
- }
- tmp = calloc(len, sizeof(unichar));
- if (tmp == NULL)
- return 0;
+ ptr = str;
- switch (term_type) {
- case TERM_TYPE_BIG5:
- big5_to_unichars(str, tmp);
- break;
- case TERM_TYPE_UTF8:
- ptr = str;
- for (i = 0; i < len; i++) {
- tmp[i] = g_utf8_get_char(ptr);
+ if (term_type != TERM_TYPE_BIG5) {
+ while (*ptr != '\0') {
+ tmp = g_utf8_get_char(ptr);
+ len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
ptr = g_utf8_next_char(ptr);
}
- break;
- default:
- for (i = 0; i < len; i++)
- tmp[i] = str[i];
+ } else {
+ while (*ptr != '\0') {
+ if (is_big5(ptr[0], ptr[1])) {
+ tmp = ptr[0] << 8 | ptr[1];
+ ptr += 2;
+ } else {
+ tmp = *ptr;
+ ptr += 1;
+ }
+ len += (tmp > 0xff) ? 2 : 1;
+ }
}
- for (len = i = 0; i < len; i++)
- len += unichar_isprint(tmp[i]) ? mk_wcwidth(tmp[i]) : 1;
-
- free(tmp);
-
term_printed_text(len);
/* Use strlen() here since we need the number of raw bytes */
From c7646dc58d1e70abc8d2981e08baa83e459affdb Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 15:07:59 +0200
Subject: [PATCH 73/82] Even simpler logic
---
src/fe-text/term-terminfo.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 2ee69a1c..6d289cfc 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -543,18 +543,8 @@ int term_addstr(TERM_WINDOW *window, const char *str)
len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
ptr = g_utf8_next_char(ptr);
}
- } else {
- while (*ptr != '\0') {
- if (is_big5(ptr[0], ptr[1])) {
- tmp = ptr[0] << 8 | ptr[1];
- ptr += 2;
- } else {
- tmp = *ptr;
- ptr += 1;
- }
- len += (tmp > 0xff) ? 2 : 1;
- }
- }
+ } else
+ len = raw_len;
term_printed_text(len);
From 48ab298a67151e6fce33c1d7b34f4f83796b8d9a Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 15:08:48 +0200
Subject: [PATCH 74/82] Kill an unneeded declaration
---
src/fe-common/core/utf8.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/fe-common/core/utf8.h b/src/fe-common/core/utf8.h
index 70b44d7e..3c15dc7d 100644
--- a/src/fe-common/core/utf8.h
+++ b/src/fe-common/core/utf8.h
@@ -8,8 +8,6 @@
#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE)
#define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo))
-int strlen_big5(const unsigned char *str);
-
/* Returns width for character (0-2). */
int mk_wcwidth(unichar c);
From db5ae4adce6ad82150a4fef01c8b141631f89d96 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 2 Oct 2015 17:13:49 +0200
Subject: [PATCH 75/82] Flush the dirty buffer to disk
Given a big enough write_buffer_size and a long enough
write_buffer_timeout it might be possible to show the user an incomplete
or empty awaylog.
Patch by: Petteri Aimonen
---
src/core/log-away.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/core/log-away.c b/src/core/log-away.c
index 681edcbf..c6de721c 100644
--- a/src/core/log-away.c
+++ b/src/core/log-away.c
@@ -62,6 +62,9 @@ static void awaylog_open(void)
return;
}
+ /* Flush the dirty buffers to disk before acquiring the file position */
+ write_buffer_flush();
+
awaylog = log;
away_filepos = lseek(log->handle, 0, SEEK_CUR);
away_msgs = 0;
@@ -83,6 +86,9 @@ static void awaylog_close(void)
if (awaylog == log) awaylog = NULL;
+ /* Flush the dirty buffers to disk before showing the away log */
+ write_buffer_flush();
+
signal_emit("awaylog show", 3, log, GINT_TO_POINTER(away_msgs),
GINT_TO_POINTER(away_filepos));
log_close(log);
From ef55e0f6534a5b790131c320fd0490a5beb21a68 Mon Sep 17 00:00:00 2001
From: dequis
Date: Fri, 2 Oct 2015 13:48:23 -0300
Subject: [PATCH 76/82] Add missing null terminator to the g_build_path()
varargs
Lemon broke it a few commits ago.
---
src/core/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/core.c b/src/core/core.c
index 879d346f..bbeec6f4 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -161,7 +161,7 @@ static char *fix_path(const char *str)
char *tmp_str = new_str;
char *current_dir = g_get_current_dir();
- new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str);
+ new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str, NULL);
g_free(current_dir);
g_free(tmp_str);
From a66bb95d0e3d76dfb6abda88d6f128540279b461 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Fri, 2 Oct 2015 18:57:06 +0200
Subject: [PATCH 77/82] Use silent rules.
---
.travis.yml | 2 +-
configure.ac | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index aa807a7b..f066c17b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,7 +20,7 @@ before_install:
install: true
script:
- - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build --enable-silent-rules
+ - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
- cat config.log
- make
- make install
diff --git a/configure.ac b/configure.ac
index 7bcd3fe7..325b5e5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,8 @@ AC_CONFIG_HEADERS([irssi-config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.9 no-define foreign])
+AM_SILENT_RULES([yes])
+
AM_MAINTAINER_MODE
AC_PROG_CC
From da3f2f0d0174675faa1a092722e8298460254112 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Fri, 2 Oct 2015 19:51:54 +0200
Subject: [PATCH 78/82] Set HOST_NAME_MAX to 255, if it's undefined.
Thanks to Jilles and dx.
Fixes #309
---
src/irc/core/irc-expandos.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index 5d8150f0..62ef577a 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -27,6 +27,10 @@
#include "irc-channels.h"
#include "nicklist.h"
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
static char *last_join;
/* last person to join a channel you are on */
@@ -56,7 +60,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
{
IRC_SERVER_REC *ircserver;
const char *username;
- char hostname[HOST_NAME_MAX];
+ char hostname[HOST_NAME_MAX + 1];
ircserver = IRC_SERVER(server);
@@ -80,7 +84,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
{
IRC_SERVER_REC *ircserver;
- char hostname[HOST_NAME_MAX];
+ char hostname[HOST_NAME_MAX + 1];
char **list;
char *hostname_split;
From b68a30cdfe43bec9cdb0e7c822b66d90ccf8982d Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 3 Oct 2015 14:32:38 +0200
Subject: [PATCH 79/82] Include write-buffer.h in log-away.c
Silence a warning and make the world a better place.
---
src/core/log-away.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/core/log-away.c b/src/core/log-away.c
index c6de721c..e2a0120b 100644
--- a/src/core/log-away.c
+++ b/src/core/log-away.c
@@ -24,6 +24,7 @@
#include "log.h"
#include "servers.h"
#include "settings.h"
+#include "write-buffer.h"
static LOG_REC *awaylog;
static int away_filepos;
From 48375c3f900f56434441caa0161c0531fd0ce435 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?=
Date: Sat, 3 Oct 2015 18:50:23 +0200
Subject: [PATCH 80/82] Simplify Travis config.
---
.travis.yml | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index f066c17b..c8bbb6d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,15 +24,3 @@ script:
- cat config.log
- make
- make install
-
-notifications:
- irc:
- channels:
- - "irc.freenode.net#irssi"
- template:
- - "%{repository} (%{commit}: %{author}): %{message}"
- - "Build details : %{build_url}"
- on_success: always
- on_failure: always
- use_notice: true
- skip_join: true
From 0140e7c6b23ff1490965b080a7882b2508677d55 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 4 Oct 2015 11:56:54 +0200
Subject: [PATCH 81/82] Fix the indentation.
---
src/fe-text/term-terminfo.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 6d289cfc..27be904e 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -537,14 +537,14 @@ int term_addstr(TERM_WINDOW *window, const char *str)
ptr = str;
- if (term_type != TERM_TYPE_BIG5) {
- while (*ptr != '\0') {
- tmp = g_utf8_get_char(ptr);
- len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
- ptr = g_utf8_next_char(ptr);
- }
+ if (term_type == TERM_TYPE_UTF8) {
+ while (*ptr != '\0') {
+ tmp = g_utf8_get_char(ptr);
+ len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
+ ptr = g_utf8_next_char(ptr);
+ }
} else
- len = raw_len;
+ len = raw_len;
term_printed_text(len);
From f540ec9de1bb35b226e3c97e763238072fe295dd Mon Sep 17 00:00:00 2001
From: dequis
Date: Thu, 8 Oct 2015 00:06:17 -0300
Subject: [PATCH 82/82] Fix /reconnect RECON-1 saying "Reconnection tag 1 not
found"
Turns out it was fixing the wrong string, and trying to do
atoi("RECON-1") instead of atoi("1").
"/reconnect 1" worked, but "/reconnect RECON-1" gave that confusing
error message.
---
src/core/servers-reconnect.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c
index ae97ecd2..f419035b 100644
--- a/src/core/servers-reconnect.c
+++ b/src/core/servers-reconnect.c
@@ -420,8 +420,8 @@ static void cmd_reconnect(const char *data, SERVER_REC *server)
cmd_param_error(CMDERR_NOT_CONNECTED);
rec = reconnects->data;
} else {
- if (g_ascii_strncasecmp(data, "RECON-", 6) == 0)
- data += 6;
+ if (g_ascii_strncasecmp(tag, "RECON-", 6) == 0)
+ tag += 6;
tagnum = atoi(tag);
rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum);