diff --git a/src/muc.c b/src/muc.c index ea4ae915..1c5e1825 100644 --- a/src/muc.c +++ b/src/muc.c @@ -62,6 +62,7 @@ typedef struct _muc_room_t { Autocomplete jid_ac; GHashTable *nick_changes; gboolean roster_received; + muc_member_type_t member_type; } ChatRoom; GHashTable *rooms = NULL; @@ -177,6 +178,7 @@ muc_join(const char * const room, const char * const nick, new_room->roster_received = FALSE; new_room->pending_nick_change = FALSE; new_room->autojoin = autojoin; + new_room->member_type = MUC_MEMBER_TYPE_UNKNOWN; g_hash_table_insert(rooms, strdup(room), new_room); } @@ -763,6 +765,18 @@ muc_set_affiliation(const char * const room, const char * const affiliation) } } +muc_member_type_t +muc_member_type(const char * const room) +{ + ChatRoom *chat_room = g_hash_table_lookup(rooms, room); + if (chat_room) { + return chat_room->member_type; + } else { + return MUC_MEMBER_TYPE_UNKNOWN; + } +} + + static void _free_room(ChatRoom *room) { diff --git a/src/muc.h b/src/muc.h index 16f217d0..60cf7108 100644 --- a/src/muc.h +++ b/src/muc.h @@ -56,6 +56,12 @@ typedef enum { MUC_AFFILIATION_OWNER } muc_affiliation_t; +typedef enum { + MUC_MEMBER_TYPE_UNKNOWN, + MUC_MEMBER_TYPE_PUBLIC, + MUC_MEMBER_TYPE_MEMBERS_ONLY +} muc_member_type_t; + typedef struct _muc_occupant_t { char *nick; char *jid; @@ -134,4 +140,6 @@ void muc_set_affiliation(const char * const room, const char * const affiliation char *muc_role_str(const char * const room); char *muc_affiliation_str(const char * const room); +muc_member_type_t muc_member_type(const char * const room); + #endif diff --git a/src/server_events.c b/src/server_events.c index a97e0786..f9f5afe4 100644 --- a/src/server_events.c +++ b/src/server_events.c @@ -697,6 +697,9 @@ handle_muc_self_online(const char * const room, const char * const nick, gboolea } else { ui_room_join(room, TRUE); } + + // TODO send disco info request to room + muc_invites_remove(room); muc_roster_set_complete(room); diff --git a/src/xmpp/message.c b/src/xmpp/message.c index e6927f76..1bb3bcdc 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -204,7 +204,16 @@ message_send_invite(const char * const roomjid, const char * const contact, { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *stanza = stanza_create_invite(ctx, roomjid, contact, reason); + xmpp_stanza_t *stanza; + + muc_member_type_t member_type = muc_member_type(roomjid); + if (member_type == MUC_MEMBER_TYPE_PUBLIC) { + log_debug("Sending direct invite to %s, for %s", contact, roomjid); + stanza = stanza_create_invite(ctx, roomjid, contact, reason); + } else { + log_debug("Sending mediated invite to %s, for %s", contact, roomjid); + stanza = stanza_create_mediated_invite(ctx, roomjid, contact, reason); + } xmpp_send(conn, stanza); xmpp_stanza_release(stanza); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 0b291d2e..03567e31 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -440,6 +440,46 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room, return message; } +xmpp_stanza_t * +stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char * const room, + const char * const contact, const char * const reason) +{ + xmpp_stanza_t *message, *x, *invite; + + message = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE); + xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, room); + char *id = create_unique_id(NULL); + xmpp_stanza_set_id(message, id); + free(id); + + x = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(x, STANZA_NAME_X); + xmpp_stanza_set_ns(x, STANZA_NS_MUC_USER); + + invite = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(invite, STANZA_NAME_INVITE); + xmpp_stanza_set_attribute(invite, STANZA_ATTR_TO, contact); + + if (reason != NULL) { + xmpp_stanza_t *reason_st = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(reason_st, STANZA_NAME_REASON); + xmpp_stanza_t *reason_txt = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(reason_txt, reason); + xmpp_stanza_add_child(reason_st, reason_txt); + xmpp_stanza_release(reason_txt); + xmpp_stanza_add_child(invite, reason_st); + xmpp_stanza_release(reason_st); + } + + xmpp_stanza_add_child(x, invite); + xmpp_stanza_release(invite); + xmpp_stanza_add_child(message, x); + xmpp_stanza_release(x); + + return message; +} + xmpp_stanza_t * stanza_create_room_join_presence(xmpp_ctx_t * const ctx, const char * const full_room_jid, const char * const passwd) diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 50f3dbd0..744bd7fb 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -215,6 +215,8 @@ xmpp_stanza_t* stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char * const i xmpp_stanza_t* stanza_create_invite(xmpp_ctx_t *ctx, const char * const room, const char * const contact, const char * const reason); +xmpp_stanza_t* stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char * const room, + const char * const contact, const char * const reason); gboolean stanza_contains_chat_state(xmpp_stanza_t *stanza);