diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2010-09-17 14:47:36 +0200 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2010-09-17 14:47:36 +0200 |
commit | d2d60d47110f49c3f4bb34c539da87222b76b9d4 (patch) | |
tree | 8943fca087668f8883ab2d77bddc05cb40f6a88d /src/plugins/relay | |
parent | 26a99c2912a30e994117bae5e042e60b2c229a26 (diff) | |
download | weechat-d2d60d47110f49c3f4bb34c539da87222b76b9d4.zip |
Beta version of IRC proxy feature in Relay plugin
Major changes in Relay plugin:
- IRC proxy feature (beta),
- raw buffer.
Changes in IRC plugin:
- add tags for messages sent to servers,
- add signal "irc_input_send" to simulate text/command on an IRC buffer,
- add prefix in infolist "irc_nick".
Diffstat (limited to 'src/plugins/relay')
-rw-r--r-- | src/plugins/relay/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/plugins/relay/Makefile.am | 10 | ||||
-rw-r--r-- | src/plugins/relay/relay-buffer.c | 3 | ||||
-rw-r--r-- | src/plugins/relay/relay-client-irc.c | 983 | ||||
-rw-r--r-- | src/plugins/relay/relay-client-irc.h (renamed from src/plugins/relay/relay-protocol-irc.h) | 26 | ||||
-rw-r--r-- | src/plugins/relay/relay-client-weechat.c (renamed from src/plugins/relay/relay-protocol-weechat.c) | 86 | ||||
-rw-r--r-- | src/plugins/relay/relay-client-weechat.h (renamed from src/plugins/relay/relay-protocol-weechat.h) | 20 | ||||
-rw-r--r-- | src/plugins/relay/relay-client.c | 67 | ||||
-rw-r--r-- | src/plugins/relay/relay-client.h | 1 | ||||
-rw-r--r-- | src/plugins/relay/relay-command.c | 28 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.c | 7 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.h | 1 | ||||
-rw-r--r-- | src/plugins/relay/relay-protocol-irc.c | 553 | ||||
-rw-r--r-- | src/plugins/relay/relay-raw.c | 370 | ||||
-rw-r--r-- | src/plugins/relay/relay-raw.h | 52 |
15 files changed, 1550 insertions, 662 deletions
diff --git a/src/plugins/relay/CMakeLists.txt b/src/plugins/relay/CMakeLists.txt index 9a36b5eba..dc9d09cfc 100644 --- a/src/plugins/relay/CMakeLists.txt +++ b/src/plugins/relay/CMakeLists.txt @@ -21,12 +21,13 @@ ADD_LIBRARY(relay MODULE relay.c relay.h relay-buffer.c relay-buffer.h relay-client.c relay-client.h +relay-client-irc.c relay-client-irc.h +relay-client-weechat.c relay-client-weechat.h relay-command.c relay-command.h relay-completion.c relay-completion.h relay-config.c relay-config.h relay-info.c relay-info.h -relay-protocol-irc.c relay-protocol-irc.h -relay-protocol-weechat.c relay-protocol-weechat.h +relay-raw.c relay-raw.h relay-server.c relay-server.h relay-upgrade.c relay-upgrade.h) SET_TARGET_PROPERTIES(relay PROPERTIES PREFIX "") diff --git a/src/plugins/relay/Makefile.am b/src/plugins/relay/Makefile.am index 53f6583f1..958614a44 100644 --- a/src/plugins/relay/Makefile.am +++ b/src/plugins/relay/Makefile.am @@ -29,6 +29,10 @@ relay_la_SOURCES = relay.c \ relay-buffer.h \ relay-client.c \ relay-client.h \ + relay-client-irc.c \ + relay-client-irc.h \ + relay-client-weechat.c \ + relay-client-weechat.h \ relay-command.c \ relay-command.h \ relay-completion.c \ @@ -37,10 +41,8 @@ relay_la_SOURCES = relay.c \ relay-config.h \ relay-info.c \ relay-info.h \ - relay-protocol-irc.c \ - relay-protocol-irc.h \ - relay-protocol-weechat.c \ - relay-protocol-weechat.h \ + relay-raw.c \ + relay-raw.h \ relay-server.c \ relay-server.h \ relay-upgrade.c \ diff --git a/src/plugins/relay/relay-buffer.c b/src/plugins/relay/relay-buffer.c index df39df81e..da68513f2 100644 --- a/src/plugins/relay/relay-buffer.c +++ b/src/plugins/relay/relay-buffer.c @@ -125,9 +125,10 @@ relay_buffer_refresh (const char *hotlist) str_recv = weechat_string_format_size (ptr_client->bytes_recv); str_sent = weechat_string_format_size (ptr_client->bytes_sent); weechat_printf_y (relay_buffer, (line * 2) + 3, - _("%s%-26s protocol: %s, received: %s, sent: %s"), + _("%s%-26s id: %d, protocol: %s, received: %s, sent: %s"), weechat_color(str_color), " ", + ptr_client->id, relay_protocol_string[ptr_client->protocol], (str_recv) ? str_recv : "?", (str_sent) ? str_sent : "?"); diff --git a/src/plugins/relay/relay-client-irc.c b/src/plugins/relay/relay-client-irc.c new file mode 100644 index 000000000..766c9e06d --- /dev/null +++ b/src/plugins/relay/relay-client-irc.c @@ -0,0 +1,983 @@ +/* + * Copyright (C) 2003-2010 Sebastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat 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 3 of the License, or + * (at your option) any later version. + * + * WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * relay-client-irc.c: IRC protocol for relay to client + * (relay acting as an IRC proxy/bouncer) + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-client-irc.h" +#include "relay-client.h" +#include "relay-raw.h" + + +char *relay_client_irc_relay_commands[] = { "privmsg", "notice", NULL }; +char *relay_client_irc_ignore_commands[] = { "pong", "quit", NULL }; + + +/* + * relay_client_irc_command_relayed: return 1 if IRC command has to be + * relayed to client, or 0 if command + * must NOT be relayed + */ + +int +relay_client_irc_command_relayed (const char *irc_command) +{ + int i; + + if (irc_command) + { + for (i = 0; relay_client_irc_relay_commands[i]; i++) + { + if (weechat_strcasecmp (relay_client_irc_relay_commands[i], irc_command) == 0) + return 1; + } + } + + /* command must NOT be relayed to client */ + return 0; +} + +/* + * relay_client_irc_command_ignored: return 1 if IRC command from client + * has to be ignored + */ + +int +relay_client_irc_command_ignored (const char *irc_command) +{ + int i; + + if (irc_command) + { + for (i = 0; relay_client_irc_ignore_commands[i]; i++) + { + if (weechat_strcasecmp (relay_client_irc_ignore_commands[i], irc_command) == 0) + return 1; + } + } + + /* command must NOT be relayed to client */ + return 0; +} + +/* + * relay_client_irc_parse_message: parse IRC message + */ + +struct t_hashtable * +relay_client_irc_parse_message (const char *message) +{ + struct t_hashtable *hash_msg, *hash_parsed; + + hash_msg = NULL; + hash_parsed = NULL; + + hash_msg = weechat_hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hash_msg) + { + weechat_printf (NULL, + _("%s%s: not enough memory for parsing message"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + goto end; + } + weechat_hashtable_set (hash_msg, "message", (char *)message); + hash_parsed = weechat_info_get_hashtable ("irc_parse_message", + hash_msg); + if (!hash_parsed) + { + weechat_printf (NULL, + _("%s%s: not enough memory for parsing message"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + goto end; + } + +end: + if (hash_msg) + weechat_hashtable_free (hash_msg); + + return hash_parsed; +} + +/* + * relay_client_irc_sendf: send formatted data to client + */ + +int +relay_client_irc_sendf (struct t_relay_client *client, const char *format, ...) +{ + va_list args; + static char buffer[4096]; + int length, num_sent; + char *pos; + + if (!client) + return 0; + + va_start (args, format); + vsnprintf (buffer, sizeof (buffer) - 3, format, args); + va_end (args); + + if (weechat_relay_plugin->debug >= 2) + { + weechat_printf (NULL, "%s: send: %s", + RELAY_PLUGIN_NAME, buffer); + } + + length = strlen (buffer); + + pos = strchr (buffer, '\r'); + if (pos) + pos[0] = '\0'; + + relay_raw_print (client, 1, buffer); + + if (pos) + pos[0] = '\r'; + else + { + buffer[length] = '\r'; + buffer[length + 1] = '\n'; + buffer[length + 2] = '\0'; + length += 2; + } + + num_sent = send (client->sock, buffer, length, 0); + + if (num_sent >= 0) + client->bytes_sent += num_sent; + else + { + weechat_printf (NULL, + _("%s%s: error sending data to client: %s"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME, + strerror (errno)); + } + + return num_sent; +} + +/* + * relay_client_irc_signal_irc_in2_cb: callback for "irc_in2" signal + * It is called when something is + * received on IRC server, and message + * can be relayed (or not) to client. + */ + +int +relay_client_irc_signal_irc_in2_cb (void *data, const char *signal, + const char *type_data, void *signal_data) +{ + struct t_relay_client *client; + const char *ptr_msg, *irc_host, *irc_command, *irc_args; + struct t_hashtable *hash_parsed; + + /* make C compiler happy */ + (void) signal; + (void) type_data; + + client = (struct t_relay_client *)data; + ptr_msg = (const char *)signal_data; + + if (weechat_relay_plugin->debug >= 2) + { + weechat_printf (NULL, "%s: irc_in2: client: %s, data: %s", + RELAY_PLUGIN_NAME, + client->protocol_string, + ptr_msg); + } + + hash_parsed = relay_client_irc_parse_message (ptr_msg); + if (hash_parsed) + { + irc_host = weechat_hashtable_get (hash_parsed, "host"); + irc_command = weechat_hashtable_get (hash_parsed, "command"); + irc_args = weechat_hashtable_get (hash_parsed, "arguments"); + + /* if self nick has changed, update it in client data */ + if (irc_command && (weechat_strcasecmp (irc_command, "nick") == 0)) + { + if (irc_args && irc_args[0]) + { + if (RELAY_IRC_DATA(client, nick)) + free (RELAY_IRC_DATA(client, nick)); + RELAY_IRC_DATA(client, nick) = strdup (irc_args); + } + } + + /* relay all commands to client, but not ping/pong */ + if (irc_command + && (weechat_strcasecmp (irc_command, "ping") != 0) + && (weechat_strcasecmp (irc_command, "pong") != 0)) + { + relay_client_irc_sendf (client, ":%s %s %s", + (irc_host && irc_host[0]) ? irc_host : RELAY_IRC_DATA(client, address), + irc_command, + irc_args); + } + } + + return WEECHAT_RC_OK; +} + +/* + * relay_client_irc_tag_relay_client_id: get id of client by looking for tag + * "relay_client_NNN" in list of tags + * (comma separated list) + * Return number found, or -1 if tag + * is not found. + */ + +int +relay_client_irc_tag_relay_client_id (const char *tags) +{ + char **argv, *error; + int result, argc, i; + long number; + + result = -1; + + if (tags && tags[0]) + { + argv = weechat_string_split (tags, ",", 0, 0, &argc); + if (argv) + { + for (i = 0; i < argc; i++) + { + if (strncmp (argv[i], "relay_client_", 13) == 0) + { + error = NULL; + number = strtol (argv[i] + 13, &error, 10); + if (error && !error[0]) + { + result = number; + break; + } + } + } + weechat_string_free_split (argv); + } + } + + return result; +} + +/* + * relay_client_irc_signal_irc_outtags_cb: callback for "irc_out" signal + * It is called when a message is sent + * to IRC server (by irc plugin or any + * other plugin/script). + */ + +int +relay_client_irc_signal_irc_outtags_cb (void *data, const char *signal, + const char *type_data, + void *signal_data) +{ + struct t_relay_client *client; + struct t_hashtable *hash_parsed; + const char *irc_command, *irc_args, *host, *ptr_message; + char *pos, *tags, *irc_channel, *message; + struct t_infolist *infolist_nick; + char str_infolist_args[256]; + + /* make C compiler happy */ + (void) signal; + (void) type_data; + + client = (struct t_relay_client *)data; + + message = strdup ((char *)signal_data); + if (!message) + goto end; + pos = strchr (message, '\r'); + if (pos) + pos[0] = '\0'; + + if (weechat_relay_plugin->debug >= 2) + { + weechat_printf (NULL, "%s: irc_out: client: %s, message: %s", + RELAY_PLUGIN_NAME, + client->protocol_string, + message); + } + + tags = NULL; + ptr_message = message; + + pos = strchr (ptr_message, ';'); + if (pos) + { + if (pos > ptr_message + 1) + tags = weechat_strndup (ptr_message, pos - ptr_message); + ptr_message = pos + 1; + } + + /* + * We check if there is a tag "relay_client_NNN" and if NNN (numeric) + * is equal to current client, then we ignore message, because message + * was sent from this same client! + * This is to prevent message from being displayed twice on client. + */ + if (relay_client_irc_tag_relay_client_id (tags) == client->id) + goto end; + + hash_parsed = relay_client_irc_parse_message (ptr_message); + if (hash_parsed) + { + irc_command = weechat_hashtable_get (hash_parsed, "command"); + irc_args = weechat_hashtable_get (hash_parsed, "arguments"); + + pos = strchr (irc_args, ' '); + irc_channel = (pos) ? + weechat_strndup (irc_args, pos - irc_args) : strdup (irc_args); + + /* if command has to be relayed, relay it to client */ + if (irc_command && irc_command[0] + && irc_channel && irc_channel[0] + && relay_client_irc_command_relayed (irc_command)) + { + /* get host for nick (it is self nick) */ + snprintf (str_infolist_args, sizeof (str_infolist_args) - 1, + "%s,%s,%s", + client->protocol_string, + irc_channel, + RELAY_IRC_DATA(client, nick)); + + host = NULL; + infolist_nick = weechat_infolist_get ("irc_nick", NULL, str_infolist_args); + if (infolist_nick && weechat_infolist_next (infolist_nick)) + host = weechat_infolist_string (infolist_nick, "host"); + + /* send message to client */ + relay_client_irc_sendf (client, + ":%s%s%s %s", + RELAY_IRC_DATA(client, nick), + (host && host[0]) ? "!" : "", + (host && host[0]) ? host : "", + ptr_message); + + if (infolist_nick) + weechat_infolist_free (infolist_nick); + } + if (irc_channel) + free (irc_channel); + weechat_hashtable_free (hash_parsed); + } + +end: + if (message) + free (message); + if (tags) + free (tags); + + return WEECHAT_RC_OK; +} + +/* + * relay_client_irc_signal_irc_disc_cb: callback for "irc_disconnected" signal + * It is called when connection to a + * server is lost. + */ + +int +relay_client_irc_signal_irc_disc_cb (void *data, const char *signal, + const char *type_data, void *signal_data) +{ + struct t_relay_client *client; + + /* make C compiler happy */ + (void) signal; + (void) type_data; + (void) signal_data; + + client = (struct t_relay_client *)data; + + if (strcmp ((char *)signal_data, client->protocol_string) == 0) + { + relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_client_irc_send_join: send join for a channel to client + */ + +void +relay_client_irc_send_join (struct t_relay_client *client, + const char *channel) +{ + char *infolist_name, *nicks; + const char *nick, *prefix; + char *host; + int length, length_nicks; + struct t_infolist *infolist_nick, *infolist_nicks; + + length = strlen (client->protocol_string) + 1 + strlen (channel) + 1 + + strlen (RELAY_IRC_DATA(client, nick)) + 1; + infolist_name = malloc (length); + if (infolist_name) + { + /* get nick host */ + host = NULL; + snprintf (infolist_name, length, "%s,%s,%s", + client->protocol_string, + channel, + RELAY_IRC_DATA(client, nick)); + infolist_nick = weechat_infolist_get ("irc_nick", NULL, infolist_name); + if (infolist_nick) + { + if (weechat_infolist_next (infolist_nick)) + { + host = (char *)weechat_infolist_string (infolist_nick, "host"); + if (host) + host = strdup (host); + } + weechat_infolist_free (infolist_nick); + } + relay_client_irc_sendf (client, + ":%s!%s JOIN %s", + RELAY_IRC_DATA(client, nick), + (host && host[0]) ? host : "weechat@proxy", + channel); + if (host) + free (host); + snprintf (infolist_name, length, "%s,%s", + client->protocol_string, + channel); + infolist_nicks = weechat_infolist_get ("irc_nick", NULL, infolist_name); + if (infolist_nicks) + { + length_nicks = 0; + nicks = NULL; + while (weechat_infolist_next (infolist_nicks)) + { + nick = weechat_infolist_string (infolist_nicks, "name"); + prefix = weechat_infolist_string (infolist_nicks, "prefix"); + if (nick && nick[0]) + { + length_nicks += strlen (nick) + 1 + 1; + if (nicks) + { + nicks = realloc (nicks, length_nicks); + strcat (nicks, " "); + } + else + { + nicks = malloc (length_nicks); + nicks[0] = '\0'; + } + if (prefix && (prefix[0] != ' ')) + strcat (nicks, prefix); + strcat (nicks, nick); + } + } + if (nicks) + { + relay_client_irc_sendf (client, + ":%s 353 %s = %s :%s", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + channel, nicks); + free (nicks); + } + weechat_infolist_free (infolist_nicks); + } + relay_client_irc_sendf (client, + ":%s 366 %s %s :End of /NAMES list.", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + channel); + free (infolist_name); + } +} + +/* + * relay_client_irc_send_join_channels: send join for all channels of server to + * client + */ + +void +relay_client_irc_send_join_channels (struct t_relay_client *client) +{ + struct t_infolist *infolist_channels; + const char *channel; + + infolist_channels = weechat_infolist_get ("irc_channel", NULL, + client->protocol_string); + if (infolist_channels) + { + while (weechat_infolist_next (infolist_channels)) + { + channel = weechat_infolist_string (infolist_channels, "name"); + relay_client_irc_send_join (client, channel); + } + weechat_infolist_free (infolist_channels); + } +} + +/* + * relay_client_irc_input_send: send text or command on an IRC buffer + */ + +void +relay_client_irc_input_send (struct t_relay_client *client, + const char *irc_channel, + int flags, + const char *format, ...) +{ + va_list args; + static char buffer[4096]; + int length; + + snprintf (buffer, sizeof (buffer), + "%s;%s;%d;relay_client_%d;", + client->protocol_string, + (irc_channel) ? irc_channel : "", + flags, + client->id); + + length = strlen (buffer); + + va_start (args, format); + vsnprintf (buffer + length, sizeof (buffer) - 1 - length, format, args); + va_end (args); + + if (weechat_relay_plugin->debug >= 2) + { + weechat_printf (NULL, + "%s: irc_input_send: \"%s\"", + RELAY_PLUGIN_NAME, buffer); + } + + weechat_hook_signal_send ("irc_input_send", + WEECHAT_HOOK_SIGNAL_STRING, + buffer); +} + +/* + * relay_client_irc_recv_one_msg: read one message from client + */ + +void +relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) +{ + char *pos, str_time[128], str_signal_name[128], *target; + const char *irc_command, *irc_channel, *irc_args, *irc_args2; + const char *nick, *irc_is_channel, *isupport; + struct t_hashtable *hash_parsed; + struct t_infolist *infolist_server; + + hash_parsed = NULL; + + /* remove \r at the end of message */ + pos = strchr (data, '\r'); + if (pos) + pos[0] = '\0'; + + /* display debug message */ + if (weechat_relay_plugin->debug >= 2) + { + weechat_printf (NULL, "%s: recv from client: \"%s\"", + RELAY_PLUGIN_NAME, data); + } + + relay_raw_print (client, 0, data); + + /* parse IRC message */ + hash_parsed = relay_client_irc_parse_message (data); + if (!hash_parsed) + goto end; + irc_command = weechat_hashtable_get (hash_parsed, "command"); + irc_channel = weechat_hashtable_get (hash_parsed, "channel"); + irc_args = weechat_hashtable_get (hash_parsed, "arguments"); + + /* process the message */ + if (irc_command && (weechat_strcasecmp (irc_command, "nick") == 0)) + { + if (irc_args && irc_args[0]) + { + if (RELAY_IRC_DATA(client, nick)) + free (RELAY_IRC_DATA(client, nick)); + RELAY_IRC_DATA(client, nick) = strdup (irc_args); + } + } + if (!RELAY_IRC_DATA(client, connected)) + { + if (irc_command && (weechat_strcasecmp (irc_command, "user") == 0)) + { + /* check if connection to server is ok */ + infolist_server = weechat_infolist_get ("irc_server", NULL, + client->protocol_string); + if (infolist_server) + { + if (weechat_infolist_next (infolist_server)) + { + if (!weechat_infolist_integer (infolist_server, + "is_connected")) + { + relay_client_irc_sendf (client, + ":%s ERROR :WeeChat: no " + "connection to server \"%s\"", + RELAY_IRC_DATA(client, address), + client->protocol_string); + relay_client_irc_sendf (client, + ":%s ERROR :Closing Link", + RELAY_IRC_DATA(client, address)); + relay_client_set_status (client, + RELAY_STATUS_DISCONNECTED); + return; + } + if (irc_args && irc_args[0]) + { + RELAY_IRC_DATA(client, user_received) = 1; + } + } + weechat_infolist_free (infolist_server); + } + } + if (RELAY_IRC_DATA(client, nick) && RELAY_IRC_DATA(client, user_received)) + { + RELAY_IRC_DATA(client, connected) = 1; + + /* + * send nick to client if server nick is different of nick asked + * by client with command NICK + */ + nick = weechat_info_get ("irc_nick", client->protocol_string); + if (nick && (strcmp (nick, RELAY_IRC_DATA(client, nick)) != 0)) + { + relay_client_irc_sendf (client, + ":%s!proxy NICK :%s", + RELAY_IRC_DATA(client, nick), + nick); + free (RELAY_IRC_DATA(client, nick)); + RELAY_IRC_DATA(client, nick) = strdup (nick); + } + + relay_client_irc_sendf (client, + ":%s 001 %s :Welcome to the Internet " + "Relay Chat Network %s!%s@proxy", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + RELAY_IRC_DATA(client, nick), + "weechat"); + relay_client_irc_sendf (client, + ":%s 002 %s :Your host is " + "weechat-relay-irc, running version %s", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + weechat_info_get("version", NULL)); + snprintf (str_time, sizeof (str_time), "%s", + ctime (&client->listen_start_time)); + if (str_time[0]) + str_time[strlen (str_time) - 1] = '\0'; + relay_client_irc_sendf (client, + ":%s 003 %s :This server was created on %s", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + str_time); + relay_client_irc_sendf (client, + ":%s 004 %s %s %s oirw abiklmnopqstv", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + RELAY_IRC_DATA(client, address), + weechat_info_get("version", NULL)); + infolist_server = weechat_infolist_get ("irc_server", NULL, + client->protocol_string); + if (infolist_server) + { + if (weechat_infolist_next (infolist_server)) + { + isupport = weechat_infolist_string (infolist_server, + "isupport"); + if (isupport && isupport[0]) + { + while (isupport[0] == ' ') + { + isupport++; + } + /* TODO: split this message into many messages */ + relay_client_irc_sendf (client, + ":%s 005 %s %s :are supported " + "by this server", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + isupport); + } + } + weechat_infolist_free (infolist_server); + } + relay_client_irc_sendf (client, + ":%s 251 %s :There are %d users and 0 " + "invisible on 1 servers", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + relay_client_count); + relay_client_irc_sendf (client, + ":%s 255 %s :I have %d clients, 0 " + "services and 0 servers", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + relay_client_count); + relay_client_irc_sendf (client, + ":%s 422 %s :MOTD File is missing", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick)); + + /* + * hook signal "xxx,irc_in2_*" to catch IRC data received from + * this server + */ + snprintf (str_signal_name, sizeof (str_signal_name), + "%s,irc_in2_*", + client->protocol_string); + RELAY_IRC_DATA(client, hook_signal_irc_in2) = + weechat_hook_signal (str_signal_name, + &relay_client_irc_signal_irc_in2_cb, + client); + + /* + * hook signal "xxx,irc_outtags_*" to catch IRC data sent to + * this server + */ + snprintf (str_signal_name, sizeof (str_signal_name), + "%s,irc_outtags_*", + client->protocol_string); + RELAY_IRC_DATA(client, hook_signal_irc_outtags) = + weechat_hook_signal (str_signal_name, + &relay_client_irc_signal_irc_outtags_cb, + client); + + /* + * hook signal "irc_server_disconnected" to disconnect client if + * connection to server is lost + */ + RELAY_IRC_DATA(client, hook_signal_irc_disc) = + weechat_hook_signal ("irc_server_disconnected", + &relay_client_irc_signal_irc_disc_cb, + client); + + /* send JOIN for all channels on server to client */ + relay_client_irc_send_join_channels (client); + } + } + else + { + if (irc_command && weechat_strcasecmp (irc_command, "ping") == 0) + { + relay_client_irc_sendf (client, + ":%s PONG %s :%s", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, address), + irc_args); + } + else if (irc_command && irc_channel && irc_channel[0] + && irc_args && irc_args[0] + && (weechat_strcasecmp (irc_command, "notice") == 0)) + { + irc_args2 = strchr (irc_args, ' '); + if (irc_args2) + { + target = weechat_strndup (irc_args, irc_args2 - irc_args); + if (target) + { + while (irc_args2[0] == ' ') + { + irc_args2++; + } + if (irc_args2[0] == ':') + irc_args2++; + relay_client_irc_input_send (client, NULL, 1, + "/notice %s %s", + target, + irc_args2); + free (target); + } + } + } + else if (irc_command && irc_channel && irc_channel[0] + && irc_args && irc_args[0] + && (weechat_strcasecmp (irc_command, "privmsg") == 0)) + { + irc_args2 = strchr (irc_args, ' '); + if (!irc_args2) + irc_args2 = irc_args; + while (irc_args2[0] == ' ') + { + irc_args2++; + } + if (irc_args2[0] == ':') + irc_args2++; + irc_is_channel = weechat_info_get ("irc_is_channel", irc_channel); + if (irc_is_channel && (strcmp (irc_is_channel, "1") == 0)) + { + relay_client_irc_input_send (client, irc_channel, 1, + "%s", irc_args2); + } + else + { + relay_client_irc_input_send (client, NULL, 1, + "/query %s %s", + irc_channel, irc_args2); + } + } + else if (!relay_client_irc_command_ignored (irc_command)) + { + relay_client_irc_input_send (client, NULL, 1, + "/quote %s", + data); + } + } + +end: + if (hash_parsed) + weechat_hashtable_free (hash_parsed); +} + +/* + * relay_client_irc_recv: read data from client + */ + +void +relay_client_irc_recv (struct t_relay_client *client, const char *data) +{ + char **items; + int items_count, i; + + items = weechat_string_split (data, "\n", 0, 0, &items_count); + for (i = 0; i < items_count; i++) + { + relay_client_irc_recv_one_msg (client, items[i]); + } + if (items) + weechat_string_free_split (items); +} + +/* + * relay_client_irc_close_connection: called when connection with client is + * closed + */ + +void +relay_client_irc_close_connection (struct t_relay_client *client) +{ + RELAY_IRC_DATA(client, connected) = 0; + if (RELAY_IRC_DATA(client, hook_signal_irc_in2)) + { + weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_in2)); + RELAY_IRC_DATA(client, hook_signal_irc_in2) = NULL; + } + if (RELAY_IRC_DATA(client, hook_signal_irc_outtags)) + { + weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_outtags)); + RELAY_IRC_DATA(client, hook_signal_irc_outtags) = NULL; + } + if (RELAY_IRC_DATA(client, hook_signal_irc_disc)) + { + weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_disc)); + RELAY_IRC_DATA(client, hook_signal_irc_disc) = NULL; + } +} + +/* + * relay_client_irc_alloc: init relay data specific to IRC protocol + */ + +void +relay_client_irc_alloc (struct t_relay_client *client) +{ + struct t_relay_client_irc_data *irc_data; + + client->protocol_data = malloc (sizeof (*irc_data)); + if (client->protocol_data) + { + RELAY_IRC_DATA(client, address) = strdup ("weechat.relay.irc"); + RELAY_IRC_DATA(client, nick) = NULL; + RELAY_IRC_DATA(client, user_received) = 0; + RELAY_IRC_DATA(client, connected) = 0; + RELAY_IRC_DATA(client, hook_signal_irc_in2) = NULL; + RELAY_IRC_DATA(client, hook_signal_irc_outtags) = NULL; + RELAY_IRC_DATA(client, hook_signal_irc_disc) = NULL; + } +} + +/* + * relay_client_irc_free: free relay data specific to IRC protocol + */ + +void +relay_client_irc_free (struct t_relay_client *client) +{ + if (client->protocol_data) + { + if (RELAY_IRC_DATA(client, address)) + free (RELAY_IRC_DATA(client, address)); + if (RELAY_IRC_DATA(client, nick)) + free (RELAY_IRC_DATA(client, nick)); + if (RELAY_IRC_DATA(client, hook_signal_irc_in2)) + weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_in2)); + if (RELAY_IRC_DATA(client, hook_signal_irc_outtags)) + weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_outtags)); + if (RELAY_IRC_DATA(client, hook_signal_irc_disc)) + weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_disc)); + + free (client->protocol_data); + + client->protocol_data = NULL; + } +} + +/* + * relay_client_irc_print_log: print IRC client infos in log (usually for + * crash dump) + */ + +void +relay_client_irc_print_log (struct t_relay_client *client) +{ + if (client->protocol_data) + { + weechat_log_printf (" address. . . . . . . . : '%s'", RELAY_IRC_DATA(client, address)); + weechat_log_printf (" nick . . . . . . . . . : '%s'", RELAY_IRC_DATA(client, nick)); + weechat_log_printf (" user_received. . . . . : %d", RELAY_IRC_DATA(client, user_received)); + weechat_log_printf (" connected. . . . . . . : %d", RELAY_IRC_DATA(client, connected)); + weechat_log_printf (" hook_signal_irc_in2. . : 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_in2)); + weechat_log_printf (" hook_signal_irc_outtags: 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_outtags)); + weechat_log_printf (" hook_signal_irc_disc . : 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_disc)); + } +} diff --git a/src/plugins/relay/relay-protocol-irc.h b/src/plugins/relay/relay-client-irc.h index f92a2b503..b74c57670 100644 --- a/src/plugins/relay/relay-protocol-irc.h +++ b/src/plugins/relay/relay-client-irc.h @@ -17,15 +17,15 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __WEECHAT_RELAY_PROTOCOL_IRC_H -#define __WEECHAT_RELAY_PROTOCOL_IRC_H 1 +#ifndef __WEECHAT_RELAY_CLIENT_IRC_H +#define __WEECHAT_RELAY_CLIENT_IRC_H 1 struct t_relay_client; #define RELAY_IRC_DATA(client, var) \ - (((struct t_relay_protocol_irc_data *)client->protocol_data)->var) + (((struct t_relay_client_irc_data *)client->protocol_data)->var) -struct t_relay_protocol_irc_data +struct t_relay_client_irc_data { char *address; /* client address (used when sending */ /* data to client) */ @@ -33,14 +33,16 @@ struct t_relay_protocol_irc_data int user_received; /* command "USER" received */ int connected; /* 1 if client is connected as IRC */ /* client */ - struct t_hook *hook_signal_irc_in2;/* hook signal "irc_in2" */ - struct t_hook *hook_signal_irc_out;/* hook signal "irc_out" */ + struct t_hook *hook_signal_irc_in2; /* signal "irc_in2" */ + struct t_hook *hook_signal_irc_outtags; /* signal "irc_outtags" */ + struct t_hook *hook_signal_irc_disc; /* signal "irc_disconnected" */ }; -extern void relay_protocol_irc_recv (struct t_relay_client *client, - const char *data); -extern void relay_protocol_irc_alloc (struct t_relay_client *client); -extern void relay_protocol_irc_free (struct t_relay_client *client); -extern void relay_protocol_irc_print_log (struct t_relay_client *client); +extern void relay_client_irc_recv (struct t_relay_client *client, + const char *data); +extern void relay_client_irc_close_connection (struct t_relay_client *client); +extern void relay_client_irc_alloc (struct t_relay_client *client); +extern void relay_client_irc_free (struct t_relay_client *client); +extern void relay_client_irc_print_log (struct t_relay_client *client); -#endif /* __WEECHAT_RELAY_PROTOCOL_IRC_H */ +#endif /* __WEECHAT_RELAY_CLIENT_IRC_H */ diff --git a/src/plugins/relay/relay-protocol-weechat.c b/src/plugins/relay/relay-client-weechat.c index d731fa919..7b9e31351 100644 --- a/src/plugins/relay/relay-protocol-weechat.c +++ b/src/plugins/relay/relay-client-weechat.c @@ -18,7 +18,7 @@ */ /* - * relay-protocol-weechat.c: WeeChat protocol for relay to client + * relay-client-weechat.c: WeeChat protocol for relay to client */ #include <stdlib.h> @@ -31,17 +31,17 @@ #include "../weechat-plugin.h" #include "relay.h" -#include "relay-protocol-weechat.h" +#include "relay-client-weechat.h" #include "relay-client.h" /* - * relay_protocol_weechat_sendf: send formatted data to client + * relay_client_weechat_sendf: send formatted data to client */ int -relay_protocol_weechat_sendf (struct t_relay_client *client, - const char *format, ...) +relay_client_weechat_sendf (struct t_relay_client *client, + const char *format, ...) { va_list args; static char buffer[4096]; @@ -75,19 +75,19 @@ relay_protocol_weechat_sendf (struct t_relay_client *client, } /* - * relay_protocol_weechat_send_infolist: send infolist to client + * relay_client_weechat_send_infolist: send infolist to client */ void -relay_protocol_weechat_send_infolist (struct t_relay_client *client, - const char *name, - struct t_infolist *infolist) +relay_client_weechat_send_infolist (struct t_relay_client *client, + const char *name, + struct t_infolist *infolist) { const char *fields; char **argv; int i, argc, size; - relay_protocol_weechat_sendf (client, "name %s", name); + relay_client_weechat_sendf (client, "name %s", name); while (weechat_infolist_next (infolist)) { @@ -102,34 +102,34 @@ relay_protocol_weechat_send_infolist (struct t_relay_client *client, switch (argv[i][0]) { case 'i': - relay_protocol_weechat_sendf (client, "%s %c %d", - argv[i] + 2, argv[i][0], - weechat_infolist_integer (infolist, - argv[i] + 2)); + relay_client_weechat_sendf (client, "%s %c %d", + argv[i] + 2, argv[i][0], + weechat_infolist_integer (infolist, + argv[i] + 2)); break; case 's': - relay_protocol_weechat_sendf (client, "%s %c %s", - argv[i] + 2, argv[i][0], - weechat_infolist_string (infolist, - argv[i] + 2)); + relay_client_weechat_sendf (client, "%s %c %s", + argv[i] + 2, argv[i][0], + weechat_infolist_string (infolist, + argv[i] + 2)); break; case 'p': - relay_protocol_weechat_sendf (client, "%s %c %lx", - argv[i] + 2, argv[i][0], - (long unsigned int)weechat_infolist_pointer (infolist, - argv[i] + 2)); + relay_client_weechat_sendf (client, "%s %c %lx", + argv[i] + 2, argv[i][0], + (long unsigned int)weechat_infolist_pointer (infolist, + argv[i] + 2)); break; case 'b': - relay_protocol_weechat_sendf (client, "%s %c %lx", - argv[i] + 2, argv[i][0], - (long unsigned int)weechat_infolist_buffer (infolist, - argv[i] + 2, + relay_client_weechat_sendf (client, "%s %c %lx", + argv[i] + 2, argv[i][0], + (long unsigned int)weechat_infolist_buffer (infolist, + argv[i] + 2, &size)); break; case 't': - relay_protocol_weechat_sendf (client, "%s %c %ld", - argv[i] + 2, argv[i][0], - weechat_infolist_time (infolist, argv[i] + 2)); + relay_client_weechat_sendf (client, "%s %c %ld", + argv[i] + 2, argv[i][0], + weechat_infolist_time (infolist, argv[i] + 2)); break; } } @@ -141,11 +141,11 @@ relay_protocol_weechat_send_infolist (struct t_relay_client *client, } /* - * relay_protocol_weechat_recv_one_msg: read one message from client + * relay_client_weechat_recv_one_msg: read one message from client */ void -relay_protocol_weechat_recv_one_msg (struct t_relay_client *client, char *data) +relay_client_weechat_recv_one_msg (struct t_relay_client *client, char *data) { char *pos; struct t_infolist *infolist; @@ -166,18 +166,18 @@ relay_protocol_weechat_recv_one_msg (struct t_relay_client *client, char *data) infolist = weechat_infolist_get (data, NULL, NULL); if (infolist) { - relay_protocol_weechat_send_infolist (client, data, infolist); + relay_client_weechat_send_infolist (client, data, infolist); weechat_infolist_free (infolist); } } } /* - * relay_protocol_weechat_recv: read data from client + * relay_client_weechat_recv: read data from client */ void -relay_protocol_weechat_recv (struct t_relay_client *client, const char *data) +relay_client_weechat_recv (struct t_relay_client *client, const char *data) { char **items; int items_count, i; @@ -185,20 +185,20 @@ relay_protocol_weechat_recv (struct t_relay_client *client, const char *data) items = weechat_string_split (data, "\n", 0, 0, &items_count); for (i = 0; i < items_count; i++) { - relay_protocol_weechat_recv_one_msg (client, items[i]); + relay_client_weechat_recv_one_msg (client, items[i]); } if (items) weechat_string_free_split (items); } /* - * relay_protocol_weechat_alloc: init relay data specific to weechat protocol + * relay_client_weechat_alloc: init relay data specific to weechat protocol */ void -relay_protocol_weechat_alloc (struct t_relay_client *client) +relay_client_weechat_alloc (struct t_relay_client *client) { - struct t_relay_protocol_weechat_data *weechat_data; + struct t_relay_client_weechat_data *weechat_data; client->protocol_data = malloc (sizeof (*weechat_data)); if (client->protocol_data) @@ -208,23 +208,23 @@ relay_protocol_weechat_alloc (struct t_relay_client *client) } /* - * relay_protocol_weechat_free: free relay data specific to weechat protocol + * relay_client_weechat_free: free relay data specific to weechat protocol */ void -relay_protocol_weechat_free (struct t_relay_client *client) +relay_client_weechat_free (struct t_relay_client *client) { if (client->protocol_data) free (client->protocol_data); } /* - * relay_protocol_weechat_print_log: print weechat client infos in log (usually - * for crash dump) + * relay_client_weechat_print_log: print weechat client infos in log (usually + * for crash dump) */ void -relay_protocol_weechat_print_log (struct t_relay_client *client) +relay_client_weechat_print_log (struct t_relay_client *client) { if (client->protocol_data) { diff --git a/src/plugins/relay/relay-protocol-weechat.h b/src/plugins/relay/relay-client-weechat.h index 8466868d9..32172235f 100644 --- a/src/plugins/relay/relay-protocol-weechat.h +++ b/src/plugins/relay/relay-client-weechat.h @@ -17,15 +17,15 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __WEECHAT_RELAY_PROTOCOL_WEECHAT_H -#define __WEECHAT_RELAY_PROTOCOL_WEECHAT_H 1 +#ifndef __WEECHAT_RELAY_CLIENT_WEECHAT_H +#define __WEECHAT_RELAY_CLIENT_WEECHAT_H 1 struct t_relay_client; #define RELAY_WEECHAT_DATA(client, var) \ - (((struct t_relay_protocol_weechat_data *)client->protocol_data)->var) + (((struct t_relay_client_weechat_data *)client->protocol_data)->var) -struct t_relay_protocol_weechat_data +struct t_relay_client_weechat_data { char *address; /* client address (used when sending */ /* data to client) */ @@ -35,10 +35,10 @@ struct t_relay_protocol_weechat_data /* client */ }; -extern void relay_protocol_weechat_recv (struct t_relay_client *client, - const char *data); -extern void relay_protocol_weechat_alloc (struct t_relay_client *client); -extern void relay_protocol_weechat_free (struct t_relay_client *client); -extern void relay_protocol_weechat_print_log (struct t_relay_client *client); +extern void relay_client_weechat_recv (struct t_relay_client *client, + const char *data); +extern void relay_client_weechat_alloc (struct t_relay_client *client); +extern void relay_client_weechat_free (struct t_relay_client *client); +extern void relay_client_weechat_print_log (struct t_relay_client *client); -#endif /* __WEECHAT_RELAY_PROTOCOL_WEECHAT_H */ +#endif /* __WEECHAT_RELAY_CLIENT_WEECHAT_H */ diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c index 5d018206c..1dec067af 100644 --- a/src/plugins/relay/relay-client.c +++ b/src/plugins/relay/relay-client.c @@ -34,10 +34,10 @@ #include "../weechat-plugin.h" #include "relay.h" #include "relay-client.h" +#include "relay-client-irc.h" +#include "relay-client-weechat.h" #include "relay-config.h" #include "relay-buffer.h" -#include "relay-protocol-irc.h" -#include "relay-protocol-weechat.h" #include "relay-server.h" @@ -123,10 +123,10 @@ relay_client_recv_cb (void *arg_client, int fd) switch (client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_protocol_weechat_recv (client, buffer); + relay_client_weechat_recv (client, buffer); break; case RELAY_PROTOCOL_IRC: - relay_protocol_irc_recv (client, buffer); + relay_client_irc_recv (client, buffer); break; case RELAY_NUM_PROTOCOLS: break; @@ -153,6 +153,7 @@ relay_client_new (int sock, char *address, struct t_relay_server *server) new_client = malloc (sizeof (*new_client)); if (new_client) { + new_client->id = (relay_clients) ? relay_clients->id + 1 : 1; new_client->sock = sock; new_client->address = strdup ((address) ? address : "?"); new_client->status = RELAY_STATUS_CONNECTED; @@ -171,10 +172,10 @@ relay_client_new (int sock, char *address, struct t_relay_server *server) switch (new_client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_protocol_weechat_alloc (new_client); + relay_client_weechat_alloc (new_client); break; case RELAY_PROTOCOL_IRC: - relay_protocol_irc_alloc (new_client); + relay_client_irc_alloc (new_client); break; case RELAY_NUM_PROTOCOLS: break; @@ -189,12 +190,13 @@ relay_client_new (int sock, char *address, struct t_relay_server *server) relay_clients = new_client; weechat_printf (NULL, - _("%s: new client from %s%s%s on port %d (relaying: %s.%s)"), + _("%s: new client from %s%s%s on port %d (id: %d, relaying: %s.%s)"), RELAY_PLUGIN_NAME, RELAY_COLOR_CHAT_HOST, new_client->address, RELAY_COLOR_CHAT, server->port, + new_client->id, relay_protocol_string[new_client->protocol], new_client->protocol_string); @@ -247,6 +249,16 @@ relay_client_set_status (struct t_relay_client *client, weechat_unhook (client->hook_timer); client->hook_timer = NULL; } + switch (client->protocol) + { + case RELAY_PROTOCOL_WEECHAT: + break; + case RELAY_PROTOCOL_IRC: + relay_client_irc_close_connection (client); + break; + case RELAY_NUM_PROTOCOLS: + break; + } switch (client->status) { case RELAY_STATUS_AUTH_FAILED: @@ -323,10 +335,10 @@ relay_client_free (struct t_relay_client *client) switch (client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_protocol_weechat_free (client); + relay_client_weechat_free (client); break; case RELAY_PROTOCOL_IRC: - relay_protocol_irc_free (client); + relay_client_irc_free (client); break; case RELAY_NUM_PROTOCOLS: break; @@ -446,36 +458,37 @@ relay_client_print_log () { weechat_log_printf (""); weechat_log_printf ("[relay client (addr:0x%lx)]", ptr_client); - weechat_log_printf (" sock. . . . . . . . : %d", ptr_client->sock); - weechat_log_printf (" address . . . . . . : '%s'", ptr_client->address); - weechat_log_printf (" status. . . . . . . : %d (%s)", + weechat_log_printf (" id. . . . . . . . . . : %d", ptr_client->id); + weechat_log_printf (" sock. . . . . . . . . : %d", ptr_client->sock); + weechat_log_printf (" address . . . . . . . : '%s'", ptr_client->address); + weechat_log_printf (" status. . . . . . . . : %d (%s)", ptr_client->status, relay_client_status_string[ptr_client->status]); - weechat_log_printf (" protocol. . . . . . : %d (%s)", + weechat_log_printf (" protocol. . . . . . . : %d (%s)", ptr_client->protocol, relay_protocol_string[ptr_client->protocol]); - weechat_log_printf (" protocol_string . . : '%s'", ptr_client->protocol_string); - weechat_log_printf (" listen_start_time . : %ld", ptr_client->listen_start_time); - weechat_log_printf (" start_time. . . . . : %ld", ptr_client->start_time); - weechat_log_printf (" end_time. . . . . . : %ld", ptr_client->end_time); - weechat_log_printf (" hook_fd . . . . . . : 0x%lx", ptr_client->hook_fd); - weechat_log_printf (" hook_timer. . . . . : 0x%lx", ptr_client->hook_timer); - weechat_log_printf (" last_activity . . . : %ld", ptr_client->last_activity); - weechat_log_printf (" bytes_recv. . . . . : %lu", ptr_client->bytes_recv); - weechat_log_printf (" bytes_sent. . . . . : %lu", ptr_client->bytes_sent); - weechat_log_printf (" protocol_data . . . : 0x%lx", ptr_client->protocol_data); + weechat_log_printf (" protocol_string . . . : '%s'", ptr_client->protocol_string); + weechat_log_printf (" listen_start_time . . : %ld", ptr_client->listen_start_time); + weechat_log_printf (" start_time. . . . . . : %ld", ptr_client->start_time); + weechat_log_printf (" end_time. . . . . . . : %ld", ptr_client->end_time); + weechat_log_printf (" hook_fd . . . . . . . : 0x%lx", ptr_client->hook_fd); + weechat_log_printf (" hook_timer. . . . . . : 0x%lx", ptr_client->hook_timer); + weechat_log_printf (" last_activity . . . . : %ld", ptr_client->last_activity); + weechat_log_printf (" bytes_recv. . . . . . : %lu", ptr_client->bytes_recv); + weechat_log_printf (" bytes_sent. . . . . . : %lu", ptr_client->bytes_sent); + weechat_log_printf (" protocol_data . . . . : 0x%lx", ptr_client->protocol_data); switch (ptr_client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_protocol_weechat_print_log (ptr_client); + relay_client_weechat_print_log (ptr_client); break; case RELAY_PROTOCOL_IRC: - relay_protocol_irc_print_log (ptr_client); + relay_client_irc_print_log (ptr_client); break; case RELAY_NUM_PROTOCOLS: break; } - weechat_log_printf (" prev_client . . . . : 0x%lx", ptr_client->prev_client); - weechat_log_printf (" next_client . . . . : 0x%lx", ptr_client->next_client); + weechat_log_printf (" prev_client . . . . . : 0x%lx", ptr_client->prev_client); + weechat_log_printf (" next_client . . . . . : 0x%lx", ptr_client->next_client); } } diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h index fa0b5818a..9e1eec957 100644 --- a/src/plugins/relay/relay-client.h +++ b/src/plugins/relay/relay-client.h @@ -44,6 +44,7 @@ enum t_relay_status struct t_relay_client { + int id; /* unique id (diff. for each client) */ int sock; /* socket for connection */ char *address; /* string with IP address */ enum t_relay_status status; /* status (connecting, active,..) */ diff --git a/src/plugins/relay/relay-command.c b/src/plugins/relay/relay-command.c index 008274edc..33b315bf3 100644 --- a/src/plugins/relay/relay-command.c +++ b/src/plugins/relay/relay-command.c @@ -30,6 +30,7 @@ #include "relay-buffer.h" #include "relay-client.h" #include "relay-config.h" +#include "relay-raw.h" #include "relay-server.h" @@ -64,9 +65,10 @@ relay_command_client_list (int full) if (full) { weechat_printf (NULL, - _("%3d. %s%s%s (%s%s%s), started on: %s, last " - "activity: %s, bytes: %lu recv, %lu sent"), - i, + _(" id: %d, %s%s%s (%s%s%s), " + "started on: %s, last activity: %s, " + "bytes: %lu recv, %lu sent"), + ptr_client->id, RELAY_COLOR_CHAT_HOST, ptr_client->address, RELAY_COLOR_CHAT, @@ -83,8 +85,8 @@ relay_command_client_list (int full) if (!RELAY_CLIENT_HAS_ENDED(ptr_client->status)) { weechat_printf (NULL, - _("%3d. %s%s%s, started on: %s"), - i, + _(" id: %d, %s%s%s, started on: %s"), + ptr_client->id, RELAY_COLOR_CHAT_HOST, ptr_client->address, RELAY_COLOR_CHAT, @@ -124,8 +126,7 @@ relay_command_server_list () "%a, %d %b %Y %H:%M:%S", date_tmp); weechat_printf (NULL, - _("%3d. port %s%d%s, relay: %s%s.%s%s, started on: %s"), - i, + _(" port %s%d%s, relay: %s%s.%s%s, started on: %s"), RELAY_COLOR_CHAT_BUFFER, ptr_server->port, RELAY_COLOR_CHAT, @@ -223,6 +224,11 @@ relay_command_relay (void *data, struct t_gui_buffer *buffer, int argc, } return WEECHAT_RC_OK; } + if (weechat_strcasecmp (argv[1], "raw") == 0) + { + relay_raw_open (1); + return WEECHAT_RC_OK; + } } if (!relay_buffer) @@ -262,7 +268,7 @@ relay_command_init () weechat_hook_command ("relay", N_("relay control"), N_("[list | listfull | add protocol.name port | " - "del protocol.name]"), + "del protocol.name | raw]"), N_(" list: list relay clients (only active " "relays)\n" " listfull: list relay clients (verbose, all " @@ -272,13 +278,15 @@ relay_command_init () " del: remove relay for a protocol + name\n" "protocol.name: protocol and name to relay\n" " for example: irc.freenode\n" - " port: port used for relay\n\n" + " port: port used for relay\n" + " raw: open buffer with raw Relay data\n\n" "Without argument, this command opens buffer " "with list of relay clients."), "list %(relay_relays)" " || listfull %(relay_relays)" " || listrelay" " || add %(relay_protocol_name) %(relay_free_port)" - " || del %(relay_relays)", + " || del %(relay_relays)" + " || raw", &relay_command_relay, NULL); } diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c index d5b3f940d..1e99113ee 100644 --- a/src/plugins/relay/relay-config.c +++ b/src/plugins/relay/relay-config.c @@ -38,6 +38,7 @@ struct t_config_section *relay_config_section_port = NULL; /* relay config, look section */ struct t_config_option *relay_config_look_auto_open_buffer; +struct t_config_option *relay_config_look_raw_messages; /* relay config, color section */ @@ -257,6 +258,12 @@ relay_config_init () "auto_open_buffer", "boolean", N_("auto open relay buffer when a new client is connecting"), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + relay_config_look_raw_messages = weechat_config_new_option ( + relay_config_file, ptr_section, + "raw_messages", "integer", + N_("number of raw messages to save in memory when raw data buffer is " + "closed (messages will be displayed when opening raw data buffer)"), + NULL, 0, 65535, "256", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); ptr_section = weechat_config_new_section (relay_config_file, "color", 0, 0, diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h index 5790b3261..a6f14b54a 100644 --- a/src/plugins/relay/relay-config.h +++ b/src/plugins/relay/relay-config.h @@ -26,6 +26,7 @@ extern struct t_config_file *relay_config_file; extern struct t_config_section *relay_config_section_port; extern struct t_config_option *relay_config_look_auto_open_buffer; +extern struct t_config_option *relay_config_look_raw_messages; extern struct t_config_option *relay_config_color_text; extern struct t_config_option *relay_config_color_text_bg; diff --git a/src/plugins/relay/relay-protocol-irc.c b/src/plugins/relay/relay-protocol-irc.c deleted file mode 100644 index ca2723221..000000000 --- a/src/plugins/relay/relay-protocol-irc.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Copyright (C) 2003-2010 Sebastien Helleu <flashcode@flashtux.org> - * - * This file is part of WeeChat, the extensible chat client. - * - * WeeChat 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 3 of the License, or - * (at your option) any later version. - * - * WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * relay-protocol-irc.c: IRC protocol for relay to client - * (relay acting as an IRC proxy/bouncer) - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <errno.h> - -#include "../weechat-plugin.h" -#include "relay.h" -#include "relay-protocol-irc.h" -#include "relay-client.h" - - -/* - * relay_protocol_irc_search_buffer: search IRC buffer with server and channel - * name - */ - -struct t_gui_buffer * -relay_protocol_irc_search_buffer (const char *server, const char *channel) -{ - char string[256]; - long unsigned int value; - const char *str_ptr_buffer; - - snprintf (string, sizeof (string), "%s,%s", server, channel); - str_ptr_buffer = weechat_info_get ("irc_buffer", string); - if (str_ptr_buffer && str_ptr_buffer[0]) - { - sscanf (str_ptr_buffer, "%lx", &value); - return (struct t_gui_buffer *)value; - } - - return NULL; -} - -/* - * relay_protocol_irc_sendf: send formatted data to client - */ - -int -relay_protocol_irc_sendf (struct t_relay_client *client, const char *format, ...) -{ - va_list args; - static char buffer[4096]; - int length, num_sent; - - if (!client) - return 0; - - va_start (args, format); - vsnprintf (buffer, sizeof (buffer) - 3, format, args); - va_end (args); - - if (weechat_relay_plugin->debug) - { - weechat_printf (NULL, "relay: send: %s", buffer); - } - - length = strlen (buffer); - - buffer[length] = '\r'; - buffer[length + 1] = '\n'; - buffer[length + 2] = '\0'; - length += 2; - - num_sent = send (client->sock, buffer, length, 0); - - if (num_sent >= 0) - client->bytes_sent += num_sent; - else - { - weechat_printf (NULL, - _("%s%s: error sending data to client %s"), - weechat_prefix ("error"), RELAY_PLUGIN_NAME, - strerror (errno)); - } - - return num_sent; -} - -/* - * relay_protocol_irc_signal_irc_in2_cb: callback for "irc_in2" IRC signal - */ - -int -relay_protocol_irc_signal_irc_in2_cb (void *data, const char *signal, - const char *type_data, void *signal_data) -{ - struct t_relay_client *client; - const char *ptr_msg; - char *host, *pos, *pos_end_nick; - - (void) signal; - (void) type_data; - - client = (struct t_relay_client *)data; - ptr_msg = (const char *)signal_data; - - if (weechat_relay_plugin->debug) - { - weechat_printf (NULL, "relay: irc_in2: client: %s, data: %s", - client->protocol_string, - ptr_msg); - } - - if (ptr_msg[0] == ':') - { - pos = strchr (ptr_msg, ' '); - if (pos) - { - host = weechat_strndup (ptr_msg + 1, pos - ptr_msg); - if (host) - { - pos_end_nick = strchr (host, '!'); - if (pos_end_nick) - pos_end_nick[0] = '\0'; - else - host[0] = '\0'; - - pos++; - while (pos[0] == ' ') - { - pos++; - } - - relay_protocol_irc_sendf (client, ":%s%s%s %s", - (host[0]) ? host : "", - (host[0]) ? "!" : "", - RELAY_IRC_DATA(client, address), - pos); - free (host); - } - return WEECHAT_RC_OK; - } - } - - relay_protocol_irc_sendf (client, "%s", ptr_msg); - - return WEECHAT_RC_OK; -} - -/* - * relay_protocol_irc_signal_irc_out_cb: callback for "irc_out" IRC signal - */ - -int -relay_protocol_irc_signal_irc_out_cb (void *data, const char *signal, - const char *type_data, void *signal_data) -{ - struct t_relay_client *client; - - (void) signal; - (void) type_data; - - client = (struct t_relay_client *)data; - - if (weechat_relay_plugin->debug) - { - weechat_printf (NULL, "relay: irc_out: client: %s, data: %s", - client->protocol_string, - (char *)signal_data); - } - - return WEECHAT_RC_OK; -} - -/* - * relay_protocol_irc_send_join: send join for a channel to client - */ - -void -relay_protocol_irc_send_join (struct t_relay_client *client, - const char *channel) -{ - char *infolist_name, *nicks; - const char *nick; - int length, length_nicks; - struct t_infolist *infolist_nicks; - - length = strlen (client->protocol_string) + 1 + strlen (channel) + 1; - infolist_name = malloc (length); - if (infolist_name) - { - relay_protocol_irc_sendf (client, - ":%s!%s@proxy JOIN %s", - RELAY_IRC_DATA(client, nick), - "weechat", - channel); - snprintf (infolist_name, length, "%s,%s", - client->protocol_string, - channel); - infolist_nicks = weechat_infolist_get ("irc_nick", NULL, infolist_name); - if (infolist_nicks) - { - length_nicks = 0; - nicks = NULL; - while (weechat_infolist_next (infolist_nicks)) - { - nick = weechat_infolist_string (infolist_nicks, "name"); - if (nick && nick[0]) - { - if (length_nicks == 0) - { - length_nicks = strlen (nick) + 1; - nicks = malloc (length_nicks); - strcpy (nicks, nick); - } - else - { - length_nicks += strlen (nick) + 1; - nicks = realloc (nicks, length_nicks); - strcat (nicks, " "); - strcat (nicks, nick); - } - } - } - if (nicks) - { - relay_protocol_irc_sendf (client, - ":%s 353 %s = %s :%s", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - channel, nicks); - free (nicks); - } - weechat_infolist_free (infolist_nicks); - } - relay_protocol_irc_sendf (client, - ":%s 366 %s %s :End of /NAMES list.", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - channel); - free (infolist_name); - } -} - -/* - * relay_protocol_irc_send_join_channels: send join for all channels of server - * to client - */ - -void -relay_protocol_irc_send_join_channels (struct t_relay_client *client) -{ - struct t_infolist *infolist_channels; - const char *channel; - - infolist_channels = weechat_infolist_get ("irc_channel", NULL, - client->protocol_string); - if (infolist_channels) - { - while (weechat_infolist_next (infolist_channels)) - { - channel = weechat_infolist_string (infolist_channels, "name"); - relay_protocol_irc_send_join (client, channel); - } - weechat_infolist_free (infolist_channels); - } -} - -/* - * relay_protocol_irc_recv_one_msg: read one message from client - */ - -void -relay_protocol_irc_recv_one_msg (struct t_relay_client *client, char *data) -{ - char *pos, str_time[128], **argv, **argv_eol, str_signal_name[128]; - char *command; - int argc, length; - const char *nick; - struct t_gui_buffer *ptr_buffer; - - pos = strchr (data, '\r'); - if (pos) - pos[0] = '\0'; - - if (weechat_relay_plugin->debug) - { - weechat_printf (NULL, "relay: recv from client: \"%s\"", data); - } - - argv = weechat_string_split (data, " ", 0, 0, &argc); - argv_eol = weechat_string_split (data, " ", 1, 0, &argc); - - if (!RELAY_IRC_DATA(client, connected)) - { - if (weechat_strncasecmp (data, "nick ", 5) == 0) - { - if (data[5]) - { - if (RELAY_IRC_DATA(client, nick)) - free (RELAY_IRC_DATA(client, nick)); - RELAY_IRC_DATA(client, nick) = strdup (data + 5); - } - } - if (weechat_strncasecmp (data, "user ", 5) == 0) - { - if (data[5]) - { - RELAY_IRC_DATA(client, user_received) = 1; - } - } - if (RELAY_IRC_DATA(client, nick) && RELAY_IRC_DATA(client, user_received)) - { - RELAY_IRC_DATA(client, connected) = 1; - - /* - * send nick to client if server nick is different of nick asked - * by client with command NICK - */ - nick = weechat_info_get ("irc_nick", client->protocol_string); - if (nick && (strcmp (nick, RELAY_IRC_DATA(client, nick)) != 0)) - { - relay_protocol_irc_sendf (client, - ":%s!proxy NICK :%s", - RELAY_IRC_DATA(client, nick), - nick); - free (RELAY_IRC_DATA(client, nick)); - RELAY_IRC_DATA(client, nick) = strdup (nick); - } - - relay_protocol_irc_sendf (client, - ":%s 001 %s :Welcome to the Internet " - "Relay Network %s!%s@proxy", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - RELAY_IRC_DATA(client, nick), - "weechat"); - relay_protocol_irc_sendf (client, - ":%s 002 %s :Your host is " - "weechat-relay-irc, running version %s", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - weechat_info_get("version", NULL)); - snprintf (str_time, sizeof (str_time), "%s", - ctime (&client->listen_start_time)); - if (str_time[0]) - str_time[strlen (str_time) - 1] = '\0'; - relay_protocol_irc_sendf (client, - ":%s 003 %s :This server was created " - "on %s", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - str_time); - relay_protocol_irc_sendf (client, - ":%s 004 %s %s %s oirw abiklmnopqstv", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - RELAY_IRC_DATA(client, address), - weechat_info_get("version", NULL)); - relay_protocol_irc_sendf (client, - ":%s 251 %s :There are %d users and 0 " - "invisible on 1 servers", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - relay_client_count); - relay_protocol_irc_sendf (client, - ":%s 255 %s :I have %d clients, 0 " - "services and 0 servers", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - relay_client_count); - relay_protocol_irc_sendf (client, - ":%s 422 %s :MOTD File is missing", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick)); - - /* - * hook signal "xxx,irc_in2_*" to catch IRC data received from - * this server - */ - snprintf (str_signal_name, sizeof (str_signal_name), - "%s,irc_in2_*", - client->protocol_string); - RELAY_IRC_DATA(client, hook_signal_irc_in2) = - weechat_hook_signal (str_signal_name, - &relay_protocol_irc_signal_irc_in2_cb, - client); - - /* - * hook signal "xxx,irc_out_*" to catch IRC data sent to - * this server - */ - snprintf (str_signal_name, sizeof (str_signal_name), - "%s,irc_out_*", - client->protocol_string); - RELAY_IRC_DATA(client, hook_signal_irc_out) = - weechat_hook_signal (str_signal_name, - &relay_protocol_irc_signal_irc_out_cb, - client); - - /* send JOIN for all channels on server to client */ - relay_protocol_irc_send_join_channels (client); - } - } - else - { - if (argc > 0) - { - if (weechat_strcasecmp (argv[0], "privmsg") == 0) - { - ptr_buffer = relay_protocol_irc_search_buffer (client->protocol_string, - argv[1]); - if (ptr_buffer) - { - weechat_printf (NULL, - "relay: send string \"%s\" on channel %s", - (argv_eol[2][0] == ':') ? argv_eol[2] + 1 : argv_eol[2], - argv[1]); - weechat_command (ptr_buffer, - (argv_eol[2][0] == ':') ? argv_eol[2] + 1 : argv_eol[2]); - } - else - { - weechat_printf (NULL, - _("%s%s: buffer not found for IRC server " - "\"%s\", channel \"%s\""), - weechat_prefix ("error"), - RELAY_PLUGIN_NAME, - client->protocol_string, - argv[1]); - } - } - else - { - length = 32 + strlen (client->protocol_string) + strlen (data); - command = malloc (length + 1); - if (command) - { - snprintf (command, length, "/quote -server %s %s", - client->protocol_string, - data); - weechat_command (NULL, command); - free (command); - } - } - } - } - - if (argv) - weechat_string_free_split (argv); - if (argv_eol) - weechat_string_free_split (argv_eol); -} - -/* - * relay_protocol_irc_recv: read data from client - */ - -void -relay_protocol_irc_recv (struct t_relay_client *client, const char *data) -{ - char **items; - int items_count, i; - - items = weechat_string_split (data, "\n", 0, 0, &items_count); - for (i = 0; i < items_count; i++) - { - relay_protocol_irc_recv_one_msg (client, items[i]); - } - if (items) - weechat_string_free_split (items); -} - -/* - * relay_protocol_irc_alloc: init relay data specific to IRC protocol - */ - -void -relay_protocol_irc_alloc (struct t_relay_client *client) -{ - struct t_relay_protocol_irc_data *irc_data; - - client->protocol_data = malloc (sizeof (*irc_data)); - if (client->protocol_data) - { - RELAY_IRC_DATA(client, address) = strdup ("weechat.relay.irc"); - RELAY_IRC_DATA(client, nick) = NULL; - RELAY_IRC_DATA(client, user_received) = 0; - RELAY_IRC_DATA(client, connected) = 0; - RELAY_IRC_DATA(client, hook_signal_irc_in2) = NULL; - RELAY_IRC_DATA(client, hook_signal_irc_out) = NULL; - } -} - -/* - * relay_protocol_irc_free: free relay data specific to IRC protocol - */ - -void -relay_protocol_irc_free (struct t_relay_client *client) -{ - if (client->protocol_data) - { - if (RELAY_IRC_DATA(client, address)) - free (RELAY_IRC_DATA(client, address)); - if (RELAY_IRC_DATA(client, nick)) - free (RELAY_IRC_DATA(client, nick)); - if (RELAY_IRC_DATA(client, hook_signal_irc_in2)) - weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_in2)); - if (RELAY_IRC_DATA(client, hook_signal_irc_out)) - weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_out)); - - free (client->protocol_data); - } -} - -/* - * relay_protocol_irc_print_log: print IRC client infos in log (usually for - * crash dump) - */ - -void -relay_protocol_irc_print_log (struct t_relay_client *client) -{ - if (client->protocol_data) - { - weechat_log_printf (" address. . . . . . : '%s'", RELAY_IRC_DATA(client, address)); - weechat_log_printf (" nick . . . . . . . : '%s'", RELAY_IRC_DATA(client, nick)); - weechat_log_printf (" user_received. . . : %d", RELAY_IRC_DATA(client, user_received)); - weechat_log_printf (" connected. . . . . : %d", RELAY_IRC_DATA(client, connected)); - weechat_log_printf (" hook_signal_irc_in2: 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_in2)); - weechat_log_printf (" hook_signal_irc_out: 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_out)); - } -} diff --git a/src/plugins/relay/relay-raw.c b/src/plugins/relay/relay-raw.c new file mode 100644 index 000000000..1be5b0754 --- /dev/null +++ b/src/plugins/relay/relay-raw.c @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2003-2010 Sebastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat 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 3 of the License, or + * (at your option) any later version. + * + * WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * relay-raw.c: functions for Relay raw data messages + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-raw.h" +#include "relay-client.h" +#include "relay-config.h" + + +struct t_gui_buffer *relay_raw_buffer = NULL; + +int relay_raw_messages_count = 0; +struct t_relay_raw_message *relay_raw_messages = NULL; +struct t_relay_raw_message *last_relay_raw_message = NULL; + + +/* + * relay_raw_message_print: print a relay raw message + */ + +void +relay_raw_message_print (struct t_relay_raw_message *raw_message) +{ + if (relay_raw_buffer && raw_message) + { + weechat_printf_date_tags (relay_raw_buffer, + raw_message->date, NULL, + "%s\t%s", + raw_message->prefix, + raw_message->message); + } +} + +/* + * relay_raw_input_data_cb: callback for input data in Relay raw buffer + */ + +int +relay_raw_input_data_cb (void *data, struct t_gui_buffer *buffer, + const char *input_data) +{ + /* make C compiler happy */ + (void) data; + + if (weechat_strcasecmp (input_data, "q") == 0) + weechat_buffer_close (buffer); + + return WEECHAT_RC_OK; +} + +/* + * relay_raw_buffer_close_cb: callback called when Relay raw buffer is closed + */ + +int +relay_raw_buffer_close_cb (void *data, struct t_gui_buffer *buffer) +{ + /* make C compiler happy */ + (void) data; + (void) buffer; + + relay_raw_buffer = NULL; + + return WEECHAT_RC_OK; +} + +/* + * relay_raw_open: open Relay raw buffer + */ + +void +relay_raw_open (int switch_to_buffer) +{ + struct t_relay_raw_message *ptr_raw_message; + + if (!relay_raw_buffer) + { + relay_raw_buffer = weechat_buffer_search (RELAY_PLUGIN_NAME, + RELAY_RAW_BUFFER_NAME); + if (!relay_raw_buffer) + { + relay_raw_buffer = weechat_buffer_new (RELAY_RAW_BUFFER_NAME, + &relay_raw_input_data_cb, NULL, + &relay_raw_buffer_close_cb, NULL); + + /* failed to create buffer ? then return */ + if (!relay_raw_buffer) + return; + + weechat_buffer_set (relay_raw_buffer, + "title", _("Relay raw messages")); + + weechat_buffer_set (relay_raw_buffer, "short_name", RELAY_RAW_BUFFER_NAME); + weechat_buffer_set (relay_raw_buffer, "localvar_set_type", "debug"); + weechat_buffer_set (relay_raw_buffer, "localvar_set_server", RELAY_RAW_BUFFER_NAME); + weechat_buffer_set (relay_raw_buffer, "localvar_set_channel", RELAY_RAW_BUFFER_NAME); + weechat_buffer_set (relay_raw_buffer, "localvar_set_no_log", "1"); + + /* disable all highlights on this buffer */ + weechat_buffer_set (relay_raw_buffer, "highlight_words", "-"); + + /* print messages in list */ + for (ptr_raw_message = relay_raw_messages; ptr_raw_message; + ptr_raw_message = ptr_raw_message->next_message) + { + relay_raw_message_print (ptr_raw_message); + } + } + } + + if (relay_raw_buffer && switch_to_buffer) + weechat_buffer_set (relay_raw_buffer, "display", "1"); +} + +/* + * relay_raw_message_free: free a raw message and remove it from list + */ + +void +relay_raw_message_free (struct t_relay_raw_message *raw_message) +{ + struct t_relay_raw_message *new_raw_messages; + + /* remove message from raw messages list */ + if (last_relay_raw_message == raw_message) + last_relay_raw_message = raw_message->prev_message; + if (raw_message->prev_message) + { + (raw_message->prev_message)->next_message = raw_message->next_message; + new_raw_messages = relay_raw_messages; + } + else + new_raw_messages = raw_message->next_message; + + if (raw_message->next_message) + (raw_message->next_message)->prev_message = raw_message->prev_message; + + /* free data */ + if (raw_message->prefix) + free (raw_message->prefix); + if (raw_message->message) + free (raw_message->message); + + free (raw_message); + + relay_raw_messages = new_raw_messages; + + relay_raw_messages_count--; +} + +/* + * relay_raw_message_free_all: free all raw messages + */ + +void +relay_raw_message_free_all () +{ + while (relay_raw_messages) + { + relay_raw_message_free (relay_raw_messages); + } +} + +/* + * relay_raw_message_remove_old: remove old raw messages if limit has been + * reached + */ + +void +relay_raw_message_remove_old () +{ + int max_messages; + + max_messages = weechat_config_integer (relay_config_look_raw_messages); + while (relay_raw_messages && (relay_raw_messages_count >= max_messages)) + { + relay_raw_message_free (relay_raw_messages); + } +} + +/* + * relay_raw_message_add_to_list: add new message to list + */ + +struct t_relay_raw_message * +relay_raw_message_add_to_list (time_t date, const char *prefix, + const char *message) +{ + struct t_relay_raw_message *new_raw_message; + + relay_raw_message_remove_old (); + + new_raw_message = malloc (sizeof (*new_raw_message)); + if (new_raw_message) + { + new_raw_message->date = date; + new_raw_message->prefix = strdup (prefix); + new_raw_message->message = strdup (message); + + /* add message to list */ + new_raw_message->prev_message = last_relay_raw_message; + new_raw_message->next_message = NULL; + if (relay_raw_messages) + last_relay_raw_message->next_message = new_raw_message; + else + relay_raw_messages = new_raw_message; + last_relay_raw_message = new_raw_message; + + relay_raw_messages_count++; + } + + return new_raw_message; +} + +/* + * relay_raw_message_add: add new message to list + */ + +struct t_relay_raw_message * +relay_raw_message_add (struct t_relay_client *client, int send, + const char *message) +{ + char *buf, *buf2, prefix[256]; + const unsigned char *ptr_buf; + const char *hexa = "0123456789ABCDEF"; + int pos_buf, pos_buf2, char_size, i; + struct t_relay_raw_message *new_raw_message; + + buf = weechat_iconv_to_internal (NULL, message); + buf2 = malloc ((strlen (buf) * 3) + 1); + if (buf2) + { + ptr_buf = (buf) ? (unsigned char *)buf : (unsigned char *)message; + pos_buf = 0; + pos_buf2 = 0; + while (ptr_buf[pos_buf]) + { + if (ptr_buf[pos_buf] < 32) + { + buf2[pos_buf2++] = '\\'; + buf2[pos_buf2++] = hexa[ptr_buf[pos_buf] / 16]; + buf2[pos_buf2++] = hexa[ptr_buf[pos_buf] % 16]; + pos_buf++; + } + else + { + char_size = weechat_utf8_char_size ((const char *)(ptr_buf + pos_buf)); + for (i = 0; i < char_size; i++) + { + buf2[pos_buf2++] = ptr_buf[pos_buf++]; + } + } + } + buf2[pos_buf2] = '\0'; + } + + if (client) + { + snprintf (prefix, sizeof (prefix), "%s[%s%d%s] %s%s %s%s", + weechat_color ("chat_delimiters"), + weechat_color ("chat"), + client->id, + weechat_color ("chat_delimiters"), + weechat_color ("chat_server"), + client->protocol_string, + (send) ? + weechat_color ("chat_prefix_quit") : + weechat_color ("chat_prefix_join"), + (send) ? RELAY_RAW_PREFIX_SEND : RELAY_RAW_PREFIX_RECV); + } + else + { + snprintf (prefix, sizeof (prefix), "%s%s", + (send) ? + weechat_color ("chat_prefix_quit") : + weechat_color ("chat_prefix_join"), + (send) ? RELAY_RAW_PREFIX_SEND : RELAY_RAW_PREFIX_RECV); + } + + new_raw_message = relay_raw_message_add_to_list (time (NULL), + prefix, + (buf2) ? buf2 : ((buf) ? buf : message)); + + if (buf) + free (buf); + if (buf2) + free (buf2); + + return new_raw_message; +} + +/* + * relay_raw_print: print a message on Relay raw buffer + */ + +void +relay_raw_print (struct t_relay_client *client, int send, const char *message) +{ + struct t_relay_raw_message *new_raw_message; + + if (!message) + return; + + /* auto-open Relay raw buffer if debug for irc plugin is >= 1 */ + if (!relay_raw_buffer && (weechat_relay_plugin->debug >= 1)) + relay_raw_open (0); + + new_raw_message = relay_raw_message_add (client, send, message); + if (new_raw_message) + { + if (relay_raw_buffer) + relay_raw_message_print (new_raw_message); + if (weechat_config_integer (relay_config_look_raw_messages) == 0) + relay_raw_message_free (new_raw_message); + } +} + +/* + * relay_raw_add_to_infolist: add a raw message in an infolist + * return 1 if ok, 0 if error + */ + +int +relay_raw_add_to_infolist (struct t_infolist *infolist, + struct t_relay_raw_message *raw_message) +{ + struct t_infolist_item *ptr_item; + + if (!infolist || !raw_message) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_time (ptr_item, "date", raw_message->date)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "prefix", raw_message->prefix)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "message", raw_message->message)) + return 0; + + return 1; +} diff --git a/src/plugins/relay/relay-raw.h b/src/plugins/relay/relay-raw.h new file mode 100644 index 000000000..ed0d2a577 --- /dev/null +++ b/src/plugins/relay/relay-raw.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2003-2010 Sebastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat 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 3 of the License, or + * (at your option) any later version. + * + * WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __WEECHAT_RELAY_RAW_H +#define __WEECHAT_RELAY_RAW_H 1 + +#define RELAY_RAW_BUFFER_NAME "relay_raw" +#define RELAY_RAW_PREFIX_RECV "-->" +#define RELAY_RAW_PREFIX_SEND "<--" + +struct t_relay_raw_message +{ + time_t date; /* date/time of message */ + char *prefix; /* prefix */ + char *message; /* message */ + struct t_relay_raw_message *prev_message; /* pointer to prev. message */ + struct t_relay_raw_message *next_message; /* pointer to next message */ +}; + +struct t_relay_client; + +extern struct t_gui_buffer *relay_raw_buffer; +extern int irc_relay_messages_count; +extern struct t_relay_raw_message *relay_raw_messages, *last_relay_raw_message; + +extern void relay_raw_open (int switch_to_buffer); +extern struct t_relay_raw_message *relay_raw_message_add_to_list (time_t date, + const char *prefix, + const char *message); +extern void relay_raw_print (struct t_relay_client *client, int send, + const char *message); +extern void relay_raw_message_free_all (); +extern int relay_raw_add_to_infolist (struct t_infolist *infolist, + struct t_relay_raw_message *raw_message); + +#endif /* __WEECHAT_RELAY_RAW_H */ |