summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2009-01-15 15:29:05 +0100
committerSebastien Helleu <flashcode@flashtux.org>2009-01-15 15:29:05 +0100
commit18a62f1dac870c96152063d69336ecfaf563da69 (patch)
tree7989acb4aebf8749f7ddb5e48e13431f93e0ce33 /src/plugins
parentc717d206cd73c0445a9edd1a5b723ea79a107676 (diff)
downloadweechat-18a62f1dac870c96152063d69336ecfaf563da69.zip
Add Jabber plugin (alpha version, many Jabber features are missing)
This commit introduces Jabber/XMPP protocol for WeeChat. It uses iksemel lib. Please note many major Jabber features are missing: - roster management (add/remove/.. buddies), - MUC, - transports. It is possible to define servers (with /jabber), connect to them (with /jconnect), disconnect (/jdisconnect) and chat with buddies (with /jchat).
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/CMakeLists.txt8
-rw-r--r--src/plugins/Makefile.am8
-rw-r--r--src/plugins/fifo/fifo.c2
-rw-r--r--src/plugins/irc/irc-buffer.c2
-rw-r--r--src/plugins/irc/irc-channel.c65
-rw-r--r--src/plugins/irc/irc-channel.h11
-rw-r--r--src/plugins/irc/irc-color.c10
-rw-r--r--src/plugins/irc/irc-command.c27
-rw-r--r--src/plugins/irc/irc-command.h3
-rw-r--r--src/plugins/irc/irc-completion.c152
-rw-r--r--src/plugins/irc/irc-config.c54
-rw-r--r--src/plugins/irc/irc-config.h8
-rw-r--r--src/plugins/irc/irc-display.c2
-rw-r--r--src/plugins/irc/irc-ignore.c2
-rw-r--r--src/plugins/irc/irc-ignore.h2
-rw-r--r--src/plugins/irc/irc-info.c7
-rw-r--r--src/plugins/irc/irc-input.h4
-rw-r--r--src/plugins/irc/irc-nick.c8
-rw-r--r--src/plugins/irc/irc-nick.h12
-rw-r--r--src/plugins/irc/irc-protocol.c6
-rw-r--r--src/plugins/irc/irc-protocol.h6
-rw-r--r--src/plugins/irc/irc-server.c149
-rw-r--r--src/plugins/irc/irc-server.h19
-rw-r--r--src/plugins/irc/irc-upgrade.c2
-rw-r--r--src/plugins/irc/irc.c9
-rw-r--r--src/plugins/irc/irc.h4
-rw-r--r--src/plugins/jabber/CMakeLists.txt45
-rw-r--r--src/plugins/jabber/Makefile.am55
-rw-r--r--src/plugins/jabber/jabber-bar-item.c190
-rw-r--r--src/plugins/jabber/jabber-bar-item.h25
-rw-r--r--src/plugins/jabber/jabber-buddy.c719
-rw-r--r--src/plugins/jabber/jabber-buddy.h101
-rw-r--r--src/plugins/jabber/jabber-buffer.c320
-rw-r--r--src/plugins/jabber/jabber-buffer.h41
-rw-r--r--src/plugins/jabber/jabber-command.c847
-rw-r--r--src/plugins/jabber/jabber-command.h37
-rw-r--r--src/plugins/jabber/jabber-completion.c448
-rw-r--r--src/plugins/jabber/jabber-completion.h25
-rw-r--r--src/plugins/jabber/jabber-config.c990
-rw-r--r--src/plugins/jabber/jabber-config.h80
-rw-r--r--src/plugins/jabber/jabber-debug.c145
-rw-r--r--src/plugins/jabber/jabber-debug.h36
-rw-r--r--src/plugins/jabber/jabber-display.c224
-rw-r--r--src/plugins/jabber/jabber-display.h26
-rw-r--r--src/plugins/jabber/jabber-info.c357
-rw-r--r--src/plugins/jabber/jabber-info.h25
-rw-r--r--src/plugins/jabber/jabber-input.c104
-rw-r--r--src/plugins/jabber/jabber-input.h30
-rw-r--r--src/plugins/jabber/jabber-muc.c662
-rw-r--r--src/plugins/jabber/jabber-muc.h106
-rw-r--r--src/plugins/jabber/jabber-server.c1987
-rw-r--r--src/plugins/jabber/jabber-server.h205
-rw-r--r--src/plugins/jabber/jabber-upgrade.c329
-rw-r--r--src/plugins/jabber/jabber-upgrade.h37
-rw-r--r--src/plugins/jabber/jabber-xmpp.c425
-rw-r--r--src/plugins/jabber/jabber-xmpp.h39
-rw-r--r--src/plugins/jabber/jabber.c212
-rw-r--r--src/plugins/jabber/jabber.h70
-rw-r--r--src/plugins/logger/logger.c10
-rw-r--r--src/plugins/notify/notify.c14
60 files changed, 9272 insertions, 276 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index a4408a79a..0b4eae29f 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -58,6 +58,14 @@ IF(NOT DISABLE_IRC)
ADD_SUBDIRECTORY( irc )
ENDIF(NOT DISABLE_IRC)
+IF(NOT DISABLE_JABBER)
+ # Check for iksemel library
+ FIND_PACKAGE(Iksemel)
+ IF(IKSEMEL_FOUND)
+ ADD_SUBDIRECTORY( jabber )
+ ENDIF(IKSEMEL_FOUND)
+ENDIF(NOT DISABLE_JABBER)
+
IF(NOT DISABLE_LOGGER)
ADD_SUBDIRECTORY( logger )
ENDIF(NOT DISABLE_LOGGER)
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 31c529992..a716f2cd2 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -50,6 +50,10 @@ if PLUGIN_IRC
irc_dir = irc
endif
+if PLUGIN_JABBER
+jabber_dir = jabber
+endif
+
if PLUGIN_LOGGER
logger_dir = logger
endif
@@ -91,5 +95,5 @@ xfer_dir = xfer
endif
SUBDIRS = . $(alias_dir) $(aspell_dir) $(charset_dir) $(demo_dir) $(fifo_dir) \
- $(irc_dir) $(logger_dir) $(notify_dir) $(relay_dir) $(script_dir) \
- $(trigger_dir) $(xfer_dir)
+ $(irc_dir) $(jabber_dir) $(logger_dir) $(notify_dir) $(relay_dir) \
+ $(script_dir) $(trigger_dir) $(xfer_dir)
diff --git a/src/plugins/fifo/fifo.c b/src/plugins/fifo/fifo.c
index fe16f2015..3484af9eb 100644
--- a/src/plugins/fifo/fifo.c
+++ b/src/plugins/fifo/fifo.c
@@ -96,7 +96,7 @@ fifo_create ()
O_RDONLY | O_NONBLOCK)) != -1)
{
weechat_printf (NULL,
- _("%s: pipe open"),
+ _("%s: pipe opened"),
FIFO_PLUGIN_NAME),
rc = 1;
}
diff --git a/src/plugins/irc/irc-buffer.c b/src/plugins/irc/irc-buffer.c
index 86640f603..7792a8845 100644
--- a/src/plugins/irc/irc-buffer.c
+++ b/src/plugins/irc/irc-buffer.c
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* irc-buffer.c: manages buffers for IRC plugin */
+/* irc-buffer.c: buffer functions for IRC plugin */
#include <stdlib.h>
diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c
index daf9adced..c3fab2cd1 100644
--- a/src/plugins/irc/irc-channel.c
+++ b/src/plugins/irc/irc-channel.c
@@ -61,7 +61,7 @@ irc_channel_valid (struct t_irc_server *server, struct t_irc_channel *channel)
}
/*
- * irc_channel_new: allocate a new channel for a server and add it to servers
+ * irc_channel_new: allocate a new channel for a server and add it to channels
* list
*/
@@ -142,19 +142,19 @@ irc_channel_new (struct t_irc_server *server, int channel_type,
new_channel->modes = NULL;
new_channel->limit = 0;
new_channel->key = NULL;
- new_channel->nicks_count = 0;
new_channel->checking_away = 0;
new_channel->away_message = NULL;
new_channel->cycle = 0;
new_channel->display_creation_date = 0;
new_channel->nick_completion_reset = 0;
+ new_channel->nicks_count = 0;
new_channel->nicks = NULL;
new_channel->last_nick = NULL;
- new_channel->buffer = new_buffer;
new_channel->nicks_speaking[0] = NULL;
new_channel->nicks_speaking[1] = NULL;
new_channel->nicks_speaking_time = NULL;
new_channel->last_nick_speaking_time = NULL;
+ new_channel->buffer = new_buffer;
new_channel->buffer_as_string = NULL;
/* add new channel to channels list */
@@ -270,14 +270,14 @@ irc_channel_check_away (struct t_irc_server *server,
*/
void
-irc_channel_set_away (struct t_irc_channel *channel, const char *nick,
+irc_channel_set_away (struct t_irc_channel *channel, const char *nick_name,
int is_away)
{
struct t_irc_nick *ptr_nick;
if (channel->type == IRC_CHANNEL_TYPE_CHANNEL)
{
- ptr_nick = irc_nick_search (channel, nick);
+ ptr_nick = irc_nick_search (channel, nick_name);
if (ptr_nick)
irc_nick_set_away (channel, ptr_nick, is_away);
}
@@ -288,8 +288,8 @@ irc_channel_set_away (struct t_irc_channel *channel, const char *nick,
*/
void
-irc_channel_nick_speaking_add (struct t_irc_channel *channel, const char *nick,
- int highlight)
+irc_channel_nick_speaking_add (struct t_irc_channel *channel,
+ const char *nick_name, int highlight)
{
int size, to_remove, i;
@@ -301,7 +301,7 @@ irc_channel_nick_speaking_add (struct t_irc_channel *channel, const char *nick,
if (!channel->nicks_speaking[highlight])
channel->nicks_speaking[highlight] = weechat_list_new ();
- weechat_list_add (channel->nicks_speaking[highlight], nick,
+ weechat_list_add (channel->nicks_speaking[highlight], nick_name,
WEECHAT_LIST_POS_END);
size = weechat_list_size (channel->nicks_speaking[highlight]);
@@ -346,7 +346,7 @@ irc_channel_nick_speaking_rename (struct t_irc_channel *channel,
struct t_irc_channel_speaking *
irc_channel_nick_speaking_time_search (struct t_irc_channel *channel,
- const char *nick,
+ const char *nick_name,
int check_time)
{
struct t_irc_channel_speaking *ptr_nick;
@@ -358,7 +358,7 @@ irc_channel_nick_speaking_time_search (struct t_irc_channel *channel,
for (ptr_nick = channel->nicks_speaking_time; ptr_nick;
ptr_nick = ptr_nick->next_nick)
{
- if (strcmp (ptr_nick->nick, nick) == 0)
+ if (strcmp (ptr_nick->nick, nick_name) == 0)
{
if (check_time && (ptr_nick->time_last_message < time_limit))
return NULL;
@@ -376,23 +376,23 @@ irc_channel_nick_speaking_time_search (struct t_irc_channel *channel,
void
irc_channel_nick_speaking_time_free (struct t_irc_channel *channel,
- struct t_irc_channel_speaking *nick)
+ struct t_irc_channel_speaking *nick_speaking)
{
/* free data */
- if (nick->nick)
- free (nick->nick);
+ if (nick_speaking->nick)
+ free (nick_speaking->nick);
/* remove nick from list */
- if (nick->prev_nick)
- (nick->prev_nick)->next_nick = nick->next_nick;
- if (nick->next_nick)
- (nick->next_nick)->prev_nick = nick->prev_nick;
- if (channel->nicks_speaking_time == nick)
- channel->nicks_speaking_time = nick->next_nick;
- if (channel->last_nick_speaking_time == nick)
- channel->last_nick_speaking_time = nick->prev_nick;
-
- free (nick);
+ if (nick_speaking->prev_nick)
+ (nick_speaking->prev_nick)->next_nick = nick_speaking->next_nick;
+ if (nick_speaking->next_nick)
+ (nick_speaking->next_nick)->prev_nick = nick_speaking->prev_nick;
+ if (channel->nicks_speaking_time == nick_speaking)
+ channel->nicks_speaking_time = nick_speaking->next_nick;
+ if (channel->last_nick_speaking_time == nick_speaking)
+ channel->last_nick_speaking_time = nick_speaking->prev_nick;
+
+ free (nick_speaking);
}
/*
@@ -437,19 +437,19 @@ irc_channel_nick_speaking_time_remove_old (struct t_irc_channel *channel)
void
irc_channel_nick_speaking_time_add (struct t_irc_channel *channel,
- const char *nick,
+ const char *nick_name,
time_t time_last_message)
{
struct t_irc_channel_speaking *ptr_nick, *new_nick;
- ptr_nick = irc_channel_nick_speaking_time_search (channel, nick, 0);
+ ptr_nick = irc_channel_nick_speaking_time_search (channel, nick_name, 0);
if (ptr_nick)
irc_channel_nick_speaking_time_free (channel, ptr_nick);
new_nick = malloc (sizeof (*new_nick));
if (new_nick)
{
- new_nick->nick = strdup (nick);
+ new_nick->nick = strdup (nick_name);
new_nick->time_last_message = time_last_message;
/* insert nick at beginning of list */
@@ -538,15 +538,16 @@ irc_channel_free (struct t_irc_server *server, struct t_irc_channel *channel)
}
/*
- * irc_channel_free_all: free all allocated channels
+ * irc_channel_free_all: free all allocated channels for a server
*/
void
irc_channel_free_all (struct t_irc_server *server)
{
- /* remove all channels for the server */
while (server->channels)
+ {
irc_channel_free (server, server->channels);
+ }
}
/*
@@ -669,12 +670,16 @@ irc_channel_print_log (struct t_irc_channel *channel)
weechat_log_printf (" away_message . . . . . . : '%s'", channel->away_message);
weechat_log_printf (" cycle. . . . . . . . . . : %d", channel->cycle);
weechat_log_printf (" display_creation_date. . : %d", channel->display_creation_date);
+ weechat_log_printf (" nick_completion_reset. . : %d", channel->nick_completion_reset);
+ weechat_log_printf (" nicks_count. . . . . . . : %d", channel->nicks_count);
weechat_log_printf (" nicks. . . . . . . . . . : 0x%lx", channel->nicks);
weechat_log_printf (" last_nick. . . . . . . . : 0x%lx", channel->last_nick);
- weechat_log_printf (" buffer . . . . . . . . . : 0x%lx", channel->buffer);
- weechat_log_printf (" nicks_speaking . . . . . : 0x%lx", channel->nicks_speaking);
+ weechat_log_printf (" nicks_speaking[0]. . . . : 0x%lx", channel->nicks_speaking[0]);
+ weechat_log_printf (" nicks_speaking[1]. . . . : 0x%lx", channel->nicks_speaking[1]);
weechat_log_printf (" nicks_speaking_time. . . : 0x%lx", channel->nicks_speaking_time);
weechat_log_printf (" last_nick_speaking_time. : 0x%lx", channel->last_nick_speaking_time);
+ weechat_log_printf (" buffer . . . . . . . . . : 0x%lx", channel->buffer);
+ weechat_log_printf (" buffer_as_string . . . . : '%s'", channel->buffer_as_string);
weechat_log_printf (" prev_channel . . . . . . : 0x%lx", channel->prev_channel);
weechat_log_printf (" next_channel . . . . . . : 0x%lx", channel->next_channel);
for (i = 0; i < 2; i++)
diff --git a/src/plugins/irc/irc-channel.h b/src/plugins/irc/irc-channel.h
index c6c36160a..bd129f6fa 100644
--- a/src/plugins/irc/irc-channel.h
+++ b/src/plugins/irc/irc-channel.h
@@ -47,13 +47,13 @@ struct t_irc_channel
char *modes; /* channel modes */
int limit; /* user limit (0 is limit not set) */
char *key; /* channel key (NULL if no key set) */
- int nicks_count; /* # nicks on channel (0 if pv) */
int checking_away; /* = 1 if checking away with WHO cmd */
char *away_message; /* to display away only once in pv */
int cycle; /* currently cycling (/part + /join) */
int display_creation_date; /* 1 for displaying creation date */
int nick_completion_reset; /* 1 for resetting nick completion */
/* there was some join/part on chan */
+ int nicks_count; /* # nicks on channel (0 if pv) */
struct t_irc_nick *nicks; /* nicks on the channel */
struct t_irc_nick *last_nick; /* last nick on the channel */
struct t_weelist *nicks_speaking[2]; /* for smart completion: first */
@@ -85,20 +85,21 @@ extern int irc_channel_is_channel (const char *string);
extern void irc_channel_remove_away (struct t_irc_channel *channel);
extern void irc_channel_check_away (struct t_irc_server *server,
struct t_irc_channel *channel, int force);
-extern void irc_channel_set_away (struct t_irc_channel *channel, const char *nick,
+extern void irc_channel_set_away (struct t_irc_channel *channel,
+ const char *nick_name,
int is_away);
extern void irc_channel_nick_speaking_add (struct t_irc_channel *channel,
- const char *nick,
+ const char *nick_name,
int highlight);
extern void irc_channel_nick_speaking_rename (struct t_irc_channel *channel,
const char *old_nick,
const char *new_nick);
extern struct t_irc_channel_speaking *irc_channel_nick_speaking_time_search (struct t_irc_channel *channel,
- const char *nick,
+ const char *nick_name,
int check_time);
extern void irc_channel_nick_speaking_time_remove_old (struct t_irc_channel *channel);
extern void irc_channel_nick_speaking_time_add (struct t_irc_channel *channel,
- const char *nick,
+ const char *nick_name,
time_t time_last_message);
extern void irc_channel_nick_speaking_time_rename (struct t_irc_channel *channel,
const char *old_nick,
diff --git a/src/plugins/irc/irc-color.c b/src/plugins/irc/irc-color.c
index c210c9d45..91a60ac93 100644
--- a/src/plugins/irc/irc-color.c
+++ b/src/plugins/irc/irc-color.c
@@ -268,12 +268,12 @@ irc_color_encode (const char *string, int keep_colors)
{
switch (ptr_string[0])
{
- case 0x02: // ^B
+ case 0x02: /* ^B */
if (keep_colors)
out[out_pos++] = IRC_COLOR_BOLD_CHAR;
ptr_string++;
break;
- case 0x03: // ^C
+ case 0x03: /* ^C */
if (keep_colors)
out[out_pos++] = IRC_COLOR_COLOR_CHAR;
ptr_string++;
@@ -308,17 +308,17 @@ irc_color_encode (const char *string, int keep_colors)
}
}
break;
- case 0x0F: // ^O
+ case 0x0F: /* ^O */
if (keep_colors)
out[out_pos++] = IRC_COLOR_RESET_CHAR;
ptr_string++;
break;
- case 0x12: // ^R
+ case 0x12: /* ^R */
if (keep_colors)
out[out_pos++] = IRC_COLOR_REVERSE_CHAR;
ptr_string++;
break;
- case 0x15: // ^U
+ case 0x15: /* ^U */
if (keep_colors)
out[out_pos++] = IRC_COLOR_UNDERLINE_CHAR;
ptr_string++;
diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c
index 46585a392..ec2c974ce 100644
--- a/src/plugins/irc/irc-command.c
+++ b/src/plugins/irc/irc-command.c
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* irc-command.c: IRC commands managment */
+/* irc-command.c: IRC commands */
#include <stdlib.h>
@@ -35,6 +35,7 @@
#include "irc-buffer.h"
#include "irc-color.h"
#include "irc-config.h"
+#include "irc-input.h"
#include "irc-server.h"
#include "irc-channel.h"
#include "irc-nick.h"
@@ -515,7 +516,8 @@ irc_command_connect_one_server (struct t_irc_server *server, int no_join)
server->name);
return 0;
}
- if (irc_server_connect (server, no_join))
+ server->disable_autojoin = no_join;
+ if (irc_server_connect (server))
{
server->reconnect_start = 0;
server->reconnect_join = (server->channels) ? 1 : 0;
@@ -1132,7 +1134,7 @@ irc_command_quit_server (struct t_irc_server *server, const char *arguments)
/*
* irc_command_disconnect_one_server: disconnect from a server
- * return 0 if error, 1 if ok
+ * return 0 if error, 1 if ok
*/
int
@@ -2526,12 +2528,8 @@ irc_command_query (void *data, struct t_gui_buffer *buffer, int argc,
{
string = irc_color_decode (argv_eol[2],
weechat_config_boolean (irc_config_network_colors_receive));
- weechat_printf (ptr_channel->buffer,
- "%s%s",
- irc_nick_as_prefix (NULL,
- ptr_server->nick,
- IRC_COLOR_CHAT_NICK_SELF),
- (string) ? string : argv_eol[2]);
+ irc_input_user_message_display (ptr_channel->buffer,
+ (string) ? string : argv_eol[2]);
if (string)
free (string);
irc_server_sendf (ptr_server, "PRIVMSG %s :%s",
@@ -2593,7 +2591,8 @@ irc_command_reconnect_one_server (struct t_irc_server *server, int no_join)
}
irc_command_quit_server (server, NULL);
irc_server_disconnect (server, 0);
- if (irc_server_connect (server, no_join))
+ server->disable_autojoin = no_join;
+ if (irc_server_connect (server))
{
server->reconnect_start = 0;
server->reconnect_join = (server->channels) ? 1 : 0;
@@ -2870,7 +2869,7 @@ irc_command_server (void *data, struct t_gui_buffer *buffer, int argc,
IRC_COLOR_CHAT);
if (IRC_SERVER_OPTION_BOOLEAN(new_server, IRC_SERVER_OPTION_AUTOCONNECT))
- irc_server_connect (new_server, 0);
+ irc_server_connect (new_server);
return WEECHAT_RC_OK;
}
@@ -3733,7 +3732,7 @@ irc_command_init ()
"nickname: user or host to ban"),
"%(irc_channel_nicks_hosts)", &irc_command_ban, NULL);
weechat_hook_command ("connect",
- N_("connect to server(s)"),
+ N_("connect to IRC server(s)"),
N_("[-all [-nojoin] | servername [servername ...] "
"[-nojoin] | hostname [-port port] [-ipv6] "
"[-ssl]]"),
@@ -3794,7 +3793,7 @@ irc_command_init ()
"",
NULL, &irc_command_die, NULL);
weechat_hook_command ("disconnect",
- N_("disconnect from server(s)"),
+ N_("disconnect from IRC server(s)"),
N_("[-all | servername [servername ...]]"),
N_(" -all: disconnect from all servers\n"
"servername: server name to disconnect"),
@@ -4028,7 +4027,7 @@ irc_command_init ()
" type: reserved for future usage"),
NULL, &irc_command_service, NULL);
weechat_hook_command ("server",
- N_("list, add or remove servers"),
+ N_("list, add or remove IRC servers"),
N_("[list [servername]] | [listfull [servername]] | "
"[add servername hostname[/port] "
"[-auto | -noauto] [-ipv6] [-ssl]] | "
diff --git a/src/plugins/irc/irc-command.h b/src/plugins/irc/irc-command.h
index 34557e260..4cc654be7 100644
--- a/src/plugins/irc/irc-command.h
+++ b/src/plugins/irc/irc-command.h
@@ -24,8 +24,9 @@ struct t_irc_server;
#define IRC_COMMAND_TOO_FEW_ARGUMENTS(__buffer, __command) \
weechat_printf (__buffer, \
- _("%sirc: too few arguments for \"%s\" command"), \
+ _("%s%s: too few arguments for \"%s\" command"), \
irc_buffer_get_server_prefix (ptr_server, "error"), \
+ IRC_PLUGIN_NAME, \
__command); \
return WEECHAT_RC_ERROR;
diff --git a/src/plugins/irc/irc-completion.c b/src/plugins/irc/irc-completion.c
index 6e1e25f77..4052b0bec 100644
--- a/src/plugins/irc/irc-completion.c
+++ b/src/plugins/irc/irc-completion.c
@@ -35,7 +35,7 @@
/*
- * irc_completion_server_cb: callback for completion with current IRC server
+ * irc_completion_server_cb: callback for completion with current server
*/
int
@@ -60,7 +60,7 @@ irc_completion_server_cb (void *data, const char *completion_item,
/*
* irc_completion_server_nick_cb: callback for completion with self nick
- * of current IRC server
+ * of current server
*/
int
@@ -85,7 +85,7 @@ irc_completion_server_nick_cb (void *data, const char *completion_item,
/*
* irc_completion_server_nicks_cb: callback for completion with nicks
- * of current IRC server
+ * of current server
*/
int
@@ -127,7 +127,7 @@ irc_completion_server_nicks_cb (void *data, const char *completion_item,
}
/*
- * irc_completion_servers_cb: callback for completion with IRC servers
+ * irc_completion_servers_cb: callback for completion with servers
*/
int
@@ -153,7 +153,7 @@ irc_completion_servers_cb (void *data, const char *completion_item,
}
/*
- * irc_completion_channel_cb: callback for completion with current IRC channel
+ * irc_completion_channel_cb: callback for completion with current channel
*/
int
@@ -178,7 +178,7 @@ irc_completion_channel_cb (void *data, const char *completion_item,
/*
* irc_completion_channel_nicks_cb: callback for completion with nicks
- * of current IRC channel
+ * of current channel
*/
int
@@ -198,47 +198,53 @@ irc_completion_channel_nicks_cb (void *data, const char *completion_item,
if (ptr_channel)
{
- if (ptr_channel->type == IRC_CHANNEL_TYPE_CHANNEL)
+ switch (ptr_channel->type)
{
- for (ptr_nick = ptr_channel->nicks; ptr_nick;
- ptr_nick = ptr_nick->next_nick)
- {
- weechat_hook_completion_list_add (completion, ptr_nick->name,
- 1, WEECHAT_LIST_POS_SORT);
- }
-
- /* add nicks speaking recently on this channel */
- if (weechat_config_boolean (irc_config_look_nick_completion_smart))
- {
- /* 0 => nick speaking ; 1 => nick speaking to me (with highlight) */
- for (i = 0; i < 2; i++)
+ case IRC_CHANNEL_TYPE_CHANNEL:
+ for (ptr_nick = ptr_channel->nicks; ptr_nick;
+ ptr_nick = ptr_nick->next_nick)
+ {
+ weechat_hook_completion_list_add (completion,
+ ptr_nick->name,
+ 1,
+ WEECHAT_LIST_POS_SORT);
+ }
+ /* add nicks speaking recently on this channel */
+ if (weechat_config_boolean (irc_config_look_nick_completion_smart))
{
- if (ptr_channel->nicks_speaking[i])
+ /* 0 => nick speaking ; 1 => nick speaking to me (with highlight) */
+ for (i = 0; i < 2; i++)
{
- list_size = weechat_list_size (ptr_channel->nicks_speaking[i]);
- for (j = 0; j < list_size; j++)
+ if (ptr_channel->nicks_speaking[i])
{
- nick = weechat_list_string (weechat_list_get (ptr_channel->nicks_speaking[i], j));
- if (nick && irc_nick_search (ptr_channel, nick))
+ list_size = weechat_list_size (ptr_channel->nicks_speaking[i]);
+ for (j = 0; j < list_size; j++)
{
- weechat_hook_completion_list_add (completion, nick,
- 1, WEECHAT_LIST_POS_BEGINNING);
+ nick = weechat_list_string (weechat_list_get (ptr_channel->nicks_speaking[i], j));
+ if (nick && irc_nick_search (ptr_channel, nick))
+ {
+ weechat_hook_completion_list_add (completion,
+ nick,
+ 1,
+ WEECHAT_LIST_POS_BEGINNING);
+ }
}
}
}
}
- }
-
- /* add self nick at the end */
- weechat_hook_completion_list_add (completion, ptr_server->nick,
- 1, WEECHAT_LIST_POS_END);
- }
- if (ptr_channel->type == IRC_CHANNEL_TYPE_PRIVATE)
- {
- weechat_hook_completion_list_add (completion, ptr_channel->name,
- 0, WEECHAT_LIST_POS_SORT);
+ /* add self nick at the end */
+ weechat_hook_completion_list_add (completion,
+ ptr_server->nick,
+ 1,
+ WEECHAT_LIST_POS_END);
+ break;
+ case IRC_CHANNEL_TYPE_PRIVATE:
+ weechat_hook_completion_list_add (completion,
+ ptr_channel->name,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ break;
}
-
ptr_channel->nick_completion_reset = 0;
}
@@ -247,7 +253,7 @@ irc_completion_channel_nicks_cb (void *data, const char *completion_item,
/*
* irc_completion_channel_nicks_hosts_cb: callback for completion with nicks
- * and hosts of current IRC channel
+ * and hosts of current channel
*/
int
@@ -267,33 +273,40 @@ irc_completion_channel_nicks_hosts_cb (void *data, const char *completion_item,
if (ptr_channel)
{
- if (ptr_channel->type == IRC_CHANNEL_TYPE_CHANNEL)
+ switch (ptr_channel->type)
{
- for (ptr_nick = ptr_channel->nicks; ptr_nick;
- ptr_nick = ptr_nick->next_nick)
- {
- weechat_hook_completion_list_add (completion, ptr_nick->name,
- 1, WEECHAT_LIST_POS_SORT);
- if (ptr_nick->host)
+ case IRC_CHANNEL_TYPE_CHANNEL:
+ for (ptr_nick = ptr_channel->nicks; ptr_nick;
+ ptr_nick = ptr_nick->next_nick)
{
- length = strlen (ptr_nick->name) + 1 +
- strlen (ptr_nick->host) + 1;
- buf = malloc (length);
- if (buf)
+ weechat_hook_completion_list_add (completion,
+ ptr_nick->name,
+ 1,
+ WEECHAT_LIST_POS_SORT);
+ if (ptr_nick->host)
{
- snprintf (buf, length, "%s!%s",
- ptr_nick->name, ptr_nick->host);
- weechat_hook_completion_list_add (completion, buf,
- 0, WEECHAT_LIST_POS_SORT);
- free (buf);
+ length = strlen (ptr_nick->name) + 1 +
+ strlen (ptr_nick->host) + 1;
+ buf = malloc (length);
+ if (buf)
+ {
+ snprintf (buf, length, "%s!%s",
+ ptr_nick->name, ptr_nick->host);
+ weechat_hook_completion_list_add (completion,
+ buf,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ free (buf);
+ }
}
}
- }
- }
- if (ptr_channel->type == IRC_CHANNEL_TYPE_PRIVATE)
- {
- weechat_hook_completion_list_add (completion, ptr_channel->name,
- 0, WEECHAT_LIST_POS_SORT);
+ break;
+ case IRC_CHANNEL_TYPE_PRIVATE:
+ weechat_hook_completion_list_add (completion,
+ ptr_channel->name,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ break;
}
}
@@ -302,7 +315,7 @@ irc_completion_channel_nicks_hosts_cb (void *data, const char *completion_item,
/*
* irc_completion_channel_topic_cb: callback for completion with topic of
- * current IRC channel
+ * current channel
*/
int
@@ -332,7 +345,7 @@ irc_completion_channel_topic_cb (void *data, const char *completion_item,
}
/*
- * irc_completion_channels_cb: callback for completion with IRC channels
+ * irc_completion_channels_cb: callback for completion with channels
*/
int
@@ -394,19 +407,24 @@ irc_completion_msg_part_cb (void *data, const char *completion_item,
void
irc_completion_init ()
{
- weechat_hook_completion ("irc_server", &irc_completion_server_cb, NULL);
+ weechat_hook_completion ("irc_server",
+ &irc_completion_server_cb, NULL);
weechat_hook_completion ("irc_server_nick",
&irc_completion_server_nick_cb, NULL);
weechat_hook_completion ("irc_server_nicks",
&irc_completion_server_nicks_cb, NULL);
- weechat_hook_completion ("irc_servers", &irc_completion_servers_cb, NULL);
- weechat_hook_completion ("irc_channel", &irc_completion_channel_cb, NULL);
+ weechat_hook_completion ("irc_servers",
+ &irc_completion_servers_cb, NULL);
+ weechat_hook_completion ("irc_channel",
+ &irc_completion_channel_cb, NULL);
weechat_hook_completion ("nick",
&irc_completion_channel_nicks_cb, NULL);
weechat_hook_completion ("irc_channel_nicks_hosts",
&irc_completion_channel_nicks_hosts_cb, NULL);
weechat_hook_completion ("irc_channel_topic",
&irc_completion_channel_topic_cb, NULL);
- weechat_hook_completion ("irc_channels", &irc_completion_channels_cb, NULL);
- weechat_hook_completion ("irc_msg_part", &irc_completion_msg_part_cb, NULL);
+ weechat_hook_completion ("irc_channels",
+ &irc_completion_channels_cb, NULL);
+ weechat_hook_completion ("irc_msg_part",
+ &irc_completion_msg_part_cb, NULL);
}
diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c
index 415c86076..8ced94784 100644
--- a/src/plugins/irc/irc-config.c
+++ b/src/plugins/irc/irc-config.c
@@ -569,11 +569,11 @@ irc_config_server_new_option (struct t_config_file *config_file,
switch (index_option)
{
- case IRC_SERVER_OPTION_AUTOCONNECT:
+ case IRC_SERVER_OPTION_ADDRESSES:
new_option = weechat_config_new_option (
config_file, section,
- option_name, "boolean",
- N_("automatically connect to server when WeeChat is starting"),
+ option_name, "string",
+ N_("list of hostname/port or IP/port for server (separated by comma)"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -581,11 +581,11 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_AUTORECONNECT:
+ case IRC_SERVER_OPTION_PROXY:
new_option = weechat_config_new_option (
config_file, section,
- option_name, "boolean",
- N_("automatically reconnect to server when disconnected"),
+ option_name, "string",
+ N_("proxy used for this server (optional)"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -593,23 +593,23 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_AUTORECONNECT_DELAY:
+ case IRC_SERVER_OPTION_IPV6:
new_option = weechat_config_new_option (
config_file, section,
- option_name, "integer",
- N_("delay (in seconds) before trying again to reconnect to server"),
- NULL, 0, 65535,
+ option_name, "boolean",
+ N_("use IPv6 protocol for server communication"),
+ NULL, 0, 0,
default_value, value,
null_value_allowed,
NULL, NULL,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_PROXY:
+ case IRC_SERVER_OPTION_SSL:
new_option = weechat_config_new_option (
config_file, section,
- option_name, "string",
- N_("proxy used for this server (optional)"),
+ option_name, "boolean",
+ N_("use SSL for server communication"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -617,11 +617,11 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_ADDRESSES:
+ case IRC_SERVER_OPTION_PASSWORD:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
- N_("list of IP/port or hostname/port for server (separated by comma)"),
+ N_("password for server"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -629,11 +629,11 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_IPV6:
+ case IRC_SERVER_OPTION_AUTOCONNECT:
new_option = weechat_config_new_option (
config_file, section,
option_name, "boolean",
- N_("use IPv6 protocol for server communication"),
+ N_("automatically connect to server when WeeChat is starting"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -641,11 +641,11 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_SSL:
+ case IRC_SERVER_OPTION_AUTORECONNECT:
new_option = weechat_config_new_option (
config_file, section,
option_name, "boolean",
- N_("use SSL for server communication"),
+ N_("automatically reconnect to server when disconnected"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -653,12 +653,12 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change, callback_change_data,
NULL, NULL);
break;
- case IRC_SERVER_OPTION_PASSWORD:
+ case IRC_SERVER_OPTION_AUTORECONNECT_DELAY:
new_option = weechat_config_new_option (
config_file, section,
- option_name, "string",
- N_("password for IRC server"),
- NULL, 0, 0,
+ option_name, "integer",
+ N_("delay (in seconds) before trying again to reconnect to server"),
+ NULL, 0, 65535,
default_value, value,
null_value_allowed,
NULL, NULL,
@@ -669,7 +669,7 @@ irc_config_server_new_option (struct t_config_file *config_file,
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
- N_("nicknames to use on IRC server (separated by comma)"),
+ N_("nicknames to use on server (separated by comma)"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -681,7 +681,7 @@ irc_config_server_new_option (struct t_config_file *config_file,
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
- N_("user name to use on IRC server"),
+ N_("user name to use on server"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -693,7 +693,7 @@ irc_config_server_new_option (struct t_config_file *config_file,
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
- N_("real name to use on IRC server"),
+ N_("real name to use on server"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
@@ -1181,7 +1181,7 @@ irc_config_init ()
irc_config_network_send_unknown_commands = weechat_config_new_option (
irc_config_file, ptr_section,
"send_unknown_commands", "boolean",
- N_("send unknown commands to IRC server"),
+ N_("send unknown commands to server"),
NULL, 0, 0, "off", NULL, 0, NULL, NULL,
&irc_config_change_network_send_unknown_commands, NULL, NULL, NULL);
diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h
index f12115958..2ea24f5fc 100644
--- a/src/plugins/irc/irc-config.h
+++ b/src/plugins/irc/irc-config.h
@@ -26,14 +26,6 @@
#define IRC_CONFIG_DISPLAY_AWAY_LOCAL 1
#define IRC_CONFIG_DISPLAY_AWAY_CHANNEL 2
-#define IRC_CONFIG_SERVER_DEFAULT_AUTOCONNECT 0
-#define IRC_CONFIG_SERVER_DEFAULT_AUTORECONNECT 1
-#define IRC_CONFIG_SERVER_DEFAULT_AUTORECONNECT_DELAY 30
-#define IRC_CONFIG_SERVER_DEFAULT_IPV6 0
-#define IRC_CONFIG_SERVER_DEFAULT_SSL 0
-#define IRC_CONFIG_SERVER_DEFAULT_COMMAND_DELAY 1
-#define IRC_CONFIG_SERVER_DEFAULT_AUTOREJOIN 0
-
extern struct t_config_file *irc_config_file;
extern struct t_config_section *irc_config_section_server_default;
diff --git a/src/plugins/irc/irc-display.c b/src/plugins/irc/irc-display.c
index c804a6dcc..4099ae60f 100644
--- a/src/plugins/irc/irc-display.c
+++ b/src/plugins/irc/irc-display.c
@@ -113,7 +113,7 @@ irc_display_away (struct t_irc_server *server, const char *string1, const char *
}
/*
- * irc_display_server: display server description
+ * irc_display_server: display server infos
*/
void
diff --git a/src/plugins/irc/irc-ignore.c b/src/plugins/irc/irc-ignore.c
index f3ad0b791..e116ec8bd 100644
--- a/src/plugins/irc/irc-ignore.c
+++ b/src/plugins/irc/irc-ignore.c
@@ -183,7 +183,7 @@ irc_ignore_new (const char *mask, const char *server, const char *channel)
int
irc_ignore_check (struct t_irc_server *server, struct t_irc_channel *channel,
- char *nick, char *host)
+ const char *nick, const char *host)
{
struct t_irc_ignore *ptr_ignore;
int server_match, channel_match, regex_match;
diff --git a/src/plugins/irc/irc-ignore.h b/src/plugins/irc/irc-ignore.h
index ff116cd8d..5f751a4f9 100644
--- a/src/plugins/irc/irc-ignore.h
+++ b/src/plugins/irc/irc-ignore.h
@@ -48,7 +48,7 @@ extern struct t_irc_ignore *irc_ignore_new (const char *mask,
const char *channel);
extern int irc_ignore_check (struct t_irc_server *server,
struct t_irc_channel *channel,
- char *nick, char *host);
+ const char *nick, const char *host);
extern void irc_ignore_free (struct t_irc_ignore *ignore);
extern void irc_ignore_free_all ();
extern int irc_ignore_add_to_infolist (struct t_infolist *infolist,
diff --git a/src/plugins/irc/irc-info.c b/src/plugins/irc/irc-info.c
index 87911d87c..83c516d55 100644
--- a/src/plugins/irc/irc-info.c
+++ b/src/plugins/irc/irc-info.c
@@ -63,7 +63,8 @@ const char *
irc_info_get_info_cb (void *data, const char *info_name,
const char *arguments)
{
- char *pos_comma, *pos_comma2, *server, *channel, *host, *nick;
+ char *pos_comma, *pos_comma2, *server, *channel, *host;
+ const char *nick;
static char str_true[2] = "1";
struct t_irc_server *ptr_server;
struct t_irc_channel *ptr_channel;
@@ -361,7 +362,7 @@ irc_info_get_infolist_cb (void *data, const char *infolist_name,
void
irc_info_init ()
{
- /* irc info hooks */
+ /* info hooks */
weechat_hook_info ("irc_is_channel", N_("1 if string is an IRC channel"),
&irc_info_get_info_cb, NULL);
weechat_hook_info ("irc_nick_from_host", N_("get nick from IRC host"),
@@ -369,7 +370,7 @@ irc_info_init ()
weechat_hook_info ("irc_buffer", N_("get buffer pointer for an IRC server/channel"),
&irc_info_get_info_cb, NULL);
- /* irc infolist hooks */
+ /* infolist hooks */
weechat_hook_infolist ("irc_server", N_("list of IRC servers"),
&irc_info_get_infolist_cb, NULL);
weechat_hook_infolist ("irc_channel", N_("list of channels for an IRC server"),
diff --git a/src/plugins/irc/irc-input.h b/src/plugins/irc/irc-input.h
index d98406a87..2366c12c7 100644
--- a/src/plugins/irc/irc-input.h
+++ b/src/plugins/irc/irc-input.h
@@ -20,6 +20,10 @@
#ifndef __WEECHAT_IRC_INPUT_H
#define __WEECHAT_IRC_INPUT_H 1
+struct t_gui_buffer;
+
+extern void irc_input_user_message_display (struct t_gui_buffer *buffer,
+ const char *text);
extern int irc_input_data_cb (void *data, struct t_gui_buffer *buffer,
const char *input_data);
diff --git a/src/plugins/irc/irc-nick.c b/src/plugins/irc/irc-nick.c
index 2161c6fb8..549cad1f0 100644
--- a/src/plugins/irc/irc-nick.c
+++ b/src/plugins/irc/irc-nick.c
@@ -34,8 +34,8 @@
/*
* irc_nick_valid: check if a nick pointer exists for a channel
- * return 1 if nick exists
- * 0 if nick is not found
+ * return 1 if nick exists
+ * 0 if nick is not found
*/
int
@@ -419,7 +419,9 @@ irc_nick_free_all (struct t_irc_channel *channel)
/* remove all nicks for the channel */
while (channel->nicks)
+ {
irc_nick_free (channel, channel->nicks);
+ }
/* sould be zero, but prevent any bug :D */
channel->nicks_count = 0;
@@ -443,6 +445,8 @@ irc_nick_search (struct t_irc_channel *channel, const char *nickname)
if (weechat_strcasecmp (ptr_nick->name, nickname) == 0)
return ptr_nick;
}
+
+ /* nick not found */
return NULL;
}
diff --git a/src/plugins/irc/irc-nick.h b/src/plugins/irc/irc-nick.h
index 1eaeeaa23..bdbbeac74 100644
--- a/src/plugins/irc/irc-nick.h
+++ b/src/plugins/irc/irc-nick.h
@@ -61,10 +61,14 @@ extern int irc_nick_valid (struct t_irc_channel *channel,
extern const char *irc_nick_find_color (struct t_irc_nick *nick);
extern struct t_irc_nick *irc_nick_new (struct t_irc_server *server,
struct t_irc_channel *channel,
- const char *nick_name, int is_chanowner,
- int is_chanadmin, int is_chanadmin2,
- int is_op, int is_halfop,
- int has_voice, int is_chanuser,
+ const char *nick_name,
+ int is_chanowner,
+ int is_chanadmin,
+ int is_chanadmin2,
+ int is_op,
+ int is_halfop,
+ int has_voice,
+ int is_chanuser,
int is_away);
extern void irc_nick_change (struct t_irc_server *server,
struct t_irc_channel *channel,
diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c
index f45b4ae91..5d8af3b3b 100644
--- a/src/plugins/irc/irc-protocol.c
+++ b/src/plugins/irc/irc-protocol.c
@@ -49,7 +49,7 @@
* irc_protocol_get_nick_from_host: get nick from host in an IRC message
*/
-char *
+const char *
irc_protocol_get_nick_from_host (const char *host)
{
static char nick[128];
@@ -79,7 +79,7 @@ irc_protocol_get_nick_from_host (const char *host)
* irc_protocol_get_address_from_host: get address from host in an IRC message
*/
-char *
+const char *
irc_protocol_get_address_from_host (const char *host)
{
static char address[256];
@@ -128,7 +128,7 @@ irc_protocol_log_level_for_command (const char *command)
* irc_protocol_tags: build tags list with IRC command and/or tags
*/
-char *
+const char *
irc_protocol_tags (const char *command, const char *tags)
{
static char string[512];
diff --git a/src/plugins/irc/irc-protocol.h b/src/plugins/irc/irc-protocol.h
index 6585140a2..3e3c68eaa 100644
--- a/src/plugins/irc/irc-protocol.h
+++ b/src/plugins/irc/irc-protocol.h
@@ -21,7 +21,7 @@
#define __WEECHAT_IRC_PROTOCOL_H 1
#define IRC_PROTOCOL_GET_HOST \
- char *nick, *address, *host; \
+ const char *nick, *address, *host; \
if (argv[0][0] == ':') \
{ \
nick = irc_protocol_get_nick_from_host (argv[0]); \
@@ -69,8 +69,8 @@ struct t_irc_protocol_msg
t_irc_recv_func *recv_function; /* function called when msg is received */
};
-extern char *irc_protocol_get_nick_from_host (const char *host);
-extern char *irc_protocol_tags (const char *command, const char *tags);
+extern const char *irc_protocol_get_nick_from_host (const char *host);
+extern const char *irc_protocol_tags (const char *command, const char *tags);
extern void irc_protocol_recv_command (struct t_irc_server *server,
const char *entire_line,
const char *host, const char *command,
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index 4b4709826..1ba258883 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* irc-server.c: connection and communication with IRC server */
+/* irc-server.c: connection and I/O communication with IRC server */
#include <stdlib.h>
@@ -26,8 +26,16 @@
#include <stdarg.h>
#include <string.h>
#include <time.h>
+#ifdef _WIN32
+#include <winsock.h>
+#else
#include <sys/socket.h>
#include <sys/time.h>
+#endif
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
#include "../weechat-plugin.h"
#include "irc.h"
@@ -682,11 +690,8 @@ irc_server_free (struct t_irc_server *server)
if (!server)
return;
- /* close any opened channel/private */
- while (server->channels)
- {
- irc_channel_free (server, server->channels);
- }
+ /* close all channels/privates */
+ irc_channel_free_all (server);
/* remove server from queue */
if (last_irc_server == server)
@@ -1287,8 +1292,7 @@ irc_server_msgq_add_msg (struct t_irc_server *server, const char *msg)
if (!message)
{
weechat_printf (server->buffer,
- _("%s%s: not enough memory for received IRC "
- "message"),
+ _("%s%s: not enough memory for received message"),
irc_buffer_get_server_prefix (server, "error"),
IRC_PLUGIN_NAME);
return;
@@ -1301,8 +1305,7 @@ irc_server_msgq_add_msg (struct t_irc_server *server, const char *msg)
if (!message->data)
{
weechat_printf (server->buffer,
- _("%s%s: not enough memory for received IRC "
- "message"),
+ _("%s%s: not enough memory for received message"),
irc_buffer_get_server_prefix (server, "error"),
IRC_PLUGIN_NAME);
}
@@ -1349,8 +1352,7 @@ irc_server_msgq_add_unterminated (struct t_irc_server *server, const char *strin
if (!server->unterminated_message)
{
weechat_printf (server->buffer,
- _("%s%s: not enough memory for received IRC "
- "message"),
+ _("%s%s: not enough memory for received message"),
irc_buffer_get_server_prefix (server, "error"),
IRC_PLUGIN_NAME);
}
@@ -1363,8 +1365,7 @@ irc_server_msgq_add_unterminated (struct t_irc_server *server, const char *strin
if (!server->unterminated_message)
{
weechat_printf (server->buffer,
- _("%s%s: not enough memory for received IRC "
- "message"),
+ _("%s%s: not enough memory for received message"),
irc_buffer_get_server_prefix (server, "error"),
IRC_PLUGIN_NAME);
}
@@ -1714,7 +1715,11 @@ irc_server_close_connection (struct t_irc_server *server)
}
if (server->sock != -1)
{
+#ifdef _WIN32
+ closesocket (server->sock);
+#else
close (server->sock);
+#endif
server->sock = -1;
}
@@ -1813,7 +1818,7 @@ irc_server_switch_address (struct t_irc_server *server)
IRC_PLUGIN_NAME,
server->addresses_array[server->index_current_address],
server->ports_array[server->index_current_address]);
- irc_server_connect (server, 0);
+ irc_server_connect (server);
}
else
irc_server_reconnect_schedule (server);
@@ -1848,11 +1853,11 @@ irc_server_connect_cb (void *arg_server, int status, const char *ip_address)
IRC_PLUGIN_NAME,
server->addresses_array[server->index_current_address],
(server->current_ip) ? server->current_ip : "?");
- irc_server_login (server);
server->hook_fd = weechat_hook_fd (server->sock,
1, 0, 0,
&irc_server_recv_cb,
server);
+ irc_server_login (server);
break;
case WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND:
weechat_printf (server->buffer,
@@ -1890,8 +1895,8 @@ irc_server_connect_cb (void *arg_server, int status, const char *ip_address)
_("%s%s: proxy fails to establish "
"connection to server "
"(check username/password if used "
- "and if IRC server address/port is "
- "allowed by proxy)"),
+ "and if server address/port is allowed by "
+ "proxy)"),
irc_buffer_get_server_prefix (server, "error"),
IRC_PLUGIN_NAME);
irc_server_close_connection (server);
@@ -2054,20 +2059,13 @@ irc_server_set_current_server (struct t_irc_server *server)
*/
int
-irc_server_connect (struct t_irc_server *server, int disable_autojoin)
+irc_server_connect (struct t_irc_server *server)
{
int set, length;
char *option_name, charset_modifier[256];
struct t_config_option *proxy_type, *proxy_ipv6, *proxy_address, *proxy_port;
const char *proxy, *str_proxy_type, *str_proxy_address;
- proxy_type = NULL;
- proxy_ipv6 = NULL;
- proxy_address = NULL;
- proxy_port = NULL;
- str_proxy_type = NULL;
- str_proxy_address = NULL;
-
if (!server->buffer)
{
if (weechat_config_boolean (irc_config_look_one_server_buffer)
@@ -2104,6 +2102,23 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin)
"/command irc /server switch");
}
+ if (!server->addresses_array)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: addresses not defined for server \"%s\", "
+ "cannot connect"),
+ irc_buffer_get_server_prefix (server, "error"),
+ IRC_PLUGIN_NAME, server->name);
+ return 0;
+ }
+
+ proxy_type = NULL;
+ proxy_ipv6 = NULL;
+ proxy_address = NULL;
+ proxy_port = NULL;
+ str_proxy_type = NULL;
+ str_proxy_address = NULL;
+
proxy = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PROXY);
if (proxy && proxy[0])
{
@@ -2149,16 +2164,6 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin)
}
}
- if (!server->addresses_array)
- {
- weechat_printf (server->buffer,
- _("%s%s: addresses not defined for server \"%s\", "
- "cannot connect"),
- irc_buffer_get_server_prefix (server, "error"),
- IRC_PLUGIN_NAME, server->name);
- return 0;
- }
-
if (!server->nicks_array)
{
weechat_printf (server->buffer,
@@ -2173,7 +2178,7 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin)
if (weechat_config_boolean (IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_SSL)))
{
weechat_printf (server->buffer,
- _("%s%s: cannot connect with SSL since WeeChat "
+ _("%s%s: cannot connect with SSL because WeeChat "
"was not built with GnuTLS support"),
irc_buffer_get_server_prefix (server, "error"),
IRC_PLUGIN_NAME);
@@ -2233,7 +2238,7 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin)
" (SSL)" : "");
}
- /* close connection if open */
+ /* close connection if opened */
irc_server_close_connection (server);
/* create socket and set options */
@@ -2289,8 +2294,6 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin)
server->ssl_connected = 1;
#endif
- server->disable_autojoin = disable_autojoin;
-
server->hook_connect = weechat_hook_connect (proxy,
server->addresses_array[server->index_current_address],
server->ports_array[server->index_current_address],
@@ -2302,7 +2305,7 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin)
NULL,
#endif
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_LOCAL_HOSTNAME),
- irc_server_connect_cb,
+ &irc_server_connect_cb,
server);
/* send signal "irc_server_connecting" with server name */
@@ -2326,7 +2329,7 @@ irc_server_reconnect (struct t_irc_server *server)
server->reconnect_start = 0;
server->index_current_address = 0;
- if (irc_server_connect (server, 0))
+ if (irc_server_connect (server))
server->reconnect_join = 1;
else
irc_server_reconnect_schedule (server);
@@ -2337,17 +2340,16 @@ irc_server_reconnect (struct t_irc_server *server)
*/
void
-irc_server_auto_connect (int auto_connect)
+irc_server_auto_connect ()
{
struct t_irc_server *ptr_server;
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
- if (auto_connect
- && IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTOCONNECT))
+ if (IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTOCONNECT))
{
- if (!irc_server_connect (ptr_server, 0))
+ if (!irc_server_connect (ptr_server))
irc_server_reconnect_schedule (ptr_server);
}
}
@@ -2364,7 +2366,8 @@ irc_server_disconnect (struct t_irc_server *server, int reconnect)
if (server->is_connected)
{
- /* write disconnection message on each channel/private buffer */
+ /* remove all nicks and write disconnection message on each
+ channel/private buffer */
for (ptr_channel = server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
@@ -2379,10 +2382,12 @@ irc_server_disconnect (struct t_irc_server *server, int reconnect)
irc_server_close_connection (server);
if (server->buffer)
+ {
weechat_printf (server->buffer,
_("%s%s: disconnected from server"),
irc_buffer_get_server_prefix (server, NULL),
IRC_PLUGIN_NAME);
+ }
server->index_current_address = 0;
if (server->nick_modes)
@@ -2577,7 +2582,7 @@ irc_server_get_pv_count (struct t_irc_server *server)
for (ptr_channel = server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
- if (ptr_channel->type != IRC_CHANNEL_TYPE_CHANNEL)
+ if (ptr_channel->type == IRC_CHANNEL_TYPE_PRIVATE)
count++;
}
return count;
@@ -2888,21 +2893,12 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
&& (irc_current_server != server)) ?
0 : 1))
return 0;
- if (!weechat_infolist_new_var_integer (ptr_item, "autoconnect",
- IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOCONNECT)))
- return 0;
- if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect",
- IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTORECONNECT)))
- return 0;
- if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect_delay",
- IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AUTORECONNECT_DELAY)))
+ if (!weechat_infolist_new_var_string (ptr_item, "addresses",
+ IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_ADDRESSES)))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "proxy",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PROXY)))
return 0;
- if (!weechat_infolist_new_var_string (ptr_item, "addresses",
- IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_ADDRESSES)))
- return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "ipv6",
IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_IPV6)))
return 0;
@@ -2912,6 +2908,15 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
if (!weechat_infolist_new_var_string (ptr_item, "password",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD)))
return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autoconnect",
+ IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOCONNECT)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect",
+ IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTORECONNECT)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect_delay",
+ IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AUTORECONNECT_DELAY)))
+ return 0;
if (!weechat_infolist_new_var_string (ptr_item, "nicks",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_NICKS)))
return 0;
@@ -2940,6 +2945,8 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "index_current_address", server->index_current_address))
return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "current_ip", server->current_ip))
+ return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "sock", server->sock))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "is_connected", server->is_connected))
@@ -2999,13 +3006,13 @@ irc_server_print_log ()
weechat_log_printf ("[server %s (addr:0x%lx)]", ptr_server->name, ptr_server);
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_ADDRESSES]))
- weechat_log_printf (" addresses. . . . . . : null (%s)",
+ weechat_log_printf (" addresses. . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_ADDRESSES));
else
weechat_log_printf (" addresses. . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_ADDRESSES]));
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_PROXY]))
- weechat_log_printf (" proxy. . . . . . . . : null (%s)",
+ weechat_log_printf (" proxy. . . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_PROXY));
else
weechat_log_printf (" proxy. . . . . . . . : '%s'",
@@ -3053,25 +3060,25 @@ irc_server_print_log ()
weechat_log_printf (" autoreconnect_delay. : %d",
weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_AUTORECONNECT_DELAY]));
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_NICKS]))
- weechat_log_printf (" nicks. . . . . . . . : null (%s)",
+ weechat_log_printf (" nicks. . . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_NICKS));
else
weechat_log_printf (" nicks. . . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_NICKS]));
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_USERNAME]))
- weechat_log_printf (" username . . . . . . : null (%s)",
+ weechat_log_printf (" username . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_USERNAME));
else
weechat_log_printf (" username . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_USERNAME]));
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_REALNAME]))
- weechat_log_printf (" realname . . . . . . : null (%s)",
+ weechat_log_printf (" realname . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_REALNAME));
else
weechat_log_printf (" realname . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_REALNAME]));
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_LOCAL_HOSTNAME]))
- weechat_log_printf (" local_hostname . . . : null (%s)",
+ weechat_log_printf (" local_hostname . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_LOCAL_HOSTNAME));
else
weechat_log_printf (" local_hostname . . . : '%s'",
@@ -3087,7 +3094,7 @@ irc_server_print_log ()
weechat_log_printf (" command_delay. . . . : %d",
weechat_config_integer (ptr_server->options[IRC_SERVER_OPTION_COMMAND_DELAY]));
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOJOIN]))
- weechat_log_printf (" autojoin . . . . . . : null (%s)",
+ weechat_log_printf (" autojoin . . . . . . : null ('%s')",
IRC_SERVER_OPTION_STRING(ptr_server, IRC_SERVER_OPTION_AUTOJOIN));
else
weechat_log_printf (" autojoin . . . . . . : '%s'",
@@ -3106,11 +3113,16 @@ irc_server_print_log ()
weechat_log_printf (" addresses_count. . . : %d", ptr_server->addresses_count);
weechat_log_printf (" addresses_array. . . : 0x%lx", ptr_server->addresses_array);
weechat_log_printf (" ports_array. . . . . : 0x%lx", ptr_server->ports_array);
+ weechat_log_printf (" index_current_address: %d", ptr_server->index_current_address);
+ weechat_log_printf (" current_ip . . . . . : '%s'", ptr_server->current_ip);
weechat_log_printf (" sock . . . . . . . . : %d", ptr_server->sock);
weechat_log_printf (" hook_connect . . . . : 0x%lx", ptr_server->hook_connect);
weechat_log_printf (" hook_fd. . . . . . . : 0x%lx", ptr_server->hook_fd);
weechat_log_printf (" is_connected . . . . : %d", ptr_server->is_connected);
weechat_log_printf (" ssl_connected. . . . : %d", ptr_server->ssl_connected);
+#ifdef HAVE_GNUTLS
+ weechat_log_printf (" gnutls_sess. . . . . : 0x%lx", ptr_server->gnutls_sess);
+#endif
weechat_log_printf (" unterminated_message : '%s'", ptr_server->unterminated_message);
weechat_log_printf (" nicks_count. . . . . : %d", ptr_server->nicks_count);
weechat_log_printf (" nicks_array. . . . . : 0x%lx", ptr_server->nicks_array);
@@ -3129,15 +3141,18 @@ irc_server_print_log ()
ptr_server->lag_check_time.tv_sec,
ptr_server->lag_check_time.tv_usec);
weechat_log_printf (" lag_next_check . . . : %ld", ptr_server->lag_next_check);
+ weechat_log_printf (" cmd_list_regexp. . . : 0x%lx", ptr_server->cmd_list_regexp);
+ weechat_log_printf (" queue_msg. . . . . . : %d", ptr_server->queue_msg);
weechat_log_printf (" last_user_message. . : %ld", ptr_server->last_user_message);
weechat_log_printf (" outqueue . . . . . . : 0x%lx", ptr_server->outqueue);
weechat_log_printf (" last_outqueue. . . . : 0x%lx", ptr_server->last_outqueue);
weechat_log_printf (" buffer . . . . . . . : 0x%lx", ptr_server->buffer);
+ weechat_log_printf (" buffer_as_string . . : 0x%lx", ptr_server->buffer_as_string);
weechat_log_printf (" channels . . . . . . : 0x%lx", ptr_server->channels);
weechat_log_printf (" last_channel . . . . : 0x%lx", ptr_server->last_channel);
weechat_log_printf (" prev_server. . . . . : 0x%lx", ptr_server->prev_server);
weechat_log_printf (" next_server. . . . . : 0x%lx", ptr_server->next_server);
-
+
for (ptr_channel = ptr_server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h
index eb0b9ff53..ac6211a52 100644
--- a/src/plugins/irc/irc-server.h
+++ b/src/plugins/irc/irc-server.h
@@ -54,23 +54,23 @@ enum t_irc_server_option
};
#define IRC_SERVER_OPTION_BOOLEAN(__server, __index) \
- ((!weechat_config_option_is_null (__server->options[__index])) ? \
+ ((!weechat_config_option_is_null(__server->options[__index])) ? \
weechat_config_boolean(__server->options[__index]) : \
- ((!weechat_config_option_is_null (irc_config_server_default[__index])) ? \
+ ((!weechat_config_option_is_null(irc_config_server_default[__index])) ? \
weechat_config_boolean(irc_config_server_default[__index]) \
: weechat_config_boolean_default(irc_config_server_default[__index])))
#define IRC_SERVER_OPTION_INTEGER(__server, __index) \
- ((!weechat_config_option_is_null (__server->options[__index])) ? \
+ ((!weechat_config_option_is_null(__server->options[__index])) ? \
weechat_config_integer(__server->options[__index]) : \
- ((!weechat_config_option_is_null (irc_config_server_default[__index])) ? \
+ ((!weechat_config_option_is_null(irc_config_server_default[__index])) ? \
weechat_config_integer(irc_config_server_default[__index]) \
: weechat_config_integer_default(irc_config_server_default[__index])))
#define IRC_SERVER_OPTION_STRING(__server, __index) \
- ((!weechat_config_option_is_null (__server->options[__index])) ? \
+ ((!weechat_config_option_is_null(__server->options[__index])) ? \
weechat_config_string(__server->options[__index]) : \
- ((!weechat_config_option_is_null (irc_config_server_default[__index])) ? \
+ ((!weechat_config_option_is_null(irc_config_server_default[__index])) ? \
weechat_config_string(irc_config_server_default[__index]) \
: weechat_config_string_default(irc_config_server_default[__index])))
@@ -147,7 +147,7 @@ struct t_irc_server
struct t_gui_buffer *buffer; /* GUI buffer allocated for server */
char *buffer_as_string; /* used to return buffer info */
struct t_irc_channel *channels; /* opened channels on server */
- struct t_irc_channel *last_channel; /* last opened channal on server */
+ struct t_irc_channel *last_channel; /* last opened channel on server */
struct t_irc_server *prev_server; /* link to previous server */
struct t_irc_server *next_server; /* link to next server */
};
@@ -194,9 +194,8 @@ extern void irc_server_set_buffer_title (struct t_irc_server *server);
extern struct t_gui_buffer *irc_server_create_buffer (struct t_irc_server *server,
int all_servers);
extern void irc_server_set_current_server (struct t_irc_server *server);
-extern int irc_server_connect (struct t_irc_server *server,
- int disable_autojoin);
-extern void irc_server_auto_connect (int auto_connect);
+extern int irc_server_connect (struct t_irc_server *server);
+extern void irc_server_auto_connect ();
extern void irc_server_autojoin_channels ();
extern int irc_server_recv_cb (void *arg_server);
extern int irc_server_timer_cb (void *data);
diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c
index 0b138b9a0..857683b69 100644
--- a/src/plugins/irc/irc-upgrade.c
+++ b/src/plugins/irc/irc-upgrade.c
@@ -162,7 +162,7 @@ irc_upgrade_set_buffer_callbacks ()
}
/*
- * irc_upgrade_read_cb: read callback for
+ * irc_upgrade_read_cb: read callback for upgrade
*/
int
diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c
index 70f41fd5c..b9ee5ae04 100644
--- a/src/plugins/irc/irc.c
+++ b/src/plugins/irc/irc.c
@@ -146,7 +146,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
if (!irc_server_alloc_with_url (argv[i]))
{
weechat_printf (NULL,
- _("%s%s: error with IRC server from URL "
+ _("%s%s: error with server from URL "
"(\"%s\"), ignored"),
weechat_prefix ("error"), IRC_PLUGIN_NAME,
argv[i]);
@@ -164,13 +164,16 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
{
weechat_printf (NULL,
_("%s%s: WARNING: some network connections may "
- "still be open and not visible, you should "
+ "still be opened and not visible, you should "
"restart WeeChat now (with /quit)."),
weechat_prefix ("error"), IRC_PLUGIN_NAME);
}
}
else
- irc_server_auto_connect (auto_connect);
+ {
+ if (auto_connect)
+ irc_server_auto_connect ();
+ }
irc_hook_timer = weechat_hook_timer (1 * 1000, 0, 0,
&irc_server_timer_cb, NULL);
diff --git a/src/plugins/irc/irc.h b/src/plugins/irc/irc.h
index e26d5f782..de8e1ece2 100644
--- a/src/plugins/irc/irc.h
+++ b/src/plugins/irc/irc.h
@@ -20,10 +20,6 @@
#ifndef __WEECHAT_IRC_H
#define __WEECHAT_IRC_H 1
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
#define weechat_plugin weechat_irc_plugin
#define IRC_PLUGIN_NAME "irc"
diff --git a/src/plugins/jabber/CMakeLists.txt b/src/plugins/jabber/CMakeLists.txt
new file mode 100644
index 000000000..57ec9c56b
--- /dev/null
+++ b/src/plugins/jabber/CMakeLists.txt
@@ -0,0 +1,45 @@
+# Copyright (c) 2009 FlashCode <flashcode@flashtux.org>
+#
+# This program 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.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+ADD_LIBRARY(jabber MODULE
+jabber.c jabber.h
+jabber-bar-item.c jabber-bar-item.h
+jabber-buddy.c jabber-buddy.h
+jabber-buffer.c jabber-buffer.h
+jabber-command.c jabber-command.h
+jabber-completion.c jabber-completion.h
+jabber-config.c jabber-config.h
+jabber-debug.c jabber-debug.h
+jabber-display.c jabber-display.h
+jabber-info.c jabber-info.h
+jabber-input.c jabber-input.h
+jabber-muc.c jabber-muc.h
+jabber-server.c jabber-server.h
+jabber-upgrade.c jabber-upgrade.h
+jabber-xmpp.c jabber-xmpp.h)
+SET_TARGET_PROPERTIES(jabber PROPERTIES PREFIX "")
+
+CHECK_INCLUDE_FILES("regex.h" HAVE_REGEX_H)
+CHECK_FUNCTION_EXISTS(regexec HAVE_REGEXEC)
+
+IF(GNUTLS_FOUND)
+ INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_PATH} ${IKSEMEL_INCLUDE_PATH})
+ TARGET_LINK_LIBRARIES(jabber ${GNUTLS_LIBRARY} ${IKSEMEL_LIBRARY})
+ELSE(GNUTLS_FOUND)
+ TARGET_LINK_LIBRARIES(jabber ${IKSEMEL_LIBRARY})
+ENDIF(GNUTLS_FOUND)
+
+INSTALL(TARGETS jabber LIBRARY DESTINATION lib/${PROJECT_NAME}/plugins)
diff --git a/src/plugins/jabber/Makefile.am b/src/plugins/jabber/Makefile.am
new file mode 100644
index 000000000..fb8d38975
--- /dev/null
+++ b/src/plugins/jabber/Makefile.am
@@ -0,0 +1,55 @@
+# Copyright (c) 2009 FlashCode <flashcode@flashtux.org>
+#
+# This program 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.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+INCLUDES = -DLOCALEDIR=\"$(datadir)/locale\" $(GNUTLS_CFLAGS) $(IKSEMEL_CFLAGS)
+
+libdir = ${weechat_libdir}/plugins
+
+lib_LTLIBRARIES = jabber.la
+
+jabber_la_SOURCES = jabber.c \
+ jabber.h \
+ jabber-bar-item.c \
+ jabber-bar-item.h \
+ jabber-buddy.c \
+ jabber-buddy.h \
+ jabber-buffer.c \
+ jabber-buffer.h \
+ jabber-command.c \
+ jabber-command.h \
+ jabber-completion.c \
+ jabber-completion.h \
+ jabber-config.c \
+ jabber-config.h \
+ jabber-debug.c \
+ jabber-debug.h \
+ jabber-display.c \
+ jabber-display.h \
+ jabber-info.c \
+ jabber-info.h \
+ jabber-input.c \
+ jabber-input.h \
+ jabber-muc.c \
+ jabber-muc.h \
+ jabber-server.c \
+ jabber-server.h \
+ jabber-upgrade.c \
+ jabber-upgrade.h \
+ jabber-xmpp.c \
+ jabber-xmpp.h
+
+jabber_la_LDFLAGS = -module
+jabber_la_LIBADD = $(JABBER_LFLAGS) $(GNUTLS_LFLAGS) $(IKSEMEL_LFLAGS)
diff --git a/src/plugins/jabber/jabber-bar-item.c b/src/plugins/jabber/jabber-bar-item.c
new file mode 100644
index 000000000..83a77514b
--- /dev/null
+++ b/src/plugins/jabber/jabber-bar-item.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-bar-item.c: bar items for Jabber plugin */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-buffer.h"
+#include "jabber-config.h"
+#include "jabber-server.h"
+#include "jabber-muc.h"
+
+
+/*
+ * jabber_bar_item_buffer_name: bar item with buffer name
+ */
+
+char *
+jabber_bar_item_buffer_name (void *data, struct t_gui_bar_item *item,
+ struct t_gui_window *window)
+{
+ char buf[512], buf_name[256], modes[128], away[128];
+ const char *name;
+ int part_from_muc;
+ struct t_gui_buffer *buffer;
+ struct t_jabber_server *server;
+ struct t_jabber_muc *muc;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) item;
+
+ if (!window)
+ window = weechat_current_window ();
+
+ buf_name[0] = '\0';
+ modes[0] = '\0';
+ away[0] = '\0';
+
+ buffer = weechat_window_get_pointer (window, "buffer");
+
+ if (buffer)
+ {
+ jabber_buffer_get_server_muc (buffer, &server, &muc);
+ if (server || muc)
+ {
+ if (server && !muc)
+ {
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer))
+ {
+ snprintf (buf_name, sizeof (buf_name), "%s%s[<%s%s%s>]",
+ _("servers"),
+ JABBER_COLOR_BAR_DELIM,
+ JABBER_COLOR_STATUS_NAME,
+ (jabber_current_server) ? jabber_current_server->name : "-",
+ JABBER_COLOR_BAR_DELIM);
+ }
+ else
+ {
+ snprintf (buf_name, sizeof (buf_name), "%s%s[%s%s%s]",
+ _("server"),
+ JABBER_COLOR_BAR_DELIM,
+ JABBER_COLOR_STATUS_NAME,
+ server->name,
+ JABBER_COLOR_BAR_DELIM);
+ }
+ }
+ else
+ {
+ if (muc)
+ {
+ part_from_muc = ((muc->type == JABBER_MUC_TYPE_MUC)
+ && !muc->buddies);
+ snprintf (buf_name, sizeof (buf_name),
+ "%s%s%s%s%s/%s%s%s%s",
+ (part_from_muc) ? JABBER_COLOR_BAR_DELIM : "",
+ (part_from_muc) ? "(" : "",
+ JABBER_COLOR_STATUS_NAME,
+ server->name,
+ JABBER_COLOR_BAR_DELIM,
+ JABBER_COLOR_STATUS_NAME,
+ muc->name,
+ (part_from_muc) ? JABBER_COLOR_BAR_DELIM : "",
+ (part_from_muc) ? ")" : "");
+ if (!part_from_muc
+ && weechat_config_boolean (jabber_config_look_display_muc_modes)
+ && muc->modes && muc->modes[0]
+ && (strcmp (muc->modes, "+") != 0))
+ {
+ snprintf (modes, sizeof (modes),
+ "%s(%s%s%s)",
+ JABBER_COLOR_BAR_DELIM,
+ JABBER_COLOR_STATUS_NAME,
+ muc->modes,
+ JABBER_COLOR_BAR_DELIM);
+ }
+ }
+ }
+ if (server && server->is_away)
+ {
+ snprintf (away, sizeof (away), " %s(%s%s%s)",
+ JABBER_COLOR_BAR_DELIM,
+ JABBER_COLOR_BAR_FG,
+ _("away"),
+ JABBER_COLOR_BAR_DELIM);
+ }
+ }
+ else
+ {
+ name = weechat_buffer_get_string (buffer, "name");
+ if (name)
+ snprintf (buf_name, sizeof (buf_name), "%s", name);
+ }
+
+ snprintf (buf, sizeof (buf), "%s%s%s%s",
+ JABBER_COLOR_STATUS_NAME,
+ buf_name,
+ modes,
+ away);
+ return strdup (buf);
+ }
+
+ return NULL;
+}
+
+/*
+ * jabber_bar_item_input_prompt: bar item with input prompt
+ */
+
+char *
+jabber_bar_item_input_prompt (void *data, struct t_gui_bar_item *item,
+ struct t_gui_window *window)
+{
+ struct t_gui_buffer *buffer;
+ struct t_jabber_server *server;
+ const char *local_name;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) item;
+
+ if (!window)
+ window = weechat_current_window ();
+
+ buffer = weechat_window_get_pointer (window, "buffer");
+
+ if (buffer)
+ {
+ jabber_buffer_get_server_muc (buffer, &server, NULL);
+ if (!server)
+ return NULL;
+
+ local_name = jabber_server_get_local_name (server);
+
+ return (local_name) ? strdup (local_name) : NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * jabber_bar_item_init: initialize Jabber bar items
+ */
+
+void
+jabber_bar_item_init ()
+{
+ weechat_bar_item_new ("buffer_name", &jabber_bar_item_buffer_name, NULL);
+ weechat_bar_item_new ("input_prompt", &jabber_bar_item_input_prompt, NULL);
+}
diff --git a/src/plugins/jabber/jabber-bar-item.h b/src/plugins/jabber/jabber-bar-item.h
new file mode 100644
index 000000000..a73bfc65d
--- /dev/null
+++ b/src/plugins/jabber/jabber-bar-item.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_BAR_ITEM_H
+#define __WEECHAT_JABBER_BAR_ITEM_H 1
+
+extern void jabber_bar_item_init ();
+
+#endif /* jabber-bar-item.h */
diff --git a/src/plugins/jabber/jabber-buddy.c b/src/plugins/jabber/jabber-buddy.c
new file mode 100644
index 000000000..7d2adfebe
--- /dev/null
+++ b/src/plugins/jabber/jabber-buddy.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-buddy.c: manages buddies list for servers and MUCs */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-buddy.h"
+#include "jabber-config.h"
+#include "jabber-server.h"
+#include "jabber-muc.h"
+
+
+/*
+ * jabber_buddy_valid: check if a buddy pointer exists for a server or a muc
+ * return 1 if buddy exists
+ * 0 if buddy is not found
+ */
+
+int
+jabber_buddy_valid (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy)
+{
+ struct t_jabber_buddy *ptr_buddy;
+
+ if (server)
+ {
+ for (ptr_buddy = server->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (ptr_buddy == buddy)
+ return 1;
+ }
+ }
+
+ if (muc)
+ {
+ for (ptr_buddy = muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (ptr_buddy == buddy)
+ return 1;
+ }
+ }
+
+ /* buddy not found */
+ return 0;
+}
+
+/*
+ * jabber_buddy_find_color: find a color for a buddy (according to buddy letters)
+ */
+
+const char *
+jabber_buddy_find_color (struct t_jabber_buddy *buddy)
+{
+ int i, color;
+ char color_name[64];
+
+ color = 0;
+ for (i = strlen (buddy->name) - 1; i >= 0; i--)
+ {
+ color += (int)(buddy->name[i]);
+ }
+ color = (color %
+ weechat_config_integer (weechat_config_get ("weechat.look.color_nicks_number")));
+
+ snprintf (color_name, sizeof (color_name),
+ "chat_buddy_color%02d", color + 1);
+
+ return weechat_color (color_name);
+}
+
+/*
+ * jabber_buddy_get_gui_infos: get GUI infos for a buddy (sort_index, prefix,
+ * prefix color)
+ */
+
+void
+jabber_buddy_get_gui_infos (struct t_jabber_buddy *buddy,
+ char *prefix, int *prefix_color,
+ struct t_gui_buffer *buffer,
+ struct t_gui_nick_group **group)
+{
+ if (buddy->flags & JABBER_BUDDY_CHANOWNER)
+ {
+ if (prefix)
+ *prefix = '~';
+ if (prefix_color)
+ *prefix_color = 1;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_OP);
+ }
+ else if (buddy->flags & JABBER_BUDDY_CHANADMIN)
+ {
+ if (prefix)
+ *prefix = '&';
+ if (prefix_color)
+ *prefix_color = 1;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_OP);
+ }
+ else if (buddy->flags & JABBER_BUDDY_CHANADMIN2)
+ {
+ if (prefix)
+ *prefix = '!';
+ if (prefix_color)
+ *prefix_color = 1;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_OP);
+ }
+ else if (buddy->flags & JABBER_BUDDY_OP)
+ {
+ if (prefix)
+ *prefix = '@';
+ if (prefix_color)
+ *prefix_color = 1;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_OP);
+ }
+ else if (buddy->flags & JABBER_BUDDY_HALFOP)
+ {
+ if (prefix)
+ *prefix = '%';
+ if (prefix_color)
+ *prefix_color = 2;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_HALFOP);
+ }
+ else if (buddy->flags & JABBER_BUDDY_VOICE)
+ {
+ if (prefix)
+ *prefix = '+';
+ if (prefix_color)
+ *prefix_color = 3;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_VOICE);
+ }
+ else if (buddy->flags & JABBER_BUDDY_CHANUSER)
+ {
+ if (prefix)
+ *prefix = '-';
+ if (prefix_color)
+ *prefix_color = 4;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_CHANUSER);
+ }
+ else
+ {
+ if (prefix)
+ *prefix = ' ';
+ if (prefix_color)
+ *prefix_color = 0;
+ if (buffer && group)
+ *group = weechat_nicklist_search_group (buffer, NULL,
+ JABBER_BUDDY_GROUP_NORMAL);
+ }
+}
+
+/*
+ * jabber_buddy_new: allocate a new buddy for a muc and add it to the buddy list
+ */
+
+struct t_jabber_buddy *
+jabber_buddy_new (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ const char *buddy_name, int is_chanowner, int is_chanadmin,
+ int is_chanadmin2, int is_op, int is_halfop, int has_voice,
+ int is_chanuser, int is_away)
+{
+ struct t_jabber_buddy *new_buddy, *ptr_buddy;
+ char prefix, str_prefix_color[64];
+ const char *local_name;
+ int prefix_color;
+ struct t_gui_buffer *ptr_buffer;
+ struct t_gui_nick_group *ptr_group;
+
+ ptr_buffer = (muc) ? muc->buffer : server->buffer;
+
+ /* buddy already exists on this muc? */
+ if (muc)
+ ptr_buddy = jabber_buddy_search (NULL, muc, buddy_name);
+ else
+ ptr_buddy = jabber_buddy_search (server, NULL, buddy_name);
+ if (ptr_buddy)
+ {
+ /* remove old buddy from buddylist */
+ jabber_buddy_get_gui_infos (ptr_buddy, &prefix,
+ &prefix_color, ptr_buffer, &ptr_group);
+ weechat_nicklist_remove_nick (ptr_buffer,
+ weechat_nicklist_search_nick (ptr_buffer,
+ ptr_group,
+ ptr_buddy->name));
+
+ /* update buddy */
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_chanowner, JABBER_BUDDY_CHANOWNER);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_chanadmin, JABBER_BUDDY_CHANADMIN);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_chanadmin2, JABBER_BUDDY_CHANADMIN2);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_op, JABBER_BUDDY_OP);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_halfop, JABBER_BUDDY_HALFOP);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, has_voice, JABBER_BUDDY_VOICE);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_chanuser, JABBER_BUDDY_CHANUSER);
+ JABBER_BUDDY_SET_FLAG(ptr_buddy, is_away, JABBER_BUDDY_AWAY);
+
+ /* add new buddy in buddylist */
+ jabber_buddy_get_gui_infos (ptr_buddy, &prefix,
+ &prefix_color, ptr_buffer, &ptr_group);
+ snprintf (str_prefix_color, sizeof (str_prefix_color),
+ "weechat.color.nicklist_prefix%d",
+ prefix_color);
+ weechat_nicklist_add_nick (ptr_buffer, ptr_group,
+ ptr_buddy->name,
+ (is_away) ?
+ "weechat.color.nicklist_away" : "bar_fg",
+ prefix, str_prefix_color, 1);
+
+ return ptr_buddy;
+ }
+
+ /* alloc memory for new buddy */
+ if ((new_buddy = malloc (sizeof (*new_buddy))) == NULL)
+ return NULL;
+
+ /* initialize new buddy */
+ new_buddy->name = strdup (buddy_name);
+ new_buddy->host = NULL;
+ new_buddy->flags = 0;
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_chanowner, JABBER_BUDDY_CHANOWNER);
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_chanadmin, JABBER_BUDDY_CHANADMIN);
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_chanadmin2, JABBER_BUDDY_CHANADMIN2);
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_op, JABBER_BUDDY_OP);
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_halfop, JABBER_BUDDY_HALFOP);
+ JABBER_BUDDY_SET_FLAG(new_buddy, has_voice, JABBER_BUDDY_VOICE);
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_chanuser, JABBER_BUDDY_CHANUSER);
+ JABBER_BUDDY_SET_FLAG(new_buddy, is_away, JABBER_BUDDY_AWAY);
+ local_name = jabber_server_get_local_name (server);
+ if (weechat_strcasecmp (new_buddy->name, local_name) == 0)
+ new_buddy->color = JABBER_COLOR_CHAT_NICK_SELF;
+ else
+ new_buddy->color = jabber_buddy_find_color (new_buddy);
+
+ /* add buddy to end of list */
+ if (muc)
+ {
+ new_buddy->prev_buddy = muc->last_buddy;
+ if (muc->buddies)
+ muc->last_buddy->next_buddy = new_buddy;
+ else
+ muc->buddies = new_buddy;
+ muc->last_buddy = new_buddy;
+ new_buddy->next_buddy = NULL;
+
+ muc->buddies_count++;
+
+ muc->nick_completion_reset = 1;
+ }
+ else
+ {
+ new_buddy->prev_buddy = server->last_buddy;
+ if (server->buddies)
+ server->last_buddy->next_buddy = new_buddy;
+ else
+ server->buddies = new_buddy;
+ server->last_buddy = new_buddy;
+ new_buddy->next_buddy = NULL;
+
+ server->buddies_count++;
+ }
+
+ /* add buddy to buffer buddylist */
+ jabber_buddy_get_gui_infos (new_buddy, &prefix, &prefix_color,
+ ptr_buffer, &ptr_group);
+ snprintf (str_prefix_color, sizeof (str_prefix_color),
+ "weechat.color.nicklist_prefix%d",
+ prefix_color);
+ weechat_nicklist_add_nick (ptr_buffer, ptr_group,
+ new_buddy->name,
+ (is_away) ?
+ "weechat.color.nicklist_away" : "bar_fg",
+ prefix, str_prefix_color, 1);
+
+ /* all is ok, return address of new buddy */
+ return new_buddy;
+}
+
+/*
+ * jabber_buddy_change: change buddyname
+ */
+
+void
+jabber_buddy_change (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy, const char *new_buddy)
+{
+ int buddy_is_me, prefix_color;
+ struct t_gui_buffer *ptr_buffer;
+ struct t_gui_nick_group *ptr_group;
+ char prefix, str_prefix_color[64];
+ const char *local_name;
+
+ ptr_buffer = (muc) ? muc->buffer : server->buffer;
+
+ /* remove buddy from buddylist */
+ jabber_buddy_get_gui_infos (buddy, &prefix, &prefix_color,
+ ptr_buffer, &ptr_group);
+ weechat_nicklist_remove_nick (ptr_buffer,
+ weechat_nicklist_search_nick (ptr_buffer,
+ ptr_group,
+ buddy->name));
+
+ /* update buddies speaking */
+ local_name = jabber_server_get_local_name (server);
+ buddy_is_me = (strcmp (buddy->name, local_name) == 0) ? 1 : 0;
+ if (muc && !buddy_is_me)
+ jabber_muc_buddy_speaking_rename (muc, buddy->name, new_buddy);
+
+ /* change buddyname */
+ if (buddy->name)
+ free (buddy->name);
+ buddy->name = strdup (new_buddy);
+ if (buddy_is_me)
+ buddy->color = JABBER_COLOR_CHAT_NICK_SELF;
+ else
+ buddy->color = jabber_buddy_find_color (buddy);
+
+ /* add buddy in buddylist */
+ jabber_buddy_get_gui_infos (buddy, &prefix, &prefix_color,
+ ptr_buffer, &ptr_group);
+ snprintf (str_prefix_color, sizeof (str_prefix_color),
+ "weechat.color.nicklist_prefix%d",
+ prefix_color);
+ weechat_nicklist_add_nick (ptr_buffer, ptr_group,
+ buddy->name, "bar_fg",
+ prefix, str_prefix_color, 1);
+}
+
+/*
+ * jabber_buddy_set: set a flag for a buddy
+ */
+
+void
+jabber_buddy_set (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy, int set, int flag)
+{
+ struct t_gui_buffer *ptr_buffer;
+ struct t_gui_nick_group *ptr_group;
+ char prefix, str_prefix_color[64];
+ int prefix_color;
+
+ if (server || muc)
+ {
+ ptr_buffer = (muc) ? muc->buffer : server->buffer;
+
+ /* remove buddy from buddylist */
+ jabber_buddy_get_gui_infos (buddy, &prefix, &prefix_color,
+ ptr_buffer, &ptr_group);
+ weechat_nicklist_remove_nick (ptr_buffer,
+ weechat_nicklist_search_nick (ptr_buffer,
+ ptr_group,
+ buddy->name));
+
+ /* set flag */
+ JABBER_BUDDY_SET_FLAG(buddy, set, flag);
+
+ /* add buddy in buddylist */
+ jabber_buddy_get_gui_infos (buddy, &prefix, &prefix_color,
+ ptr_buffer, &ptr_group);
+ snprintf (str_prefix_color, sizeof (str_prefix_color),
+ "weechat.color.nicklist_prefix%d",
+ prefix_color);
+ weechat_nicklist_add_nick (ptr_buffer, ptr_group,
+ buddy->name,
+ (buddy->flags & JABBER_BUDDY_AWAY) ?
+ "weechat.color.nicklist_away" : "bar_fg",
+ prefix, str_prefix_color, 1);
+ }
+}
+
+/*
+ * jabber_buddy_free: free a buddy and remove it from buddies list
+ */
+
+void
+jabber_buddy_free (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy)
+{
+ struct t_gui_buffer *ptr_buffer;
+ struct t_gui_nick_group *ptr_group;
+ struct t_jabber_buddy *new_buddies;
+ char prefix;
+ int prefix_color;
+
+ if ((!server && !muc) || !buddy)
+ return;
+
+ ptr_buffer = (muc) ? muc->buffer : server->buffer;
+
+ /* remove buddy from buddylist */
+ jabber_buddy_get_gui_infos (buddy, &prefix, &prefix_color,
+ ptr_buffer, &ptr_group);
+ weechat_nicklist_remove_nick (ptr_buffer,
+ weechat_nicklist_search_nick (ptr_buffer,
+ ptr_group,
+ buddy->name));
+
+ /* remove buddy */
+ if (muc)
+ {
+ if (muc->last_buddy == buddy)
+ muc->last_buddy = buddy->prev_buddy;
+ if (buddy->prev_buddy)
+ {
+ (buddy->prev_buddy)->next_buddy = buddy->next_buddy;
+ new_buddies = muc->buddies;
+ }
+ else
+ new_buddies = buddy->next_buddy;
+ if (buddy->next_buddy)
+ (buddy->next_buddy)->prev_buddy = buddy->prev_buddy;
+ muc->buddies_count--;
+ }
+ else
+ {
+ if (server->last_buddy == buddy)
+ server->last_buddy = buddy->prev_buddy;
+ if (buddy->prev_buddy)
+ {
+ (buddy->prev_buddy)->next_buddy = buddy->next_buddy;
+ new_buddies = server->buddies;
+ }
+ else
+ new_buddies = buddy->next_buddy;
+ if (buddy->next_buddy)
+ (buddy->next_buddy)->prev_buddy = buddy->prev_buddy;
+ server->buddies_count--;
+ }
+
+ /* free data */
+ if (buddy->name)
+ free (buddy->name);
+ if (buddy->host)
+ free (buddy->host);
+
+ free (buddy);
+
+ if (muc)
+ {
+ muc->buddies = new_buddies;
+ muc->nick_completion_reset = 1;
+ }
+ else
+ {
+ server->buddies = new_buddies;
+ }
+}
+
+/*
+ * jabber_buddy_free_all: free all allocated buddies for a muc
+ */
+
+void
+jabber_buddy_free_all (struct t_jabber_server *server,
+ struct t_jabber_muc *muc)
+{
+ if (server)
+ {
+ while (server->buddies)
+ {
+ jabber_buddy_free (server, NULL, server->buddies);
+ }
+ /* sould be zero, but prevent any bug :D */
+ server->buddies_count = 0;
+ }
+
+ if (muc)
+ {
+ while (muc->buddies)
+ {
+ jabber_buddy_free (NULL, muc, muc->buddies);
+ }
+ /* sould be zero, but prevent any bug :D */
+ muc->buddies_count = 0;
+ }
+}
+
+/*
+ * jabber_buddy_search: returns pointer on a buddy
+ */
+
+struct t_jabber_buddy *
+jabber_buddy_search (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ const char *buddyname)
+{
+ struct t_jabber_buddy *ptr_buddy;
+
+ if (!buddyname)
+ return NULL;
+
+ if (server)
+ {
+ for (ptr_buddy = server->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (weechat_strcasecmp (ptr_buddy->name, buddyname) == 0)
+ return ptr_buddy;
+ }
+ }
+
+ if (muc)
+ {
+ for (ptr_buddy = muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (weechat_strcasecmp (ptr_buddy->name, buddyname) == 0)
+ return ptr_buddy;
+ }
+ }
+
+ /* buddy not found */
+ return NULL;
+}
+
+/*
+ * jabber_buddy_count: returns number of buddies (total, op, halfop, voice) on
+ * a server or MUC
+ */
+
+void
+jabber_buddy_count (struct t_jabber_server *server, struct t_jabber_muc *muc,
+ int *total, int *count_op, int *count_halfop,
+ int *count_voice, int *count_normal)
+{
+ struct t_jabber_buddy *ptr_buddy;
+
+ (*total) = 0;
+ (*count_op) = 0;
+ (*count_halfop) = 0;
+ (*count_voice) = 0;
+ (*count_normal) = 0;
+
+ if (server || muc)
+ {
+ for (ptr_buddy = (muc) ? muc->buddies : server->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ (*total)++;
+ if ((ptr_buddy->flags & JABBER_BUDDY_CHANOWNER) ||
+ (ptr_buddy->flags & JABBER_BUDDY_CHANADMIN) ||
+ (ptr_buddy->flags & JABBER_BUDDY_CHANADMIN2) ||
+ (ptr_buddy->flags & JABBER_BUDDY_OP))
+ (*count_op)++;
+ else
+ {
+ if (ptr_buddy->flags & JABBER_BUDDY_HALFOP)
+ (*count_halfop)++;
+ else
+ {
+ if (ptr_buddy->flags & JABBER_BUDDY_VOICE)
+ (*count_voice)++;
+ else
+ (*count_normal)++;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * jabber_buddy_set_away: set/unset away status for a muc
+ */
+
+void
+jabber_buddy_set_away (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy, int is_away)
+{
+ if (((is_away) && (!(buddy->flags & JABBER_BUDDY_AWAY))) ||
+ ((!is_away) && (buddy->flags & JABBER_BUDDY_AWAY)))
+ {
+ if (muc)
+ jabber_buddy_set (NULL, muc, buddy, is_away, JABBER_BUDDY_AWAY);
+ else
+ jabber_buddy_set (server, NULL, buddy, is_away, JABBER_BUDDY_AWAY);
+ }
+}
+
+/*
+ * jabber_buddy_as_prefix: return string with buddy to display as prefix on
+ * buffer (string will end by a tab)
+ */
+
+char *
+jabber_buddy_as_prefix (struct t_jabber_buddy *buddy, const char *buddyname,
+ const char *force_color)
+{
+ static char result[256];
+ char prefix[2], str_prefix_color[64];
+ int prefix_color;
+
+ prefix[0] = '\0';
+ prefix[1] = '\0';
+ if (weechat_config_boolean (weechat_config_get ("weechat.look.nickmode")))
+ {
+ if (buddy)
+ {
+ jabber_buddy_get_gui_infos (buddy, &prefix[0], &prefix_color, NULL, NULL);
+ if ((prefix[0] == ' ')
+ && !weechat_config_boolean (weechat_config_get ("weechat.look.nickmode_empty")))
+ prefix[0] = '\0';
+ snprintf (str_prefix_color, sizeof (str_prefix_color),
+ "weechat.color.nicklist_prefix%d",
+ prefix_color);
+ }
+ else
+ {
+ prefix[0] = (weechat_config_boolean (weechat_config_get ("weechat.look.nickmode_empty"))) ?
+ ' ' : '\0';
+ snprintf (str_prefix_color, sizeof (str_prefix_color),
+ "weechat.color.chat");
+ }
+ }
+ else
+ {
+ prefix[0] = '\0';
+ snprintf (str_prefix_color, sizeof (str_prefix_color), "chat");
+ }
+
+ snprintf (result, sizeof (result), "%s%s%s%s%s%s%s%s\t",
+ (weechat_config_string (jabber_config_look_nick_prefix)
+ && weechat_config_string (jabber_config_look_nick_prefix)[0]) ?
+ JABBER_COLOR_CHAT_DELIMITERS : "",
+ (weechat_config_string (jabber_config_look_nick_prefix)
+ && weechat_config_string (jabber_config_look_nick_prefix)[0]) ?
+ weechat_config_string (jabber_config_look_nick_prefix) : "",
+ weechat_color(weechat_config_string(weechat_config_get(str_prefix_color))),
+ prefix,
+ (force_color) ? force_color : ((buddy) ? buddy->color : JABBER_COLOR_CHAT_NICK),
+ (buddy) ? buddy->name : buddyname,
+ (weechat_config_string (jabber_config_look_nick_suffix)
+ && weechat_config_string (jabber_config_look_nick_suffix)[0]) ?
+ JABBER_COLOR_CHAT_DELIMITERS : "",
+ (weechat_config_string (jabber_config_look_nick_suffix)
+ && weechat_config_string (jabber_config_look_nick_suffix)[0]) ?
+ weechat_config_string (jabber_config_look_nick_suffix) : "");
+
+ return result;
+}
+
+/*
+ * jabber_buddy_add_to_infolist: add a buddy in an infolist
+ * return 1 if ok, 0 if error
+ */
+
+int
+jabber_buddy_add_to_infolist (struct t_infolist *infolist,
+ struct t_jabber_buddy *buddy)
+{
+ struct t_infolist_item *ptr_item;
+
+ if (!infolist || !buddy)
+ return 0;
+
+ ptr_item = weechat_infolist_new_item (infolist);
+ if (!ptr_item)
+ return 0;
+
+ if (!weechat_infolist_new_var_string (ptr_item, "name", buddy->name))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "host", buddy->host))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "flags", buddy->flags))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "color", buddy->color))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * jabber_buddy_print_log: print buddy infos in log (usually for crash dump)
+ */
+
+void
+jabber_buddy_print_log (struct t_jabber_buddy *buddy)
+{
+ weechat_log_printf ("");
+ weechat_log_printf (" => buddy %s (addr:0x%lx):", buddy->name, buddy);
+ weechat_log_printf (" host . . . . . : %s", buddy->host);
+ weechat_log_printf (" flags. . . . . : %d", buddy->flags);
+ weechat_log_printf (" color. . . . . : '%s'", buddy->color);
+ weechat_log_printf (" prev_buddy . . : 0x%lx", buddy->prev_buddy);
+ weechat_log_printf (" next_buddy . . : 0x%lx", buddy->next_buddy);
+}
diff --git a/src/plugins/jabber/jabber-buddy.h b/src/plugins/jabber/jabber-buddy.h
new file mode 100644
index 000000000..fdc7261aa
--- /dev/null
+++ b/src/plugins/jabber/jabber-buddy.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_BUDDY_H
+#define __WEECHAT_JABBER_BUDDY_H 1
+
+#define JABBER_BUDDY_CHANOWNER 1
+#define JABBER_BUDDY_CHANADMIN 2
+#define JABBER_BUDDY_CHANADMIN2 4
+#define JABBER_BUDDY_OP 8
+#define JABBER_BUDDY_HALFOP 16
+#define JABBER_BUDDY_VOICE 32
+#define JABBER_BUDDY_AWAY 64
+#define JABBER_BUDDY_CHANUSER 128
+#define JABBER_BUDDY_SET_FLAG(buddy, set, flag) \
+ if (set) \
+ buddy->flags |= flag; \
+ else \
+ buddy->flags &= 0xFFFF - flag;
+
+#define JABBER_BUDDY_GROUP_OP "1|op"
+#define JABBER_BUDDY_GROUP_HALFOP "2|halfop"
+#define JABBER_BUDDY_GROUP_VOICE "3|voice"
+#define JABBER_BUDDY_GROUP_CHANUSER "4|chanuser"
+#define JABBER_BUDDY_GROUP_NORMAL "5|normal"
+
+struct t_jabber_server;
+struct t_jabber_muc;
+
+struct t_jabber_buddy
+{
+ char *name; /* buddyname */
+ char *host; /* full hostname */
+ int flags; /* chanowner/chanadmin, op, halfop, */
+ /* voice, away */
+ const char *color; /* color for buddyname in chat window */
+ struct t_jabber_buddy *prev_buddy; /* link to previous buddy in MUC */
+ struct t_jabber_buddy *next_buddy; /* link to next buddy in MUC */
+};
+
+extern int jabber_buddy_valid (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy);
+extern const char *jabber_buddy_find_color (struct t_jabber_buddy *buddy);
+extern struct t_jabber_buddy *jabber_buddy_new (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ const char *buddy_name,
+ int is_chanowner,
+ int is_chanadmin,
+ int is_chanadmin2,
+ int is_op,
+ int is_halfop,
+ int has_voice,
+ int is_chanuser,
+ int is_away);
+extern void jabber_buddy_change (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy,
+ const char *new_buddy);
+extern void jabber_buddy_set (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy, int set, int flag);
+extern void jabber_buddy_free (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy);
+extern void jabber_buddy_free_all (struct t_jabber_server *server,
+ struct t_jabber_muc *muc);
+extern struct t_jabber_buddy *jabber_buddy_search (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ const char *buddyname);
+extern void jabber_buddy_count (struct t_jabber_server *server,
+ struct t_jabber_muc *muc, int *total,
+ int *count_op, int *count_halfop,
+ int *count_voice, int *count_normal);
+extern void jabber_buddy_set_away (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ struct t_jabber_buddy *buddy, int is_away);
+extern char *jabber_buddy_as_prefix (struct t_jabber_buddy *buddy,
+ const char *buddyname,
+ const char *force_color);
+extern int jabber_buddy_add_to_infolist (struct t_infolist *infolist,
+ struct t_jabber_buddy *buddy);
+extern void jabber_buddy_print_log (struct t_jabber_buddy *buddy);
+
+#endif /* jabber-buddy.h */
diff --git a/src/plugins/jabber/jabber-buffer.c b/src/plugins/jabber/jabber-buffer.c
new file mode 100644
index 000000000..a52200f9b
--- /dev/null
+++ b/src/plugins/jabber/jabber-buffer.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-buffer.c: buffer functions for Jabber plugin */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-buffer.h"
+#include "jabber-command.h"
+#include "jabber-config.h"
+#include "jabber-muc.h"
+#include "jabber-server.h"
+
+
+/* buffer for all servers (if using one buffer for all servers) */
+struct t_gui_buffer *jabber_buffer_servers = NULL;
+
+
+/*
+ * jabber_buffer_get_server_muc: get Jabber server and MUC pointers
+ * with a buffer pointer
+ * (buffer may be a server or a MUC)
+ */
+
+void
+jabber_buffer_get_server_muc (struct t_gui_buffer *buffer,
+ struct t_jabber_server **server,
+ struct t_jabber_muc **muc)
+{
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+
+ if (server)
+ *server = NULL;
+ if (muc)
+ *muc = NULL;
+
+ if (!buffer)
+ return;
+
+ /* look for a server or MUC using this buffer */
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->buffer == buffer)
+ {
+ if (server)
+ {
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer))
+ *server = jabber_current_server;
+ else
+ *server = ptr_server;
+ }
+ return;
+ }
+
+ for (ptr_muc = ptr_server->mucs; ptr_muc;
+ ptr_muc = ptr_muc->next_muc)
+ {
+ if (ptr_muc->buffer == buffer)
+ {
+ if (server)
+ *server = ptr_server;
+ if (muc)
+ *muc = ptr_muc;
+ return;
+ }
+ }
+ }
+
+ /* no server or MUC found */
+}
+
+/*
+ * jabber_buffer_build_name: build buffer name with a server and a MUC
+ */
+
+char *
+jabber_buffer_build_name (const char *server, const char *muc)
+{
+ static char buffer[128];
+
+ buffer[0] = '\0';
+
+ if (!server && !muc)
+ return buffer;
+
+ if (server && muc)
+ snprintf (buffer, sizeof (buffer), "%s.%s", server, muc);
+ else
+ snprintf (buffer, sizeof (buffer), "%s",
+ (server) ? server : muc);
+
+ return buffer;
+}
+
+/*
+ * jabber_buffer_get_server_prefix: return prefix, with server name if server
+ * buffers are displayed in only one buffer
+ */
+
+char *
+jabber_buffer_get_server_prefix (struct t_jabber_server *server,
+ char *prefix_code)
+{
+ static char buf[256];
+ const char *prefix;
+
+ prefix = (prefix_code && prefix_code[0]) ?
+ weechat_prefix (prefix_code) : NULL;
+
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer) && server)
+ {
+ snprintf (buf, sizeof (buf), "%s%s[%s%s%s]%s ",
+ (prefix) ? prefix : "",
+ JABBER_COLOR_CHAT_DELIMITERS,
+ JABBER_COLOR_CHAT_SERVER,
+ server->name,
+ JABBER_COLOR_CHAT_DELIMITERS,
+ JABBER_COLOR_CHAT);
+ }
+ else
+ {
+ snprintf (buf, sizeof (buf), "%s",
+ (prefix) ? prefix : "");
+ }
+ return buf;
+}
+
+/*
+ * jabber_buffer_merge_servers: merge server buffers in one buffer
+ */
+
+void
+jabber_buffer_merge_servers ()
+{
+ struct t_jabber_server *ptr_server;
+ struct t_gui_buffer *ptr_buffer;
+ int number, number_selected;
+ char charset_modifier[256];
+
+ jabber_buffer_servers = NULL;
+ jabber_current_server = NULL;
+
+ /* choose server buffer with lower number (should be first created) */
+ number_selected = -1;
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->buffer)
+ {
+ number = weechat_buffer_get_integer (ptr_server->buffer, "number");
+ if ((number_selected == -1) || (number < number_selected))
+ {
+ jabber_buffer_servers = ptr_server->buffer;
+ jabber_current_server = ptr_server;
+ number_selected = number;
+ }
+ }
+ }
+
+ if (jabber_buffer_servers)
+ {
+ weechat_buffer_set (jabber_buffer_servers,
+ "name", JABBER_BUFFER_ALL_SERVERS_NAME);
+ weechat_buffer_set (jabber_buffer_servers,
+ "short_name", JABBER_BUFFER_ALL_SERVERS_NAME);
+ weechat_buffer_set (jabber_buffer_servers, "key_bind_meta-s",
+ "/command jabber /jabber switch");
+ weechat_buffer_set (jabber_buffer_servers,
+ "localvar_set_server", JABBER_BUFFER_ALL_SERVERS_NAME);
+ weechat_buffer_set (jabber_buffer_servers,
+ "localvar_set_muc", JABBER_BUFFER_ALL_SERVERS_NAME);
+ snprintf (charset_modifier, sizeof (charset_modifier),
+ "jabber.%s", jabber_current_server->name);
+ weechat_buffer_set (jabber_buffer_servers,
+ "localvar_set_charset_modifier",
+ charset_modifier);
+ weechat_hook_signal_send ("logger_stop",
+ WEECHAT_HOOK_SIGNAL_POINTER,
+ jabber_buffer_servers);
+ weechat_hook_signal_send ("logger_start",
+ WEECHAT_HOOK_SIGNAL_POINTER,
+ jabber_buffer_servers);
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->buffer
+ && (ptr_server->buffer != jabber_buffer_servers))
+ {
+ ptr_buffer = ptr_server->buffer;
+ ptr_server->buffer = jabber_buffer_servers;
+ weechat_buffer_close (ptr_buffer);
+ }
+ }
+
+ jabber_server_set_buffer_title (jabber_current_server);
+ jabber_server_buffer_set_highlight_words (jabber_buffer_servers);
+ }
+}
+
+/*
+ * jabber_buffer_split_server: split the server buffer into many buffers (one by server)
+ */
+
+void
+jabber_buffer_split_server ()
+{
+ struct t_jabber_server *ptr_server;
+ char buffer_name[256], charset_modifier[256];
+
+ if (jabber_buffer_servers)
+ {
+ weechat_buffer_set (jabber_buffer_servers, "key_unbind_meta-s", "");
+ }
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->buffer && (ptr_server != jabber_current_server))
+ {
+ jabber_server_create_buffer (ptr_server, 0);
+ }
+ }
+
+ if (jabber_current_server)
+ {
+ snprintf (buffer_name, sizeof (buffer_name),
+ "server.%s", jabber_current_server->name);
+ weechat_buffer_set (jabber_current_server->buffer, "name", buffer_name);
+ weechat_buffer_set (jabber_current_server->buffer,
+ "short_name", jabber_current_server->name);
+ weechat_buffer_set (jabber_current_server->buffer,
+ "localvar_set_server", jabber_current_server->name);
+ weechat_buffer_set (jabber_current_server->buffer,
+ "localvar_set_muc", jabber_current_server->name);
+ snprintf (charset_modifier, sizeof (charset_modifier),
+ "jabber.%s", jabber_current_server->name);
+ weechat_buffer_set (jabber_current_server->buffer,
+ "localvar_set_charset_modifier",
+ charset_modifier);
+ weechat_hook_signal_send ("logger_stop",
+ WEECHAT_HOOK_SIGNAL_POINTER,
+ jabber_current_server->buffer);
+ weechat_hook_signal_send ("logger_start",
+ WEECHAT_HOOK_SIGNAL_POINTER,
+ jabber_current_server->buffer);
+ }
+
+ jabber_buffer_servers = NULL;
+ jabber_current_server = NULL;
+}
+
+/*
+ * jabber_buffer_close_cb: callback called when a buffer is closed
+ */
+
+int
+jabber_buffer_close_cb (void *data, struct t_gui_buffer *buffer)
+{
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+
+ if (ptr_muc)
+ {
+ /* send PART for channel if its buffer is closed */
+ //if ((ptr_channel->type == JABBER_CHANNEL_TYPE_CHANNEL)
+ // && (ptr_channel->nicks))
+ //{
+ // jabber_command_part_channel (ptr_server, ptr_channel->name, NULL);
+ //}
+ jabber_muc_free (ptr_server, ptr_muc);
+ }
+ else
+ {
+ if (ptr_server)
+ {
+ /* send PART on all channels for server, then disconnect from server */
+ //ptr_channel = ptr_server->channels;
+ //while (ptr_channel)
+ //{
+ // next_channel = ptr_channel->next_channel;
+ // weechat_buffer_close (ptr_channel->buffer);
+ // ptr_channel = next_channel;
+ //}
+ jabber_server_disconnect (ptr_server, 0);
+ ptr_server->buffer = NULL;
+ }
+ }
+
+ if (jabber_buffer_servers == buffer)
+ jabber_buffer_servers = NULL;
+ if (ptr_server && (jabber_current_server == ptr_server))
+ jabber_current_server = NULL;
+
+ return WEECHAT_RC_OK;
+}
diff --git a/src/plugins/jabber/jabber-buffer.h b/src/plugins/jabber/jabber-buffer.h
new file mode 100644
index 000000000..032d8afe8
--- /dev/null
+++ b/src/plugins/jabber/jabber-buffer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_BUFFER_H
+#define __WEECHAT_JABBER_BUFFER_H 1
+
+#define JABBER_BUFFER_ALL_SERVERS_NAME "servers"
+
+struct t_gui_buffer;
+struct t_jabber_server;
+struct t_jabber_muc;
+
+extern struct t_gui_buffer *jabber_buffer_servers;
+
+extern void jabber_buffer_get_server_muc (struct t_gui_buffer *buffer,
+ struct t_jabber_server **server,
+ struct t_jabber_muc **muc);
+extern char *jabber_buffer_build_name (const char *server, const char *muc);
+extern char *jabber_buffer_get_server_prefix (struct t_jabber_server *server,
+ char *prefix_code);
+extern void jabber_buffer_merge_servers ();
+extern void jabber_buffer_split_server ();
+extern int jabber_buffer_close_cb (void *data, struct t_gui_buffer *buffer);
+
+#endif /* jabber-buffer.h */
diff --git a/src/plugins/jabber/jabber-command.c b/src/plugins/jabber/jabber-command.c
new file mode 100644
index 000000000..900e8e71d
--- /dev/null
+++ b/src/plugins/jabber/jabber-command.c
@@ -0,0 +1,847 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-command.c: Jabber commands */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-command.h"
+#include "jabber-buddy.h"
+#include "jabber-buffer.h"
+#include "jabber-config.h"
+#include "jabber-input.h"
+#include "jabber-muc.h"
+#include "jabber-server.h"
+#include "jabber-display.h"
+#include "jabber-xmpp.h"
+
+
+/*
+ * jabber_command_quit_server: send QUIT to a server
+ */
+
+void
+jabber_command_quit_server (struct t_jabber_server *server,
+ const char *arguments)
+{
+ if (!server)
+ return;
+
+ (void) arguments;
+}
+
+/*
+ * jabber_command_jabber: test
+ */
+
+int
+jabber_command_jabber (void *data, struct t_gui_buffer *buffer, int argc,
+ char **argv, char **argv_eol)
+{
+ int i, detailed_list, one_server_found;
+ struct t_jabber_server *ptr_server2, *server_found, *new_server;
+ char *server_name;
+
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) buffer;
+ (void) argv_eol;
+
+ if ((argc == 1)
+ || (weechat_strcasecmp (argv[1], "list") == 0)
+ || (weechat_strcasecmp (argv[1], "listfull") == 0))
+ {
+ /* list servers */
+ server_name = NULL;
+ detailed_list = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (weechat_strcasecmp (argv[i], "list") == 0)
+ continue;
+ if (weechat_strcasecmp (argv[i], "listfull") == 0)
+ {
+ detailed_list = 1;
+ continue;
+ }
+ if (!server_name)
+ server_name = argv[i];
+ }
+ if (!server_name)
+ {
+ if (jabber_servers)
+ {
+ weechat_printf (NULL, "");
+ weechat_printf (NULL, _("All servers:"));
+ for (ptr_server2 = jabber_servers; ptr_server2;
+ ptr_server2 = ptr_server2->next_server)
+ {
+ jabber_display_server (ptr_server2, detailed_list);
+ }
+ }
+ else
+ weechat_printf (NULL, _("No server"));
+ }
+ else
+ {
+ one_server_found = 0;
+ for (ptr_server2 = jabber_servers; ptr_server2;
+ ptr_server2 = ptr_server2->next_server)
+ {
+ if (weechat_strcasestr (ptr_server2->name, server_name))
+ {
+ if (!one_server_found)
+ {
+ weechat_printf (NULL, "");
+ weechat_printf (NULL,
+ _("Servers with \"%s\":"),
+ server_name);
+ }
+ one_server_found = 1;
+ jabber_display_server (ptr_server2, detailed_list);
+ }
+ }
+ if (!one_server_found)
+ weechat_printf (NULL,
+ _("No server found with \"%s\""),
+ server_name);
+ }
+
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "add") == 0)
+ {
+ if (argc < 6)
+ {
+ JABBER_COMMAND_TOO_FEW_ARGUMENTS(NULL, "server add");
+ }
+ if (jabber_server_search (argv[2]))
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" already exists, "
+ "can't create it!"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2]);
+ return WEECHAT_RC_ERROR;
+ }
+
+ new_server = jabber_server_alloc (argv[2]);
+ if (!new_server)
+ {
+ weechat_printf (NULL,
+ _("%s%s: unable to create server"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME);
+ return WEECHAT_RC_ERROR;
+ }
+
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_USERNAME],
+ argv[3], 1);
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_SERVER],
+ argv[4], 1);
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_PASSWORD],
+ argv[5], 1);
+
+ /* parse arguments */
+ for (i = 6; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ if (weechat_strcasecmp (argv[i], "-auto") == 0)
+ {
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_AUTOCONNECT],
+ "on", 1);
+ }
+ if (weechat_strcasecmp (argv[i], "-noauto") == 0)
+ {
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_AUTOCONNECT],
+ "off", 1);
+ }
+ if (weechat_strcasecmp (argv[i], "-ipv6") == 0)
+ {
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_IPV6],
+ "on", 1);
+ }
+ if (weechat_strcasecmp (argv[i], "-tls") == 0)
+ {
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_TLS],
+ "on", 1);
+ }
+ if (weechat_strcasecmp (argv[i], "-sasl") == 0)
+ {
+ weechat_config_option_set (new_server->options[JABBER_SERVER_OPTION_SASL],
+ "on", 1);
+ }
+ }
+ }
+
+ weechat_printf (NULL,
+ _("%s: server %s%s%s created"),
+ JABBER_PLUGIN_NAME,
+ JABBER_COLOR_CHAT_SERVER,
+ new_server->name,
+ JABBER_COLOR_CHAT);
+
+ if (JABBER_SERVER_OPTION_BOOLEAN(new_server, JABBER_SERVER_OPTION_AUTOCONNECT))
+ jabber_server_connect (new_server);
+
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "copy") == 0)
+ {
+ if (argc < 4)
+ {
+ JABBER_COMMAND_TOO_FEW_ARGUMENTS(NULL, "server copy");
+ }
+
+ /* look for server by name */
+ server_found = jabber_server_search (argv[2]);
+ if (!server_found)
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" not found for "
+ "\"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2], "server copy");
+ return WEECHAT_RC_ERROR;
+ }
+
+ /* check if target name already exists */
+ if (jabber_server_search (argv[3]))
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" already exists for "
+ "\"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[3], "server copy");
+ return WEECHAT_RC_ERROR;
+ }
+
+ /* copy server */
+ new_server = jabber_server_copy (server_found, argv[3]);
+ if (new_server)
+ {
+ weechat_printf (NULL,
+ _("%s: server %s%s%s has been copied to "
+ "%s%s"),
+ JABBER_PLUGIN_NAME,
+ JABBER_COLOR_CHAT_SERVER,
+ argv[2],
+ JABBER_COLOR_CHAT,
+ JABBER_COLOR_CHAT_SERVER,
+ argv[3]);
+ return WEECHAT_RC_OK;
+ }
+
+ return WEECHAT_RC_ERROR;
+ }
+
+ if (weechat_strcasecmp (argv[1], "rename") == 0)
+ {
+ if (argc < 4)
+ {
+ JABBER_COMMAND_TOO_FEW_ARGUMENTS(NULL, "server rename");
+ }
+
+ /* look for server by name */
+ server_found = jabber_server_search (argv[2]);
+ if (!server_found)
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" not found for "
+ "\"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2], "server rename");
+ return WEECHAT_RC_ERROR;
+ }
+
+ /* check if target name already exists */
+ if (jabber_server_search (argv[3]))
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" already exists for "
+ "\"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[3], "server rename");
+ return WEECHAT_RC_ERROR;
+ }
+
+ /* rename server */
+ if (jabber_server_rename (server_found, argv[3]))
+ {
+ weechat_printf (NULL,
+ _("%s: server %s%s%s has been renamed to "
+ "%s%s"),
+ JABBER_PLUGIN_NAME,
+ JABBER_COLOR_CHAT_SERVER,
+ argv[2],
+ JABBER_COLOR_CHAT,
+ JABBER_COLOR_CHAT_SERVER,
+ argv[3]);
+ return WEECHAT_RC_OK;
+ }
+
+ return WEECHAT_RC_ERROR;
+ }
+
+ if (weechat_strcasecmp (argv[1], "keep") == 0)
+ {
+ if (argc < 3)
+ {
+ JABBER_COMMAND_TOO_FEW_ARGUMENTS(NULL, "server keep");
+ }
+
+ /* look for server by name */
+ server_found = jabber_server_search (argv[2]);
+ if (!server_found)
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" not found for "
+ "\"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2], "server keep");
+ return WEECHAT_RC_ERROR;
+ }
+
+ /* check that is it temporary server */
+ if (!server_found->temp_server)
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" is not a temporary server"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2], "server keep");
+ return WEECHAT_RC_ERROR;
+ }
+
+ /* remove temporary flag on server */
+ server_found->temp_server = 0;
+
+ weechat_printf (NULL,
+ _("%s: server %s%s%s is not temporary any more"),
+ JABBER_PLUGIN_NAME,
+ JABBER_COLOR_CHAT_SERVER,
+ argv[2],
+ JABBER_COLOR_CHAT);
+
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "del") == 0)
+ {
+ if (argc < 3)
+ {
+ JABBER_COMMAND_TOO_FEW_ARGUMENTS(NULL, "server del");
+ }
+
+ /* look for server by name */
+ server_found = jabber_server_search (argv[2]);
+ if (!server_found)
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" not found for "
+ "\"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2], "server del");
+ return WEECHAT_RC_ERROR;
+ }
+ if (server_found->is_connected)
+ {
+ weechat_printf (NULL,
+ _("%s%s: you can not delete server \"%s\" "
+ "because you are connected to. "
+ "Try \"/disconnect %s\" before."),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[2], argv[2]);
+ return WEECHAT_RC_ERROR;
+ }
+
+ server_name = strdup (server_found->name);
+ jabber_server_free (server_found);
+ weechat_printf (NULL,
+ _("%s: Server %s%s%s has been deleted"),
+ JABBER_PLUGIN_NAME,
+ JABBER_COLOR_CHAT_SERVER,
+ (server_name) ? server_name : "???",
+ JABBER_COLOR_CHAT);
+ if (server_name)
+ free (server_name);
+
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "switch") == 0)
+ {
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer))
+ {
+ if (jabber_current_server)
+ {
+ ptr_server2 = jabber_current_server->next_server;
+ if (!ptr_server2)
+ ptr_server2 = jabber_servers;
+ while (ptr_server2 != jabber_current_server)
+ {
+ if (ptr_server2->buffer)
+ {
+ jabber_current_server = ptr_server2;
+ break;
+ }
+ ptr_server2 = ptr_server2->next_server;
+ if (!ptr_server2)
+ ptr_server2 = jabber_servers;
+ }
+ }
+ else
+ {
+ for (ptr_server2 = jabber_servers; ptr_server2;
+ ptr_server2 = ptr_server2->next_server)
+ {
+ if (ptr_server2->buffer)
+ {
+ jabber_current_server = ptr_server2;
+ break;
+ }
+ }
+ }
+ jabber_server_set_current_server (jabber_current_server);
+ }
+ return WEECHAT_RC_OK;
+ }
+
+ weechat_printf (NULL,
+ _("%s%s: unknown option for \"%s\" command"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME, "server");
+
+ return WEECHAT_RC_ERROR;
+}
+
+/*
+ * jabber_command_jchat: chat with a buddy
+ */
+
+int
+jabber_command_jchat (void *data, struct t_gui_buffer *buffer, int argc,
+ char **argv, char **argv_eol)
+{
+ JABBER_GET_SERVER_MUC(buffer);
+ if (!ptr_server || !ptr_server->is_connected || !ptr_server->iks_authorized)
+ return WEECHAT_RC_ERROR;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) argv;
+
+ if (argc > 1)
+ {
+ /* create private window if not already opened */
+ ptr_muc = jabber_muc_search (ptr_server, argv[1]);
+ if (!ptr_muc)
+ {
+ ptr_muc = jabber_muc_new (ptr_server,
+ JABBER_MUC_TYPE_PRIVATE,
+ argv[1], 1);
+ if (!ptr_muc)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: cannot create new private "
+ "buffer \"%s\""),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME, argv[1]);
+ return WEECHAT_RC_ERROR;
+ }
+ }
+ weechat_buffer_set (ptr_muc->buffer, "display", "1");
+
+ /* display text if given */
+ if (argv_eol[2])
+ {
+ jabber_xmpp_send_chat_message (ptr_server, ptr_muc, argv_eol[2]);
+ jabber_input_user_message_display (ptr_muc->buffer, argv_eol[2]);
+ }
+ }
+ else
+ {
+ JABBER_COMMAND_TOO_FEW_ARGUMENTS(ptr_server->buffer, "chat");
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_command_jconnect_one_server: connect to one server
+ * return 0 if error, 1 if ok
+ */
+
+int
+jabber_command_jconnect_one_server (struct t_jabber_server *server, int no_join)
+{
+ if (!server)
+ return 0;
+
+ if (server->is_connected)
+ {
+ weechat_printf (NULL,
+ _("%s%s: already connected to server "
+ "\"%s\"!"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ server->name);
+ return 0;
+ }
+ if (server->hook_connect)
+ {
+ weechat_printf (NULL,
+ _("%s%s: currently connecting to server "
+ "\"%s\"!"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ server->name);
+ return 0;
+ }
+ server->disable_autojoin = no_join;
+ if (jabber_server_connect (server))
+ {
+ server->reconnect_start = 0;
+ server->reconnect_join = (server->mucs) ? 1 : 0;
+ }
+
+ /* connect ok */
+ return 1;
+}
+
+/*
+ * jabber_command_jconnect: connect to server(s)
+ */
+
+int
+jabber_command_jconnect (void *data, struct t_gui_buffer *buffer, int argc,
+ char **argv, char **argv_eol)
+{
+ int i, nb_connect, connect_ok, all_servers, no_join, port, ipv6, tls, sasl;
+ char *name, *error;
+ long number;
+
+ JABBER_GET_SERVER(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) argv_eol;
+
+ nb_connect = 0;
+ connect_ok = 1;
+ port = JABBER_SERVER_DEFAULT_PORT;
+ ipv6 = 0;
+ tls = 0;
+ sasl = 0;
+
+ all_servers = 0;
+ no_join = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (weechat_strcasecmp (argv[i], "-all") == 0)
+ all_servers = 1;
+ if (weechat_strcasecmp (argv[i], "-nojoin") == 0)
+ no_join = 1;
+ if (weechat_strcasecmp (argv[i], "-ipv6") == 0)
+ ipv6 = 1;
+ if (weechat_strcasecmp (argv[i], "-tls") == 0)
+ tls = 1;
+ if (weechat_strcasecmp (argv[i], "-sasl") == 0)
+ sasl = 1;
+ if (weechat_strcasecmp (argv[i], "-port") == 0)
+ {
+ if (i == (argc - 1))
+ {
+ weechat_printf (NULL,
+ _("%s%s: missing argument for \"%s\" "
+ "option"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ "-port");
+ return WEECHAT_RC_ERROR;
+ }
+ error = NULL;
+ number = strtol (argv[++i], &error, 10);
+ if (error && !error[0])
+ port = number;
+ }
+ }
+
+ if (all_servers)
+ {
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ nb_connect++;
+ if (!ptr_server->is_connected && (!ptr_server->hook_connect))
+ {
+ if (!jabber_command_jconnect_one_server (ptr_server, no_join))
+ connect_ok = 0;
+ }
+ }
+ }
+ else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] != '-')
+ {
+ nb_connect++;
+ ptr_server = jabber_server_search (argv[i]);
+ if (ptr_server)
+ {
+ if (!jabber_command_jconnect_one_server (ptr_server, no_join))
+ connect_ok = 0;
+ }
+ else
+ {
+ name = jabber_server_get_name_without_port (argv[i]);
+ ptr_server = jabber_server_alloc ((name) ? name : argv[i]);
+ if (name)
+ free (name);
+ if (ptr_server)
+ {
+ ptr_server->temp_server = 1;
+ weechat_config_option_set (ptr_server->options[JABBER_SERVER_OPTION_SERVER],
+ argv[i], 1);
+ weechat_printf (NULL,
+ _("%s: server %s%s%s created (temporary server, NOT SAVED!)"),
+ JABBER_PLUGIN_NAME,
+ JABBER_COLOR_CHAT_SERVER,
+ ptr_server->name,
+ JABBER_COLOR_CHAT);
+ if (!jabber_command_jconnect_one_server (ptr_server, 0))
+ connect_ok = 0;
+ }
+ else
+ {
+ weechat_printf (NULL,
+ _("%s%s: unable to create server "
+ "\"%s\""),
+ weechat_prefix ("error"),
+ JABBER_PLUGIN_NAME, argv[i]);
+ }
+ }
+ }
+ else
+ {
+ if (weechat_strcasecmp (argv[i], "-port") == 0)
+ i++;
+ }
+ }
+ }
+
+ if (nb_connect == 0)
+ connect_ok = jabber_command_jconnect_one_server (ptr_server, no_join);
+
+ if (!connect_ok)
+ return WEECHAT_RC_ERROR;
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_command_jdisconnect_one_server: disconnect from a server
+ * return 0 if error, 1 if ok
+ */
+
+int
+jabber_command_jdisconnect_one_server (struct t_jabber_server *server)
+{
+ if (!server)
+ return 0;
+
+ if ((!server->is_connected) && (!server->hook_connect)
+ && (server->reconnect_start == 0))
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: not connected to server \"%s\"!"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME, server->name);
+ return 0;
+ }
+ if (server->reconnect_start > 0)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: auto-reconnection is cancelled"),
+ jabber_buffer_get_server_prefix (server, NULL),
+ JABBER_PLUGIN_NAME);
+ }
+ jabber_command_quit_server (server, NULL);
+ jabber_server_disconnect (server, 0);
+
+ /* disconnect ok */
+ return 1;
+}
+
+/*
+ * jabber_command_jdisconnect: disconnect from server(s)
+ */
+
+int
+jabber_command_jdisconnect (void *data, struct t_gui_buffer *buffer, int argc,
+ char **argv, char **argv_eol)
+{
+ int i, disconnect_ok;
+
+ JABBER_GET_SERVER(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) argv_eol;
+
+ if (argc < 2)
+ disconnect_ok = jabber_command_jdisconnect_one_server (ptr_server);
+ else
+ {
+ disconnect_ok = 1;
+
+ if (weechat_strcasecmp (argv[1], "-all") == 0)
+ {
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if ((ptr_server->is_connected) || (ptr_server->hook_connect)
+ || (ptr_server->reconnect_start != 0))
+ {
+ if (!jabber_command_jdisconnect_one_server (ptr_server))
+ disconnect_ok = 0;
+ }
+ }
+ }
+ else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ ptr_server = jabber_server_search (argv[i]);
+ if (ptr_server)
+ {
+ if (!jabber_command_jdisconnect_one_server (ptr_server))
+ disconnect_ok = 0;
+ }
+ else
+ {
+ weechat_printf (NULL,
+ _("%s%s: server \"%s\" not found"),
+ weechat_prefix ("error"),
+ JABBER_PLUGIN_NAME, argv[i]);
+ disconnect_ok = 0;
+ }
+ }
+ }
+ }
+
+ if (!disconnect_ok)
+ return WEECHAT_RC_ERROR;
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_command_init: init Jabber commands (create hooks)
+ */
+
+void
+jabber_command_init ()
+{
+ weechat_hook_command ("jabber",
+ N_("list, add or remove Jabber servers"),
+ N_("[list [servername]] | [listfull [servername]] | "
+ "[add servername username hostname[/port] password "
+ "[-auto | -noauto] [-ipv6] [-tls] [-sasl]] | "
+ "[copy servername newservername] | "
+ "[rename servername newservername] | "
+ "[keep servername] | [del servername] | "
+ "[switch]"),
+ N_(" list: list servers (no parameter implies "
+ "this list)\n"
+ " listfull: list servers with detailed info for "
+ "each server\n"
+ " add: create a new server\n"
+ "servername: server name, for internal and "
+ "display use\n"
+ " username: username to use on server\n"
+ " hostname: name or IP address of server, with "
+ "optional port (default: 5222)\n"
+ " password: password for username on server\n"
+ " auto: automatically connect to server "
+ "when WeeChat starts\n"
+ " noauto: do not connect to server when "
+ "WeeChat starts (default)\n"
+ " ipv6: use IPv6 protocol\n"
+ " tls: use TLS cryptographic protocol\n"
+ " sasl: use SASL for authentication\n"
+ " copy: duplicate a server\n"
+ " rename: rename a server\n"
+ " keep: keep server in config file (for "
+ "temporary servers only)\n"
+ " del: delete a server\n"
+ " switch: switch active server (when one "
+ "buffer is used for all servers, default key: "
+ "alt-s on server buffer)\n\n"
+ "Examples:\n"
+ " /jabber listfull\n"
+ " /jabber add jabberfr user jabber.fr/5222 "
+ "password -tls\n"
+ " /jabber copy jabberfr jabberfr2\n"
+ " /jabber rename jabberfr jabbfr\n"
+ " /jabber del jabberfr\n"
+ " /jabber switch"),
+ "add|copy|rename|keep|del|list|listfull|switch "
+ "%(jabber_servers) %(jabber_servers)",
+ &jabber_command_jabber, NULL);
+ weechat_hook_command ("jchat",
+ N_("chat with a buddy"),
+ N_("buddy [text]"),
+ N_("buddy: buddy name for chat\n"
+ " text: text to send"),
+ "%n %-", &jabber_command_jchat, NULL);
+ weechat_hook_command ("jconnect",
+ N_("connect to Jabber server(s)"),
+ N_("[-all [-nojoin] | servername [servername ...] "
+ "[-nojoin] | hostname [-port port] [-ipv6] "
+ "[-tls] [-sasl]]"),
+ N_(" -all: connect to all servers\n"
+ "servername: internal server name to connect\n"
+ " -nojoin: do not join any MUC (even if "
+ "autojoin is enabled on server)\n"
+ " hostname: hostname to connect\n"
+ " port: port for server (integer, default "
+ "is 6667)\n"
+ " ipv6: use IPv6 protocol\n"
+ " tls: use TLS cryptographic protocol\n"
+ " saal: use SASL for authentication"),
+ "%(jabber_servers)|-all|-nojoin|%*",
+ &jabber_command_jconnect, NULL);
+ weechat_hook_command ("jdisconnect",
+ N_("disconnect from Jabber server(s)"),
+ N_("[-all | servername [servername ...]]"),
+ N_(" -all: disconnect from all servers\n"
+ "servername: server name to disconnect"),
+ "%(jabber_servers)|-all",
+ &jabber_command_jdisconnect, NULL);
+}
diff --git a/src/plugins/jabber/jabber-command.h b/src/plugins/jabber/jabber-command.h
new file mode 100644
index 000000000..5a2c15138
--- /dev/null
+++ b/src/plugins/jabber/jabber-command.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_COMMAND_H
+#define __WEECHAT_JABBER_COMMAND_H 1
+
+struct t_jabber_server;
+
+#define JABBER_COMMAND_TOO_FEW_ARGUMENTS(__buffer, __command) \
+ weechat_printf (__buffer, \
+ _("%s%s: too few arguments for \"%s\" command"), \
+ jabber_buffer_get_server_prefix (ptr_server, "error"), \
+ JABBER_PLUGIN_NAME, \
+ __command); \
+ return WEECHAT_RC_ERROR;
+
+extern void jabber_command_quit_server (struct t_jabber_server *server,
+ const char *arguments);
+extern void jabber_command_init ();
+
+#endif /* jabber-command.h */
diff --git a/src/plugins/jabber/jabber-completion.c b/src/plugins/jabber/jabber-completion.c
new file mode 100644
index 000000000..e08f665b1
--- /dev/null
+++ b/src/plugins/jabber/jabber-completion.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-completion.c: completion for Jabber commands */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-buddy.h"
+#include "jabber-buffer.h"
+#include "jabber-completion.h"
+#include "jabber-config.h"
+#include "jabber-muc.h"
+#include "jabber-server.h"
+
+
+/*
+ * jabber_completion_server_cb: callback for completion with current server
+ */
+
+int
+jabber_completion_server_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ JABBER_GET_SERVER(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_server)
+ {
+ weechat_hook_completion_list_add (completion, ptr_server->name,
+ 0, WEECHAT_LIST_POS_SORT);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_server_local_name_cb: callback for completion with local
+ * name on server
+ */
+
+int
+jabber_completion_server_local_name_cb (void *data,
+ const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ const char *local_name;
+
+ JABBER_GET_SERVER(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_server)
+ {
+ local_name = jabber_server_get_local_name (ptr_server);
+ if (local_name && local_name[0])
+ {
+ weechat_hook_completion_list_add (completion, local_name,
+ 1, WEECHAT_LIST_POS_SORT);
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_server_buddies_cb: callback for completion with buddies
+ * of current server
+ */
+
+int
+jabber_completion_server_buddies_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ struct t_jabber_muc *ptr_muc2;
+ struct t_jabber_buddy *ptr_buddy;
+ const char *local_name;
+
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_server)
+ {
+ for (ptr_muc2 = ptr_server->mucs; ptr_muc2;
+ ptr_muc2 = ptr_muc2->next_muc)
+ {
+ if (ptr_muc2->type == JABBER_MUC_TYPE_MUC)
+ {
+ for (ptr_buddy = ptr_muc2->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ weechat_hook_completion_list_add (completion,
+ ptr_buddy->name,
+ 1, WEECHAT_LIST_POS_SORT);
+ }
+ }
+ }
+
+ local_name = jabber_server_get_local_name (ptr_server);
+
+ if (local_name && local_name[0])
+ {
+ /* add local name at the end */
+ weechat_hook_completion_list_add (completion, local_name,
+ 1, WEECHAT_LIST_POS_END);
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_servers_cb: callback for completion with servers
+ */
+
+int
+jabber_completion_servers_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ struct t_jabber_server *ptr_server;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+ (void) buffer;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ weechat_hook_completion_list_add (completion, ptr_server->name,
+ 0, WEECHAT_LIST_POS_SORT);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_muc_cb: callback for completion with current MUC
+ */
+
+int
+jabber_completion_muc_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_muc)
+ {
+ weechat_hook_completion_list_add (completion, ptr_muc->name,
+ 0, WEECHAT_LIST_POS_SORT);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_muc_buddies_cb: callback for completion with buddies
+ * of current MUC
+ */
+
+int
+jabber_completion_muc_buddies_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ struct t_jabber_buddy *ptr_buddy;
+ const char *buddy, *local_name;
+ int list_size, i, j;
+
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_muc)
+ {
+ switch (ptr_muc->type)
+ {
+ case JABBER_MUC_TYPE_MUC:
+ for (ptr_buddy = ptr_muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ weechat_hook_completion_list_add (completion,
+ ptr_buddy->name,
+ 1,
+ WEECHAT_LIST_POS_SORT);
+ }
+ /* add buddies speaking recently on this MUC */
+ if (weechat_config_boolean (jabber_config_look_nick_completion_smart))
+ {
+ /* 0 => buddy speaking ; 1 => buddy speaking to me
+ (with highlight) */
+ for (i = 0; i < 2; i++)
+ {
+ if (ptr_muc->buddies_speaking[i])
+ {
+ list_size = weechat_list_size (ptr_muc->buddies_speaking[i]);
+ for (j = 0; j < list_size; j++)
+ {
+ buddy = weechat_list_string (weechat_list_get (ptr_muc->buddies_speaking[i], j));
+ if (buddy && jabber_buddy_search (NULL, ptr_muc, buddy))
+ {
+ weechat_hook_completion_list_add (completion,
+ buddy,
+ 1,
+ WEECHAT_LIST_POS_BEGINNING);
+ }
+ }
+ }
+ }
+ }
+ /* add local name at the end */
+ local_name = jabber_server_get_local_name (ptr_server);
+ if (local_name && local_name[0])
+ {
+ weechat_hook_completion_list_add (completion,
+ local_name,
+ 1,
+ WEECHAT_LIST_POS_END);
+ }
+ break;
+ case JABBER_MUC_TYPE_PRIVATE:
+ weechat_hook_completion_list_add (completion,
+ ptr_muc->name,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ break;
+ }
+ ptr_muc->nick_completion_reset = 0;
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_muc_buddies_hosts_cb: callback for completion with buddies
+ * and hosts of current MUC
+ */
+
+int
+jabber_completion_muc_buddies_hosts_cb (void *data,
+ const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ struct t_jabber_buddy *ptr_buddy;
+ char *buf;
+ int length;
+
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_muc)
+ {
+ switch (ptr_muc->type)
+ {
+ case JABBER_MUC_TYPE_MUC:
+ for (ptr_buddy = ptr_muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ weechat_hook_completion_list_add (completion,
+ ptr_buddy->name,
+ 1,
+ WEECHAT_LIST_POS_SORT);
+ if (ptr_buddy->host)
+ {
+ length = strlen (ptr_buddy->name) + 1 +
+ strlen (ptr_buddy->host) + 1;
+ buf = malloc (length);
+ if (buf)
+ {
+ snprintf (buf, length, "%s!%s",
+ ptr_buddy->name, ptr_buddy->host);
+ weechat_hook_completion_list_add (completion,
+ buf,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ free (buf);
+ }
+ }
+ }
+ break;
+ case JABBER_MUC_TYPE_PRIVATE:
+ weechat_hook_completion_list_add (completion,
+ ptr_muc->name,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_muc_topic_cb: callback for completion with topic of
+ * current MUC
+ */
+
+int
+jabber_completion_muc_topic_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ JABBER_GET_SERVER_MUC(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+
+ if (ptr_muc && ptr_muc->topic && ptr_muc->topic[0])
+ {
+ weechat_hook_completion_list_add (completion,
+ ptr_muc->topic,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_mucs_cb: callback for completion with MUCs
+ */
+
+int
+jabber_completion_mucs_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ (void) completion;
+
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+ (void) buffer;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ for (ptr_muc = ptr_server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ weechat_hook_completion_list_add (completion,
+ ptr_muc->name,
+ 0,
+ WEECHAT_LIST_POS_SORT);
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_msg_part_cb: callback for completion with default part
+ * message
+ */
+
+int
+jabber_completion_msg_part_cb (void *data, const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) completion_item;
+ (void) buffer;
+
+ if (weechat_config_string (jabber_config_network_default_msg_part)
+ && weechat_config_string (jabber_config_network_default_msg_part)[0])
+ {
+ weechat_hook_completion_list_add (completion,
+ weechat_config_string (jabber_config_network_default_msg_part),
+ 0, WEECHAT_LIST_POS_SORT);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_completion_init: init completion for Jabber plugin
+ */
+
+void
+jabber_completion_init ()
+{
+ weechat_hook_completion ("jabber_server",
+ &jabber_completion_server_cb, NULL);
+ weechat_hook_completion ("jabber_server_local_name",
+ &jabber_completion_server_local_name_cb, NULL);
+ weechat_hook_completion ("jabber_server_buddies",
+ &jabber_completion_server_buddies_cb, NULL);
+ weechat_hook_completion ("jabber_servers",
+ &jabber_completion_servers_cb, NULL);
+ weechat_hook_completion ("jabber_muc",
+ &jabber_completion_muc_cb, NULL);
+ weechat_hook_completion ("buddy",
+ &jabber_completion_muc_buddies_cb, NULL);
+ weechat_hook_completion ("jabber_muc_buddies_hosts",
+ &jabber_completion_muc_buddies_hosts_cb, NULL);
+ weechat_hook_completion ("jabber_muc_topic",
+ &jabber_completion_muc_topic_cb, NULL);
+ weechat_hook_completion ("jabber_mucs",
+ &jabber_completion_mucs_cb, NULL);
+ weechat_hook_completion ("jabber_msg_part",
+ &jabber_completion_msg_part_cb, NULL);
+}
diff --git a/src/plugins/jabber/jabber-completion.h b/src/plugins/jabber/jabber-completion.h
new file mode 100644
index 000000000..8f0d187b5
--- /dev/null
+++ b/src/plugins/jabber/jabber-completion.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_COMPLETION_H
+#define __WEECHAT_JABBER_COMPLETION_H 1
+
+extern void jabber_completion_init ();
+
+#endif /* jabber-completion.h */
diff --git a/src/plugins/jabber/jabber-config.c b/src/plugins/jabber/jabber-config.c
new file mode 100644
index 000000000..9ea5dc862
--- /dev/null
+++ b/src/plugins/jabber/jabber-config.c
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-config.c: Jabber configuration options */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <pwd.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-config.h"
+#include "jabber-buffer.h"
+#include "jabber-buddy.h"
+#include "jabber-server.h"
+#include "jabber-muc.h"
+
+
+struct t_config_file *jabber_config_file = NULL;
+struct t_config_section *jabber_config_section_server_default = NULL;
+struct t_config_section *jabber_config_section_server = NULL;
+
+/* Jabber config, look section */
+
+struct t_config_option *jabber_config_look_color_nicks_in_server_messages;
+struct t_config_option *jabber_config_look_one_server_buffer;
+struct t_config_option *jabber_config_look_open_near_server;
+struct t_config_option *jabber_config_look_nick_prefix;
+struct t_config_option *jabber_config_look_nick_suffix;
+struct t_config_option *jabber_config_look_nick_completion_smart;
+struct t_config_option *jabber_config_look_display_away;
+struct t_config_option *jabber_config_look_display_muc_modes;
+struct t_config_option *jabber_config_look_hide_nickserv_pwd;
+struct t_config_option *jabber_config_look_highlight_tags;
+struct t_config_option *jabber_config_look_show_away_once;
+struct t_config_option *jabber_config_look_smart_filter;
+struct t_config_option *jabber_config_look_smart_filter_delay;
+struct t_config_option *jabber_config_look_notice_as_pv;
+
+/* Jabber config, color section */
+
+struct t_config_option *jabber_config_color_message_join;
+struct t_config_option *jabber_config_color_message_quit;
+struct t_config_option *jabber_config_color_input_nick;
+
+/* Jabber config, network section */
+
+struct t_config_option *jabber_config_network_default_msg_part;
+struct t_config_option *jabber_config_network_default_msg_quit;
+struct t_config_option *jabber_config_network_lag_check;
+struct t_config_option *jabber_config_network_lag_min_show;
+struct t_config_option *jabber_config_network_lag_disconnect;
+struct t_config_option *jabber_config_network_anti_flood;
+struct t_config_option *jabber_config_network_colors_receive;
+struct t_config_option *jabber_config_network_colors_send;
+
+/* Jabber config, server section */
+
+struct t_config_option *jabber_config_server_default[JABBER_SERVER_NUM_OPTIONS];
+
+struct t_hook *hook_config_color_nicks_number = NULL;
+
+int jabber_config_write_temp_servers = 0;
+
+
+struct t_jabber_server *
+jabber_config_get_server_from_option_name (const char *name)
+{
+ struct t_jabber_server *ptr_server;
+ char *pos_option, *server_name;
+
+ ptr_server = NULL;
+
+ if (name)
+ {
+ pos_option = strrchr (name, '.');
+ if (pos_option)
+ {
+ server_name = weechat_strndup (name, pos_option - name);
+ if (server_name)
+ {
+ ptr_server = jabber_server_search (server_name);
+ free (server_name);
+ }
+ }
+ }
+
+ return ptr_server;
+}
+
+/*
+ * jabber_config_change_look_color_nicks_number: called when the
+ * "weechat.look.color_nicks_number"
+ * option is changed
+ */
+
+int
+jabber_config_change_look_color_nicks_number (void *data, const char *option,
+ const char *value)
+{
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+ struct t_jabber_buddy *ptr_buddy;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) option;
+ (void) value;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ /* buddies in roster */
+ for (ptr_buddy = ptr_server->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ ptr_buddy->color = jabber_buddy_find_color (ptr_buddy);
+ }
+ /* buddies in MUCs */
+ for (ptr_muc = ptr_server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ for (ptr_buddy = ptr_muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ ptr_buddy->color = jabber_buddy_find_color (ptr_buddy);
+ }
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_config_change_look_one_server_buffer: called when the "one server buffer"
+ * option is changed
+ */
+
+void
+jabber_config_change_look_one_server_buffer (void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) option;
+
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer))
+ jabber_buffer_merge_servers ();
+ else
+ jabber_buffer_split_server ();
+}
+
+/*
+ * jabber_config_change_look_display_muc_modes: called when the "display
+ * MUC modes" option is changed
+ */
+
+void
+jabber_config_change_look_display_muc_modes (void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) option;
+
+ weechat_bar_item_update ("buffer_name");
+}
+
+/*
+ * jabber_config_change_look_highlight_tags: called when the "highlight tags"
+ * option is changed
+ */
+
+void
+jabber_config_change_look_highlight_tags (void *data,
+ struct t_config_option *option)
+{
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) option;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->buffer)
+ {
+ weechat_buffer_set (ptr_server->buffer, "highlight_tags",
+ weechat_config_string (jabber_config_look_highlight_tags));
+ }
+ for (ptr_muc = ptr_server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ if (ptr_muc->buffer)
+ {
+ weechat_buffer_set (ptr_muc->buffer, "highlight_tags",
+ weechat_config_string (jabber_config_look_highlight_tags));
+ }
+ }
+ }
+}
+
+/*
+ * jabber_config_change_color_input_nick: called when the color of input nick
+ * ischanged
+ */
+
+void
+jabber_config_change_color_input_nick (void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) option;
+
+ weechat_bar_item_update ("input_prompt");
+}
+
+/*
+ * jabber_config_server_default_change_cb: callback called when a default server
+ * option is modified
+ */
+
+void
+jabber_config_server_default_change_cb (void *data,
+ struct t_config_option *option)
+{
+ int index_option;
+ struct t_jabber_server *ptr_server;
+
+ index_option = jabber_server_search_option (data);
+ if (index_option >= 0)
+ {
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (weechat_config_option_is_null (ptr_server->options[index_option]))
+ {
+ switch (index_option)
+ {
+ case JABBER_SERVER_OPTION_SERVER:
+ jabber_server_set_server (ptr_server,
+ weechat_config_string (option));
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * jabber_config_server_change_cb: callback called when a server option is
+ * modified
+ */
+
+void
+jabber_config_server_change_cb (void *data, struct t_config_option *option)
+{
+ int index_option;
+ char *name;
+ struct t_jabber_server *ptr_server;
+
+ index_option = jabber_server_search_option (data);
+ if (index_option >= 0)
+ {
+ name = weechat_config_option_get_pointer (option, "name");
+ ptr_server = jabber_config_get_server_from_option_name (name);
+ if (ptr_server)
+ {
+ switch (index_option)
+ {
+ case JABBER_SERVER_OPTION_SERVER:
+ jabber_server_set_server (ptr_server,
+ JABBER_SERVER_OPTION_STRING(ptr_server,
+ JABBER_SERVER_OPTION_SERVER));
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * jabber_config_reload: reload Jabber configuration file
+ */
+
+int
+jabber_config_reload (void *data, struct t_config_file *config_file)
+{
+ int rc;
+ struct t_jabber_server *ptr_server, *next_server;
+
+ /* make C compiler happy */
+ (void) data;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ ptr_server->reloading_from_config = 1;
+ ptr_server->reloaded_from_config = 0;
+ }
+
+ rc = weechat_config_reload (config_file);
+
+ ptr_server = jabber_servers;
+ while (ptr_server)
+ {
+ next_server = ptr_server->next_server;
+
+ if (!ptr_server->reloaded_from_config)
+ {
+ if (ptr_server->is_connected)
+ {
+ weechat_printf (NULL,
+ _("%s%s: warning: server \"%s\" not found "
+ "in configuration file, not deleted in "
+ "memory because it's currently used"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ ptr_server->name);
+ }
+ else
+ jabber_server_free (ptr_server);
+ }
+
+ ptr_server = next_server;
+ }
+
+ return rc;
+}
+
+/*
+ * jabber_config_server_new_option: create a new option for a server
+ */
+
+struct t_config_option *
+jabber_config_server_new_option (struct t_config_file *config_file,
+ struct t_config_section *section,
+ int index_option,
+ const char *option_name,
+ const char *default_value,
+ const char *value,
+ int null_value_allowed,
+ void *callback_change,
+ void *callback_change_data)
+{
+ struct t_config_option *new_option;
+
+ new_option = NULL;
+
+ switch (index_option)
+ {
+ case JABBER_SERVER_OPTION_USERNAME:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("user name to use on server"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_SERVER:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("hostname/port or IP/port for server"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_PROXY:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("proxy used for this server (optional)"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_IPV6:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "boolean",
+ N_("use IPv6 protocol for server communication"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_TLS:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "boolean",
+ N_("use TLS cryptographic protocol for server communication"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_SASL:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "boolean",
+ N_("use SASL for authentication"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_RESOURCE:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("resource (for example: Home or Work)"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_PASSWORD:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("password"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_LOCAL_ALIAS:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("local alias"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_AUTOCONNECT:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "boolean",
+ N_("automatically connect to server when WeeChat is starting"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_AUTORECONNECT:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "boolean",
+ N_("automatically reconnect to server when disconnected"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_AUTORECONNECT_DELAY:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "integer",
+ N_("delay (in seconds) before trying again to reconnect to "
+ "server"),
+ NULL, 0, 65535,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_LOCAL_HOSTNAME:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("custom local hostname/IP for server (optional, if empty "
+ "local hostname is used)"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_COMMAND:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("command(s) to run when connected to server (many commands "
+ "should be separated by ';', use '\\;' for a semicolon, "
+ "special variables $nick, $muc and $server are "
+ "replaced by their value)"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_COMMAND_DELAY:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "integer",
+ N_("delay (in seconds) after command was executed (example: "
+ "give some time for authentication)"),
+ NULL, 0, 3600,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_AUTOJOIN:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ N_("comma separated list of MUCs to join when connected "
+ "to server (example: \"#chan1,#chan2,#chan3 key1,key2\")"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_OPTION_AUTOREJOIN:
+ new_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "boolean",
+ N_("automatically rejoin MUCs when kicked"),
+ NULL, 0, 0,
+ default_value, value,
+ null_value_allowed,
+ NULL, NULL,
+ callback_change, callback_change_data,
+ NULL, NULL);
+ break;
+ case JABBER_SERVER_NUM_OPTIONS:
+ break;
+ }
+
+ return new_option;
+}
+
+/*
+ * jabber_config_server_read_cb: read server option in configuration file
+ */
+
+int
+jabber_config_server_read_cb (void *data, struct t_config_file *config_file,
+ struct t_config_section *section,
+ const char *option_name, const char *value)
+{
+ struct t_jabber_server *ptr_server;
+ int index_option, rc, i;
+ char *pos_option, *server_name;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) config_file;
+ (void) section;
+
+ rc = WEECHAT_CONFIG_OPTION_SET_ERROR;
+
+ if (option_name)
+ {
+ pos_option = strrchr (option_name, '.');
+ if (pos_option)
+ {
+ server_name = weechat_strndup (option_name,
+ pos_option - option_name);
+ pos_option++;
+ if (server_name)
+ {
+ index_option = jabber_server_search_option (pos_option);
+ if (index_option >= 0)
+ {
+ ptr_server = jabber_server_search (server_name);
+ if (!ptr_server)
+ ptr_server = jabber_server_alloc (server_name);
+ if (ptr_server)
+ {
+ if (ptr_server->reloading_from_config
+ && !ptr_server->reloaded_from_config)
+ {
+ for (i = 0; i < JABBER_SERVER_NUM_OPTIONS; i++)
+ {
+ weechat_config_option_set (ptr_server->options[i],
+ NULL, 1);
+ }
+ ptr_server->reloaded_from_config = 1;
+ }
+ rc = weechat_config_option_set (ptr_server->options[index_option],
+ value, 1);
+ }
+ else
+ {
+ weechat_printf (NULL,
+ _("%s%s: error creating server "
+ "\"%s\""),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ server_name);
+ }
+ }
+ free (server_name);
+ }
+ }
+ }
+
+ if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR)
+ {
+ weechat_printf (NULL,
+ _("%s%s: error creating server option \"%s\""),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ option_name);
+ }
+
+ return rc;
+}
+
+/*
+ * jabber_config_server_write_cb: write server section in configuration file
+ */
+
+void
+jabber_config_server_write_cb (void *data, struct t_config_file *config_file,
+ const char *section_name)
+{
+ struct t_jabber_server *ptr_server;
+ int i;
+
+ /* make C compiler happy */
+ (void) data;
+
+ weechat_config_write_line (config_file, section_name, NULL);
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (!ptr_server->temp_server || jabber_config_write_temp_servers)
+ {
+ for (i = 0; i < JABBER_SERVER_NUM_OPTIONS; i++)
+ {
+ weechat_config_write_option (config_file,
+ ptr_server->options[i]);
+ }
+ }
+ }
+}
+
+/*
+ * jabber_config_server_create_default_options: create default options for
+ * servers
+ */
+
+void
+jabber_config_server_create_default_options (struct t_config_section *section)
+{
+ int i;
+
+ for (i = 0; i < JABBER_SERVER_NUM_OPTIONS; i++)
+ {
+ jabber_config_server_default[i] = jabber_config_server_new_option (
+ jabber_config_file,
+ section,
+ i,
+ jabber_server_option_string[i],
+ jabber_server_option_default[i],
+ jabber_server_option_default[i],
+ 0,
+ &jabber_config_server_default_change_cb,
+ jabber_server_option_string[i]);
+ }
+}
+
+/*
+ * jabber_config_init: init Jabber configuration file
+ * return: 1 if ok, 0 if error
+ */
+
+int
+jabber_config_init ()
+{
+ struct t_config_section *ptr_section;
+
+ jabber_config_file = weechat_config_new (JABBER_CONFIG_NAME,
+ &jabber_config_reload, NULL);
+ if (!jabber_config_file)
+ return 0;
+
+ /* look */
+ ptr_section = weechat_config_new_section (jabber_config_file, "look",
+ 0, 0,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (jabber_config_file);
+ return 0;
+ }
+
+ jabber_config_look_color_nicks_in_server_messages = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "color_nicks_in_server_messages", "boolean",
+ N_("use nick color in messages from server"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ jabber_config_look_one_server_buffer = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "one_server_buffer", "boolean",
+ N_("use same buffer for all servers"),
+ NULL, 0, 0, "off", NULL, 0, NULL, NULL,
+ &jabber_config_change_look_one_server_buffer, NULL, NULL, NULL);
+ jabber_config_look_open_near_server = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "open_near_server", "boolean",
+ N_("open new MUCs/privates near server"),
+ NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_nick_prefix = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "nick_prefix", "string",
+ N_("text to display before nick in chat window"),
+ NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_nick_suffix = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "nick_suffix", "string",
+ N_("text to display after nick in chat window"),
+ NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_nick_completion_smart = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "nick_completion_smart", "boolean",
+ N_("smart completion for nicks (completes with last speakers first)"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_display_away = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "display_away", "integer",
+ N_("display message when (un)marking as away"),
+ "off|local|muc", 0, 0, "local", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_display_muc_modes = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "display_muc_modes", "boolean",
+ N_("display MUC modes in \"buffer_name\" bar item"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL,
+ &jabber_config_change_look_display_muc_modes, NULL, NULL, NULL);
+ jabber_config_look_hide_nickserv_pwd = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "hide_nickserv_pwd", "boolean",
+ N_("hide password displayed by nickserv"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_highlight_tags = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "highlight_tags", "string",
+ N_("comma separated list of tags for messages that may produce "
+ "highlight (usually any message from another user, not server "
+ "messages,..)"),
+ NULL, 0, 0, "jabber_chat_msg,jabber_notice", NULL, 0, NULL, NULL,
+ &jabber_config_change_look_highlight_tags, NULL, NULL, NULL);
+ jabber_config_look_show_away_once = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "show_away_once", "boolean",
+ N_("show remote away message only once in private"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_smart_filter = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "smart_filter", "boolean",
+ N_("filter join/part/quit messages for a nick if not speaking for "
+ "some minutes on MUC (you must create a filter on tag "
+ "\"jabber_smart_filter\")"),
+ NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_smart_filter_delay = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "smart_filter_delay", "integer",
+ N_("delay for filtering join/part/quit messages (in minutes)"),
+ NULL, 1, 60*24*7, "5", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_look_notice_as_pv = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "notice_as_pv", "boolean",
+ N_("display notices as private messages"),
+ NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* color */
+ ptr_section = weechat_config_new_section (jabber_config_file, "color",
+ 0, 0,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (jabber_config_file);
+ return 0;
+ }
+
+ jabber_config_color_message_join = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "message_join", "color",
+ N_("color for text in join messages"),
+ NULL, -1, 0, "green", NULL, 0, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ jabber_config_color_message_quit = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "message_quit", "color",
+ N_("color for text in part/quit messages"),
+ NULL, -1, 0, "red", NULL, 0, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ jabber_config_color_input_nick = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "input_nick", "color",
+ N_("color for nick in input bar"),
+ NULL, -1, 0, "lightcyan", NULL, 0, NULL, NULL,
+ &jabber_config_change_color_input_nick, NULL, NULL, NULL);
+
+ /* network */
+ ptr_section = weechat_config_new_section (jabber_config_file, "network",
+ 0, 0,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (jabber_config_file);
+ return 0;
+ }
+
+ jabber_config_network_default_msg_part = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "default_msg_part", "string",
+ N_("default part message (leaving MUC) ('%v' will be replaced by "
+ "WeeChat version in string)"),
+ NULL, 0, 0, "WeeChat %v", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_default_msg_quit = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "default_msg_quit", "string",
+ N_("default quit message (disconnecting from server) ('%v' will be "
+ "replaced by WeeChat version in string)"),
+ NULL, 0, 0, "WeeChat %v", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_lag_check = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "lag_check", "integer",
+ N_("interval between two checks for lag (in seconds, 0 = never "
+ "check)"),
+ NULL, 0, INT_MAX, "60", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_lag_min_show = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "lag_min_show", "integer",
+ N_("minimum lag to show (in seconds)"),
+ NULL, 0, INT_MAX, "1", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_lag_disconnect = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "lag_disconnect", "integer",
+ N_("disconnect after important lag (in minutes, 0 = never "
+ "disconnect)"),
+ NULL, 0, INT_MAX, "5", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_anti_flood = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "anti_flood", "integer",
+ N_("anti-flood: # seconds between two user messages (0 = no "
+ "anti-flood)"),
+ NULL, 0, 5, "2", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_colors_receive = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "colors_receive", "boolean",
+ N_("when off, colors codes are ignored in incoming messages"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ jabber_config_network_colors_send = weechat_config_new_option (
+ jabber_config_file, ptr_section,
+ "colors_send", "boolean",
+ N_("allow user to send colors with special codes (^Cb=bold, "
+ "^Ccxx=color, ^Ccxx,yy=color+background, ^Cu=underline, "
+ "^Cr=reverse)"),
+ NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* server_default */
+ ptr_section = weechat_config_new_section (jabber_config_file, "server_default",
+ 0, 0,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (jabber_config_file);
+ return 0;
+ }
+
+ jabber_config_section_server_default = ptr_section;
+
+ jabber_config_server_create_default_options (ptr_section);
+
+ /* server */
+ ptr_section = weechat_config_new_section (jabber_config_file, "server",
+ 0, 0,
+ &jabber_config_server_read_cb, NULL,
+ &jabber_config_server_write_cb, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (jabber_config_file);
+ return 0;
+ }
+
+ jabber_config_section_server = ptr_section;
+
+ hook_config_color_nicks_number = weechat_hook_config ("weechat.look.color_nicks_number",
+ &jabber_config_change_look_color_nicks_number, NULL);
+
+ return 1;
+}
+
+/*
+ * jabber_config_read: read Jabber configuration file
+ */
+
+int
+jabber_config_read ()
+{
+ return weechat_config_read (jabber_config_file);
+}
+
+/*
+ * jabber_config_write: write Jabber configuration file
+ */
+
+int
+jabber_config_write (int write_temp_servers)
+{
+ jabber_config_write_temp_servers = write_temp_servers;
+
+ return weechat_config_write (jabber_config_file);
+}
+
+/*
+ * jabber_config_free: free Jabber configuration
+ */
+
+void
+jabber_config_free ()
+{
+ weechat_config_free (jabber_config_file);
+
+ if (hook_config_color_nicks_number)
+ {
+ weechat_unhook (hook_config_color_nicks_number);
+ hook_config_color_nicks_number = NULL;
+ }
+}
diff --git a/src/plugins/jabber/jabber-config.h b/src/plugins/jabber/jabber-config.h
new file mode 100644
index 000000000..466ea3539
--- /dev/null
+++ b/src/plugins/jabber/jabber-config.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_CONFIG_H
+#define __WEECHAT_JABBER_CONFIG_H 1
+
+#define JABBER_CONFIG_NAME "jabber"
+
+#define JABBER_CONFIG_DISPLAY_AWAY_OFF 0
+#define JABBER_CONFIG_DISPLAY_AWAY_LOCAL 1
+#define JABBER_CONFIG_DISPLAY_AWAY_MUC 2
+
+
+extern struct t_config_file *jabber_config_file;
+extern struct t_config_section *jabber_config_section_server_default;
+extern struct t_config_section *jabber_config_section_server;
+
+extern struct t_config_option *jabber_config_look_color_nicks_in_server_messages;
+extern struct t_config_option *jabber_config_look_one_server_buffer;
+extern struct t_config_option *jabber_config_look_open_near_server;
+extern struct t_config_option *jabber_config_look_nick_prefix;
+extern struct t_config_option *jabber_config_look_nick_suffix;
+extern struct t_config_option *jabber_config_look_nick_completion_smart;
+extern struct t_config_option *jabber_config_look_display_away;
+extern struct t_config_option *jabber_config_look_display_muc_modes;
+extern struct t_config_option *jabber_config_look_hide_nickserv_pwd;
+extern struct t_config_option *jabber_config_look_highlight_tags;
+extern struct t_config_option *jabber_config_look_show_away_once;
+extern struct t_config_option *jabber_config_look_smart_filter;
+extern struct t_config_option *jabber_config_look_smart_filter_delay;
+extern struct t_config_option *jabber_config_look_notice_as_pv;
+
+extern struct t_config_option *jabber_config_color_message_join;
+extern struct t_config_option *jabber_config_color_message_quit;
+extern struct t_config_option *jabber_config_color_input_nick;
+
+extern struct t_config_option *jabber_config_network_default_msg_part;
+extern struct t_config_option *jabber_config_network_default_msg_quit;
+extern struct t_config_option *jabber_config_network_lag_check;
+extern struct t_config_option *jabber_config_network_lag_min_show;
+extern struct t_config_option *jabber_config_network_lag_disconnect;
+extern struct t_config_option *jabber_config_network_anti_flood;
+extern struct t_config_option *jabber_config_network_colors_receive;
+extern struct t_config_option *jabber_config_network_colors_send;
+
+extern struct t_config_option *jabber_config_server_default[];
+
+extern void jabber_config_server_change_cb (void *data,
+ struct t_config_option *option);
+struct t_config_option *jabber_config_server_new_option (struct t_config_file *config_file,
+ struct t_config_section *section,
+ int index_option,
+ const char *option_name,
+ const char *default_value,
+ const char *value,
+ int null_value_allowed,
+ void *callback_change,
+ void *callback_change_data);
+extern int jabber_config_init ();
+extern int jabber_config_read ();
+extern int jabber_config_write (int write_temp_servers);
+extern void jabber_config_free ();
+
+#endif /* jabber-config.h */
diff --git a/src/plugins/jabber/jabber-debug.c b/src/plugins/jabber/jabber-debug.c
new file mode 100644
index 000000000..b5914f8a5
--- /dev/null
+++ b/src/plugins/jabber/jabber-debug.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-debug.c: debug functions for Jabber plugin */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-debug.h"
+#include "jabber-server.h"
+
+
+struct t_gui_buffer *jabber_debug_buffer = NULL;
+
+
+/*
+ * jabber_debug_buffer_close_cb: callback called when Jabber debug buffer is
+ * closed
+ */
+
+int
+jabber_debug_buffer_close_cb (void *data, struct t_gui_buffer *buffer)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) buffer;
+
+ jabber_debug_buffer = NULL;
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_debug_printf: print a message on Jabber debug buffer
+ */
+
+void
+jabber_debug_printf (struct t_jabber_server *server, int send, int modified,
+ const char *message)
+{
+ char *buf;
+
+ if (!weechat_jabber_plugin->debug || !message)
+ return;
+
+ if (!jabber_debug_buffer)
+ {
+ jabber_debug_buffer = weechat_buffer_search ("jabber",
+ JABBER_DEBUG_BUFFER_NAME);
+ if (!jabber_debug_buffer)
+ {
+ jabber_debug_buffer = weechat_buffer_new (JABBER_DEBUG_BUFFER_NAME,
+ NULL, NULL,
+ &jabber_debug_buffer_close_cb, NULL);
+
+ /* failed to create buffer ? then return */
+ if (!jabber_debug_buffer)
+ return;
+
+ weechat_buffer_set (jabber_debug_buffer,
+ "title", _("Jabber debug messages"));
+
+ weechat_buffer_set (jabber_debug_buffer, "short_name", JABBER_DEBUG_BUFFER_NAME);
+ weechat_buffer_set (jabber_debug_buffer, "localvar_set_server", JABBER_DEBUG_BUFFER_NAME);
+ weechat_buffer_set (jabber_debug_buffer, "localvar_set_muc", JABBER_DEBUG_BUFFER_NAME);
+ weechat_buffer_set (jabber_debug_buffer, "localvar_set_no_log", "1");
+
+ /* disabled all highlights on this debug buffer */
+ weechat_buffer_set (jabber_debug_buffer, "highlight_words", "-");
+ }
+ }
+
+ buf = weechat_iconv_to_internal (NULL, message);
+
+ weechat_printf (jabber_debug_buffer,
+ "%s%s%s%s%s%s\t%s",
+ (server) ? weechat_color ("chat_server") : "",
+ (server) ? server->name : "",
+ (server) ? " " : "",
+ (send) ?
+ weechat_color ("chat_prefix_quit") :
+ weechat_color ("chat_prefix_join"),
+ (iks_is_secure (server->iks_parser)) ? "* " : "",
+ (send) ?
+ ((modified) ? JABBER_DEBUG_PREFIX_SEND_MOD : JABBER_DEBUG_PREFIX_SEND) :
+ ((modified) ? JABBER_DEBUG_PREFIX_RECV_MOD : JABBER_DEBUG_PREFIX_RECV),
+ (buf) ? buf : message);
+ if (buf)
+ free (buf);
+}
+
+/*
+ * jabber_debug_signal_debug_dump_cb: dump Jabber data in WeeChat log file
+ */
+
+int
+jabber_debug_signal_debug_dump_cb (void *data, const char *signal,
+ const char *type_data, void *signal_data)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) signal;
+ (void) type_data;
+ (void) signal_data;
+
+ weechat_log_printf ("");
+ weechat_log_printf ("***** \"%s\" plugin dump *****",
+ weechat_plugin->name);
+
+ jabber_server_print_log ();
+
+ weechat_log_printf ("");
+ weechat_log_printf ("***** End of \"%s\" plugin dump *****",
+ weechat_plugin->name);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_debug_init: initialize debug for Jabber plugin
+ */
+
+void
+jabber_debug_init ()
+{
+ weechat_hook_signal ("debug_dump", &jabber_debug_signal_debug_dump_cb, NULL);
+}
diff --git a/src/plugins/jabber/jabber-debug.h b/src/plugins/jabber/jabber-debug.h
new file mode 100644
index 000000000..52a1379fb
--- /dev/null
+++ b/src/plugins/jabber/jabber-debug.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_DEBUG_H
+#define __WEECHAT_JABBER_DEBUG_H 1
+
+#define JABBER_DEBUG_BUFFER_NAME "jabber_debug"
+
+#define JABBER_DEBUG_PREFIX_RECV "-->"
+#define JABBER_DEBUG_PREFIX_RECV_MOD "==>"
+#define JABBER_DEBUG_PREFIX_SEND "<--"
+#define JABBER_DEBUG_PREFIX_SEND_MOD "<=="
+
+struct t_jabber_server;
+
+extern void jabber_debug_printf (struct t_jabber_server *server, int send,
+ int modified, const char *message);
+extern void jabber_debug_init ();
+
+#endif /* jabber-debug.h */
diff --git a/src/plugins/jabber/jabber-display.c b/src/plugins/jabber/jabber-display.c
new file mode 100644
index 000000000..7eace16c7
--- /dev/null
+++ b/src/plugins/jabber/jabber-display.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-display.c: display functions for Jabber plugin */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-command.h"
+#include "jabber-config.h"
+#include "jabber-server.h"
+
+
+/*
+ * jabber_display_server: display server infos
+ */
+
+void
+jabber_display_server (struct t_jabber_server *server, int with_detail)
+{
+ int num_mucs, num_pv;
+
+ if (with_detail)
+ {
+ weechat_printf (NULL, "");
+ weechat_printf (NULL, _("%sServer: %s%s %s[%s%s%s]%s%s"),
+ JABBER_COLOR_CHAT,
+ JABBER_COLOR_CHAT_SERVER,
+ server->name,
+ JABBER_COLOR_CHAT_DELIMITERS,
+ JABBER_COLOR_CHAT,
+ (server->is_connected) ?
+ _("connected") : _("not connected"),
+ JABBER_COLOR_CHAT_DELIMITERS,
+ JABBER_COLOR_CHAT,
+ (server->temp_server) ? _(" (temporary)") : "");
+
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_USERNAME]))
+ weechat_printf (NULL, " username . . . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_USERNAME));
+ else
+ weechat_printf (NULL, " username . . . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_USERNAME]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_SERVER]))
+ weechat_printf (NULL, " server . . . . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_SERVER));
+ else
+ weechat_printf (NULL, " server . . . . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_SERVER]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_PROXY]))
+ weechat_printf (NULL, " proxy. . . . . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_PROXY));
+ else
+ weechat_printf (NULL, " proxy. . . . . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_PROXY]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_IPV6]))
+ weechat_printf (NULL, " ipv6 . . . . . . . . : (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_IPV6)) ?
+ _("on") : _("off"));
+ else
+ weechat_printf (NULL, " ipv6 . . . . . . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_boolean (server->options[JABBER_SERVER_OPTION_IPV6]) ?
+ _("on") : _("off"));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_TLS]))
+ weechat_printf (NULL, " tls. . . . . . . . . : (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_TLS)) ?
+ _("on") : _("off"));
+ else
+ weechat_printf (NULL, " tls. . . . . . . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_boolean (server->options[JABBER_SERVER_OPTION_TLS]) ?
+ _("on") : _("off"));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_SASL]))
+ weechat_printf (NULL, " sasl . . . . . . . . : (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_SASL)) ?
+ _("on") : _("off"));
+ else
+ weechat_printf (NULL, " sasl . . . . . . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_boolean (server->options[JABBER_SERVER_OPTION_SASL]) ?
+ _("on") : _("off"));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_RESOURCE]))
+ weechat_printf (NULL, " resource . . . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_RESOURCE));
+ else
+ weechat_printf (NULL, " resource . . . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_RESOURCE]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_PASSWORD]))
+ weechat_printf (NULL, " password . . . . . . : %s",
+ _("(hidden)"));
+ else
+ weechat_printf (NULL, " password . . . . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ _("(hidden)"));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_LOCAL_ALIAS]))
+ weechat_printf (NULL, " local_alias. . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_LOCAL_ALIAS));
+ else
+ weechat_printf (NULL, " local_alias. . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_LOCAL_ALIAS]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_AUTOCONNECT]))
+ weechat_printf (NULL, " autoconnect. . . . . : (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTOCONNECT)) ?
+ _("on") : _("off"));
+ else
+ weechat_printf (NULL, " autoconnect. . . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_boolean (server->options[JABBER_SERVER_OPTION_AUTOCONNECT]) ?
+ _("on") : _("off"));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_AUTORECONNECT]))
+ weechat_printf (NULL, " autoreconnect. . . . : (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTORECONNECT)) ?
+ _("on") : _("off"));
+ else
+ weechat_printf (NULL, " autoreconnect. . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_boolean (server->options[JABBER_SERVER_OPTION_AUTORECONNECT]) ?
+ _("on") : _("off"));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_AUTORECONNECT_DELAY]))
+ weechat_printf (NULL, " autoreconnect_delay. : (%d %s)",
+ JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_AUTORECONNECT_DELAY),
+ NG_("second", "seconds", JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_AUTORECONNECT_DELAY)));
+ else
+ weechat_printf (NULL, " autoreconnect_delay. : %s%d %s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_integer (server->options[JABBER_SERVER_OPTION_AUTORECONNECT_DELAY]),
+ NG_("second", "seconds", weechat_config_integer (server->options[JABBER_SERVER_OPTION_AUTORECONNECT_DELAY])));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_LOCAL_HOSTNAME]))
+ weechat_printf (NULL, " local_hostname . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_LOCAL_HOSTNAME));
+ else
+ weechat_printf (NULL, " local_hostname . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_LOCAL_HOSTNAME]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_COMMAND]))
+ weechat_printf (NULL, " command. . . . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_COMMAND));
+ else
+ weechat_printf (NULL, " command. . . . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_COMMAND]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_COMMAND_DELAY]))
+ weechat_printf (NULL, " command_delay. . . . : (%d %s)",
+ JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_COMMAND_DELAY),
+ NG_("second", "seconds", JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_COMMAND_DELAY)));
+ else
+ weechat_printf (NULL, " command_delay. . . . : %s%d %s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_integer (server->options[JABBER_SERVER_OPTION_COMMAND_DELAY]),
+ NG_("second", "seconds", weechat_config_integer (server->options[JABBER_SERVER_OPTION_COMMAND_DELAY])));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_AUTOJOIN]))
+ weechat_printf (NULL, " autojoin . . . . . . : ('%s')",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_AUTOJOIN));
+ else
+ weechat_printf (NULL, " autojoin . . . . . . : %s'%s'",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_string (server->options[JABBER_SERVER_OPTION_AUTOJOIN]));
+ if (weechat_config_option_is_null (server->options[JABBER_SERVER_OPTION_AUTOREJOIN]))
+ weechat_printf (NULL, " autorejoin . . . . . : (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTOREJOIN)) ?
+ _("on") : _("off"));
+ else
+ weechat_printf (NULL, " autorejoin . . . . . : %s%s",
+ JABBER_COLOR_CHAT_HOST,
+ weechat_config_boolean (server->options[JABBER_SERVER_OPTION_AUTOREJOIN]) ?
+ _("on") : _("off"));
+ }
+ else
+ {
+ if (server->is_connected)
+ {
+ num_mucs = jabber_server_get_muc_count (server);
+ num_pv = jabber_server_get_pv_count (server);
+ weechat_printf (NULL, " %s %s%s %s[%s%s%s]%s%s, %d %s, %d pv",
+ (server->is_connected) ? "*" : " ",
+ JABBER_COLOR_CHAT_SERVER,
+ server->name,
+ JABBER_COLOR_CHAT_DELIMITERS,
+ JABBER_COLOR_CHAT,
+ (server->is_connected) ?
+ _("connected") : _("not connected"),
+ JABBER_COLOR_CHAT_DELIMITERS,
+ JABBER_COLOR_CHAT,
+ (server->temp_server) ? _(" (temporary)") : "",
+ num_mucs,
+ NG_("MUC", "MUCs", num_mucs),
+ num_pv);
+ }
+ else
+ {
+ weechat_printf (NULL, " %s%s%s%s",
+ JABBER_COLOR_CHAT_SERVER,
+ server->name,
+ JABBER_COLOR_CHAT,
+ (server->temp_server) ? _(" (temporary)") : "");
+ }
+ }
+}
diff --git a/src/plugins/jabber/jabber-display.h b/src/plugins/jabber/jabber-display.h
new file mode 100644
index 000000000..bec2e51c9
--- /dev/null
+++ b/src/plugins/jabber/jabber-display.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_DISPLAY_H
+#define __WEECHAT_JABBER_DISPLAY_H 1
+
+extern void jabber_display_server (struct t_jabber_server *server,
+ int with_detail);
+
+#endif /* jabber-display.h */
diff --git a/src/plugins/jabber/jabber-info.c b/src/plugins/jabber/jabber-info.c
new file mode 100644
index 000000000..4279d6199
--- /dev/null
+++ b/src/plugins/jabber/jabber-info.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-info.c: info and infolist hooks for Jabber plugin */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-buddy.h"
+#include "jabber-muc.h"
+#include "jabber-server.h"
+
+
+/*
+ * jabber_info_create_string_with_pointer: create a string with a pointer inside
+ * a Jabber structure
+ */
+
+void
+jabber_info_create_string_with_pointer (char **string, void *pointer)
+{
+ if (*string)
+ {
+ free (*string);
+ *string = NULL;
+ }
+ if (pointer)
+ {
+ *string = malloc (64);
+ if (*string)
+ {
+ snprintf (*string, 64 - 1, "0x%lx", (long unsigned int)pointer);
+ }
+ }
+}
+
+/*
+ * jabber_info_get_info_cb: callback called when Jabber info is asked
+ */
+
+const char *
+jabber_info_get_info_cb (void *data, const char *info_name,
+ const char *arguments)
+{
+ char *pos_comma, *pos_comma2, *server, *muc, *host;
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+
+ /* make C compiler happy */
+ (void) data;
+
+ if (weechat_strcasecmp (info_name, "jabber_buffer") == 0)
+ {
+ if (arguments && arguments[0])
+ {
+ server = NULL;
+ muc = NULL;
+ host = NULL;
+ ptr_server = NULL;
+ ptr_muc = NULL;
+
+ pos_comma = strchr (arguments, ',');
+ if (pos_comma)
+ {
+ server = weechat_strndup (arguments, pos_comma - arguments);
+ pos_comma2 = strchr (pos_comma + 1, ',');
+ if (pos_comma2)
+ {
+ muc = weechat_strndup (pos_comma + 1,
+ pos_comma2 - pos_comma - 1);
+ host = strdup (pos_comma2 + 1);
+ }
+ else
+ muc = strdup (pos_comma + 1);
+ }
+
+ /* replace MUC by buddy in host if MUC is not a MUC (private ?) */
+ if (muc && host)
+ {
+ //if (!jabber_muc_is_muc (muc))
+ //{
+ // free (muc);
+ // muc = NULL;
+ // buddy = jabber_xmpp_get_buddy_from_host (host);
+ // if (buddy)
+ // muc = strdup (buddy);
+ //}
+ }
+
+ /* search for server or MUC buffer */
+ if (server)
+ {
+ ptr_server = jabber_server_search (server);
+ if (ptr_server && muc)
+ ptr_muc = jabber_muc_search (ptr_server, muc);
+ }
+
+ if (server)
+ free (server);
+ if (muc)
+ free (muc);
+ if (host)
+ free (host);
+
+ if (ptr_muc)
+ {
+ jabber_info_create_string_with_pointer (&ptr_muc->buffer_as_string,
+ ptr_muc->buffer);
+ return ptr_muc->buffer_as_string;
+ }
+ if (ptr_server)
+ {
+ jabber_info_create_string_with_pointer (&ptr_server->buffer_as_string,
+ ptr_server->buffer);
+ return ptr_server->buffer_as_string;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * jabber_info_get_infolist_cb: callback called when Jabber infolist is asked
+ */
+
+struct t_infolist *
+jabber_info_get_infolist_cb (void *data, const char *infolist_name,
+ void *pointer, const char *arguments)
+{
+ struct t_infolist *ptr_infolist;
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+ struct t_jabber_buddy *ptr_buddy;
+ char *pos_comma, *server_name;
+
+ /* make C compiler happy */
+ (void) data;
+
+ if (!infolist_name || !infolist_name[0])
+ return NULL;
+
+ if (weechat_strcasecmp (infolist_name, "jabber_server") == 0)
+ {
+ if (pointer && !jabber_server_valid (pointer))
+ return NULL;
+
+ ptr_infolist = weechat_infolist_new ();
+ if (ptr_infolist)
+ {
+ if (pointer)
+ {
+ /* build list with only one server */
+ if (!jabber_server_add_to_infolist (ptr_infolist, pointer))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ return ptr_infolist;
+ }
+ else
+ {
+ /* build list with all servers */
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (!jabber_server_add_to_infolist (ptr_infolist, ptr_server))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ }
+ return ptr_infolist;
+ }
+ }
+ }
+ else if (weechat_strcasecmp (infolist_name, "jabber_muc") == 0)
+ {
+ if (arguments && arguments[0])
+ {
+ ptr_server = jabber_server_search (arguments);
+ if (ptr_server)
+ {
+ if (pointer && !jabber_muc_valid (ptr_server, pointer))
+ return NULL;
+
+ ptr_infolist = weechat_infolist_new ();
+ if (ptr_infolist)
+ {
+ if (pointer)
+ {
+ /* build list with only one MUC */
+ if (!jabber_muc_add_to_infolist (ptr_infolist, pointer))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ return ptr_infolist;
+ }
+ else
+ {
+ /* build list with all MUCs of server */
+ for (ptr_muc = ptr_server->mucs; ptr_muc;
+ ptr_muc = ptr_muc->next_muc)
+ {
+ if (!jabber_muc_add_to_infolist (ptr_infolist,
+ ptr_muc))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ }
+ return ptr_infolist;
+ }
+ }
+ }
+ }
+ }
+ else if (weechat_strcasecmp (infolist_name, "jabber_buddy") == 0)
+ {
+ if (arguments && arguments[0])
+ {
+ ptr_server = NULL;
+ ptr_muc = NULL;
+ pos_comma = strchr (arguments, ',');
+ if (pos_comma)
+ {
+ server_name = weechat_strndup (arguments, pos_comma - arguments);
+ if (server_name)
+ {
+ ptr_server = jabber_server_search (server_name);
+ if (ptr_server)
+ {
+ ptr_muc = jabber_muc_search (ptr_server,
+ pos_comma + 1);
+ }
+ free (server_name);
+ }
+ }
+ if (ptr_muc)
+ {
+ if (pointer && !jabber_buddy_valid (NULL, ptr_muc, pointer))
+ return NULL;
+
+ ptr_infolist = weechat_infolist_new ();
+ if (ptr_infolist)
+ {
+ if (pointer)
+ {
+ /* build list with only one buddy */
+ if (!jabber_buddy_add_to_infolist (ptr_infolist, pointer))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ return ptr_infolist;
+ }
+ else
+ {
+ /* build list with all buddies of MUC */
+ for (ptr_buddy = ptr_muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (!jabber_buddy_add_to_infolist (ptr_infolist,
+ ptr_buddy))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ }
+ return ptr_infolist;
+ }
+ }
+ }
+ else if (ptr_server)
+ {
+ if (pointer && !jabber_buddy_valid (ptr_server, NULL, pointer))
+ return NULL;
+
+ ptr_infolist = weechat_infolist_new ();
+ if (ptr_infolist)
+ {
+ if (pointer)
+ {
+ /* build list with only one buddy */
+ if (!jabber_buddy_add_to_infolist (ptr_infolist, pointer))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ return ptr_infolist;
+ }
+ else
+ {
+ /* build list with all buddies of server */
+ for (ptr_buddy = ptr_server->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (!jabber_buddy_add_to_infolist (ptr_infolist,
+ ptr_buddy))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ }
+ return ptr_infolist;
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * jabber_info_init: initialize info and infolist hooks for Jabber plugin
+ */
+
+void
+jabber_info_init ()
+{
+ /* info hooks */
+ weechat_hook_info ("jabber_buffer",
+ N_("get buffer pointer for a Jabber server/MUC"),
+ &jabber_info_get_info_cb, NULL);
+
+ /* infolist hooks */
+ weechat_hook_infolist ("jabber_server",
+ N_("list of Jabber servers"),
+ &jabber_info_get_infolist_cb, NULL);
+ weechat_hook_infolist ("jabber_muc",
+ N_("list of MUCs for a Jabber server"),
+ &jabber_info_get_infolist_cb, NULL);
+ weechat_hook_infolist ("jabber_buddy",
+ N_("list of buddies for a Jabber server or MUC"),
+ &jabber_info_get_infolist_cb, NULL);
+}
diff --git a/src/plugins/jabber/jabber-info.h b/src/plugins/jabber/jabber-info.h
new file mode 100644
index 000000000..364a0c1ae
--- /dev/null
+++ b/src/plugins/jabber/jabber-info.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_INFO_H
+#define __WEECHAT_JABBER_INFO_H 1
+
+extern void jabber_info_init ();
+
+#endif /* jabber-info.h */
diff --git a/src/plugins/jabber/jabber-input.c b/src/plugins/jabber/jabber-input.c
new file mode 100644
index 000000000..42f2b83c4
--- /dev/null
+++ b/src/plugins/jabber/jabber-input.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-input.c: Jabber input data (read from user) */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-buffer.h"
+#include "jabber-server.h"
+#include "jabber-muc.h"
+#include "jabber-buddy.h"
+#include "jabber-config.h"
+#include "jabber-xmpp.h"
+
+
+/*
+ * jabber_input_user_message_display: display user message
+ */
+
+void
+jabber_input_user_message_display (struct t_gui_buffer *buffer,
+ const char *text)
+{
+ struct t_jabber_buddy *ptr_buddy;
+ const char *local_name;
+
+ JABBER_GET_SERVER_MUC(buffer);
+
+ local_name = jabber_server_get_local_name (ptr_server);
+
+ if (ptr_muc)
+ {
+ if (ptr_muc->type == JABBER_MUC_TYPE_MUC)
+ ptr_buddy = jabber_buddy_search (NULL, ptr_muc, local_name);
+ else
+ ptr_buddy = NULL;
+
+ weechat_printf_tags (buffer,
+ jabber_xmpp_tags ("chat_msg", "no_highlight"),
+ "%s%s",
+ jabber_buddy_as_prefix ((ptr_buddy) ? ptr_buddy : NULL,
+ (ptr_buddy) ? NULL : local_name,
+ JABBER_COLOR_CHAT_NICK_SELF),
+ text);
+ }
+}
+
+/*
+ * jabber_input_data_cb: callback for input data in a buffer
+ */
+
+int
+jabber_input_data_cb (void *data, struct t_gui_buffer *buffer,
+ const char *input_data)
+{
+ const char *ptr_data;
+ char *msg;
+
+ /* make C compiler happy */
+ (void) data;
+
+ JABBER_GET_SERVER_MUC(buffer);
+
+ if (ptr_muc)
+ {
+ ptr_data = ((input_data[0] == '/') && (input_data[1] == '/')) ?
+ input_data + 1 : input_data;
+
+ msg = strdup (ptr_data);
+ if (msg)
+ {
+ jabber_xmpp_send_chat_message (ptr_server, ptr_muc, msg);
+ jabber_input_user_message_display (buffer, msg);
+ free (msg);
+ }
+ }
+ else
+ {
+ weechat_printf (buffer,
+ _("%s: this buffer is not a MUC!"),
+ JABBER_PLUGIN_NAME);
+ }
+
+ return WEECHAT_RC_OK;
+}
diff --git a/src/plugins/jabber/jabber-input.h b/src/plugins/jabber/jabber-input.h
new file mode 100644
index 000000000..979546f96
--- /dev/null
+++ b/src/plugins/jabber/jabber-input.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_INPUT_H
+#define __WEECHAT_JABBER_INPUT_H 1
+
+struct t_gui_buffer;
+
+extern void jabber_input_user_message_display (struct t_gui_buffer *buffer,
+ const char *text);
+extern int jabber_input_data_cb (void *data, struct t_gui_buffer *buffer,
+ const char *input_data);
+
+#endif /* jabber-input.h */
diff --git a/src/plugins/jabber/jabber-muc.c b/src/plugins/jabber/jabber-muc.c
new file mode 100644
index 000000000..80a1e8787
--- /dev/null
+++ b/src/plugins/jabber/jabber-muc.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-muc.c: jabber MUC management */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-muc.h"
+#include "jabber-buffer.h"
+#include "jabber-config.h"
+#include "jabber-buddy.h"
+#include "jabber-server.h"
+#include "jabber-input.h"
+
+
+/*
+ * jabber_muc_valid: check if a MUC pointer exists for a server
+ * return 1 if MUC exists
+ * 0 if MUC is not found
+ */
+
+int
+jabber_muc_valid (struct t_jabber_server *server, struct t_jabber_muc *muc)
+{
+ struct t_jabber_muc *ptr_muc;
+
+ if (!server)
+ return 0;
+
+ for (ptr_muc = server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ if (ptr_muc == muc)
+ return 1;
+ }
+
+ /* MUC not found */
+ return 0;
+}
+
+/*
+ * jabber_muc_new: allocate a new MUC for a server and add it to MUC list
+ */
+
+struct t_jabber_muc *
+jabber_muc_new (struct t_jabber_server *server, int muc_type,
+ const char *muc_name, int switch_to_muc)
+{
+ struct t_jabber_muc *new_muc;
+ struct t_gui_buffer *new_buffer;
+ char *buffer_name;
+
+ /* alloc memory for new MUCl */
+ if ((new_muc = malloc (sizeof (*new_muc))) == NULL)
+ {
+ weechat_printf (NULL,
+ _("%s%s: cannot allocate new MUC"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME);
+ return NULL;
+ }
+
+ /* create buffer for MUC (or use existing one) */
+ buffer_name = jabber_buffer_build_name (server->name, muc_name);
+ new_buffer = weechat_buffer_search (JABBER_PLUGIN_NAME, buffer_name);
+ if (new_buffer)
+ weechat_nicklist_remove_all (new_buffer);
+ else
+ {
+ new_buffer = weechat_buffer_new (buffer_name,
+ &jabber_input_data_cb, NULL,
+ &jabber_buffer_close_cb, NULL);
+ if (!new_buffer)
+ {
+ free (new_muc);
+ return NULL;
+ }
+
+ weechat_buffer_set (new_buffer, "short_name", muc_name);
+ weechat_buffer_set (new_buffer, "localvar_set_nick",
+ jabber_server_get_local_name (server));
+ weechat_buffer_set (new_buffer, "localvar_set_server", server->name);
+ weechat_buffer_set (new_buffer, "localvar_set_muc", muc_name);
+
+ weechat_hook_signal_send ("logger_backlog",
+ WEECHAT_HOOK_SIGNAL_POINTER, new_buffer);
+ }
+
+ if (muc_type == JABBER_MUC_TYPE_MUC)
+ {
+ weechat_buffer_set (new_buffer, "nicklist", "1");
+ weechat_buffer_set (new_buffer, "nicklist_display_groups", "0");
+ weechat_nicklist_add_group (new_buffer, NULL, JABBER_BUDDY_GROUP_OP,
+ "weechat.color.nicklist_group", 1);
+ weechat_nicklist_add_group (new_buffer, NULL, JABBER_BUDDY_GROUP_HALFOP,
+ "weechat.color.nicklist_group", 1);
+ weechat_nicklist_add_group (new_buffer, NULL, JABBER_BUDDY_GROUP_VOICE,
+ "weechat.color.nicklist_group", 1);
+ weechat_nicklist_add_group (new_buffer, NULL, JABBER_BUDDY_GROUP_CHANUSER,
+ "weechat.color.nicklist_group", 1);
+ weechat_nicklist_add_group (new_buffer, NULL, JABBER_BUDDY_GROUP_NORMAL,
+ "weechat.color.nicklist_group", 1);
+ }
+
+ /* set highlights settings on MUC buffer */
+ weechat_buffer_set (new_buffer, "highlight_words",
+ jabber_server_get_local_name (server));
+ if (weechat_config_string (jabber_config_look_highlight_tags)
+ && weechat_config_string (jabber_config_look_highlight_tags)[0])
+ {
+ weechat_buffer_set (new_buffer, "highlight_tags",
+ weechat_config_string (jabber_config_look_highlight_tags));
+ }
+
+ /* initialize new MUC */
+ new_muc->type = muc_type;
+ new_muc->name = strdup (muc_name);
+ new_muc->topic = NULL;
+ new_muc->modes = NULL;
+ new_muc->limit = 0;
+ new_muc->key = NULL;
+ new_muc->away_message = NULL;
+ new_muc->nick_completion_reset = 0;
+ new_muc->buddies_count = 0;
+ new_muc->buddies = NULL;
+ new_muc->last_buddy = NULL;
+ new_muc->buddies_speaking[0] = NULL;
+ new_muc->buddies_speaking[1] = NULL;
+ new_muc->buddies_speaking_time = NULL;
+ new_muc->last_buddy_speaking_time = NULL;
+ new_muc->buffer = new_buffer;
+ new_muc->buffer_as_string = NULL;
+
+ /* add new MUC to MUCs list */
+ new_muc->prev_muc = server->last_muc;
+ new_muc->next_muc = NULL;
+ if (server->mucs)
+ (server->last_muc)->next_muc = new_muc;
+ else
+ server->mucs = new_muc;
+ server->last_muc = new_muc;
+
+ if (switch_to_muc)
+ weechat_buffer_set (new_buffer, "display", "1");
+
+ /* all is ok, return address of new muc */
+ return new_muc;
+}
+
+/*
+ * jabber_muc_set_topic: set topic for a muc
+ */
+
+void
+jabber_muc_set_topic (struct t_jabber_muc *muc, const char *topic)
+{
+ if (muc->topic)
+ free (muc->topic);
+
+ muc->topic = (topic) ? strdup (topic) : NULL;
+ weechat_buffer_set (muc->buffer, "title", muc->topic);
+}
+
+/*
+ * jabber_muc_search: returns pointer on a muc with name
+ */
+
+struct t_jabber_muc *
+jabber_muc_search (struct t_jabber_server *server, const char *muc_name)
+{
+ struct t_jabber_muc *ptr_muc;
+
+ if (!server || !muc_name)
+ return NULL;
+
+ for (ptr_muc = server->mucs; ptr_muc;
+ ptr_muc = ptr_muc->next_muc)
+ {
+ if (weechat_strcasecmp (ptr_muc->name, muc_name) == 0)
+ return ptr_muc;
+ }
+ return NULL;
+}
+
+/*
+ * jabber_muc_remove_away: remove away for all buddies in a MUC
+ */
+
+void
+jabber_muc_remove_away (struct t_jabber_muc *muc)
+{
+ struct t_jabber_buddy *ptr_buddy;
+
+ if (muc->type == JABBER_MUC_TYPE_MUC)
+ {
+ for (ptr_buddy = muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ jabber_buddy_set (NULL, muc, ptr_buddy, 0, JABBER_BUDDY_AWAY);
+ }
+ }
+}
+
+/*
+ * jabber_muc_set_away: set/unset away status for a MUC
+ */
+
+void
+jabber_muc_set_away (struct t_jabber_muc *muc, const char *buddy_name,
+ int is_away)
+{
+ struct t_jabber_buddy *ptr_buddy;
+
+ if (muc->type == JABBER_MUC_TYPE_MUC)
+ {
+ ptr_buddy = jabber_buddy_search (NULL, muc, buddy_name);
+ if (ptr_buddy)
+ jabber_buddy_set_away (NULL, muc, ptr_buddy, is_away);
+ }
+}
+
+/*
+ * jabber_muc_buddy_speaking_add: add a buddy speaking in a MUC
+ */
+
+void
+jabber_muc_buddy_speaking_add (struct t_jabber_muc *muc, const char *buddy_name,
+ int highlight)
+{
+ int size, to_remove, i;
+
+ if (highlight < 0)
+ highlight = 0;
+ if (highlight > 1)
+ highlight = 1;
+
+ if (!muc->buddies_speaking[highlight])
+ muc->buddies_speaking[highlight] = weechat_list_new ();
+
+ weechat_list_add (muc->buddies_speaking[highlight], buddy_name,
+ WEECHAT_LIST_POS_END);
+
+ size = weechat_list_size (muc->buddies_speaking[highlight]);
+ if (size > JABBER_MUC_BUDDIES_SPEAKING_LIMIT)
+ {
+ to_remove = size - JABBER_MUC_BUDDIES_SPEAKING_LIMIT;
+ for (i = 0; i < to_remove; i++)
+ {
+ weechat_list_remove (muc->buddies_speaking[highlight],
+ weechat_list_get (muc->buddies_speaking[highlight], 0));
+ }
+ }
+}
+
+/*
+ * jabber_muc_buddy_speaking_rename: rename a buddy speaking in a MUC
+ */
+
+void
+jabber_muc_buddy_speaking_rename (struct t_jabber_muc *muc,
+ const char *old_nick,
+ const char *new_nick)
+{
+ struct t_weelist_item *ptr_item;
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (muc->buddies_speaking[i])
+ {
+ ptr_item = weechat_list_search (muc->buddies_speaking[i], old_nick);
+ if (ptr_item)
+ weechat_list_set (ptr_item, new_nick);
+ }
+ }
+}
+
+/*
+ * jabber_muc_buddy_speaking_time_search: search a buddy speaking time in a MUC
+ */
+
+struct t_jabber_muc_speaking *
+jabber_muc_buddy_speaking_time_search (struct t_jabber_muc *muc,
+ const char *buddy_name,
+ int check_time)
+{
+ struct t_jabber_muc_speaking *ptr_buddy;
+ time_t time_limit;
+
+ time_limit = time (NULL) -
+ (weechat_config_integer (jabber_config_look_smart_filter_delay) * 60);
+
+ for (ptr_buddy = muc->buddies_speaking_time; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ if (strcmp (ptr_buddy->buddy, buddy_name) == 0)
+ {
+ if (check_time && (ptr_buddy->time_last_message < time_limit))
+ return NULL;
+ return ptr_buddy;
+ }
+ }
+
+ /* buddy speaking time not found */
+ return NULL;
+}
+
+/*
+ * jabber_muc_buddy_speaking_time_free: free a buddy speaking in a MUC
+ */
+
+void
+jabber_muc_buddy_speaking_time_free (struct t_jabber_muc *muc,
+ struct t_jabber_muc_speaking *buddy_speaking)
+{
+ /* free data */
+ if (buddy_speaking->buddy)
+ free (buddy_speaking->buddy);
+
+ /* remove buddy from list */
+ if (buddy_speaking->prev_buddy)
+ (buddy_speaking->prev_buddy)->next_buddy = buddy_speaking->next_buddy;
+ if (buddy_speaking->next_buddy)
+ (buddy_speaking->next_buddy)->prev_buddy = buddy_speaking->prev_buddy;
+ if (muc->buddies_speaking_time == buddy_speaking)
+ muc->buddies_speaking_time = buddy_speaking->next_buddy;
+ if (muc->last_buddy_speaking_time == buddy_speaking)
+ muc->last_buddy_speaking_time = buddy_speaking->prev_buddy;
+
+ free (buddy_speaking);
+}
+
+/*
+ * jabber_muc_buddy_speaking_time_free_all: free all buddies speaking in a MUC
+ */
+
+void
+jabber_muc_buddy_speaking_time_free_all (struct t_jabber_muc *muc)
+{
+ while (muc->buddies_speaking_time)
+ {
+ jabber_muc_buddy_speaking_time_free (muc,
+ muc->buddies_speaking_time);
+ }
+}
+
+/*
+ * jabber_muc_buddy_speaking_time_remove_old: remove old buddies speaking
+ */
+
+void
+jabber_muc_buddy_speaking_time_remove_old (struct t_jabber_muc *muc)
+{
+ time_t time_limit;
+
+ time_limit = time (NULL) -
+ (weechat_config_integer (jabber_config_look_smart_filter_delay) * 60);
+
+ while (muc->last_buddy_speaking_time)
+ {
+ if (muc->last_buddy_speaking_time->time_last_message >= time_limit)
+ break;
+
+ jabber_muc_buddy_speaking_time_free (muc,
+ muc->last_buddy_speaking_time);
+ }
+}
+
+/*
+ * jabber_muc_buddy_speaking_time_add: add a buddy speaking time in a MUC
+ */
+
+void
+jabber_muc_buddy_speaking_time_add (struct t_jabber_muc *muc,
+ const char *buddy_name,
+ time_t time_last_message)
+{
+ struct t_jabber_muc_speaking *ptr_buddy, *new_buddy;
+
+ ptr_buddy = jabber_muc_buddy_speaking_time_search (muc, buddy_name, 0);
+ if (ptr_buddy)
+ jabber_muc_buddy_speaking_time_free (muc, ptr_buddy);
+
+ new_buddy = malloc (sizeof (*new_buddy));
+ if (new_buddy)
+ {
+ new_buddy->buddy = strdup (buddy_name);
+ new_buddy->time_last_message = time_last_message;
+
+ /* insert buddy at beginning of list */
+ new_buddy->prev_buddy = NULL;
+ new_buddy->next_buddy = muc->buddies_speaking_time;
+ if (muc->buddies_speaking_time)
+ muc->buddies_speaking_time->prev_buddy = new_buddy;
+ else
+ muc->last_buddy_speaking_time = new_buddy;
+ muc->buddies_speaking_time = new_buddy;
+ }
+}
+
+/*
+ * jabber_muc_buddy_speaking_time_rename: rename a buddy speaking time in a MUC
+ */
+
+void
+jabber_muc_buddy_speaking_time_rename (struct t_jabber_muc *muc,
+ const char *old_buddy,
+ const char *new_buddy)
+{
+ struct t_jabber_muc_speaking *ptr_buddy;
+
+ if (muc->buddies_speaking_time)
+ {
+ ptr_buddy = jabber_muc_buddy_speaking_time_search (muc, old_buddy, 0);
+ if (ptr_buddy)
+ {
+ free (ptr_buddy->buddy);
+ ptr_buddy->buddy = strdup (new_buddy);
+ }
+ }
+}
+
+/*
+ * jabber_muc_free: free a muc and remove it from MUCs list
+ */
+
+void
+jabber_muc_free (struct t_jabber_server *server, struct t_jabber_muc *muc)
+{
+ struct t_jabber_muc *new_mucs;
+
+ if (!server || !muc)
+ return;
+
+ /* remove muc from MUCs list */
+ if (server->last_muc == muc)
+ server->last_muc = muc->prev_muc;
+ if (muc->prev_muc)
+ {
+ (muc->prev_muc)->next_muc = muc->next_muc;
+ new_mucs = server->mucs;
+ }
+ else
+ new_mucs = muc->next_muc;
+
+ if (muc->next_muc)
+ (muc->next_muc)->prev_muc = muc->prev_muc;
+
+ /* free data */
+ if (muc->name)
+ free (muc->name);
+ if (muc->topic)
+ free (muc->topic);
+ if (muc->modes)
+ free (muc->modes);
+ if (muc->key)
+ free (muc->key);
+ jabber_buddy_free_all (NULL, muc);
+ if (muc->away_message)
+ free (muc->away_message);
+ if (muc->buddies_speaking[0])
+ weechat_list_free (muc->buddies_speaking[0]);
+ if (muc->buddies_speaking[1])
+ weechat_list_free (muc->buddies_speaking[1]);
+ jabber_muc_buddy_speaking_time_free_all (muc);
+ if (muc->buffer_as_string)
+ free (muc->buffer_as_string);
+
+ free (muc);
+
+ server->mucs = new_mucs;
+}
+
+/*
+ * jabber_muc_free_all: free all allocated MUCs for a server
+ */
+
+void
+jabber_muc_free_all (struct t_jabber_server *server)
+{
+ while (server->mucs)
+ {
+ jabber_muc_free (server, server->mucs);
+ }
+}
+
+/*
+ * jabber_muc_add_to_infolist: add a muc in an infolist
+ * return 1 if ok, 0 if error
+ */
+
+int
+jabber_muc_add_to_infolist (struct t_infolist *infolist,
+ struct t_jabber_muc *muc)
+{
+ struct t_infolist_item *ptr_item;
+ struct t_weelist_item *ptr_list_item;
+ struct t_jabber_muc_speaking *ptr_buddy;
+ char option_name[64];
+ int i, index;
+
+ if (!infolist || !muc)
+ return 0;
+
+ ptr_item = weechat_infolist_new_item (infolist);
+ if (!ptr_item)
+ return 0;
+
+ if (!weechat_infolist_new_var_pointer (ptr_item, "buffer", muc->buffer))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "buffer_name",
+ (muc->buffer) ?
+ weechat_buffer_get_string (muc->buffer, "name") : ""))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "buffer_short_name",
+ (muc->buffer) ?
+ weechat_buffer_get_string (muc->buffer, "short_name") : ""))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "type", muc->type))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "name", muc->name))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "topic", muc->topic))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "modes", muc->modes))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "limit", muc->limit))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "key", muc->key))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "buddies_count", muc->buddies_count))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "away_message", muc->away_message))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "nick_completion_reset", muc->nick_completion_reset))
+ return 0;
+ for (i = 0; i < 2; i++)
+ {
+ if (muc->buddies_speaking[i])
+ {
+ index = 0;
+ for (ptr_list_item = weechat_list_get (muc->buddies_speaking[i], 0);
+ ptr_list_item;
+ ptr_list_item = weechat_list_next (ptr_list_item))
+ {
+ snprintf (option_name, sizeof (option_name),
+ "buddy_speaking%d_%05d", i, index);
+ if (!weechat_infolist_new_var_string (ptr_item, option_name,
+ weechat_list_string (ptr_list_item)))
+ return 0;
+ index++;
+ }
+ }
+ }
+ if (muc->buddies_speaking_time)
+ {
+ i = 0;
+ for (ptr_buddy = muc->last_buddy_speaking_time; ptr_buddy;
+ ptr_buddy = ptr_buddy->prev_buddy)
+ {
+ snprintf (option_name, sizeof (option_name),
+ "buddy_speaking_time_buddy_%05d", i);
+ if (!weechat_infolist_new_var_string (ptr_item, option_name,
+ ptr_buddy->buddy))
+ return 0;
+ snprintf (option_name, sizeof (option_name),
+ "buddy_speaking_time_time_%05d", i);
+ if (!weechat_infolist_new_var_time (ptr_item, option_name,
+ ptr_buddy->time_last_message))
+ return 0;
+ i++;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * jabber_muc_print_log: print muc infos in log (usually for crash dump)
+ */
+
+void
+jabber_muc_print_log (struct t_jabber_muc *muc)
+{
+ struct t_weelist_item *ptr_item;
+ struct t_jabber_muc_speaking *ptr_buddy_speaking;
+ int i, index;
+ struct t_jabber_buddy *ptr_buddy;
+
+ weechat_log_printf ("");
+ weechat_log_printf (" => muc %s (addr:0x%lx)]", muc->name, muc);
+ weechat_log_printf (" type . . . . . . . . . . : %d", muc->type);
+ weechat_log_printf (" topic. . . . . . . . . . : '%s'", muc->topic);
+ weechat_log_printf (" modes. . . . . . . . . . : '%s'", muc->modes);
+ weechat_log_printf (" limit. . . . . . . . . . : %d", muc->limit);
+ weechat_log_printf (" key. . . . . . . . . . . : '%s'", muc->key);
+ weechat_log_printf (" away_message . . . . . . : '%s'", muc->away_message);
+ weechat_log_printf (" nick_completion_reset. . : %d", muc->nick_completion_reset);
+ weechat_log_printf (" buddies_count. . . . . . : %d", muc->buddies_count);
+ weechat_log_printf (" buddies. . . . . . . . . : 0x%lx", muc->buddies);
+ weechat_log_printf (" last_buddy . . . . . . . : 0x%lx", muc->last_buddy);
+ weechat_log_printf (" buddies_speaking[0]. . . : 0x%lx", muc->buddies_speaking[0]);
+ weechat_log_printf (" buddies_speaking[1]. . . : 0x%lx", muc->buddies_speaking[1]);
+ weechat_log_printf (" buddies_speaking_time. . : 0x%lx", muc->buddies_speaking_time);
+ weechat_log_printf (" last_buddy_speaking_time.: 0x%lx", muc->last_buddy_speaking_time);
+ weechat_log_printf (" buffer . . . . . . . . . : 0x%lx", muc->buffer);
+ weechat_log_printf (" buffer_as_string . . . . : '%s'", muc->buffer_as_string);
+ weechat_log_printf (" prev_muc . . . . . . . . : 0x%lx", muc->prev_muc);
+ weechat_log_printf (" next_muc . . . . . . . . : 0x%lx", muc->next_muc);
+ for (i = 0; i < 2; i++)
+ {
+ if (muc->buddies_speaking[i])
+ {
+ weechat_log_printf ("");
+ index = 0;
+ for (ptr_item = weechat_list_get (muc->buddies_speaking[i], 0);
+ ptr_item; ptr_item = weechat_list_next (ptr_item))
+ {
+ weechat_log_printf (" buddy speaking[%d][%d]: '%s'",
+ i, index, weechat_list_string (ptr_item));
+ index++;
+ }
+ }
+ }
+ if (muc->buddies_speaking_time)
+ {
+ weechat_log_printf ("");
+ for (ptr_buddy_speaking = muc->buddies_speaking_time;
+ ptr_buddy_speaking;
+ ptr_buddy_speaking = ptr_buddy_speaking->next_buddy)
+ {
+ weechat_log_printf (" buddy speaking time: '%s', time: %ld",
+ ptr_buddy_speaking->buddy,
+ ptr_buddy_speaking->time_last_message);
+ }
+ }
+ for (ptr_buddy = muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ jabber_buddy_print_log (ptr_buddy);
+ }
+}
diff --git a/src/plugins/jabber/jabber-muc.h b/src/plugins/jabber/jabber-muc.h
new file mode 100644
index 000000000..4d0e81604
--- /dev/null
+++ b/src/plugins/jabber/jabber-muc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_MUC_H
+#define __WEECHAT_JABBER_MUC_H 1
+
+/* MUC types */
+#define JABBER_MUC_TYPE_UNKNOWN -1
+#define JABBER_MUC_TYPE_MUC 0
+#define JABBER_MUC_TYPE_PRIVATE 1
+
+#define JABBER_MUC_BUDDIES_SPEAKING_LIMIT 128
+
+struct t_jabber_server;
+
+struct t_jabber_muc_speaking
+{
+ char *buddy; /* buddy speaking */
+ time_t time_last_message; /* time */
+ struct t_jabber_muc_speaking *prev_buddy; /* pointer to previous buddy */
+ struct t_jabber_muc_speaking *next_buddy; /* pointer to next buddy */
+};
+
+struct t_jabber_muc
+{
+ int type; /* MUC type */
+ char *name; /* name of MUC (exemple: "test") */
+ char *topic; /* topic of MUC (host for pv) */
+ char *modes; /* MUC modes */
+ int limit; /* user limit (0 is limit not set) */
+ char *key; /* MUC key (NULL if no key set) */
+ char *away_message; /* to display away only once in pv */
+ int nick_completion_reset; /* 1 for resetting nick completion */
+ /* there was some join/part on chan */
+ int buddies_count; /* # buddies in MUC (0 if pv) */
+ struct t_jabber_buddy *buddies; /* buddies in MUC */
+ struct t_jabber_buddy *last_buddy; /* last buddy in MUC */
+ struct t_weelist *buddies_speaking[2]; /* for smart completion: first */
+ /* list is buddy speaking, second is */
+ /* speaking to me (highlight) */
+ struct t_jabber_muc_speaking *buddies_speaking_time; /* for smart filter*/
+ /* of join/quit messages */
+ struct t_jabber_muc_speaking *last_buddy_speaking_time;
+ struct t_gui_buffer *buffer; /* buffer allocated for MUC */
+ char *buffer_as_string; /* used to return buffer info */
+ struct t_jabber_muc *prev_muc; /* link to previous MUC */
+ struct t_jabber_muc *next_muc; /* link to next MUC */
+};
+
+extern int jabber_muc_valid (struct t_jabber_server *server,
+ struct t_jabber_muc *muc);
+extern struct t_jabber_muc *jabber_muc_new (struct t_jabber_server *server,
+ int muc_type,
+ const char *muc_name,
+ int switch_to_muc);
+extern void jabber_muc_set_topic (struct t_jabber_muc *muc,
+ const char *topic);
+extern void jabber_muc_free (struct t_jabber_server *server,
+ struct t_jabber_muc *muc);
+extern void jabber_muc_free_all (struct t_jabber_server *server);
+extern struct t_jabber_muc *jabber_muc_search (struct t_jabber_server *server,
+ const char *muc_name);
+extern int jabber_muc_is_muc (const char *string);
+extern void jabber_muc_remove_away (struct t_jabber_muc *muc);
+extern void jabber_muc_check_away (struct t_jabber_server *server,
+ struct t_jabber_muc *muc, int force);
+extern void jabber_muc_set_away (struct t_jabber_muc *muc,
+ const char *buddy_name,
+ int is_away);
+extern void jabber_muc_buddy_speaking_add (struct t_jabber_muc *muc,
+ const char *buddy_name,
+ int highlight);
+extern void jabber_muc_buddy_speaking_rename (struct t_jabber_muc *muc,
+ const char *old_buddy,
+ const char *new_buddy);
+extern struct t_jabber_muc_speaking *jabber_muc_buddy_speaking_time_search (struct t_jabber_muc *muc,
+ const char *buddy_name,
+ int check_time);
+extern void jabber_muc_buddy_speaking_time_remove_old (struct t_jabber_muc *muc);
+extern void jabber_muc_buddy_speaking_time_add (struct t_jabber_muc *muc,
+ const char *buddy_name,
+ time_t time_last_message);
+extern void jabber_muc_buddy_speaking_time_rename (struct t_jabber_muc *muc,
+ const char *old_buddy,
+ const char *new_buddy);
+extern int jabber_muc_add_to_infolist (struct t_infolist *infolist,
+ struct t_jabber_muc *muc);
+extern void jabber_muc_print_log (struct t_jabber_muc *muc);
+
+#endif /* jabber-muc.h */
diff --git a/src/plugins/jabber/jabber-server.c b/src/plugins/jabber/jabber-server.c
new file mode 100644
index 000000000..859ce51dc
--- /dev/null
+++ b/src/plugins/jabber/jabber-server.c
@@ -0,0 +1,1987 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-server.c: connection and I/O communication with Jabber server */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#include <iksemel.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-server.h"
+#include "jabber-buddy.h"
+#include "jabber-buffer.h"
+#include "jabber-command.h"
+#include "jabber-config.h"
+#include "jabber-debug.h"
+#include "jabber-muc.h"
+#include "jabber-xmpp.h"
+
+
+struct t_jabber_server *jabber_servers = NULL;
+struct t_jabber_server *last_jabber_server = NULL;
+
+/* current server when there is one buffer for all servers */
+struct t_jabber_server *jabber_current_server = NULL;
+
+struct t_jabber_message *jabber_recv_msgq = NULL;
+struct t_jabber_message *jabber_msgq_last_msg = NULL;
+
+ikstransport jabber_iks_transport =
+{
+ .abi_version = IKS_TRANSPORT_V1,
+ .connect = NULL,
+ .send = &jabber_server_iks_transport_send,
+ .recv = &jabber_server_iks_transport_recv,
+ .close = &jabber_server_iks_transport_close,
+ .connect_async = &jabber_server_iks_transport_connect_async,
+};
+
+char *jabber_server_option_string[JABBER_SERVER_NUM_OPTIONS] =
+{ "username", "server", "proxy", "ipv6", "tls", "sasl", "resource", "password",
+ "local_alias", "autoconnect", "autoreconnect", "autoreconnect_delay",
+ "local_hostname", "command", "command_delay", "autojoin", "autorejoin"
+};
+
+char *jabber_server_option_default[JABBER_SERVER_NUM_OPTIONS] =
+{ "", "", "", "off", "off", "on", "", "", "", "off", "on", "10", "", "", "0",
+ "", "off"
+};
+
+
+/*
+ * jabber_server_valid: check if a server pointer exists
+ * return 1 if server exists
+ * 0 if server is not found
+ */
+
+int
+jabber_server_valid (struct t_jabber_server *server)
+{
+ struct t_jabber_server *ptr_server;
+
+ if (!server)
+ return 0;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server == server)
+ return 1;
+ }
+
+ /* server not found */
+ return 0;
+}
+
+/*
+ * jabber_server_search_option: search a server option name
+ * return index of option in array
+ * "jabber_server_option_string", or -1 if
+ * not found
+ */
+
+int
+jabber_server_search_option (const char *option_name)
+{
+ int i;
+
+ if (!option_name)
+ return -1;
+
+ for (i = 0; i < JABBER_SERVER_NUM_OPTIONS; i++)
+ {
+ if (weechat_strcasecmp (jabber_server_option_string[i],
+ option_name) == 0)
+ return i;
+ }
+
+ /* server option not found */
+ return -1;
+}
+
+/*
+ * jabber_server_search: return pointer on a server with a name
+ */
+
+struct t_jabber_server *
+jabber_server_search (const char *server_name)
+{
+ struct t_jabber_server *ptr_server;
+
+ if (!server_name)
+ return NULL;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (strcmp (ptr_server->name, server_name) == 0)
+ return ptr_server;
+ }
+
+ /* server not found */
+ return NULL;
+}
+
+/*
+ * jabber_server_get_muc_count: return number of MUCs for server
+ */
+
+int
+jabber_server_get_muc_count (struct t_jabber_server *server)
+{
+ int count;
+ struct t_jabber_muc *ptr_muc;
+
+ count = 0;
+ for (ptr_muc = server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ if (ptr_muc->type == JABBER_MUC_TYPE_MUC)
+ count++;
+ }
+ return count;
+}
+
+/*
+ * jabber_server_get_pv_count: return number of pv for server
+ */
+
+int
+jabber_server_get_pv_count (struct t_jabber_server *server)
+{
+ int count;
+ struct t_jabber_muc *ptr_muc;
+
+ count = 0;
+ for (ptr_muc = server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ if (ptr_muc->type == JABBER_MUC_TYPE_PRIVATE)
+ count++;
+ }
+ return count;
+}
+
+/*
+ * jabber_server_get_name_without_port: get name of server without port
+ * (ends before first '/' if found)
+ */
+
+char *
+jabber_server_get_name_without_port (const char *name)
+{
+ char *pos;
+
+ if (!name)
+ return NULL;
+
+ pos = strchr (name, '/');
+ if (pos && (pos != name))
+ return weechat_strndup (name, pos - name);
+
+ return strdup (name);
+}
+
+/*
+ * jabber_server_get_local_name: get local alias for server (if defined),
+ * otherwise return username
+ */
+
+const char *
+jabber_server_get_local_name (struct t_jabber_server *server)
+{
+ const char *local_alias;
+
+ local_alias = JABBER_SERVER_OPTION_STRING(server,
+ JABBER_SERVER_OPTION_LOCAL_ALIAS);
+ if (local_alias && local_alias[0])
+ return local_alias;
+
+ /* fallback to username */
+ return JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_USERNAME);
+}
+
+/*
+ * jabber_server_set_server: set server address
+ */
+
+void
+jabber_server_set_server (struct t_jabber_server *server,
+ const char *address)
+{
+ char *pos, *error;
+ long number;
+
+ /* free data */
+ if (server->address)
+ {
+ free (server->address);
+ server->address = NULL;
+ }
+ server->port = JABBER_SERVER_DEFAULT_PORT;
+
+ if (address && address[0])
+ {
+ pos = strchr (address, '/');
+ if (pos && (pos > address))
+ {
+ server->address = weechat_strndup (address, pos - address);
+ pos++;
+ error = NULL;
+ number = strtol (pos, &error, 10);
+ if (error && !error[0])
+ server->port = number;
+ }
+ else
+ server->address = strdup (address);
+ }
+}
+
+/*
+ * jabber_server_buffer_set_highlight_words: set highlight words for buffer
+ * with all servers
+ */
+
+void
+jabber_server_buffer_set_highlight_words (struct t_gui_buffer *buffer)
+{
+ struct t_jabber_server *ptr_server;
+ int length;
+ const char *local_name;
+ char *words;
+
+ length = 0;
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->is_connected)
+ {
+ local_name = jabber_server_get_local_name (ptr_server);
+ if (local_name && local_name[0])
+ length += strlen (local_name) + 1;
+ }
+ }
+ words = malloc (length + 1);
+ if (words)
+ {
+ words[0] = '\0';
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->is_connected)
+ {
+ local_name = jabber_server_get_local_name (ptr_server);
+ if (local_name && local_name[0])
+ {
+ if (words[0])
+ strcat (words, ",");
+ strcat (words, local_name);
+ }
+ }
+ }
+ weechat_buffer_set (buffer, "highlight_words", words);
+ free (words);
+ }
+}
+
+/*
+ * jabber_server_alloc: allocate a new server and add it to the servers queue
+ */
+
+struct t_jabber_server *
+jabber_server_alloc (const char *name)
+{
+ struct t_jabber_server *new_server;
+ int i, length;
+ char *option_name;
+
+ if (jabber_server_search (name))
+ return NULL;
+
+ /* alloc memory for new server */
+ new_server = malloc (sizeof (*new_server));
+ if (!new_server)
+ {
+ weechat_printf (NULL,
+ _("%s%s: error when allocating new server"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME);
+ return NULL;
+ }
+
+ /* add new server to queue */
+ new_server->prev_server = last_jabber_server;
+ new_server->next_server = NULL;
+ if (jabber_servers)
+ last_jabber_server->next_server = new_server;
+ else
+ jabber_servers = new_server;
+ last_jabber_server = new_server;
+
+ /* set name */
+ new_server->name = strdup (name);
+
+ /* internal vars */
+ new_server->temp_server = 0;
+ new_server->reloading_from_config = 0;
+ new_server->reloaded_from_config = 0;
+ new_server->address = NULL;
+ new_server->port = JABBER_SERVER_DEFAULT_PORT;
+ new_server->current_ip = NULL;
+ new_server->sock = -1;
+ new_server->iks_parser = NULL;
+ new_server->iks_id_string = NULL;
+ new_server->iks_id = NULL;
+ new_server->iks_server_name = NULL;
+ new_server->iks_password = NULL;
+ new_server->iks_filter = NULL;
+ new_server->iks_roster = NULL;
+ new_server->iks_features = 0;
+ new_server->iks_authorized = 0;
+ new_server->hook_connect = NULL;
+ new_server->hook_fd = NULL;
+ new_server->is_connected = 0;
+ new_server->tls_connected = 0;
+ new_server->reconnect_start = 0;
+ new_server->command_time = 0;
+ new_server->reconnect_join = 0;
+ new_server->disable_autojoin = 0;
+ new_server->is_away = 0;
+ new_server->away_message = NULL;
+ new_server->away_time = 0;
+ new_server->lag = 0;
+ new_server->lag_check_time.tv_sec = 0;
+ new_server->lag_check_time.tv_usec = 0;
+ new_server->lag_next_check = time (NULL) +
+ weechat_config_integer (jabber_config_network_lag_check);
+ new_server->buffer = NULL;
+ new_server->buffer_as_string = NULL;
+ new_server->buddies_count = 0;
+ new_server->buddies = NULL;
+ new_server->last_buddy = NULL;
+ new_server->mucs = NULL;
+ new_server->last_muc = NULL;
+
+ /* create options with null value */
+ for (i = 0; i < JABBER_SERVER_NUM_OPTIONS; i++)
+ {
+ length = strlen (new_server->name) + 1 +
+ strlen (jabber_server_option_string[i]) + 1;
+ option_name = malloc (length);
+ if (option_name)
+ {
+ snprintf (option_name, length, "%s.%s",
+ new_server->name,
+ jabber_server_option_string[i]);
+ new_server->options[i] =
+ jabber_config_server_new_option (jabber_config_file,
+ jabber_config_section_server,
+ i,
+ option_name,
+ NULL,
+ NULL,
+ 1,
+ &jabber_config_server_change_cb,
+ jabber_server_option_string[i]);
+ jabber_config_server_change_cb (jabber_server_option_string[i],
+ new_server->options[i]);
+ free (option_name);
+ }
+ }
+
+ return new_server;
+}
+
+/*
+ * jabber_server_close_connection: close server connection
+ */
+
+void
+jabber_server_close_connection (struct t_jabber_server *server)
+{
+ if (server->hook_fd)
+ {
+ weechat_unhook (server->hook_fd);
+ server->hook_fd = NULL;
+ }
+
+ if (server->hook_connect)
+ {
+ weechat_unhook (server->hook_connect);
+ server->hook_connect = NULL;
+ }
+ else
+ {
+#ifdef HAVE_GNUTLS
+ /* close TLS connection */
+ //if ((server->sock != -1) && (server->tls_connected))
+ //{
+ // if (server->tls_connected)
+ // gnutls_bye (server->gnutls_sess, GNUTLS_SHUT_WR);
+ // if (server->tls_connected)
+ // gnutls_deinit (server->gnutls_sess);
+ //}
+#endif
+ }
+ if (server->iks_parser)
+ {
+ iks_parser_delete (server->iks_parser);
+ server->iks_parser = NULL;
+ }
+ server->sock = -1;
+ if (server->iks_id_string)
+ {
+ free (server->iks_id_string);
+ server->iks_id_string = NULL;
+ }
+ server->iks_id = NULL;
+ if (server->iks_server_name)
+ {
+ free (server->iks_server_name);
+ server->iks_server_name = NULL;
+ }
+ if (server->iks_password)
+ {
+ free (server->iks_password);
+ server->iks_password = NULL;
+ }
+ if (server->iks_filter)
+ {
+ iks_filter_delete (server->iks_filter);
+ server->iks_filter = NULL;
+ }
+ server->iks_roster = NULL;
+ server->iks_features = 0;
+ server->iks_authorized = 0;
+
+ /* remove buddies */
+ jabber_buddy_free_all (server, NULL);
+
+ /* server is now disconnected */
+ server->is_connected = 0;
+ server->tls_connected = 0;
+ if (server->current_ip)
+ {
+ free (server->current_ip);
+ server->current_ip = NULL;
+ }
+}
+
+/*
+ * jabber_server_reconnect_schedule: schedule reconnect for a server
+ */
+
+void
+jabber_server_reconnect_schedule (struct t_jabber_server *server)
+{
+ int delay;
+
+ if (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTORECONNECT))
+ {
+ server->reconnect_start = time (NULL);
+ delay = JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_AUTORECONNECT_DELAY);
+ weechat_printf (server->buffer,
+ _("%s%s: reconnecting to server in %d %s"),
+ jabber_buffer_get_server_prefix (server, NULL),
+ JABBER_PLUGIN_NAME,
+ delay,
+ NG_("second", "seconds", delay));
+ }
+ else
+ server->reconnect_start = 0;
+}
+
+/*
+ * jabber_server_login: login to Jabber server
+ */
+
+void
+jabber_server_login (struct t_jabber_server *server)
+{
+ server->is_connected = 1;
+
+ iks_send_header (server->iks_parser, server->iks_server_name);
+}
+
+/*
+ * jabber_server_connect_cb: read connection status
+ */
+
+int
+jabber_server_connect_cb (void *arg_server, int status, const char *ip_address)
+{
+ struct t_jabber_server *server;
+ const char *proxy;
+
+ server = (struct t_jabber_server *)arg_server;
+
+ proxy = JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_PROXY);
+
+ server->hook_connect = NULL;
+
+ switch (status)
+ {
+ case WEECHAT_HOOK_CONNECT_OK:
+ /* login to server */
+ if (server->current_ip)
+ free (server->current_ip);
+ server->current_ip = (ip_address) ? strdup (ip_address) : NULL;
+ weechat_printf (server->buffer,
+ _("%s%s: connected to %s (%s)"),
+ jabber_buffer_get_server_prefix (server, NULL),
+ JABBER_PLUGIN_NAME,
+ server->address,
+ (server->current_ip) ? server->current_ip : "?");
+ server->hook_fd = weechat_hook_fd (server->sock,
+ 1, 0, 0,
+ &jabber_server_recv_cb,
+ server);
+ jabber_server_login (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND:
+ weechat_printf (server->buffer,
+ (proxy && proxy[0]) ?
+ _("%s%s: proxy address \"%s\" not found") :
+ _("%s%s: address \"%s\" not found"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME,
+ server->address);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND:
+ weechat_printf (server->buffer,
+ (proxy && proxy[0]) ?
+ _("%s%s: proxy IP address not found") :
+ _("%s%s: IP address not found"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED:
+ weechat_printf (server->buffer,
+ (proxy && proxy[0]) ?
+ _("%s%s: proxy connection refused") :
+ _("%s%s: connection refused"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_PROXY_ERROR:
+ weechat_printf (server->buffer,
+ _("%s%s: proxy fails to establish "
+ "connection to server "
+ "(check username/password if used "
+ "and if server address/port is allowed by "
+ "proxy)"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR:
+ weechat_printf (server->buffer,
+ _("%s%s: unable to set local hostname/IP"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR:
+ weechat_printf (server->buffer,
+ _("%s%s: GnuTLS init error"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR:
+ weechat_printf (server->buffer,
+ _("%s%s: GnuTLS handshake failed"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ case WEECHAT_HOOK_CONNECT_MEMORY_ERROR:
+ weechat_printf (server->buffer,
+ _("%s%s: not enough memory"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_close_connection (server);
+ jabber_server_reconnect_schedule (server);
+ break;
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_server_set_buffer_title: set title for a server buffer
+ */
+
+void
+jabber_server_set_buffer_title (struct t_jabber_server *server)
+{
+ char *title;
+ int length;
+
+ if (server && server->buffer)
+ {
+ if (server->is_connected)
+ {
+ length = 16 + strlen (server->address) + 16 +
+ ((server->current_ip) ? strlen (server->current_ip) : 16) + 1;
+ title = malloc (length);
+ if (title)
+ {
+ snprintf (title, length, "Jabber: %s/%d (%s)",
+ server->address, server->port,
+ (server->current_ip) ? server->current_ip : "");
+ weechat_buffer_set (server->buffer, "title", title);
+ free (title);
+ }
+ }
+ else
+ {
+ weechat_buffer_set (server->buffer, "title", "");
+ }
+ }
+}
+
+/*
+ * jabber_server_create_buffer: create a buffer for a Jabber server
+ */
+
+struct t_gui_buffer *
+jabber_server_create_buffer (struct t_jabber_server *server, int all_servers)
+{
+ char buffer_name[256], charset_modifier[256];
+ const char *local_name;
+
+ if (all_servers)
+ {
+ snprintf (buffer_name, sizeof (buffer_name),
+ JABBER_BUFFER_ALL_SERVERS_NAME);
+ }
+ else
+ {
+ snprintf (buffer_name, sizeof (buffer_name),
+ "server.%s", server->name);
+ }
+ server->buffer = weechat_buffer_new (buffer_name,
+ NULL, NULL,
+ &jabber_buffer_close_cb, NULL);
+ if (!server->buffer)
+ return NULL;
+
+ weechat_buffer_set (server->buffer, "short_name",
+ (weechat_config_boolean (jabber_config_look_one_server_buffer)) ?
+ JABBER_BUFFER_ALL_SERVERS_NAME : server->name);
+ weechat_buffer_set (server->buffer, "localvar_set_server",
+ (weechat_config_boolean (jabber_config_look_one_server_buffer)) ?
+ JABBER_BUFFER_ALL_SERVERS_NAME : server->name);
+ weechat_buffer_set (server->buffer, "localvar_set_muc",
+ (weechat_config_boolean (jabber_config_look_one_server_buffer)) ?
+ JABBER_BUFFER_ALL_SERVERS_NAME : server->name);
+ snprintf (charset_modifier, sizeof (charset_modifier),
+ "jabber.%s", server->name);
+ weechat_buffer_set (server->buffer, "localvar_set_charset_modifier",
+ charset_modifier);
+
+ weechat_buffer_set (server->buffer, "nicklist", "1");
+ weechat_buffer_set (server->buffer, "nicklist_display_groups", "0");
+
+ weechat_hook_signal_send ("logger_backlog",
+ WEECHAT_HOOK_SIGNAL_POINTER, server->buffer);
+
+ /* set highlights settings on server buffer */
+ local_name = jabber_server_get_local_name (server);
+ if (local_name && local_name[0])
+ weechat_buffer_set (server->buffer, "highlight_words", local_name);
+ if (weechat_config_string (jabber_config_look_highlight_tags)
+ && weechat_config_string (jabber_config_look_highlight_tags)[0])
+ {
+ weechat_buffer_set (server->buffer, "highlight_tags",
+ weechat_config_string (jabber_config_look_highlight_tags));
+ }
+
+ jabber_server_set_buffer_title (server);
+
+ return server->buffer;
+}
+
+/*
+ * jabber_server_set_current_server: set new current server (when all servers
+ * are in one buffer)
+ */
+
+void
+jabber_server_set_current_server (struct t_jabber_server *server)
+{
+ char charset_modifier[256];
+
+ jabber_current_server = server;
+
+ jabber_server_set_buffer_title (jabber_current_server);
+ snprintf (charset_modifier, sizeof (charset_modifier),
+ "jabber.%s", jabber_current_server->name);
+ weechat_buffer_set (jabber_current_server->buffer,
+ "localvar_set_charset_modifier",
+ charset_modifier);
+ weechat_bar_item_update ("buffer_name");
+ weechat_bar_item_update ("input_prompt");
+}
+
+/*
+ * jabber_server_iks_transport_connect_async: async connection to server
+ * (for iksemel lib)
+ */
+
+int
+jabber_server_iks_transport_connect_async (iksparser *parser, void **socketptr,
+ const char *server,
+ const char *server_name,
+ int port, void *notify_data,
+ iksAsyncNotify *notify_func)
+{
+ struct t_jabber_server *ptr_server;
+ int set, length;
+ char *option_name;
+ struct t_config_option *proxy_type, *proxy_ipv6, *proxy_address, *proxy_port;
+ const char *proxy, *str_proxy_type, *str_proxy_address;
+
+ /* make C compiler happy */
+ (void) parser;
+ (void) server_name;
+ (void) notify_func;
+
+ ptr_server = (struct t_jabber_server *)notify_data;
+
+ proxy_type = NULL;
+ proxy_ipv6 = NULL;
+ proxy_address = NULL;
+ proxy_port = NULL;
+ str_proxy_type = NULL;
+ str_proxy_address = NULL;
+
+ proxy = JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_PROXY);
+ if (proxy && proxy[0])
+ {
+ length = 32 + strlen (proxy) + 1;
+ option_name = malloc (length);
+ if (!option_name)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: not enough memory"),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME);
+ return 0;
+ }
+ snprintf (option_name, length, "weechat.proxy.%s.type", proxy);
+ proxy_type = weechat_config_get (option_name);
+ snprintf (option_name, length, "weechat.proxy.%s.ipv6", proxy);
+ proxy_ipv6 = weechat_config_get (option_name);
+ snprintf (option_name, length, "weechat.proxy.%s.address", proxy);
+ proxy_address = weechat_config_get (option_name);
+ snprintf (option_name, length, "weechat.proxy.%s.port", proxy);
+ proxy_port = weechat_config_get (option_name);
+ free (option_name);
+ if (!proxy_type || !proxy_address)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: proxy \"%s\" not found for server "
+ "\"%s\", cannot connect"),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME, proxy, ptr_server->name);
+ return 0;
+ }
+ str_proxy_type = weechat_config_string (proxy_type);
+ str_proxy_address = weechat_config_string (proxy_address);
+ if (!str_proxy_type[0] || !proxy_ipv6 || !str_proxy_address[0]
+ || !proxy_port)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: missing proxy settings, check options "
+ "for proxy \"%s\""),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME, proxy);
+ return 0;
+ }
+ }
+
+ if (proxy_type)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: connecting to server %s/%d%s%s%s via %s "
+ "proxy %s/%d%s..."),
+ jabber_buffer_get_server_prefix (ptr_server, NULL),
+ JABBER_PLUGIN_NAME,
+ server,
+ port,
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6)) ?
+ " (IPv6)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_TLS)) ?
+ " (TLS)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_SASL)) ?
+ " (SASL)" : "",
+ str_proxy_type,
+ str_proxy_address,
+ weechat_config_integer (proxy_port),
+ (weechat_config_boolean (proxy_ipv6)) ? " (IPv6)" : "");
+ weechat_log_printf (_("Connecting to server %s/%d%s%s%s via %s proxy "
+ "%s/%d%s..."),
+ server,
+ port,
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6)) ?
+ " (IPv6)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_TLS)) ?
+ " (TLS)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_SASL)) ?
+ " (SASL)" : "",
+ str_proxy_type,
+ str_proxy_address,
+ weechat_config_integer (proxy_port),
+ (weechat_config_boolean (proxy_ipv6)) ? " (IPv6)" : "");
+ }
+ else
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: connecting to server %s/%d%s%s%s..."),
+ jabber_buffer_get_server_prefix (ptr_server, NULL),
+ JABBER_PLUGIN_NAME,
+ server,
+ port,
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6)) ?
+ " (IPv6)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_TLS)) ?
+ " (TLS)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_SASL)) ?
+ " (SASL)" : "");
+ weechat_log_printf (_("%s%s: connecting to server %s/%d%s%s%s..."),
+ "",
+ JABBER_PLUGIN_NAME,
+ server,
+ port,
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6)) ?
+ " (IPv6)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_TLS)) ?
+ " (TLS)" : "",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_SASL)) ?
+ " (SASL)" : "");
+ }
+
+ /* create socket and set options */
+ if (proxy_type)
+ {
+ ptr_server->sock = socket ((weechat_config_integer (proxy_ipv6)) ?
+ AF_INET6 : AF_INET,
+ SOCK_STREAM, 0);
+ }
+ else
+ {
+ ptr_server->sock = socket ((JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6)) ?
+ AF_INET6 : AF_INET,
+ SOCK_STREAM, 0);
+ }
+ if (ptr_server->sock == -1)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: cannot create socket"),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME);
+ return 0;
+ }
+
+ /* set SO_REUSEADDR option for socket */
+ set = 1;
+ if (setsockopt (ptr_server->sock, SOL_SOCKET, SO_REUSEADDR,
+ (void *) &set, sizeof (set)) == -1)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: cannot set socket option "
+ "\"SO_REUSEADDR\""),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME);
+ }
+
+ /* set SO_KEEPALIVE option for socket */
+ set = 1;
+ if (setsockopt (ptr_server->sock, SOL_SOCKET, SO_KEEPALIVE,
+ (void *) &set, sizeof (set)) == -1)
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: cannot set socket option "
+ "\"SO_KEEPALIVE\""),
+ jabber_buffer_get_server_prefix (ptr_server, "error"),
+ JABBER_PLUGIN_NAME);
+ }
+
+ *socketptr = (void *) ptr_server->sock;
+
+ /* init TLS if asked */
+ ptr_server->tls_connected = 0;
+#ifdef HAVE_GNUTLS
+ if (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_TLS))
+ ptr_server->tls_connected = 1;
+#endif
+
+ ptr_server->hook_connect = weechat_hook_connect (proxy,
+ server,
+ port,
+ ptr_server->sock,
+ JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6),
+#ifdef HAVE_GNUTLS
+ //(ptr_server->tls_connected) ? &ptr_server->gnutls_sess : NULL,
+ NULL,
+#else
+ NULL,
+#endif
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_LOCAL_HOSTNAME),
+ &jabber_server_connect_cb,
+ ptr_server);
+
+ /* send signal "jabber_server_connecting" with server name */
+ weechat_hook_signal_send ("jabber_server_connecting",
+ WEECHAT_HOOK_SIGNAL_STRING, ptr_server->name);
+
+ return IKS_OK;
+}
+
+/*
+ * jabber_server_iks_transport_send: send data to server (for iksemel lib)
+ */
+
+int
+jabber_server_iks_transport_send (void *socket, const char *data, size_t len)
+{
+ if (send ((int) socket, data, len, 0) == -1)
+ return IKS_NET_RWERR;
+
+ return IKS_OK;
+}
+
+/*
+ * jabber_server_iks_transport_recv: recv data from server (for iksemel lib)
+ */
+
+int
+jabber_server_iks_transport_recv (void *socket, char *buffer, size_t buf_len,
+ int timeout)
+{
+ int sock;
+ fd_set fds;
+ struct timeval tv;
+ int len;
+
+ /* make C compiler happy */
+ (void) timeout;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ sock = (int) socket;
+ FD_ZERO (&fds);
+ FD_SET (sock, &fds);
+ if (select (sock + 1, &fds, NULL, NULL, &tv) > 0)
+ {
+ len = recv (sock, buffer, buf_len, 0);
+ if (len > 0)
+ return len;
+ else if (len <= 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * jabber_server_iks_transport_close: close connection with server
+ * (for iksemel lib)
+ */
+
+void
+jabber_server_iks_transport_close (void *socket)
+{
+ int sock = (int)socket;
+
+#ifdef _WIN32
+ closesocket (sock);
+#else
+ close (sock);
+#endif
+}
+
+/*
+ * jabber_server_connect: connect to a Jabber server
+ * Return: 1 if ok
+ * 0 if error
+ */
+
+int
+jabber_server_connect (struct t_jabber_server *server)
+{
+ int length;
+ char charset_modifier[256];
+ const char *username, *resource, *password;
+
+ username = JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_USERNAME);
+ resource = JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_RESOURCE);
+ if (!username || !username[0] || !server->address || !server->address[0])
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: username or server not defined for server "
+ "\"%s\", cannot connect"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME, server->name);
+ return 0;
+ }
+
+ if (!server->buffer)
+ {
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer)
+ && jabber_buffer_servers)
+ {
+ server->buffer = jabber_buffer_servers;
+ jabber_server_set_buffer_title (server);
+ }
+ else
+ {
+ if (!jabber_server_create_buffer (server,
+ weechat_config_boolean (jabber_config_look_one_server_buffer)))
+ return 0;
+ }
+
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer))
+ {
+ jabber_current_server = server;
+ if (!jabber_buffer_servers)
+ jabber_buffer_servers = server->buffer;
+
+ snprintf (charset_modifier, sizeof (charset_modifier),
+ "jabber.%s", jabber_current_server->name);
+ weechat_buffer_set (jabber_buffer_servers,
+ "localvar_set_charset_modifier",
+ charset_modifier);
+ }
+
+ weechat_buffer_set (server->buffer, "display", "1");
+
+ weechat_bar_item_update ("buffer_name");
+
+ weechat_buffer_set (server->buffer, "key_bind_meta-s",
+ "/command jabber /jabber switch");
+ }
+
+ if (!server->address)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: hostname/IP not defined for server \"%s\", "
+ "cannot connect"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME, server->name);
+ return 0;
+ }
+
+#ifndef HAVE_GNUTLS
+ //if (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_TLS))
+ //{
+ // weechat_printf (server->buffer,
+ // _("%s%s: cannot connect with TLS because WeeChat "
+ // "was not built with GnuTLS support"),
+ // jabber_buffer_get_server_prefix (server, "error"),
+ // JABBER_PLUGIN_NAME);
+ // return 0;
+ //}
+#endif
+
+ if (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_TLS)
+ && !iks_has_tls ())
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: cannot connect with TLS because iksemel "
+ "library was not built with GnuTLS support"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ return 0;
+ }
+
+ /* close connection if opened */
+ jabber_server_close_connection (server);
+
+ /* build jabber ID */
+ length = strlen (username) + 1 + strlen (server->address) + 1 +
+ strlen ((resource && resource[0]) ? resource : JABBER_SERVER_DEFAULT_RESOURCE) + 1;
+ server->iks_id_string = malloc (length);
+ if (!server->iks_id_string)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: not enough memory"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ return 0;
+ }
+ snprintf (server->iks_id_string, length, "%s@%s/%s",
+ username, server->address,
+ (resource && resource[0]) ?
+ resource : JABBER_SERVER_DEFAULT_RESOURCE);
+ server->iks_parser = iks_stream_new (IKS_NS_CLIENT, server,
+ &jabber_xmpp_iks_stream_hook);
+ if (!server->iks_parser)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: failed to create stream parser"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ return 0;
+ }
+ server->iks_id = iks_id_new (iks_parser_stack (server->iks_parser),
+ server->iks_id_string);
+ if (!server->iks_id)
+ {
+ iks_parser_delete (server->iks_parser);
+ server->iks_parser = NULL;
+ free (server->iks_id_string);
+ server->iks_id_string = NULL;
+ weechat_printf (server->buffer,
+ _("%s%s: failed to create id"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+ return 0;
+ }
+ server->iks_server_name = strdup (server->address);
+ password = JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_PASSWORD);
+ server->iks_password = strdup ((password) ? password : "");
+ iks_set_log_hook (server->iks_parser, &jabber_xmpp_iks_log);
+ server->iks_filter = iks_filter_new ();
+ iks_filter_add_rule (server->iks_filter,
+ &jabber_xmpp_iks_result, server,
+ IKS_RULE_TYPE, IKS_PAK_IQ,
+ IKS_RULE_SUBTYPE, IKS_TYPE_RESULT,
+ IKS_RULE_ID, "auth",
+ IKS_RULE_DONE);
+ iks_filter_add_rule (server->iks_filter,
+ &jabber_xmpp_iks_error, server,
+ IKS_RULE_TYPE, IKS_PAK_IQ,
+ IKS_RULE_SUBTYPE, IKS_TYPE_ERROR,
+ IKS_RULE_ID, "auth",
+ IKS_RULE_DONE);
+ iks_filter_add_rule (server->iks_filter,
+ &jabber_xmpp_iks_roster, server,
+ IKS_RULE_TYPE, IKS_PAK_IQ,
+ IKS_RULE_SUBTYPE, IKS_TYPE_RESULT,
+ IKS_RULE_ID, "roster",
+ IKS_RULE_DONE);
+ iks_connect_async_with (server->iks_parser, server->address, server->port,
+ server->iks_server_name, &jabber_iks_transport,
+ server, NULL);
+
+ return 1;
+}
+
+/*
+ * jabber_server_reconnect: reconnect to a server (after disconnection)
+ */
+
+void
+jabber_server_reconnect (struct t_jabber_server *server)
+{
+ weechat_printf (server->buffer,
+ _("%s%s: reconnecting to server..."),
+ jabber_buffer_get_server_prefix (server, NULL),
+ JABBER_PLUGIN_NAME);
+ server->reconnect_start = 0;
+
+ if (jabber_server_connect (server))
+ server->reconnect_join = 1;
+ else
+ jabber_server_reconnect_schedule (server);
+}
+
+/*
+ * jabber_server_auto_connect: auto-connect to servers (called at startup)
+ */
+
+void
+jabber_server_auto_connect ()
+{
+ struct t_jabber_server *ptr_server;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_AUTOCONNECT))
+ {
+ if (!jabber_server_connect (ptr_server))
+ jabber_server_reconnect_schedule (ptr_server);
+ }
+ }
+}
+
+/*
+ * jabber_server_disconnect: disconnect from a Jabber server
+ */
+
+void
+jabber_server_disconnect (struct t_jabber_server *server, int reconnect)
+{
+ struct t_jabber_muc *ptr_muc;
+
+ if (server->is_connected)
+ {
+ /* remove all buddies and write disconnection message on each
+ MUC/private buffer */
+ for (ptr_muc = server->mucs; ptr_muc; ptr_muc = ptr_muc->next_muc)
+ {
+ jabber_buddy_free_all (NULL, ptr_muc);
+ weechat_printf (ptr_muc->buffer,
+ _("%s%s: disconnected from server"),
+ "",
+ JABBER_PLUGIN_NAME);
+ }
+ }
+
+ jabber_server_close_connection (server);
+
+ if (server->buffer)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: disconnected from server"),
+ jabber_buffer_get_server_prefix (server, NULL),
+ JABBER_PLUGIN_NAME);
+ }
+
+ server->is_away = 0;
+ server->away_time = 0;
+ server->lag = 0;
+ server->lag_check_time.tv_sec = 0;
+ server->lag_check_time.tv_usec = 0;
+ server->lag_next_check = time (NULL) +
+ weechat_config_integer (jabber_config_network_lag_check);
+
+ if (reconnect
+ && JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTORECONNECT))
+ jabber_server_reconnect_schedule (server);
+ else
+ server->reconnect_start = 0;
+
+ jabber_server_set_buffer_title (server);
+
+ /* send signal "jabber_server_disconnected" with server name */
+ weechat_hook_signal_send ("jabber_server_disconnected",
+ WEECHAT_HOOK_SIGNAL_STRING, server->name);
+}
+
+/*
+ * jabber_server_disconnect_all: disconnect from all jabber servers
+ */
+
+void
+jabber_server_disconnect_all ()
+{
+ struct t_jabber_server *ptr_server;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ jabber_server_disconnect (ptr_server, 0);
+ }
+}
+
+/*
+ * jabber_server_free_data: free server data
+ */
+
+void
+jabber_server_free_data (struct t_jabber_server *server)
+{
+ int i;
+
+ if (!server)
+ return;
+
+ /* free data */
+ for (i = 0; i < JABBER_SERVER_NUM_OPTIONS; i++)
+ {
+ if (server->options[i])
+ weechat_config_option_free (server->options[i]);
+ }
+ if (server->address)
+ free (server->address);
+ if (server->current_ip)
+ free (server->current_ip);
+ if (server->iks_parser)
+ iks_parser_delete (server->iks_parser);
+ if (server->iks_id_string)
+ free (server->iks_id_string);
+ if (server->iks_server_name)
+ free (server->iks_server_name);
+ if (server->iks_password)
+ free (server->iks_password);
+ if (server->iks_filter)
+ iks_filter_delete (server->iks_filter);
+ if (server->away_message)
+ free (server->away_message);
+ if (server->mucs)
+ jabber_muc_free_all (server);
+ if (server->buddies)
+ jabber_buddy_free_all (server, NULL);
+ if (server->buffer_as_string)
+ free (server->buffer_as_string);
+}
+
+/*
+ * jabber_server_free: free a server and remove it from servers queue
+ */
+
+void
+jabber_server_free (struct t_jabber_server *server)
+{
+ struct t_jabber_server *new_jabber_servers;
+
+ if (!server)
+ return;
+
+ /* close all MUCs/privates */
+ jabber_muc_free_all (server);
+
+ /* remove server from queue */
+ if (last_jabber_server == server)
+ last_jabber_server = server->prev_server;
+ if (server->prev_server)
+ {
+ (server->prev_server)->next_server = server->next_server;
+ new_jabber_servers = jabber_servers;
+ }
+ else
+ new_jabber_servers = server->next_server;
+
+ if (server->next_server)
+ (server->next_server)->prev_server = server->prev_server;
+
+ jabber_server_free_data (server);
+ free (server);
+ jabber_servers = new_jabber_servers;
+}
+
+/*
+ * jabber_server_free_all: free all allocated servers
+ */
+
+void
+jabber_server_free_all ()
+{
+ /* for each server in memory, remove it */
+ while (jabber_servers)
+ {
+ jabber_server_free (jabber_servers);
+ }
+}
+
+/*
+ * jabber_server_copy: copy a server
+ * return: pointer to new server, NULL if error
+ */
+
+struct t_jabber_server *
+jabber_server_copy (struct t_jabber_server *server, const char *new_name)
+{
+ struct t_jabber_server *new_server;
+ struct t_infolist *infolist;
+ char *mask, *pos;
+ const char *option_name;
+ int length, index_option;
+
+ /* check if another server exists with this name */
+ if (jabber_server_search (new_name))
+ return NULL;
+
+ new_server = jabber_server_alloc (new_name);
+ if (new_server)
+ {
+ /* duplicate options */
+ length = 32 + strlen (server->name) + 1;
+ mask = malloc (length);
+ if (!mask)
+ return 0;
+ snprintf (mask, length, "jabber.server.%s.*", server->name);
+ infolist = weechat_infolist_get ("option", NULL, mask);
+ free (mask);
+ while (weechat_infolist_next (infolist))
+ {
+ if (!weechat_infolist_integer (infolist, "value_is_null"))
+ {
+ option_name = weechat_infolist_string (infolist, "option_name");
+ pos = strrchr (option_name, '.');
+ if (pos)
+ {
+ index_option = jabber_server_search_option (pos + 1);
+ if (index_option >= 0)
+ {
+ weechat_config_option_set (new_server->options[index_option],
+ weechat_infolist_string (infolist, "value"),
+ 1);
+ }
+ }
+ }
+ }
+ }
+
+ return new_server;
+}
+
+/*
+ * jabber_server_rename: rename server (internal name)
+ * return: 1 if ok, 0 if error
+ */
+
+int
+jabber_server_rename (struct t_jabber_server *server,
+ const char *new_server_name)
+{
+ int length;
+ char *mask, *pos_option, *new_option_name, *buffer_name;
+ const char *option_name;
+ struct t_infolist *infolist;
+ struct t_config_option *ptr_option;
+ //struct t_jabber_channel *ptr_channel;
+
+ /* check if another server exists with this name */
+ if (jabber_server_search (new_server_name))
+ return 0;
+
+ /* rename options */
+ length = 32 + strlen (server->name) + 1;
+ mask = malloc (length);
+ if (!mask)
+ return 0;
+ snprintf (mask, length, "jabber.server.%s.*", server->name);
+ infolist = weechat_infolist_get ("option", NULL, mask);
+ free (mask);
+ while (weechat_infolist_next (infolist))
+ {
+ weechat_config_search_with_string (weechat_infolist_string (infolist,
+ "full_name"),
+ NULL, NULL, &ptr_option,
+ NULL);
+ if (ptr_option)
+ {
+ option_name = weechat_infolist_string (infolist, "option_name");
+ if (option_name)
+ {
+ pos_option = strrchr (option_name, '.');
+ if (pos_option)
+ {
+ pos_option++;
+ length = strlen (new_server_name) + 1 + strlen (pos_option) + 1;
+ new_option_name = malloc (length);
+ if (new_option_name)
+ {
+ snprintf (new_option_name, length,
+ "%s.%s", new_server_name, pos_option);
+ weechat_config_option_rename (ptr_option, new_option_name);
+ free (new_option_name);
+ }
+ }
+ }
+ }
+ }
+ weechat_infolist_free (infolist);
+
+ /* rename server */
+ if (server->name)
+ free (server->name);
+ server->name = strdup (new_server_name);
+
+ /* change name for buffers with this server */
+ /*
+ for (ptr_channel = server->channels; ptr_channel;
+ ptr_channel = ptr_channel->next_channel)
+ {
+ if (ptr_channel->buffer)
+ {
+ buffer_name = jabber_buffer_build_name (server->name, ptr_channel->name);
+ weechat_buffer_set (ptr_channel->buffer, "name", buffer_name);
+ }
+ }
+ */
+ if (server->buffer)
+ {
+ buffer_name = jabber_buffer_build_name (server->name, NULL);
+ weechat_buffer_set (server->buffer, "name", buffer_name);
+ }
+
+ return 1;
+}
+
+/*
+ * jabber_server_send_signal: send a signal for a Jabber message (received or sent)
+ */
+
+void
+jabber_server_send_signal (struct t_jabber_server *server, const char *signal,
+ const char *command, const char *full_message)
+{
+ int length;
+ char *str_signal;
+
+ length = strlen (server->name) + 1 + strlen (signal) + 1 + strlen (command) + 1;
+ str_signal = malloc (length);
+ if (str_signal)
+ {
+ snprintf (str_signal, length,
+ "%s,%s_%s", server->name, signal, command);
+ weechat_hook_signal_send (str_signal, WEECHAT_HOOK_SIGNAL_STRING,
+ (void *)full_message);
+ free (str_signal);
+ }
+}
+
+/*
+ * jabber_server_recv_cb: receive data from a jabber server
+ */
+
+int
+jabber_server_recv_cb (void *arg_server)
+{
+ struct t_jabber_server *server;
+
+ server = (struct t_jabber_server *)arg_server;
+
+ if (!server)
+ return WEECHAT_RC_ERROR;
+
+ iks_recv (server->iks_parser, 0);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_server_timer_cb: timer called each second to perform some operations
+ * on servers
+ */
+
+int
+jabber_server_timer_cb (void *data)
+{
+ struct t_jabber_server *ptr_server;
+ time_t new_time;
+ //static struct timeval tv;
+ //int diff;
+
+ /* make C compiler happy */
+ (void) data;
+
+ new_time = time (NULL);
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ /* check if reconnection is pending */
+ if ((!ptr_server->is_connected)
+ && (ptr_server->reconnect_start > 0)
+ && (new_time >= (ptr_server->reconnect_start +
+ JABBER_SERVER_OPTION_INTEGER(ptr_server, JABBER_SERVER_OPTION_AUTORECONNECT_DELAY))))
+ jabber_server_reconnect (ptr_server);
+ else
+ {
+ if (ptr_server->is_connected)
+ {
+ /* check for lag */
+ //if ((ptr_server->lag_check_time.tv_sec == 0)
+ // && (new_time >= ptr_server->lag_next_check))
+ //{
+ // jabber_server_sendf (ptr_server, "PING %s",
+ // ptr_server->addresses_array[ptr_server->index_current_address]);
+ // gettimeofday (&(ptr_server->lag_check_time), NULL);
+ //}
+
+ /* check if it's time to autojoin channels (after command delay) */
+ //if ((ptr_server->command_time != 0)
+ // && (new_time >= ptr_server->command_time +
+ // JABBER_SERVER_OPTION_INTEGER(ptr_server, JABBER_SERVER_OPTION_COMMAND_DELAY)))
+ //{
+ // jabber_server_autojoin_channels (ptr_server);
+ // ptr_server->command_time = 0;
+ //}
+
+ /* lag timeout => disconnect */
+ //if ((ptr_server->lag_check_time.tv_sec != 0)
+ // && (weechat_config_integer (jabber_config_network_lag_disconnect) > 0))
+ //{
+ // gettimeofday (&tv, NULL);
+ // diff = (int) weechat_timeval_diff (&(ptr_server->lag_check_time),
+ // &tv);
+ // if (diff / 1000 > weechat_config_integer (jabber_config_network_lag_disconnect) * 60)
+ // {
+ // weechat_printf (ptr_server->buffer,
+ // _("%s%s: lag is high, "
+ // "disconnecting from "
+ // "server..."),
+ // jabber_buffer_get_server_prefix (ptr_server,
+ // NULL),
+ // JABBER_PLUGIN_NAME);
+ // jabber_server_disconnect (ptr_server, 1);
+ // }
+ //}
+ }
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_server_add_to_infolist: add a server in an infolist
+ * return 1 if ok, 0 if error
+ */
+
+int
+jabber_server_add_to_infolist (struct t_infolist *infolist,
+ struct t_jabber_server *server)
+{
+ struct t_infolist_item *ptr_item;
+
+ if (!infolist || !server)
+ return 0;
+
+ ptr_item = weechat_infolist_new_item (infolist);
+ if (!ptr_item)
+ return 0;
+
+ if (!weechat_infolist_new_var_string (ptr_item, "name", server->name))
+ return 0;
+ if (!weechat_infolist_new_var_pointer (ptr_item, "buffer", server->buffer))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "buffer_name",
+ (server->buffer) ?
+ weechat_buffer_get_string (server->buffer, "name") : ""))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "buffer_short_name",
+ (server->buffer) ?
+ weechat_buffer_get_string (server->buffer, "short_name") : ""))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "selected",
+ (weechat_config_boolean (jabber_config_look_one_server_buffer)
+ && (jabber_current_server != server)) ?
+ 0 : 1))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "username",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_USERNAME)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "server",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_SERVER)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "proxy",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_PROXY)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "ipv6",
+ JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_IPV6)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "tls",
+ JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_TLS)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "sasl",
+ JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_SASL)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "resource",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_RESOURCE)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "password",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_PASSWORD)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "local_alias",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_LOCAL_ALIAS)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autoconnect",
+ JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTOCONNECT)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect",
+ JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTORECONNECT)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect_delay",
+ JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_AUTORECONNECT_DELAY)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "local_hostname",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_LOCAL_HOSTNAME)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "command",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_COMMAND)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "command_delay",
+ JABBER_SERVER_OPTION_INTEGER(server, JABBER_SERVER_OPTION_COMMAND_DELAY)))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "autojoin",
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_AUTOJOIN)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "autorejoin",
+ JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_AUTOREJOIN)))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "temp_server", server->temp_server))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "address", server->address))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "port", server->port))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "current_ip", server->current_ip))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "sock", server->sock))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "iks_id_string", server->iks_id_string))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "iks_server_name", server->iks_server_name))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "iks_password", server->iks_password))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "iks_features", server->iks_features))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "iks_authorized", server->iks_authorized))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "is_connected", server->is_connected))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "tls_connected", server->tls_connected))
+ return 0;
+ if (!weechat_infolist_new_var_time (ptr_item, "reconnect_start", server->reconnect_start))
+ return 0;
+ if (!weechat_infolist_new_var_time (ptr_item, "command_time", server->command_time))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "reconnect_join", server->reconnect_join))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "disable_autojoin", server->disable_autojoin))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "is_away", server->is_away))
+ return 0;
+ if (!weechat_infolist_new_var_string (ptr_item, "away_message", server->away_message))
+ return 0;
+ if (!weechat_infolist_new_var_time (ptr_item, "away_time", server->away_time))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "lag", server->lag))
+ return 0;
+ if (!weechat_infolist_new_var_buffer (ptr_item, "lag_check_time", &(server->lag_check_time), sizeof (struct timeval)))
+ return 0;
+ if (!weechat_infolist_new_var_time (ptr_item, "lag_next_check", server->lag_next_check))
+ return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "buddies_count", server->buddies_count))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * jabber_server_print_log: print server infos in log (usually for crash dump)
+ */
+
+void
+jabber_server_print_log ()
+{
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_buddy *ptr_buddy;
+ struct t_jabber_muc *ptr_muc;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ weechat_log_printf ("");
+ weechat_log_printf ("[server %s (addr:0x%lx)]", ptr_server->name, ptr_server);
+
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_USERNAME]))
+ weechat_log_printf (" username . . . . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_USERNAME));
+ else
+ weechat_log_printf (" username . . . . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_USERNAME]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_SERVER]))
+ weechat_log_printf (" server . . . . . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_SERVER));
+ else
+ weechat_log_printf (" server . . . . . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_SERVER]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_PROXY]))
+ weechat_log_printf (" proxy. . . . . . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_PROXY));
+ else
+ weechat_log_printf (" proxy. . . . . . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_PROXY]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_IPV6]))
+ weechat_log_printf (" ipv6 . . . . . . . . : null (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_IPV6)) ?
+ "on" : "off");
+ else
+ weechat_log_printf (" ipv6 . . . . . . . . : %s",
+ weechat_config_boolean (ptr_server->options[JABBER_SERVER_OPTION_IPV6]) ?
+ "on" : "off");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_TLS]))
+ weechat_log_printf (" tls. . . . . . . . . : null (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_TLS)) ?
+ "on" : "off");
+ else
+ weechat_log_printf (" tls. . . . . . . . . : %s",
+ weechat_config_boolean (ptr_server->options[JABBER_SERVER_OPTION_TLS]) ?
+ "on" : "off");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_SASL]))
+ weechat_log_printf (" sasl . . . . . . . . : null (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_SASL)) ?
+ "on" : "off");
+ else
+ weechat_log_printf (" sasl . . . . . . . . : %s",
+ weechat_config_boolean (ptr_server->options[JABBER_SERVER_OPTION_SASL]) ?
+ "on" : "off");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_RESOURCE]))
+ weechat_log_printf (" resource . . . . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_RESOURCE));
+ else
+ weechat_log_printf (" resource . . . . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_RESOURCE]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_PASSWORD]))
+ weechat_log_printf (" password . . . . . . : null");
+ else
+ weechat_log_printf (" password . . . . . . : (hidden)");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_LOCAL_ALIAS]))
+ weechat_log_printf (" local_alias. . . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_LOCAL_ALIAS));
+ else
+ weechat_log_printf (" local_alias. . . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_LOCAL_ALIAS]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_AUTOCONNECT]))
+ weechat_log_printf (" autoconnect. . . . . : null (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_AUTOCONNECT)) ?
+ "on" : "off");
+ else
+ weechat_log_printf (" autoconnect. . . . . : %s",
+ weechat_config_boolean (ptr_server->options[JABBER_SERVER_OPTION_AUTOCONNECT]) ?
+ "on" : "off");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_AUTORECONNECT]))
+ weechat_log_printf (" autoreconnect. . . . : null (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_AUTORECONNECT)) ?
+ "on" : "off");
+ else
+ weechat_log_printf (" autoreconnect. . . . : %s",
+ weechat_config_boolean (ptr_server->options[JABBER_SERVER_OPTION_AUTORECONNECT]) ?
+ "on" : "off");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_AUTORECONNECT_DELAY]))
+ weechat_log_printf (" autoreconnect_delay. : null (%d)",
+ JABBER_SERVER_OPTION_INTEGER(ptr_server, JABBER_SERVER_OPTION_AUTORECONNECT_DELAY));
+ else
+ weechat_log_printf (" autoreconnect_delay. : %d",
+ weechat_config_integer (ptr_server->options[JABBER_SERVER_OPTION_AUTORECONNECT_DELAY]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_LOCAL_HOSTNAME]))
+ weechat_log_printf (" local_hostname . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_LOCAL_HOSTNAME));
+ else
+ weechat_log_printf (" local_hostname . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_LOCAL_HOSTNAME]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_COMMAND]))
+ weechat_log_printf (" command. . . . . . . : null");
+ else
+ weechat_log_printf (" command. . . . . . . : (hidden)");
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_COMMAND_DELAY]))
+ weechat_log_printf (" command_delay. . . . : null (%d)",
+ JABBER_SERVER_OPTION_INTEGER(ptr_server, JABBER_SERVER_OPTION_COMMAND_DELAY));
+ else
+ weechat_log_printf (" command_delay. . . . : %d",
+ weechat_config_integer (ptr_server->options[JABBER_SERVER_OPTION_COMMAND_DELAY]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_AUTOJOIN]))
+ weechat_log_printf (" autojoin . . . . . . : null ('%s')",
+ JABBER_SERVER_OPTION_STRING(ptr_server, JABBER_SERVER_OPTION_AUTOJOIN));
+ else
+ weechat_log_printf (" autojoin . . . . . . : '%s'",
+ weechat_config_string (ptr_server->options[JABBER_SERVER_OPTION_AUTOJOIN]));
+ if (weechat_config_option_is_null (ptr_server->options[JABBER_SERVER_OPTION_AUTOREJOIN]))
+ weechat_log_printf (" autorejoin . . . . . : null (%s)",
+ (JABBER_SERVER_OPTION_BOOLEAN(ptr_server, JABBER_SERVER_OPTION_AUTOREJOIN)) ?
+ "on" : "off");
+ else
+ weechat_log_printf (" autorejoin . . . . . : %s",
+ weechat_config_boolean (ptr_server->options[JABBER_SERVER_OPTION_AUTOREJOIN]) ?
+ "on" : "off");
+ weechat_log_printf (" temp_server. . . . . : %d", ptr_server->temp_server);
+ weechat_log_printf (" reloading_from_config: %d", ptr_server->reloaded_from_config);
+ weechat_log_printf (" reloaded_from_config : %d", ptr_server->reloaded_from_config);
+ weechat_log_printf (" address. . . . . . . : '%s'", ptr_server->address);
+ weechat_log_printf (" port . . . . . . . . : %d", ptr_server->port);
+ weechat_log_printf (" current_ip . . . . . : '%s'", ptr_server->current_ip);
+ weechat_log_printf (" sock . . . . . . . . : %d", ptr_server->sock);
+ weechat_log_printf (" iks_parser . . . . . : 0x%lx", ptr_server->iks_parser);
+ weechat_log_printf (" iks_id_string. . . . : '%s'", ptr_server->iks_id_string);
+ weechat_log_printf (" iks_id . . . . . . . : 0x%lx", ptr_server->iks_id);
+ weechat_log_printf (" iks_server_name. . . : '%s'", ptr_server->iks_server_name);
+ weechat_log_printf (" iks_password . . . . : (hidden)");
+ weechat_log_printf (" iks_filter . . . . . : 0x%lx", ptr_server->iks_filter);
+ weechat_log_printf (" iks_roster . . . . . : 0x%lx", ptr_server->iks_roster);
+ weechat_log_printf (" iks_features . . . . : %d", ptr_server->iks_features);
+ weechat_log_printf (" iks_authorized . . . : %d", ptr_server->iks_authorized);
+ weechat_log_printf (" hook_connect . . . . : 0x%lx", ptr_server->hook_connect);
+ weechat_log_printf (" hook_fd. . . . . . . : 0x%lx", ptr_server->hook_fd);
+ weechat_log_printf (" is_connected . . . . : %d", ptr_server->is_connected);
+ weechat_log_printf (" tls_connected. . . . : %d", ptr_server->tls_connected);
+#ifdef HAVE_GNUTLS
+ weechat_log_printf (" gnutls_sess. . . . . : 0x%lx", ptr_server->gnutls_sess);
+#endif
+ weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start);
+ weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time);
+ weechat_log_printf (" reconnect_join . . . : %d", ptr_server->reconnect_join);
+ weechat_log_printf (" disable_autojoin . . : %d", ptr_server->disable_autojoin);
+ weechat_log_printf (" is_away. . . . . . . : %d", ptr_server->is_away);
+ weechat_log_printf (" away_message . . . . : '%s'", ptr_server->away_message);
+ weechat_log_printf (" away_time. . . . . . : %ld", ptr_server->away_time);
+ weechat_log_printf (" lag. . . . . . . . . : %d", ptr_server->lag);
+ weechat_log_printf (" lag_check_time . . . : tv_sec:%d, tv_usec:%d",
+ ptr_server->lag_check_time.tv_sec,
+ ptr_server->lag_check_time.tv_usec);
+ weechat_log_printf (" lag_next_check . . . : %ld", ptr_server->lag_next_check);
+ weechat_log_printf (" buffer . . . . . . . : 0x%lx", ptr_server->buffer);
+ weechat_log_printf (" buffer_as_string . . : '%s'", ptr_server->buffer_as_string);
+ weechat_log_printf (" buddies_count. . . . : %d", ptr_server->buddies_count);
+ weechat_log_printf (" buddies. . . . . . . : 0x%lx", ptr_server->buddies);
+ weechat_log_printf (" last_buddy . . . . . : 0x%lx", ptr_server->last_buddy);
+ weechat_log_printf (" mucs . . . . . . . . : 0x%lx", ptr_server->mucs);
+ weechat_log_printf (" last_muc . . . . . . : 0x%lx", ptr_server->last_muc);
+ weechat_log_printf (" prev_server. . . . . : 0x%lx", ptr_server->prev_server);
+ weechat_log_printf (" next_server. . . . . : 0x%lx", ptr_server->next_server);
+
+ for (ptr_buddy = ptr_server->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ jabber_buddy_print_log (ptr_buddy);
+ }
+
+ for (ptr_muc = ptr_server->mucs; ptr_muc;
+ ptr_muc = ptr_muc->next_muc)
+ {
+ jabber_muc_print_log (ptr_muc);
+ }
+ }
+}
diff --git a/src/plugins/jabber/jabber-server.h b/src/plugins/jabber/jabber-server.h
new file mode 100644
index 000000000..5a0a01149
--- /dev/null
+++ b/src/plugins/jabber/jabber-server.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_SERVER_H
+#define __WEECHAT_JABBER_SERVER_H 1
+
+#include <sys/time.h>
+#include <regex.h>
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#include <iksemel.h>
+
+enum t_jabber_server_option
+{
+ JABBER_SERVER_OPTION_USERNAME = 0, /* username on server */
+ JABBER_SERVER_OPTION_SERVER, /* server hostname/IP */
+ JABBER_SERVER_OPTION_PROXY, /* proxy used for server (optional) */
+ JABBER_SERVER_OPTION_IPV6, /* use IPv6 protocol */
+ JABBER_SERVER_OPTION_TLS, /* use TLS cryptographic protocol */
+ JABBER_SERVER_OPTION_SASL, /* use SASL for auth */
+ JABBER_SERVER_OPTION_RESOURCE, /* resource */
+ JABBER_SERVER_OPTION_PASSWORD, /* password */
+ JABBER_SERVER_OPTION_LOCAL_ALIAS, /* local alias */
+ JABBER_SERVER_OPTION_AUTOCONNECT, /* autoconnect to server at startup */
+ JABBER_SERVER_OPTION_AUTORECONNECT, /* autoreconnect when disconnected */
+ JABBER_SERVER_OPTION_AUTORECONNECT_DELAY, /* delay before next reconnect */
+ JABBER_SERVER_OPTION_LOCAL_HOSTNAME,/* custom local hostname */
+ JABBER_SERVER_OPTION_COMMAND, /* command to run once connected */
+ JABBER_SERVER_OPTION_COMMAND_DELAY, /* delay after execution of command */
+ JABBER_SERVER_OPTION_AUTOJOIN, /* MUCs to automatically join */
+ JABBER_SERVER_OPTION_AUTOREJOIN, /* auto rejoin MUCs when kicked */
+ /* number of server options */
+ JABBER_SERVER_NUM_OPTIONS,
+};
+
+#define JABBER_SERVER_OPTION_BOOLEAN(__server, __index) \
+ ((!weechat_config_option_is_null(__server->options[__index])) ? \
+ weechat_config_boolean(__server->options[__index]) : \
+ ((!weechat_config_option_is_null(jabber_config_server_default[__index])) ? \
+ weechat_config_boolean(jabber_config_server_default[__index]) \
+ : weechat_config_boolean_default(jabber_config_server_default[__index])))
+
+#define JABBER_SERVER_OPTION_INTEGER(__server, __index) \
+ ((!weechat_config_option_is_null(__server->options[__index])) ? \
+ weechat_config_integer(__server->options[__index]) : \
+ ((!weechat_config_option_is_null(jabber_config_server_default[__index])) ? \
+ weechat_config_integer(jabber_config_server_default[__index]) \
+ : weechat_config_integer_default(jabber_config_server_default[__index])))
+
+#define JABBER_SERVER_OPTION_STRING(__server, __index) \
+ ((!weechat_config_option_is_null(__server->options[__index])) ? \
+ weechat_config_string(__server->options[__index]) : \
+ ((!weechat_config_option_is_null(jabber_config_server_default[__index])) ? \
+ weechat_config_string(jabber_config_server_default[__index]) \
+ : weechat_config_string_default(jabber_config_server_default[__index])))
+
+#define JABBER_SERVER_DEFAULT_PORT 5222
+#define JABBER_SERVER_DEFAULT_RESOURCE "WeeChat"
+
+#define jabber_server_sendf_queued(server, fmt, argz...) \
+ if (server) \
+ { \
+ server->queue_msg = 1; \
+ jabber_server_sendf (server, fmt, ##argz); \
+ server->queue_msg = 0; \
+ }
+
+struct t_jabber_server
+{
+ /* user choices */
+ char *name; /* internal name of server */
+ struct t_config_option *options[JABBER_SERVER_NUM_OPTIONS];
+
+ /* internal vars */
+ int temp_server; /* temporary server (not saved) */
+ int reloading_from_config; /* 1 if reloading from config file */
+ int reloaded_from_config; /* 1 if reloaded from config file */
+ char *address; /* address from "server" option */
+ int port; /* port from "server" option */
+ char *current_ip; /* current IP address */
+ int sock; /* socket for server (IPv4 or IPv6) */
+ iksparser *iks_parser; /* parser for libiksemel */
+ char *iks_id_string; /* string with id (user@server/resource) */
+ iksid *iks_id; /* id for libiksemel */
+ char *iks_server_name; /* server name for libiksemel */
+ char *iks_password; /* password for libiksemel */
+ iksfilter *iks_filter; /* filter for libiksemel */
+ iks *iks_roster; /* jabber roster (buddy list) */
+ int iks_features; /* stream features */
+ int iks_authorized; /* authorized by jabber server */
+ struct t_hook *hook_connect; /* connection hook */
+ struct t_hook *hook_fd; /* hook for server socket */
+ int is_connected; /* 1 if WeeChat is connected to server */
+ int tls_connected; /* = 1 if connected with TLS */
+#ifdef HAVE_GNUTLS
+ gnutls_session_t gnutls_sess; /* gnutls session (only if TLS is used) */
+#endif
+ time_t reconnect_start; /* this time + delay = reconnect time */
+ time_t command_time; /* this time + command_delay = time to */
+ /* autojoin MUCs */
+ int reconnect_join; /* 1 if opened MUCs to rejoin */
+ int disable_autojoin; /* 1 if user asked to not autojoin MUCs */
+ int is_away; /* 1 is user is marked as away */
+ char *away_message; /* away message, NULL if not away */
+ time_t away_time; /* time() when user marking as away */
+ int lag; /* lag (in milliseconds) */
+ struct timeval lag_check_time; /* last time lag was checked (ping sent) */
+ time_t lag_next_check; /* time for next check */
+ struct t_gui_buffer *buffer; /* GUI buffer allocated for server */
+ char *buffer_as_string; /* used to return buffer info */
+ int buddies_count; /* # buddies in roster */
+ struct t_jabber_buddy *buddies; /* buddies in roster */
+ struct t_jabber_buddy *last_buddy; /* last buddy in roster */
+ struct t_jabber_muc *mucs; /* MUCs opened on server */
+ struct t_jabber_muc *last_muc; /* last opened MUC on server */
+ struct t_jabber_server *prev_server; /* link to previous server */
+ struct t_jabber_server *next_server; /* link to next server */
+};
+
+/* Jabber messages */
+
+struct t_jabber_message
+{
+ struct t_jabber_server *server; /* server pointer for received msg */
+ char *data; /* message content */
+ struct t_jabber_message *next_message; /* link to next message */
+};
+
+extern struct t_jabber_server *jabber_servers;
+extern struct t_jabber_server *jabber_current_server;
+#ifdef HAVE_GNUTLS
+extern const int gnutls_cert_type_prio[];
+extern const int gnutls_prot_prio[];
+#endif
+extern struct t_jabber_message *jabber_recv_msgq, *jabber_msgq_last_msg;
+extern char *jabber_server_option_string[];
+extern char *jabber_server_option_default[];
+
+extern int jabber_server_valid (struct t_jabber_server *server);
+extern int jabber_server_search_option (const char *option_name);
+extern struct t_jabber_server *jabber_server_search (const char *server_name);
+extern int jabber_server_get_muc_count (struct t_jabber_server *server);
+extern int jabber_server_get_pv_count (struct t_jabber_server *server);
+extern char *jabber_server_get_name_without_port (const char *name);
+extern const char *jabber_server_get_local_name (struct t_jabber_server *server);
+extern void jabber_server_set_server (struct t_jabber_server *server,
+ const char *address);
+extern void jabber_server_set_nicks (struct t_jabber_server *server,
+ const char *nicks);
+extern void jabber_server_buffer_set_highlight_words (struct t_gui_buffer *buffer);
+extern struct t_jabber_server *jabber_server_alloc (const char *name);
+extern void jabber_server_set_buffer_title (struct t_jabber_server *server);
+extern struct t_gui_buffer *jabber_server_create_buffer (struct t_jabber_server *server,
+ int all_servers);
+extern void jabber_server_set_current_server (struct t_jabber_server *server);
+extern int jabber_server_iks_transport_connect_async (iksparser *parser,
+ void **socketptr,
+ const char *server,
+ const char *server_name,
+ int port,
+ void *notify_data,
+ iksAsyncNotify *notify_func);
+extern int jabber_server_iks_transport_send (void *socket, const char *data,
+ size_t len);
+extern int jabber_server_iks_transport_recv (void *socket, char *buffer,
+ size_t buf_len, int timeout);
+extern void jabber_server_iks_transport_close (void *socket);
+extern int jabber_server_connect (struct t_jabber_server *server);
+extern void jabber_server_auto_connect ();
+extern void jabber_server_disconnect (struct t_jabber_server *server,
+ int reconnect);
+extern void jabber_server_disconnect_all ();
+extern void jabber_server_free_data (struct t_jabber_server *server);
+extern void jabber_server_free (struct t_jabber_server *server);
+extern void jabber_server_free_all ();
+extern struct t_jabber_server *jabber_server_copy (struct t_jabber_server *server,
+ const char *new_name);
+extern int jabber_server_rename (struct t_jabber_server *server,
+ const char *new_server_name);
+extern int jabber_server_recv_cb (void *arg_server);
+extern int jabber_server_timer_cb (void *data);
+extern int jabber_server_add_to_infolist (struct t_infolist *infolist,
+ struct t_jabber_server *server);
+extern void jabber_server_print_log ();
+
+#endif /* jabber-server.h */
diff --git a/src/plugins/jabber/jabber-upgrade.c b/src/plugins/jabber/jabber-upgrade.c
new file mode 100644
index 000000000..77aa5b73b
--- /dev/null
+++ b/src/plugins/jabber/jabber-upgrade.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-upgrade.c: save/restore Jabber plugin data */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-upgrade.h"
+#include "jabber-buddy.h"
+#include "jabber-buffer.h"
+#include "jabber-config.h"
+#include "jabber-input.h"
+#include "jabber-muc.h"
+#include "jabber-server.h"
+
+
+struct t_jabber_server *jabber_upgrade_current_server = NULL;
+struct t_jabber_muc *jabber_upgrade_current_muc = NULL;
+
+
+/*
+ * jabber_upgrade_save_all_data: save servers/MUCs/buddies info to upgrade
+ * file
+ */
+
+int
+jabber_upgrade_save_all_data (struct t_upgrade_file *upgrade_file)
+{
+ struct t_infolist *infolist;
+ struct t_jabber_server *ptr_server;
+ struct t_jabber_muc *ptr_muc;
+ struct t_jabber_buddy *ptr_buddy;
+ int rc;
+
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ /* save server */
+ infolist = weechat_infolist_new ();
+ if (!infolist)
+ return 0;
+ if (!jabber_server_add_to_infolist (infolist, ptr_server))
+ {
+ weechat_infolist_free (infolist);
+ return 0;
+ }
+ rc = weechat_upgrade_write_object (upgrade_file,
+ JABBER_UPGRADE_TYPE_SERVER,
+ infolist);
+ weechat_infolist_free (infolist);
+ if (!rc)
+ return 0;
+
+ for (ptr_muc = ptr_server->mucs; ptr_muc;
+ ptr_muc = ptr_muc->next_muc)
+ {
+ /* save MUC */
+ infolist = weechat_infolist_new ();
+ if (!infolist)
+ return 0;
+ if (!jabber_muc_add_to_infolist (infolist, ptr_muc))
+ {
+ weechat_infolist_free (infolist);
+ return 0;
+ }
+ rc = weechat_upgrade_write_object (upgrade_file,
+ JABBER_UPGRADE_TYPE_MUC,
+ infolist);
+ weechat_infolist_free (infolist);
+ if (!rc)
+ return 0;
+
+ for (ptr_buddy = ptr_muc->buddies; ptr_buddy;
+ ptr_buddy = ptr_buddy->next_buddy)
+ {
+ /* save buddy */
+ infolist = weechat_infolist_new ();
+ if (!infolist)
+ return 0;
+ if (!jabber_buddy_add_to_infolist (infolist, ptr_buddy))
+ {
+ weechat_infolist_free (infolist);
+ return 0;
+ }
+ rc = weechat_upgrade_write_object (upgrade_file,
+ JABBER_UPGRADE_TYPE_BUDDY,
+ infolist);
+ weechat_infolist_free (infolist);
+ if (!rc)
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * jabber_upgrade_save: save upgrade file
+ * return 1 if ok, 0 if error
+ */
+
+int
+jabber_upgrade_save ()
+{
+ int rc;
+ struct t_upgrade_file *upgrade_file;
+
+ upgrade_file = weechat_upgrade_create (JABBER_UPGRADE_FILENAME, 1);
+ if (!upgrade_file)
+ return 0;
+
+ rc = jabber_upgrade_save_all_data (upgrade_file);
+
+ weechat_upgrade_close (upgrade_file);
+
+ return rc;
+}
+
+/*
+ * jabber_upgrade_set_buffer_callbacks: restore buffers callbacks (input and
+ * close) for buffers created by Jabber
+ * plugin
+ */
+
+void
+jabber_upgrade_set_buffer_callbacks ()
+{
+ struct t_infolist *infolist;
+ struct t_gui_buffer *ptr_buffer;
+
+ infolist = weechat_infolist_get ("buffer", NULL, NULL);
+ if (infolist)
+ {
+ while (weechat_infolist_next (infolist))
+ {
+ if (weechat_infolist_pointer (infolist, "plugin") == weechat_jabber_plugin)
+ {
+ ptr_buffer = weechat_infolist_pointer (infolist, "pointer");
+ weechat_buffer_set_pointer (ptr_buffer, "close_callback", &jabber_buffer_close_cb);
+ weechat_buffer_set_pointer (ptr_buffer, "input_callback", &jabber_input_data_cb);
+ }
+ }
+ }
+}
+
+/*
+ * jabber_upgrade_read_cb: read callback for upgrade
+ */
+
+int
+jabber_upgrade_read_cb (int object_id,
+ struct t_infolist *infolist)
+{
+ int flags, size, i, index;
+ char *buf, option_name[64];
+ const char *buffer_name, *str, *buddy;
+ struct t_jabber_buddy *ptr_buddy;
+ struct t_gui_buffer *ptr_buffer;
+
+ weechat_infolist_reset_item_cursor (infolist);
+ while (weechat_infolist_next (infolist))
+ {
+ switch (object_id)
+ {
+ case JABBER_UPGRADE_TYPE_SERVER:
+ jabber_upgrade_current_server = jabber_server_search (weechat_infolist_string (infolist, "name"));
+ if (jabber_upgrade_current_server)
+ {
+ jabber_upgrade_current_server->temp_server =
+ weechat_infolist_integer (infolist, "temp_server");
+ jabber_upgrade_current_server->buffer = NULL;
+ buffer_name = weechat_infolist_string (infolist, "buffer_name");
+ if (buffer_name && buffer_name[0])
+ {
+ ptr_buffer = weechat_buffer_search (JABBER_PLUGIN_NAME,
+ buffer_name);
+ if (ptr_buffer)
+ {
+ jabber_upgrade_current_server->buffer = ptr_buffer;
+ if (weechat_config_boolean (jabber_config_look_one_server_buffer)
+ && !jabber_buffer_servers)
+ {
+ jabber_buffer_servers = ptr_buffer;
+ }
+ if (weechat_infolist_integer (infolist, "selected"))
+ jabber_current_server = jabber_upgrade_current_server;
+ }
+ }
+ jabber_upgrade_current_server->reconnect_start = weechat_infolist_time (infolist, "reconnect_start");
+ jabber_upgrade_current_server->command_time = weechat_infolist_time (infolist, "command_time");
+ jabber_upgrade_current_server->reconnect_join = weechat_infolist_integer (infolist, "reconnect_join");
+ jabber_upgrade_current_server->disable_autojoin = weechat_infolist_integer (infolist, "disable_autojoin");
+ jabber_upgrade_current_server->is_away = weechat_infolist_integer (infolist, "is_away");
+ str = weechat_infolist_string (infolist, "away_message");
+ if (str)
+ jabber_upgrade_current_server->away_message = strdup (str);
+ jabber_upgrade_current_server->away_time = weechat_infolist_time (infolist, "away_time");
+ jabber_upgrade_current_server->lag = weechat_infolist_integer (infolist, "lag");
+ buf = weechat_infolist_buffer (infolist, "lag_check_time", &size);
+ if (buf)
+ memcpy (&(jabber_upgrade_current_server->lag_check_time), buf, size);
+ jabber_upgrade_current_server->lag_next_check = weechat_infolist_time (infolist, "lag_next_check");
+ }
+ break;
+ case JABBER_UPGRADE_TYPE_MUC:
+ if (jabber_upgrade_current_server)
+ {
+ jabber_upgrade_current_muc = jabber_muc_new (jabber_upgrade_current_server,
+ weechat_infolist_integer (infolist, "type"),
+ weechat_infolist_string (infolist, "name"),
+ 0);
+ if (jabber_upgrade_current_muc)
+ {
+ str = weechat_infolist_string (infolist, "topic");
+ if (str)
+ jabber_muc_set_topic (jabber_upgrade_current_muc, str);
+ str = weechat_infolist_string (infolist, "modes");
+ if (str)
+ jabber_upgrade_current_muc->modes = strdup (str);
+ jabber_upgrade_current_muc->limit = weechat_infolist_integer (infolist, "limit");
+ str = weechat_infolist_string (infolist, "key");
+ if (str)
+ jabber_upgrade_current_muc->key = strdup (str);
+ str = weechat_infolist_string (infolist, "away_message");
+ if (str)
+ jabber_upgrade_current_muc->away_message = strdup (str);
+ jabber_upgrade_current_muc->nick_completion_reset = weechat_infolist_integer (infolist, "nick_completion_reset");
+ for (i = 0; i < 2; i++)
+ {
+ index = 0;
+ while (1)
+ {
+ snprintf (option_name, sizeof (option_name),
+ "buddy_speaking%d_%05d", i, index);
+ buddy = weechat_infolist_string (infolist, option_name);
+ if (!buddy)
+ break;
+ jabber_muc_buddy_speaking_add (jabber_upgrade_current_muc,
+ buddy,
+ i);
+ index++;
+ }
+ }
+ index = 0;
+ while (1)
+ {
+ snprintf (option_name, sizeof (option_name),
+ "buddy_speaking_time_buddy_%05d", index);
+ buddy = weechat_infolist_string (infolist, option_name);
+ if (!buddy)
+ break;
+ snprintf (option_name, sizeof (option_name),
+ "buddy_speaking_time_time_%05d", index);
+ jabber_muc_buddy_speaking_time_add (jabber_upgrade_current_muc,
+ buddy,
+ weechat_infolist_time (infolist,
+ option_name));
+ index++;
+ }
+ }
+ }
+ break;
+ case JABBER_UPGRADE_TYPE_BUDDY:
+ if (jabber_upgrade_current_server)
+ {
+ flags = weechat_infolist_integer (infolist, "flags");
+ ptr_buddy = jabber_buddy_new (jabber_upgrade_current_server,
+ jabber_upgrade_current_muc,
+ weechat_infolist_string (infolist, "name"),
+ flags & JABBER_BUDDY_CHANOWNER,
+ flags & JABBER_BUDDY_CHANADMIN,
+ flags & JABBER_BUDDY_CHANADMIN2,
+ flags & JABBER_BUDDY_OP,
+ flags & JABBER_BUDDY_HALFOP,
+ flags & JABBER_BUDDY_VOICE,
+ flags & JABBER_BUDDY_CHANUSER,
+ flags & JABBER_BUDDY_AWAY);
+ if (ptr_buddy)
+ {
+ str = weechat_infolist_string (infolist, "host");
+ if (str)
+ ptr_buddy->host = strdup (str);
+ }
+ }
+ break;
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_upgrade_load: load upgrade file
+ * return 1 if ok, 0 if error
+ */
+
+int
+jabber_upgrade_load ()
+{
+ int rc;
+ struct t_upgrade_file *upgrade_file;
+
+ jabber_upgrade_set_buffer_callbacks ();
+
+ upgrade_file = weechat_upgrade_create (JABBER_UPGRADE_FILENAME, 0);
+ rc = weechat_upgrade_read (upgrade_file, &jabber_upgrade_read_cb);
+
+ return rc;
+}
diff --git a/src/plugins/jabber/jabber-upgrade.h b/src/plugins/jabber/jabber-upgrade.h
new file mode 100644
index 000000000..efd83d295
--- /dev/null
+++ b/src/plugins/jabber/jabber-upgrade.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_UPGRADE_H
+#define __WEECHAT_JABBER_UPGRADE_H 1
+
+#define JABBER_UPGRADE_FILENAME "jabber"
+
+/* For developers: please add new values ONLY AT THE END of enums */
+
+enum t_jabber_upgrade_type
+{
+ JABBER_UPGRADE_TYPE_SERVER = 0,
+ JABBER_UPGRADE_TYPE_MUC,
+ JABBER_UPGRADE_TYPE_BUDDY,
+};
+
+extern int jabber_upgrade_save ();
+extern int jabber_upgrade_load ();
+
+#endif /* jabber-upgrade.h */
diff --git a/src/plugins/jabber/jabber-xmpp.c b/src/plugins/jabber/jabber-xmpp.c
new file mode 100644
index 000000000..ffc68452b
--- /dev/null
+++ b/src/plugins/jabber/jabber-xmpp.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber-xmpp.c: XMPP protocol for Jabber plugin */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iksemel.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-xmpp.h"
+#include "jabber-buddy.h"
+#include "jabber-buffer.h"
+#include "jabber-config.h"
+#include "jabber-debug.h"
+#include "jabber-muc.h"
+#include "jabber-server.h"
+
+
+/*
+ * jabber_xmpp_log_level_for_command: get log level for Jabber command
+ */
+
+int
+jabber_xmpp_log_level_for_command (const char *command)
+{
+ if (!command || !command[0])
+ return 0;
+
+ if (strcmp (command, "chat_msg") == 0)
+ return 1;
+
+ return 3;
+}
+
+/*
+ * jabber_xmpp_tags: build tags list with Jabber command and/or tags
+ */
+
+const char *
+jabber_xmpp_tags (const char *command, const char *tags)
+{
+ static char string[512];
+ int log_level;
+ char str_log_level[32];
+
+ log_level = 0;
+ str_log_level[0] = '\0';
+
+ if (command && command[0])
+ {
+ log_level = jabber_xmpp_log_level_for_command (command);
+ if (log_level > 0)
+ {
+ snprintf (str_log_level, sizeof (str_log_level),
+ ",log%d", log_level);
+ }
+ }
+
+ if (command && command[0] && tags && tags[0])
+ {
+ snprintf (string, sizeof (string),
+ "jabber_%s,%s%s", command, tags, str_log_level);
+ return string;
+ }
+
+ if (command && command[0])
+ {
+ snprintf (string, sizeof (string),
+ "jabber_%s%s", command, str_log_level);
+ return string;
+ }
+
+ if (tags && tags[0])
+ {
+ snprintf (string, sizeof (string), "%s", tags);
+ return string;
+ }
+
+ return NULL;
+}
+
+/*
+ * jabber_xmpp_recv_chat_message: receive a message
+ */
+
+int
+jabber_xmpp_recv_chat_message (struct t_jabber_server *server,
+ iks *node)
+{
+ char *attrib_from, *from, *pos;
+ char *body;
+ struct t_jabber_muc *ptr_muc;
+
+ attrib_from = iks_find_attrib (node, "from");
+ if (!attrib_from || !attrib_from[0])
+ return WEECHAT_RC_ERROR;
+
+ body = iks_find_cdata (node, "body");
+ if (!body)
+ return WEECHAT_RC_ERROR;
+
+ pos = strchr (attrib_from, '/');
+ from = (pos) ?
+ weechat_strndup (attrib_from, pos - attrib_from) : strdup (attrib_from);
+ if (from)
+ {
+ ptr_muc = jabber_muc_search (server, from);
+ if (!ptr_muc)
+ {
+ ptr_muc = jabber_muc_new (server,
+ JABBER_MUC_TYPE_PRIVATE,
+ from, 0);
+ if (!ptr_muc)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: cannot create new "
+ "private buffer \"%s\""),
+ jabber_buffer_get_server_prefix (server,
+ "error"),
+ JABBER_PLUGIN_NAME, from);
+ return WEECHAT_RC_ERROR;
+ }
+ }
+ //jabber_muc_set_topic (ptr_channel, address);
+
+ weechat_printf_tags (ptr_muc->buffer,
+ jabber_xmpp_tags ("chat_msg", "notify_private"),
+ "%s%s",
+ jabber_buddy_as_prefix (NULL,
+ from,
+ JABBER_COLOR_CHAT_NICK_OTHER),
+ body);
+
+ weechat_hook_signal_send ("jabber_pv",
+ WEECHAT_HOOK_SIGNAL_STRING,
+ body);
+ free (from);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_xmpp_send_chat_message: send a message to MUC or buddy
+ */
+
+void
+jabber_xmpp_send_chat_message (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ const char *message)
+{
+ iks *msg;
+
+ if (muc->type == JABBER_MUC_TYPE_PRIVATE)
+ {
+ msg = iks_make_msg (IKS_TYPE_CHAT, muc->name, message);
+ if (msg)
+ {
+ iks_send (server->iks_parser, msg);
+ iks_delete (msg);
+ }
+ }
+ else
+ {
+ // TODO: send message to MUC
+ }
+}
+
+/*
+ * jabber_xmpp_iks_stream_hook: iksemel stream hook
+ */
+
+int
+jabber_xmpp_iks_stream_hook (void *user_data, int type, iks *node)
+{
+ struct t_jabber_server *server;
+ iks *x, *t;
+ ikspak *pak;
+
+ server = (struct t_jabber_server *)user_data;
+
+ switch (type)
+ {
+ case IKS_NODE_START:
+ if (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_TLS)
+ && !iks_is_secure (server->iks_parser))
+ {
+ iks_start_tls (server->iks_parser);
+ }
+ else
+ {
+ if (!JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_SASL))
+ {
+ x = iks_make_auth (server->iks_id,
+ JABBER_SERVER_OPTION_STRING(server, JABBER_SERVER_OPTION_PASSWORD),
+ iks_find_attrib (node, "id"));
+ iks_insert_attrib (x, "id", "auth");
+ iks_send (server->iks_parser, x);
+ iks_delete (x);
+ }
+ }
+ break;
+ case IKS_NODE_NORMAL:
+ if (strcmp ("stream:features", iks_name (node)) == 0)
+ {
+ server->iks_features = iks_stream_features (node);
+ if (JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_SASL))
+ {
+ if (!JABBER_SERVER_OPTION_BOOLEAN(server, JABBER_SERVER_OPTION_TLS)
+ || iks_is_secure (server->iks_parser))
+ {
+ if (server->iks_authorized)
+ {
+ if (server->iks_features & IKS_STREAM_BIND)
+ {
+ t = iks_make_resource_bind (server->iks_id);
+ iks_send (server->iks_parser, t);
+ iks_delete (t);
+ }
+ if (server->iks_features & IKS_STREAM_SESSION)
+ {
+ t = iks_make_session ();
+ iks_insert_attrib (t, "id", "auth");
+ iks_send (server->iks_parser, t);
+ iks_delete (t);
+ }
+ }
+ else
+ {
+ if (server->iks_features & IKS_STREAM_SASL_MD5)
+ {
+ iks_start_sasl (server->iks_parser,
+ IKS_SASL_DIGEST_MD5,
+ server->iks_id->user,
+ server->iks_password);
+ }
+ else if (server->iks_features & IKS_STREAM_SASL_PLAIN)
+ {
+ iks_start_sasl (server->iks_parser,
+ IKS_SASL_PLAIN,
+ server->iks_id->user,
+ server->iks_password);
+ }
+ }
+ }
+ }
+ }
+ else if (strcmp ("failure", iks_name (node)) == 0)
+ {
+ weechat_printf (server->buffer,
+ _("%s%s: SASL authentication failed (check "
+ "SASL option and password)"),
+ jabber_buffer_get_server_prefix (server,
+ "error"),
+ JABBER_PLUGIN_NAME);
+
+ jabber_server_disconnect (server, 0);
+ }
+ else if (strcmp ("success", iks_name (node)) == 0)
+ {
+ server->iks_authorized = 1;
+ iks_send_header (server->iks_parser, server->iks_id->server);
+ }
+ else if (strcmp ("message", iks_name (node)) == 0)
+ {
+ jabber_xmpp_recv_chat_message (server, node);
+ }
+ else
+ {
+ pak = iks_packet (node);
+ iks_filter_packet (server->iks_filter, pak);
+ }
+ break;
+ case IKS_NODE_STOP:
+ weechat_printf (server->buffer,
+ _("%s%s: server disconnected"),
+ jabber_buffer_get_server_prefix (server, "network"),
+ JABBER_PLUGIN_NAME);
+ jabber_server_disconnect (server, 1);
+ break;
+ case IKS_NODE_ERROR:
+ weechat_printf (server->buffer,
+ _("%s%s: stream error"),
+ jabber_buffer_get_server_prefix (server,
+ "error"),
+ JABBER_PLUGIN_NAME);
+ break;
+ }
+
+ if (node)
+ iks_delete (node);
+
+ return IKS_OK;
+}
+
+/*
+ * jabber_xmpp_iks_log: log
+ */
+
+void
+jabber_xmpp_iks_log (void *user_data, const char *data, size_t size,
+ int is_incoming)
+{
+ /* make C compiler happy */
+ (void) size;
+
+ jabber_debug_printf ((struct t_jabber_server *)user_data,
+ !is_incoming, 0,
+ data);
+}
+
+/*
+ * jabber_xmpp_iks_result: iks result
+ */
+
+int
+jabber_xmpp_iks_result (void *user_data, ikspak *pak)
+{
+ iks *x;
+ struct t_jabber_server *server;
+
+ /* make C compiler happy */
+ (void) pak;
+
+ server = (struct t_jabber_server *)user_data;
+
+ weechat_printf (server->buffer,
+ _("%s%s: login ok"),
+ jabber_buffer_get_server_prefix (server, NULL),
+ JABBER_PLUGIN_NAME);
+
+ x = iks_make_iq (IKS_TYPE_GET, IKS_NS_ROSTER);
+ iks_insert_attrib (x, "id", "roster");
+ iks_send (server->iks_parser, x);
+ iks_delete (x);
+
+ return IKS_FILTER_EAT;
+}
+
+/*
+ * jabber_xmpp_iks_error: iks error
+ */
+
+int
+jabber_xmpp_iks_error (void *user_data, ikspak *pak)
+{
+ struct t_jabber_server *server;
+
+ /* make C compiler happy */
+ (void) pak;
+
+ server = (struct t_jabber_server *)user_data;
+
+ weechat_printf (server->buffer,
+ _("%s%s: authentication failed (check SASL option and "
+ "password)"),
+ jabber_buffer_get_server_prefix (server, "error"),
+ JABBER_PLUGIN_NAME);
+
+ jabber_server_disconnect (server, 0);
+
+ return IKS_FILTER_EAT;
+}
+
+/*
+ * jabber_xmpp_iks_roster: iks roster
+ */
+
+int
+jabber_xmpp_iks_roster (void *user_data, ikspak *pak)
+{
+ struct t_jabber_server *server;
+ char *jid, *id, *pos;
+ iks *x;
+
+ server = (struct t_jabber_server *)user_data;
+
+ server->iks_roster = pak->x;
+
+ x = iks_child(pak->query);
+ while (x)
+ {
+ if (iks_strcmp (iks_name(x), "item") == 0)
+ {
+ jid = iks_find_attrib (x, "jid");
+ if (jid)
+ {
+ pos = strchr (jid, '@');
+ //id = (pos) ? weechat_strndup (jid, pos - jid) : strdup (jid);
+ id = strdup (jid);
+ if (id)
+ {
+ jabber_buddy_new (server, NULL, id, 0, 0, 0, 0, 0, 0, 0, 0);
+ free (id);
+ }
+ }
+ }
+ x = iks_next (x);
+ }
+ if (x)
+ iks_delete (x);
+
+ return IKS_FILTER_EAT;
+}
diff --git a/src/plugins/jabber/jabber-xmpp.h b/src/plugins/jabber/jabber-xmpp.h
new file mode 100644
index 000000000..c935df3b0
--- /dev/null
+++ b/src/plugins/jabber/jabber-xmpp.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_XMPP_H
+#define __WEECHAT_JABBER_XMPP_H 1
+
+#include <iksemel.h>
+
+struct t_jabber_server;
+struct t_jabber_muc;
+
+extern const char *jabber_xmpp_tags (const char *command, const char *tags);
+extern void jabber_xmpp_send_chat_message (struct t_jabber_server *server,
+ struct t_jabber_muc *muc,
+ const char *message);
+extern int jabber_xmpp_iks_stream_hook (void *user_data, int type, iks *node);
+extern void jabber_xmpp_iks_log (void *user_data, const char *data,
+ size_t size, int is_incoming);
+extern int jabber_xmpp_iks_result (void *user_data, ikspak *pak);
+extern int jabber_xmpp_iks_error (void *user_data, ikspak *pak);
+extern int jabber_xmpp_iks_roster (void *user_data, ikspak *pak);
+
+#endif /* jabber-xmpp.h */
diff --git a/src/plugins/jabber/jabber.c b/src/plugins/jabber/jabber.c
new file mode 100644
index 000000000..9f8f6a348
--- /dev/null
+++ b/src/plugins/jabber/jabber.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* jabber.c: Jabber plugin for WeeChat */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "jabber.h"
+#include "jabber-bar-item.h"
+#include "jabber-command.h"
+#include "jabber-completion.h"
+#include "jabber-config.h"
+#include "jabber-debug.h"
+#include "jabber-info.h"
+#include "jabber-server.h"
+#include "jabber-upgrade.h"
+
+
+WEECHAT_PLUGIN_NAME(JABBER_PLUGIN_NAME);
+WEECHAT_PLUGIN_DESCRIPTION("Jabber plugin for WeeChat");
+WEECHAT_PLUGIN_AUTHOR("FlashCode <flashcode@flashtux.org>");
+WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
+WEECHAT_PLUGIN_WEECHAT_VERSION(WEECHAT_VERSION);
+WEECHAT_PLUGIN_LICENSE("GPL3");
+
+struct t_weechat_plugin *weechat_jabber_plugin = NULL;
+
+struct t_hook *jabber_hook_timer = NULL;
+
+int jabber_signal_upgrade_received = 0; /* signal "upgrade" received ? */
+
+
+/*
+ * jabber_signal_quit_cb: callback for "quit" signal
+ */
+
+int
+jabber_signal_quit_cb (void *data, const char *signal, const char *type_data,
+ void *signal_data)
+{
+ struct t_jabber_server *ptr_server;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) signal;
+
+ if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0)
+ {
+ for (ptr_server = jabber_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ jabber_command_quit_server (ptr_server,
+ (signal_data) ? (char *)signal_data : NULL);
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * jabber_signal_upgrade_cb: callback for "upgrade" signal
+ */
+
+int
+jabber_signal_upgrade_cb (void *data, const char *signal, const char *type_data,
+ void *signal_data)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) signal;
+ (void) type_data;
+ (void) signal_data;
+
+ jabber_signal_upgrade_received = 1;
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * weechat_plugin_init: initialize Jabber plugin
+ */
+
+int
+weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
+{
+ int i, auto_connect, upgrading;
+
+ weechat_plugin = plugin;
+
+ if (!jabber_config_init ())
+ return WEECHAT_RC_ERROR;
+
+ if (jabber_config_read () < 0)
+ return WEECHAT_RC_ERROR;
+
+ jabber_command_init ();
+
+ jabber_info_init ();
+
+ /* hook some signals */
+ jabber_debug_init ();
+ weechat_hook_signal ("quit", &jabber_signal_quit_cb, NULL);
+ weechat_hook_signal ("upgrade", &jabber_signal_upgrade_cb, NULL);
+ //weechat_hook_signal ("xfer_send_ready", &jabber_server_xfer_send_ready_cb, NULL);
+ //weechat_hook_signal ("xfer_resume_ready", &jabber_server_xfer_resume_ready_cb, NULL);
+ //weechat_hook_signal ("xfer_send_accept_resume", &jabber_server_xfer_send_accept_resume_cb, NULL);
+
+ /* hook completions */
+ jabber_completion_init ();
+
+ jabber_bar_item_init ();
+
+ /* look at arguments */
+ auto_connect = 1;
+ upgrading = 0;
+ for (i = 0; i < argc; i++)
+ {
+ if ((weechat_strcasecmp (argv[i], "-a") == 0)
+ || (weechat_strcasecmp (argv[i], "--no-connect") == 0))
+ {
+ auto_connect = 0;
+ }
+ else if ((weechat_strncasecmp (argv[i], JABBER_PLUGIN_NAME, 3) == 0))
+ {
+ /*
+ if (!jabber_server_alloc_with_url (argv[i]))
+ {
+ weechat_printf (NULL,
+ _("%s%s: error with server from URL "
+ "(\"%s\"), ignored"),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME,
+ argv[i]);
+ }
+ */
+ }
+ else if (weechat_strcasecmp (argv[i], "--upgrade") == 0)
+ {
+ upgrading = 1;
+ }
+ }
+
+ if (upgrading)
+ {
+ if (!jabber_upgrade_load ())
+ {
+ weechat_printf (NULL,
+ _("%s%s: WARNING: some network connections may "
+ "still be opened and not visible, you should "
+ "restart WeeChat now (with /quit)."),
+ weechat_prefix ("error"), JABBER_PLUGIN_NAME);
+ }
+ }
+ else
+ {
+ if (auto_connect)
+ jabber_server_auto_connect ();
+ }
+
+ jabber_hook_timer = weechat_hook_timer (1 * 1000, 0, 0,
+ &jabber_server_timer_cb, NULL);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * weechat_plugin_end: end Jabber plugin
+ */
+
+int
+weechat_plugin_end (struct t_weechat_plugin *plugin)
+{
+ /* make C compiler happy */
+ (void) plugin;
+
+ if (jabber_hook_timer)
+ weechat_unhook (jabber_hook_timer);
+
+ if (jabber_signal_upgrade_received)
+ {
+ jabber_config_write (1);
+ jabber_upgrade_save ();
+ }
+ else
+ {
+ jabber_config_write (0);
+ jabber_server_disconnect_all ();
+ }
+
+ jabber_server_free_all ();
+
+ jabber_config_free ();
+
+ return WEECHAT_RC_OK;
+}
diff --git a/src/plugins/jabber/jabber.h b/src/plugins/jabber/jabber.h
new file mode 100644
index 000000000..b2d260228
--- /dev/null
+++ b/src/plugins/jabber/jabber.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_JABBER_H
+#define __WEECHAT_JABBER_H 1
+
+#define weechat_plugin weechat_jabber_plugin
+#define JABBER_PLUGIN_NAME "jabber"
+
+#define JABBER_GET_SERVER(__buffer) \
+ struct t_weechat_plugin *buffer_plugin = NULL; \
+ struct t_jabber_server *ptr_server = NULL; \
+ buffer_plugin = weechat_buffer_get_pointer (__buffer, "plugin"); \
+ if (buffer_plugin == weechat_jabber_plugin) \
+ jabber_buffer_get_server_muc (__buffer, &ptr_server, NULL);
+
+#define JABBER_GET_SERVER_MUC(__buffer) \
+ struct t_weechat_plugin *buffer_plugin = NULL; \
+ struct t_jabber_server *ptr_server = NULL; \
+ struct t_jabber_muc *ptr_muc = NULL; \
+ buffer_plugin = weechat_buffer_get_pointer (__buffer, "plugin"); \
+ if (buffer_plugin == weechat_jabber_plugin) \
+ { \
+ jabber_buffer_get_server_muc (__buffer, &ptr_server, &ptr_muc); \
+ }
+
+#define JABBER_COLOR_CHAT weechat_color("chat")
+#define JABBER_COLOR_CHAT_CHANNEL weechat_color("chat_channel")
+#define JABBER_COLOR_CHAT_DELIMITERS weechat_color("chat_delimiters")
+#define JABBER_COLOR_CHAT_HOST weechat_color("chat_host")
+#define JABBER_COLOR_CHAT_NICK weechat_color("chat_nick")
+#define JABBER_COLOR_CHAT_NICK_SELF weechat_color("chat_nick_self")
+#define JABBER_COLOR_CHAT_NICK_OTHER weechat_color("chat_nick_other")
+#define JABBER_COLOR_CHAT_SERVER weechat_color("chat_server")
+#define JABBER_COLOR_NICKLIST_PREFIX1 weechat_color("nicklist_prefix1")
+#define JABBER_COLOR_NICKLIST_PREFIX2 weechat_color("nicklist_prefix2")
+#define JABBER_COLOR_NICKLIST_PREFIX3 weechat_color("nicklist_prefix3")
+#define JABBER_COLOR_NICKLIST_PREFIX4 weechat_color("nicklist_prefix4")
+#define JABBER_COLOR_NICKLIST_PREFIX5 weechat_color("nicklist_prefix5")
+#define JABBER_COLOR_BAR_FG weechat_color("bar_fg")
+#define JABBER_COLOR_BAR_BG weechat_color("bar_bg")
+#define JABBER_COLOR_BAR_DELIM weechat_color("bar_delim")
+#define JABBER_COLOR_STATUS_NUMBER weechat_color(weechat_config_string(weechat_config_get("weechat.color.status_number")))
+#define JABBER_COLOR_STATUS_NAME weechat_color(weechat_config_string(weechat_config_get("weechat.color.status_name")))
+#define JABBER_COLOR_MESSAGE_JOIN weechat_color(weechat_config_string(jabber_config_color_message_join))
+#define JABBER_COLOR_MESSAGE_QUIT weechat_color(weechat_config_string(jabber_config_color_message_quit))
+#define JABBER_COLOR_INPUT_NICK weechat_color(weechat_config_string(jabber_config_color_input_nick))
+#define JABBER_COLOR_NICK_IN_SERVER_MESSAGE(nick) \
+ ((nick && weechat_config_boolean(jabber_config_look_color_nicks_in_server_messages)) ? \
+ nick->color : JABBER_COLOR_CHAT_NICK)
+
+extern struct t_weechat_plugin *weechat_jabber_plugin;
+
+#endif /* jabber.h */
diff --git a/src/plugins/logger/logger.c b/src/plugins/logger/logger.c
index 93ec28736..93f9ae62e 100644
--- a/src/plugins/logger/logger.c
+++ b/src/plugins/logger/logger.c
@@ -690,12 +690,12 @@ logger_command_cb (void *data, struct t_gui_buffer *buffer,
}
/*
- * logger_buffer_open_signal_cb: callback for "buffer_open" signal
+ * logger_buffer_opened_signal_cb: callback for "buffer_opened" signal
*/
int
-logger_buffer_open_signal_cb (void *data, const char *signal,
- const char *type_data, void *signal_data)
+logger_buffer_opened_signal_cb (void *data, const char *signal,
+ const char *type_data, void *signal_data)
{
/* make C compiler happy */
(void) data;
@@ -971,7 +971,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
weechat_hook_command ("logger",
N_("logger plugin configuration"),
N_("[list | set level | disable]"),
- N_(" list: show logging status for open buffers\n"
+ N_(" list: show logging status for opened buffers\n"
" set: set logging level on current buffer\n"
" level: level for messages to be logged (0 = "
"logging disabled, 1 = a few messages (most "
@@ -1003,7 +1003,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
logger_start_buffer_all ();
- weechat_hook_signal ("buffer_open", &logger_buffer_open_signal_cb, NULL);
+ weechat_hook_signal ("buffer_opened", &logger_buffer_opened_signal_cb, NULL);
weechat_hook_signal ("buffer_closing", &logger_buffer_closing_signal_cb, NULL);
weechat_hook_signal ("buffer_renamed", &logger_buffer_renamed_signal_cb, NULL);
weechat_hook_signal ("logger_backlog", &logger_backlog_signal_cb, NULL);
diff --git a/src/plugins/notify/notify.c b/src/plugins/notify/notify.c
index 544c35180..1e6ebf535 100644
--- a/src/plugins/notify/notify.c
+++ b/src/plugins/notify/notify.c
@@ -171,7 +171,7 @@ notify_set_buffer (struct t_gui_buffer *buffer)
}
/*
- * notify_set_buffer_all: set notify for all open buffers
+ * notify_set_buffer_all: set notify for all opened buffers
*/
void
@@ -337,12 +337,12 @@ notify_config_write ()
}
/*
- * notify_buffer_open_signal_cb: callback for "buffer_open" signal
+ * notify_buffer_opened_signal_cb: callback for "buffer_opened" signal
*/
int
-notify_buffer_open_signal_cb (void *data, const char *signal,
- const char *type_data, void *signal_data)
+notify_buffer_opened_signal_cb (void *data, const char *signal,
+ const char *type_data, void *signal_data)
{
/* make C compiler happy */
(void) data;
@@ -475,13 +475,13 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
"reset|none|highlight|message|all",
&notify_command_cb, NULL);
- /* callback when a buffer is open */
- weechat_hook_signal ("buffer_open", &notify_buffer_open_signal_cb, NULL);
+ /* callback when a buffer is opened */
+ weechat_hook_signal ("buffer_opened", &notify_buffer_opened_signal_cb, NULL);
/* callback when a config option is changed */
weechat_hook_config ("notify.buffer.*", &notify_config_cb, NULL);
- /* set notify for open buffers */
+ /* set notify for opened buffers */
notify_set_buffer_all ();
return WEECHAT_RC_OK;