aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2007-04-22 13:44:27 -0700
committerWilmer van der Gaast <wilmer@gaast.net>2007-04-22 13:44:27 -0700
commite35d1a121d5fb2da3698fbe4a365fe38d0097665 (patch)
tree390223f2df5aaaebb35c1bb118cbf2fbd69ecab9
parentc737ba70c7b3510ffb6bed8f9373e63b1a150c1b (diff)
Read-only support for Jabber conferences (non-anonymous rooms only).
Just don't use this, you're really not going to like it. :-)
-rw-r--r--protocols/jabber/Makefile2
-rw-r--r--protocols/jabber/conference.c193
-rw-r--r--protocols/jabber/jabber.c22
-rw-r--r--protocols/jabber/jabber.h26
-rw-r--r--protocols/jabber/jabber_util.c35
-rw-r--r--protocols/jabber/message.c13
-rw-r--r--protocols/jabber/presence.c29
-rw-r--r--protocols/jabber/xmltree.c2
-rw-r--r--protocols/msn/sb.c2
-rw-r--r--protocols/nogaim.c21
-rw-r--r--protocols/nogaim.h6
-rw-r--r--protocols/oscar/oscar.c2
-rw-r--r--protocols/yahoo/yahoo.c14
-rw-r--r--root_commands.c15
14 files changed, 341 insertions, 41 deletions
diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile
index 3c9e4949..1d5368b1 100644
--- a/protocols/jabber/Makefile
+++ b/protocols/jabber/Makefile
@@ -9,7 +9,7 @@
-include ../../Makefile.settings
# [SH] Program variables
-objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o
+objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o
CFLAGS += -Wall
LFLAGS += -r
diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c
new file mode 100644
index 00000000..ffc4f844
--- /dev/null
+++ b/protocols/jabber/conference.c
@@ -0,0 +1,193 @@
+/***************************************************************************\
+* *
+* BitlBee - An IRC to IM gateway *
+* Jabber module - Conference rooms *
+* *
+* Copyright 2007 Wilmer van der Gaast <wilmer@gaast.net> *
+* *
+* 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 2 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, write to the Free Software Foundation, Inc., *
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+* *
+\***************************************************************************/
+
+#include "jabber.h"
+
+struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password )
+{
+ struct jabber_chat *jc;
+ struct xt_node *node;
+ struct groupchat *c;
+ char *roomjid;
+
+ roomjid = g_strdup_printf( "%s/%s", room, nick );
+ node = xt_new_node( "x", NULL, NULL );
+ xt_add_attr( node, "xmlns", XMLNS_MUC );
+ node = jabber_make_packet( "presence", NULL, roomjid, node );
+
+ if( !jabber_write_packet( ic, node ) )
+ {
+ g_free( roomjid );
+ xt_free_node( node );
+ return NULL;
+ }
+ xt_free_node( node );
+
+ jc = g_new0( struct jabber_chat, 1 );
+ jc->name = jabber_normalize( room );
+
+ if( ( jc->me = jabber_buddy_add( ic, roomjid ) ) == NULL )
+ {
+ g_free( roomjid );
+ g_free( jc->name );
+ g_free( jc );
+ return NULL;
+ }
+ g_free( roomjid );
+
+ c = imcb_chat_new( ic, room );
+ c->data = jc;
+
+ return c;
+}
+
+int jabber_chat_leave( struct groupchat *c, const char *reason )
+{
+ struct im_connection *ic = c->ic;
+ struct jabber_chat *jc = c->data;
+ struct xt_node *node;
+
+ node = xt_new_node( "x", NULL, NULL );
+ xt_add_attr( node, "xmlns", XMLNS_MUC );
+ node = jabber_make_packet( "presence", "unavailable", jc->me->full_jid, node );
+
+ if( !jabber_write_packet( ic, node ) )
+ {
+ xt_free_node( node );
+ return 0;
+ }
+ xt_free_node( node );
+
+ /* Remove all participants from jc->buddies and clean up our data. */
+ jabber_buddy_remove_bare( ic, jc->name );
+ g_free( jc->name );
+ g_free( jc );
+
+ /* And the generic stuff. */
+ imcb_chat_free( c );
+
+ return 1;
+}
+
+/* Not really the same syntax as the normal pkt_ functions, but this isn't
+ called by the xmltree parser exactly and this way I can add some extra
+ parameters so we won't have to repeat too many things done by the caller
+ already. */
+void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node )
+{
+ struct groupchat *chat;
+ struct xt_node *c;
+ char *type = xt_find_attr( node, "type" );
+ struct jabber_chat *jc;
+ char *s;
+
+ if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL )
+ {
+ /* How could this happen?? We could do kill( self, 11 )
+ now or just wait for the OS to do it. :-) */
+ return;
+ }
+
+ jc = chat->data;
+
+ if( type == NULL && !( bud->flags & JBFLAG_IS_CHATROOM ) )
+ {
+ bud->flags |= JBFLAG_IS_CHATROOM;
+ /* If this one wasn't set yet, this buddy just joined the chat.
+ Slightly hackish way of finding out eh? ;-) */
+
+ /* This is pretty messy... */
+ for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next )
+ if( ( s = xt_find_attr( c, "xmlns" ) ) &&
+ ( strcmp( s, XMLNS_MUC_USER ) == 0 ) )
+ {
+ c = xt_find_node( c->children, "item" );
+ if( ( s = xt_find_attr( c, "jid" ) ) )
+ {
+ /* Yay, found what we need. :-) */
+ bud->orig_jid = g_strdup( s );
+ break;
+ }
+ }
+
+ /* Won't handle this for now. */
+ if( bud->orig_jid == NULL )
+ return;
+
+ s = strchr( bud->orig_jid, '/' );
+ if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */
+ imcb_chat_add_buddy( chat, bud->orig_jid );
+ if( s ) *s = '/';
+ }
+ else if( type ) /* This only gets called if type=="unavailable" */
+ {
+ /* Won't handle this for now. */
+ if( bud->orig_jid == NULL )
+ return;
+ s = strchr( bud->orig_jid, '/' );
+ if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */
+ imcb_chat_remove_buddy( chat, bud->orig_jid, NULL );
+ if( s ) *s = '/';
+
+ if( bud == jc->me )
+ {
+ g_free( jc->name );
+ g_free( jc );
+ imcb_chat_free( chat );
+ }
+ }
+}
+
+void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node )
+{
+ struct xt_node *body = xt_find_node( node->children, "body" );
+ struct groupchat *chat;
+ char *s;
+
+ if( bud == NULL )
+ {
+ s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */
+ if( strchr( s, '/' ) == NULL )
+ /* This is fine, the groupchat itself isn't in jd->buddies. */
+ imcb_log( ic, "System message from groupchat %s: %s", s, body? body->text : "NULL" );
+ else
+ /* This, however, isn't fine! */
+ imcb_log( ic, "Groupchat message from unknown participant %s: %s", s, body ? body->text : "NULL" );
+
+ return;
+ }
+ else if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL )
+ {
+ /* How could this happen?? We could do kill( self, 11 )
+ now or just wait for the OS to do it. :-) */
+ return;
+ }
+
+ if( body && body->text_len > 0 )
+ {
+ s = strchr( bud->orig_jid, '/' );
+ if( s ) *s = 0;
+ imcb_chat_msg( chat, bud->orig_jid, body->text, 0, 0 );
+ if( s ) *s = '/';
+ }
+}
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index edad5dbd..f9473015 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -323,6 +323,24 @@ static void jabber_remove_buddy( struct im_connection *ic, char *who, char *grou
presence_send_request( ic, who, "unsubscribe" );
}
+static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room, char *nick, char *password )
+{
+ if( strchr( room, '@' ) == NULL )
+ imcb_error( ic, "Invalid room name: %s", room );
+ else if( jabber_chat_by_name( ic, room ) )
+ imcb_error( ic, "Already present in chat `%s'", room );
+ else
+ return jabber_chat_join( ic, room, nick, password );
+
+ return NULL;
+}
+
+static void jabber_chat_leave_( struct groupchat *c )
+{
+ if( c )
+ jabber_chat_leave( c, NULL );
+}
+
static void jabber_keepalive( struct im_connection *ic )
{
/* Just any whitespace character is enough as a keepalive for XMPP sessions. */
@@ -395,8 +413,8 @@ void jabber_initmodule()
ret->remove_buddy = jabber_remove_buddy;
// ret->chat_msg = jabber_chat_msg;
// ret->chat_invite = jabber_chat_invite;
-// ret->chat_leave = jabber_chat_leave;
-// ret->chat_open = jabber_chat_open;
+ ret->chat_leave = jabber_chat_leave_;
+ ret->chat_join = jabber_chat_join_;
ret->keepalive = jabber_keepalive;
ret->send_typing = jabber_send_typing;
ret->handle_cmp = g_strcasecmp;
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 42f57ae1..dd771910 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -49,6 +49,8 @@ typedef enum
sure it gets sent only once. */
JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support
XEP85 (typing notification shite). */
+ JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for
+ groupchat state info too. */
} jabber_buddy_flags_t;
#define JABBER_PORT_DEFAULT "5222"
@@ -100,6 +102,9 @@ struct jabber_buddy
char *full_jid;
char *resource;
+ /* Groupchat-only */
+ char *orig_jid;
+
int priority;
struct jabber_away_state *away_state;
char *away_message;
@@ -110,6 +115,13 @@ struct jabber_buddy
struct jabber_buddy *next;
};
+struct jabber_chat
+{
+ int flags;
+ char *name;
+ struct jabber_buddy *me;
+};
+
/* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the
first one should be used, but when storing a packet in the cache, a
"special" kind of ID is assigned to make it easier later to figure out
@@ -133,6 +145,8 @@ struct jabber_buddy
#define XMLNS_VCARD "vcard-temp" /* XEP-0054 */
#define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */
#define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */
+#define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */
+#define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */
/* iq.c */
xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
@@ -163,18 +177,20 @@ void jabber_cache_clean( struct im_connection *ic );
const struct jabber_away_state *jabber_away_state_by_code( char *code );
const struct jabber_away_state *jabber_away_state_by_name( char *name );
void jabber_buddy_ask( struct im_connection *ic, char *handle );
-char *jabber_normalize( char *orig );
+char *jabber_normalize( const char *orig );
typedef enum
{
GET_BUDDY_CREAT = 1, /* Try to create it, if necessary. */
- GET_BUDDY_EXACT = 2, /* Get an exact message (only makes sense with bare JIDs). */
+ GET_BUDDY_EXACT = 2, /* Get an exact match (only makes sense with bare JIDs). */
+ GET_BUDDY_FIRST = 4, /* No selection, simply get the first resource for this JID. */
} get_buddy_flags_t;
struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid );
struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags );
int jabber_buddy_remove( struct im_connection *ic, char *full_jid );
int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid );
+struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name );
extern const struct jabber_away_state jabber_away_state_list[];
@@ -192,4 +208,10 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data );
xt_status sasl_pkt_result( struct xt_node *node, gpointer data );
gboolean sasl_supported( struct im_connection *ic );
+/* conference.c */
+struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password );
+int jabber_chat_leave( struct groupchat *c, const char *reason );
+void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );
+void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );
+
#endif
diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c
index 3c0e71f4..86ddf7bc 100644
--- a/protocols/jabber/jabber_util.c
+++ b/protocols/jabber/jabber_util.c
@@ -47,7 +47,7 @@ char *set_eval_priority( set_t *set, char *value )
convenient, they have one disadvantage: If I would just
call p_s_u() now to send the new prio setting, it would
send the old setting because the set->value gets changed
- when the eval returns a non-NULL value.
+ after the (this) eval returns a non-NULL value.
So now I can choose between implementing post-set
functions next to evals, or just do this little hack: */
@@ -128,7 +128,7 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond,
/* Cache a node/packet for later use. Mainly useful for IQ packets if you need
them when you receive the response. Use this BEFORE sending the packet so
- it'll get a new id= tag, and do NOT free() the packet after writing it! */
+ it'll get a new id= tag, and do NOT free() the packet after sending it! */
void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func )
{
struct jabber_data *jd = ic->proto_data;
@@ -251,7 +251,7 @@ void jabber_buddy_ask( struct im_connection *ic, char *handle )
}
/* Returns a new string. Don't leak it! */
-char *jabber_normalize( char *orig )
+char *jabber_normalize( const char *orig )
{
int len, i;
char *new;
@@ -352,6 +352,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
if( ( s = strchr( jid, '/' ) ) )
{
+ int none_found = 0;
+
*s = 0;
if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
{
@@ -369,8 +371,16 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
break;
}
}
+ else
+ {
+ /* This hack is there to make sure that O_CREAT will
+ work if there's already another resouce present
+ for this JID, even if it's an unknown buddy. This
+ is done to handle conferences properly. */
+ none_found = 1;
+ }
- if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) )
+ if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) )
{
*s = '/';
bud = jabber_buddy_add( ic, jid );
@@ -530,3 +540,20 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ )
return 0;
}
}
+
+struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name )
+{
+ char *normalized = jabber_normalize( name );
+ struct groupchat *ret;
+ struct jabber_chat *jc;
+
+ for( ret = ic->groupchats; ret; ret = ret->next )
+ {
+ jc = ret->data;
+ if( strcmp( normalized, jc->name ) == 0 )
+ break;
+ }
+ g_free( normalized );
+
+ return ret;
+}
diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c
index 19edbdfd..8a4ecaf4 100644
--- a/protocols/jabber/message.c
+++ b/protocols/jabber/message.c
@@ -29,24 +29,29 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
char *from = xt_find_attr( node, "from" );
char *type = xt_find_attr( node, "type" );
struct xt_node *body = xt_find_node( node->children, "body" ), *c;
+ struct jabber_buddy *bud = NULL;
char *s;
+ if( !from )
+ return XT_HANDLED; /* Consider this packet corrupted. */
+
+ bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT );
+
if( type && strcmp( type, "error" ) == 0 )
{
/* Handle type=error packet. */
}
- else if( type && strcmp( type, "groupchat" ) == 0 )
+ else if( type && from && strcmp( type, "groupchat" ) == 0 )
{
- /* TODO! */
+ jabber_chat_pkt_message( ic, bud, node );
}
else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */
{
- struct jabber_buddy *bud = NULL;
GString *fullmsg = g_string_new( "" );
if( ( s = strchr( from, '/' ) ) )
{
- if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) )
+ if( bud )
bud->last_act = time( NULL );
else
*s = 0; /* We need to generate a bare JID now. */
diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c
index ef92740a..096b4fd5 100644
--- a/protocols/jabber/presence.c
+++ b/protocols/jabber/presence.c
@@ -30,11 +30,20 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */
struct xt_node *c;
struct jabber_buddy *bud;
+ int is_chat = 0;
char *s;
if( !from )
return XT_HANDLED;
+ if( ( s = strchr( from, '/' ) ) )
+ {
+ *s = 0;
+ if( jabber_chat_by_name( ic, from ) )
+ is_chat = 1;
+ *s = '/';
+ }
+
if( type == NULL )
{
int is_away = 0;
@@ -71,23 +80,35 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
else
bud->priority = 0;
- if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) )
+ if( is_chat )
+ jabber_chat_pkt_presence( ic, bud, node );
+ else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) )
imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
bud->away_message );
}
else if( strcmp( type, "unavailable" ) == 0 )
{
- if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL )
+ if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) == NULL )
{
if( set_getbool( &ic->irc->set, "debug" ) )
imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from );
return XT_HANDLED;
}
+ /* Handle this before we delete the JID. */
+ if( is_chat )
+ {
+ jabber_chat_pkt_presence( ic, bud, node );
+ }
+
jabber_buddy_remove( ic, from );
- if( ( s = strchr( from, '/' ) ) )
+ if( is_chat )
+ {
+ /* Nothing else to do for now? */
+ }
+ else if( ( s = strchr( from, '/' ) ) )
{
*s = 0;
@@ -95,6 +116,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
available anymore. */
if( jabber_buddy_by_jid( ic, from, 0 ) == NULL )
imcb_buddy_status( ic, from, 0, NULL, NULL );
+ /* FIXME: If this resource was not away and another resource is,
+ we should definitely send an update here. */
*s = '/';
}
diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c
index 7a165a1e..c8bef362 100644
--- a/protocols/jabber/xmltree.c
+++ b/protocols/jabber/xmltree.c
@@ -187,6 +187,8 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth )
/* If there's no parent, the handler should mention <root> as a parent. */
g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
{
+ xt_print( node );
+
st = xt->handlers[i].func( node, xt->data );
if( st == XT_ABORT )
diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c
index 1693cb95..cb9e2cab 100644
--- a/protocols/msn/sb.c
+++ b/protocols/msn/sb.c
@@ -231,7 +231,7 @@ void msn_sb_destroy( struct msn_switchboard *sb )
if( sb->chat )
{
- imcb_chat_removed( sb->chat );
+ imcb_chat_free( sb->chat );
}
if( sb->handler )
diff --git a/protocols/nogaim.c b/protocols/nogaim.c
index a70d6eca..f3dbb0b8 100644
--- a/protocols/nogaim.c
+++ b/protocols/nogaim.c
@@ -553,8 +553,8 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,
irc_kill( ic->irc, u );
u->online = 0;
- /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */
- for( c = ic->conversations; c; c = c->next )
+ /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
+ for( c = ic->groupchats; c; c = c->next )
remove_chat_buddy_silent( c, (char*) handle );
}
@@ -684,10 +684,10 @@ void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags
}
}
-void imcb_chat_removed( struct groupchat *c )
+void imcb_chat_free( struct groupchat *c )
{
struct im_connection *ic = c->ic;
- struct groupchat *l = NULL;
+ struct groupchat *l;
GList *ir;
if( set_getbool( &ic->irc->set, "debug" ) )
@@ -707,10 +707,13 @@ void imcb_chat_removed( struct groupchat *c )
/* irc_part( ic->irc, u, c->channel ); */
}
+ /* Find the previous chat in the linked list. */
+ for( l = ic->groupchats; l && l->next != c; l = l->next );
+
if( l )
l->next = c->next;
else
- ic->conversations = c->next;
+ ic->groupchats = c->next;
for( ir = c->in_room; ir; ir = ir->next )
g_free( ir->data );
@@ -748,13 +751,13 @@ struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle )
/* This one just creates the conversation structure, user won't see anything yet */
- if( ic->conversations )
+ if( ic->groupchats )
{
- for( c = ic->conversations; c->next; c = c->next );
+ for( c = ic->groupchats; c->next; c = c->next );
c = c->next = g_new0( struct groupchat, 1 );
}
else
- ic->conversations = c = g_new0( struct groupchat, 1 );
+ ic->groupchats = c = g_new0( struct groupchat, 1 );
c->ic = ic;
c->title = g_strdup( handle );
@@ -862,7 +865,7 @@ struct groupchat *chat_by_channel( char *channel )
for( l = connections; l; l = l->next )
{
ic = l->data;
- for( c = ic->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next );
+ for( c = ic->groupchats; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next );
if( c )
return c;
}
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index 59f9e870..b26cf73e 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -90,17 +90,15 @@ struct im_connection
/* BitlBee */
irc_t *irc;
- struct groupchat *conversations;
+ struct groupchat *groupchats;
};
struct groupchat {
struct im_connection *ic;
- /* stuff used just for chat */
GList *in_room;
GList *ignored;
- /* BitlBee */
struct groupchat *next;
char *channel;
char *title;
@@ -207,7 +205,7 @@ G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, char
G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle );
G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason );
G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at );
-G_MODULE_EXPORT void imcb_chat_removed( struct groupchat *c );
+G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c );
struct groupchat *chat_by_channel( char *channel );
/* Actions, or whatever. */
diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c
index 0c175df6..b72c683a 100644
--- a/protocols/oscar/oscar.c
+++ b/protocols/oscar/oscar.c
@@ -2512,7 +2512,7 @@ void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc)
struct oscar_data *od = (struct oscar_data *)ic->proto_data;
/* Notify the conversation window that we've left the chat */
- imcb_chat_removed(cc->cnv);
+ imcb_chat_free(cc->cnv);
/* Destroy the chat_connection */
od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c
index 69fc29bb..28a72877 100644
--- a/protocols/yahoo/yahoo.c
+++ b/protocols/yahoo/yahoo.c
@@ -144,8 +144,8 @@ static void byahoo_logout( struct im_connection *ic )
struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
GSList *l;
- while( ic->conversations )
- imcb_chat_removed( ic->conversations );
+ while( ic->groupchats )
+ imcb_chat_free( ic->groupchats );
for( l = yd->buddygroups; l; l = l->next )
{
@@ -317,7 +317,7 @@ static void byahoo_chat_leave( struct groupchat *c )
struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title );
- imcb_chat_removed( c );
+ imcb_chat_free( c );
}
static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who )
@@ -797,7 +797,7 @@ static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv )
static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv )
{
yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" );
- imcb_chat_removed( inv->c );
+ imcb_chat_free( inv->c );
g_free( inv->name );
g_free( inv );
}
@@ -840,7 +840,7 @@ void ext_yahoo_conf_userjoin( int id, const char *ignored, const char *who, cons
struct im_connection *ic = byahoo_get_ic_by_id( id );
struct groupchat *c;
- for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next );
+ for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
if( c )
imcb_chat_add_buddy( c, (char*) who );
@@ -852,7 +852,7 @@ void ext_yahoo_conf_userleave( int id, const char *ignored, const char *who, con
struct im_connection *ic = byahoo_get_ic_by_id( id );
struct groupchat *c;
- for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next );
+ for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
if( c )
imcb_chat_remove_buddy( c, (char*) who, "" );
@@ -864,7 +864,7 @@ void ext_yahoo_conf_message( int id, const char *ignored, const char *who, const
char *m = byahoo_strip( msg );
struct groupchat *c;
- for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next );
+ for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
if( c )
imcb_chat_msg( c, (char*) who, (char*) m, 0, 0 );
diff --git a/root_commands.c b/root_commands.c
index a7582936..2b57fb4f 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -923,12 +923,21 @@ static void cmd_join_chat( irc_t *irc, char **cmd )
}
if( cmd[3] && cmd[4] )
nick = cmd[4];
+ else
+ nick = irc->nick;
if( cmd[3] && cmd[4] && cmd[5] )
password = cmd[5];
- c = a->prpl->chat_join( ic, chat, nick, password );
-
- g_free( channel );
+ if( ( c = a->prpl->chat_join( ic, chat, nick, password ) ) )
+ {
+ g_free( c->channel );
+ c->channel = channel;
+ }
+ else
+ {
+ irc_usermsg( irc, "Tried to join chat, not sure if this was successful" );
+ g_free( channel );
+ }
}
const command_t commands[] = {