source: protocols/jabber/presence.c @ ec5e57d

Last change on this file since ec5e57d was 71d45c2, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-12-14T13:39:02Z

Dropping warnings about unknown JIDs since they're spammy (mostly show up
when the user logs in from mulitple locations) and the irc->debug setting
shouldn't be read from inside the IM modules.

  • Property mode set to 100644
File size: 8.6 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 && !( *send_presence->away_state->code == 0 ||
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 ) ?
198                                   send_presence->away_state->full_name : NULL,
199                                   send_presence->away_message );
200        }
201       
202        return XT_HANDLED;
203}
204
205/* Whenever presence information is updated, call this function to inform the
206   server. */
207int presence_send_update( struct im_connection *ic )
208{
209        struct jabber_data *jd = ic->proto_data;
210        struct xt_node *node, *cap;
211        char *show = jd->away_state->code;
212        char *status = jd->away_message;
213        struct groupchat *c;
214        int st;
215       
216        node = jabber_make_packet( "presence", NULL, NULL, NULL );
217        xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) );
218        if( show && *show )
219                xt_add_child( node, xt_new_node( "show", show, NULL ) );
220        if( status )
221                xt_add_child( node, xt_new_node( "status", status, NULL ) );
222       
223        /* This makes the packet slightly bigger, but clients interested in
224           capabilities can now cache the discovery info. This reduces the
225           usual post-login iq-flood. See XEP-0115. At least libpurple and
226           Trillian seem to do this right. */
227        cap = xt_new_node( "c", NULL, NULL );
228        xt_add_attr( cap, "xmlns", XMLNS_CAPS );
229        xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" );
230        xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */
231        xt_add_child( node, cap );
232       
233        st = jabber_write_packet( ic, node );
234       
235        /* Have to send this update to all groupchats too, the server won't
236           do this automatically. */
237        for( c = ic->groupchats; c && st; c = c->next )
238        {
239                struct jabber_chat *jc = c->data;
240               
241                xt_add_attr( node, "to", jc->my_full_jid );
242                st = jabber_write_packet( ic, node );
243        }
244       
245        xt_free_node( node );
246        return st;
247}
248
249/* Send a subscribe/unsubscribe request to a buddy. */
250int presence_send_request( struct im_connection *ic, char *handle, char *request )
251{
252        struct xt_node *node;
253        int st;
254       
255        node = jabber_make_packet( "presence", NULL, NULL, NULL );
256        xt_add_attr( node, "to", handle );
257        xt_add_attr( node, "type", request );
258       
259        st = jabber_write_packet( ic, node );
260       
261        xt_free_node( node );
262        return st;
263}
Note: See TracBrowser for help on using the repository browser.