gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type) { GoogleSession *session; JabberBuddy *jb; JabberBuddyResource *jbr; gchar *jid; GoogleAVSessionData *session_data = NULL; /* construct JID to send to */ jb = jabber_buddy_find(js, who, FALSE); if (!jb) { purple_debug_error("jingle-rtp", "Could not find Jabber buddy\n"); return FALSE; } jbr = jabber_buddy_find_resource(jb, NULL); if (!jbr) { purple_debug_error("jingle-rtp", "Could not find buddy's resource\n"); } if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) { jid = g_strdup_printf("%s/%s", who, jbr->name); } else { jid = g_strdup(who); } session = g_new0(GoogleSession, 1); session->id.id = jabber_get_next_id(js); session->id.initiator = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource); session->state = SENT_INITIATE; session->js = js; session->remote_jid = jid; session_data = g_new0(GoogleAVSessionData, 1); session->session_data = session_data; if (type & PURPLE_MEDIA_VIDEO) session_data->video = TRUE; /* if we got a relay token and relay host in google:jingleinfo, issue an HTTP request to get that data */ if (js->google_relay_host && js->google_relay_token) { jabber_google_do_relay_request(js, session, jabber_google_relay_response_session_initiate_cb); } else { jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0, NULL, NULL); } /* we don't actually know yet wether it succeeded... maybe this is very wrong... */ return TRUE; }
void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status) { PurpleAccount *account; PurplePresence *presence; JabberBuddy *jb; JabberBuddyResource *jbr; const char *username; JabberBuddyState state; char *msg; int priority; g_return_if_fail(js->user != NULL); account = purple_connection_get_account(js->gc); username = purple_connection_get_display_name(js->gc); presence = purple_account_get_presence(account); if (status == NULL) status = purple_presence_get_active_status(presence); purple_status_to_jabber(status, &state, &msg, &priority); jb = js->user_jb; if (state == JABBER_BUDDY_STATE_UNAVAILABLE || state == JABBER_BUDDY_STATE_UNKNOWN) { jabber_buddy_remove_resource(jb, js->user->resource); } else { jbr = jabber_buddy_track_resource(jb, js->user->resource, priority, state, msg); jbr->idle = purple_presence_is_idle(presence) ? purple_presence_get_idle_time(presence) : 0; } /* * While we need to track the status of this resource, the core * only cares if we're on our own buddy list. */ if (purple_find_buddy(account, username)) { jbr = jabber_buddy_find_resource(jb, NULL); if (jbr) { purple_prpl_got_user_status(account, username, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); purple_prpl_got_user_idle(account, username, jbr->idle, jbr->idle); } else { purple_prpl_got_user_status(account, username, "offline", msg ? "message" : NULL, msg, NULL); } } g_free(msg); }
static void jabber_chat_all_participants_have_capability_foreach(gpointer key, gpointer value, gpointer user_data) { const gchar *cap = ((JabberChatCapsData *) user_data)->cap; gboolean *all_support = ((JabberChatCapsData *) user_data)->all_support; JabberBuddy *jb = ((JabberChatCapsData *) user_data)->jb; JabberChatMember *member = (JabberChatMember *) value; const gchar *resource = member->handle; JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); if (jbr) { *all_support &= jabber_resource_has_capability(jbr, cap); } else { *all_support = FALSE; } }
void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { JabberStream *js = gc->proto_data; char *who; JabberBuddy *jb; JabberBuddyResource *jbr; char *my_bare_jid; if(!js->roster_parsed) return; if(!(who = jabber_get_bare_jid(buddy->name))) return; jb = jabber_buddy_find(js, buddy->name, FALSE); jabber_roster_update(js, who, NULL); my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); if(!strcmp(who, my_bare_jid)) { PurplePresence *gpresence; PurpleStatus *status; gpresence = purple_account_get_presence(js->gc->account); status = purple_presence_get_active_status(gpresence); jabber_presence_fake_to_self(js, status); } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { jabber_presence_subscription_set(js, who, "subscribe"); } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { purple_prpl_got_user_status(gc->account, who, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); } g_free(my_bare_jid); g_free(who); }
void jabber_presence_fake_to_self(JabberStream *js, const char *away_state, const char *msg) { char *my_base_jid; if(!js->user) return; my_base_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); if(gaim_find_buddy(js->gc->account, my_base_jid)) { JabberBuddy *jb; JabberBuddyResource *jbr; if((jb = jabber_buddy_find(js, my_base_jid, TRUE))) { int state = 0; if(away_state) { if(!strcmp(away_state, _("Away")) || (msg && *msg && !strcmp(away_state, GAIM_AWAY_CUSTOM))) state = JABBER_STATE_AWAY; else if(!strcmp(away_state, _("Chatty"))) state = JABBER_STATE_CHAT; else if(!strcmp(away_state, _("Extended Away"))) state = JABBER_STATE_XA; else if(!strcmp(away_state, _("Do Not Disturb"))) state = JABBER_STATE_DND; } if (away_state && !strcmp(away_state, "unavailable")) { jabber_buddy_remove_resource(jb, js->user->resource); } else { jabber_buddy_track_resource(jb, js->user->resource, 0, state, (msg && *msg) ? msg : NULL); } if((jbr = jabber_buddy_find_resource(jb, NULL))) serv_got_update(js->gc, my_base_jid, TRUE, 0, 0, 0, jbr->state); else serv_got_update(js->gc, my_base_jid, FALSE, 0, 0, 0, 0); } } g_free(my_base_jid); }
void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { JabberStream *js = gc->proto_data; char *who; JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr; const char *name; /* If we haven't received the roster yet, ignore any adds */ if (js->state != JABBER_STREAM_CONNECTED) return; name = purple_buddy_get_name(buddy); jid = jabber_id_new(name); if (jid == NULL) { /* TODO: Remove the buddy from the list? */ return; } /* Adding a chat room or a chat buddy to the roster is *not* supported. */ if (jid->node && jabber_chat_find(js, jid->node, jid->domain) != NULL) { /* * This is the same thing Bonjour does. If it causes problems, move * it to an idle callback. */ purple_debug_warning("jabber", "Cowardly refusing to add a MUC user " "to your buddy list and removing the buddy. " "Buddies can only be added by real (non-MUC) " "JID\n"); purple_blist_remove_buddy(buddy); jabber_id_free(jid); return; } who = jabber_id_get_bare_jid(jid); if (jid->resource != NULL) { /* * If the buddy name added contains a resource, strip that off and * rename the buddy. */ purple_blist_rename_buddy(buddy, who); } jb = jabber_buddy_find(js, who, FALSE); purple_debug_info("jabber", "jabber_roster_add_buddy(): Adding %s\n", who); jabber_roster_update(js, who, NULL); if (jb == js->user_jb) { jabber_presence_fake_to_self(js, NULL); } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { jabber_presence_subscription_set(js, who, "subscribe"); } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { purple_prpl_got_user_status(gc->account, who, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); } g_free(who); }
static gboolean handle_presence_contact(JabberStream *js, JabberPresence *presence) { JabberBuddyResource *jbr; PurpleAccount *account; PurpleBuddy *b; char *buddy_name; PurpleConversation *conv; buddy_name = jabber_id_get_bare_jid(presence->jid_from); account = purple_connection_get_account(js->gc); b = purple_find_buddy(account, buddy_name); /* * Unbind/unlock from sending messages to a specific resource on * presence changes. This is locked to a specific resource when * receiving a message (in message.c). */ conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy_name, account); if (conv) { purple_debug_info("jabber", "Changed conversation binding from %s to %s\n", purple_conversation_get_name(conv), buddy_name); purple_conversation_set_name(conv, buddy_name); } if (b == NULL) { if (presence->jb != js->user_jb) { purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%p)\n", buddy_name, purple_account_get_username(account), account); g_free(buddy_name); return FALSE; } else { /* this is a different resource of our own account. Resume even when this account isn't on our blist */ } } if (b && presence->vcard_avatar_hash) { const char *ah = presence->vcard_avatar_hash[0] != '\0' ? presence->vcard_avatar_hash : NULL; const char *ah2 = purple_buddy_icons_get_checksum_for_user(b); if (!purple_strequal(ah, ah2)) { /* XXX this is a crappy way of trying to prevent * someone from spamming us with presence packets * and causing us to DoS ourselves...what we really * need is a queue system that can throttle itself, * but i'm too tired to write that right now */ if(!g_slist_find(js->pending_avatar_requests, presence->jb)) { JabberIq *iq; xmlnode *vcard; js->pending_avatar_requests = g_slist_prepend(js->pending_avatar_requests, presence->jb); iq = jabber_iq_new(js, JABBER_IQ_GET); xmlnode_set_attrib(iq->node, "to", buddy_name); vcard = xmlnode_new_child(iq->node, "vCard"); xmlnode_set_namespace(vcard, "vcard-temp"); jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL); jabber_iq_send(iq); } } } if (presence->state == JABBER_BUDDY_STATE_ERROR || presence->type == JABBER_PRESENCE_UNAVAILABLE || presence->type == JABBER_PRESENCE_UNSUBSCRIBED) { jabber_buddy_remove_resource(presence->jb, presence->jid_from->resource); } else { jbr = jabber_buddy_track_resource(presence->jb, presence->jid_from->resource, presence->priority, presence->state, presence->status); jbr->idle = presence->idle ? time(NULL) - presence->idle : 0; } jbr = jabber_buddy_find_resource(presence->jb, NULL); if (jbr) { jabber_google_presence_incoming(js, buddy_name, jbr); purple_prpl_got_user_status(account, buddy_name, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, "message", jbr->status, NULL); purple_prpl_got_user_idle(account, buddy_name, jbr->idle, jbr->idle); if (presence->nickname) serv_got_alias(js->gc, buddy_name, presence->nickname); } else { purple_prpl_got_user_status(account, buddy_name, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE), presence->status ? "message" : NULL, presence->status, NULL); } g_free(buddy_name); return TRUE; }
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 jabber_si_xfer_init(GaimXfer *xfer) { JabberSIXfer *jsx = xfer->data; JabberIq *iq; if(gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { JabberBuddy *jb; JabberBuddyResource *jbr = NULL; jb = jabber_buddy_find(jsx->js, xfer->who, TRUE); /* XXX */ if(!jb) return; /* XXX: for now, send to the first resource available */ if(g_list_length(jb->resources) >= 1) { char **who_v = g_strsplit(xfer->who, "/", 2); char *who; jbr = jabber_buddy_find_resource(jb, NULL); who = g_strdup_printf("%s/%s", who_v[0], jbr->name); g_strfreev(who_v); g_free(xfer->who); xfer->who = who; jabber_disco_info_do(jsx->js, who, jabber_si_xfer_send_disco_cb, xfer); } else { return; /* XXX: ick */ } } else { xmlnode *si, *feature, *x, *field, *value; iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT); xmlnode_set_attrib(iq->node, "to", xfer->who); if(jsx->iq_id) jabber_iq_set_id(iq, jsx->iq_id); jsx->accepted = TRUE; si = xmlnode_new_child(iq->node, "si"); xmlnode_set_namespace(si, "http://jabber.org/protocol/si"); feature = xmlnode_new_child(si, "feature"); xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg"); x = xmlnode_new_child(feature, "x"); xmlnode_set_namespace(x, "jabber:x:data"); xmlnode_set_attrib(x, "type", "submit"); field = xmlnode_new_child(x, "field"); xmlnode_set_attrib(field, "var", "stream-method"); value = xmlnode_new_child(field, "value"); if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", -1); /* else if(jsx->stream_method & STREAM_METHOD_IBB) xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1); */ jabber_iq_send(iq); } }