diff options
-rw-r--r-- | protocols/jabber/Makefile | 2 | ||||
-rw-r--r-- | protocols/jabber/conference.c | 193 | ||||
-rw-r--r-- | protocols/jabber/jabber.c | 22 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 26 | ||||
-rw-r--r-- | protocols/jabber/jabber_util.c | 35 | ||||
-rw-r--r-- | protocols/jabber/message.c | 13 | ||||
-rw-r--r-- | protocols/jabber/presence.c | 29 | ||||
-rw-r--r-- | protocols/jabber/xmltree.c | 2 | ||||
-rw-r--r-- | protocols/msn/sb.c | 2 | ||||
-rw-r--r-- | protocols/nogaim.c | 21 | ||||
-rw-r--r-- | protocols/nogaim.h | 6 | ||||
-rw-r--r-- | protocols/oscar/oscar.c | 2 | ||||
-rw-r--r-- | protocols/yahoo/yahoo.c | 14 | ||||
-rw-r--r-- | root_commands.c | 15 |
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[] = { |