void LM::HeapRoster::on_personal_details_updated () { LmMessage* message = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_message_node_add_child (lm_message_get_node (message), "show", details->get_presence ().c_str ()); lm_message_node_add_child (lm_message_get_node (message), "status", details->get_status ().c_str ()); lm_connection_send (connection, message, NULL); lm_message_unref (message); }
void LM::Presentity::edit_presentity_form_submitted (bool submitted, Ekiga::Form& result) { if (!submitted) return; const std::string name = result.text ("name"); const std::set<std::string> groups = result.editable_set ("groups"); LmMessage* message = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET); LmMessageNode* query = lm_message_node_add_child (lm_message_get_node (message), "query", NULL); lm_message_node_set_attribute (query, "xmlns", "jabber:iq:roster"); LmMessageNode* node = lm_message_node_add_child (query, "item", NULL); { gchar* escaped = g_markup_escape_text (name.c_str (), -1); lm_message_node_set_attributes (node, "jid", get_jid ().c_str (), "name", escaped, NULL); g_free (escaped); } for (std::set<std::string>::const_iterator iter = groups.begin (); iter != groups.end (); ++iter) { gchar* escaped = g_markup_escape_text (iter->c_str (), -1); lm_message_node_add_child (node, "group", escaped); g_free (escaped); } lm_connection_send_with_reply (connection, message, build_message_handler (boost::bind(&LM::Presentity::handle_edit_reply, this, _1, _2)), NULL); lm_message_unref (message); }
static LmHandlerResult chat_handler(LmMessageHandler* /*handler*/, LmConnection* /*connection*/, LmMessage* m, gpointer user_data) { XMPPAccountHandler * pHandler = static_cast<XMPPAccountHandler *>(user_data); UT_return_val_if_fail(pHandler, LM_HANDLER_RESULT_REMOVE_MESSAGE); /* TODO: we should run run through all the nodes to find the message node */ LmMessageNode* node = lm_message_get_node(m); if (strcmp(node->name, "message") == 0) { for (LmMessageNode* child = node->children; child != 0; child = child->next) { if (strcmp(child->name, "body") == 0) { /* Note: we don't trust a message body with a from-address in it, as it could be forged. Instead get the from-address directly from the LmMessage */ std::string buddy = lm_message_node_get_attribute (m->node, "from"); std::string::size_type pos = buddy.find_last_of("/"); if (pos != std::string::npos) buddy.resize(pos); // TODO: check the resource as an additional sanity check UT_DEBUGMSG(("chat_handler(): Got a message from buddy: %s\n", buddy.c_str())); pHandler->handleMessage(child->value, buddy); break; } } } return LM_HANDLER_RESULT_REMOVE_MESSAGE; }
static LmHandlerResult presence_handler(LmMessageHandler* /*handler*/, LmConnection * /*connection*/, LmMessage* m, gpointer /*user_data*/) { // XMPPAccountHandler * pHandler = static_cast<XMPPAccountHandler *>(user_data); LmMessageNode* node = lm_message_get_node(m); if (node) { const char* from = static_cast<const char*>(lm_message_node_get_attribute (node, "from")); if (from) { const gchar* type = lm_message_node_get_attribute (node, "type"); if (type && strcmp(type, "unavailable") == 0) { UT_DEBUGMSG(("Disconnect presence from %s\n", from)); // TODO: handle this } else { UT_DEBUGMSG(("Connect presence from %s\n", from)); // TODO: handle this } } else { UT_DEBUGMSG(("presence message without from\n")); } } return LM_HANDLER_RESULT_REMOVE_MESSAGE; }
void LM::Presentity::ask_to () { LmMessage* message = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_message_node_set_attributes (lm_message_get_node (message), "to", get_jid ().c_str (), "type", "subscribe", NULL); lm_connection_send_with_reply (connection, message, get_ignore_answer_handler (), NULL); lm_message_unref (message); }
LmHandlerResult LM::Presentity::handle_edit_reply (LmConnection* /*connection*/, LmMessage* message) { if (lm_message_get_sub_type (message) == LM_MESSAGE_SUB_TYPE_ERROR) { std::cout << "Don't know how to handle : " << lm_message_node_to_string (lm_message_get_node (message)) << std::endl; } return LM_HANDLER_RESULT_REMOVE_MESSAGE; }
void LM::HeapRoster::subscribe_from_form_submitted (bool submitted, Ekiga::Form& result) { if ( !submitted) return; const std::string jid = result.hidden ("jid"); const std::string answer = result.single_choice ("answer"); if (answer == "grant") { LmMessage* message = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_message_node_set_attributes (lm_message_get_node (message), "to", jid.c_str (), "type", "subscribed", NULL); lm_connection_send (connection, message, NULL); lm_message_unref (message); LmMessage* subscribe = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_message_node_set_attributes (lm_message_get_node (subscribe), "to", jid.c_str (), "type", "subscribe", NULL); lm_connection_send (connection, subscribe, NULL); lm_message_unref (subscribe); } else if (answer == "refuse") { LmMessage* message = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_message_node_set_attributes (lm_message_get_node (message), "to", jid.c_str (), "type", "unsubscribed", NULL); lm_connection_send (connection, message, NULL); lm_message_unref (message); } }
void LM::Presentity::remove_presentity () { LmMessage* message = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET); LmMessageNode* query = lm_message_node_add_child (lm_message_get_node (message), "query", NULL); lm_message_node_set_attribute (query, "xmlns", "jabber:iq:roster"); LmMessageNode* node = lm_message_node_add_child (query, "item", NULL); lm_message_node_set_attributes (node, "jid", get_jid ().c_str (), "subscription", "remove", NULL); lm_connection_send_with_reply (connection, message, get_ignore_answer_handler (), NULL); lm_message_unref (message); }
LmHandlerResult LM::HeapRoster::handle_initial_roster_reply (LmConnection* /*connection*/, LmMessage* message) { LmHandlerResult result = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; if (lm_message_get_sub_type (message) == LM_MESSAGE_SUB_TYPE_RESULT) { LmMessageNode* node = lm_message_node_get_child (lm_message_get_node (message), "query"); if (node != NULL) { const gchar* xmlns = lm_message_node_get_attribute (node, "xmlns"); if (xmlns != NULL && g_strcmp0 (xmlns, "jabber:iq:roster") == 0) { parse_roster (node); result = LM_HANDLER_RESULT_REMOVE_MESSAGE; } } } return result; }
void LM::HeapRoster::add_item_form_submitted (bool submitted, Ekiga::Form& result) { if ( !submitted) return; const std::string jid = result.text ("jid"); const std::string contact_name = result.text ("name"); const std::list<std::string> groups = result.editable_set ("groups"); if ( !jid.empty ()) { LmMessage* message = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET); LmMessageNode* query = lm_message_node_add_child (lm_message_get_node (message), "query", NULL); lm_message_node_set_attribute (query, "xmlns", "jabber:iq:roster"); LmMessageNode* node = lm_message_node_add_child (query, "item", NULL); lm_message_node_set_attributes (node, "jid", jid.c_str (), NULL); if ( !contact_name.empty ()) { gchar* escaped = g_markup_escape_text (contact_name.c_str (), -1); lm_message_node_set_attributes (node, "name", escaped, NULL); } for (std::list<std::string>::const_iterator iter = groups.begin (); iter != groups.end (); ++iter) { gchar* escaped = g_markup_escape_text (iter->c_str (), -1); lm_message_node_add_child (node, "group", escaped); g_free (escaped); } items_added_by_me.insert (jid); lm_connection_send (connection, message, NULL); lm_message_unref (message); } }
LmHandlerResult LM::HeapRoster::handle_message (LmConnection* /*connection*/, LmMessage* message) { LmHandlerResult result = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; LmMessageNode* node = lm_message_get_node (message); const gchar* from_c = lm_message_node_get_attribute (node, "from"); const gchar* type_attr = lm_message_node_get_attribute (node, "type"); std::string base_jid; if (from_c != 0) { std::string from (from_c); std::string::size_type index = from.find ('/'); base_jid = std::string (from, 0, index); } PresentityPtr item = find_item (base_jid); if (item && (type_attr == NULL || (type_attr != NULL && g_strcmp0 (type_attr, "normal") == 0) || (type_attr != NULL && g_strcmp0 (type_attr, "chat") == 0))) { // let's imagine it's a basic chat message LmMessageNode* body = lm_message_node_find_child (node, "body"); if (body && lm_message_node_get_value (body) != NULL) { result = LM_HANDLER_RESULT_REMOVE_MESSAGE; Ekiga::Message::payload_type payload; payload["text/plain"] = lm_message_node_get_value (body); dialect->push_message (item, payload); } // it could also be an avatar or a pubsub event or... } return result; }
LmHandlerResult LM::Account::handle_presence (LmMessage* message) { LmHandlerResult result = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; if (result == LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS) { result = dialect->handle_presence (connection, message); } if (result == LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS) { result = cluster->handle_presence (connection, message); } #if DEBUG if (result == LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS) { std::cout << "Nobody cared about : " << lm_message_node_to_string (lm_message_get_node (message)) << std::endl; } #endif return result; }
void LM::HeapRoster::handle_up (LmConnection* connection_, const std::string name_) { connection = connection_; name = name_; { // populate the roster LmMessage* roster_request = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET); LmMessageNode* node = lm_message_node_add_child (lm_message_get_node (roster_request), "query", NULL); lm_message_node_set_attributes (node, "xmlns", "jabber:iq:roster", NULL); lm_connection_send_with_reply (connection, roster_request, build_message_handler (boost::bind (&LM::HeapRoster::handle_initial_roster_reply, this, _1, _2)), NULL); lm_message_unref (roster_request); } { // initial presence push LmMessage* presence_push = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_connection_send (connection, presence_push, NULL); lm_message_unref (presence_push); } on_personal_details_updated (); // fake, but if we start as dnd, we want it known updated (); }
void LM::HeapRoster::parse_roster (LmMessageNode* query) { for (LmMessageNode* node = query->children; node != NULL; node = node->next) { if (g_strcmp0 (node->name, "item") != 0) { continue; } const gchar* jid = lm_message_node_get_attribute (node, "jid"); bool found = false; for (iterator iter = begin (); !found && iter != end (); ++iter) { if ((*iter)->get_jid () == jid) { found = true; const gchar* subscription = lm_message_node_get_attribute (node, "subscription"); if (subscription != NULL && g_strcmp0 (subscription, "remove") == 0) { (*iter)->removed (); } else { (*iter)->update (node); } } } if ( !found) { PresentityPtr presentity(new Presentity (connection, node)); presentity->chat_requested.connect (boost::bind (&LM::HeapRoster::on_chat_requested, this, presentity)); add_presentity (presentity); const gchar* subscription = lm_message_node_get_attribute (node, "subscription"); if (subscription != NULL && g_strcmp0 (subscription, "none") == 0) { const gchar* ask = lm_message_node_get_attribute (node, "ask"); if (ask == NULL || (ask != NULL && g_strcmp0 (ask, "subscribe") != 0)) { std::set<std::string>::iterator iter = items_added_by_me.find (presentity->get_jid ()); if (iter != items_added_by_me.end ()) { /* if we're here then this is a new contact, we are not subscribed to it, * and we did not ask to be subscribed to it and we added it recently: * let's ask for subscription! * * Beware that the first three actions could have been done from another client, * so that last condition is important so we don't start doing things * in the back of the user! */ items_added_by_me.erase (iter); LmMessage* subscribe = lm_message_new (NULL, LM_MESSAGE_TYPE_PRESENCE); lm_message_node_set_attributes (lm_message_get_node (subscribe), "to", presentity->get_jid ().c_str (), "type", "subscribe", NULL); lm_connection_send (connection, subscribe, NULL); lm_message_unref (subscribe); } } } } } }
LmHandlerResult LM::HeapRoster::handle_presence (LmConnection* /*connection*/, LmMessage* message) { LmHandlerResult result = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; const gchar* from_c = lm_message_node_get_attribute (lm_message_get_node (message), "from"); const gchar* type_attr = lm_message_node_get_attribute (lm_message_get_node (message), "type"); std::string base_jid; std::string resource; if (from_c != 0) { std::string from (from_c); std::string::size_type index = from.find ('/'); base_jid = std::string (from, 0, index); resource = std::string (from, index + 1, std::string::npos); } PresentityPtr item = find_item (base_jid); if (type_attr != NULL && g_strcmp0 (type_attr, "subscribe") == 0) { result = LM_HANDLER_RESULT_REMOVE_MESSAGE; boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&LM::HeapRoster::subscribe_from_form_submitted, this, _1, _2))); LmMessageNode* status = lm_message_node_find_child (lm_message_get_node (message), "status"); gchar* instructions = NULL; std::string item_name; if (item) { item_name = item->get_name (); } else { item_name = base_jid; } request->title (_("Authorization to see your presence")); if (status != NULL && lm_message_node_get_value (status) != NULL) { instructions = g_strdup_printf (_("%s asks the permission to see your presence, saying: \"%s\"."), item_name.c_str (), lm_message_node_get_value (status)); } else { instructions = g_strdup_printf (_("%s asks the permission to see your presence."), item_name.c_str ()); } request->instructions (instructions); g_free (instructions); std::map<std::string, std::string> choices; choices["grant"] = _("grant him/her the permission to see your presence"); choices["refuse"] = _("refuse him/her the permission to see your presence"); choices["later"] = _("decide later (also close or cancel this dialog)"); request->single_choice ("answer", _("Your answer is: "), "grant", choices); request->hidden ("jid", base_jid); questions (request); } else { if (item) { result = LM_HANDLER_RESULT_REMOVE_MESSAGE; item->push_presence (resource, lm_message_get_node (message)); } } return result; }
static LmHandlerResult ft_msg_msg_handler (LmMessageHandler *handler, LmConnection *conn, LmMessage *msg, gpointer user_data) { LmMessageNode *root, *body, *x; const char *from, *msg_str, *type; char *ts = NULL; char *new_from = NULL; root = lm_message_get_node (msg); if (!root) goto out; body = lm_message_node_get_child (root, "body"); if (!body) goto out; from = lm_message_node_get_attribute (msg->node, "from"); if (!from) goto out; msg_str = lm_message_node_get_value (body); type = lm_message_node_get_attribute (msg->node, "type"); if (type && g_ascii_strcasecmp (type, "chat") != 0) { PRINTF (_("[message of type '%s']"), type); goto out; } // Offline messages for (x = root->children; x != NULL; x = x->next) { if (!g_ascii_strcasecmp (x->name, "x")) { const char *xmlns = lm_message_node_get_attribute (x, "xmlns"); if (xmlns && !g_ascii_strcasecmp (xmlns, "jabber:x:delay")) { ts = parse_timestamp ((char *)lm_message_node_get_attribute (x, "stamp")); } } } set_hook_return (0); { FtRosterItem *item = NULL; char *nickname; new_from = g_strdup (from); item = ft_roster_lookup (new_from); if (!item) nickname = NULL; else nickname = item->nickname; scm_run_hook (ex_message_receive_hook, scm_list_n (ts ? scm_from_locale_string (ts) : scm_from_locale_string (""), scm_from_locale_string (new_from), nickname ? scm_from_locale_string (nickname) : scm_from_locale_string (""), scm_from_locale_string (msg_str), SCM_UNDEFINED)); } if (get_hook_return () == 1) goto out; PRINTF ("%s: %s", new_from, msg_str); out: if (ts) g_free (ts); if (new_from) g_free (new_from); return LM_HANDLER_RESULT_REMOVE_MESSAGE; }