summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/channels-setup.c9
-rw-r--r--src/core/levels.c21
-rw-r--r--src/core/levels.h4
-rw-r--r--src/core/misc.c20
-rw-r--r--src/core/misc.h3
-rw-r--r--src/core/network-openssl.c20
-rw-r--r--src/core/servers-setup.c11
-rw-r--r--src/core/servers.c45
-rw-r--r--src/core/special-vars.c19
9 files changed, 112 insertions, 40 deletions
diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c
index 4966d77d..8002646d 100644
--- a/src/core/channels-setup.c
+++ b/src/core/channels-setup.c
@@ -37,9 +37,14 @@ static int compare_channel_setup (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
name = config_node_get_str(node, "name", NULL);
chatnet = config_node_get_str(node, "chatnet", NULL);
- if (g_strcmp0(name, channel->name) != 0 ||
- g_strcmp0(chatnet, channel->chatnet) != 0)
+ if (name == NULL || chatnet == NULL) {
+ return 0;
+ }
+
+ if (g_ascii_strcasecmp(name, channel->name) != 0 ||
+ g_ascii_strcasecmp(chatnet, channel->chatnet) != 0) {
return 1;
+ }
return 0;
}
diff --git a/src/core/levels.c b/src/core/levels.c
index e623c4de..eb7efcf7 100644
--- a/src/core/levels.c
+++ b/src/core/levels.c
@@ -21,6 +21,7 @@
#include "module.h"
#include "levels.h"
+/* the order of these levels must match the bits in levels.h */
static const char *levels[] = {
"CRAP",
"MSGS",
@@ -44,9 +45,6 @@ static const char *levels[] = {
"CLIENTCRAP",
"CLIENTERRORS",
"HILIGHTS",
-
- "NOHILIGHT",
- "NO_ACT",
NULL
};
@@ -63,6 +61,9 @@ int level_get(const char *level)
if (g_ascii_strcasecmp(level, "NO_ACT") == 0)
return MSGLEVEL_NO_ACT;
+ if (g_ascii_strcasecmp(level, "HIDDEN") == 0)
+ return MSGLEVEL_HIDDEN;
+
len = strlen(level);
if (len == 0) return 0;
@@ -138,17 +139,13 @@ char *bits2level(int bits)
str = g_string_new(NULL);
- if (bits & MSGLEVEL_NEVER) {
+ if (bits & MSGLEVEL_NEVER)
g_string_append(str, "NEVER ");
- bits &= ~MSGLEVEL_NEVER;
- }
- if (bits & MSGLEVEL_NO_ACT) {
+ if (bits & MSGLEVEL_NO_ACT)
g_string_append(str, "NO_ACT ");
- bits &= ~MSGLEVEL_NO_ACT;
- }
- if (bits == MSGLEVEL_ALL) {
+ if ((bits & MSGLEVEL_ALL) == MSGLEVEL_ALL) {
g_string_append(str, "ALL ");
} else {
for (n = 0; levels[n] != NULL; n++) {
@@ -156,6 +153,10 @@ char *bits2level(int bits)
g_string_append_printf(str, "%s ", levels[n]);
}
}
+
+ if (bits & MSGLEVEL_HIDDEN)
+ g_string_append(str, "HIDDEN ");
+
if (str->len > 0)
g_string_truncate(str, str->len-1);
diff --git a/src/core/levels.h b/src/core/levels.h
index 9f7e588f..b0ebafba 100644
--- a/src/core/levels.h
+++ b/src/core/levels.h
@@ -36,7 +36,9 @@ enum {
MSGLEVEL_NOHILIGHT = 0x1000000, /* Don't highlight this message */
MSGLEVEL_NO_ACT = 0x2000000, /* Don't trigger channel activity */
MSGLEVEL_NEVER = 0x4000000, /* never ignore / never log */
- MSGLEVEL_LASTLOG = 0x8000000 /* never ignore / never log */
+ MSGLEVEL_LASTLOG = 0x8000000, /* used for /lastlog */
+
+ MSGLEVEL_HIDDEN = 0x10000000 /* Hidden from view */
};
int level_get(const char *level);
diff --git a/src/core/misc.c b/src/core/misc.c
index e589b8c5..27741220 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -218,6 +218,19 @@ GSList *gslist_remove_string (GSList *list, const char *str)
return list;
}
+GSList *gslist_delete_string (GSList *list, const char *str, GDestroyNotify free_func)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(list, str, (GCompareFunc) g_strcmp0);
+ if (l != NULL) {
+ free_func(l->data);
+ return g_slist_delete_link(list, l);
+ }
+
+ return list;
+}
+
/* `list' contains pointer to structure with a char* to string. */
char *gslistptr_to_string(GSList *list, int offset, const char *delimiter)
{
@@ -703,8 +716,11 @@ int expand_escape(const char **data)
*data += 2;
return strtol(digit, NULL, 16);
case 'c':
- /* control character (\cA = ^A) */
- (*data)++;
+ /* check for end of string */
+ if ((*data)[1] == '\0')
+ return 0;
+ /* control character (\cA = ^A) */
+ (*data)++;
return i_toupper(**data) - 64;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
diff --git a/src/core/misc.h b/src/core/misc.h
index 375744db..a46a1432 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -21,7 +21,8 @@ GSList *gslist_find_string(GSList *list, const char *key);
GSList *gslist_find_icase_string(GSList *list, const char *key);
GList *glist_find_string(GList *list, const char *key);
GList *glist_find_icase_string(GList *list, const char *key);
-GSList *gslist_remove_string (GSList *list, const char *str);
+GSList *gslist_remove_string (GSList *list, const char *str) G_GNUC_DEPRECATED;
+GSList *gslist_delete_string (GSList *list, const char *str, GDestroyNotify free_func);
void gslist_free_full (GSList *list, GDestroyNotify free_func);
diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c
index c7ce4b43..9fddf073 100644
--- a/src/core/network-openssl.c
+++ b/src/core/network-openssl.c
@@ -46,6 +46,7 @@
#endif
/* OpenSSL 1.1.0 also introduced some useful additions to the api */
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined (LIBRESSL_VERSION_NUMBER)
static int X509_STORE_up_ref(X509_STORE *vfy)
{
@@ -57,6 +58,7 @@ static int X509_STORE_up_ref(X509_STORE *vfy)
return (n > 1) ? 1 : 0;
}
#endif
+#endif
/* ssl i/o channel object */
typedef struct
@@ -72,7 +74,10 @@ typedef struct
} GIOSSLChannel;
static int ssl_inited = FALSE;
+/* https://github.com/irssi/irssi/issues/820 */
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
static X509_STORE *store = NULL;
+#endif
static void irssi_ssl_free(GIOChannel *handle)
{
@@ -379,7 +384,9 @@ static GIOFuncs irssi_ssl_channel_funcs = {
gboolean irssi_ssl_init(void)
{
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
int success;
+#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
if (!OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL)) {
@@ -391,6 +398,8 @@ gboolean irssi_ssl_init(void)
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
#endif
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
store = X509_STORE_new();
if (store == NULL) {
g_error("Could not initialize OpenSSL: X509_STORE_new() failed");
@@ -404,6 +413,7 @@ gboolean irssi_ssl_init(void)
store = NULL;
/* Don't return an error; the user might have their own cafile/capath. */
}
+#endif
ssl_inited = TRUE;
@@ -522,13 +532,21 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_
g_free(scafile);
g_free(scapath);
verify = TRUE;
- } else if (store != NULL) {
+ }
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
+ else if (store != NULL) {
/* Make sure to increment the refcount every time the store is
* used, that's essential not to get it free'd by OpenSSL when
* the SSL_CTX is destroyed. */
X509_STORE_up_ref(store);
SSL_CTX_set_cert_store(ctx, store);
}
+#else
+ else {
+ if (!SSL_CTX_set_default_verify_paths(ctx))
+ g_warning("Could not load default certificates");
+ }
+#endif
if(!(ssl = SSL_new(ctx)))
{
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 9492c58c..2a92a367 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -474,10 +474,15 @@ static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
chatnet = config_node_get_str(node, "chatnet", NULL);
port = config_node_get_int(node, "port", 0);
- if (g_strcmp0(address, server->address) != 0 ||
- g_strcmp0(chatnet, server->chatnet) != 0 ||
- port != server->port)
+ if (address == NULL || chatnet == NULL) {
+ return 0;
+ }
+
+ if (g_ascii_strcasecmp(address, server->address) != 0 ||
+ g_ascii_strcasecmp(chatnet, server->chatnet) != 0 ||
+ port != server->port) {
return 1;
+ }
return 0;
}
diff --git a/src/core/servers.c b/src/core/servers.c
index b9faab81..11eccc53 100644
--- a/src/core/servers.c
+++ b/src/core/servers.c
@@ -460,8 +460,6 @@ static int server_remove_channels(SERVER_REC *server)
void server_disconnect(SERVER_REC *server)
{
- int chans;
-
g_return_if_fail(IS_SERVER(server));
if (server->disconnected)
@@ -480,21 +478,9 @@ void server_disconnect(SERVER_REC *server)
server->disconnected = TRUE;
signal_emit("server disconnected", 1, server);
- /* close all channels */
- chans = server_remove_channels(server);
-
- if (server->handle != NULL) {
- if (!chans || server->connection_lost)
- net_sendbuffer_destroy(server->handle, TRUE);
- else {
- /* we were on some channels, try to let the server
- disconnect so that our quit message is guaranteed
- to get displayed */
- net_disconnect_later(net_sendbuffer_handle(server->handle));
- net_sendbuffer_destroy(server->handle, FALSE);
- }
- server->handle = NULL;
- }
+ /* we used to destroy the handle here but it may be still in
+ use during signal processing, so destroy it on unref
+ instead */
if (server->readtag > 0) {
g_source_remove(server->readtag);
@@ -513,6 +499,8 @@ void server_ref(SERVER_REC *server)
int server_unref(SERVER_REC *server)
{
+ int chans;
+
g_return_val_if_fail(IS_SERVER(server), FALSE);
if (--server->refcount > 0)
@@ -524,6 +512,29 @@ int server_unref(SERVER_REC *server)
return TRUE;
}
+ /* close all channels */
+ chans = server_remove_channels(server);
+
+ /* since module initialisation uses server connected, only let
+ them know that the object got destroyed if the server was
+ disconnected */
+ if (server->disconnected) {
+ signal_emit("server destroyed", 1, server);
+ }
+
+ if (server->handle != NULL) {
+ if (!chans || server->connection_lost)
+ net_sendbuffer_destroy(server->handle, TRUE);
+ else {
+ /* we were on some channels, try to let the server
+ disconnect so that our quit message is guaranteed
+ to get displayed */
+ net_disconnect_later(net_sendbuffer_handle(server->handle));
+ net_sendbuffer_destroy(server->handle, FALSE);
+ }
+ server->handle = NULL;
+ }
+
MODULE_DATA_DEINIT(server);
server_connect_unref(server->connrec);
if (server->rawlog != NULL) rawlog_destroy(server->rawlog);
diff --git a/src/core/special-vars.c b/src/core/special-vars.c
index aaf8da8f..33d9cd55 100644
--- a/src/core/special-vars.c
+++ b/src/core/special-vars.c
@@ -33,6 +33,8 @@
#define isarg(c) \
(i_isdigit(c) || (c) == '*' || (c) == '~' || (c) == '-')
+#define ALIGN_MAX 222488
+
static SPECIAL_HISTORY_FUNC history_func = NULL;
static char *get_argument(char **cmd, char **arglist)
@@ -300,6 +302,10 @@ static int get_alignment_args(char **data, int *align, int *flags, char *pad)
if (!parse_uint(str, &endptr, 10, &align_)) {
return FALSE;
}
+ /* alignment larger than supported */
+ if (align_ > ALIGN_MAX) {
+ return FALSE;
+ }
str = endptr;
*align = align_;
@@ -337,11 +343,14 @@ char *get_alignment(const char *text, int align, int flags, char pad)
/* add pad characters */
if (flags & ALIGN_PAD) {
- while (string_width(str->str, policy) < align) {
+ int pad_len = align - string_width(str->str, policy);
+ if (pad_len > 0) {
+ char *pad_full = g_strnfill(pad_len, pad);
if (flags & ALIGN_RIGHT)
- g_string_prepend_c(str, pad);
+ g_string_prepend(str, pad_full);
else
- g_string_append_c(str, pad);
+ g_string_append(str, pad_full);
+ g_free(pad_full);
}
}
@@ -384,6 +393,7 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item,
}
nest_free = FALSE; nest_value = NULL;
+#if 0 /* this code is disabled due to security issues until it is fixed */
if (**cmd == '(' && (*cmd)[1] != '\0') {
/* subvariable */
int toplevel = nested_orig_cmd == NULL;
@@ -412,6 +422,9 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item,
if (toplevel) nested_orig_cmd = NULL;
}
+#else
+ if (nested_orig_cmd) nested_orig_cmd = NULL;
+#endif
if (**cmd != '{')
brackets = FALSE;