1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-07 10:13:12 +02:00

relay: add WeeChat protocol (for remote GUI), doc about protocol, new options

The protocol is partial, under development, and NOT ready for usage.

New options added in relay.conf:
- relay.network.allowed_ips: allow only some IPs on relay plugin (by default
  all IPs are allowed)
- relay.network.compression_level: compression level used in WeeChat protocol
  (compression is made using zlib)
This commit is contained in:
Sebastien Helleu
2011-12-06 23:06:23 +01:00
parent 00a3f990b3
commit 013f8cc757
51 changed files with 3890 additions and 919 deletions
+11 -3
View File
@@ -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)
+10 -6
View File
@@ -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
@@ -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)
{
@@ -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 */
+5 -5
View File
@@ -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);
-347
View File
@@ -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)
{
}
}
-43
View File
@@ -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 */
+16 -15
View File
@@ -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;
+4 -3
View File
@@ -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);
+1 -1
View File
@@ -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"),
+58
View File
@@ -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
@@ -70,6 +77,42 @@ relay_config_refresh_cb (void *data, struct t_config_option *option)
relay_buffer_refresh (NULL);
}
/*
* 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",
+5
View File
@@ -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,
+34 -10
View File
@@ -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);
}
/*
+5 -2
View File
@@ -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);
+16
View File
@@ -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;
+6 -6
View File
@@ -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;
-2
View File
@@ -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 */
@@ -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;
}
@@ -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 */
@@ -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);
}
@@ -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 */
+217
View File
@@ -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));
}
}
+54
View File
@@ -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 */