diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2011-12-06 23:06:23 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2011-12-06 23:06:23 +0100 |
commit | 013f8cc7570a283e4c265d2a03920ff60f681885 (patch) | |
tree | a81404bd4af44aef206b68a069e05b15ee6315a1 /src | |
parent | 00a3f990b3e512a7dc14343dd522a3a8497c4762 (diff) | |
download | weechat-013f8cc7570a283e4c265d2a03920ff60f681885.zip |
relay: add WeeChat protocol (for remote GUI), doc about protocol, new options
The protocol is partial, under development, and NOT ready for usage.
New options added in relay.conf:
- relay.network.allowed_ips: allow only some IPs on relay plugin (by default
all IPs are allowed)
- relay.network.compression_level: compression level used in WeeChat protocol
(compression is made using zlib)
Diffstat (limited to 'src')
24 files changed, 2209 insertions, 670 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9fe2d9f53..9a93cb4f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -104,6 +104,14 @@ IF(ENABLE_GNUTLS) ENDIF(GNUTLS_FOUND) ENDIF(ENABLE_GNUTLS) +# Check for zlib +IF(ENABLE_ZLIB) + FIND_PACKAGE(ZLIB) + IF(ZLIB_FOUND) + ADD_DEFINITIONS(-DHAVE_ZLIB) + ENDIF(ZLIB_FOUND) +ENDIF(ENABLE_ZLIB) + # Check for iconv FIND_PACKAGE(Iconv) IF(ICONV_FOUND) diff --git a/src/plugins/relay/CMakeLists.txt b/src/plugins/relay/CMakeLists.txt index 44c1fef6c..c324cb9ec 100644 --- a/src/plugins/relay/CMakeLists.txt +++ b/src/plugins/relay/CMakeLists.txt @@ -21,8 +21,10 @@ 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 +irc/relay-irc.c irc/relay-irc.h +weechat/relay-weechat.c weechat/relay-weechat.h +weechat/relay-weechat-msg.c weechat/relay-weechat-msg.h +weechat/relay-weechat-protocol.c weechat/relay-weechat-protocol.h relay-command.c relay-command.h relay-completion.c relay-completion.h relay-config.c relay-config.h @@ -32,6 +34,12 @@ relay-server.c relay-server.h relay-upgrade.c relay-upgrade.h) SET_TARGET_PROPERTIES(relay PROPERTIES PREFIX "") -TARGET_LINK_LIBRARIES(relay) +SET (LINK_LIBS) + +IF(ZLIB_FOUND) + LIST(APPEND LINK_LIBS ${ZLIB_LIBRARY}) +ENDIF(ZLIB_FOUND) + +TARGET_LINK_LIBRARIES(relay ${LINK_LIBS}) INSTALL(TARGETS relay LIBRARY DESTINATION ${LIBDIR}/plugins) diff --git a/src/plugins/relay/Makefile.am b/src/plugins/relay/Makefile.am index da1620c5b..66656798f 100644 --- a/src/plugins/relay/Makefile.am +++ b/src/plugins/relay/Makefile.am @@ -17,7 +17,7 @@ # along with WeeChat. If not, see <http://www.gnu.org/licenses/>. # -INCLUDES = -DLOCALEDIR=\"$(datadir)/locale\" +INCLUDES = -DLOCALEDIR=\"$(datadir)/locale\" $(ZLIB_CFLAGS) libdir = ${weechat_libdir}/plugins @@ -29,10 +29,14 @@ 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 \ + irc/relay-irc.c \ + irc/relay-irc.h \ + weechat/relay-weechat.c \ + weechat/relay-weechat.h \ + weechat/relay-weechat-msg.c \ + weechat/relay-weechat-msg.h \ + weechat/relay-weechat-protocol.c \ + weechat/relay-weechat-protocol.h \ relay-command.c \ relay-command.h \ relay-completion.c \ @@ -49,6 +53,6 @@ relay_la_SOURCES = relay.c \ relay-upgrade.h relay_la_LDFLAGS = -module -relay_la_LIBADD = $(RELAY_LFLAGS) +relay_la_LIBADD = $(RELAY_LFLAGS) $(ZLIB_LFLAGS) EXTRA_DIST = CMakeLists.txt diff --git a/src/plugins/relay/relay-client-irc.c b/src/plugins/relay/irc/relay-irc.c index 7076065fa..c1353ac00 100644 --- a/src/plugins/relay/relay-client-irc.c +++ b/src/plugins/relay/irc/relay-irc.c @@ -18,8 +18,8 @@ */ /* - * relay-client-irc.c: IRC protocol for relay to client - * (relay acting as an IRC proxy/bouncer) + * relay-irc.c: IRC protocol for relay to client + * (relay acting as an IRC proxy/bouncer) */ #include <stdlib.h> @@ -31,34 +31,33 @@ #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-config.h" -#include "relay-raw.h" +#include "../../weechat-plugin.h" +#include "../relay.h" +#include "relay-irc.h" +#include "../relay-client.h" +#include "../relay-config.h" +#include "../relay-raw.h" -char *relay_client_irc_relay_commands[] = { "privmsg", "notice", NULL }; -char *relay_client_irc_ignore_commands[] = { "pong", "quit", NULL }; +char *relay_irc_relay_commands[] = { "privmsg", "notice", NULL }; +char *relay_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 + * relay_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) +relay_irc_command_relayed (const char *irc_command) { int i; if (irc_command) { - for (i = 0; relay_client_irc_relay_commands[i]; i++) + for (i = 0; relay_irc_relay_commands[i]; i++) { - if (weechat_strcasecmp (relay_client_irc_relay_commands[i], irc_command) == 0) + if (weechat_strcasecmp (relay_irc_relay_commands[i], irc_command) == 0) return 1; } } @@ -68,20 +67,20 @@ relay_client_irc_command_relayed (const char *irc_command) } /* - * relay_client_irc_command_ignored: return 1 if IRC command from client - * has to be ignored + * relay_irc_command_ignored: return 1 if IRC command from client has to be + * ignored */ int -relay_client_irc_command_ignored (const char *irc_command) +relay_irc_command_ignored (const char *irc_command) { int i; if (irc_command) { - for (i = 0; relay_client_irc_ignore_commands[i]; i++) + for (i = 0; relay_irc_ignore_commands[i]; i++) { - if (weechat_strcasecmp (relay_client_irc_ignore_commands[i], irc_command) == 0) + if (weechat_strcasecmp (relay_irc_ignore_commands[i], irc_command) == 0) return 1; } } @@ -91,11 +90,11 @@ relay_client_irc_command_ignored (const char *irc_command) } /* - * relay_client_irc_message_parse: parse IRC message + * relay_irc_message_parse: parse IRC message */ struct t_hashtable * -relay_client_irc_message_parse (const char *message) +relay_irc_message_parse (const char *message) { struct t_hashtable *hash_msg, *hash_parsed; @@ -133,11 +132,11 @@ end: } /* - * relay_client_irc_sendf: send formatted data to client + * relay_irc_sendf: send formatted data to client */ int -relay_client_irc_sendf (struct t_relay_client *client, const char *format, ...) +relay_irc_sendf (struct t_relay_client *client, const char *format, ...) { int length, num_sent, total_sent, number; char *pos, hash_key[32], *message; @@ -180,7 +179,7 @@ relay_client_irc_sendf (struct t_relay_client *client, const char *format, ...) str_message = weechat_hashtable_get (hashtable_out, hash_key); if (!str_message) break; - relay_raw_print (client, 1, str_message); + relay_raw_print (client, RELAY_RAW_FLAG_SEND, "%s", str_message); length = strlen (str_message) + 16 + 1; message = malloc (length); if (message) @@ -213,15 +212,15 @@ relay_client_irc_sendf (struct t_relay_client *client, const char *format, ...) } /* - * 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. + * relay_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) +relay_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_nick, *irc_host, *irc_command, *irc_args; @@ -242,7 +241,7 @@ relay_client_irc_signal_irc_in2_cb (void *data, const char *signal, ptr_msg); } - hash_parsed = relay_client_irc_message_parse (ptr_msg); + hash_parsed = relay_irc_message_parse (ptr_msg); if (hash_parsed) { irc_nick = weechat_hashtable_get (hash_parsed, "nick"); @@ -267,10 +266,10 @@ relay_client_irc_signal_irc_in2_cb (void *data, const char *signal, && (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); + relay_irc_sendf (client, ":%s %s %s", + (irc_host && irc_host[0]) ? irc_host : RELAY_IRC_DATA(client, address), + irc_command, + irc_args); } weechat_hashtable_free (hash_parsed); @@ -280,15 +279,15 @@ relay_client_irc_signal_irc_in2_cb (void *data, const char *signal, } /* - * 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. + * relay_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) +relay_irc_tag_relay_client_id (const char *tags) { char **argv, *error; int result, argc, i; @@ -322,16 +321,16 @@ relay_client_irc_tag_relay_client_id (const char *tags) } /* - * 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). + * relay_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) +relay_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; @@ -379,10 +378,10 @@ relay_client_irc_signal_irc_outtags_cb (void *data, const char *signal, * 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) + if (relay_irc_tag_relay_client_id (tags) == client->id) goto end; - hash_parsed = relay_client_irc_message_parse (ptr_message); + hash_parsed = relay_irc_message_parse (ptr_message); if (hash_parsed) { irc_command = weechat_hashtable_get (hash_parsed, "command"); @@ -395,7 +394,7 @@ relay_client_irc_signal_irc_outtags_cb (void *data, const char *signal, /* 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)) + && relay_irc_command_relayed (irc_command)) { /* get host for nick (it is self nick) */ snprintf (str_infolist_args, sizeof (str_infolist_args) - 1, @@ -410,12 +409,12 @@ relay_client_irc_signal_irc_outtags_cb (void *data, const char *signal, 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); + relay_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); @@ -435,14 +434,14 @@ end: } /* - * relay_client_irc_signal_irc_disc_cb: callback for "irc_disconnected" signal - * It is called when connection to a - * server is lost. + * relay_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) +relay_irc_signal_irc_disc_cb (void *data, const char *signal, + const char *type_data, void *signal_data) { struct t_relay_client *client; @@ -462,12 +461,12 @@ relay_client_irc_signal_irc_disc_cb (void *data, const char *signal, } /* - * relay_client_irc_send_join: send join for a channel to client + * relay_irc_send_join: send join for a channel to client */ void -relay_client_irc_send_join (struct t_relay_client *client, - const char *channel) +relay_irc_send_join (struct t_relay_client *client, + const char *channel) { char *infolist_name, *nicks, *nicks2; const char *nick, *prefix, *topic; @@ -497,11 +496,11 @@ relay_client_irc_send_join (struct t_relay_client *client, } 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); + relay_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", @@ -516,11 +515,11 @@ relay_client_irc_send_join (struct t_relay_client *client, topic = weechat_infolist_string (infolist_channel, "topic"); if (topic && topic[0]) { - relay_client_irc_sendf (client, - ":%s 332 %s %s :%s", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - channel, topic); + relay_irc_sendf (client, + ":%s 332 %s %s :%s", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick), + channel, topic); } } weechat_infolist_free (infolist_channel); @@ -562,31 +561,30 @@ relay_client_irc_send_join (struct t_relay_client *client, } if (nicks) { - relay_client_irc_sendf (client, - ":%s 353 %s = %s :%s", - RELAY_IRC_DATA(client, address), - RELAY_IRC_DATA(client, nick), - channel, nicks); + relay_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); + relay_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 + * relay_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) +relay_irc_send_join_channels (struct t_relay_client *client) { struct t_infolist *infolist_channels; const char *channel; @@ -600,7 +598,7 @@ relay_client_irc_send_join_channels (struct t_relay_client *client) if (weechat_infolist_integer (infolist_channels, "nicks_count") > 0) { channel = weechat_infolist_string (infolist_channels, "name"); - relay_client_irc_send_join (client, channel); + relay_irc_send_join (client, channel); } } weechat_infolist_free (infolist_channels); @@ -608,14 +606,12 @@ relay_client_irc_send_join_channels (struct t_relay_client *client) } /* - * relay_client_irc_input_send: send text or command on an IRC buffer + * relay_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, ...) +relay_irc_input_send (struct t_relay_client *client, const char *irc_channel, + int flags, const char *format, ...) { char buf_beginning[1024], *buf; int length_beginning, length_vbuffer; @@ -655,11 +651,11 @@ relay_client_irc_input_send (struct t_relay_client *client, } /* - * relay_client_irc_hook_signals: hook signals for a client + * relay_irc_hook_signals: hook signals for a client */ void -relay_client_irc_hook_signals (struct t_relay_client *client) +relay_irc_hook_signals (struct t_relay_client *client) { char str_signal_name[128]; @@ -672,7 +668,7 @@ relay_client_irc_hook_signals (struct t_relay_client *client) client->protocol_args); RELAY_IRC_DATA(client, hook_signal_irc_in2) = weechat_hook_signal (str_signal_name, - &relay_client_irc_signal_irc_in2_cb, + &relay_irc_signal_irc_in2_cb, client); /* @@ -684,7 +680,7 @@ relay_client_irc_hook_signals (struct t_relay_client *client) client->protocol_args); RELAY_IRC_DATA(client, hook_signal_irc_outtags) = weechat_hook_signal (str_signal_name, - &relay_client_irc_signal_irc_outtags_cb, + &relay_irc_signal_irc_outtags_cb, client); /* @@ -693,16 +689,16 @@ relay_client_irc_hook_signals (struct t_relay_client *client) */ RELAY_IRC_DATA(client, hook_signal_irc_disc) = weechat_hook_signal ("irc_server_disconnected", - &relay_client_irc_signal_irc_disc_cb, + &relay_irc_signal_irc_disc_cb, client); } /* - * relay_client_irc_recv_one_msg: read one message from client + * relay_irc_recv_one_msg: read one message from client */ void -relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) +relay_irc_recv_one_msg (struct t_relay_client *client, char *data) { char *pos, str_time[128], *target; const char *irc_command, *irc_channel, *irc_args, *irc_args2; @@ -720,14 +716,15 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) /* display debug message */ if (weechat_relay_plugin->debug >= 2) { - weechat_printf (NULL, "%s: recv from client: \"%s\"", - RELAY_PLUGIN_NAME, data); + weechat_printf (NULL, "%s: recv from client %d: \"%s\"", + RELAY_PLUGIN_NAME, client->id, data); } - relay_raw_print (client, 0, data); + /* display message in raw buffer */ + relay_raw_print (client, RELAY_RAW_FLAG_RECV, "%s", data); /* parse IRC message */ - hash_parsed = relay_client_irc_message_parse (data); + hash_parsed = relay_irc_message_parse (data); if (!hash_parsed) goto end; irc_command = weechat_hashtable_get (hash_parsed, "command"); @@ -770,14 +767,14 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) 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_args); - relay_client_irc_sendf (client, - ":%s ERROR :Closing Link", - RELAY_IRC_DATA(client, address)); + relay_irc_sendf (client, + ":%s ERROR :WeeChat: no " + "connection to server \"%s\"", + RELAY_IRC_DATA(client, address), + client->protocol_args); + relay_irc_sendf (client, + ":%s ERROR :Closing Link", + RELAY_IRC_DATA(client, address)); relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); goto end; @@ -796,9 +793,9 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) /* disconnect client if password was not received or wrong */ if (!RELAY_IRC_DATA(client, password_ok)) { - relay_client_irc_sendf (client, - ":%s ERROR :WeeChat: password error", - RELAY_IRC_DATA(client, address)); + relay_irc_sendf (client, + ":%s ERROR :WeeChat: password error", + RELAY_IRC_DATA(client, address)); relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); goto end; @@ -813,42 +810,42 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) nick = weechat_info_get ("irc_nick", client->protocol_args); 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); + relay_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)); + relay_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_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)); + relay_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_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_args); if (infolist_server) @@ -863,49 +860,49 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) { isupport++; } - 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); + relay_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)); + relay_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_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_irc_sendf (client, + ":%s 422 %s :MOTD File is missing", + RELAY_IRC_DATA(client, address), + RELAY_IRC_DATA(client, nick)); /* hook signals */ - relay_client_irc_hook_signals (client); + relay_irc_hook_signals (client); /* send JOIN for all channels on server to client */ - relay_client_irc_send_join_channels (client); + relay_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); + relay_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] @@ -923,10 +920,10 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) } if (irc_args2[0] == ':') irc_args2++; - relay_client_irc_input_send (client, NULL, 1, - "/notice %s %s", - target, - irc_args2); + relay_irc_input_send (client, NULL, 1, + "/notice %s %s", + target, + irc_args2); free (target); } } @@ -947,21 +944,21 @@ relay_client_irc_recv_one_msg (struct t_relay_client *client, char *data) 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); + relay_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); + relay_irc_input_send (client, NULL, 1, + "/query %s %s", + irc_channel, irc_args2); } } - else if (!relay_client_irc_command_ignored (irc_command)) + else if (!relay_irc_command_ignored (irc_command)) { - relay_client_irc_input_send (client, NULL, 1, - "/quote %s", - data); + relay_irc_input_send (client, NULL, 1, + "/quote %s", + data); } } @@ -971,11 +968,11 @@ end: } /* - * relay_client_irc_recv: read data from client + * relay_irc_recv: read data from client */ void -relay_client_irc_recv (struct t_relay_client *client, const char *data) +relay_irc_recv (struct t_relay_client *client, const char *data) { char **items; int items_count, i; @@ -983,19 +980,18 @@ relay_client_irc_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_client_irc_recv_one_msg (client, items[i]); + relay_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 + * relay_irc_close_connection: called when connection with client is closed */ void -relay_client_irc_close_connection (struct t_relay_client *client) +relay_irc_close_connection (struct t_relay_client *client) { RELAY_IRC_DATA(client, connected) = 0; if (RELAY_IRC_DATA(client, hook_signal_irc_in2)) @@ -1016,13 +1012,13 @@ relay_client_irc_close_connection (struct t_relay_client *client) } /* - * relay_client_irc_alloc: init relay data specific to IRC protocol + * relay_irc_alloc: init relay data specific to IRC protocol */ void -relay_client_irc_alloc (struct t_relay_client *client) +relay_irc_alloc (struct t_relay_client *client) { - struct t_relay_client_irc_data *irc_data; + struct t_relay_irc_data *irc_data; const char *password; password = weechat_config_string (relay_config_network_password); @@ -1042,15 +1038,15 @@ relay_client_irc_alloc (struct t_relay_client *client) } /* - * relay_client_irc_alloc_with_infolist: init relay data specific to IRC - * protocol using an infolist + * relay_irc_alloc_with_infolist: init relay data specific to IRC protocol + * using an infolist */ void -relay_client_irc_alloc_with_infolist (struct t_relay_client *client, - struct t_infolist *infolist) +relay_irc_alloc_with_infolist (struct t_relay_client *client, + struct t_infolist *infolist) { - struct t_relay_client_irc_data *irc_data; + struct t_relay_irc_data *irc_data; client->protocol_data = malloc (sizeof (*irc_data)); if (client->protocol_data) @@ -1065,7 +1061,7 @@ relay_client_irc_alloc_with_infolist (struct t_relay_client *client, RELAY_IRC_DATA(client, connected) = weechat_infolist_integer (infolist, "connected"); if (RELAY_IRC_DATA(client, connected)) { - relay_client_irc_hook_signals (client); + relay_irc_hook_signals (client); } else { @@ -1077,11 +1073,11 @@ relay_client_irc_alloc_with_infolist (struct t_relay_client *client, } /* - * relay_client_irc_free: free relay data specific to IRC protocol + * relay_irc_free: free relay data specific to IRC protocol */ void -relay_client_irc_free (struct t_relay_client *client) +relay_irc_free (struct t_relay_client *client) { if (client->protocol_data) { @@ -1103,13 +1099,13 @@ relay_client_irc_free (struct t_relay_client *client) } /* - * relay_client_irc_add_to_infolist: add client irc data in an infolist item - * return 1 if ok, 0 if error + * relay_irc_add_to_infolist: add client irc data in an infolist item + * return 1 if ok, 0 if error */ int -relay_client_irc_add_to_infolist (struct t_infolist_item *item, - struct t_relay_client *client) +relay_irc_add_to_infolist (struct t_infolist_item *item, + struct t_relay_client *client) { if (!item || !client) return 0; @@ -1135,12 +1131,11 @@ relay_client_irc_add_to_infolist (struct t_infolist_item *item, } /* - * relay_client_irc_print_log: print IRC client infos in log (usually for - * crash dump) + * relay_irc_print_log: print IRC client infos in log (usually for crash dump) */ void -relay_client_irc_print_log (struct t_relay_client *client) +relay_irc_print_log (struct t_relay_client *client) { if (client->protocol_data) { diff --git a/src/plugins/relay/relay-client-irc.h b/src/plugins/relay/irc/relay-irc.h index fe14b8b36..e387c6241 100644 --- a/src/plugins/relay/relay-client-irc.h +++ b/src/plugins/relay/irc/relay-irc.h @@ -17,15 +17,15 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __WEECHAT_RELAY_CLIENT_IRC_H -#define __WEECHAT_RELAY_CLIENT_IRC_H 1 +#ifndef __WEECHAT_RELAY_IRC_H +#define __WEECHAT_RELAY_IRC_H 1 struct t_relay_client; -#define RELAY_IRC_DATA(client, var) \ - (((struct t_relay_client_irc_data *)client->protocol_data)->var) +#define RELAY_IRC_DATA(client, var) \ + (((struct t_relay_irc_data *)client->protocol_data)->var) -struct t_relay_client_irc_data +struct t_relay_irc_data { char *address; /* client address (used when sending */ /* data to client) */ @@ -39,15 +39,15 @@ struct t_relay_client_irc_data struct t_hook *hook_signal_irc_disc; /* signal "irc_disconnected" */ }; -extern void relay_client_irc_recv (struct t_relay_client *client, +extern void relay_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_alloc_with_infolist (struct t_relay_client *client, - struct t_infolist *infolist); -extern void relay_client_irc_free (struct t_relay_client *client); -extern int relay_client_irc_add_to_infolist (struct t_infolist_item *item, - struct t_relay_client *client); -extern void relay_client_irc_print_log (struct t_relay_client *client); +extern void relay_irc_close_connection (struct t_relay_client *client); +extern void relay_irc_alloc (struct t_relay_client *client); +extern void relay_irc_alloc_with_infolist (struct t_relay_client *client, + struct t_infolist *infolist); +extern void relay_irc_free (struct t_relay_client *client); +extern int relay_irc_add_to_infolist (struct t_infolist_item *item, + struct t_relay_client *client); +extern void relay_irc_print_log (struct t_relay_client *client); -#endif /* __WEECHAT_RELAY_CLIENT_IRC_H */ +#endif /* __WEECHAT_RELAY_IRC_H */ diff --git a/src/plugins/relay/relay-buffer.c b/src/plugins/relay/relay-buffer.c index 5501f6cfd..0e22f5bf7 100644 --- a/src/plugins/relay/relay-buffer.c +++ b/src/plugins/relay/relay-buffer.c @@ -64,11 +64,11 @@ relay_buffer_refresh (const char *hotlist) weechat_color("lightgreen"), /* disconnect */ (client_selected - && !RELAY_CLIENT_HAS_ENDED(client_selected->status)) ? + && !RELAY_CLIENT_HAS_ENDED(client_selected)) ? _(" [D] Disconnect") : "", /* remove */ (client_selected - && RELAY_CLIENT_HAS_ENDED(client_selected->status)) ? + && RELAY_CLIENT_HAS_ENDED(client_selected)) ? _(" [R] Remove") : "", /* purge old */ _(" [P] Purge finished"), @@ -178,7 +178,7 @@ relay_buffer_input_cb (void *data, struct t_gui_buffer *buffer, /* disconnect client */ if (weechat_strcasecmp (input_data, "d") == 0) { - if (client && !RELAY_CLIENT_HAS_ENDED(client->status)) + if (client && !RELAY_CLIENT_HAS_ENDED(client)) { relay_client_disconnect (client); relay_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); @@ -191,7 +191,7 @@ relay_buffer_input_cb (void *data, struct t_gui_buffer *buffer, while (ptr_client) { next_client = ptr_client->next_client; - if (RELAY_CLIENT_HAS_ENDED(ptr_client->status)) + if (RELAY_CLIENT_HAS_ENDED(ptr_client)) relay_client_free (ptr_client); ptr_client = next_client; } @@ -205,7 +205,7 @@ relay_buffer_input_cb (void *data, struct t_gui_buffer *buffer, /* remove client */ else if (weechat_strcasecmp (input_data, "r") == 0) { - if (client && RELAY_CLIENT_HAS_ENDED(client->status)) + if (client && RELAY_CLIENT_HAS_ENDED(client)) { relay_client_free (client); relay_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); diff --git a/src/plugins/relay/relay-client-weechat.c b/src/plugins/relay/relay-client-weechat.c deleted file mode 100644 index ca2573502..000000000 --- a/src/plugins/relay/relay-client-weechat.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2003-2011 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-weechat.c: WeeChat protocol for relay to client - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <errno.h> - -#include "../weechat-plugin.h" -#include "relay.h" -#include "relay-client-weechat.h" -#include "relay-client.h" -#include "relay-config.h" - - -/* - * relay_client_weechat_sendf: send formatted data to client - */ - -int -relay_client_weechat_sendf (struct t_relay_client *client, - const char *format, ...) -{ - char str_length[8]; - int length_vbuffer, num_sent, total_sent; - - if (!client) - return 0; - - weechat_va_format (format); - if (!vbuffer) - return 0; - length_vbuffer = strlen (vbuffer); - - total_sent = 0; - - snprintf (str_length, sizeof (str_length), "%07d", length_vbuffer); - - num_sent = send (client->sock, str_length, 7, 0); - client->bytes_sent += 7; - total_sent += num_sent; - if (num_sent >= 0) - { - num_sent = send (client->sock, vbuffer, length_vbuffer, 0); - client->bytes_sent += length_vbuffer; - total_sent += num_sent; - } - - if (num_sent < 0) - { - weechat_printf (NULL, - _("%s%s: error sending data to client %s"), - weechat_prefix ("error"), RELAY_PLUGIN_NAME, - strerror (errno)); - } - - return total_sent; -} - -/* - * relay_client_weechat_send_infolist: send infolist to client - */ - -void -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_client_weechat_sendf (client, "name %s", name); - - while (weechat_infolist_next (infolist)) - { - fields = weechat_infolist_fields (infolist); - if (fields) - { - argv = weechat_string_split (fields, ",", 0, 0, &argc); - if (argv && (argc > 0)) - { - for (i = 0; i < argc; i++) - { - switch (argv[i][0]) - { - case 'i': - 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_client_weechat_sendf (client, "%s %c %s", - argv[i] + 2, argv[i][0], - weechat_infolist_string (infolist, - argv[i] + 2)); - break; - case 'p': - 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_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_client_weechat_sendf (client, "%s %c %ld", - argv[i] + 2, argv[i][0], - weechat_infolist_time (infolist, argv[i] + 2)); - break; - } - } - } - if (argv) - weechat_string_free_split (argv); - } - } -} - -/* - * relay_client_weechat_recv_one_msg: read one message from client - */ - -void -relay_client_weechat_recv_one_msg (struct t_relay_client *client, - const char *data) -{ - char *data2, *pos, **argv, **argv_eol, *args; - int argc, rc; - long unsigned int value; - const char *info; - struct t_infolist *infolist; - - data2 = NULL; - argv = NULL; - argv_eol = NULL; - - data2 = strdup (data); - if (!data2) - goto end; - pos = strchr (data2, '\r'); - if (pos) - pos[0] = '\0'; - pos = strchr (data2, '\n'); - if (pos) - pos[0] = '\0'; - - if (weechat_relay_plugin->debug) - { - weechat_printf (NULL, "relay: weechat: \"%s\"", data2); - } - - argv = weechat_string_split (data2, " ", 0, 0, &argc); - argv_eol = weechat_string_split (data2, " ", 1, 0, NULL); - if (argv && argv_eol && (argc >= 1)) - { - if (!RELAY_WEECHAT_DATA(client, password_ok)) - { - if ((argc > 1) - && (strcmp (argv[0], "password") == 0) - && (strcmp (weechat_config_string (relay_config_network_password), - argv_eol[1]) == 0)) - { - RELAY_WEECHAT_DATA(client, password_ok) = 1; - } - } - - if (!RELAY_WEECHAT_DATA(client, password_ok)) - { - relay_client_set_status (client, - RELAY_STATUS_DISCONNECTED); - goto end; - } - - if (strcmp (argv[0], "quit") == 0) - { - relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); - } - else if (strcmp (argv[0], "info") == 0) - { - if (argc > 1) - { - info = weechat_info_get (argv[1], - (argc > 2) ? argv_eol[2] : NULL); - relay_client_weechat_sendf (client, "%s", info); - } - } - else if (strcmp (argv[0], "infolist") == 0) - { - if (argc > 1) - { - value = 0; - args = NULL; - if (argc > 2) - { - rc = sscanf (argv[2], "%lx", &value); - if ((rc == EOF) || (rc == 0)) - value = 0; - if (argc > 3) - args = argv_eol[3]; - } - infolist = weechat_infolist_get (argv[1], (void *)value, args); - if (infolist) - { - relay_client_weechat_send_infolist (client, data, infolist); - weechat_infolist_free (infolist); - } - } - } - } - -end: - if (data2) - free (data2); - if (argv) - weechat_string_free_split (argv); - if (argv_eol) - weechat_string_free_split (argv_eol); -} - -/* - * relay_client_weechat_recv: read data from client - */ - -void -relay_client_weechat_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_weechat_recv_one_msg (client, items[i]); - } - if (items) - weechat_string_free_split (items); -} - -/* - * relay_client_weechat_alloc: init relay data specific to weechat protocol - */ - -void -relay_client_weechat_alloc (struct t_relay_client *client) -{ - struct t_relay_client_weechat_data *weechat_data; - const char *password; - - password = weechat_config_string (relay_config_network_password); - - client->protocol_data = malloc (sizeof (*weechat_data)); - if (client->protocol_data) - { - RELAY_WEECHAT_DATA(client, password_ok) = (password && password[0]) ? 0 : 1; - } -} - -/* - * relay_client_weechat_alloc_with_infolist: init relay data specific to - * weechat protocol with an infolist - */ - -void -relay_client_weechat_alloc_with_infolist (struct t_relay_client *client, - struct t_infolist *infolist) -{ - struct t_relay_client_weechat_data *weechat_data; - - /* make C compiler happy */ - (void) infolist; - - client->protocol_data = malloc (sizeof (*weechat_data)); - if (client->protocol_data) - { - /* ... */ - } -} - -/* - * relay_client_weechat_free: free relay data specific to weechat protocol - */ - -void -relay_client_weechat_free (struct t_relay_client *client) -{ - if (client->protocol_data) - free (client->protocol_data); -} - -/* - * relay_client_weechat_add_to_infolist: add client weechat data in an - * infolist item - * return 1 if ok, 0 if error - */ - -int -relay_client_weechat_add_to_infolist (struct t_infolist_item *item, - struct t_relay_client *client) -{ - if (!item || !client) - return 0; - - return 1; -} - -/* - * relay_client_weechat_print_log: print weechat client infos in log (usually - * for crash dump) - */ - -void -relay_client_weechat_print_log (struct t_relay_client *client) -{ - if (client->protocol_data) - { - } -} diff --git a/src/plugins/relay/relay-client-weechat.h b/src/plugins/relay/relay-client-weechat.h deleted file mode 100644 index 7f7ca9254..000000000 --- a/src/plugins/relay/relay-client-weechat.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2003-2011 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_CLIENT_WEECHAT_H -#define __WEECHAT_RELAY_CLIENT_WEECHAT_H 1 - -struct t_relay_client; - -#define RELAY_WEECHAT_DATA(client, var) \ - (((struct t_relay_client_weechat_data *)client->protocol_data)->var) - -struct t_relay_client_weechat_data -{ - int password_ok; /* password received and ok? */ -}; - -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_alloc_with_infolist (struct t_relay_client *client, - struct t_infolist *infolist); -extern void relay_client_weechat_free (struct t_relay_client *client); -extern int relay_client_weechat_add_to_infolist (struct t_infolist_item *item, - struct t_relay_client *client); -extern void relay_client_weechat_print_log (struct t_relay_client *client); - -#endif /* __WEECHAT_RELAY_CLIENT_WEECHAT_H */ diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c index f82821048..f763e8fa8 100644 --- a/src/plugins/relay/relay-client.c +++ b/src/plugins/relay/relay-client.c @@ -34,8 +34,8 @@ #include "../weechat-plugin.h" #include "relay.h" #include "relay-client.h" -#include "relay-client-irc.h" -#include "relay-client-weechat.h" +#include "irc/relay-irc.h" +#include "weechat/relay-weechat.h" #include "relay-config.h" #include "relay-buffer.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_client_weechat_recv (client, buffer); + relay_weechat_recv (client, buffer); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_recv (client, buffer); + relay_irc_recv (client, buffer); break; case RELAY_NUM_PROTOCOLS: break; @@ -146,7 +146,7 @@ relay_client_recv_cb (void *arg_client, int fd) */ struct t_relay_client * -relay_client_new (int sock, char *address, struct t_relay_server *server) +relay_client_new (int sock, const char *address, struct t_relay_server *server) { struct t_relay_client *new_client; @@ -171,10 +171,10 @@ relay_client_new (int sock, char *address, struct t_relay_server *server) switch (new_client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_client_weechat_alloc (new_client); + relay_weechat_alloc (new_client); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_alloc (new_client); + relay_irc_alloc (new_client); break; case RELAY_NUM_PROTOCOLS: break; @@ -234,7 +234,7 @@ relay_client_set_status (struct t_relay_client *client, { client->status = status; - if (RELAY_CLIENT_HAS_ENDED(client->status)) + if (RELAY_CLIENT_HAS_ENDED(client)) { client->end_time = time (NULL); @@ -246,9 +246,10 @@ relay_client_set_status (struct t_relay_client *client, switch (client->protocol) { case RELAY_PROTOCOL_WEECHAT: + relay_weechat_close_connection (client); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_close_connection (client); + relay_irc_close_connection (client); break; case RELAY_NUM_PROTOCOLS: break; @@ -327,10 +328,10 @@ relay_client_free (struct t_relay_client *client) switch (client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_client_weechat_free (client); + relay_weechat_free (client); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_free (client); + relay_irc_free (client); break; case RELAY_NUM_PROTOCOLS: break; @@ -446,10 +447,10 @@ relay_client_add_to_infolist (struct t_infolist *infolist, switch (client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_client_weechat_add_to_infolist (ptr_item, client); + relay_weechat_add_to_infolist (ptr_item, client); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_add_to_infolist (ptr_item, client); + relay_irc_add_to_infolist (ptr_item, client); break; case RELAY_NUM_PROTOCOLS: break; @@ -493,10 +494,10 @@ relay_client_print_log () switch (ptr_client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_client_weechat_print_log (ptr_client); + relay_weechat_print_log (ptr_client); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_print_log (ptr_client); + relay_irc_print_log (ptr_client); break; case RELAY_NUM_PROTOCOLS: break; diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h index ffaaf74a0..031ea43c2 100644 --- a/src/plugins/relay/relay-client.h +++ b/src/plugins/relay/relay-client.h @@ -37,8 +37,9 @@ enum t_relay_status /* macros for status */ -#define RELAY_CLIENT_HAS_ENDED(status) ((status == RELAY_STATUS_AUTH_FAILED) || \ - (status == RELAY_STATUS_DISCONNECTED)) +#define RELAY_CLIENT_HAS_ENDED(client) \ + ((client->status == RELAY_STATUS_AUTH_FAILED) || \ + (client->status == RELAY_STATUS_DISCONNECTED)) /* relay client */ @@ -71,7 +72,7 @@ extern int relay_client_count; extern int relay_client_valid (struct t_relay_client *client); extern struct t_relay_client *relay_client_search_by_number (int number); extern int relay_client_recv_cb (void *arg_client, int fd); -extern struct t_relay_client *relay_client_new (int sock, char *address, +extern struct t_relay_client *relay_client_new (int sock, const char *address, struct t_relay_server *server); extern void relay_client_set_status (struct t_relay_client *client, enum t_relay_status status); diff --git a/src/plugins/relay/relay-command.c b/src/plugins/relay/relay-command.c index b1741f228..5748a0913 100644 --- a/src/plugins/relay/relay-command.c +++ b/src/plugins/relay/relay-command.c @@ -90,7 +90,7 @@ relay_command_client_list (int full) } else { - if (!RELAY_CLIENT_HAS_ENDED(ptr_client->status)) + if (!RELAY_CLIENT_HAS_ENDED(ptr_client)) { weechat_printf (NULL, _(" id: %d, %s%s%s, started on: %s"), diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c index c36c3b04a..131b20c92 100644 --- a/src/plugins/relay/relay-config.c +++ b/src/plugins/relay/relay-config.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <limits.h> +#include <regex.h> #include "../weechat-plugin.h" #include "relay.h" @@ -49,10 +50,16 @@ struct t_config_option *relay_config_color_status[RELAY_NUM_STATUS]; /* relay config, network section */ +struct t_config_option *relay_config_network_allowed_ips; struct t_config_option *relay_config_network_bind_address; +struct t_config_option *relay_config_network_compression_level; struct t_config_option *relay_config_network_max_clients; struct t_config_option *relay_config_network_password; +/* other */ + +regex_t *relay_config_regex_allowed_ips = NULL; + /* * relay_config_refresh_cb: callback called when user changes relay option that @@ -71,6 +78,42 @@ relay_config_refresh_cb (void *data, struct t_config_option *option) } /* + * relay_config_change_network_allowed_ips: called when allowed ips changes + */ + +void +relay_config_change_network_allowed_ips (void *data, + struct t_config_option *option) +{ + const char *allowed_ips; + + /* make C compiler happy */ + (void) data; + (void) option; + + if (relay_config_regex_allowed_ips) + { + regfree (relay_config_regex_allowed_ips); + free (relay_config_regex_allowed_ips); + relay_config_regex_allowed_ips = NULL; + } + + allowed_ips = weechat_config_string (relay_config_network_allowed_ips); + if (allowed_ips && allowed_ips[0]) + { + relay_config_regex_allowed_ips = malloc (sizeof (*relay_config_regex_allowed_ips)); + if (relay_config_regex_allowed_ips) + { + if (regcomp (relay_config_regex_allowed_ips, allowed_ips, REG_EXTENDED) != 0) + { + free (relay_config_regex_allowed_ips); + relay_config_regex_allowed_ips = NULL; + } + } + } +} + +/* * relay_config_change_network_bind_address_cb: callback called when user changes * network bind address option */ @@ -370,6 +413,13 @@ relay_config_init () return 0; } + relay_config_network_allowed_ips = weechat_config_new_option ( + relay_config_file, ptr_section, + "allowed_ips", "string", + N_("regular expression with IPs allowed to use relay, example: " + "\"^(123.45.67.89|192.160.*)$\""), + NULL, 0, 0, "", NULL, 0, NULL, NULL, + &relay_config_change_network_allowed_ips, NULL, NULL, NULL); relay_config_network_bind_address = weechat_config_new_option ( relay_config_file, ptr_section, "bind_address", "string", @@ -378,6 +428,14 @@ relay_config_init () "local machine only)"), NULL, 0, 0, "", NULL, 0, NULL, NULL, &relay_config_change_network_bind_address_cb, NULL, NULL, NULL); + relay_config_network_compression_level = weechat_config_new_option ( + relay_config_file, ptr_section, + "compression_level", "integer", + N_("compression level for packets sent to client with WeeChat protocol " + "(0 = disable compression, 1 = low compression ... 9 = best " + "compression)"), + NULL, 0, 9, "6", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL); relay_config_network_max_clients = weechat_config_new_option ( relay_config_file, ptr_section, "max_clients", "integer", diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h index fabd7c574..035acd8ef 100644 --- a/src/plugins/relay/relay-config.h +++ b/src/plugins/relay/relay-config.h @@ -20,6 +20,8 @@ #ifndef __WEECHAT_RELAY_CONFIG_H #define __WEECHAT_RELAY_CONFIG_H 1 +#include <regex.h> + #define RELAY_CONFIG_NAME "relay" extern struct t_config_file *relay_config_file; @@ -36,6 +38,9 @@ extern struct t_config_option *relay_config_color_status[]; extern struct t_config_option *relay_config_network_bind_address; extern struct t_config_option *relay_config_network_max_clients; extern struct t_config_option *relay_config_network_password; +extern struct t_config_option *relay_config_network_compression_level; + +extern regex_t *relay_config_regex_allowed_ips; extern int relay_config_create_option_port (void *data, struct t_config_file *config_file, diff --git a/src/plugins/relay/relay-raw.c b/src/plugins/relay/relay-raw.c index 23f30ffcc..266b88beb 100644 --- a/src/plugins/relay/relay-raw.c +++ b/src/plugins/relay/relay-raw.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <stdio.h> +#include <stdarg.h> #include <string.h> #include <time.h> @@ -218,10 +219,10 @@ relay_raw_message_add_to_list (time_t date, const char *prefix, */ struct t_relay_raw_message * -relay_raw_message_add (struct t_relay_client *client, int send, +relay_raw_message_add (struct t_relay_client *client, int flags, const char *message) { - char *buf, *buf2, prefix[256]; + char *buf, *buf2, prefix[256], prefix_arrow[16]; const unsigned char *ptr_buf; const char *hexa = "0123456789ABCDEF"; int pos_buf, pos_buf2, char_size, i; @@ -255,27 +256,46 @@ relay_raw_message_add (struct t_relay_client *client, int send, buf2[pos_buf2] = '\0'; } + /* build prefix with arrow */ + prefix_arrow[0] = '\0'; + switch (flags & (RELAY_RAW_FLAG_RECV | RELAY_RAW_FLAG_SEND)) + { + case RELAY_RAW_FLAG_RECV: + strcpy (prefix_arrow, RELAY_RAW_PREFIX_RECV); + break; + case RELAY_RAW_FLAG_SEND: + strcpy (prefix_arrow, RELAY_RAW_PREFIX_SEND); + break; + default: + if (flags & RELAY_RAW_FLAG_RECV) + strcpy (prefix_arrow, RELAY_RAW_PREFIX_RECV); + else + strcpy (prefix_arrow, RELAY_RAW_PREFIX_SEND); + break; + } + if (client) { - snprintf (prefix, sizeof (prefix), "%s[%s%d%s] %s%s %s%s", + snprintf (prefix, sizeof (prefix), "%s[%s%d%s] %s%s.%s %s%s", weechat_color ("chat_delimiters"), weechat_color ("chat"), client->id, weechat_color ("chat_delimiters"), weechat_color ("chat_server"), + relay_protocol_string[client->protocol], client->protocol_args, - (send) ? + (flags & RELAY_RAW_FLAG_SEND) ? weechat_color ("chat_prefix_quit") : weechat_color ("chat_prefix_join"), - (send) ? RELAY_RAW_PREFIX_SEND : RELAY_RAW_PREFIX_RECV); + prefix_arrow); } else { snprintf (prefix, sizeof (prefix), "%s%s", - (send) ? + (flags & RELAY_RAW_FLAG_SEND) ? weechat_color ("chat_prefix_quit") : weechat_color ("chat_prefix_join"), - (send) ? RELAY_RAW_PREFIX_SEND : RELAY_RAW_PREFIX_RECV); + prefix_arrow); } new_raw_message = relay_raw_message_add_to_list (time (NULL), @@ -295,18 +315,20 @@ relay_raw_message_add (struct t_relay_client *client, int send, */ void -relay_raw_print (struct t_relay_client *client, int send, const char *message) +relay_raw_print (struct t_relay_client *client, int flags, + const char *format, ...) { struct t_relay_raw_message *new_raw_message; - if (!message) + weechat_va_format (format); + if (!vbuffer) 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); + new_raw_message = relay_raw_message_add (client, flags, vbuffer); if (new_raw_message) { if (relay_raw_buffer) @@ -314,6 +336,8 @@ relay_raw_print (struct t_relay_client *client, int send, const char *message) if (weechat_config_integer (relay_config_look_raw_messages) == 0) relay_raw_message_free (new_raw_message); } + + free (vbuffer); } /* diff --git a/src/plugins/relay/relay-raw.h b/src/plugins/relay/relay-raw.h index 1cfc93932..a50a98670 100644 --- a/src/plugins/relay/relay-raw.h +++ b/src/plugins/relay/relay-raw.h @@ -24,6 +24,9 @@ #define RELAY_RAW_PREFIX_RECV "-->" #define RELAY_RAW_PREFIX_SEND "<--" +#define RELAY_RAW_FLAG_RECV 1 +#define RELAY_RAW_FLAG_SEND 2 + struct t_relay_raw_message { time_t date; /* date/time of message */ @@ -43,8 +46,8 @@ 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_print (struct t_relay_client *client, int flags, + const char *format, ...); 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); diff --git a/src/plugins/relay/relay-server.c b/src/plugins/relay/relay-server.c index 7a361b389..4f94745c7 100644 --- a/src/plugins/relay/relay-server.c +++ b/src/plugins/relay/relay-server.c @@ -199,6 +199,22 @@ relay_server_sock_cb (void *data, int fd) ptr_address = ipv4_address; } + /* check if IP is allowed, if not, just close socket */ + if (relay_config_regex_allowed_ips + && (regexec (relay_config_regex_allowed_ips, ptr_address, 0, NULL, 0) != 0)) + { + if (weechat_relay_plugin->debug >= 2) + { + weechat_printf (NULL, + _("%s%s: IP address \"%s\" not allowed for relay"), + weechat_prefix ("error"), + RELAY_PLUGIN_NAME, + ptr_address); + } + close (client_fd); + return WEECHAT_RC_OK; + } + relay_client_new (client_fd, ptr_address, server); return WEECHAT_RC_OK; diff --git a/src/plugins/relay/relay-upgrade.c b/src/plugins/relay/relay-upgrade.c index ac1062209..f7d701faf 100644 --- a/src/plugins/relay/relay-upgrade.c +++ b/src/plugins/relay/relay-upgrade.c @@ -30,8 +30,8 @@ #include "relay-upgrade.h" #include "relay-buffer.h" #include "relay-client.h" -#include "relay-client-irc.h" -#include "relay-client-weechat.h" +#include "irc/relay-irc.h" +#include "weechat/relay-weechat.h" #include "relay-raw.h" @@ -201,12 +201,12 @@ relay_upgrade_read_cb (void *data, switch (new_client->protocol) { case RELAY_PROTOCOL_WEECHAT: - relay_client_weechat_alloc_with_infolist (new_client, - infolist); + relay_weechat_alloc_with_infolist (new_client, + infolist); break; case RELAY_PROTOCOL_IRC: - relay_client_irc_alloc_with_infolist (new_client, - infolist); + relay_irc_alloc_with_infolist (new_client, + infolist); break; case RELAY_NUM_PROTOCOLS: break; diff --git a/src/plugins/relay/relay.c b/src/plugins/relay/relay.c index 7b9cc787a..e140056ec 100644 --- a/src/plugins/relay/relay.c +++ b/src/plugins/relay/relay.c @@ -63,9 +63,7 @@ relay_protocol_search (const char *name) for (i = 0; i < RELAY_NUM_PROTOCOLS; i++) { if (weechat_strcasecmp (relay_protocol_string[i], name) == 0) - { return i; - } } /* protocol not found */ diff --git a/src/plugins/relay/weechat/relay-weechat-msg.c b/src/plugins/relay/weechat/relay-weechat-msg.c new file mode 100644 index 000000000..188e1809e --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat-msg.c @@ -0,0 +1,963 @@ +/* + * Copyright (C) 2003-2011 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-weechat-msg.c: build binary messages for WeeChat protocol + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <errno.h> +#include <arpa/inet.h> + +#ifdef HAVE_ZLIB +#include <zlib.h> +#endif + +#include "../../weechat-plugin.h" +#include "../relay.h" +#include "relay-weechat.h" +#include "relay-weechat-msg.h" +#include "../relay-client.h" +#include "../relay-config.h" +#include "../relay-raw.h" + + +/* + * relay_weechat_msg_new: build a new message (for sending to client) + */ + +struct t_relay_weechat_msg * +relay_weechat_msg_new (const char *id) +{ + struct t_relay_weechat_msg *new_msg; + + new_msg = malloc (sizeof (*new_msg)); + if (!new_msg) + return NULL; + + new_msg->id = (id) ? strdup (id) : NULL; + new_msg->data = malloc (RELAY_WEECHAT_MSG_INITIAL_ALLOC); + if (!new_msg->data) + { + free (new_msg); + return NULL; + } + new_msg->data_alloc = RELAY_WEECHAT_MSG_INITIAL_ALLOC; + new_msg->data_size = 0; + + /* add size and compression flag (they will be set later) */ + relay_weechat_msg_add_int (new_msg, 0); + relay_weechat_msg_add_char (new_msg, 0); + + /* add id */ + relay_weechat_msg_add_string (new_msg, id); + + return new_msg; +} + +/* + * relay_weechat_msg_add_bytes: add some bytes to a message + */ + +void +relay_weechat_msg_add_bytes (struct t_relay_weechat_msg *msg, + const void *buffer, int size) +{ + char *ptr; + + if (!msg || !msg->data) + return; + + while (msg->data_size + size > msg->data_alloc) + { + msg->data_alloc *= 2; + ptr = realloc (msg->data, msg->data_alloc); + if (!ptr) + { + free (msg->data); + msg->data = NULL; + msg->data_alloc = 0; + msg->data_size = 0; + return; + } + msg->data = ptr; + } + + memcpy (msg->data + msg->data_size, buffer, size); + msg->data_size += size; +} + +/* + * relay_weechat_msg_set_bytes: set some bytes in a message + */ + +void +relay_weechat_msg_set_bytes (struct t_relay_weechat_msg *msg, + int position, const void *buffer, int size) +{ + if (!msg || !msg->data || (position + size) > msg->data_size) + return; + + memcpy (msg->data + position, buffer, size); +} + +/* + * relay_weechat_msg_add_type: add type to a message + */ + +void +relay_weechat_msg_add_type (struct t_relay_weechat_msg *msg, const char *string) +{ + if (string) + relay_weechat_msg_add_bytes (msg, string, strlen (string)); +} + +/* + * relay_weechat_msg_add_char: add a char to a message + */ + +void +relay_weechat_msg_add_char (struct t_relay_weechat_msg *msg, char c) +{ + relay_weechat_msg_add_bytes (msg, &c, 1); +} + +/* + * relay_weechat_msg_add_int: add an integer to a message + */ + +void +relay_weechat_msg_add_int (struct t_relay_weechat_msg *msg, int value) +{ + uint32_t value32; + + value32 = htonl ((uint32_t)value); + relay_weechat_msg_add_bytes (msg, &value32, 4); +} + +/* + * relay_weechat_msg_add_long: add a long integer to a message + */ + +void +relay_weechat_msg_add_long (struct t_relay_weechat_msg *msg, long value) +{ + char str_long[128]; + unsigned char length; + + snprintf (str_long, sizeof (str_long), "%ld", value); + length = strlen (str_long); + relay_weechat_msg_add_bytes (msg, &length, 1); + relay_weechat_msg_add_bytes (msg, str_long, length); +} + +/* + * relay_weechat_msg_add_string: add length + string to a message + */ + +void +relay_weechat_msg_add_string (struct t_relay_weechat_msg *msg, + const char *string) +{ + int length; + + if (string) + { + length = strlen (string); + relay_weechat_msg_add_int (msg, length); + if (length > 0) + relay_weechat_msg_add_bytes (msg, string, length); + } + else + { + relay_weechat_msg_add_int (msg, -1); + } +} + +/* + * relay_weechat_msg_add_buffer: add buffer (length + data) to a message + */ + +void +relay_weechat_msg_add_buffer (struct t_relay_weechat_msg *msg, + void *buffer, int length) +{ + if (buffer) + { + relay_weechat_msg_add_int (msg, length); + if (length > 0) + relay_weechat_msg_add_bytes (msg, buffer, length); + } + else + { + relay_weechat_msg_add_int (msg, -1); + } +} + +/* + * relay_weechat_msg_add_pointer: add a pointer to a message + */ + +void +relay_weechat_msg_add_pointer (struct t_relay_weechat_msg *msg, void *pointer) +{ + char str_pointer[128]; + unsigned char length; + + snprintf (str_pointer, sizeof (str_pointer), + "%lx", (long unsigned int)pointer); + length = strlen (str_pointer); + relay_weechat_msg_add_bytes (msg, &length, 1); + relay_weechat_msg_add_bytes (msg, str_pointer, length); +} + +/* + * relay_weechat_msg_add_time: add a time to a message + */ + +void +relay_weechat_msg_add_time (struct t_relay_weechat_msg *msg, time_t time) +{ + char str_time[128]; + unsigned char length; + + snprintf (str_time, sizeof (str_time), "%ld", time); + length = strlen (str_time); + relay_weechat_msg_add_bytes (msg, &length, 1); + relay_weechat_msg_add_bytes (msg, str_time, length); +} + +/* + * relay_weechat_msg_add_hdata_path: recursively add hdata for a path + * return number of hdata objects added in + * message + */ + +int +relay_weechat_msg_add_hdata_path (struct t_relay_weechat_msg *msg, + char **list_path, + int index_path, + void **path_pointers, + struct t_hdata *hdata, + void *pointer, + char **list_keys) +{ + int num_added, i, count, count_all, type; + char *pos, *pos2, *str_count, *error; + void *sub_pointer; + struct t_hdata *sub_hdata; + const char *sub_hdata_name; + + num_added = 0; + + count_all = 0; + count = 0; + pos = strchr (list_path[index_path], '('); + if (pos) + { + pos2 = strchr (pos + 1, ')'); + if (pos2 && (pos2 > pos + 1)) + { + str_count = weechat_strndup (pos + 1, pos2 - (pos + 1)); + if (str_count) + { + if (strcmp (str_count, "*") == 0) + count_all = 1; + else + { + error = NULL; + count = (int)strtol (str_count, &error, 10); + if (error && !error[0]) + { + if (count > 0) + count--; + else if (count < 0) + count++; + } + else + count = 0; + } + free (str_count); + } + } + } + + while (pointer) + { + path_pointers[index_path] = pointer; + + if (list_path[index_path + 1]) + { + /* recursive call with next path */ + pos = strchr (list_path[index_path + 1], '('); + if (pos) + pos[0] = '\0'; + sub_pointer = weechat_hdata_pointer (hdata, pointer, list_path[index_path + 1]); + sub_hdata_name = weechat_hdata_get_var_hdata (hdata, list_path[index_path + 1]); + if (pos) + pos[0] = '('; + if (sub_pointer && sub_hdata_name) + { + sub_hdata = weechat_hdata_get (sub_hdata_name); + if (sub_hdata) + { + num_added += relay_weechat_msg_add_hdata_path (msg, + list_path, + index_path + 1, + path_pointers, + sub_hdata, + sub_pointer, + list_keys); + } + } + } + else + { + /* last path? then get pointer + values and fill message with them */ + for (i = 0; list_path[i]; i++) + { + relay_weechat_msg_add_pointer (msg, path_pointers[i]); + } + for (i = 0; list_keys[i]; i++) + { + type = weechat_hdata_get_var_type (hdata, list_keys[i]); + if ((type >= 0) && (type != WEECHAT_HDATA_OTHER)) + { + switch (type) + { + case WEECHAT_HDATA_CHAR: + relay_weechat_msg_add_char (msg, + weechat_hdata_char (hdata, + pointer, + list_keys[i])); + break; + case WEECHAT_HDATA_INTEGER: + relay_weechat_msg_add_int (msg, + weechat_hdata_integer (hdata, + pointer, + list_keys[i])); + break; + case WEECHAT_HDATA_LONG: + relay_weechat_msg_add_long (msg, + weechat_hdata_long (hdata, + pointer, + list_keys[i])); + break; + case WEECHAT_HDATA_STRING: + relay_weechat_msg_add_string (msg, + weechat_hdata_string (hdata, + pointer, + list_keys[i])); + break; + case WEECHAT_HDATA_POINTER: + relay_weechat_msg_add_pointer (msg, + weechat_hdata_pointer (hdata, + pointer, + list_keys[i])); + break; + case WEECHAT_HDATA_TIME: + relay_weechat_msg_add_time (msg, + weechat_hdata_time (hdata, + pointer, + list_keys[i])); + break; + } + } + } + num_added++; + } + if (count_all) + { + pointer = weechat_hdata_move (hdata, pointer, 1); + } + else if (count == 0) + pointer = NULL; + else if (count > 0) + { + pointer = weechat_hdata_move (hdata, pointer, 1); + count--; + } + else + { + pointer = weechat_hdata_move (hdata, pointer, -1); + count++; + } + if (!pointer) + break; + } + + return num_added; +} + +/* + * relay_weechat_msg_add_hdata: add a hdata to a message + * path has format: + * hdata_head:ptr->var->var->...->var + * where ptr can be a list name or a + * pointer (0x12345) + * keys is optional: if not NULL, + * comma-separated list of keys to return + * for hdata + */ + +void +relay_weechat_msg_add_hdata (struct t_relay_weechat_msg *msg, + const char *path, const char *keys) +{ + struct t_hdata *ptr_hdata_head, *ptr_hdata; + char *hdata_head, *pos, **list_keys, *keys_types, **list_path; + char *path_returned; + const char *hdata_name; + void *pointer, **path_pointers; + long unsigned int value; + int num_keys, num_path, i, type, pos_count, count, rc; + uint32_t count32; + + hdata_head = NULL; + list_keys = NULL; + num_keys = 0; + keys_types = NULL; + list_path = NULL; + num_path = 0; + path_returned = NULL; + + /* extract hdata name (head) from path */ + pos = strchr (path, ':'); + if (!pos) + goto end; + hdata_head = weechat_strndup (path, pos - path); + if (!hdata_head) + goto end; + ptr_hdata_head = weechat_hdata_get (hdata_head); + if (!ptr_hdata_head) + goto end; + + /* split path */ + list_path = weechat_string_split (pos + 1, "/", 0, 0, &num_path); + if (!list_path) + goto end; + + /* extract pointer from first path (direct pointer or list name) */ + pointer = NULL; + pos = strchr (list_path[0], '('); + if (pos) + pos[0] = '\0'; + if (strncmp (list_path[0], "0x", 2) == 0) + { + rc = sscanf (list_path[0], "%lx", &value); + if ((rc != EOF) && (rc != 0)) + pointer = (void *)value; + } + else + pointer = weechat_hdata_get_list (ptr_hdata_head, list_path[0]); + if (pos) + pos[0] = '('; + if (!pointer) + goto end; + + /* + * build string with path where: + * - counters are removed + * - variable names are replaced by hdata name + */ + path_returned = malloc (strlen (path) * 2); + if (!path_returned) + goto end; + ptr_hdata = ptr_hdata_head; + strcpy (path_returned, hdata_head); + hdata_name = hdata_head; + for (i = 1; i < num_path; i++) + { + pos = strchr (list_path[i], '('); + if (pos) + pos[0] = '\0'; + hdata_name = weechat_hdata_get_var_hdata (ptr_hdata, list_path[i]); + if (!hdata_name) + goto end; + ptr_hdata = weechat_hdata_get (hdata_name); + if (!ptr_hdata) + goto end; + strcat (path_returned, "/"); + strcat (path_returned, hdata_name); + if (pos) + pos[0] = '('; + } + + /* split keys */ + if (!keys) + keys = weechat_hdata_get_string (ptr_hdata, "var_keys"); + list_keys = weechat_string_split (keys, ",", 0, 0, &num_keys); + if (!list_keys) + goto end; + + /* build string with list of keys with types: "key1:type1,key2:type2,..." */ + keys_types = malloc (strlen (keys) + (num_keys * 8) + 1); + if (!keys_types) + goto end; + keys_types[0] = '\0'; + for (i = 0; i < num_keys; i++) + { + type = weechat_hdata_get_var_type (ptr_hdata, list_keys[i]); + if ((type >= 0) && (type != WEECHAT_HDATA_OTHER)) + { + if (keys_types[0]) + strcat (keys_types, ","); + strcat (keys_types, list_keys[i]); + strcat (keys_types, ":"); + switch (type) + { + case WEECHAT_HDATA_CHAR: + strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_CHAR); + break; + case WEECHAT_HDATA_INTEGER: + strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_INT); + break; + case WEECHAT_HDATA_LONG: + strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_LONG); + break; + case WEECHAT_HDATA_STRING: + strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_STRING); + break; + case WEECHAT_HDATA_POINTER: + strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_POINTER); + break; + case WEECHAT_HDATA_TIME: + strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_TIME); + break; + } + } + } + if (!keys_types[0]) + goto end; + + /* start hdata in message */ + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA); + relay_weechat_msg_add_string (msg, path_returned); + relay_weechat_msg_add_string (msg, keys_types); + + /* "count" will be set later, with number of objects in hdata */ + pos_count = msg->data_size; + count = 0; + relay_weechat_msg_add_int (msg, 0); + path_pointers = malloc (sizeof (*path_pointers) * num_path); + if (path_pointers) + { + count = relay_weechat_msg_add_hdata_path (msg, + list_path, + 0, + path_pointers, + ptr_hdata_head, + pointer, + list_keys); + } + count32 = htonl ((uint32_t)count); + relay_weechat_msg_set_bytes (msg, pos_count, &count32, 4); + +end: + if (list_keys) + weechat_string_free_split (list_keys); + if (keys_types) + free (keys_types); + if (list_path) + weechat_string_free_split (list_path); + if (path_returned) + free (path_returned); + if (hdata_head) + free (hdata_head); +} + +/* + * relay_weechat_msg_add_infolist: add an infolist to a message + */ + +void +relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg, + const char *name, + void *pointer, + const char *arguments) +{ + struct t_infolist *infolist; + const char *fields; + char **list_fields; + void *buf_ptr; + int num_fields, i, buf_size; + int pos_count_items, count_items, pos_count_vars, count_vars; + uint32_t count32; + + infolist = weechat_infolist_get (name, pointer, arguments); + if (!infolist) + return; + + /* start infolist in message */ + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INFOLIST); + relay_weechat_msg_add_string (msg, name); + + /* count of items will be set later, with number of items in infolist */ + pos_count_items = msg->data_size; + count_items = 0; + relay_weechat_msg_add_int (msg, 0); + + while (weechat_infolist_next (infolist)) + { + fields = weechat_infolist_fields (infolist); + if (fields) + { + list_fields = weechat_string_split (fields, ",", 0, 0, &num_fields); + if (list_fields) + { + count_items++; + pos_count_vars = msg->data_size; + count_vars = 0; + relay_weechat_msg_add_int (msg, 0); + for (i = 0; i < num_fields; i++) + { + if (strlen (list_fields[i]) > 2) + { + count_vars++; + relay_weechat_msg_add_string (msg, list_fields[i] + 2); + switch (list_fields[i][0]) + { + case 'i': + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INT); + relay_weechat_msg_add_int (msg, + weechat_infolist_integer (infolist, + list_fields[i] + 2)); + break; + case 's': + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING); + relay_weechat_msg_add_string (msg, + weechat_infolist_string (infolist, + list_fields[i] + 2)); + break; + case 'p': + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_POINTER); + relay_weechat_msg_add_pointer (msg, + weechat_infolist_pointer (infolist, + list_fields[i] + 2)); + break; + case 'b': + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_BUFFER); + buf_ptr = weechat_infolist_buffer (infolist, + list_fields[i] + 2, + &buf_size); + relay_weechat_msg_add_buffer (msg, buf_ptr, buf_size); + break; + case 't': + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_TIME); + relay_weechat_msg_add_time (msg, + weechat_infolist_time (infolist, + list_fields[i] + 2)); + break; + } + } + } + + /* set count of variables in item */ + count32 = htonl ((uint32_t)count_vars); + relay_weechat_msg_set_bytes (msg, pos_count_vars, &count32, 4); + + weechat_string_free_split (list_fields); + } + } + } + + /* set count of items */ + count32 = htonl ((uint32_t)count_items); + relay_weechat_msg_set_bytes (msg, pos_count_items, &count32, 4); + + weechat_infolist_free (infolist); +} + +/* + * relay_weechat_msg_add_nicklist_buffer: add nicklist for a buffer, as hdata + * object + * return number of nicks+groups added + * in message + */ + +int +relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg, + struct t_gui_buffer *buffer) +{ + int count; + struct t_hdata *ptr_hdata_group, *ptr_hdata_nick; + struct t_gui_nick_group *ptr_group; + struct t_gui_nick *ptr_nick; + + count = 0; + + ptr_hdata_group = weechat_hdata_get ("nick_group"); + ptr_hdata_nick = weechat_hdata_get ("nick"); + + ptr_group = NULL; + ptr_nick = NULL; + weechat_nicklist_get_next_item (buffer, &ptr_group, &ptr_nick); + while (ptr_group || ptr_nick) + { + if (ptr_nick) + { + relay_weechat_msg_add_pointer (msg, buffer); + relay_weechat_msg_add_pointer (msg, ptr_nick); + relay_weechat_msg_add_char (msg, 0); /* group */ + relay_weechat_msg_add_char (msg, + (char)weechat_hdata_integer(ptr_hdata_nick, + ptr_nick, + "visible")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "name")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "color")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "prefix")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "prefix_color")); + relay_weechat_msg_add_int (msg, + weechat_hdata_integer (ptr_hdata_nick, + ptr_nick, + "level")); + count++; + } + else + { + relay_weechat_msg_add_pointer (msg, buffer); + relay_weechat_msg_add_pointer (msg, ptr_group); + relay_weechat_msg_add_char (msg, 1); /* group */ + relay_weechat_msg_add_char (msg, + (char)weechat_hdata_integer(ptr_hdata_group, + ptr_group, + "visible")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_group, + ptr_group, + "name")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_group, + ptr_group, + "color")); + relay_weechat_msg_add_string (msg, NULL); /* prefix */ + relay_weechat_msg_add_string (msg, NULL); /* prefix_color */ + relay_weechat_msg_add_int (msg, + weechat_hdata_integer (ptr_hdata_group, + ptr_group, + "level")); + count++; + } + weechat_nicklist_get_next_item (buffer, &ptr_group, &ptr_nick); + } + + return count; +} + +/* + * relay_weechat_msg_add_nicklist: add nicklist for one or all buffers, as + * hdata object + */ + +void +relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg, + struct t_gui_buffer *buffer) +{ + struct t_hdata *ptr_hdata; + struct t_gui_buffer *ptr_buffer; + int pos_count, count; + uint32_t count32; + + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA); + relay_weechat_msg_add_string (msg, "buffer/nick_group"); + relay_weechat_msg_add_string (msg, + "group:chr,visible:chr,name:str,color:str," + "prefix:str,prefix_color:str,level:int"); + + /* "count" will be set later, with number of objects in hdata */ + pos_count = msg->data_size; + count = 0; + relay_weechat_msg_add_int (msg, 0); + + if (buffer) + count += relay_weechat_msg_add_nicklist_buffer (msg, buffer); + else + { + ptr_hdata = weechat_hdata_get ("buffer"); + ptr_buffer = weechat_hdata_get_list (ptr_hdata, "gui_buffers"); + while (ptr_buffer) + { + count += relay_weechat_msg_add_nicklist_buffer (msg, ptr_buffer); + ptr_buffer = weechat_hdata_move (ptr_hdata, ptr_buffer, 1); + } + } + + count32 = htonl ((uint32_t)count); + relay_weechat_msg_set_bytes (msg, pos_count, &count32, 4); +} + +/* + * relay_weechat_msg_send: send a message + */ + +void +relay_weechat_msg_send (struct t_relay_client *client, + struct t_relay_weechat_msg *msg) +{ + uint32_t size32; + char compression; +#ifdef HAVE_ZLIB + int rc, num_sent; + Bytef *dest; + uLongf dest_size; + struct timeval tv1, tv2; + long time_diff; + + if (RELAY_WEECHAT_DATA(client, compression) + && (weechat_config_integer (relay_config_network_compression_level) > 0)) + { + dest_size = compressBound (msg->data_size - 5); + dest = malloc (dest_size + 5); + if (dest) + { + gettimeofday (&tv1, NULL); + rc = compress2 (dest + 5, &dest_size, + (Bytef *)(msg->data + 5), msg->data_size - 5, + weechat_config_integer (relay_config_network_compression_level)); + gettimeofday (&tv2, NULL); + time_diff = weechat_util_timeval_diff (&tv1, &tv2); + if ((rc == Z_OK) && ((int)dest_size + 5 < msg->data_size)) + { + /* set size and compression flag */ + size32 = htonl ((uint32_t)(dest_size + 5)); + memcpy (dest, &size32, 4); + dest[4] = 1; + + /* send compressed data */ + num_sent = send (client->sock, dest, dest_size + 5, 0); + + /* display message in raw buffer */ + relay_raw_print (client, RELAY_RAW_FLAG_SEND, + "obj: %d/%d bytes (%d%%, %ldms), id: %s", + (int)dest_size + 5, + msg->data_size, + 100 - ((((int)dest_size + 5) * 100) / msg->data_size), + time_diff, + msg->id); + + if (num_sent < 0) + { + relay_raw_print (client, RELAY_RAW_FLAG_SEND, + "error: %s", strerror (errno)); + } + + free (dest); + return; + } + free (dest); + } + } +#endif + + /* set size and compression flag */ + size32 = htonl ((uint32_t)msg->data_size); + relay_weechat_msg_set_bytes (msg, 0, &size32, 4); + compression = 0; + relay_weechat_msg_set_bytes (msg, 4, &compression, 1); + + /* send uncompressed data */ + num_sent = send (client->sock, msg->data, msg->data_size, 0); + + /* display message in raw buffer */ + relay_raw_print (client, RELAY_RAW_FLAG_SEND, + "obj: %d bytes", msg->data_size); + + if (num_sent < 0) + { + relay_raw_print (client, RELAY_RAW_FLAG_SEND, + "error: %s", strerror (errno)); + } +} + +/* + * relay_weechat_msg_free: free a message + */ + +void +relay_weechat_msg_free (struct t_relay_weechat_msg *msg) +{ + if (msg->id) + free (msg->id); + if (msg->data) + free (msg->data); + + free (msg); +} + +/* + * relay_weechat_sendf: send formatted data to client + */ + +int +relay_weechat_sendf (struct t_relay_client *client, const char *format, ...) +{ + char str_length[8]; + int length_vbuffer, num_sent, total_sent; + + if (!client) + return 0; + + weechat_va_format (format); + if (!vbuffer) + return 0; + length_vbuffer = strlen (vbuffer); + + total_sent = 0; + + snprintf (str_length, sizeof (str_length), "%07d", length_vbuffer); + + num_sent = send (client->sock, str_length, 7, 0); + client->bytes_sent += 7; + total_sent += num_sent; + if (num_sent >= 0) + { + num_sent = send (client->sock, vbuffer, length_vbuffer, 0); + client->bytes_sent += length_vbuffer; + total_sent += num_sent; + } + + if (num_sent < 0) + { + weechat_printf (NULL, + _("%s%s: error sending data to client %d (%s)"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME, + client->id, strerror (errno)); + } + + return total_sent; +} diff --git a/src/plugins/relay/weechat/relay-weechat-msg.h b/src/plugins/relay/weechat/relay-weechat-msg.h new file mode 100644 index 000000000..044219969 --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat-msg.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003-2011 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_WEECHAT_MSG_H +#define __WEECHAT_RELAY_WEECHAT_MSG_H 1 + +#define RELAY_WEECHAT_MSG_INITIAL_ALLOC 4096 + +/* object ids in binary messages */ +#define RELAY_WEECHAT_MSG_OBJ_CHAR "chr" +#define RELAY_WEECHAT_MSG_OBJ_INT "int" +#define RELAY_WEECHAT_MSG_OBJ_LONG "lon" +#define RELAY_WEECHAT_MSG_OBJ_STRING "str" +#define RELAY_WEECHAT_MSG_OBJ_BUFFER "buf" +#define RELAY_WEECHAT_MSG_OBJ_POINTER "ptr" +#define RELAY_WEECHAT_MSG_OBJ_TIME "tim" +#define RELAY_WEECHAT_MSG_OBJ_HDATA "hda" +#define RELAY_WEECHAT_MSG_OBJ_INFO "inf" +#define RELAY_WEECHAT_MSG_OBJ_INFOLIST "lis" + +struct t_relay_weechat_msg +{ + char *id; /* message id */ + char *data; /* binary buffer */ + int data_alloc; /* currently allocated size */ + int data_size; /* current size of buffer */ +}; + +extern struct t_relay_weechat_msg *relay_weechat_msg_new (const char *id); +extern void relay_weechat_msg_add_bytes (struct t_relay_weechat_msg *msg, + const void *buffer, int size); +extern void relay_weechat_msg_set_bytes (struct t_relay_weechat_msg *msg, + int position, const void *buffer, + int size); +extern void relay_weechat_msg_add_type (struct t_relay_weechat_msg *msg, + const char *string); +extern void relay_weechat_msg_add_char (struct t_relay_weechat_msg *msg, + char c); +extern void relay_weechat_msg_add_int (struct t_relay_weechat_msg *msg, + int value); +extern void relay_weechat_msg_add_long (struct t_relay_weechat_msg *msg, + long value); +extern void relay_weechat_msg_add_string (struct t_relay_weechat_msg *msg, + const char *string); +extern void relay_weechat_msg_add_buffer (struct t_relay_weechat_msg *msg, + void *data, int length); +extern void relay_weechat_msg_add_pointer (struct t_relay_weechat_msg *msg, + void *pointer); +extern void relay_weechat_msg_add_time (struct t_relay_weechat_msg *msg, + time_t time); +extern void relay_weechat_msg_add_hdata1 (struct t_relay_weechat_msg *msg, + const char *name, const char *list, + const char *keys); +extern void relay_weechat_msg_add_hdata (struct t_relay_weechat_msg *msg, + const char *path, const char *keys); +extern void relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg, + const char *name, + void *pointer, + const char *arguments); +extern void relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg, + struct t_gui_buffer *buffer); +extern void relay_weechat_msg_send (struct t_relay_client *client, + struct t_relay_weechat_msg *msg); +extern void relay_weechat_msg_free (struct t_relay_weechat_msg *msg); + +#endif /* __WEECHAT_RELAY_WEECHAT_MSG_H */ diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.c b/src/plugins/relay/weechat/relay-weechat-protocol.c new file mode 100644 index 000000000..a0bf98231 --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat-protocol.c @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2003-2011 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-weechat-protocol.c: WeeChat protocol for relay to client + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../../weechat-plugin.h" +#include "../relay.h" +#include "relay-weechat.h" +#include "relay-weechat-protocol.h" +#include "relay-weechat-msg.h" +#include "../relay-client.h" +#include "../relay-config.h" +#include "../relay-raw.h" + + +/* + * relay_weechat_protocol_get_buffer: get buffer pointer with argument from a + * command, which can be a pointer + * ("0x12345") or a full name + * ("irc.freenode.#weechat") + */ + +struct t_gui_buffer * +relay_weechat_protocol_get_buffer (const char *arg) +{ + struct t_gui_buffer *ptr_buffer; + long unsigned int value; + int rc; + char *pos, *plugin; + + ptr_buffer = NULL; + + if (strncmp (arg, "0x", 2) == 0) + { + rc = sscanf (arg, "%lx", &value); + if ((rc != EOF) && (rc != 0)) + ptr_buffer = (void *)value; + } + else + { + pos = strchr (arg, '.'); + if (pos) + { + plugin = weechat_strndup (arg, pos - arg); + if (plugin) + { + ptr_buffer = weechat_buffer_search (plugin, pos + 1); + free (plugin); + } + } + } + + return ptr_buffer; +} + +/* + * relay_weechat_protocol_cb_init: 'init' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(init) +{ + char **options, *pos; + int num_options, i, compression; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(1); + + options = weechat_string_split (argv_eol[0], ",", 0, 0, &num_options); + if (options) + { + for (i = 0; i < num_options; i++) + { + pos = strchr (options[i], '='); + if (pos) + { + pos[0] = '\0'; + pos++; + if (strcmp (options[i], "password") == 0) + { + if (strcmp (weechat_config_string (relay_config_network_password), + pos) == 0) + { + RELAY_WEECHAT_DATA(client, password_ok) = 1; + } + } + else if (strcmp (options[i], "compression") == 0) + { + compression = relay_weechat_compression_search (pos); + if (compression >= 0) + RELAY_WEECHAT_DATA(client, compression) = compression; + } + } + } + weechat_string_free_split (options); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_hdata: 'hdata' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(hdata) +{ + struct t_relay_weechat_msg *msg; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(1); + + msg = relay_weechat_msg_new (id); + if (msg) + { + relay_weechat_msg_add_hdata (msg, argv[0], + (argc > 1) ? argv_eol[1] : NULL); + relay_weechat_msg_send (client, msg); + relay_weechat_msg_free (msg); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_info: 'info' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(info) +{ + struct t_relay_weechat_msg *msg; + const char *info; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(1); + + msg = relay_weechat_msg_new (id); + if (msg) + { + info = weechat_info_get (argv[0], + (argc > 1) ? argv_eol[1] : NULL); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INFO); + relay_weechat_msg_add_string (msg, argv[0]); + relay_weechat_msg_add_string (msg, info); + relay_weechat_msg_send (client, msg); + relay_weechat_msg_free (msg); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_infolist: 'infolist' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(infolist) +{ + struct t_relay_weechat_msg *msg; + long unsigned int value; + char *args; + int rc; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(1); + + msg = relay_weechat_msg_new (id); + if (msg) + { + value = 0; + args = NULL; + if (argc > 1) + { + rc = sscanf (argv[1], "%lx", &value); + if ((rc == EOF) || (rc == 0)) + value = 0; + if (argc > 2) + args = argv_eol[2]; + } + relay_weechat_msg_add_infolist (msg, argv[0], (void *)value, args); + relay_weechat_msg_send (client, msg); + relay_weechat_msg_free (msg); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_nicklist: 'nicklist' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(nicklist) +{ + struct t_relay_weechat_msg *msg; + struct t_gui_buffer *ptr_buffer; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0); + + ptr_buffer = NULL; + + if (argc > 0) + { + ptr_buffer = relay_weechat_protocol_get_buffer (argv[0]); + if (!ptr_buffer) + return WEECHAT_RC_OK; + } + + msg = relay_weechat_msg_new (id); + if (msg) + { + relay_weechat_msg_add_nicklist (msg, ptr_buffer); + relay_weechat_msg_send (client, msg); + relay_weechat_msg_free (msg); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_input: 'input' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(input) +{ + struct t_gui_buffer *ptr_buffer; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(2); + + ptr_buffer = relay_weechat_protocol_get_buffer (argv[0]); + if (ptr_buffer) + weechat_command (ptr_buffer, argv_eol[1]); + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_test: 'test' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(test) +{ + struct t_relay_weechat_msg *msg; + + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0); + + msg = relay_weechat_msg_new (id); + if (msg) + { + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_CHAR); + relay_weechat_msg_add_char (msg, 'A'); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INT); + relay_weechat_msg_add_int (msg, 123456789); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_LONG); + relay_weechat_msg_add_long (msg, 123456789012345L); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING); + relay_weechat_msg_add_string (msg, "a string"); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING); + relay_weechat_msg_add_string (msg, ""); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING); + relay_weechat_msg_add_string (msg, NULL); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_BUFFER); + relay_weechat_msg_add_buffer (msg, "buffer", 6); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_BUFFER); + relay_weechat_msg_add_buffer (msg, NULL, 0); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_POINTER); + relay_weechat_msg_add_pointer (msg, &msg); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_TIME); + relay_weechat_msg_add_time (msg, 1321993456); + relay_weechat_msg_send (client, msg); + relay_weechat_msg_free (msg); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_cb_quit: 'quit' command from client + */ + +RELAY_WEECHAT_PROTOCOL_CALLBACK(quit) +{ + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0); + + relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); + + return WEECHAT_RC_OK; +} + +/* + * relay_weechat_protocol_recv: read a command from client + */ + +void +relay_weechat_protocol_recv (struct t_relay_client *client, char *data) +{ + char *pos, *id, *command, **argv, **argv_eol; + int i, argc, return_code; + struct t_relay_weechat_protocol_cb protocol_cb[] = + { { "init", &relay_weechat_protocol_cb_init }, + { "hdata", &relay_weechat_protocol_cb_hdata }, + { "info", &relay_weechat_protocol_cb_info }, + { "infolist", &relay_weechat_protocol_cb_infolist }, + { "nicklist", &relay_weechat_protocol_cb_nicklist }, + { "input", &relay_weechat_protocol_cb_input }, + { "test", &relay_weechat_protocol_cb_test }, + { "quit", &relay_weechat_protocol_cb_quit }, + { NULL, NULL } + }; + + if (!data || !data[0] || RELAY_CLIENT_HAS_ENDED(client)) + return; + + /* 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 %d: \"%s\"", + RELAY_PLUGIN_NAME, client->id, data); + } + + /* display message in raw buffer */ + relay_raw_print (client, RELAY_RAW_FLAG_RECV, "cmd: %s", data); + + /* extract id */ + id = NULL; + if (data[0] == '(') + { + pos = strchr (data, ')'); + if (pos) + { + id = weechat_strndup (data + 1, pos - data - 1); + data = pos + 1; + while (data[0] == ' ') + { + data++; + } + } + } + + /* search end of data */ + pos = strchr (data, ' '); + if (pos) + command = weechat_strndup (data, pos - data); + else + command = strdup (data); + + if (!command) + { + if (id) + free (id); + return; + } + + argc = 0; + argv = NULL; + argv_eol = NULL; + + if (pos) + { + while (pos[0] == ' ') + { + pos++; + } + argv = weechat_string_split (pos, " ", 0, 0, &argc); + argv_eol = weechat_string_split (pos, " ", 1, 0, NULL); + } + + for (i = 0; protocol_cb[i].name; i++) + { + if (strcmp (protocol_cb[i].name, command) == 0) + { + if ((strcmp (protocol_cb[i].name, "init") != 0) + && (!RELAY_WEECHAT_DATA(client, password_ok))) + { + /* + * command is not "init" and password is not set? + * then close connection! + */ + relay_client_set_status (client, + RELAY_STATUS_DISCONNECTED); + } + else + { + return_code = (int) (protocol_cb[i].cmd_function) (client, + id, + protocol_cb[i].name, + argc, + argv, + argv_eol); + if ((weechat_relay_plugin->debug >= 1) + && (return_code == WEECHAT_RC_ERROR)) + { + weechat_printf (NULL, + _("%s%s: failed to execute command \"%s\" " + "for client %d"), + weechat_prefix ("error"), + RELAY_PLUGIN_NAME, command, client->id); + } + } + break; + } + } + + if (id) + free (id); + if (argv) + weechat_string_free_split (argv); + if (argv_eol) + weechat_string_free_split (argv_eol); +} diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.h b/src/plugins/relay/weechat/relay-weechat-protocol.h new file mode 100644 index 000000000..8df7c76ee --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat-protocol.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2003-2011 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_WEECHAT_PROTOCOL_H +#define __WEECHAT_RELAY_WEECHAT_PROTOCOL_H 1 + +#define RELAY_WEECHAT_PROTOCOL_CALLBACK(__command) \ + int \ + relay_weechat_protocol_cb_##__command ( \ + struct t_relay_client *client, \ + const char *id, \ + const char *command, \ + int argc, \ + char **argv, \ + char **argv_eol) + +#define RELAY_WEECHAT_PROTOCOL_MIN_ARGS(__min_args) \ + (void) id; \ + (void) command; \ + (void) argv; \ + (void) argv_eol; \ + if ((weechat_relay_plugin->debug >= 1) && (argc < __min_args)) \ + { \ + weechat_printf (NULL, \ + _("%s%s: too few arguments received from " \ + "client %d for command \"%s\" " \ + "(received: %d arguments, expected: at " \ + "least %d)"), \ + weechat_prefix ("error"), RELAY_PLUGIN_NAME, \ + client->id, command, argc, __min_args); \ + return WEECHAT_RC_ERROR; \ + } + +typedef int (t_relay_weechat_cmd_func)(struct t_relay_client *client, + const char *id, const char *command, + int argc, char **argv, char **argv_eol); + +struct t_relay_weechat_protocol_cb +{ + char *name; /* relay command */ + t_relay_weechat_cmd_func *cmd_function; /* callback */ +}; + +extern void relay_weechat_protocol_recv (struct t_relay_client *client, + char *data); + +#endif /* __WEECHAT_RELAY_WEECHAT_PROTOCOL_H */ diff --git a/src/plugins/relay/weechat/relay-weechat.c b/src/plugins/relay/weechat/relay-weechat.c new file mode 100644 index 000000000..45f96aa2d --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2003-2011 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-weechat.c: WeeChat protocol for relay to client + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <errno.h> +#include <arpa/inet.h> + +#include "../../weechat-plugin.h" +#include "../relay.h" +#include "relay-weechat.h" +#include "relay-weechat-protocol.h" +#include "../relay-client.h" +#include "../relay-config.h" +#include "../relay-raw.h" + + +char *relay_weechat_compression_string[] = /* strings for compressions */ +{ "off", "gzip" }; + +char *relay_weechat_partial_message = NULL; + + +/* + * relay_weechat_compression_search: search a compression by name + */ + +int +relay_weechat_compression_search (const char *compression) +{ + int i; + + for (i = 0; i < RELAY_WEECHAT_NUM_COMPRESSIONS; i++) + { + if (weechat_strcasecmp (relay_weechat_compression_string[i], compression) == 0) + return i; + } + + /* compression not found */ + return -1; +} + +/* + * relay_weechat_recv: read data from client + */ + +void +relay_weechat_recv (struct t_relay_client *client, const char *data) +{ + char *new_partial, *pos, *tmp, **commands; + int num_commands, i; + + if (relay_weechat_partial_message) + { + new_partial = realloc (relay_weechat_partial_message, + strlen (relay_weechat_partial_message) + + strlen (data) + 1); + if (!new_partial) + return; + relay_weechat_partial_message = new_partial; + strcat (relay_weechat_partial_message, data); + } + else + relay_weechat_partial_message = strdup (data); + + pos = strrchr (relay_weechat_partial_message, '\n'); + if (pos) + { + pos[0] = '\0'; + commands = weechat_string_split (relay_weechat_partial_message, "\n", + 0, 0, &num_commands); + if (commands) + { + for (i = 0; i < num_commands; i++) + { + relay_weechat_protocol_recv (client, commands[i]); + } + weechat_string_free_split (commands); + } + if (pos[1]) + { + tmp = strdup (pos + 1); + free (relay_weechat_partial_message); + relay_weechat_partial_message = tmp; + } + else + { + free (relay_weechat_partial_message); + relay_weechat_partial_message = NULL; + } + } +} + +/* + * relay_weechat_close_connection: called when connection with client is closed + */ + +void +relay_weechat_close_connection (struct t_relay_client *client) +{ + (void) client; +} + +/* + * relay_weechat_alloc: init relay data specific to weechat protocol + */ + +void +relay_weechat_alloc (struct t_relay_client *client) +{ + struct t_relay_weechat_data *weechat_data; + const char *password; + + password = weechat_config_string (relay_config_network_password); + + client->protocol_data = malloc (sizeof (*weechat_data)); + if (client->protocol_data) + { + RELAY_WEECHAT_DATA(client, password_ok) = (password && password[0]) ? 0 : 1; +#ifdef HAVE_ZLIB + RELAY_WEECHAT_DATA(client, compression) = 1; +#else + RELAY_WEECHAT_DATA(client, compression) = 0; +#endif + } +} + +/* + * relay_weechat_alloc_with_infolist: init relay data specific to weechat + * protocol with an infolist + */ + +void +relay_weechat_alloc_with_infolist (struct t_relay_client *client, + struct t_infolist *infolist) +{ + struct t_relay_weechat_data *weechat_data; + + client->protocol_data = malloc (sizeof (*weechat_data)); + if (client->protocol_data) + { + RELAY_WEECHAT_DATA(client, password_ok) = weechat_infolist_integer (infolist, "password_ok"); + RELAY_WEECHAT_DATA(client, compression) = weechat_infolist_integer (infolist, "compression"); + } +} + +/* + * relay_weechat_free: free relay data specific to weechat protocol + */ + +void +relay_weechat_free (struct t_relay_client *client) +{ + if (client->protocol_data) + free (client->protocol_data); +} + +/* + * relay_weechat_add_to_infolist: add client weechat data in an infolist item + * return 1 if ok, 0 if error + */ + +int +relay_weechat_add_to_infolist (struct t_infolist_item *item, + struct t_relay_client *client) +{ + if (!item || !client) + return 0; + + if (!weechat_infolist_new_var_integer (item, "password_ok", RELAY_WEECHAT_DATA(client, password_ok))) + return 0; + if (!weechat_infolist_new_var_integer (item, "compression", RELAY_WEECHAT_DATA(client, compression))) + return 0; + + return 1; +} + +/* + * relay_weechat_print_log: print weechat client infos in log (usually for + * crash dump) + */ + +void +relay_weechat_print_log (struct t_relay_client *client) +{ + if (client->protocol_data) + { + weechat_log_printf (" password_ok. . . . . . : %d", RELAY_WEECHAT_DATA(client, password_ok)); + weechat_log_printf (" compression. . . . . . : %d", RELAY_WEECHAT_DATA(client, compression)); + } +} diff --git a/src/plugins/relay/weechat/relay-weechat.h b/src/plugins/relay/weechat/relay-weechat.h new file mode 100644 index 000000000..89cd9770e --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2003-2011 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_WEECHAT_H +#define __WEECHAT_RELAY_WEECHAT_H 1 + +struct t_relay_client; + +#define RELAY_WEECHAT_DATA(client, var) \ + (((struct t_relay_weechat_data *)client->protocol_data)->var) + +enum t_relay_weechat_compression +{ + RELAY_WEECHAT_COMPRESSION_OFF = 0, /* no compression of binary objects */ + RELAY_WEECHAT_COMPRESSION_GZIP, /* gzip compression */ + /* number of compressions */ + RELAY_WEECHAT_NUM_COMPRESSIONS, +}; + +struct t_relay_weechat_data +{ + int password_ok; /* password received and ok? */ + int compression; /* compression type */ +}; + +extern int relay_weechat_compression_search (const char *compression); +extern void relay_weechat_recv (struct t_relay_client *client, + const char *data); +extern void relay_weechat_close_connection (struct t_relay_client *client); +extern void relay_weechat_alloc (struct t_relay_client *client); +extern void relay_weechat_alloc_with_infolist (struct t_relay_client *client, + struct t_infolist *infolist); +extern void relay_weechat_free (struct t_relay_client *client); +extern int relay_weechat_add_to_infolist (struct t_infolist_item *item, + struct t_relay_client *client); +extern void relay_weechat_print_log (struct t_relay_client *client); + +#endif /* __WEECHAT_RELAY_WEECHAT_H */ |