source: protocols/jabber/presence.c @ a42169b

Last change on this file since a42169b was 7e68015, checked in by dequis <dx@…>, at 2016-01-21T06:15:44Z

Revert "hipchat: Implement their own variant of self-messages [...]"

This reverts commit d11ccbf6ea94264bde8b0f525c4bbedf50de0174.

After thinking about this long enough I've decided this is a bad idea,
and better wait for the hipchat server to support carbons.

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