示例#1
0
void
jabber_ibb_session_destroy(JabberIBBSession *sess)
{
	purple_debug_info("jabber", "IBB: destroying session %p %s\n", sess,
		sess->sid);

	if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) {
		jabber_ibb_session_close(sess);
	}

	if (sess->last_iq_id) {
		purple_debug_info("jabber", "IBB: removing callback for <iq/> %s\n",
			sess->last_iq_id);
		jabber_iq_remove_callback_by_id(jabber_ibb_session_get_js(sess),
			sess->last_iq_id);
		g_free(sess->last_iq_id);
		sess->last_iq_id = NULL;
	}

	g_hash_table_remove(jabber_ibb_sessions, sess->sid);
	g_free(sess->id);
	g_free(sess->sid);
	g_free(sess->who);
	g_free(sess);
}
示例#2
0
文件: iq.c 项目: bf4/pidgin-mac
void jabber_iq_parse(JabberStream *js, xmlnode *packet)
{
	JabberCallbackData *jcd;
	xmlnode *query, *error, *x;
	const char *xmlns;
	const char *type, *id, *from;
	JabberIqHandler *jih;

	query = xmlnode_get_child(packet, "query");
	type = xmlnode_get_attrib(packet, "type");
	from = xmlnode_get_attrib(packet, "from");
	id = xmlnode_get_attrib(packet, "id");

	if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set")
			|| !strcmp(type, "result") || !strcmp(type, "error"))) {
		purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
						   type ? type : "(null)");
		return;
	}

	/* All IQs must have an ID, so send an error for a set/get that doesn't */
	if(!id || !*id) {

		if(!strcmp(type, "set") || !strcmp(type, "get")) {
			JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);

			xmlnode_free(iq->node);
			iq->node = xmlnode_copy(packet);
			xmlnode_set_attrib(iq->node, "to", from);
			xmlnode_remove_attrib(iq->node, "from");
			xmlnode_set_attrib(iq->node, "type", "error");
			/* This id is clearly not useful, but we must put something there for a valid stanza */
			iq->id = jabber_get_next_id(js);
			xmlnode_set_attrib(iq->node, "id", iq->id);
			error = xmlnode_new_child(iq->node, "error");
			xmlnode_set_attrib(error, "type", "modify");
			x = xmlnode_new_child(error, "bad-request");
			xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas");

			jabber_iq_send(iq);
		} else
			purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type);

		return;
	}

	/* First, lets see if a special callback got registered */

	if(!strcmp(type, "result") || !strcmp(type, "error")) {
		if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) {
			jcd->callback(js, packet, jcd->data);
			jabber_iq_remove_callback_by_id(js, id);
			return;
		}
	}

	/* Apparently not, so lets see if we have a pre-defined handler */

	if(query && (xmlns = xmlnode_get_namespace(query))) {
		if((jih = g_hash_table_lookup(iq_handlers, xmlns))) {
			jih(js, packet);
			return;
		}
	}

	if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) {
		jabber_si_parse(js, packet);
		return;
	}

	if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) {
		jabber_gmail_poke(js, packet);
		return;
	}

	purple_debug_info("jabber", "jabber_iq_parse\n");

	if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) {
		jabber_ping_parse(js, packet);
		return;
	}

	if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) {
		jabber_data_parse(js, packet);
		return;
	}

	/* If we get here, send the default error reply mandated by XMPP-CORE */
	if(!strcmp(type, "set") || !strcmp(type, "get")) {
		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);

		xmlnode_free(iq->node);
		iq->node = xmlnode_copy(packet);
		xmlnode_set_attrib(iq->node, "to", from);
		xmlnode_remove_attrib(iq->node, "from");
		xmlnode_set_attrib(iq->node, "type", "error");
		error = xmlnode_new_child(iq->node, "error");
		xmlnode_set_attrib(error, "type", "cancel");
		xmlnode_set_attrib(error, "code", "501");
		x = xmlnode_new_child(error, "feature-not-implemented");
		xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas");

		jabber_iq_send(iq);
	}
}
示例#3
0
void jabber_iq_parse(JabberStream *js, PurpleXmlNode *packet)
{
	JabberIqCallbackData *jcd;
	PurpleXmlNode *child, *error, *x;
	const char *xmlns;
	const char *iq_type, *id, *from;
	JabberIqType type = JABBER_IQ_NONE;
	gboolean signal_return;
	JabberID *from_id;

	from = purple_xmlnode_get_attrib(packet, "from");
	id = purple_xmlnode_get_attrib(packet, "id");
	iq_type = purple_xmlnode_get_attrib(packet, "type");

	/*
	 * Ensure the 'from' attribute is valid. No point in handling a stanza
	 * of which we don't understand where it came from.
	 */
	from_id = jabber_id_new(from);

	if (from && !from_id) {
		purple_debug_error("jabber", "Received an iq with an invalid from: %s\n", from);
		return;
	}

	/*
	 * child will be either the first tag child or NULL if there is no child.
	 * Historically, we used just the 'query' subchild, but newer XEPs use
	 * differently named children. Grabbing the first child is (for the time
	 * being) sufficient.
	 */
	for (child = packet->child; child; child = child->next) {
		if (child->type == PURPLE_XMLNODE_TYPE_TAG)
			break;
	}

	if (iq_type) {
		if (!strcmp(iq_type, "get"))
			type = JABBER_IQ_GET;
		else if (!strcmp(iq_type, "set"))
			type = JABBER_IQ_SET;
		else if (!strcmp(iq_type, "result"))
			type = JABBER_IQ_RESULT;
		else if (!strcmp(iq_type, "error"))
			type = JABBER_IQ_ERROR;
	}

	if (type == JABBER_IQ_NONE) {
		purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
						   iq_type ? iq_type : "(null)");
		jabber_id_free(from_id);
		return;
	}

	/* All IQs must have an ID, so send an error for a set/get that doesn't */
	if(!id || !*id) {

		if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) {
			JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);

			purple_xmlnode_free(iq->node);
			iq->node = purple_xmlnode_copy(packet);
			if (from) {
				purple_xmlnode_set_attrib(iq->node, "to", from);
				purple_xmlnode_remove_attrib(iq->node, "from");
			}

			purple_xmlnode_set_attrib(iq->node, "type", "error");
			/* This id is clearly not useful, but we must put something there for a valid stanza */
			iq->id = jabber_get_next_id(js);
			purple_xmlnode_set_attrib(iq->node, "id", iq->id);
			error = purple_xmlnode_new_child(iq->node, "error");
			purple_xmlnode_set_attrib(error, "type", "modify");
			x = purple_xmlnode_new_child(error, "bad-request");
			purple_xmlnode_set_namespace(x, NS_XMPP_STANZAS);

			jabber_iq_send(iq);
		} else
			purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n",
			                   iq_type);

		jabber_id_free(from_id);
		return;
	}

	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc),
			"jabber-receiving-iq", js->gc, iq_type, id, from, packet));
	if (signal_return) {
		jabber_id_free(from_id);
		return;
	}

	/* First, lets see if a special callback got registered */
	if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) {
		jcd = g_hash_table_lookup(js->iq_callbacks, id);
		if (jcd) {
			if (does_reply_from_match_request_to(js, jcd->to, from_id)) {
				jcd->callback(js, from, type, id, packet, jcd->data);
				jabber_iq_remove_callback_by_id(js, id);
				jabber_id_free(from_id);
				return;
			} else {
				char *expected_to;

				if (jcd->to) {
					expected_to = jabber_id_get_full_jid(jcd->to);
				} else {
					expected_to = jabber_id_get_bare_jid(js->user);
				}

				purple_debug_error("jabber", "Got a result iq with id %s from %s instead of expected %s!\n", id, from ? from : "(null)", expected_to);

				g_free(expected_to);
			}
		}
	}

	/*
	 * Apparently not, so let's see if we have a pre-defined handler
	 * or if an outside plugin is interested.
	 */
	if(child && (xmlns = purple_xmlnode_get_namespace(child))) {
		char *key = g_strdup_printf("%s %s", child->name, xmlns);
		JabberIqHandler *jih = g_hash_table_lookup(iq_handlers, key);
		int signal_ref = GPOINTER_TO_INT(g_hash_table_lookup(signal_iq_handlers, key));
		g_free(key);

		if (signal_ref > 0) {
			signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), "jabber-watched-iq",
					js->gc, iq_type, id, from, child));
			if (signal_return) {
				jabber_id_free(from_id);
				return;
			}
		}

		if(jih) {
			jih(js, from, type, id, child);
			jabber_id_free(from_id);
			return;
		}
	}

	purple_debug_misc("jabber", "Unhandled IQ with id %s\n", id);

	/* If we get here, send the default error reply mandated by XMPP-CORE */
	if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) {
		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);

		purple_xmlnode_free(iq->node);
		iq->node = purple_xmlnode_copy(packet);
		if (from) {
			purple_xmlnode_set_attrib(iq->node, "to", from);
			purple_xmlnode_remove_attrib(iq->node, "from");
		}

		purple_xmlnode_set_attrib(iq->node, "type", "error");
		error = purple_xmlnode_new_child(iq->node, "error");
		purple_xmlnode_set_attrib(error, "type", "cancel");
		purple_xmlnode_set_attrib(error, "code", "501");
		x = purple_xmlnode_new_child(error, "feature-not-implemented");
		purple_xmlnode_set_namespace(x, NS_XMPP_STANZAS);

		jabber_iq_send(iq);
	}

	jabber_id_free(from_id);
}