diff options
Diffstat (limited to 'protocols/jabber')
| -rw-r--r-- | protocols/jabber/hipchat.c | 50 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 13 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 4 | 
3 files changed, 67 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 | 
