source: protocols/jabber/conference.c @ eda54e4

Last change on this file since eda54e4 was 85023c6, checked in by Wilmer van der Gaast <wilmer@…>, at 2007-07-15T15:47:34Z

Added imcb_clean_handle() to sanitize handles properly (without putting
IRC-specific stuff into the Jabber module). Only using this in the MUC
code for now because this only works if the IM module can somehow convert
the cleaned up handle back to the original one.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  Jabber module - Conference rooms                                         *
5*                                                                           *
6*  Copyright 2007 Wilmer van der Gaast <wilmer@gaast.net>                   *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
12*                                                                           *
13*  This program is distributed in the hope that it will be useful,          *
14*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
15*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
16*  GNU General Public License for more details.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24#include "jabber.h"
25
26struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password )
27{
28        struct jabber_chat *jc;
29        struct xt_node *node;
30        struct groupchat *c;
31        char *roomjid;
32       
33        roomjid = g_strdup_printf( "%s/%s", room, nick );
34        node = xt_new_node( "x", NULL, NULL );
35        xt_add_attr( node, "xmlns", XMLNS_MUC );
36        node = jabber_make_packet( "presence", NULL, roomjid, node );
37       
38        if( !jabber_write_packet( ic, node ) )
39        {
40                g_free( roomjid );
41                xt_free_node( node );
42                return NULL;
43        }
44        xt_free_node( node );
45       
46        jc = g_new0( struct jabber_chat, 1 );
47        jc->name = jabber_normalize( room );
48       
49        if( ( jc->me = jabber_buddy_add( ic, roomjid ) ) == NULL )
50        {
51                g_free( roomjid );
52                g_free( jc->name );
53                g_free( jc );
54                return NULL;
55        }
56       
57        /* roomjid isn't normalized yet, and we need an original version
58           of the nick to send a proper presence update. */
59        jc->my_full_jid = roomjid;
60       
61        c = imcb_chat_new( ic, room );
62        c->data = jc;
63       
64        return c;
65}
66
67void jabber_chat_free( struct groupchat *c )
68{
69        struct jabber_chat *jc = c->data;
70       
71        jabber_buddy_remove_bare( c->ic, jc->name );
72       
73        g_free( jc->my_full_jid );
74        g_free( jc->name );
75        g_free( jc );
76       
77        imcb_chat_free( c );
78}
79
80int jabber_chat_msg( struct groupchat *c, char *message, int flags )
81{
82        struct im_connection *ic = c->ic;
83        struct jabber_chat *jc = c->data;
84        struct xt_node *node;
85       
86        node = xt_new_node( "body", message, NULL );
87        node = jabber_make_packet( "message", "groupchat", jc->name, node );
88       
89        if( !jabber_write_packet( ic, node ) )
90        {
91                xt_free_node( node );
92                return 0;
93        }
94        xt_free_node( node );
95       
96        return 1;
97}
98
99int jabber_chat_leave( struct groupchat *c, const char *reason )
100{
101        struct im_connection *ic = c->ic;
102        struct jabber_chat *jc = c->data;
103        struct xt_node *node;
104       
105        node = xt_new_node( "x", NULL, NULL );
106        xt_add_attr( node, "xmlns", XMLNS_MUC );
107        node = jabber_make_packet( "presence", "unavailable", jc->my_full_jid, node );
108       
109        if( !jabber_write_packet( ic, node ) )
110        {
111                xt_free_node( node );
112                return 0;
113        }
114        xt_free_node( node );
115       
116        return 1;
117}
118
119/* Not really the same syntax as the normal pkt_ functions, but this isn't
120   called by the xmltree parser directly and this way I can add some extra
121   parameters so we won't have to repeat too many things done by the caller
122   already. */
123void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node )
124{
125        struct groupchat *chat;
126        struct xt_node *c;
127        char *type = xt_find_attr( node, "type" );
128        struct jabber_chat *jc;
129        char *s;
130       
131        if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL )
132        {
133                /* How could this happen?? We could do kill( self, 11 )
134                   now or just wait for the OS to do it. :-) */
135                return;
136        }
137       
138        jc = chat->data;
139       
140        if( type == NULL && !( bud->flags & JBFLAG_IS_CHATROOM ) )
141        {
142                bud->flags |= JBFLAG_IS_CHATROOM;
143                /* If this one wasn't set yet, this buddy just joined the chat.
144                   Slightly hackish way of finding out eh? ;-) */
145               
146                /* This is pretty messy... Here it sets ext_jid to the real
147                   JID of the participant. Works for non-anonymized channels.
148                   Might break if someone joins a chat twice, though. */
149                for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next )
150                        if( ( s = xt_find_attr( c, "xmlns" ) ) &&
151                            ( strcmp( s, XMLNS_MUC_USER ) == 0 ) )
152                        {
153                                c = xt_find_node( c->children, "item" );
154                                if( ( s = xt_find_attr( c, "jid" ) ) )
155                                {
156                                        /* Yay, found what we need. :-) */
157                                        bud->ext_jid = jabber_normalize( s );
158                                        break;
159                                }
160                        }
161               
162                /* Make up some other handle, if necessary. */
163                if( bud->ext_jid == NULL )
164                {
165                        if( bud == jc->me )
166                        {
167                                bud->ext_jid = jabber_normalize( ic->acc->user );
168                        }
169                        else
170                        {
171                                int i;
172                               
173                                /* Don't want the nick to be at the end, so let's
174                                   think of some slightly different notation to use
175                                   for anonymous groupchat participants in BitlBee. */
176                                bud->ext_jid = g_strdup_printf( "%s=%s", bud->resource, bud->bare_jid );
177                               
178                                /* And strip any unwanted characters. */
179                                for( i = 0; bud->resource[i]; i ++ )
180                                        if( bud->ext_jid[i] == '=' || bud->ext_jid[i] == '@' )
181                                                bud->ext_jid[i] = '_';
182                               
183                                /* Some program-specific restrictions. */
184                                imcb_clean_handle( ic, bud->ext_jid );
185                        }
186                        bud->flags |= JBFLAG_IS_ANONYMOUS;
187                }
188               
189                if( bud != jc->me )
190                {
191                        imcb_add_buddy( ic, bud->ext_jid, NULL );
192                        imcb_buddy_nick_hint( ic, bud->ext_jid, bud->resource );
193                }
194               
195                s = strchr( bud->ext_jid, '/' );
196                if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */
197                imcb_chat_add_buddy( chat, bud->ext_jid );
198                if( s ) *s = '/';
199        }
200        else if( type ) /* type can only be NULL or "unavailable" in this function */
201        {
202                s = strchr( bud->ext_jid, '/' );
203                if( s ) *s = 0;
204                imcb_chat_remove_buddy( chat, bud->ext_jid, NULL );
205                if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS )
206                        imcb_remove_buddy( ic, bud->ext_jid, NULL );
207                if( s ) *s = '/';
208               
209                if( bud == jc->me )
210                        jabber_chat_free( chat );
211        }
212}
213
214void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node )
215{
216        struct xt_node *body = xt_find_node( node->children, "body" );
217        struct groupchat *chat;
218        char *s;
219       
220        if( bud == NULL )
221        {
222                s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */
223                if( strchr( s, '/' ) == NULL )
224                        /* This is fine, the groupchat itself isn't in jd->buddies. */
225                        imcb_log( ic, "System message from groupchat %s: %s", s, body? body->text : "NULL" );
226                else
227                        /* This, however, isn't fine! */
228                        imcb_log( ic, "Groupchat message from unknown participant %s: %s", s, body ? body->text : "NULL" );
229               
230                return;
231        }
232        else if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL )
233        {
234                /* How could this happen?? We could do kill( self, 11 )
235                   now or just wait for the OS to do it. :-) */
236                return;
237        }
238       
239        if( body && body->text_len > 0 )
240        {
241                s = strchr( bud->ext_jid, '/' );
242                if( s ) *s = 0;
243                imcb_chat_msg( chat, bud->ext_jid, body->text, 0, jabber_get_timestamp( node ) );
244                if( s ) *s = '/';
245        }
246}
Note: See TracBrowser for help on using the repository browser.