1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-30 23:06:38 +02:00

Add SASL authentication in IRC plugin (task #8829), add function "string_encode_base64" in plugin API, fix bug with base64 encoding

New options for IRC servers:
- sasl_mechanism (only "plain" for now)
- sasl_username
- sasl_password
This commit is contained in:
Sebastien Helleu
2010-02-15 11:51:44 +01:00
parent 34272b7e4d
commit 341551f2f2
26 changed files with 925 additions and 115 deletions
+7 -4
View File
@@ -1247,7 +1247,7 @@ irc_command_disconnect_one_server (struct t_irc_server *server)
return 0;
if ((!server->is_connected) && (!server->hook_connect)
&& (server->reconnect_start == 0))
&& (!server->hook_fd) && (server->reconnect_start == 0))
{
weechat_printf (server->buffer,
_("%s%s: not connected to server \"%s\"!"),
@@ -1296,6 +1296,7 @@ irc_command_disconnect (void *data, struct t_gui_buffer *buffer, int argc,
ptr_server = ptr_server->next_server)
{
if ((ptr_server->is_connected) || (ptr_server->hook_connect)
|| (ptr_server->hook_fd)
|| (ptr_server->reconnect_start != 0))
{
if (!irc_command_disconnect_one_server (ptr_server))
@@ -2853,7 +2854,7 @@ irc_command_quote (void *data, struct t_gui_buffer *buffer, int argc,
/*
* irc_command_reconnect_one_server: reconnect to a server
* return 0 if error, 1 if ok
* return 0 if error, 1 if ok
*/
int
@@ -2862,7 +2863,8 @@ irc_command_reconnect_one_server (struct t_irc_server *server, int no_join)
if (!server)
return 0;
if ((!server->is_connected) && (!server->hook_connect))
if ((!server->is_connected) && (!server->hook_connect)
&& (!server->hook_fd))
{
weechat_printf (server->buffer,
_("%s%s: not connected to server \"%s\"!"),
@@ -2918,7 +2920,8 @@ irc_command_reconnect (void *data, struct t_gui_buffer *buffer, int argc,
ptr_server = ptr_server->next_server)
{
nb_reconnect++;
if ((ptr_server->is_connected) || (ptr_server->hook_connect))
if ((ptr_server->is_connected) || (ptr_server->hook_connect)
|| (ptr_server->hook_fd))
{
if (!irc_command_reconnect_one_server (ptr_server, no_join))
reconnect_ok = 0;
+36
View File
@@ -964,6 +964,42 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
case IRC_SERVER_OPTION_SASL_MECHANISM:
new_option = weechat_config_new_option (
config_file, section,
option_name, "integer",
N_("mechanism for SASL authentication"),
"plain" /*"plain|dh-blowfish"*/, 0, 0,
default_value, value,
null_value_allowed,
NULL, NULL,
callback_change, callback_change_data,
NULL, NULL);
break;
case IRC_SERVER_OPTION_SASL_USERNAME:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("username for SASL authentication"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
NULL, NULL,
callback_change, callback_change_data,
NULL, NULL);
break;
case IRC_SERVER_OPTION_SASL_PASSWORD:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("password for SASL authentication"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
NULL, NULL,
callback_change, callback_change_data,
NULL, NULL);
break;
case IRC_SERVER_OPTION_AUTOCONNECT:
new_option = weechat_config_new_option (
config_file, section,
+44 -2
View File
@@ -172,7 +172,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_DELIMITERS,
IRC_COLOR_CHAT,
(server->temp_server) ? _(" (temporary)") : "");
/* addresses */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_ADDRESSES]))
weechat_printf (NULL, " addresses. . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_ADDRESSES));
@@ -180,6 +180,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " addresses. . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_ADDRESSES]));
/* proxy */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_PROXY]))
weechat_printf (NULL, " proxy. . . . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PROXY));
@@ -187,6 +188,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " proxy. . . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_PROXY]));
/* ipv6 */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_IPV6]))
weechat_printf (NULL, " ipv6 . . . . . . . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_IPV6)) ?
@@ -196,6 +198,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_boolean (server->options[IRC_SERVER_OPTION_IPV6]) ?
_("on") : _("off"));
/* ssl */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SSL]))
weechat_printf (NULL, " ssl. . . . . . . . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_SSL)) ?
@@ -205,7 +208,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_boolean (server->options[IRC_SERVER_OPTION_SSL]) ?
_("on") : _("off"));
/* ssl_cert */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SSL_CERT]))
weechat_printf (NULL, " ssl_cert . . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SSL_CERT));
@@ -213,6 +216,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " ssl_cert . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_SSL_CERT]));
/* ssl_dhkey_size */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SSL_DHKEY_SIZE]))
weechat_printf (NULL, " ssl_dhkey_size . . . : (%d)",
IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SSL_DHKEY_SIZE));
@@ -220,6 +224,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " ssl_dhkey_size . . . : %s%d",
IRC_COLOR_CHAT_VALUE,
weechat_config_integer (server->options[IRC_SERVER_OPTION_SSL_DHKEY_SIZE]));
/* ssl_verify */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SSL_VERIFY]))
weechat_printf (NULL, " ssl_verify . . . . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_SSL_VERIFY)) ?
@@ -229,6 +234,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_boolean (server->options[IRC_SERVER_OPTION_SSL_VERIFY]) ?
_("on") : _("off"));
/* password */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_PASSWORD]))
weechat_printf (NULL, " password . . . . . . : %s",
_("(hidden)"));
@@ -236,6 +242,31 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " password . . . . . . : %s%s",
IRC_COLOR_CHAT_VALUE,
_("(hidden)"));
/* sasl_mechanism */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SASL_MECHANISM]))
weechat_printf (NULL, " sasl_mechanism . . . : ('%s')",
irc_sasl_mechanism_string[IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SASL_MECHANISM)]);
else
weechat_printf (NULL, " sasl_mechanism . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
irc_sasl_mechanism_string[weechat_config_integer (server->options[IRC_SERVER_OPTION_SASL_MECHANISM])]);
/* sasl_username */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SASL_USERNAME]))
weechat_printf (NULL, " sasl_username. . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME));
else
weechat_printf (NULL, " sasl_username. . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_SASL_USERNAME]));
/* sasl_password */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SASL_PASSWORD]))
weechat_printf (NULL, " sasl_password. . . . : %s",
_("(hidden)"));
else
weechat_printf (NULL, " sasl_password. . . . : %s%s",
IRC_COLOR_CHAT_VALUE,
_("(hidden)"));
/* autoconnect */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTOCONNECT]))
weechat_printf (NULL, " autoconnect. . . . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOCONNECT)) ?
@@ -245,6 +276,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_boolean (server->options[IRC_SERVER_OPTION_AUTOCONNECT]) ?
_("on") : _("off"));
/* autoreconnect */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTORECONNECT]))
weechat_printf (NULL, " autoreconnect. . . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTORECONNECT)) ?
@@ -254,6 +286,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_boolean (server->options[IRC_SERVER_OPTION_AUTORECONNECT]) ?
_("on") : _("off"));
/* autoreconnect_delay */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTORECONNECT_DELAY]))
weechat_printf (NULL, " autoreconnect_delay. : (%d %s)",
IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AUTORECONNECT_DELAY),
@@ -263,6 +296,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_integer (server->options[IRC_SERVER_OPTION_AUTORECONNECT_DELAY]),
NG_("second", "seconds", weechat_config_integer (server->options[IRC_SERVER_OPTION_AUTORECONNECT_DELAY])));
/* nicks */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_NICKS]))
weechat_printf (NULL, " nicks. . . . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_NICKS));
@@ -270,6 +304,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " nicks. . . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_NICKS]));
/* username */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_USERNAME]))
weechat_printf (NULL, " username . . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME));
@@ -277,6 +312,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " username . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_USERNAME]));
/* realname */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_REALNAME]))
weechat_printf (NULL, " realname . . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME));
@@ -284,6 +320,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " realname . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_REALNAME]));
/* local_hostname */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_LOCAL_HOSTNAME]))
weechat_printf (NULL, " local_hostname . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_LOCAL_HOSTNAME));
@@ -291,6 +328,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " local_hostname . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_LOCAL_HOSTNAME]));
/* command */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_COMMAND]))
{
string = strdup (IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND));
@@ -312,6 +350,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
if (string)
free (string);
}
/* command_delay */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_COMMAND_DELAY]))
weechat_printf (NULL, " command_delay. . . . : (%d %s)",
IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_COMMAND_DELAY),
@@ -321,6 +360,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_integer (server->options[IRC_SERVER_OPTION_COMMAND_DELAY]),
NG_("second", "seconds", weechat_config_integer (server->options[IRC_SERVER_OPTION_COMMAND_DELAY])));
/* autojoin */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTOJOIN]))
weechat_printf (NULL, " autojoin . . . . . . : ('%s')",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN));
@@ -328,6 +368,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " autojoin . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_AUTOJOIN]));
/* autorejoin */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTOREJOIN]))
weechat_printf (NULL, " autorejoin . . . . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOREJOIN)) ?
@@ -337,6 +378,7 @@ irc_display_server (struct t_irc_server *server, int with_detail)
IRC_COLOR_CHAT_VALUE,
weechat_config_boolean (server->options[IRC_SERVER_OPTION_AUTOREJOIN]) ?
_("on") : _("off"));
/* autorejoin_delay */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTOREJOIN_DELAY]))
weechat_printf (NULL, " autorejoin_delay . . : (%d %s)",
IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AUTOREJOIN_DELAY),
+225 -1
View File
@@ -215,6 +215,158 @@ irc_protocol_replace_vars (struct t_irc_server *server,
return res;
}
/*
* irc_protocol_cmd_authenticate: 'authenticate' message received
*/
int
irc_protocol_cmd_authenticate (struct t_irc_server *server, const char *command,
int argc, char **argv, char **argv_eol)
{
const char *sasl_username, *sasl_password;
char *string, *string_base64;
int length_username, length;
/* AUTHENTICATE message looks like:
AUTHENTICATE +
*/
IRC_PROTOCOL_MIN_ARGS(2);
/* make C compiler happy */
(void) command;
(void) argv_eol;
if (strcmp (argv[1], "+") == 0)
{
sasl_username = IRC_SERVER_OPTION_STRING(server,
IRC_SERVER_OPTION_SASL_USERNAME);
sasl_password = IRC_SERVER_OPTION_STRING(server,
IRC_SERVER_OPTION_SASL_PASSWORD);
if (sasl_username && sasl_username[0]
&& sasl_password && sasl_password[0])
{
length_username = strlen (sasl_username);
length = ((length_username + 1) * 2) + strlen (sasl_password) + 1;
string = malloc (length);
if (string)
{
snprintf (string, length, "%s|%s|%s",
sasl_username, sasl_username, sasl_password);
string[length_username] = '\0';
string[(length_username * 2) + 1] = '\0';
string_base64 = malloc (length * 2);
if (string_base64)
{
weechat_string_encode_base64 (string, length - 1, string_base64);
irc_server_sendf (server, 0, "AUTHENTICATE %s", string_base64);
free (string_base64);
}
free (string);
}
}
}
return WEECHAT_RC_OK;
}
/*
* irc_protocol_cmd_cap: 'cap' message received (client capability)
*/
int
irc_protocol_cmd_cap (struct t_irc_server *server, const char *command,
int argc, char **argv, char **argv_eol)
{
char *ptr_caps, **items;
int num_items, sasl, i;
/* CAP message looks like:
:server CAP * LS :identify-msg multi-prefix sasl
:server CAP * ACK :sasl
*/
IRC_PROTOCOL_MIN_ARGS(4);
/* make C compiler happy */
(void) command;
if (strcmp (argv[3], "LS") == 0)
{
if (argc > 4)
{
ptr_caps = (argv_eol[4][0] == ':') ? argv_eol[4] + 1 : argv_eol[4];
weechat_printf (server->buffer,
_("%s%s: client capability, server supports: %s"),
weechat_prefix ("network"),
IRC_PLUGIN_NAME,
ptr_caps);
sasl = 0;
items = weechat_string_split (ptr_caps, " ", 0, 0, &num_items);
if (items)
{
for (i = 0; i < num_items; i++)
{
if (strcmp (items[i], "sasl") == 0)
{
sasl = 1;
break;
}
}
weechat_string_free_split (items);
}
if (sasl)
{
weechat_printf (server->buffer,
_("%s%s: client capability, requesting: sasl"),
weechat_prefix ("network"),
IRC_PLUGIN_NAME);
irc_server_sendf (server, 0, "CAP REQ :sasl");
}
else
{
weechat_printf (server->buffer,
_("%s%s: client capability: sasl not supported"),
weechat_prefix ("network"),
IRC_PLUGIN_NAME);
irc_server_sendf (server, 0, "CAP END");
}
}
}
else if (strcmp (argv[3], "ACK") == 0)
{
if (argc > 4)
{
ptr_caps = (argv_eol[4][0] == ':') ? argv_eol[4] + 1 : argv_eol[4];
weechat_printf (server->buffer,
_("%s%s: client capability, enabled: %s"),
weechat_prefix ("network"),
IRC_PLUGIN_NAME,
ptr_caps);
if (strcmp (ptr_caps, "sasl") == 0)
{
switch (IRC_SERVER_OPTION_INTEGER(server,
IRC_SERVER_OPTION_SASL_USERNAME))
{
case IRC_SASL_MECHANISM_PLAIN:
irc_server_sendf (server, 0, "AUTHENTICATE PLAIN");
break;
default:
irc_server_sendf (server, 0, "AUTHENTICATE PLAIN");
break;
}
if (server->hook_timer_sasl)
weechat_unhook (server->hook_timer_sasl);
server->hook_timer_sasl = weechat_hook_timer (5 * 1000, 0, 1,
&irc_server_timer_sasl_cb,
server);
}
}
}
return WEECHAT_RC_OK;
}
/*
* irc_protocol_cmd_error: error received from server
*/
@@ -3557,6 +3709,35 @@ irc_protocol_cmd_438 (struct t_irc_server *server, const char *command,
return WEECHAT_RC_OK;
}
/*
* irc_protocol_cmd_900: '900' command (logged in as (SASL))
*/
int
irc_protocol_cmd_900 (struct t_irc_server *server, const char *command,
int argc, char **argv, char **argv_eol)
{
/* 900 message looks like:
:server 900 mynick nick!user@host mynick :You are now logged in as mynick
*/
IRC_PROTOCOL_MIN_ARGS(6);
weechat_printf_tags (irc_msgbuffer_get_target_buffer (server, argv[3],
command, NULL,
NULL),
irc_protocol_tags (command, "irc_numeric"),
"%s%s %s(%s%s%s)",
weechat_prefix ("network"),
(argv_eol[5][0] == ':') ? argv_eol[5] + 1 : argv_eol[5],
IRC_COLOR_CHAT_DELIMITERS,
IRC_COLOR_CHAT_HOST,
argv[3],
IRC_COLOR_CHAT_DELIMITERS);
return WEECHAT_RC_OK;
}
/*
* irc_protocol_cmd_901: '901' command received (you are now logged in)
*/
@@ -3587,6 +3768,44 @@ irc_protocol_cmd_901 (struct t_irc_server *server, const char *command,
return WEECHAT_RC_OK;
}
/*
* irc_protocol_cmd_903: '903' command received (SASL authentication successful)
*/
int
irc_protocol_cmd_903 (struct t_irc_server *server, const char *command,
int argc, char **argv, char **argv_eol)
{
/* 903 message looks like:
:server 903 nick :SASL authentication successful
*/
irc_protocol_cmd_numeric (server, command, argc, argv, argv_eol);
irc_server_sendf (server, 0, "CAP END");
return WEECHAT_RC_OK;
}
/*
* irc_protocol_cmd_904: '904' command received (SASL authentication failed)
*/
int
irc_protocol_cmd_904 (struct t_irc_server *server, const char *command,
int argc, char **argv, char **argv_eol)
{
/* 904 message looks like:
:server 904 nick :SASL authentication failed
*/
irc_protocol_cmd_numeric (server, command, argc, argv, argv_eol);
irc_server_sendf (server, 0, "CAP END");
return WEECHAT_RC_OK;
}
/*
* irc_protocol_is_numeric_command: return 1 if given string is 100% numeric
*/
@@ -3621,7 +3840,9 @@ irc_protocol_recv_command (struct t_irc_server *server, const char *entire_line,
const char *cmd_name;
char **argv, **argv_eol;
struct t_irc_protocol_msg irc_protocol_messages[] =
{ { "error", /* error received from IRC server */ 1, &irc_protocol_cmd_error },
{ { "authenticate", /* authenticate */ 1, &irc_protocol_cmd_authenticate },
{ "cap", /* client capability */ 1, &irc_protocol_cmd_cap },
{ "error", /* error received from IRC server */ 1, &irc_protocol_cmd_error },
{ "invite", /* invite a nick on a channel */ 1, &irc_protocol_cmd_invite },
{ "join", /* join a channel */ 1, &irc_protocol_cmd_join },
{ "kick", /* forcibly remove a user from a channel */ 1, &irc_protocol_cmd_kick },
@@ -3741,7 +3962,10 @@ irc_protocol_recv_command (struct t_irc_server *server, const char *entire_line,
{ "501", /* unknown mode flag */ 1, &irc_protocol_cmd_error },
{ "502", /* can't change mode for other users */ 1, &irc_protocol_cmd_error },
{ "671", /* whois (secure connection) */ 1, &irc_protocol_cmd_whois_nick_msg },
{ "900", /* logged in as (SASL) */ 1, &irc_protocol_cmd_900 },
{ "901", /* you are now logged in */ 1, &irc_protocol_cmd_901 },
{ "903", /* SASL authentication successful */ 1, &irc_protocol_cmd_903 },
{ "904", /* SASL authentication failed */ 1, &irc_protocol_cmd_904 },
{ "973", /* whois (secure connection) */ 1, &irc_protocol_cmd_server_mode_reason },
{ "974", /* whois (secure connection) */ 1, &irc_protocol_cmd_server_mode_reason },
{ "975", /* whois (secure connection) */ 1, &irc_protocol_cmd_server_mode_reason },
+144 -10
View File
@@ -58,19 +58,26 @@ struct t_irc_message *irc_recv_msgq = NULL;
struct t_irc_message *irc_msgq_last_msg = NULL;
char *irc_server_option_string[IRC_SERVER_NUM_OPTIONS] =
{ "addresses", "proxy", "ipv6", "ssl", "ssl_cert", "ssl_dhkey_size",
"ssl_verify", "password", "autoconnect", "autoreconnect",
"autoreconnect_delay", "nicks", "username", "realname", "local_hostname",
{ "addresses", "proxy", "ipv6",
"ssl", "ssl_cert", "ssl_dhkey_size", "ssl_verify",
"password", "sasl_mechanism", "sasl_username", "sasl_password",
"autoconnect", "autoreconnect", "autoreconnect_delay",
"nicks", "username", "realname", "local_hostname",
"command", "command_delay", "autojoin", "autorejoin", "autorejoin_delay",
};
char *irc_server_option_default[IRC_SERVER_NUM_OPTIONS] =
{ "", "", "off", "off", "", "2048",
"on", "", "off", "on",
"30", "", "", "", "",
{ "", "", "off",
"off", "", "2048", "on",
"", "plain", "", "",
"off", "on", "30",
"", "", "", "",
"", "0", "", "off", "30",
};
char *irc_sasl_mechanism_string[IRC_NUM_SASL_MECHANISMS] =
{ "plain", /*"dh-blowfish"*/ };
void irc_server_reconnect (struct t_irc_server *server);
void irc_server_check_away ();
@@ -128,6 +135,26 @@ irc_server_search_option (const char *option_name)
return -1;
}
/*
* irc_server_sasl_enabled: return 1 if SASL is enabled on server
* 0 if SASL is NOT enabled on server
*/
int
irc_server_sasl_enabled (struct t_irc_server *server)
{
const char *sasl_username, *sasl_password;
sasl_username = IRC_SERVER_OPTION_STRING(server,
IRC_SERVER_OPTION_SASL_USERNAME);
sasl_password = IRC_SERVER_OPTION_STRING(server,
IRC_SERVER_OPTION_SASL_PASSWORD);
/* SASL is enabled if username AND password are set */
return (sasl_username && sasl_username[0]
&& sasl_password && sasl_password[0]) ? 1 : 0;
}
/*
* irc_server_get_name_without_port: get name of server without port
* (ends before first '/' if found)
@@ -295,6 +322,7 @@ irc_server_alloc (const char *name)
new_server->sock = -1;
new_server->hook_connect = NULL;
new_server->hook_fd = NULL;
new_server->hook_timer_sasl = NULL;
new_server->is_connected = 0;
new_server->ssl_connected = 0;
new_server->unterminated_message = NULL;
@@ -684,10 +712,16 @@ irc_server_free_data (struct t_irc_server *server)
free (server->ports_array);
if (server->current_ip)
free (server->current_ip);
if (server->nicks_array)
weechat_string_free_split (server->nicks_array);
if (server->hook_connect)
weechat_unhook (server->hook_connect);
if (server->hook_fd)
weechat_unhook (server->hook_fd);
if (server->hook_timer_sasl)
weechat_unhook (server->hook_timer_sasl);
if (server->unterminated_message)
free (server->unterminated_message);
if (server->nicks_array)
weechat_string_free_split (server->nicks_array);
if (server->nick)
free (server->nick);
if (server->nick_modes)
@@ -696,6 +730,11 @@ irc_server_free_data (struct t_irc_server *server)
free (server->prefix);
if (server->away_message)
free (server->away_message);
if (server->cmd_list_regexp)
{
regfree (server->cmd_list_regexp);
free (server->cmd_list_regexp);
}
for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++)
{
irc_server_outqueue_free_all (server, i);
@@ -1693,6 +1732,41 @@ irc_server_recv_cb (void *arg_server, int fd)
return WEECHAT_RC_OK;
}
/*
* irc_server_timer_sasl_cb: callback for SASL authentication timer
* it is called if there is a timeout with SASL
* authentication
* (if SASL authentication is ok or failed, then
* hook timer is removed before this callback is
* called)
*/
int
irc_server_timer_sasl_cb (void *arg_server, int remaining_calls)
{
struct t_irc_server *server;
/* make C compiler happy */
(void) remaining_calls;
server = (struct t_irc_server *)arg_server;
if (!server)
return WEECHAT_RC_ERROR;
server->hook_timer_sasl = NULL;
if (!server->is_connected)
{
weechat_printf (server->buffer,
_("%s%s: sasl authentication timeout"),
weechat_prefix ("error"), IRC_PLUGIN_NAME);
irc_server_sendf (server, 0, "CAP END");
}
return WEECHAT_RC_OK;
}
/*
* irc_server_timer_cb: timer called each second to perform some operations
* on servers
@@ -1795,6 +1869,12 @@ void
irc_server_close_connection (struct t_irc_server *server)
{
int i;
if (server->hook_timer_sasl)
{
weechat_unhook (server->hook_timer_sasl);
server->hook_timer_sasl = NULL;
}
if (server->hook_fd)
{
@@ -1883,7 +1963,7 @@ void
irc_server_login (struct t_irc_server *server)
{
const char *password, *username, *realname;
password = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD);
username = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME);
realname = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME);
@@ -1898,6 +1978,11 @@ irc_server_login (struct t_irc_server *server)
server->nicks_array[0] : "weechat");
}
if (irc_server_sasl_enabled (server))
{
irc_server_sendf (server, 0, "CAP LS");
}
irc_server_sendf (server, 0,
"NICK %s\n"
"USER %s %s %s :%s",
@@ -3276,6 +3361,15 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
if (!weechat_infolist_new_var_string (ptr_item, "password",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD)))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "sasl_mechanism",
IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SASL_MECHANISM)))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "sasl_username",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "sasl_password",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "autoconnect",
IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOCONNECT)))
return 0;
@@ -3374,19 +3468,21 @@ irc_server_print_log ()
{
weechat_log_printf ("");
weechat_log_printf ("[server %s (addr:0x%lx)]", ptr_server->name, ptr_server);
/* addresses */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_ADDRESSES]))
weechat_log_printf (" addresses. . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_ADDRESSES));
else
weechat_log_printf (" addresses. . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_ADDRESSES]));
/* proxy */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_PROXY]))
weechat_log_printf (" proxy. . . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_PROXY));
else
weechat_log_printf (" proxy. . . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_PROXY]));
/* ipv6 */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_IPV6]))
weechat_log_printf (" ipv6 . . . . . . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_IPV6)) ?
@@ -3395,6 +3491,7 @@ irc_server_print_log ()
weechat_log_printf (" ipv6 . . . . . . . . : %s",
weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_IPV6]) ?
"on" : "off");
/* ssl */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SSL]))
weechat_log_printf (" ssl. . . . . . . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_SSL)) ?
@@ -3403,18 +3500,21 @@ irc_server_print_log ()
weechat_log_printf (" ssl. . . . . . . . . : %s",
weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_SSL]) ?
"on" : "off");
/* ssl_cert */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SSL_CERT]))
weechat_log_printf (" ssl_cert . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_SSL_CERT));
else
weechat_log_printf (" ssl_cert . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_SSL_CERT]));
/* ssl_dhkey_size */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SSL_DHKEY_SIZE]))
weechat_log_printf (" ssl_dhkey_size . . . : null ('%d')",
IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_SSL_DHKEY_SIZE));
else
weechat_log_printf (" ssl_dhkey_size . . . : '%d'",
weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_SSL_DHKEY_SIZE]));
/* ssl_verify */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SSL_VERIFY]))
weechat_log_printf (" ssl_verify . . . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_SSL_VERIFY)) ?
@@ -3423,10 +3523,31 @@ irc_server_print_log ()
weechat_log_printf (" ssl_verify . . . . . : %s",
weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_SSL_VERIFY]) ?
"on" : "off");
/* password */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_PASSWORD]))
weechat_log_printf (" password . . . . . . : null");
else
weechat_log_printf (" password . . . . . . : (hidden)");
/* sasl_mechanism */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SASL_MECHANISM]))
weechat_log_printf (" sasl_mechanism . . . : null ('%s')",
irc_sasl_mechanism_string[IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_SASL_MECHANISM)]);
else
weechat_log_printf (" sasl_mechanism . . . : '%s'",
irc_sasl_mechanism_string[weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_SASL_MECHANISM])]);
/* sasl_username */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SASL_USERNAME]))
weechat_log_printf (" sasl_username. . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_SASL_USERNAME));
else
weechat_log_printf (" sasl_username. . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_USERNAME]));
/* sasl_password */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_SASL_PASSWORD]))
weechat_log_printf (" sasl_password. . . . : null");
else
weechat_log_printf (" sasl_password. . . . : (hidden)");
/* autoconnect */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOCONNECT]))
weechat_log_printf (" autoconnect. . . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTOCONNECT)) ?
@@ -3435,6 +3556,7 @@ irc_server_print_log ()
weechat_log_printf (" autoconnect. . . . . : %s",
weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_AUTOCONNECT]) ?
"on" : "off");
/* autoreconnect */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTORECONNECT]))
weechat_log_printf (" autoreconnect. . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTORECONNECT)) ?
@@ -3443,52 +3565,61 @@ irc_server_print_log ()
weechat_log_printf (" autoreconnect. . . . : %s",
weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_AUTORECONNECT]) ?
"on" : "off");
/* autoreconnect_delay */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTORECONNECT_DELAY]))
weechat_log_printf (" autoreconnect_delay. : null (%d)",
IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_AUTORECONNECT_DELAY));
else
weechat_log_printf (" autoreconnect_delay. : %d",
weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_AUTORECONNECT_DELAY]));
/* nicks */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_NICKS]))
weechat_log_printf (" nicks. . . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_NICKS));
else
weechat_log_printf (" nicks. . . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_NICKS]));
/* username */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_USERNAME]))
weechat_log_printf (" username . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_USERNAME));
else
weechat_log_printf (" username . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_USERNAME]));
/* realname */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_REALNAME]))
weechat_log_printf (" realname . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_REALNAME));
else
weechat_log_printf (" realname . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_REALNAME]));
/* local_hostname */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_LOCAL_HOSTNAME]))
weechat_log_printf (" local_hostname . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_LOCAL_HOSTNAME));
else
weechat_log_printf (" local_hostname . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_LOCAL_HOSTNAME]));
/* command */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_COMMAND]))
weechat_log_printf (" command. . . . . . . : null");
else
weechat_log_printf (" command. . . . . . . : (hidden)");
/* command_delay */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_COMMAND_DELAY]))
weechat_log_printf (" command_delay. . . . : null (%d)",
IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_COMMAND_DELAY));
else
weechat_log_printf (" command_delay. . . . : %d",
weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_COMMAND_DELAY]));
/* autojoin */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOJOIN]))
weechat_log_printf (" autojoin . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_AUTOJOIN));
else
weechat_log_printf (" autojoin . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_AUTOJOIN]));
/* autorejoin */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOREJOIN]))
weechat_log_printf (" autorejoin . . . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTOREJOIN)) ?
@@ -3497,12 +3628,14 @@ irc_server_print_log ()
weechat_log_printf (" autorejoin . . . . . : %s",
weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_AUTOREJOIN]) ?
"on" : "off");
/* autorejoin_delay */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOREJOIN_DELAY]))
weechat_log_printf (" autorejoin_delay . . : null (%d)",
IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_AUTOREJOIN_DELAY));
else
weechat_log_printf (" autorejoin_delay . . : %d",
weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_AUTOREJOIN_DELAY]));
/* other server variables */
weechat_log_printf (" temp_server. . . . . : %d", ptr_server->temp_server);
weechat_log_printf (" reloading_from_config: %d", ptr_server->reloaded_from_config);
weechat_log_printf (" reloaded_from_config : %d", ptr_server->reloaded_from_config);
@@ -3514,6 +3647,7 @@ irc_server_print_log ()
weechat_log_printf (" sock . . . . . . . . : %d", ptr_server->sock);
weechat_log_printf (" hook_connect . . . . : 0x%lx", ptr_server->hook_connect);
weechat_log_printf (" hook_fd. . . . . . . : 0x%lx", ptr_server->hook_fd);
weechat_log_printf (" hook_timer_sasl. . . : 0x%lx", ptr_server->hook_timer_sasl);
weechat_log_printf (" is_connected . . . . : %d", ptr_server->is_connected);
weechat_log_printf (" ssl_connected. . . . : %d", ptr_server->ssl_connected);
#ifdef HAVE_GNUTLS
+17
View File
@@ -41,6 +41,9 @@ enum t_irc_server_option
IRC_SERVER_OPTION_SSL_DHKEY_SIZE, /* Diffie Hellman key size */
IRC_SERVER_OPTION_SSL_VERIFY, /* check if the connection is trusted */
IRC_SERVER_OPTION_PASSWORD, /* password for server */
IRC_SERVER_OPTION_SASL_MECHANISM,/* mechanism for SASL authentication */
IRC_SERVER_OPTION_SASL_USERNAME, /* username for SASL authentication */
IRC_SERVER_OPTION_SASL_PASSWORD, /* password for SASL authentication */
IRC_SERVER_OPTION_AUTOCONNECT, /* autoconnect to server at startup */
IRC_SERVER_OPTION_AUTORECONNECT, /* autoreconnect when disconnected */
IRC_SERVER_OPTION_AUTORECONNECT_DELAY, /* delay before trying again reco */
@@ -87,6 +90,16 @@ enum t_irc_server_option
#define IRC_SERVER_OUTQUEUE_PRIO_LOW 2
#define IRC_SERVER_NUM_OUTQUEUES_PRIO 2
/* SASL authentication mechanisms */
enum t_irc_sasl_mechanism
{
IRC_SASL_MECHANISM_PLAIN = 0,
/* TODO: IRC_SASL_MECHANISM_DH_BLOWFISH, */
/* number of SASL mechanisms */
IRC_NUM_SASL_MECHANISMS,
};
/* output queue of messages to server (for sending slowly to server) */
struct t_irc_outqueue
@@ -117,6 +130,7 @@ struct t_irc_server
int sock; /* socket for server (IPv4 or IPv6) */
struct t_hook *hook_connect; /* connection hook */
struct t_hook *hook_fd; /* hook for server socket */
struct t_hook *hook_timer_sasl; /* timer for SASL authentication */
int is_connected; /* 1 if WeeChat is connected to server */
int ssl_connected; /* = 1 if connected with SSL */
#ifdef HAVE_GNUTLS
@@ -171,9 +185,11 @@ extern const int gnutls_prot_prio[];
extern struct t_irc_message *irc_recv_msgq, *irc_msgq_last_msg;
extern char *irc_server_option_string[];
extern char *irc_server_option_default[];
extern char *irc_sasl_mechanism_string[];
extern int irc_server_valid (struct t_irc_server *server);
extern int irc_server_search_option (const char *option_name);
extern int irc_server_sasl_enabled (struct t_irc_server *server);
extern char *irc_server_get_name_without_port (const char *name);
extern void irc_server_set_addresses (struct t_irc_server *server,
const char *addresses);
@@ -199,6 +215,7 @@ extern int irc_server_connect (struct t_irc_server *server);
extern void irc_server_auto_connect ();
extern void irc_server_autojoin_channels ();
extern int irc_server_recv_cb (void *arg_server, int fd);
extern int irc_server_timer_sasl_cb (void *arg_server, int remaining_calls);
extern int irc_server_timer_cb (void *data, int remaining_calls);
extern int irc_server_timer_check_away_cb (void *data, int remaining_calls);
extern void irc_server_outqueue_free_all (struct t_irc_server *server,
+1
View File
@@ -384,6 +384,7 @@ plugin_load (const char *filename)
new_plugin->string_free_split_command = &string_free_split_command;
new_plugin->string_format_size = &string_format_size;
new_plugin->string_remove_color = &gui_color_decode;
new_plugin->string_encode_base64 = &string_encode_base64;
new_plugin->utf8_has_8bits = &utf8_has_8bits;
new_plugin->utf8_is_valid = &utf8_is_valid;
+4 -1
View File
@@ -34,7 +34,7 @@ struct t_weelist;
struct timeval;
/* API version (used to check that plugin has same API and can be loaded) */
#define WEECHAT_PLUGIN_API_VERSION "20100212-01"
#define WEECHAT_PLUGIN_API_VERSION "20100215-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -170,6 +170,7 @@ struct t_weechat_plugin
void (*string_free_split_command) (char **split_command);
char *(*string_format_size) (unsigned long size);
char *(*string_remove_color) (const char *string, const char *replacement);
void (*string_encode_base64) (const char *from, int length, char *to);
/* UTF-8 strings */
int (*utf8_has_8bits) (const char *string);
@@ -717,6 +718,8 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
weechat_plugin->string_format_size(__size)
#define weechat_string_remove_color(__string, __replacement) \
weechat_plugin->string_remove_color(__string, __replacement)
#define weechat_string_encode_base64(__from, __length, __to) \
weechat_plugin->string_encode_base64(__from, __length, __to)
/* UTF-8 strings */
#define weechat_utf8_has_8bits(__string) \