void jabber_chat_register(JabberChat *chat) { JabberIq *iq; char *room_jid; if(!chat) return; room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, "jabber:iq:register"); xmlnode_set_attrib(iq->node, "to", room_jid); g_free(room_jid); jabber_iq_set_callback(iq, jabber_chat_register_cb, NULL); jabber_iq_send(iq); }
static void jabber_chat_register_x_data_cb(JabberStream *js, xmlnode *result, gpointer data) { JabberChat *chat = data; xmlnode *query; JabberIq *iq; char *to = g_strdup_printf("%s@%s", chat->room, chat->server); iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register"); xmlnode_set_attrib(iq->node, "to", to); g_free(to); query = xmlnode_get_child(iq->node, "query"); xmlnode_insert_child(query, result); jabber_iq_set_callback(iq, jabber_chat_register_x_data_result_cb, NULL); jabber_iq_send(iq); }
static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet) { const char *type, *id, *from; JabberIq *iq; type = xmlnode_get_attrib(packet, "type"); from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); if(type && !strcmp(type, "get")) { iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping"); jabber_iq_set_id(iq, id); xmlnode_set_attrib(iq->node, "to", from); jabber_iq_send(iq); } else { /* XXX: error */ } }
gboolean jabber_chat_role_list(JabberChat *chat, const char *role) { JabberIq *iq; char *room_jid; xmlnode *query, *item; iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, "http://jabber.org/protocol/muc#admin"); room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); xmlnode_set_attrib(iq->node, "to", room_jid); query = xmlnode_get_child(iq->node, "query"); item = xmlnode_new_child(query, "item"); xmlnode_set_attrib(item, "role", role); jabber_iq_set_callback(iq, jabber_chat_role_list_cb, GINT_TO_POINTER(chat->id)); jabber_iq_send(iq); return TRUE; }
static void roomlist_ok_cb(JabberStream *js, const char *server) { JabberIq *iq; if(!js->roomlist) return; if(!server || !*server) { purple_notify_error(js->gc, _("Invalid Server"), _("Invalid Server"), NULL); return; } purple_roomlist_set_in_progress(js->roomlist, TRUE); iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); xmlnode_set_attrib(iq->node, "to", server); jabber_iq_set_callback(iq, roomlist_disco_result_cb, NULL); jabber_iq_send(iq); }
void jabber_chat_disco_traffic(JabberChat *chat) { JabberIq *iq; xmlnode *query; char *room_jid; room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, NS_DISCO_INFO); xmlnode_set_attrib(iq->node, "to", room_jid); query = xmlnode_get_child(iq->node, "query"); xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/muc#traffic"); jabber_iq_set_callback(iq, jabber_chat_disco_traffic_cb, GINT_TO_POINTER(chat->id)); jabber_iq_send(iq); g_free(room_jid); }
static void jabber_iq_last_parse(JabberStream *js, const char *from, JabberIqType type, const char *id, PurpleXmlNode *packet) { JabberIq *iq; PurpleXmlNode *query; char *idle_time; if(type == JABBER_IQ_GET) { iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, NS_LAST_ACTIVITY); jabber_iq_set_id(iq, id); if (from) purple_xmlnode_set_attrib(iq->node, "to", from); query = purple_xmlnode_get_child(iq->node, "query"); idle_time = g_strdup_printf("%ld", js->idle ? time(NULL) - js->idle : 0); purple_xmlnode_set_attrib(query, "seconds", idle_time); g_free(idle_time); jabber_iq_send(iq); } }
void jabber_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { const char *name = purple_buddy_get_name(buddy); GSList *buddies = purple_find_buddies(purple_connection_get_account(gc), name); buddies = g_slist_remove(buddies, buddy); if(buddies != NULL) { PurpleBuddy *tmpbuddy; PurpleGroup *tmpgroup; GSList *groups = NULL; while(buddies) { tmpbuddy = buddies->data; tmpgroup = purple_buddy_get_group(tmpbuddy); groups = g_slist_append(groups, (char *)purple_group_get_name(tmpgroup)); buddies = g_slist_remove(buddies, tmpbuddy); } purple_debug_info("jabber", "jabber_roster_remove_buddy(): Removing %s from %s\n", purple_buddy_get_name(buddy), purple_group_get_name(group)); jabber_roster_update(gc->proto_data, name, groups); } else { JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET, "jabber:iq:roster"); xmlnode *query = xmlnode_get_child(iq->node, "query"); xmlnode *item = xmlnode_new_child(query, "item"); xmlnode_set_attrib(item, "jid", name); xmlnode_set_attrib(item, "subscription", "remove"); purple_debug_info("jabber", "jabber_roster_remove_buddy(): Removing %s\n", purple_buddy_get_name(buddy)); jabber_iq_send(iq); } }
void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type, const char *id, PurpleXmlNode *new_mail) { PurpleXmlNode *query; JabberIq *iq; /* bail if the user isn't interested */ if (!purple_account_get_check_mail(purple_connection_get_account(js->gc))) return; /* Is this an initial incoming mail notification? If so, send a request for more info */ if (type != JABBER_IQ_SET) return; /* Acknowledge the notification */ iq = jabber_iq_new(js, JABBER_IQ_RESULT); if (from) purple_xmlnode_set_attrib(iq->node, "to", from); purple_xmlnode_set_attrib(iq->node, "id", id); jabber_iq_send(iq); purple_debug_misc("jabber", "Got new mail notification. Sending request for more info\n"); iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY); jabber_iq_set_callback(iq, jabber_gmail_parse, NULL); query = purple_xmlnode_get_child(iq->node, "query"); if (js->gmail_last_time) purple_xmlnode_set_attrib(query, "newer-than-time", js->gmail_last_time); if (js->gmail_last_tid) purple_xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid); jabber_iq_send(iq); return; }
void jabber_chat_create_instant_room(JabberChat *chat) { JabberIq *iq; xmlnode *query, *x; char *room_jid; if(!chat) return; chat->config_dialog_handle = NULL; iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, "http://jabber.org/protocol/muc#owner"); query = xmlnode_get_child(iq->node, "query"); x = xmlnode_new_child(query, "x"); room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); xmlnode_set_attrib(iq->node, "to", room_jid); xmlnode_set_namespace(x, "jabber:x:data"); xmlnode_set_attrib(x, "type", "submit"); jabber_iq_send(iq); g_free(room_jid); }
gboolean jabber_chat_ban_user(JabberChat *chat, const char *who, const char *why) { JabberChatMember *jcm; const char *jid; char *to; JabberIq *iq; xmlnode *query, *item, *reason; jcm = g_hash_table_lookup(chat->members, who); if (jcm && jcm->jid) jid = jcm->jid; else if (strchr(who, '@') != NULL) jid = who; else return FALSE; iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, "http://jabber.org/protocol/muc#admin"); to = g_strdup_printf("%s@%s", chat->room, chat->server); xmlnode_set_attrib(iq->node, "to", to); g_free(to); query = xmlnode_get_child(iq->node, "query"); item = xmlnode_new_child(query, "item"); xmlnode_set_attrib(item, "jid", jid); xmlnode_set_attrib(item, "affiliation", "outcast"); if(why) { reason = xmlnode_new_child(item, "reason"); xmlnode_insert_data(reason, why, -1); } jabber_iq_send(iq); return TRUE; }
/* jabber_roster_update frees the GSList* passed in */ static void jabber_roster_update(JabberStream *js, const char *name, GSList *groups) { PurpleBuddy *b; PurpleGroup *g; GSList *l; JabberIq *iq; xmlnode *query, *item, *group; const char *balias; if (js->currently_parsing_roster_push) return; if(!(b = purple_find_buddy(js->gc->account, name))) return; if (groups) { char *tmp = roster_groups_join(groups); purple_debug_info("jabber", "jabber_roster_update(%s): [Source: " "groups]: groups: %s\n", name, tmp); g_free(tmp); } else { GSList *buddies = purple_find_buddies(js->gc->account, name); char *tmp; if(!buddies) return; while(buddies) { b = buddies->data; g = purple_buddy_get_group(b); groups = g_slist_append(groups, (char *)purple_group_get_name(g)); buddies = g_slist_remove(buddies, b); } tmp = roster_groups_join(groups); purple_debug_info("jabber", "jabber_roster_update(%s): [Source: local blist]: groups: %s\n", name, tmp); g_free(tmp); } iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); query = xmlnode_get_child(iq->node, "query"); item = xmlnode_new_child(query, "item"); xmlnode_set_attrib(item, "jid", name); balias = purple_buddy_get_local_buddy_alias(b); xmlnode_set_attrib(item, "name", balias ? balias : ""); for(l = groups; l; l = l->next) { group = xmlnode_new_child(item, "group"); xmlnode_insert_data(group, l->data, -1); } g_slist_free(groups); if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) { jabber_google_roster_outgoing(js, query, item); xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); xmlnode_set_attrib(query, "gr:ext", "2"); } jabber_iq_send(iq); }
static void jabber_presence_set_capabilities(JabberCapsClientInfo *info, GList *exts, JabberPresenceCapabilities *userdata) { JabberBuddyResource *jbr; char *resource = strchr(userdata->from, '/'); if (resource) resource += 1; jbr = jabber_buddy_find_resource(userdata->jb, resource); if (!jbr) { g_free(userdata->from); g_free(userdata); if (exts) { g_list_foreach(exts, (GFunc)g_free, NULL); g_list_free(exts); } return; } /* Any old jbr->caps.info is owned by the caps code */ if (jbr->caps.exts) { g_list_foreach(jbr->caps.exts, (GFunc)g_free, NULL); g_list_free(jbr->caps.exts); } jbr->caps.info = info; jbr->caps.exts = exts; purple_prpl_got_media_caps( purple_connection_get_account(userdata->js->gc), userdata->from); if (info == NULL) goto out; if (!jbr->commands_fetched && jabber_resource_has_capability(jbr, "http://jabber.org/protocol/commands")) { JabberIq *iq = jabber_iq_new_query(userdata->js, JABBER_IQ_GET, NS_DISCO_ITEMS); xmlnode *query = xmlnode_get_child_with_namespace(iq->node, "query", NS_DISCO_ITEMS); xmlnode_set_attrib(iq->node, "to", userdata->from); xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/commands"); jabber_iq_set_callback(iq, jabber_adhoc_disco_result_cb, NULL); jabber_iq_send(iq); jbr->commands_fetched = TRUE; } #if 0 /* * Versions of libpurple before 2.6.0 didn't advertise this capability, so * we can't yet use Entity Capabilities to determine whether or not the * other client supports Chat States. */ if (jabber_resource_has_capability(jbr, "http://jabber.org/protocol/chatstates")) jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED; else jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED; #endif out: g_free(userdata->from); g_free(userdata); }
static void auth_old_cb(JabberStream *js, const char *from, JabberIqType type, const char *id, PurpleXmlNode *packet, gpointer data) { JabberIq *iq; PurpleXmlNode *query, *x; const char *pw = purple_connection_get_password(js->gc); if (type == JABBER_IQ_ERROR) { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); purple_connection_error(js->gc, reason, msg); g_free(msg); } else if (type == JABBER_IQ_RESULT) { query = purple_xmlnode_get_child(packet, "query"); if (js->stream_id && *js->stream_id && purple_xmlnode_get_child(query, "digest")) { char *s, *hash; iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); query = purple_xmlnode_get_child(iq->node, "query"); x = purple_xmlnode_new_child(query, "username"); purple_xmlnode_insert_data(x, js->user->node, -1); x = purple_xmlnode_new_child(query, "resource"); purple_xmlnode_insert_data(x, js->user->resource, -1); x = purple_xmlnode_new_child(query, "digest"); s = g_strdup_printf("%s%s", js->stream_id, pw); hash = jabber_calculate_data_hash(s, strlen(s), "sha1"); purple_xmlnode_insert_data(x, hash, -1); g_free(hash); g_free(s); jabber_iq_set_callback(iq, auth_old_result_cb, NULL); jabber_iq_send(iq); } else if ((x = purple_xmlnode_get_child(query, "crammd5"))) { /* For future reference, this appears to be a custom OS X extension * to non-SASL authentication. */ const char *challenge; gchar digest[33]; PurpleCipher *hmac; PurpleHash *md5; gssize diglen; /* Calculate the MHAC-MD5 digest */ md5 = purple_md5_hash_new(); hmac = purple_hmac_cipher_new(md5); challenge = purple_xmlnode_get_attrib(x, "challenge"); purple_cipher_set_key(hmac, (guchar *)pw, strlen(pw)); purple_cipher_append(hmac, (guchar *)challenge, strlen(challenge)); diglen = purple_cipher_digest_to_str(hmac, digest, 33); g_object_unref(hmac); g_object_unref(md5); g_return_if_fail(diglen > 0); /* Create the response query */ iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); query = purple_xmlnode_get_child(iq->node, "query"); x = purple_xmlnode_new_child(query, "username"); purple_xmlnode_insert_data(x, js->user->node, -1); x = purple_xmlnode_new_child(query, "resource"); purple_xmlnode_insert_data(x, js->user->resource, -1); x = purple_xmlnode_new_child(query, "crammd5"); purple_xmlnode_insert_data(x, digest, 32); jabber_iq_set_callback(iq, auth_old_result_cb, NULL); jabber_iq_send(iq); } else if(purple_xmlnode_get_child(query, "password")) { PurpleAccount *account = purple_connection_get_account(js->gc); if(!jabber_stream_is_ssl(js) && !purple_account_get_bool(account, "auth_plain_in_clear", FALSE)) { char *msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), purple_account_get_username(account)); purple_request_yes_no(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), msg, 1, purple_request_cpar_from_account(account), account, allow_plaintext_auth, disallow_plaintext_auth); g_free(msg); return; } finish_plaintext_authentication(js); } else { purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("Server does not use any supported authentication method")); return; } } }