static void roster_request_cb(JabberStream *js, const char *from, JabberIqType type, const char *id, xmlnode *packet, gpointer data) { xmlnode *query; if (type == JABBER_IQ_ERROR) { /* * This shouldn't happen in any real circumstances and * likely constitutes a server-side misconfiguration (i.e. * explicitly not loading mod_roster...) */ purple_debug_error("jabber", "Error retrieving roster!?\n"); jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); return; } query = xmlnode_get_child(packet, "query"); if (query == NULL) { jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); return; } jabber_roster_parse(js, from, type, id, query); jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); }
static void auth_old_result_cb(JabberStream *js, const char *from, JabberIqType type, const char *id, PurpleXmlNode *packet, gpointer data) { if (type == JABBER_IQ_RESULT) { jabber_stream_set_state(js, JABBER_STREAM_POST_AUTH); jabber_disco_items_server(js); } else { PurpleAccount *account; PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); PurpleXmlNode *error; const char *err_code; account = purple_connection_get_account(js->gc); /* FIXME: Why is this not in jabber_parse_error? */ if((error = purple_xmlnode_get_child(packet, "error")) && (err_code = purple_xmlnode_get_attrib(error, "code")) && g_str_equal(err_code, "401")) { reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; /* Clear the pasword if it isn't being saved */ if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL, NULL, NULL); } purple_connection_error(js->gc, reason, msg); g_free(msg); } }
void jabber_auth_handle_success(JabberStream *js, PurpleXmlNode *packet) { const char *ns = purple_xmlnode_get_namespace(packet); if (!purple_strequal(ns, NS_XMPP_SASL)) { purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); return; } if (js->auth_mech && js->auth_mech->handle_success) { char *msg = NULL; JabberSaslState state = js->auth_mech->handle_success(js, packet, &msg); if (state == JABBER_SASL_STATE_FAIL) { purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Invalid response from server")); return; } else if (state == JABBER_SASL_STATE_CONTINUE) { purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Server thinks authentication is complete, but client does not")); return; } g_free(msg); } /* * The stream will be reinitialized later in jabber_recv_cb_ssl() or * jabber_bosh_connection_send. */ js->reinit = TRUE; jabber_stream_set_state(js, JABBER_STREAM_POST_AUTH); }
static void boot_response_cb(PurpleBOSHConnection *conn, xmlnode *node) { JabberStream *js = conn->js; const char *sid, *version; const char *inactivity, *requests; xmlnode *packet; g_return_if_fail(node != NULL); if (jabber_bosh_connection_error_check(conn, node)) return; sid = xmlnode_get_attrib(node, "sid"); version = xmlnode_get_attrib(node, "ver"); inactivity = xmlnode_get_attrib(node, "inactivity"); requests = xmlnode_get_attrib(node, "requests"); if (sid) { conn->sid = g_strdup(sid); } else { purple_connection_error_reason(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("No session ID given")); return; } if (version) { const char *dot = strchr(version, '.'); int major, minor = 0; purple_debug_info("jabber", "BOSH connection manager version %s\n", version); major = atoi(version); if (dot) minor = atoi(dot + 1); if (major != 1 || minor < 6) { purple_connection_error_reason(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unsupported version of BOSH protocol")); return; } } else { purple_debug_info("jabber", "Missing version in BOSH initiation\n"); } if (inactivity) { js->max_inactivity = atoi(inactivity); if (js->max_inactivity <= 5) { purple_debug_warning("jabber", "Ignoring bogusly small inactivity: %s\n", inactivity); /* Leave it at the default */ } else { /* TODO: Can this check fail? It shouldn't */ js->max_inactivity -= 5; /* rounding */ if (js->inactivity_timer == 0) { purple_debug_misc("jabber", "Starting BOSH inactivity timer " "for %d secs (compensating for rounding)\n", js->max_inactivity); jabber_stream_restart_inactivity_timer(js); } } } if (requests) conn->max_requests = atoi(requests); jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING); /* FIXME: Depending on receiving features might break with some hosts */ packet = xmlnode_get_child(node, "features"); conn->state = BOSH_CONN_ONLINE; conn->receive_cb = jabber_bosh_connection_received; jabber_stream_features_parse(js, packet); }
void jabber_roster_parse(JabberStream *js, const char *from, JabberIqType type, const char *id, xmlnode *query) { xmlnode *item, *group; if (!jabber_is_own_account(js, from)) { purple_debug_warning("jabber", "Received bogon roster push from %s\n", from); return; } js->currently_parsing_roster_push = TRUE; for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid, *name, *subscription, *ask; JabberBuddy *jb; subscription = xmlnode_get_attrib(item, "subscription"); jid = xmlnode_get_attrib(item, "jid"); name = xmlnode_get_attrib(item, "name"); ask = xmlnode_get_attrib(item, "ask"); if(!jid) continue; if(!(jb = jabber_buddy_find(js, jid, TRUE))) continue; if(subscription) { if (jb == js->user_jb) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "none")) jb->subscription = JABBER_SUB_NONE; else if(!strcmp(subscription, "to")) jb->subscription = JABBER_SUB_TO; else if(!strcmp(subscription, "from")) jb->subscription = JABBER_SUB_FROM; else if(!strcmp(subscription, "both")) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "remove")) jb->subscription = JABBER_SUB_REMOVE; } if(purple_strequal(ask, "subscribe")) jb->subscription |= JABBER_SUB_PENDING; else jb->subscription &= ~JABBER_SUB_PENDING; if(jb->subscription & JABBER_SUB_REMOVE) { remove_purple_buddies(js, jid); } else { GSList *groups = NULL; gboolean seen_empty = FALSE; if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) if (!jabber_google_roster_incoming(js, item)) continue; for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { char *group_name = xmlnode_get_data(group); if (!group_name && !seen_empty) { group_name = g_strdup(""); seen_empty = TRUE; } groups = g_slist_prepend(groups, group_name); } add_purple_buddy_to_groups(js, jid, name, groups); if (jb == js->user_jb) jabber_presence_fake_to_self(js, NULL); } } js->currently_parsing_roster_push = FALSE; /* if we're just now parsing the roster for the first time, * then now would be the time to declare ourselves connected. */ if (js->state != JABBER_STREAM_CONNECTED) jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); }
static void jabber_bosh_connection_session_created(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer _bosh_conn) { PurpleJabberBOSHConnection *bosh_conn = _bosh_conn; PurpleXmlNode *node, *features; const gchar *sid, *ver, *inactivity_str; int inactivity = 0; bosh_conn->sc_req = NULL; if (purple_debug_is_verbose() && purple_debug_is_unsafe()) { purple_debug_misc("jabber-bosh", "received (session creation): %s\n", purple_http_response_get_data(response, NULL)); } node = jabber_bosh_connection_parse(bosh_conn, response); if (node == NULL) return; sid = purple_xmlnode_get_attrib(node, "sid"); ver = purple_xmlnode_get_attrib(node, "ver"); inactivity_str = purple_xmlnode_get_attrib(node, "inactivity"); /* requests = purple_xmlnode_get_attrib(node, "requests"); */ if (!sid) { purple_connection_error(bosh_conn->js->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("No BOSH session ID given")); purple_xmlnode_free(node); return; } if (ver == NULL) { purple_debug_info("jabber-bosh", "Missing version in BOSH initiation\n"); } else if (!jabber_bosh_version_check(ver, 1, 6)) { purple_debug_error("jabber-bosh", "Unsupported BOSH version: %s\n", ver); purple_connection_error(bosh_conn->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unsupported version of BOSH protocol")); purple_xmlnode_free(node); return; } purple_debug_misc("jabber-bosh", "Session created for %p\n", bosh_conn); bosh_conn->sid = g_strdup(sid); if (inactivity_str) inactivity = atoi(inactivity_str); if (inactivity < 0 || inactivity > 3600) { purple_debug_warning("jabber-bosh", "Ignoring invalid " "inactivity value: %s\n", inactivity_str); inactivity = 0; } if (inactivity > 0) { inactivity -= 5; /* rounding */ if (inactivity <= 0) inactivity = 1; bosh_conn->js->max_inactivity = inactivity; if (bosh_conn->js->inactivity_timer == 0) { purple_debug_misc("jabber-bosh", "Starting inactivity " "timer for %d secs (compensating for " "rounding)\n", inactivity); jabber_stream_restart_inactivity_timer(bosh_conn->js); } } jabber_stream_set_state(bosh_conn->js, JABBER_STREAM_AUTHENTICATING); /* FIXME: Depending on receiving features might break with some hosts */ features = purple_xmlnode_get_child(node, "features"); jabber_stream_features_parse(bosh_conn->js, features); purple_xmlnode_free(node); jabber_bosh_connection_send(bosh_conn, NULL); }