summaryrefslogtreecommitdiff
path: root/src/plugins/relay
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/relay')
-rw-r--r--src/plugins/relay/CMakeLists.txt14
-rw-r--r--src/plugins/relay/Makefile.am16
-rw-r--r--src/plugins/relay/irc/relay-irc.c (renamed from src/plugins/relay/relay-client-irc.c)419
-rw-r--r--src/plugins/relay/irc/relay-irc.h (renamed from src/plugins/relay/relay-client-irc.h)30
-rw-r--r--src/plugins/relay/relay-buffer.c10
-rw-r--r--src/plugins/relay/relay-client-weechat.c347
-rw-r--r--src/plugins/relay/relay-client-weechat.h43
-rw-r--r--src/plugins/relay/relay-client.c31
-rw-r--r--src/plugins/relay/relay-client.h7
-rw-r--r--src/plugins/relay/relay-command.c2
-rw-r--r--src/plugins/relay/relay-config.c58
-rw-r--r--src/plugins/relay/relay-config.h5
-rw-r--r--src/plugins/relay/relay-raw.c44
-rw-r--r--src/plugins/relay/relay-raw.h7
-rw-r--r--src/plugins/relay/relay-server.c16
-rw-r--r--src/plugins/relay/relay-upgrade.c12
-rw-r--r--src/plugins/relay/relay.c2
-rw-r--r--src/plugins/relay/weechat/relay-weechat-msg.c963
-rw-r--r--src/plugins/relay/weechat/relay-weechat-msg.h82
-rw-r--r--src/plugins/relay/weechat/relay-weechat-protocol.c429
-rw-r--r--src/plugins/relay/weechat/relay-weechat-protocol.h63
-rw-r--r--src/plugins/relay/weechat/relay-weechat.c217
-rw-r--r--src/plugins/relay/weechat/relay-weechat.h54
23 files changed, 2201 insertions, 670 deletions
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 */