1 /***************************************************************************\
2 * *
3 * BitlBee - An IRC to IM gateway *
4 * Jabber module - HipChat specific functions *
5 * *
6 * Copyright 2015 Xamarin Inc *
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
hipchat_handle_success(struct im_connection * ic,struct xt_node * node)26 xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node)
27 {
28 struct jabber_data *jd = ic->proto_data;
29 char *sep, *jid;
30
31 jid = xt_find_attr(node, "jid");
32
33 sep = strchr(jid, '/');
34 if (sep) {
35 *sep = '\0';
36 }
37
38 jabber_set_me(ic, jid);
39 imcb_log(ic, "Setting Hipchat JID to %s", jid);
40
41 if (sep) {
42 *sep = '/';
43 }
44
45 jd->muc_host = g_strdup(xt_find_attr(node, "muc_host"));
46
47 /* Hipchat's auth doesn't expect a restart here */
48 jd->flags &= ~JFLAG_STREAM_RESTART;
49
50 if (!jabber_get_roster(ic) ||
51 !jabber_iq_disco_server(ic) ||
52 !jabber_get_hipchat_profile(ic)) {
53 return XT_ABORT;
54 }
55
56 return XT_HANDLED;
57 }
58
jabber_get_hipchat_profile(struct im_connection * ic)59 int jabber_get_hipchat_profile(struct im_connection *ic)
60 {
61 struct jabber_data *jd = ic->proto_data;
62 struct xt_node *node;
63 int st;
64
65 imcb_log(ic, "Fetching hipchat profile for %s", jd->me);
66
67 node = xt_new_node("query", NULL, NULL);
68 xt_add_attr(node, "xmlns", XMLNS_HIPCHAT_PROFILE);
69 node = jabber_make_packet("iq", "get", jd->me, node);
70
71 jabber_cache_add(ic, node, jabber_parse_hipchat_profile);
72 st = jabber_write_packet(ic, node);
73
74 return st;
75 }
76
jabber_parse_hipchat_profile(struct im_connection * ic,struct xt_node * node,struct xt_node * orig)77 xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)
78 {
79 struct xt_node *query, *name_node;
80
81 if (!(query = xt_find_node(node->children, "query"))) {
82 imcb_log(ic, "Warning: Received NULL profile packet");
83 return XT_ABORT;
84 }
85
86 name_node = xt_find_node(query->children, "name");
87 if (!name_node) {
88 imcb_log(ic, "Warning: Can't find real name in profile. Joining groupchats will not be possible.");
89 return XT_ABORT;
90 }
91
92 set_setstr(&ic->acc->set, "display_name", name_node->text);
93 return XT_HANDLED;
94
95 }
96
97 /* Returns a newly allocated string that tries to match the "slug" part of the JID using an
98 * approximation of the method used by the server. This might fail in some rare conditions
99 * (old JIDs generated a different way, locale settings unicode, etc) */
hipchat_make_channel_slug(const char * name)100 char *hipchat_make_channel_slug(const char *name)
101 {
102 char *lower;
103 char *new = g_malloc(strlen(name) + 1);
104 int i = 0;
105
106 do {
107 if (*name == ' ') {
108 new[i++] = '_';
109 } else if (*name && !strchr("\"&'/:<>@", *name)) {
110 new[i++] = *name;
111 }
112 } while (*(name++));
113
114 new[i] = '\0';
115
116 lower = g_utf8_strdown(new, -1);
117 g_free(new);
118
119 return lower;
120 }
121
hipchat_guess_channel_name(struct im_connection * ic,const char * name)122 char *hipchat_guess_channel_name(struct im_connection *ic, const char *name)
123 {
124 struct jabber_data *jd = ic->proto_data;
125 char *slug, *retval, *underscore;
126
127 if (!(underscore = strchr(jd->username, '_')) || !jd->muc_host) {
128 return NULL;
129 }
130
131 slug = hipchat_make_channel_slug(name);
132
133 /* Get the organization ID from the username, before the underscore */
134 *underscore = '\0';
135
136 retval = g_strdup_printf("%s_%s@%s", jd->username, slug, jd->muc_host);
137
138 *underscore = '_';
139
140 g_free(slug);
141
142 return retval;
143 }
144