aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--protocols/jabber/hipchat.c50
-rw-r--r--protocols/jabber/jabber.c13
-rw-r--r--protocols/jabber/jabber.h4
-rw-r--r--tests/check_jabber_util.c20
4 files changed, 87 insertions, 0 deletions
diff --git a/protocols/jabber/hipchat.c b/protocols/jabber/hipchat.c
index 66675885..49e7c895 100644
--- a/protocols/jabber/hipchat.c
+++ b/protocols/jabber/hipchat.c
@@ -42,6 +42,8 @@ xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node)
*sep = '/';
}
+ jd->muc_host = g_strdup(xt_find_attr(node, "muc_host"));
+
/* Hipchat's auth doesn't expect a restart here */
jd->flags &= ~JFLAG_STREAM_RESTART;
@@ -91,3 +93,51 @@ xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node
return XT_HANDLED;
}
+
+/* Returns a newly allocated string that tries to match the "slug" part of the JID using an
+ * approximation of the method used by the server. This might fail in some rare conditions
+ * (old JIDs generated a different way, locale settings unicode, etc) */
+char *hipchat_make_channel_slug(const char *name)
+{
+ char *lower;
+ char *new = g_malloc(strlen(name) + 1);
+ int i = 0;
+
+ do {
+ if (*name == ' ') {
+ new[i++] = '_';
+ } else if (*name && !strchr("\"&'/:<>@", *name)) {
+ new[i++] = *name;
+ }
+ } while (*(name++));
+
+ new[i] = '\0';
+
+ lower = g_utf8_strdown(new, -1);
+ g_free(new);
+
+ return lower;
+}
+
+char *hipchat_guess_channel_name(struct im_connection *ic, const char *name)
+{
+ struct jabber_data *jd = ic->proto_data;
+ char *slug, *retval, *underscore;
+
+ if (!(underscore = strchr(jd->username, '_')) || !jd->muc_host) {
+ return NULL;
+ }
+
+ slug = hipchat_make_channel_slug(name);
+
+ /* Get the organization ID from the username, before the underscore */
+ *underscore = '\0';
+
+ retval = g_strdup_printf("%s_%s@%s", jd->username, slug, jd->muc_host);
+
+ *underscore = '_';
+
+ g_free(slug);
+
+ return retval;
+}
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index 35cf0c90..ddf4f2d3 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -370,6 +370,7 @@ static void jabber_logout(struct im_connection *ic)
g_free(jd->away_message);
g_free(jd->internal_jid);
g_free(jd->gmail_tid);
+ g_free(jd->muc_host);
g_free(jd->username);
g_free(jd->me);
g_free(jd);
@@ -532,12 +533,24 @@ static struct groupchat *jabber_chat_join_(struct im_connection *ic, const char
final_nick = (char *) nick;
}
+ if (jd->flags & JFLAG_HIPCHAT && jd->muc_host && !g_str_has_suffix(room, jd->muc_host)) {
+ char *guessed_name = hipchat_guess_channel_name(ic, room);
+ if (guessed_name) {
+ set_setstr(sets, "room", guessed_name);
+ g_free(guessed_name);
+
+ /* call this same function again with the fixed name */
+ return jabber_chat_join_(ic, set_getstr(sets, "room"), nick, password, sets);
+ }
+ }
+
if (strchr(room, '@') == NULL) {
imcb_error(ic, "%s is not a valid Jabber room name. Maybe you mean %s@conference.%s?",
room, room, jd->server);
} else if (jabber_chat_by_jid(ic, room)) {
imcb_error(ic, "Already present in chat `%s'", room);
} else {
+ /* jabber_chat_join without the underscore is the conference.c one */
return jabber_chat_join(ic, room, final_nick, set_getstr(sets, "password"));
}
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 75bd123f..b50e0cb5 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -112,6 +112,8 @@ struct jabber_data {
GSList *filetransfers;
GSList *streamhosts;
int have_streamhosts;
+
+ char *muc_host;
};
struct jabber_away_state {
@@ -357,5 +359,7 @@ void jabber_chat_invite(struct groupchat *c, char *who, char *message);
int jabber_get_hipchat_profile(struct im_connection *ic);
xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node);
+char *hipchat_make_channel_slug(const char *name);
+char *hipchat_guess_channel_name(struct im_connection *ic, const char *name);
#endif
diff --git a/tests/check_jabber_util.c b/tests/check_jabber_util.c
index 1a574ec2..1ffea011 100644
--- a/tests/check_jabber_util.c
+++ b/tests/check_jabber_util.c
@@ -104,6 +104,25 @@ static void check_compareJID(int l)
fail_if(jabber_compare_jid("", "bugtest@google.com/A"));
}
+static void check_hipchat_slug(int l)
+{
+ int i;
+
+ const char *tests[] = {
+ "test !\"#$%&\'()*+,-./0123456789:;<=>?@ABC", "test_!#$%\()*+,-.0123456789;=?abc",
+ "test XYZ[\\]^_`abc", "test_xyz[\\]^_`abc",
+ "test {|}~¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆ", "test_{|}~¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿àáâãäåæ",
+ "test IJ ij I ı I ı", "test_ij_ij_i_ı_i_ı",
+ NULL,
+ };
+
+ for (i = 0; tests[i]; i += 2) {
+ char *new = hipchat_make_channel_slug(tests[i]);
+ fail_unless(!strcmp(tests[i + 1], new));
+ g_free(new);
+ }
+}
+
Suite *jabber_util_suite(void)
{
Suite *s = suite_create("jabber/util");
@@ -120,5 +139,6 @@ Suite *jabber_util_suite(void)
suite_add_tcase(s, tc_core);
tcase_add_test(tc_core, check_buddy_add);
tcase_add_test(tc_core, check_compareJID);
+ tcase_add_test(tc_core, check_hipchat_slug);
return s;
}