source: protocols/jabber/presence.c @ 60e4df3

Last change on this file since 60e4df3 was 840bba8, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-03-06T14:50:52Z

The Jabber part of the change. Also made representation of not-away a bit
more consistent. Except for free-for-chat, which is nuts anyway.

  • Property mode set to 100644
File size: 8.5 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, *cap;
32        struct jabber_buddy *bud, *send_presence = NULL;
33        int is_chat = 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_jid( 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                        /*
52                        imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from );
53                        */
54                        return XT_HANDLED;
55                }
56               
57                g_free( bud->away_message );
58                if( ( c = xt_find_node( node->children, "status" ) ) && c->text_len > 0 )
59                        bud->away_message = g_strdup( c->text );
60                else
61                        bud->away_message = NULL;
62               
63                if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 )
64                {
65                        bud->away_state = (void*) jabber_away_state_by_code( c->text );
66                }
67                else
68                {
69                        bud->away_state = NULL;
70                        /* Let's only set last_act if there's *no* away state,
71                           since it could be some auto-away thingy. */
72                        bud->last_act = time( NULL );
73                }
74               
75                if( ( c = xt_find_node( node->children, "priority" ) ) && c->text_len > 0 )
76                        bud->priority = atoi( c->text );
77                else
78                        bud->priority = 0;
79               
80                if( bud && ( cap = xt_find_node( node->children, "c" ) ) &&
81                    ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 )
82                {
83                        /* This <presence> stanza includes an XEP-0115
84                           capabilities part. Not too interesting, but we can
85                           see if it has an ext= attribute. */
86                        s = xt_find_attr( cap, "ext" );
87                        if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) )
88                                bud->flags |= JBFLAG_DOES_XEP85;
89                       
90                        /* This field can contain more information like xhtml
91                           support, but we don't support that ourselves.
92                           Officially the ext= tag was deprecated, but enough
93                           clients do send it.
94                           
95                           (I'm aware that this is not the right way to use
96                           this field.) See for an explanation of ext=:
97                           http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/
98                }
99               
100                if( is_chat )
101                        jabber_chat_pkt_presence( ic, bud, node );
102                else
103                        send_presence = jabber_buddy_by_jid( ic, bud->bare_jid, 0 );
104        }
105        else if( strcmp( type, "unavailable" ) == 0 )
106        {
107                if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
108                {
109                        /*
110                        imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from );
111                        */
112                        return XT_HANDLED;
113                }
114               
115                /* Handle this before we delete the JID. */
116                if( is_chat )
117                {
118                        jabber_chat_pkt_presence( ic, bud, node );
119                }
120               
121                if( strchr( from, '/' ) == NULL )
122                        /* Sometimes servers send a type="unavailable" from a
123                           bare JID, which should mean that suddenly all
124                           resources for this JID disappeared. */
125                        jabber_buddy_remove_bare( ic, from );
126                else
127                        jabber_buddy_remove( ic, from );
128               
129                if( is_chat )
130                {
131                        /* Nothing else to do for now? */
132                }
133                else if( ( s = strchr( from, '/' ) ) )
134                {
135                        *s = 0;
136               
137                        /* If another resource is still available, send its presence
138                           information. */
139                        if( ( send_presence = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
140                        {
141                                /* Otherwise, count him/her as offline now. */
142                                imcb_buddy_status( ic, from, 0, NULL, NULL );
143                        }
144                       
145                        *s = '/';
146                }
147                else
148                {
149                        imcb_buddy_status( ic, from, 0, NULL, NULL );
150                }
151        }
152        else if( strcmp( type, "subscribe" ) == 0 )
153        {
154                jabber_buddy_ask( ic, from );
155        }
156        else if( strcmp( type, "subscribed" ) == 0 )
157        {
158                /* Not sure about this one, actually... */
159                imcb_log( ic, "%s just accepted your authorization request", from );
160        }
161        else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 )
162        {
163                /* Do nothing here. Plenty of control freaks or over-curious
164                   souls get excited when they can see who still has them in
165                   their buddy list and who finally removed them. Somehow I
166                   got the impression that those are the people who get
167                   removed from many buddy lists for "some" reason...
168                   
169                   If you're one of those people, this is your chance to write
170                   your first line of code in C... */
171        }
172        else if( strcmp( type, "error" ) == 0 )
173        {
174                return jabber_cache_handle_packet( ic, node );
175               
176                /*
177                struct jabber_error *err;
178                if( ( c = xt_find_node( node->children, "error" ) ) )
179                {
180                        err = jabber_error_parse( c, XMLNS_STANZA_ERROR );
181                        imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name,
182                                    err->code, err->text ? ": " : "",
183                                    err->text ? err->text : "" );
184                        jabber_error_free( err );
185                } */
186        }
187
188        if( send_presence )
189        {
190                int is_away = 0;
191
192                if( send_presence->away_state &&
193                    strcmp( send_presence->away_state->code, "chat" ) != 0 )
194                        is_away = OPT_AWAY;
195
196                imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away,
197                                   is_away ? send_presence->away_state->full_name : NULL,
198                                   send_presence->away_message );
199        }
200       
201        return XT_HANDLED;
202}
203
204/* Whenever presence information is updated, call this function to inform the
205   server. */
206int presence_send_update( struct im_connection *ic )
207{
208        struct jabber_data *jd = ic->proto_data;
209        struct xt_node *node, *cap;
210        struct groupchat *c;
211        int st;
212       
213        node = jabber_make_packet( "presence", NULL, NULL, NULL );
214        xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) );
215        if( jd->away_state )
216                xt_add_child( node, xt_new_node( "show", jd->away_state->code, NULL ) );
217        if( jd->away_message )
218                xt_add_child( node, xt_new_node( "status", jd->away_message, NULL ) );
219       
220        /* This makes the packet slightly bigger, but clients interested in
221           capabilities can now cache the discovery info. This reduces the
222           usual post-login iq-flood. See XEP-0115. At least libpurple and
223           Trillian seem to do this right. */
224        cap = xt_new_node( "c", NULL, NULL );
225        xt_add_attr( cap, "xmlns", XMLNS_CAPS );
226        xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" );
227        xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */
228        xt_add_child( node, cap );
229       
230        st = jabber_write_packet( ic, node );
231       
232        /* Have to send this update to all groupchats too, the server won't
233           do this automatically. */
234        for( c = ic->groupchats; c && st; c = c->next )
235        {
236                struct jabber_chat *jc = c->data;
237               
238                xt_add_attr( node, "to", jc->my_full_jid );
239                st = jabber_write_packet( ic, node );
240        }
241       
242        xt_free_node( node );
243        return st;
244}
245
246/* Send a subscribe/unsubscribe request to a buddy. */
247int presence_send_request( struct im_connection *ic, char *handle, char *request )
248{
249        struct xt_node *node;
250        int st;
251       
252        node = jabber_make_packet( "presence", NULL, NULL, NULL );
253        xt_add_attr( node, "to", handle );
254        xt_add_attr( node, "type", request );
255       
256        st = jabber_write_packet( ic, node );
257       
258        xt_free_node( node );
259        return st;
260}
Note: See TracBrowser for help on using the repository browser.