static void
google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
		gchar *sid, gchar *name, gboolean local,
		GoogleSession *session)
{
	if (sid != NULL || name != NULL)
		return;

	if (type == PURPLE_MEDIA_INFO_HANGUP) {
		xmlnode *sess;
		JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);

		xmlnode_set_attrib(iq->node, "to", session->remote_jid);
		sess = google_session_create_xmlnode(session, "terminate");
		xmlnode_insert_child(iq->node, sess);

		jabber_iq_send(iq);
	} else if (type == PURPLE_MEDIA_INFO_REJECT) {
		xmlnode *sess;
		JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);

		xmlnode_set_attrib(iq->node, "to", session->remote_jid);
		sess = google_session_create_xmlnode(session, "reject");
		xmlnode_insert_child(iq->node, sess);

		jabber_iq_send(iq);
	} else if (type == PURPLE_MEDIA_INFO_ACCEPT && local == TRUE) {
		google_session_ready(session);
	}
}
Exemple #2
0
void
jabber_data_parse(JabberStream *js, const char *who, JabberIqType type,
                  const char *id, xmlnode *data_node)
{
    JabberIq *result = NULL;
    const char *cid = xmlnode_get_attrib(data_node, "cid");
    const JabberData *data = cid ? jabber_data_find_local_by_cid(cid) : NULL;

    if (!data) {
        xmlnode *item_not_found = xmlnode_new("item-not-found");

        result = jabber_iq_new(js, JABBER_IQ_ERROR);
        if (who)
            xmlnode_set_attrib(result->node, "to", who);
        xmlnode_set_attrib(result->node, "id", id);
        xmlnode_insert_child(result->node, item_not_found);
    } else {
        result = jabber_iq_new(js, JABBER_IQ_RESULT);
        if (who)
            xmlnode_set_attrib(result->node, "to", who);
        xmlnode_set_attrib(result->node, "id", id);
        xmlnode_insert_child(result->node,
                             jabber_data_get_xml_definition(data));
    }
    jabber_iq_send(result);
}
Exemple #3
0
void
jabber_data_parse(JabberStream *js, xmlnode *packet)
{
    JabberIq *result = NULL;
    const char *who = xmlnode_get_attrib(packet, "from");
    xmlnode *data_node = xmlnode_get_child(packet, "data");
    const JabberData *data =
        jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid"));

    if (!data) {
        xmlnode *item_not_found = xmlnode_new("item-not-found");

        result = jabber_iq_new(js, JABBER_IQ_ERROR);
        xmlnode_set_attrib(result->node, "to", who);
        xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
        xmlnode_insert_child(result->node, item_not_found);
    } else {
        result = jabber_iq_new(js, JABBER_IQ_RESULT);
        xmlnode_set_attrib(result->node, "to", who);
        xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
        xmlnode_insert_child(result->node,
                             jabber_data_get_xml_definition(data));
    }
    jabber_iq_send(result);
}
void jabber_gmail_init(JabberStream *js) {
	JabberIq *iq;
	PurpleXmlNode *usersetting, *mailnotifications;

	if (!purple_account_get_check_mail(purple_connection_get_account(js->gc)))
		return;

	/*
	 * Quoting https://developers.google.com/talk/jep_extensions/usersettings:
	 * To ensure better compatibility with other clients, rather than
	 * setting this value to "false" to turn off notifications, it is
	 * recommended that a client set this to "true" and filter incoming
	 * email notifications itself.
	 */
	iq = jabber_iq_new(js, JABBER_IQ_SET);
	usersetting = purple_xmlnode_new_child(iq->node, "usersetting");
	purple_xmlnode_set_namespace(usersetting, "google:setting");
	mailnotifications = purple_xmlnode_new_child(usersetting, "mailnotifications");
	purple_xmlnode_set_attrib(mailnotifications, "value", "true");
	jabber_iq_send(iq);

	iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
	jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
	jabber_iq_send(iq);
}
Exemple #5
0
JabberIq *jabber_iq_new_query(JabberStream *js, JabberIqType type,
		const char *xmlns)
{
	JabberIq *iq = jabber_iq_new(js, type);
	xmlnode *query;

	query = xmlnode_new_child(iq->node, "query");
	xmlnode_set_namespace(query, xmlns);

	return iq;
}
Exemple #6
0
void
jabber_ibb_session_accept(JabberIBBSession *sess)
{
	JabberIq *result = jabber_iq_new(jabber_ibb_session_get_js(sess),
		JABBER_IQ_RESULT);

	purple_xmlnode_set_attrib(result->node, "to", jabber_ibb_session_get_who(sess));
	jabber_iq_set_id(result, sess->id);
	jabber_iq_send(result);
	sess->state = JABBER_IBB_SESSION_OPENED;
}
Exemple #7
0
JabberIq *
jingle_session_create_ack(JingleSession *session, const PurpleXmlNode *jingle)
{
	JabberIq *result = jabber_iq_new(
			jingle_session_get_js(session),
			JABBER_IQ_RESULT);
	PurpleXmlNode *packet = purple_xmlnode_get_parent(jingle);
	jabber_iq_set_id(result, purple_xmlnode_get_attrib(packet, "id"));
	purple_xmlnode_set_attrib(result->node, "from", purple_xmlnode_get_attrib(packet, "to"));
	purple_xmlnode_set_attrib(result->node, "to", purple_xmlnode_get_attrib(packet, "from"));
	return result;
}
Exemple #8
0
static void jabber_oob_xfer_end(PurpleXfer *xfer)
{
	JabberOOBXfer *jox = xfer->data;
	JabberIq *iq;

	iq = jabber_iq_new(jox->js, JABBER_IQ_RESULT);
	xmlnode_set_attrib(iq->node, "to", xfer->who);
	jabber_iq_set_id(iq, jox->iq_id);

	jabber_iq_send(iq);

	jabber_oob_xfer_free(xfer);
}
Exemple #9
0
Fichier : si.c Projet : VoxOx/VoxOx
static void jabber_si_xfer_send_request(GaimXfer *xfer)
{
	JabberSIXfer *jsx = xfer->data;
	JabberIq *iq;
	xmlnode *si, *file, *feature, *x, *field, *option, *value;
	char buf[32];

	xfer->filename = g_path_get_basename(xfer->local_filename);

	iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
	xmlnode_set_attrib(iq->node, "to", xfer->who);
	si = xmlnode_new_child(iq->node, "si");
	xmlnode_set_namespace(si, "http://jabber.org/protocol/si");
	jsx->stream_id = jabber_get_next_id(jsx->js);
	xmlnode_set_attrib(si, "id", jsx->stream_id);
	xmlnode_set_attrib(si, "profile",
			"http://jabber.org/protocol/si/profile/file-transfer");

	file = xmlnode_new_child(si, "file");
	xmlnode_set_namespace(file,
			"http://jabber.org/protocol/si/profile/file-transfer");
	xmlnode_set_attrib(file, "name", xfer->filename);
	g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size);
	xmlnode_set_attrib(file, "size", buf);
	/* maybe later we'll do hash and date attribs */

	feature = xmlnode_new_child(si, "feature");
	xmlnode_set_namespace(feature,
			"http://jabber.org/protocol/feature-neg");
	x = xmlnode_new_child(feature, "x");
	xmlnode_set_namespace(x, "jabber:x:data");
	xmlnode_set_attrib(x, "type", "form");
	field = xmlnode_new_child(x, "field");
	xmlnode_set_attrib(field, "var", "stream-method");
	xmlnode_set_attrib(field, "type", "list-single");
	option = xmlnode_new_child(field, "option");
	value = xmlnode_new_child(option, "value");
	xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams",
			-1);
	/*
	option = xmlnode_new_child(field, "option");
	value = xmlnode_new_child(option, "value");
	xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1);
	*/

	jabber_iq_set_callback(iq, jabber_si_xfer_send_method_cb, xfer);

	jabber_iq_send(iq);
}
Exemple #10
0
static JabberIq *
jingle_create_iq(JingleSession *session)
{
	JabberStream *js = jingle_session_get_js(session);
	JabberIq *result = jabber_iq_new(js, JABBER_IQ_SET);
	gchar *from = jingle_session_get_local_jid(session);
	gchar *to = jingle_session_get_remote_jid(session);

	purple_xmlnode_set_attrib(result->node, "from", from);
	purple_xmlnode_set_attrib(result->node, "to", to);

	g_free(from);
	g_free(to);
	return result;
}
Exemple #11
0
static void
jabber_ibb_send_error_response(JabberStream *js, const char *to, const char *id)
{
	JabberIq *result = jabber_iq_new(js, JABBER_IQ_ERROR);
	PurpleXmlNode *error = purple_xmlnode_new("error");
	PurpleXmlNode *item_not_found = purple_xmlnode_new("item-not-found");

	purple_xmlnode_set_namespace(item_not_found, NS_XMPP_STANZAS);
	purple_xmlnode_set_attrib(error, "code", "440");
	purple_xmlnode_set_attrib(error, "type", "cancel");
	jabber_iq_set_id(result, id);
	purple_xmlnode_set_attrib(result->node, "to", to);
	purple_xmlnode_insert_child(error, item_not_found);
	purple_xmlnode_insert_child(result->node, error);

	jabber_iq_send(result);
}
Exemple #12
0
void
jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data,
                             gsize size)
{
	JabberIBBSessionState state = jabber_ibb_session_get_state(sess);

	purple_debug_info("jabber", "sending data block of %" G_GSIZE_FORMAT " bytes on IBB stream\n",
		size);

	if (state != JABBER_IBB_SESSION_OPENED) {
		purple_debug_error("jabber",
			"trying to send data on a non-open IBB session\n");
	} else if (size > jabber_ibb_session_get_max_data_size(sess)) {
		purple_debug_error("jabber",
			"trying to send a too large packet in the IBB session\n");
	} else {
		JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess),
			JABBER_IQ_SET);
		PurpleXmlNode *data_element = purple_xmlnode_new("data");
		char *base64 = purple_base64_encode(data, size);
		char seq[10];
		g_snprintf(seq, sizeof(seq), "%u", jabber_ibb_session_get_send_seq(sess));

		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
		purple_xmlnode_set_namespace(data_element, NS_IBB);
		purple_xmlnode_set_attrib(data_element, "sid", jabber_ibb_session_get_sid(sess));
		purple_xmlnode_set_attrib(data_element, "seq", seq);
		purple_xmlnode_insert_data(data_element, base64, -1);

		purple_xmlnode_insert_child(set->node, data_element);

		purple_debug_info("jabber",
			"IBB: setting send <iq/> callback for session %p %s\n", sess,
			sess->sid);
		jabber_iq_set_callback(set, jabber_ibb_session_send_acknowledge_cb, sess);
		sess->last_iq_id = g_strdup(purple_xmlnode_get_attrib(set->node, "id"));
		purple_debug_info("jabber", "IBB: set sess->last_iq_id: %s\n",
			sess->last_iq_id);
		jabber_iq_send(set);

		g_free(base64);
		(sess->send_seq)++;
	}
}
Exemple #13
0
void jabber_pep_request_item(JabberStream *js, const char *to, const char *node, const char *id, JabberPEPHandler cb) {
	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
	xmlnode *pubsub, *items, *item;
	
	xmlnode_set_attrib(iq->node,"to",to);
	pubsub = xmlnode_new_child(iq->node,"pubsub");
	
	xmlnode_set_namespace(pubsub,"http://jabber.org/protocol/pubsub");
	
	items = xmlnode_new_child(pubsub, "items");
	xmlnode_set_attrib(items,"node",node);
	
	item = xmlnode_new_child(items, "item");
	if(id)
		xmlnode_set_attrib(item, "id", id);
	
	jabber_iq_set_callback(iq,do_pep_iq_request_item_callback,(gpointer)cb);
	
	jabber_iq_send(iq);
}
Exemple #14
0
void
jabber_ibb_session_close(JabberIBBSession *sess)
{
	JabberIBBSessionState state = jabber_ibb_session_get_state(sess);

	if (state != JABBER_IBB_SESSION_OPENED && state != JABBER_IBB_SESSION_ERROR) {
		purple_debug_error("jabber",
			"jabber_ibb_session_close called on a session that has not been"
			"opened\n");
	} else {
		JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess),
			JABBER_IQ_SET);
		PurpleXmlNode *close = purple_xmlnode_new("close");

		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
		purple_xmlnode_set_namespace(close, NS_IBB);
		purple_xmlnode_set_attrib(close, "sid", jabber_ibb_session_get_sid(sess));
		purple_xmlnode_insert_child(set->node, close);
		jabber_iq_send(set);
		sess->state = JABBER_IBB_SESSION_CLOSED;
	}
}
Exemple #15
0
static void jabber_time_parse(JabberStream *js, const char *from,
                              JabberIqType type, const char *id,
                              PurpleXmlNode *child)
{
	JabberIq *iq;
	time_t now_t;
	struct tm *tm;

	time(&now_t);

	if(type == JABBER_IQ_GET) {
		PurpleXmlNode *tzo, *utc;
		const char *date, *tz;

		iq = jabber_iq_new(js, JABBER_IQ_RESULT);
		jabber_iq_set_id(iq, id);
		if (from)
			purple_xmlnode_set_attrib(iq->node, "to", from);

		child = purple_xmlnode_new_child(iq->node, child->name);
		purple_xmlnode_set_namespace(child, NS_ENTITY_TIME);

		/* <tzo>-06:00</tzo> */
		tm = localtime(&now_t);
		tz = purple_get_tzoff_str(tm, TRUE);
		tzo = purple_xmlnode_new_child(child, "tzo");
		purple_xmlnode_insert_data(tzo, tz, -1);

		/* <utc>2006-12-19T17:58:35Z</utc> */
		tm = gmtime(&now_t);
		date = purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm);
		utc = purple_xmlnode_new_child(child, "utc");
		purple_xmlnode_insert_data(utc, date, -1);

		jabber_iq_send(iq);
	} else {
		/* TODO: Errors */
	}
}
Exemple #16
0
static void jabber_oob_xfer_recv_error(PurpleXfer *xfer, const char *code) {
	JabberOOBXfer *jox = xfer->data;
	JabberIq *iq;
	xmlnode *y, *z;

	iq = jabber_iq_new(jox->js, JABBER_IQ_ERROR);
	xmlnode_set_attrib(iq->node, "to", xfer->who);
	jabber_iq_set_id(iq, jox->iq_id);
	y = xmlnode_new_child(iq->node, "error");
	xmlnode_set_attrib(y, "code", code);
	if(purple_strequal(code, "406")) {
		z = xmlnode_new_child(y, "not-acceptable");
		xmlnode_set_attrib(y, "type", "modify");
		xmlnode_set_namespace(z, NS_XMPP_STANZAS);
	} else if(purple_strequal(code, "404")) {
		z = xmlnode_new_child(y, "not-found");
		xmlnode_set_attrib(y, "type", "cancel");
		xmlnode_set_namespace(z, NS_XMPP_STANZAS);
	}
	jabber_iq_send(iq);

	jabber_oob_xfer_free(xfer);
}
Exemple #17
0
void
jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
                  const char *id, PurpleXmlNode *new_mail)
{
	PurpleXmlNode *query;
	JabberIq *iq;

	/* bail if the user isn't interested */
	if (!purple_account_get_check_mail(purple_connection_get_account(js->gc)))
		return;

	/* Is this an initial incoming mail notification? If so, send a request for more info */
	if (type != JABBER_IQ_SET)
		return;

	/* Acknowledge the notification */
	iq = jabber_iq_new(js, JABBER_IQ_RESULT);
	if (from)
		purple_xmlnode_set_attrib(iq->node, "to", from);
	purple_xmlnode_set_attrib(iq->node, "id", id);
	jabber_iq_send(iq);

	purple_debug_misc("jabber",
		   "Got new mail notification. Sending request for more info\n");

	iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
	jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
	query = purple_xmlnode_get_child(iq->node, "query");

	if (js->gmail_last_time)
		purple_xmlnode_set_attrib(query, "newer-than-time", js->gmail_last_time);
	if (js->gmail_last_tid)
		purple_xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid);

	jabber_iq_send(iq);
	return;
}
Exemple #18
0
void
jabber_ibb_session_open(JabberIBBSession *sess)
{
	if (jabber_ibb_session_get_state(sess) != JABBER_IBB_SESSION_NOT_OPENED) {
		purple_debug_error("jabber",
			"jabber_ibb_session called on an already open stream\n");
	} else {
		JabberIq *set = jabber_iq_new(sess->js, JABBER_IQ_SET);
		PurpleXmlNode *open = purple_xmlnode_new("open");
		gchar block_size[10];

		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
		purple_xmlnode_set_namespace(open, NS_IBB);
		purple_xmlnode_set_attrib(open, "sid", jabber_ibb_session_get_sid(sess));
		g_snprintf(block_size, sizeof(block_size), "%" G_GSIZE_FORMAT,
			jabber_ibb_session_get_block_size(sess));
		purple_xmlnode_set_attrib(open, "block-size", block_size);
		purple_xmlnode_insert_child(set->node, open);

		jabber_iq_set_callback(set, jabber_ibb_session_opened_cb, sess);

		jabber_iq_send(set);
	}
}
Exemple #19
0
static gboolean
handle_presence_contact(JabberStream *js, JabberPresence *presence)
{
	JabberBuddyResource *jbr;
	PurpleAccount *account;
	PurpleBuddy *b;
	char *buddy_name;
	PurpleConversation *conv;

	buddy_name = jabber_id_get_bare_jid(presence->jid_from);

	account = purple_connection_get_account(js->gc);
	b = purple_find_buddy(account, buddy_name);

	/*
	 * Unbind/unlock from sending messages to a specific resource on
	 * presence changes.  This is locked to a specific resource when
	 * receiving a message (in message.c).
	 */
	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
			buddy_name, account);
	if (conv) {
		purple_debug_info("jabber", "Changed conversation binding from %s to %s\n",
				purple_conversation_get_name(conv), buddy_name);
		purple_conversation_set_name(conv, buddy_name);
	}

	if (b == NULL) {
		if (presence->jb != js->user_jb) {
			purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%p)\n",
					buddy_name, purple_account_get_username(account), account);
			g_free(buddy_name);
			return FALSE;
		} else {
			/* this is a different resource of our own account. Resume even when this account isn't on our blist */
		}
	}

	if (b && presence->vcard_avatar_hash) {
		const char *ah = presence->vcard_avatar_hash[0] != '\0' ?
				presence->vcard_avatar_hash : NULL;
		const char *ah2 = purple_buddy_icons_get_checksum_for_user(b);
		if (!purple_strequal(ah, ah2)) {
			/* XXX this is a crappy way of trying to prevent
			 * someone from spamming us with presence packets
			 * and causing us to DoS ourselves...what we really
			 * need is a queue system that can throttle itself,
			 * but i'm too tired to write that right now */
			if(!g_slist_find(js->pending_avatar_requests, presence->jb)) {
				JabberIq *iq;
				xmlnode *vcard;

				js->pending_avatar_requests =
					g_slist_prepend(js->pending_avatar_requests, presence->jb);

				iq = jabber_iq_new(js, JABBER_IQ_GET);
				xmlnode_set_attrib(iq->node, "to", buddy_name);
				vcard = xmlnode_new_child(iq->node, "vCard");
				xmlnode_set_namespace(vcard, "vcard-temp");

				jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL);
				jabber_iq_send(iq);
			}
		}
	}

	if (presence->state == JABBER_BUDDY_STATE_ERROR ||
			presence->type == JABBER_PRESENCE_UNAVAILABLE ||
			presence->type == JABBER_PRESENCE_UNSUBSCRIBED) {
		jabber_buddy_remove_resource(presence->jb, presence->jid_from->resource);
	} else {
		jbr = jabber_buddy_track_resource(presence->jb,
				presence->jid_from->resource, presence->priority,
				presence->state, presence->status);
		jbr->idle = presence->idle ? time(NULL) - presence->idle : 0;
	}

	jbr = jabber_buddy_find_resource(presence->jb, NULL);
	if (jbr) {
		jabber_google_presence_incoming(js, buddy_name, jbr);
		purple_prpl_got_user_status(account, buddy_name,
				jabber_buddy_state_get_status_id(jbr->state),
				"priority", jbr->priority,
				"message", jbr->status,
				NULL);
		purple_prpl_got_user_idle(account, buddy_name,
				jbr->idle, jbr->idle);
		if (presence->nickname)
			serv_got_alias(js->gc, buddy_name, presence->nickname);
	} else {
		purple_prpl_got_user_status(account, buddy_name,
				jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE),
				presence->status ? "message" : NULL, presence->status,
				NULL);
	}
	g_free(buddy_name);

	return TRUE;
}
Exemple #20
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);
}
Exemple #21
0
void jabber_roster_parse(JabberStream *js, const char *from,
                         JabberIqType type, const char *id, xmlnode *query)
{
	xmlnode *item, *group;
#if 0
	const char *ver;
#endif

	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 (g_str_equal(subscription, "remove"))
				jb->subscription = JABBER_SUB_REMOVE;
			else if (jb == js->user_jb)
				jb->subscription = JABBER_SUB_BOTH;
			else if (g_str_equal(subscription, "none"))
				jb->subscription = JABBER_SUB_NONE;
			else if (g_str_equal(subscription, "to"))
				jb->subscription = JABBER_SUB_TO;
			else if (g_str_equal(subscription, "from"))
				jb->subscription = JABBER_SUB_FROM;
			else if (g_str_equal(subscription, "both"))
				jb->subscription = JABBER_SUB_BOTH;
		}

		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;
				}

				/*
				 * See the note in add_purple_buddy_to_groups; the core handles
				 * names case-insensitively and this is required to not
				 * end up with duplicates if a buddy is in, e.g.,
				 * 'XMPP' and 'xmpp'
				 */
				if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp))
					g_free(group_name);
				else
					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);
		}
	}

