Mercurial > pidgin.yaz
diff libpurple/protocols/jabber/jabber.c @ 25982:7e020fbe2cdb
propagate from branch 'im.pidgin.pidgin' (head 303af74a38e7b313d4fb0be4d4054a16cb13d819)
to branch 'im.pidgin.cpw.darkrain42.xmpp.avatars' (head 11e989f3ac36a0f958f031d55245db093923ea76)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sat, 07 Mar 2009 01:32:29 +0000 |
parents | 2d92bbe6807b 5f9a24d1c25e |
children | 7027cc42e56c |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jabber.c Sat Feb 14 18:23:13 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sat Mar 07 01:32:29 2009 +0000 @@ -149,7 +149,8 @@ } static char *jabber_prep_resource(char *input) { - char hostname[256]; /* current hostname */ + char hostname[256], /* current hostname */ + *dot = NULL; /* Empty resource == don't send any */ if (input == NULL || *input == '\0') @@ -171,6 +172,12 @@ } hostname[sizeof(hostname) - 1] = '\0'; + /* We want only the short hostname, not the FQDN - this will prevent the + * resource string from being unreasonably long on systems which stuff the + * whole FQDN in the hostname */ + if((dot = strchr(hostname, '.'))) + dot = '\0'; + return purple_strreplace(input, "__HOSTNAME__", hostname); } @@ -178,7 +185,7 @@ { if(xmlnode_get_child(packet, "starttls")) { if(jabber_process_starttls(js, packet)) - + return; } else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) { purple_connection_error_reason (js->gc, @@ -461,10 +468,10 @@ if (js->keepalive_timeout == -1) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET); - + xmlnode *ping = xmlnode_new_child(iq->node, "ping"); xmlnode_set_namespace(ping, "urn:xmpp:ping"); - + js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc); jabber_iq_set_callback(iq, jabber_pong_cb, NULL); jabber_iq_send(iq); @@ -572,7 +579,7 @@ jabber_send_raw(js, "<?xml version='1.0' ?>", -1); jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING); purple_ssl_input_add(gsc, jabber_recv_cb_ssl, gc); - + /* Tell the app that we're doing encryption */ jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION); } @@ -731,7 +738,7 @@ _("Invalid XMPP ID")); return; } - + if (!js->user->domain || *(js->user->domain) == '\0') { purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, @@ -815,10 +822,11 @@ js->user->node, js->user->domain); if(account->registration_cb) (account->registration_cb)(account, TRUE, account->registration_cb_user_data); - } - else + } else { + g_return_if_fail(to != NULL); buf = g_strdup_printf(_("Registration to %s successful"), to); + } purple_notify_info(NULL, _("Registration Successful"), _("Registration Successful"), buf); g_free(buf); @@ -845,7 +853,11 @@ const char *type = xmlnode_get_attrib(packet, "type"); char *buf; char *to = data; - + + /* This function is never called for unregistering our XMPP account from + * the server, so there should always be a 'to' address. */ + g_return_if_fail(to != NULL); + if(!strcmp(type, "result")) { buf = g_strdup_printf(_("Registration from %s successfully removed"), to); @@ -854,10 +866,10 @@ g_free(buf); } else { char *msg = jabber_parse_error(js, packet, NULL); - + if(!msg) msg = g_strdup(_("Unknown Error")); - + purple_notify_error(NULL, _("Unregistration Failed"), _("Unregistration Failed"), msg); g_free(msg); @@ -880,7 +892,8 @@ iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register"); query = xmlnode_get_child(iq->node, "query"); - xmlnode_set_attrib(iq->node, "to", cbdata->who); + if (cbdata->who) + xmlnode_set_attrib(iq->node, "to", cbdata->who); for(groups = purple_request_fields_get_groups(fields); groups; groups = groups->next) { @@ -896,11 +909,12 @@ jabber_iq_free(iq); iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register"); query = xmlnode_get_child(iq->node, "query"); - xmlnode_set_attrib(iq->node,"to",cbdata->who); + if (cbdata->who) + xmlnode_set_attrib(iq->node,"to",cbdata->who); xmlnode_new_child(query, "remove"); - + jabber_iq_set_callback(iq, jabber_unregistration_result_cb, cbdata->who); - + jabber_iq_send(iq); g_free(cbdata); return; @@ -941,8 +955,7 @@ } xmlnode_insert_data(y, value, -1); if(cbdata->js->registration && !strcmp(id, "username")) { - if(cbdata->js->user->node) - g_free(cbdata->js->user->node); + g_free(cbdata->js->user->node); cbdata->js->user->node = g_strdup(value); } if(cbdata->js->registration && !strcmp(id, "password")) @@ -985,7 +998,8 @@ iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register"); query = xmlnode_get_child(iq->node, "query"); - xmlnode_set_attrib(iq->node,"to",to); + if (to) + xmlnode_set_attrib(iq->node,"to",to); xmlnode_insert_child(query, result); @@ -1010,10 +1024,7 @@ return; from = xmlnode_get_attrib(packet, "from"); - if (!from) - from = js->serverFQDN; - g_return_if_fail(from != NULL); - + if(js->registration) { /* get rid of the login thingy */ purple_connection_set_state(js->gc, PURPLE_CONNECTED); @@ -1033,12 +1044,12 @@ return; } } - - if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:data"))) { + + if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) { jabber_x_data_request(js, x, jabber_register_x_data_cb, g_strdup(from)); return; - } else if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:oob"))) { + } else if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:oob"))) { xmlnode *url; if((url = xmlnode_get_child(x, "url"))) { @@ -1158,7 +1169,9 @@ purple_connection_get_account(js->gc), NULL, NULL, cbdata); else { - char *title = registered?g_strdup_printf(_("Change Account Registration at %s"), from) + char *title; + g_return_if_fail(from != NULL); + title = registered ? g_strdup_printf(_("Change Account Registration at %s"), from) :g_strdup_printf(_("Register New Account at %s"), from); purple_request_fields(js->gc, title, title, instructions, fields, @@ -1182,7 +1195,7 @@ void jabber_register_gateway(JabberStream *js, const char *gateway) { JabberIq *iq; - + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:register"); xmlnode_set_attrib(iq->node, "to", gateway); jabber_iq_send(iq); @@ -1257,7 +1270,7 @@ const char *type = xmlnode_get_attrib(packet,"type"); if(!strcmp(type,"error")) { char *msg = jabber_parse_error(js, packet, NULL); - + purple_notify_error(js->gc, _("Error unregistering account"), _("Error unregistering account"), msg); g_free(msg); @@ -1291,7 +1304,7 @@ void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) { PurpleConnection *gc = purple_account_get_connection(account); JabberStream *js; - + if(gc->state != PURPLE_CONNECTED) { if(gc->state != PURPLE_CONNECTING) jabber_login(account); @@ -1301,7 +1314,7 @@ js->unregistration_user_data = user_data; return; } - + js = gc->proto_data; if (js->unregistration) { @@ -1603,10 +1616,10 @@ feat->shortname = g_strdup(shortname); feat->namespace = g_strdup(namespace); feat->is_enabled = cb; - + /* try to remove just in case it already exists in the list */ jabber_remove_feature(shortname); - + jabber_features = g_list_append(jabber_features, feat); } @@ -1617,7 +1630,7 @@ if(!strcmp(feat->shortname, shortname)) { g_free(feat->shortname); g_free(feat->namespace); - + g_free(feature->data); jabber_features = g_list_delete_link(jabber_features, feature); break; @@ -1634,13 +1647,14 @@ { JabberStream *js; JabberBuddy *jb = NULL; - - if(!b->account->gc) + PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(b)); + + if(!gc) return NULL; - js = b->account->gc->proto_data; + js = gc->proto_data; if(js) - jb = jabber_buddy_find(js, b->name, FALSE); + jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE); if(!PURPLE_BUDDY_IS_ONLINE(b)) { if(jb && (jb->subscription & JABBER_SUB_PENDING || @@ -1654,9 +1668,11 @@ { char *ret = NULL; JabberBuddy *jb = NULL; - - if (b->account->gc && b->account->gc->proto_data) - jb = jabber_buddy_find(b->account->gc->proto_data, b->name, FALSE); + PurpleAccount *account = purple_buddy_get_account(b); + PurpleConnection *gc = purple_account_get_connection(account); + + if (gc && gc->proto_data) + jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE); if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) { ret = g_strdup(_("Not Authorized")); @@ -1685,14 +1701,19 @@ void jabber_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { JabberBuddy *jb; + PurpleAccount *account; + PurpleConnection *gc; g_return_if_fail(b != NULL); - g_return_if_fail(b->account != NULL); - g_return_if_fail(b->account->gc != NULL); - g_return_if_fail(b->account->gc->proto_data != NULL); - - jb = jabber_buddy_find(b->account->gc->proto_data, b->name, - FALSE); + + account = purple_buddy_get_account(b); + g_return_if_fail(account != NULL); + + gc = purple_account_get_connection(account); + g_return_if_fail(gc != NULL); + g_return_if_fail(gc->proto_data != NULL); + + jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE); if(jb) { JabberBuddyResource *jbr = NULL; @@ -1800,9 +1821,12 @@ PurpleStatusType *type; GList *types = NULL; PurpleValue *priority_value; + PurpleValue *buzz_enabled; priority_value = purple_value_new(PURPLE_TYPE_INT); purple_value_set_int(priority_value, 1); + buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); + purple_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_ONLINE), NULL, TRUE, TRUE, FALSE, @@ -1811,12 +1835,14 @@ "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), - "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), + "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_append(types, type); priority_value = purple_value_new(PURPLE_TYPE_INT); purple_value_set_int(priority_value, 1); + buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); + purple_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_CHAT), _("Chatty"), TRUE, TRUE, FALSE, @@ -1825,12 +1851,14 @@ "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), - "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), + "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_append(types, type); priority_value = purple_value_new(PURPLE_TYPE_INT); purple_value_set_int(priority_value, 0); + buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); + purple_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_AWAY), NULL, TRUE, TRUE, FALSE, @@ -1839,12 +1867,14 @@ "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), - "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), + "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_append(types, type); priority_value = purple_value_new(PURPLE_TYPE_INT); purple_value_set_int(priority_value, 0); + buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); + purple_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_XA), NULL, TRUE, TRUE, FALSE, @@ -1853,7 +1883,7 @@ "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), - "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), + "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_append(types, type); @@ -1867,7 +1897,6 @@ "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), - "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN), NULL); types = g_list_append(types, type); @@ -2013,7 +2042,7 @@ if(js->pep) jabber_pep_init_actions(&m); - + if(js->commands) jabber_adhoc_init_server_commands(js, &m); @@ -2028,19 +2057,24 @@ if(!(jid = jabber_id_new(name))) return NULL; - for(gnode = purple_get_blist()->root; gnode; gnode = gnode->next) { - for(cnode = gnode->child; cnode; cnode = cnode->next) { + for(gnode = purple_blist_get_root(); gnode; + gnode = purple_blist_node_get_sibling_next(gnode)) { + for(cnode = purple_blist_node_get_first_child(gnode); + cnode; + cnode = purple_blist_node_get_sibling_next(cnode)) { PurpleChat *chat = (PurpleChat*)cnode; const char *room, *server; + GHashTable *components; if(!PURPLE_BLIST_NODE_IS_CHAT(cnode)) continue; - if(chat->account != account) + if (purple_chat_get_account(chat) != account) continue; - if(!(room = g_hash_table_lookup(chat->components, "room"))) + components = purple_chat_get_components(chat); + if(!(room = g_hash_table_lookup(components, "room"))) continue; - if(!(server = g_hash_table_lookup(chat->components, "server"))) + if(!(server = g_hash_table_lookup(components, "server"))) continue; if(jid->node && jid->domain && @@ -2060,7 +2094,7 @@ JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr; - + if(!(jid = jabber_id_new(who))) return; @@ -2321,7 +2355,7 @@ if (!chat || !args || !args[0] || !args[1]) return PURPLE_CMD_RET_FAILED; - if (strcmp(args[1], "owner") != 0 && + if (strcmp(args[1], "owner") != 0 && strcmp(args[1], "admin") != 0 && strcmp(args[1], "member") != 0 && strcmp(args[1], "outcast") != 0 && @@ -2450,63 +2484,92 @@ JabberBuddy *jb; JabberBuddyResource *jbr; - GList *iter; + PurpleConnection *gc = js->gc; + PurpleBuddy *buddy = + purple_find_buddy(purple_connection_get_account(gc), username); + const gchar *alias = + buddy ? purple_buddy_get_contact_alias(buddy) : username; if(!username) return FALSE; jb = jabber_buddy_find(js, username, FALSE); if(!jb) { - *error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), username); + *error = g_strdup_printf(_("Unable to buzz, because there is nothing " + "known about %s."), alias); return FALSE; } jbr = jabber_buddy_find_resource(jb, NULL); - if(!jbr) { - *error = g_strdup_printf(_("Unable to buzz, because user %s might be offline."), username); - return FALSE; - } - - if(!jbr->caps) { - *error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), username); + if (!jbr) { + *error = g_strdup_printf(_("Unable to buzz, because %s might be offline."), + alias); return FALSE; } - for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) { - if(!strcmp(iter->data, "http://www.xmpp.org/extensions/xep-0224.html#ns")) { - xmlnode *buzz, *msg = xmlnode_new("message"); - gchar *to; - - to = g_strdup_printf("%s/%s", username, jbr->name); - xmlnode_set_attrib(msg, "to", to); - g_free(to); - - /* avoid offline storage */ - xmlnode_set_attrib(msg, "type", "headline"); - - buzz = xmlnode_new_child(msg, "attention"); - xmlnode_set_namespace(buzz, "http://www.xmpp.org/extensions/xep-0224.html#ns"); - - jabber_send(js, msg); - xmlnode_free(msg); - - return TRUE; - } + if (jabber_resource_has_capability(jbr, XEP_0224_NAMESPACE)) { + xmlnode *buzz, *msg = xmlnode_new("message"); + gchar *to; + + to = g_strdup_printf("%s/%s", username, jbr->name); + xmlnode_set_attrib(msg, "to", to); + g_free(to); + + /* avoid offline storage */ + xmlnode_set_attrib(msg, "type", "headline"); + + buzz = xmlnode_new_child(msg, "attention"); + xmlnode_set_namespace(buzz, XEP_0224_NAMESPACE); + + jabber_send(js, msg); + xmlnode_free(msg); + + return TRUE; + } else { + *error = g_strdup_printf(_("Unable to buzz, because %s does " + "not support it or do not wish to receive buzzes now."), alias); + return FALSE; } - - *error = g_strdup_printf(_("Unable to buzz, because the user %s does not support it."), username); - return FALSE; } static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { JabberStream *js = conv->account->gc->proto_data; - - if(!args || !args[0]) + const gchar *who; + + if (!args || !args[0]) { + /* use the buddy from conversation, if it's a one-to-one conversation */ + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + who = purple_conversation_get_name(conv); + } else { + return PURPLE_CMD_RET_FAILED; + } + } else { + who = args[0]; + } + + if (_jabber_send_buzz(js, who, error)) { + const gchar *alias; + gchar *str; + PurpleBuddy *buddy = + purple_find_buddy(purple_connection_get_account(conv->account->gc), + who); + + if (buddy != NULL) + alias = purple_buddy_get_contact_alias(buddy); + else + alias = who; + + str = g_strdup_printf(_("Buzzing %s..."), alias); + purple_conversation_write(conv, NULL, str, + PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); + g_free(str); + + return PURPLE_CMD_RET_OK; + } else { return PURPLE_CMD_RET_FAILED; - - return _jabber_send_buzz(js, args[0], error) ? PURPLE_CMD_RET_OK : PURPLE_CMD_RET_FAILED; + } } GList *jabber_attention_types(PurpleAccount *account) @@ -2619,8 +2682,9 @@ "prpl-jabber", jabber_cmd_ping, _("ping <jid>: Ping a user/component/server."), NULL); - purple_cmd_register("buzz", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("buzz", "w", PURPLE_CMD_P_PRPL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY | + PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_buzz, _("buzz: Buzz a user to get their attention"), NULL); }