summaryrefslogtreecommitdiff
path: root/src/plugins/irc/irc-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/irc/irc-server.c')
-rw-r--r--src/plugins/irc/irc-server.c252
1 files changed, 195 insertions, 57 deletions
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index dd785c29a..2e43afab5 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -1,7 +1,7 @@
/*
* irc-server.c - I/O communication with IRC servers
*
- * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org>
+ * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org>
* Copyright (C) 2005-2010 Emmanuel Bouthenot <kolter@openics.org>
* Copyright (C) 2012 Simon Arlott
*
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include <ctype.h>
#include <time.h>
#ifdef _WIN32
#include <winsock.h>
@@ -117,6 +118,7 @@ char *irc_server_options[IRC_SERVER_NUM_OPTIONS][2] =
{ "msg_part", "WeeChat ${info:version}" },
{ "msg_quit", "WeeChat ${info:version}" },
{ "notify", "" },
+ { "split_msg_max_length", "512" },
};
char *irc_server_casemapping_string[IRC_SERVER_NUM_CASEMAPPING] =
@@ -337,6 +339,152 @@ irc_server_strncasecmp (struct t_irc_server *server,
}
/*
+ * Evaluates a string using the server as context:
+ * ${irc_server.xxx} and ${server} are replaced by a server option and the
+ * server name.
+ *
+ * Returns the evaluated string.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+irc_server_eval_expression (struct t_irc_server *server, const char *string)
+{
+ struct t_hashtable *pointers, *extra_vars;
+ char *value;
+
+ pointers = weechat_hashtable_new (
+ 32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER,
+ NULL, NULL);
+ extra_vars = weechat_hashtable_new (
+ 32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+
+ if (server)
+ {
+ if (pointers)
+ weechat_hashtable_set (pointers, "irc_server", server);
+ if (extra_vars)
+ weechat_hashtable_set (extra_vars, "server", server->name);
+ }
+
+ value = weechat_string_eval_expression (string,
+ pointers, extra_vars, NULL);
+
+ if (pointers)
+ weechat_hashtable_free (pointers);
+ if (extra_vars)
+ weechat_hashtable_free (extra_vars);
+
+ return value;
+}
+
+/*
+ * Evaluates and returns the fingerprint.
+ *
+ * Returns the evaluated fingerprint, NULL if the fingerprint option is
+ * invalid.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+irc_server_eval_fingerprint (struct t_irc_server *server)
+{
+#ifdef HAVE_GNUTLS
+ const char *ptr_fingerprint;
+ char *fingerprint_eval, **fingerprints, *str_sizes;
+ int i, j, rc, algo, length;
+
+ ptr_fingerprint = IRC_SERVER_OPTION_STRING(server,
+ IRC_SERVER_OPTION_SSL_FINGERPRINT);
+
+ /* empty fingerprint is just ignored (considered OK) */
+ if (!ptr_fingerprint || !ptr_fingerprint[0])
+ return strdup ("");
+
+ /* evaluate fingerprint */
+ fingerprint_eval = irc_server_eval_expression (server, ptr_fingerprint);
+ if (!fingerprint_eval || !fingerprint_eval[0])
+ {
+ weechat_printf (
+ server->buffer,
+ _("%s%s: the evaluated fingerprint for server \"%s\" must not be "
+ "empty"),
+ weechat_prefix ("error"),
+ IRC_PLUGIN_NAME,
+ server->name);
+ if (fingerprint_eval)
+ free (fingerprint_eval);
+ return NULL;
+ }
+
+ /* split fingerprint */
+ fingerprints = weechat_string_split (fingerprint_eval, ",", 0, 0, NULL);
+ if (!fingerprints)
+ return fingerprint_eval;
+
+ rc = 0;
+ for (i = 0; fingerprints[i]; i++)
+ {
+ length = strlen (fingerprints[i]);
+ algo = irc_server_fingerprint_search_algo_with_size (length * 4);
+ if (algo < 0)
+ {
+ rc = -1;
+ break;
+ }
+ for (j = 0; j < length; j++)
+ {
+ if (!isxdigit ((unsigned char)fingerprints[i][j]))
+ {
+ rc = -2;
+ break;
+ }
+ }
+ if (rc < 0)
+ break;
+ }
+ weechat_string_free_split (fingerprints);
+ switch (rc)
+ {
+ case -1: /* invalid size */
+ str_sizes = irc_server_fingerprint_str_sizes ();
+ weechat_printf (
+ server->buffer,
+ _("%s%s: invalid fingerprint size for server \"%s\", the "
+ "number of hexadecimal digits must be "
+ "one of: %s"),
+ weechat_prefix ("error"),
+ IRC_PLUGIN_NAME,
+ server->name,
+ (str_sizes) ? str_sizes : "?");
+ if (str_sizes)
+ free (str_sizes);
+ free (fingerprint_eval);
+ return NULL;
+ case -2: /* invalid content */
+ weechat_printf (
+ server->buffer,
+ _("%s%s: invalid fingerprint for server \"%s\", it must "
+ "contain only hexadecimal digits (0-9, "
+ "a-f)"),
+ weechat_prefix ("error"), IRC_PLUGIN_NAME, server->name);
+ free (fingerprint_eval);
+ return NULL;
+ }
+ return fingerprint_eval;
+#else
+ return strdup ("");
+#endif /* HAVE_GNUTLS */
+}
+
+/*
* Checks if SASL is enabled on server.
*
* Returns:
@@ -353,12 +501,12 @@ irc_server_sasl_enabled (struct t_irc_server *server)
sasl_mechanism = IRC_SERVER_OPTION_INTEGER(
server, IRC_SERVER_OPTION_SASL_MECHANISM);
- sasl_username = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME),
- NULL, NULL, NULL);
- sasl_password = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD),
- NULL, NULL, NULL);
+ sasl_username = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME));
+ sasl_password = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD));
sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY);
/*
@@ -422,8 +570,7 @@ irc_server_set_addresses (struct t_irc_server *server, const char *addresses)
if (addresses && addresses[0])
{
- addresses_eval = weechat_string_eval_expression (addresses,
- NULL, NULL, NULL);
+ addresses_eval = irc_server_eval_expression (server, addresses);
if (server->addresses_eval
&& (strcmp (server->addresses_eval, addresses_eval) == 0))
{
@@ -550,7 +697,7 @@ irc_server_set_nicks (struct t_irc_server *server, const char *nicks)
}
/* evaluate value */
- nicks2 = weechat_string_eval_expression (nicks, NULL, NULL, NULL);
+ nicks2 = irc_server_eval_expression (server, nicks);
/* set new nicks */
server->nicks_array = weechat_string_split (
@@ -2498,7 +2645,10 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags,
(new_msg) ? new_msg : items[i],
NULL);
- /* split message if needed (max is 512 bytes including final "\r\n") */
+ /*
+ * split message if needed (max is 512 bytes by default,
+ * including the final "\r\n")
+ */
hashtable = irc_message_split (server,
(new_msg) ? new_msg : items[i]);
if (hashtable)
@@ -2707,8 +2857,8 @@ void
irc_server_msgq_flush ()
{
struct t_irc_message *next;
- char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *ptr_msg3, *pos;
- char *tags, *nick, *host, *command, *channel, *arguments;
+ char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *pos;
+ char *nick, *host, *command, *channel, *arguments;
char *msg_decoded, *msg_decoded_without_color;
char str_modifier[128], modifier_data[256];
int pos_channel, pos_text, pos_decode;
@@ -2773,7 +2923,7 @@ irc_server_msgq_flush ()
}
irc_message_parse (irc_recv_msgq->server, ptr_msg,
- &tags, NULL, &nick, &host,
+ NULL, NULL, &nick, &host,
&command, &channel, &arguments,
NULL, NULL, NULL,
&pos_channel, &pos_text);
@@ -2860,25 +3010,9 @@ irc_server_msgq_flush ()
else
{
/* message not redirected, display it */
- ptr_msg3 = ptr_msg2;
- if (ptr_msg3[0] == '@')
- {
- /* skip tags in message */
- ptr_msg3 = strchr (ptr_msg3, ' ');
- if (ptr_msg3)
- {
- while (ptr_msg3[0] == ' ')
- {
- ptr_msg3++;
- }
- }
- else
- ptr_msg3 = ptr_msg2;
- }
irc_protocol_recv_command (
irc_recv_msgq->server,
- ptr_msg3,
- tags,
+ ptr_msg2,
command,
channel);
}
@@ -3508,15 +3642,15 @@ irc_server_login (struct t_irc_server *server)
const char *capabilities;
char *password, *username, *realname, *username2;
- password = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD),
- NULL, NULL, NULL);
- username = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME),
- NULL, NULL, NULL);
- realname = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME),
- NULL, NULL, NULL);
+ password = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD));
+ username = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME));
+ realname = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME));
capabilities = IRC_SERVER_OPTION_STRING(
server, IRC_SERVER_OPTION_CAPABILITIES);
@@ -4235,8 +4369,12 @@ irc_server_gnutls_callback (const void *pointer, void *data,
/* get fingerprint option in server */
ptr_fingerprint = IRC_SERVER_OPTION_STRING(server,
IRC_SERVER_OPTION_SSL_FINGERPRINT);
- fingerprint_eval = weechat_string_eval_expression (ptr_fingerprint,
- NULL, NULL, NULL);
+ fingerprint_eval = irc_server_eval_fingerprint (server);
+ if (!fingerprint_eval)
+ {
+ rc = -1;
+ goto end;
+ }
/* set match options */
fingerprint_match = (ptr_fingerprint && ptr_fingerprint[0]) ? 0 : 1;
@@ -4969,9 +5107,9 @@ irc_server_autojoin_create_buffers (struct t_irc_server *server)
return;
/* evaluate server option "autojoin" */
- autojoin = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN),
- NULL, NULL, NULL);
+ autojoin = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN));
/* extract channel names from autojoin option */
if (autojoin && autojoin[0])
@@ -5042,9 +5180,9 @@ irc_server_autojoin_channels (struct t_irc_server *server)
else
{
/* auto-join when connecting to server for first time */
- autojoin = weechat_string_eval_expression (
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN),
- NULL, NULL, NULL);
+ autojoin = irc_server_eval_expression (
+ server,
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN));
if (!server->disable_autojoin && autojoin && autojoin[0])
irc_command_join_server (server, autojoin, 0, 0);
if (autojoin)
@@ -6079,26 +6217,26 @@ irc_server_print_log ()
weechat_log_printf (" chantypes. . . . . . : '%s'", ptr_server->chantypes);
weechat_log_printf (" chanmodes. . . . . . : '%s'", ptr_server->chanmodes);
weechat_log_printf (" monitor. . . . . . . : %d", ptr_server->monitor);
- weechat_log_printf (" monitor_time . . . . : %ld", ptr_server->monitor_time);
+ weechat_log_printf (" monitor_time . . . . : %lld", (long long)ptr_server->monitor_time);
weechat_log_printf (" reconnect_delay. . . : %d", ptr_server->reconnect_delay);
- weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start);
- weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time);
+ weechat_log_printf (" reconnect_start. . . : %lld", (long long)ptr_server->reconnect_start);
+ weechat_log_printf (" command_time . . . . : %lld", (long long)ptr_server->command_time);
weechat_log_printf (" reconnect_join . . . : %d", ptr_server->reconnect_join);
weechat_log_printf (" disable_autojoin . . : %d", ptr_server->disable_autojoin);
weechat_log_printf (" is_away. . . . . . . : %d", ptr_server->is_away);
weechat_log_printf (" away_message . . . . : '%s'", ptr_server->away_message);
- weechat_log_printf (" away_time. . . . . . : %ld", ptr_server->away_time);
+ weechat_log_printf (" away_time. . . . . . : %lld", (long long)ptr_server->away_time);
weechat_log_printf (" lag. . . . . . . . . : %d", ptr_server->lag);
weechat_log_printf (" lag_displayed. . . . : %d", ptr_server->lag_displayed);
weechat_log_printf (" lag_check_time . . . : tv_sec:%d, tv_usec:%d",
ptr_server->lag_check_time.tv_sec,
ptr_server->lag_check_time.tv_usec);
- weechat_log_printf (" lag_next_check . . . : %ld", ptr_server->lag_next_check);
- weechat_log_printf (" lag_last_refresh . . : %ld", ptr_server->lag_last_refresh);
+ weechat_log_printf (" lag_next_check . . . : %lld", (long long)ptr_server->lag_next_check);
+ weechat_log_printf (" lag_last_refresh . . : %lld", (long long)ptr_server->lag_last_refresh);
weechat_log_printf (" cmd_list_regexp. . . : 0x%lx", ptr_server->cmd_list_regexp);
- weechat_log_printf (" last_user_message. . : %ld", ptr_server->last_user_message);
- weechat_log_printf (" last_away_check. . . : %ld", ptr_server->last_away_check);
- weechat_log_printf (" last_data_purge. . . : %ld", ptr_server->last_data_purge);
+ weechat_log_printf (" last_user_message. . : %lld", (long long)ptr_server->last_user_message);
+ weechat_log_printf (" last_away_check. . . : %lld", (long long)ptr_server->last_away_check);
+ weechat_log_printf (" last_data_purge. . . : %lld", (long long)ptr_server->last_data_purge);
for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++)
{
weechat_log_printf (" outqueue[%02d] . . . . : 0x%lx", i, ptr_server->outqueue[i]);