#if 0
	ver = xmlnode_get_attrib(query, "ver");
	if (ver) {
		 PurpleAccount *account = purple_connection_get_account(js->gc);
		 purple_account_set_string(account, "roster_ver", ver);
	}
#endif

	if (type == JABBER_IQ_SET) {
		JabberIq *ack = jabber_iq_new(js, JABBER_IQ_RESULT);
		jabber_iq_set_id(ack, id);
		jabber_iq_send(ack);
	}

	js->currently_parsing_roster_push = FALSE;
}
Exemple #22
0
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);
	}
}
static void
google_session_send_candidates(PurpleMedia *media, gchar *session_id,
		gchar *participant, GoogleSession *session)
{
	PurpleMedia *session_media =
		((GoogleAVSessionData *) session->session_data)->media;
	GList *candidates =
		purple_media_get_local_candidates(session_media, session_id,
		    session->remote_jid);
	GList *iter;
	PurpleMediaCandidate *transport;
	gboolean video = FALSE;

	if (!strcmp(session_id, "google-video"))
		video = TRUE;

	for (iter = candidates; iter; iter = iter->next) {
		JabberIq *iq;
		gchar *ip, *port, *username, *password;
		gchar pref[16];
		PurpleMediaCandidateType type;
		xmlnode *sess;
		xmlnode *candidate;
		guint component_id;
		transport = PURPLE_MEDIA_CANDIDATE(iter->data);
		component_id = purple_media_candidate_get_component_id(
				transport);

		iq = jabber_iq_new(session->js, JABBER_IQ_SET);
		sess = google_session_create_xmlnode(session, "candidates");
		xmlnode_insert_child(iq->node, sess);
		xmlnode_set_attrib(iq->node, "to", session->remote_jid);

		candidate = xmlnode_new("candidate");

		ip = purple_media_candidate_get_ip(transport);
		port = g_strdup_printf("%d",
				purple_media_candidate_get_port(transport));
		g_ascii_dtostr(pref, 16,
			purple_media_candidate_get_priority(transport) / 1000.0);
		username = purple_media_candidate_get_username(transport);
		password = purple_media_candidate_get_password(transport);
		type = purple_media_candidate_get_candidate_type(transport);

		xmlnode_set_attrib(candidate, "address", ip);
		xmlnode_set_attrib(candidate, "port", port);
		xmlnode_set_attrib(candidate, "name",
				component_id == PURPLE_MEDIA_COMPONENT_RTP ?
				video ? "video_rtp" : "rtp" :
				component_id == PURPLE_MEDIA_COMPONENT_RTCP ?
				video ? "video_rtcp" : "rtcp" : "none");
		xmlnode_set_attrib(candidate, "username", username);
		/*
		 * As of this writing, Farsight 2 in Google compatibility
		 * mode doesn't provide a password. The Gmail client
		 * requires this to be set.
		 */
		xmlnode_set_attrib(candidate, "password",
				password != NULL ? password : "");
		xmlnode_set_attrib(candidate, "preference", pref);
		xmlnode_set_attrib(candidate, "protocol",
				purple_media_candidate_get_protocol(transport)
				== PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
				"udp" : "tcp");
		xmlnode_set_attrib(candidate, "type", type ==
				PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "local" :
						      type ==
				PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "stun" :
					       	      type ==
				PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
				NULL);
		xmlnode_set_attrib(candidate, "generation", "0");
		xmlnode_set_attrib(candidate, "network", "0");
		xmlnode_insert_child(sess, candidate);

		g_free(ip);
		g_free(port);
		g_free(username);
		g_free(password);

		jabber_iq_send(iq);
	}
	purple_media_candidate_list_free(candidates);
}
static void
google_session_handle_accept(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
{
	xmlnode *desc_element = xmlnode_get_child(sess, "description");
	xmlnode *codec_element = xmlnode_get_child(
			desc_element, "payload-type");
	GList *codecs = NULL, *video_codecs = NULL;
	JabberIq *result = NULL;
	const gchar *xmlns = xmlnode_get_namespace(desc_element);
	gboolean video = (xmlns && !strcmp(xmlns, NS_GOOGLE_SESSION_VIDEO));
	GoogleAVSessionData *session_data =
		(GoogleAVSessionData *) session->session_data;
	
	for (; codec_element; codec_element = codec_element->next) {
		const gchar *xmlns, *encoding_name, *id,
				*clock_rate, *width, *height, *framerate;
		gboolean video_codec = FALSE;

		if (!purple_strequal(codec_element->name, "payload-type"))
			continue;

		xmlns = xmlnode_get_namespace(codec_element);
		encoding_name =	xmlnode_get_attrib(codec_element, "name");
		id = xmlnode_get_attrib(codec_element, "id");

		if (!video || purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
			clock_rate = xmlnode_get_attrib(
					codec_element, "clockrate");
		else {
			clock_rate = "90000";
			width = xmlnode_get_attrib(codec_element, "width");
			height = xmlnode_get_attrib(codec_element, "height");
			framerate = xmlnode_get_attrib(
					codec_element, "framerate");
			video_codec = TRUE;
		}

		if (id && encoding_name) {
			PurpleMediaCodec *codec = purple_media_codec_new(
					atoi(id), encoding_name,
					video_codec ? PURPLE_MEDIA_VIDEO :
					PURPLE_MEDIA_AUDIO,
					clock_rate ? atoi(clock_rate) : 0);
			if (video_codec)
				video_codecs = g_list_append(
						video_codecs, codec);
			else
				codecs = g_list_append(codecs, codec);
		}
	}

	if (codecs)
		purple_media_set_remote_codecs(session_data->media, "google-voice",
				session->remote_jid, codecs);
	if (video_codecs)
		purple_media_set_remote_codecs(session_data->media, "google-video",
				session->remote_jid, video_codecs);

	purple_media_stream_info(session_data->media, PURPLE_MEDIA_INFO_ACCEPT,
			NULL, NULL, FALSE);

	result = jabber_iq_new(js, JABBER_IQ_RESULT);
	jabber_iq_set_id(result, iq_id);
	xmlnode_set_attrib(result->node, "to", session->remote_jid);
	jabber_iq_send(result);
}
static void
google_session_handle_candidates(JabberStream  *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
{
	JabberIq *result;
	GList *list = NULL, *video_list = NULL;
	xmlnode *cand;
	static int name = 0;
	char n[4];
	GoogleAVSessionData *session_data =
		(GoogleAVSessionData *) session->session_data;
	
	for (cand = xmlnode_get_child(sess, "candidate"); cand;
			cand = xmlnode_get_next_twin(cand)) {
		PurpleMediaCandidate *info;
		const gchar *cname = xmlnode_get_attrib(cand, "name");
		const gchar *type = xmlnode_get_attrib(cand, "type");
		const gchar *protocol = xmlnode_get_attrib(cand, "protocol");
		const gchar *address = xmlnode_get_attrib(cand, "address");
		const gchar *port = xmlnode_get_attrib(cand, "port");
		const gchar *preference = xmlnode_get_attrib(cand, "preference");
		guint component_id;

		if (cname && type && address && port) {
			PurpleMediaCandidateType candidate_type;
			guint prio = preference ? g_ascii_strtod(preference, NULL) * 1000 : 0;
			
			g_snprintf(n, sizeof(n), "S%d", name++);
			
			if (g_str_equal(type, "local"))
				candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
			else if (g_str_equal(type, "stun"))
				candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;
			else if (g_str_equal(type, "relay"))
				candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
			else
				candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;

			if (purple_strequal(cname, "rtcp") ||
					purple_strequal(cname, "video_rtcp"))
				component_id = PURPLE_MEDIA_COMPONENT_RTCP;
			else
				component_id = PURPLE_MEDIA_COMPONENT_RTP;

			info = purple_media_candidate_new(n, component_id,
					candidate_type,
					purple_strequal(protocol, "udp") ?
							PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
							PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
					address,
					atoi(port));
			g_object_set(info, "username", xmlnode_get_attrib(cand, "username"),
					"password", xmlnode_get_attrib(cand, "password"),
			        "priority", prio, NULL);
			if (!strncmp(cname, "video_", 6)) {
				if (session_data->added_streams) {
					video_list = g_list_append(video_list, info);
				} else {
					session_data->remote_video_candidates =
						g_list_append(session_data->remote_video_candidates,
							info);
				}
			} else {
				if (session_data->added_streams) {
					list = g_list_append(list, info);
				} else {
					session_data->remote_audio_candidates =
						g_list_append(session_data->remote_audio_candidates,
							info);
				}
			}
		}
	}

	if (list) {
		purple_media_add_remote_candidates(session_data->media, "google-voice",
			session->remote_jid, list);
		purple_media_candidate_list_free(list);
	}
	if (video_list) {
		purple_media_add_remote_candidates(session_data->media, "google-video",
			session->remote_jid, video_list);
		purple_media_candidate_list_free(video_list);
	}

	result = jabber_iq_new(js, JABBER_IQ_RESULT);
	jabber_iq_set_id(result, iq_id);
	xmlnode_set_attrib(result->node, "to", session->remote_jid);
	jabber_iq_send(result);
}
static void
jabber_google_relay_response_session_handle_initiate_cb(GoogleSession *session,
    const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
    const gchar *relay_username, const gchar *relay_password)
{
	GParameter *params;
	guint num_params;
	JabberStream *js = session->js;
	xmlnode *codec_element;
	const gchar *xmlns;
	PurpleMediaCodec *codec;
	GList *video_codecs = NULL;
	GList *codecs = NULL;
	JabberIq *result;
	GoogleAVSessionData *session_data =
		(GoogleAVSessionData *) session->session_data;

	params =
		jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp, 
	    	relay_ssltcp, relay_username, relay_password, &num_params);

	if (purple_media_add_stream(session_data->media, "google-voice",
			session->remote_jid, PURPLE_MEDIA_AUDIO, FALSE,
			"nice", num_params, params) == FALSE ||
			(session_data->video && purple_media_add_stream(
			session_data->media, "google-video",
			session->remote_jid, PURPLE_MEDIA_VIDEO,
			FALSE, "nice", num_params, params) == FALSE)) {
		purple_media_error(session_data->media, "Error adding stream.");
		purple_media_stream_info(session_data->media,
				PURPLE_MEDIA_INFO_REJECT, NULL, NULL, TRUE);
	} else {
		/* successfully added stream(s) */
		session_data->added_streams = TRUE;

		if (session_data->remote_audio_candidates) {
			purple_media_add_remote_candidates(session_data->media,
				"google-voice", session->remote_jid, 
			    session_data->remote_audio_candidates);
			purple_media_candidate_list_free(session_data->remote_audio_candidates);
			session_data->remote_audio_candidates = NULL;
		}
		if (session_data->remote_video_candidates) {
			purple_media_add_remote_candidates(session_data->media,
				"google-video", session->remote_jid, 
			    session_data->remote_video_candidates);
			purple_media_candidate_list_free(session_data->remote_video_candidates);
			session_data->remote_video_candidates = NULL;
		}
	}
		
	g_free(params);

	for (codec_element = xmlnode_get_child(session->description, "payload-type");
	     codec_element; codec_element = codec_element->next) {
		const char *id, *encoding_name,  *clock_rate,
				*width, *height, *framerate;
		gboolean video;
		if (codec_element->name &&
				strcmp(codec_element->name, "payload-type"))
			continue;

		xmlns = xmlnode_get_namespace(codec_element);
		encoding_name = xmlnode_get_attrib(codec_element, "name");
		id = xmlnode_get_attrib(codec_element, "id");

		if (!session_data->video ||
				(xmlns && !strcmp(xmlns, NS_GOOGLE_SESSION_PHONE))) {
			clock_rate = xmlnode_get_attrib(
					codec_element, "clockrate");
			video = FALSE;
		} else {
			width = xmlnode_get_attrib(codec_element, "width");
			height = xmlnode_get_attrib(codec_element, "height");
			framerate = xmlnode_get_attrib(
					codec_element, "framerate");
			clock_rate = "90000";
			video = TRUE;
		}

		if (id) {
			codec = purple_media_codec_new(atoi(id), encoding_name,
					video ?	PURPLE_MEDIA_VIDEO :
					PURPLE_MEDIA_AUDIO,
					clock_rate ? atoi(clock_rate) : 0);
			if (video)
				video_codecs = g_list_append(
						video_codecs, codec);
			else
				codecs = g_list_append(codecs, codec);
		}
	}

	if (codecs)
		purple_media_set_remote_codecs(session_data->media, "google-voice",
				session->remote_jid, codecs);
	if (video_codecs)
		purple_media_set_remote_codecs(session_data->media, "google-video",
				session->remote_jid, video_codecs);

	purple_media_codec_list_free(codecs);
	purple_media_codec_list_free(video_codecs);

	result = jabber_iq_new(js, JABBER_IQ_RESULT);
	jabber_iq_set_id(result, session->iq_id);
	xmlnode_set_attrib(result->node, "to", session->remote_jid);
	jabber_iq_send(result);
}
Exemple #27
0
Fichier : si.c Projet : VoxOx/VoxOx
static void jabber_si_xfer_init(GaimXfer *xfer)
{
	JabberSIXfer *jsx = xfer->data;
	JabberIq *iq;
	if(gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
		JabberBuddy *jb;
		JabberBuddyResource *jbr = NULL;

		jb = jabber_buddy_find(jsx->js, xfer->who, TRUE);
		/* XXX */
		if(!jb)
			return;

		/* XXX: for now, send to the first resource available */
		if(g_list_length(jb->resources) >= 1) {
			char **who_v = g_strsplit(xfer->who, "/", 2);
			char *who;

			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 */
		}
	} else {
		xmlnode *si, *feature, *x, *field, *value;

		iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT);
		xmlnode_set_attrib(iq->node, "to", xfer->who);
		if(jsx->iq_id)
			jabber_iq_set_id(iq, jsx->iq_id);

		jsx->accepted = TRUE;

		si = xmlnode_new_child(iq->node, "si");
		xmlnode_set_namespace(si, "http://jabber.org/protocol/si");

		feature = xmlnode_new_child(si, "feature");
		xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg");

		x = xmlnode_new_child(feature, "x");
		xmlnode_set_namespace(x, "jabber:x:data");
		xmlnode_set_attrib(x, "type", "submit");

		field = xmlnode_new_child(x, "field");
		xmlnode_set_attrib(field, "var", "stream-method");

		value = xmlnode_new_child(field, "value");
		if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS)
			xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", -1);
		/*
		else if(jsx->stream_method & STREAM_METHOD_IBB)
		xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1);
		*/

		jabber_iq_send(iq);
	}
}
Exemple #28
0
Fichier : si.c Projet : VoxOx/VoxOx
static void jabber_si_bytestreams_attempt_connect(GaimXfer *xfer)
{
	JabberSIXfer *jsx = xfer->data;
	struct bytestreams_streamhost *streamhost;
	char *dstaddr, *p;
	int i;
	unsigned char hashval[20];
	JabberID *dstjid;

	if(!jsx->streamhosts) {
		JabberIq *iq = jabber_iq_new(jsx->js, JABBER_IQ_ERROR);
		xmlnode *error, *inf;

		if(jsx->iq_id)
			jabber_iq_set_id(iq, jsx->iq_id);

		xmlnode_set_attrib(iq->node, "to", xfer->who);
		error = xmlnode_new_child(iq->node, "error");
		xmlnode_set_attrib(error, "code", "404");
		xmlnode_set_attrib(error, "type", "cancel");
		inf = xmlnode_new_child(error, "item-not-found");
		xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");

		jabber_iq_send(iq);

		gaim_xfer_cancel_local(xfer);

		return;
	}

	streamhost = jsx->streamhosts->data;

	dstjid = jabber_id_new(xfer->who);

	if(dstjid != NULL) {
		jsx->gpi = gaim_proxy_info_new();
		gaim_proxy_info_set_type(jsx->gpi, GAIM_PROXY_SOCKS5);
		gaim_proxy_info_set_host(jsx->gpi, streamhost->host);
		gaim_proxy_info_set_port(jsx->gpi, streamhost->port);



		dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, dstjid->node, dstjid->domain, dstjid->resource, jsx->js->user->node,
				jsx->js->user->domain, jsx->js->user->resource);

		gaim_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr),
				sizeof(hashval), hashval, NULL);
		g_free(dstaddr);
		dstaddr = g_malloc(41);
		p = dstaddr;
		for(i=0; i<20; i++, p+=2)
			snprintf(p, 3, "%02x", hashval[i]);

		jsx->connect_data = gaim_proxy_connect_socks5(NULL, jsx->gpi,
				dstaddr, 0,
				jabber_si_bytestreams_connect_cb, xfer);
		g_free(dstaddr);

		jabber_id_free(dstjid);
	}

	if (jsx->connect_data == NULL)
	{
		jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost);
		g_free(streamhost->jid);
		g_free(streamhost->host);
		g_free(streamhost);
		jabber_si_bytestreams_attempt_connect(xfer);
	}
}
Exemple #29
0
void
jabber_ibb_parse(JabberStream *js, const char *who, JabberIqType type,
                 const char *id, PurpleXmlNode *child)
{
	const char *name = child->name;
	gboolean data  = g_str_equal(name, "data");
	gboolean close = g_str_equal(name, "close");
	gboolean open  = g_str_equal(name, "open");
	const gchar *sid = (data || close) ?
		purple_xmlnode_get_attrib(child, "sid") : NULL;
	JabberIBBSession *sess =
		sid ? g_hash_table_lookup(jabber_ibb_sessions, sid) : NULL;

	if (sess) {

		if (strcmp(who, jabber_ibb_session_get_who(sess)) != 0) {
			/* the iq comes from a different JID than the remote JID of the
			  session, ignore it */
			purple_debug_error("jabber",
				"Got IBB iq from wrong JID, ignoring\n");
		} else if (data) {
			const gchar *seq_attr = purple_xmlnode_get_attrib(child, "seq");
			guint16 seq = (seq_attr ? atoi(seq_attr) : 0);

			/* reject the data, and set the session in error if we get an
			  out-of-order packet */
			if (seq_attr && seq == jabber_ibb_session_get_recv_seq(sess)) {
				/* sequence # is the expected... */
				JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);

				jabber_iq_set_id(result, id);
				purple_xmlnode_set_attrib(result->node, "to", who);

				if (sess->data_received_cb) {
					gchar *base64 = purple_xmlnode_get_data(child);
					gsize size;
					gpointer rawdata = purple_base64_decode(base64, &size);

					g_free(base64);

					if (rawdata) {
						purple_debug_info("jabber",
							"got %" G_GSIZE_FORMAT " bytes of data on IBB stream\n",
							size);
						/* we accept other clients to send up to block-size
						 of _unencoded_ data, since there's been some confusions
						 regarding the interpretation of this attribute
						 (including previous versions of libpurple) */
						if (size > jabber_ibb_session_get_block_size(sess)) {
							purple_debug_error("jabber",
								"IBB: received a too large packet\n");
							if (sess->error_cb)
								sess->error_cb(sess);
							g_free(rawdata);
							return;
						} else {
							purple_debug_info("jabber",
								"calling IBB callback for received data\n");
							sess->data_received_cb(sess, rawdata, size);
						}
						g_free(rawdata);
					} else {
						purple_debug_error("jabber",
							"IBB: invalid BASE64 data received\n");
						if (sess->error_cb)
							sess->error_cb(sess);
						return;

					}
				}

				(sess->recv_seq)++;
				jabber_iq_send(result);

			} else {
				purple_debug_error("jabber",
					"Received an out-of-order/invalid IBB packet\n");
				sess->state = JABBER_IBB_SESSION_ERROR;

				if (sess->error_cb) {
					sess->error_cb(sess);
				}
			}
		} else if (close) {
			sess->state = JABBER_IBB_SESSION_CLOSED;
			purple_debug_info("jabber", "IBB: received close\n");

			if (sess->closed_cb) {
				purple_debug_info("jabber", "IBB: calling closed handler\n");
				sess->closed_cb(sess);
			}
		}
	} else if (open) {
		JabberIq *result;
		const GList *iterator;

		/* run all open handlers registered until one returns true */
		for (iterator = open_handlers ; iterator ;
			 iterator = g_list_next(iterator)) {
			JabberIBBOpenHandler *handler = iterator->data;

			if (handler(js, who, id, child)) {
				result = jabber_iq_new(js, JABBER_IQ_RESULT);
				purple_xmlnode_set_attrib(result->node, "to", who);
				jabber_iq_set_id(result, id);
				jabber_iq_send(result);
				return;
			}
		}
		/* no open callback returned success, reject */
		jabber_ibb_send_error_response(js, who, id);
	} else {
		/* send error reply */
		jabber_ibb_send_error_response(js, who, id);
	}
}
static void
google_session_ready(GoogleSession *session)
{
	PurpleMedia *media =
		((GoogleAVSessionData *)session->session_data)->media;
	gboolean video =
		((GoogleAVSessionData *)session->session_data)->video;
	if (purple_media_codecs_ready(media, NULL) &&
			purple_media_candidates_prepared(media, NULL, NULL)) {
		gchar *me = g_strdup_printf("%s@%s/%s",
				session->js->user->node,
				session->js->user->domain,
				session->js->user->resource);
		JabberIq *iq;
		xmlnode *sess, *desc, *payload;
		GList *codecs, *iter;
		gboolean is_initiator = !strcmp(session->id.initiator, me);

		if (!is_initiator &&
				!purple_media_accepted(media, NULL, NULL)) {
			g_free(me);
			return;
		}

		iq = jabber_iq_new(session->js, JABBER_IQ_SET);

		if (is_initiator) {
			xmlnode_set_attrib(iq->node, "to", session->remote_jid);
			xmlnode_set_attrib(iq->node, "from", session->id.initiator);
			sess = google_session_create_xmlnode(session, "initiate");
		} else {
			google_session_send_candidates(media,
					"google-voice", session->remote_jid,
					session);
			google_session_send_candidates(media,
					"google-video", session->remote_jid,
					session);
			xmlnode_set_attrib(iq->node, "to", session->remote_jid);
			xmlnode_set_attrib(iq->node, "from", me);
			sess = google_session_create_xmlnode(session, "accept");
		}
		xmlnode_insert_child(iq->node, sess);
		desc = xmlnode_new_child(sess, "description");
		if (video)
			xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
		else
			xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);

		codecs = purple_media_get_codecs(media, "google-video");

		for (iter = codecs; iter; iter = g_list_next(iter)) {
			PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
			gchar *id = g_strdup_printf("%d",
					purple_media_codec_get_id(codec));
			gchar *encoding_name =
					purple_media_codec_get_encoding_name(codec);
			payload = xmlnode_new_child(desc, "payload-type");
			xmlnode_set_attrib(payload, "id", id);
			xmlnode_set_attrib(payload, "name", encoding_name);
			xmlnode_set_attrib(payload, "width", "320");
			xmlnode_set_attrib(payload, "height", "200");
			xmlnode_set_attrib(payload, "framerate", "30");
			g_free(encoding_name);
			g_free(id);
		}
		purple_media_codec_list_free(codecs);

		codecs = purple_media_get_codecs(media, "google-voice");

		for (iter = codecs; iter; iter = g_list_next(iter)) {
			PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
			gchar *id = g_strdup_printf("%d",
					purple_media_codec_get_id(codec));
			gchar *encoding_name =
					purple_media_codec_get_encoding_name(codec);
			gchar *clock_rate = g_strdup_printf("%d",
					purple_media_codec_get_clock_rate(codec));
			payload = xmlnode_new_child(desc, "payload-type");
			if (video)
				xmlnode_set_namespace(payload, NS_GOOGLE_SESSION_PHONE);
			xmlnode_set_attrib(payload, "id", id);
			/*
			 * Hack to make Gmail accept speex as the codec.
			 * It shouldn't have to be case sensitive.
			 */
			if (purple_strequal(encoding_name, "SPEEX"))
				xmlnode_set_attrib(payload, "name", "speex");
			else
				xmlnode_set_attrib(payload, "name", encoding_name);
			xmlnode_set_attrib(payload, "clockrate", clock_rate);
			g_free(clock_rate);
			g_free(encoding_name);
			g_free(id);
		}
		purple_media_codec_list_free(codecs);

		jabber_iq_send(iq);

		if (is_initiator) {
			google_session_send_candidates(media,
					"google-voice", session->remote_jid,
					session);
			google_session_send_candidates(media,
					"google-video", session->remote_jid,
					session);
		}

		g_signal_handlers_disconnect_by_func(G_OBJECT(media),
				G_CALLBACK(google_session_ready), session);
	}
}