# HG changeset patch # User Sean Egan # Date 1180414590 0 # Node ID 837b697723c05b1da6b2d6ed65cbdc991e230103 # Parent 2284a8aad9ef10e46ee646cf2c9e32daf4a2242b# Parent fae50c8130d3e36f3033cf4df458e2b358ef7a75 merge of '4af1e220d3ae855eec7a057ef1e41b586abb8f5f' and 'c5effd605c706950531cbca778c43fafa75e1109' diff -r fae50c8130d3 -r 837b697723c0 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Mon May 28 19:56:40 2007 +0000 +++ b/libpurple/protocols/jabber/disco.c Tue May 29 04:56:30 2007 +0000 @@ -224,17 +224,17 @@ /* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */ jabber_roster_request(js); } - + /* Send initial presence; this will trigger receipt of presence for contacts on the roster */ gpresence = purple_account_get_presence(js->gc->account); status = purple_presence_get_active_status(gpresence); - jabber_presence_send(js->gc->account, status); + jabber_presence_send(js->gc->account, status); } static void jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data) { - xmlnode *query, *child; + xmlnode *query, *child; const char *from = xmlnode_get_attrib(packet, "from"); const char *type = xmlnode_get_attrib(packet, "type"); @@ -257,7 +257,7 @@ return; } - for (child = xmlnode_get_child(query, "identity"); child; + for (child = xmlnode_get_child(query, "identity"); child; child = xmlnode_get_next_twin(child)) { const char *category, *type, *name; category = xmlnode_get_attrib(child, "category"); @@ -266,7 +266,7 @@ type = xmlnode_get_attrib(child, "type"); if (!type || strcmp(type, "im")) continue; - + name = xmlnode_get_attrib(child, "name"); if (!name) continue; @@ -279,7 +279,7 @@ } } - for (child = xmlnode_get_child(query, "feature"); child; + for (child = xmlnode_get_child(query, "feature"); child; child = xmlnode_get_next_twin(child)) { const char *var; var = xmlnode_get_attrib(child, "var"); @@ -324,11 +324,16 @@ for(child = xmlnode_get_child(query, "item"); child; child = xmlnode_get_next_twin(child)) { JabberIq *iq; - const char *jid; + const char *jid, *node; if(!(jid = xmlnode_get_attrib(child, "jid"))) continue; + /* we don't actually care about the specific nodes, + * so we won't query them */ + if((node = xmlnode_get_attrib(child, "node"))) + continue; + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); xmlnode_set_attrib(iq->node, "to", jid); jabber_iq_send(iq); diff -r fae50c8130d3 -r 837b697723c0 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Mon May 28 19:56:40 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Tue May 29 04:56:30 2007 +0000 @@ -106,11 +106,12 @@ return; disconnected = purple_account_is_disconnected(account); - primitive = purple_status_type_get_primitive(purple_status_get_type(status)); if(disconnected) return; + primitive = purple_status_type_get_primitive(purple_status_get_type(status)); + gc = purple_account_get_connection(account); js = gc->proto_data; diff -r fae50c8130d3 -r 837b697723c0 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Mon May 28 19:56:40 2007 +0000 +++ b/libpurple/protocols/jabber/si.c Tue May 29 04:56:30 2007 +0000 @@ -26,6 +26,7 @@ #include "cipher.h" #include "debug.h" #include "ft.h" +#include "request.h" #include "network.h" #include "notify.h" @@ -769,6 +770,36 @@ } } +static void resource_select_cancel_cb(PurpleXfer *xfer, PurpleRequestFields *fields) +{ + purple_xfer_cancel_local(xfer); +} + +static void do_transfer_send(PurpleXfer *xfer, const char *resource) +{ + JabberSIXfer *jsx = xfer->data; + char **who_v = g_strsplit(xfer->who, "/", 2); + char *who; + + who = g_strdup_printf("%s/%s", who_v[0], resource); + 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); +} + +static void resource_select_ok_cb(PurpleXfer *xfer, PurpleRequestFields *fields) +{ + PurpleRequestField *field = purple_request_fields_get_field(fields, "resource"); + int selected_id = purple_request_field_choice_get_value(field); + GList *labels = purple_request_field_choice_get_labels(field); + + const char *selected_label = g_list_nth_data(labels, selected_id); + + do_transfer_send(xfer, selected_label); +} + static void jabber_si_xfer_init(PurpleXfer *xfer) { JabberSIXfer *jsx = xfer->data; @@ -776,26 +807,65 @@ if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { JabberBuddy *jb; JabberBuddyResource *jbr = NULL; + char *resource; + + if(NULL != (resource = jabber_get_resource(xfer->who))) { + /* they've specified a resource, no need to ask or + * default or anything, just do it */ + + do_transfer_send(xfer, resource); + g_free(resource); + } jb = jabber_buddy_find(jsx->js, xfer->who, TRUE); - /* XXX */ - if(!jb) - return; + + if(!jb || !jb->resources) { + /* no resources online, we're trying to send to someone + * whose presence we're not subscribed to, or + * someone who is offline. Let's inform the user */ + char *msg; - /* XXX: for now, send to the first resource available */ - if(jb->resources != NULL) { - char **who_v = g_strsplit(xfer->who, "/", 2); - char *who; + if(!jb) { + msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who); + } else if(jb->subscription & JABBER_SUB_TO) { + msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who); + } else { + msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who); + } + + purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg); + g_free(msg); + } else if(g_list_length(jb->resources) == 1) { + /* only 1 resource online (probably our most common case) + * so no need to ask who to send to */ + jbr = jb->resources->data; + + do_transfer_send(xfer, jbr->name); - 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 */ + /* we've got multiple resources, we need to pick one to send to */ + GList *l; + char *msg = g_strdup_printf(_("Please select which resource of %s you would like to send a file to"), xfer->who); + PurpleRequestFields *fields = purple_request_fields_new(); + PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0); + PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL); + + for(l = jb->resources; l; l = l->next) + { + jbr = l->data; + + purple_request_field_choice_add(field, jbr->name); + } + + purple_request_field_group_add_field(group, field); + + purple_request_fields_add_group(fields, group); + + purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields, + _("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb), + jsx->js->gc->account, xfer->who, NULL, xfer); + + g_free(msg); } } else { xmlnode *si, *feature, *x, *field, *value;