static gboolean
google_session_handle_initiate(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
{
	const gchar *xmlns;
	GoogleAVSessionData *session_data =
		(GoogleAVSessionData *) session->session_data;

	if (session->state != UNINIT) {
		purple_debug_error("jabber", "Received initiate for active session.\n");
		return FALSE;
	}

	session->description = purple_xmlnode_copy(purple_xmlnode_get_child(sess, "description"));
	xmlns = purple_xmlnode_get_namespace(session->description);

	if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
		session_data->video = FALSE;
	else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO))
		session_data->video = TRUE;
	else {
		purple_debug_error("jabber", "Received initiate with "
				"invalid namespace %s.\n", xmlns);
		return FALSE;
	}

	session_data->media = purple_media_manager_create_media(
			purple_media_manager_get(),
			purple_connection_get_account(js->gc),
			"fsrtpconference", session->remote_jid, FALSE);

	purple_media_set_prpl_data(session_data->media, session);

	g_signal_connect_swapped(G_OBJECT(session_data->media),
			"candidates-prepared",
			G_CALLBACK(google_session_ready), session);
	g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
			G_CALLBACK(google_session_ready), session);
	g_signal_connect(G_OBJECT(session_data->media), "state-changed",
			G_CALLBACK(google_session_state_changed_cb), session);
	g_signal_connect(G_OBJECT(session_data->media), "stream-info",
			G_CALLBACK(google_session_stream_info_cb), session);

	session->iq_id = g_strdup(iq_id);

	if (js->google_relay_host && js->google_relay_token) {
		jabber_google_do_relay_request(js, session,
			jabber_google_relay_response_session_handle_initiate_cb);
	} else {
		jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
			0, 0, 0, NULL, NULL);
	}

	return TRUE;
}
Beispiel #2
0
PurpleXmlNode *
purple_xmlnode_copy(const PurpleXmlNode *src)
{
    PurpleXmlNode *ret;
    PurpleXmlNode *child;
    PurpleXmlNode *sibling = NULL;

    g_return_val_if_fail(src != NULL, NULL);

    ret = new_node(src->name, src->type);
    ret->xmlns = g_strdup(src->xmlns);
    if (src->data) {
        if (src->data_sz) {
            ret->data = g_memdup(src->data, src->data_sz);
            ret->data_sz = src->data_sz;
        } else {
            ret->data = g_strdup(src->data);
        }
    }
    ret->prefix = g_strdup(src->prefix);
    if (src->namespace_map) {
        ret->namespace_map = g_hash_table_new_full(g_str_hash, g_str_equal,
                             g_free, g_free);
        g_hash_table_foreach(src->namespace_map, purple_xmlnode_copy_foreach_ns, ret->namespace_map);
    }

    for (child = src->child; child; child = child->next) {
        if (sibling) {
            sibling->next = purple_xmlnode_copy(child);
            sibling = sibling->next;
        } else {
            ret->child = sibling = purple_xmlnode_copy(child);
        }
        sibling->parent = ret;
    }

    ret->lastchild = sibling;

    return ret;
}
/**
 * Create and insert an identical twin
 *
 * Creates a copy of the specified node and inserts it right after
 * this original node.
 *
 * @param node	The node to clone
 * @return	A pointer to the new, cloned twin if successful
 *		or NULL otherwise.
 */
static PurpleXmlNode *
purple_xmlnode_insert_twin_copy(PurpleXmlNode *node) {
	PurpleXmlNode *copy;

	g_return_val_if_fail(node != NULL, NULL);

	copy = purple_xmlnode_copy(node);
	g_return_val_if_fail(copy != NULL, NULL);

	copy->next = node->next;
	node->next = copy;

	return copy;
}
void
xep_bytestreams_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleBuddy *pb)
{
	const char *type, *from, *iq_id, *sid;
	PurpleXmlNode *query, *streamhost;
	BonjourData *bd;
	PurpleXfer *xfer;

	g_return_if_fail(pc != NULL);
	g_return_if_fail(packet != NULL);
	g_return_if_fail(pb != NULL);

	bd = purple_connection_get_protocol_data(pc);
	if(bd == NULL)
		return;

	purple_debug_info("bonjour", "xep-bytestreams-parse.\n");

	type = purple_xmlnode_get_attrib(packet, "type");
	from = purple_buddy_get_name(pb);
	query = purple_xmlnode_get_child(packet,"query");
	if(!type)
		return;

	query = purple_xmlnode_copy(query);
	if (!query)
		return;

	if(strcmp(type, "set")) {
		purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
		return;
	}

	purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");

	iq_id = purple_xmlnode_get_attrib(packet, "id");

	sid = purple_xmlnode_get_attrib(query, "sid");
	xfer = bonjour_si_xfer_find(bd, sid, from);
	streamhost = purple_xmlnode_get_child(query, "streamhost");

	if(xfer && streamhost && __xep_bytestreams_parse(pb, xfer, streamhost, iq_id))
		return; /* success */

	purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");

	if (iq_id && xfer != NULL)
		xep_ft_si_reject(bd, iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
}
Beispiel #5
0
static gboolean
msn_oim_request_helper(MsnOimRequestData *data)
{
    MsnSession *session = data->oim->session;

    if (data->send) {
        /* The Sending of OIM's uses a different token for some reason. */
        PurpleXmlNode *ticket;
        ticket = purple_xmlnode_get_child(data->body, "Header/Ticket");
        purple_xmlnode_set_attrib(ticket, "passport",
                                  msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE));
    }
    else
    {
        PurpleXmlNode *passport;
        PurpleXmlNode *xml_t;
        PurpleXmlNode *xml_p;
        GHashTable *token;
        const char *msn_t;
        const char *msn_p;

        token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
        g_return_val_if_fail(token != NULL, FALSE);

        msn_t = g_hash_table_lookup(token, "t");
        msn_p = g_hash_table_lookup(token, "p");

        g_return_val_if_fail(msn_t != NULL, FALSE);
        g_return_val_if_fail(msn_p != NULL, FALSE);

        passport = purple_xmlnode_get_child(data->body, "Header/PassportCookie");
        xml_t = purple_xmlnode_get_child(passport, "t");
        xml_p = purple_xmlnode_get_child(passport, "p");

        /* frees old token text, or the 'EMPTY' text if first time */
        purple_xmlnode_free(xml_t->child);
        purple_xmlnode_free(xml_p->child);

        purple_xmlnode_insert_data(xml_t, msn_t, -1);
        purple_xmlnode_insert_data(xml_p, msn_p, -1);
    }

    msn_soap_service_send_message(session->soap,
                                  msn_soap_message_new(data->action, purple_xmlnode_copy(data->body)),
                                  data->host, data->url, FALSE, msn_oim_request_cb, data);

    return FALSE;
}
Beispiel #6
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);
}