source: protocols/jabber/presence.c @ 82135c7

Last change on this file since 82135c7 was 1baaef8, checked in by Wilmer van der Gaast <wilmer@…>, at 2007-07-30T19:12:06Z

Added jabber_error_parse() and using it for both stream- and stanza
(only presence so far) errors.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  Jabber module - Handling of presence (tags), etc                         *
5*                                                                           *
6*  Copyright 2006 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
26xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
27{
28        struct im_connection *ic = data;
29        char *from = xt_find_attr( node, "from" );
30        char *type = xt_find_attr( node, "type" );      /* NULL should mean the person is online. */
31        struct xt_node *c;
32        struct jabber_buddy *bud;
33        int is_chat = 0, is_away = 0;
34        char *s;
35       
36        if( !from )
37                return XT_HANDLED;
38       
39        if( ( s = strchr( from, '/' ) ) )
40        {
41                *s = 0;
42                if( jabber_chat_by_name( ic, from ) )
43                        is_chat = 1;
44                *s = '/';
45        }
46       
47        if( type == NULL )
48        {
49                if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) )
50                {
51                        if( set_getbool( &ic->irc->set, "debug" ) )
52                                imcb_log( ic, "WARNING: Could not handle presence information from JID: %s", from );
53                        return XT_HANDLED;
54                }
55               
56                g_free( bud->away_message );
57                if( ( c = xt_find_node( node->children, "status" ) ) && c->text_len > 0 )
58                        bud->away_message = g_strdup( c->text );
59                else
60                        bud->away_message = NULL;
61               
62                if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 )
63                {
64                        bud->away_state = (void*) jabber_away_state_by_code( c->text );
65                        if( strcmp( c->text, "chat" ) != 0 )
66                                is_away = OPT_AWAY;
67                }
68                else
69                {
70                        bud->away_state = NULL;
71                        /* Let's only set last_act if there's *no* away state,
72                           since it could be some auto-away thingy. */
73                        bud->last_act = time( NULL );
74                }
75               
76                if( ( c = xt_find_node( node->children, "priority" ) ) && c->text_len > 0 )
77                        bud->priority = atoi( c->text );
78                else
79                        bud->priority = 0;
80               
81                if( is_chat )
82                        jabber_chat_pkt_presence( ic, bud, node );
83                else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) )
84                        imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
85                                           ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
86                                           bud->away_message );
87        }
88        else if( strcmp( type, "unavailable" ) == 0 )
89        {
90                if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) == NULL )
91                {
92                        if( set_getbool( &ic->irc->set, "debug" ) )
93                                imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from );
94                        return XT_HANDLED;
95                }
96               
97                /* Handle this before we delete the JID. */
98                if( is_chat )
99                {
100                        jabber_chat_pkt_presence( ic, bud, node );
101                }
102               
103                jabber_buddy_remove( ic, from );
104               
105                if( is_chat )
106                {
107                        /* Nothing else to do for now? */
108                }
109                else if( ( s = strchr( from, '/' ) ) )
110                {
111                        *s = 0;
112               
113                        /* If another resource is still available, send its presence
114                           information. */
115                        if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) )
116                        {
117                                if( bud->away_state && ( *bud->away_state->code == 0 ||
118                                    strcmp( bud->away_state->code, "chat" ) == 0 ) )
119                                        is_away = OPT_AWAY;
120                               
121                                imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
122                                                   ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
123                                                   bud->away_message );
124                        }
125                        else
126                        {
127                                /* Otherwise, count him/her as offline now. */
128                                imcb_buddy_status( ic, from, 0, NULL, NULL );
129                        }
130                       
131                        *s = '/';
132                }
133                else
134                {
135                        imcb_buddy_status( ic, from, 0, NULL, NULL );
136                }
137        }
138        else if( strcmp( type, "subscribe" ) == 0 )
139        {
140                jabber_buddy_ask( ic, from );
141        }
142        else if( strcmp( type, "subscribed" ) == 0 )
143        {
144                /* Not sure about this one, actually... */
145                imcb_log( ic, "%s just accepted your authorization request", from );
146        }
147        else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 )
148        {
149                /* Do nothing here. Plenty of control freaks or over-curious
150                   souls get excited when they can see who still has them in
151                   their buddy list and who finally removed them. Somehow I
152                   got the impression that those are the people who get
153                   removed from many buddy lists for "some" reason...
154                   
155                   If you're one of those people, this is your chance to write
156                   your first line of code in C... */
157        }
158        else if( strcmp( type, "error" ) == 0 )
159        {
160                struct jabber_error *err;
161               
162                if( ( c = xt_find_node( node->children, "error" ) ) )
163                {
164                        err = jabber_error_parse( c, XMLNS_STANZA_ERROR );
165                        imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name,
166                                    err->code, err->text ? ": " : "",
167                                    err->text ? err->text : "" );
168                        jabber_error_free( err );
169                }
170                /* What else to do with it? */
171        }
172        else
173        {
174                printf( "Received PRES from %s:\n", from );
175                xt_print( node );
176        }
177       
178        return XT_HANDLED;
179}
180
181/* Whenever presence information is updated, call this function to inform the
182   server. */
183int presence_send_update( struct im_connection *ic )
184{
185        struct jabber_data *jd = ic->proto_data;
186        struct xt_node *node;
187        char *show = jd->away_state->code;
188        char *status = jd->away_message;
189        struct groupchat *c;
190        int st;
191       
192        node = jabber_make_packet( "presence", NULL, NULL, NULL );
193        xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) );
194        if( show && *show )
195                xt_add_child( node, xt_new_node( "show", show, NULL ) );
196        if( status )
197                xt_add_child( node, xt_new_node( "status", status, NULL ) );
198       
199        st = jabber_write_packet( ic, node );
200       
201        /* Have to send this update to all groupchats too, the server won't
202           do this automatically. */
203        for( c = ic->groupchats; c && st; c = c->next )
204        {
205                struct jabber_chat *jc = c->data;
206               
207                xt_add_attr( node, "to", jc->my_full_jid );
208                st = jabber_write_packet( ic, node );
209        }
210       
211        xt_free_node( node );
212        return st;
213}
214
215/* Send a subscribe/unsubscribe request to a buddy. */
216int presence_send_request( struct im_connection *ic, char *handle, char *request )
217{
218        struct xt_node *node;
219        int st;
220       
221        node = jabber_make_packet( "presence", NULL, NULL, NULL );
222        xt_add_attr( node, "to", handle );
223        xt_add_attr( node, "type", request );
224       
225        st = jabber_write_packet( ic, node );
226       
227        xt_free_node( node );
228        return st;
229}
Note: See TracBrowser for help on using the repository browser.