From 93b5ba41b99453180b14b967c23e39b5c5fd9e6a Mon Sep 17 00:00:00 2001 From: pier11 Date: Tue, 21 Jul 2009 16:07:04 +0100 Subject: [PATCH] conference: lock/unlock converence No new participants are allowed to enter conference under the lock. Lock is operated by conference Leaders and if in Leader role, the option can be found in Chat windows' Conversation menu: more->(Un)Lock Conversation --- src/sipe-conf.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/sipe-conf.h | 10 +++++++ src/sipe-session.h | 1 + src/sipe.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 167 insertions(+), 6 deletions(-) diff --git a/src/sipe-conf.c b/src/sipe-conf.c index c1a2e521..353f50ed 100644 --- a/src/sipe-conf.c +++ b/src/sipe-conf.c @@ -111,6 +111,27 @@ "" /** + * ModifyConferenceLock request to Focus. Locks/unlocks conference. + * @param focus_uri (%s) + * @param from (%s) + * @param request_id (%d) + * @param focus_uri (%s) + * @param locked (%s) "true" or "false" values applicable + */ +#define SIPE_SEND_CONF_MODIFY_CONF_LOCK \ +""\ +""\ + ""\ + ""\ + "%s"\ + ""\ +"" + +/** * Invite counterparty to join conference. * @param focus_uri (%s) * @param subject (%s) of conference @@ -329,6 +350,47 @@ sipe_conf_modify_user_role(struct sipe_account_data *sip, g_free(hdr); } +/** Modify Conference Lock */ +void +sipe_conf_modify_conference_lock(struct sipe_account_data *sip, + struct sip_session *session, + const gboolean locked) +{ + gchar *hdr; + gchar *body; + gchar *self; + + if (!session->focus_dialog || !session->focus_dialog->is_established) { + purple_debug_info("sipe", "sipe_conf_modify_user_role: no dialog with focus, exiting.\n"); + return; + } + + hdr = g_strdup( + "Content-Type: application/cccp+xml\r\n"); + + /* @TODO put request_id to queue to further compare with incoming one */ + self = sip_uri_self(sip); + body = g_strdup_printf( + SIPE_SEND_CONF_MODIFY_CONF_LOCK, + session->focus_dialog->with, + self, + session->request_id++, + session->focus_dialog->with, + locked ? "true" : "false"); + g_free(self); + + send_sip_request(sip->gc, + "INFO", + session->focus_dialog->with, + session->focus_dialog->with, + hdr, + body, + session->focus_dialog, + NULL); + g_free(body); + g_free(hdr); +} + /** Invite counterparty to join conference callback */ static gboolean process_invite_conf_response(struct sipe_account_data *sip, @@ -651,6 +713,27 @@ sipe_process_conference(struct sipe_account_data *sip, g_free(role); g_free(self); } + + /* entity-view, locked */ + for (node = xmlnode_get_descendant(xn_conference_info, "conference-view", "entity-view", NULL); + node; + node = xmlnode_get_next_twin(node)) { + + xmlnode *xn_type = xmlnode_get_descendant(node, "entity-state", "media", "entry", "type", NULL); + gchar *tmp; + if (xn_type && !strcmp("chat", (tmp = xmlnode_get_data(xn_type)))) { + xmlnode *xn_locked = xmlnode_get_descendant(node, "entity-state", "locked", NULL); + if (xn_locked) { + gchar *locked = xmlnode_get_data(xn_locked); + session->locked = (locked && !strcmp(locked, "true")) ? TRUE : FALSE; + /* @TODO in-chat notify user of lock status change */ + purple_debug_info("sipe", "sipe_process_conference: session->locked=%s\n", + session->locked ? "TRUE" : "FALSE"); + g_free(locked); + } + g_free(tmp); + } + } xmlnode_free(xn_conference_info); if (session->im_mcu_uri) { diff --git a/src/sipe-conf.h b/src/sipe-conf.h index 3d6bf9e4..6944309e 100644 --- a/src/sipe-conf.h +++ b/src/sipe-conf.h @@ -68,6 +68,16 @@ sipe_conf_modify_user_role(struct sipe_account_data *sip, const gchar* who); /** + * Modify Conference Lock. + * Sends request to Focus. + * INFO method is a carrier of application/cccp+xml + */ +void +sipe_conf_modify_conference_lock(struct sipe_account_data *sip, + struct sip_session *session, + const gboolean locked); + +/** * Invokes when we leave conversation. * Usually by closing chat wingow. */ diff --git a/src/sipe-session.h b/src/sipe-session.h index 41f82ba2..927a056a 100644 --- a/src/sipe-session.h +++ b/src/sipe-session.h @@ -61,6 +61,7 @@ struct sip_session { gchar *focus_uri; gchar *im_mcu_uri; gchar *subject; + gboolean locked; guint request_id; struct sip_dialog *focus_dialog; /** Key is Message-Id */ diff --git a/src/sipe.c b/src/sipe.c index 37a15673..3f244249 100644 --- a/src/sipe.c +++ b/src/sipe.c @@ -6281,12 +6281,16 @@ sipe_buddy_menu(PurpleBuddy *buddy) } else { - gchar *label = g_strdup_printf(_("Invite to '%s'"), session->chat_name); - act = purple_menu_action_new(label, - PURPLE_CALLBACK(sipe_buddy_menu_chat_invite_cb), - g_strdup(session->chat_name), NULL); - g_free(label); - menu = g_list_prepend(menu, act); + if (!session->focus_uri + || (session->focus_uri && !session->locked)) + { + gchar *label = g_strdup_printf(_("Invite to '%s'"), session->chat_name); + act = purple_menu_action_new(label, + PURPLE_CALLBACK(sipe_buddy_menu_chat_invite_cb), + g_strdup(session->chat_name), NULL); + g_free(label); + menu = g_list_prepend(menu, act); + } } } } SIPE_SESSION_FOREACH_END; @@ -6330,11 +6334,74 @@ sipe_buddy_menu(PurpleBuddy *buddy) return menu; } +static void +sipe_conf_modify_lock(PurpleChat *chat, gboolean locked) +{ + struct sipe_account_data *sip = chat->account->gc->proto_data; + struct sip_session *session; + + session = sipe_session_find_chat_by_name(sip, (gchar *)g_hash_table_lookup(chat->components, "channel")); + sipe_conf_modify_conference_lock(sip, session, locked); +} + +static void +sipe_chat_menu_unlock_cb(PurpleChat *chat) +{ + purple_debug_info("sipe", "sipe_chat_menu_unlock_cb() called\n"); + sipe_conf_modify_lock(chat, FALSE); +} + +static void +sipe_chat_menu_lock_cb(PurpleChat *chat) +{ + purple_debug_info("sipe", "sipe_chat_menu_lock_cb() called\n"); + sipe_conf_modify_lock(chat, TRUE); +} + +static GList * +sipe_chat_menu(PurpleChat *chat) +{ + PurpleMenuAction *act; + PurpleConvChatBuddyFlags flags_us; + GList *menu = NULL; + struct sipe_account_data *sip = chat->account->gc->proto_data; + struct sip_session *session; + gchar *self = sip_uri_self(sip); + + session = sipe_session_find_chat_by_name(sip, (gchar *)g_hash_table_lookup(chat->components, "channel")); + if (!session) return NULL; + + flags_us = purple_conv_chat_user_get_flags(PURPLE_CONV_CHAT(session->conv), self); + + if (session->focus_uri + && PURPLE_CBFLAGS_OP == (flags_us & PURPLE_CBFLAGS_OP)) /* We are a conf OP */ + { + if (session->locked) { + act = purple_menu_action_new(_("Unlock Conversation"), + PURPLE_CALLBACK(sipe_chat_menu_unlock_cb), + NULL, NULL); + menu = g_list_prepend(menu, act); + } else { + act = purple_menu_action_new(_("Lock Conversation"), + PURPLE_CALLBACK(sipe_chat_menu_lock_cb), + NULL, NULL); + menu = g_list_prepend(menu, act); + } + } + + menu = g_list_reverse(menu); + + g_free(self); + return menu; +} + static GList * sipe_blist_node_menu(PurpleBlistNode *node) { if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { return sipe_buddy_menu((PurpleBuddy *) node); + } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + return sipe_chat_menu((PurpleChat *)node); } else { return NULL; } -- 2.11.4.GIT