Пример #1
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;
}
Пример #2
0
void jabber_presence_send(JabberStream *js, gboolean force)
{
	PurpleAccount *account;
	xmlnode *presence, *x, *photo;
	char *stripped = NULL;
	JabberBuddyState state;
	int priority;
	const char *artist = NULL, *title = NULL, *source = NULL, *uri = NULL, *track = NULL;
	int length = -1;
	gboolean allowBuzz;
	PurplePresence *p;
	PurpleStatus *status, *tune;

	account = purple_connection_get_account(js->gc);
	p = purple_account_get_presence(account);
	status = purple_presence_get_active_status(p);

	/* we don't want to send presence before we've gotten our roster */
	if (js->state != JABBER_STREAM_CONNECTED) {
		purple_debug_misc("jabber", "attempt to send presence before roster retrieved\n");
		return;
	}

	purple_status_to_jabber(status, &state, &stripped, &priority);

	/* check for buzz support */
	allowBuzz = purple_status_get_attr_boolean(status,"buzz");
	/* changing the buzz state has to trigger a re-broadcasting of the presence for caps */

	tune = purple_presence_get_status(p, "tune");
	if (js->googletalk && !stripped && purple_status_is_active(tune)) {
		stripped = jabber_google_presence_outgoing(tune);
	}

#define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \
					  (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b)))
	/* check if there are any differences to the <presence> and send them in that case */
	if (force || allowBuzz != js->allowBuzz || js->old_state != state ||
		CHANGED(js->old_msg, stripped) || js->old_priority != priority ||
		CHANGED(js->old_avatarhash, js->avatar_hash) || js->old_idle != js->idle) {
		/* Need to update allowBuzz before creating the presence (with caps) */
		js->allowBuzz = allowBuzz;

		presence = jabber_presence_create_js(js, state, stripped, priority);

		/* Per XEP-0153 4.1, we must always send the <x> */
		x = xmlnode_new_child(presence, "x");
		xmlnode_set_namespace(x, "vcard-temp:x:update");
		/*
		 * FIXME: Per XEP-0153 4.3.2 bullet 2, we must not publish our
		 * image hash if another resource has logged in and updated the
		 * vcard avatar. Requires changes in jabber_presence_parse.
		 */
		if (js->vcard_fetched) {
			/* Always publish a <photo>; it's empty if we have no image. */
			photo = xmlnode_new_child(x, "photo");
			if (js->avatar_hash)
				xmlnode_insert_data(photo, js->avatar_hash, -1);
		}

		jabber_send(js, presence);

		g_hash_table_foreach(js->chats, chats_send_presence_foreach, presence);
		xmlnode_free(presence);

		/* update old values */

		if(js->old_msg)
			g_free(js->old_msg);
		if(js->old_avatarhash)
			g_free(js->old_avatarhash);
		js->old_msg = g_strdup(stripped);
		js->old_avatarhash = g_strdup(js->avatar_hash);
		js->old_state = state;
		js->old_priority = priority;
		js->old_idle = js->idle;
	}
	g_free(stripped);

	/* next, check if there are any changes to the tune values */
	if (purple_status_is_active(tune)) {
		artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
		title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
		source = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
		uri = purple_status_get_attr_string(tune, PURPLE_TUNE_URL);
		track = purple_status_get_attr_string(tune, PURPLE_TUNE_TRACK);
		length = (!purple_status_get_attr_value(tune, PURPLE_TUNE_TIME)) ? -1 :
				purple_status_get_attr_int(tune, PURPLE_TUNE_TIME);
	}

	if(CHANGED(artist, js->old_artist) || CHANGED(title, js->old_title) || CHANGED(source, js->old_source) ||
	   CHANGED(uri, js->old_uri) || CHANGED(track, js->old_track) || (length != js->old_length)) {
		PurpleJabberTuneInfo tuneinfo = {
			(char*)artist,
			(char*)title,
			(char*)source,
			(char*)track,
			length,
			(char*)uri
		};
		jabber_tune_set(js->gc, &tuneinfo);

		/* update old values */
		g_free(js->old_artist);
		g_free(js->old_title);
		g_free(js->old_source);
		g_free(js->old_uri);
		g_free(js->old_track);
		js->old_artist = g_strdup(artist);
		js->old_title = g_strdup(title);
		js->old_source = g_strdup(source);
		js->old_uri = g_strdup(uri);
		js->old_length = length;
		js->old_track = g_strdup(track);
	}

#undef CHANGED

	jabber_presence_fake_to_self(js, status);
}
Пример #3
0
xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority)
{
	xmlnode *show, *status, *presence, *pri, *c;
	const char *show_string = NULL;
#ifdef USE_VV
	gboolean audio_enabled, video_enabled;
#endif

	presence = xmlnode_new("presence");

	if(state == JABBER_BUDDY_STATE_UNAVAILABLE)
		xmlnode_set_attrib(presence, "type", "unavailable");
	else if(state != JABBER_BUDDY_STATE_ONLINE &&
			state != JABBER_BUDDY_STATE_UNKNOWN &&
			state != JABBER_BUDDY_STATE_ERROR)
		show_string = jabber_buddy_state_get_show(state);

	if(show_string) {
		show = xmlnode_new_child(presence, "show");
		xmlnode_insert_data(show, show_string, -1);
	}

	if(msg) {
		status = xmlnode_new_child(presence, "status");
		xmlnode_insert_data(status, msg, -1);
	}

	if(priority) {
		char *pstr = g_strdup_printf("%d", priority);
		pri = xmlnode_new_child(presence, "priority");
		xmlnode_insert_data(pri, pstr, -1);
		g_free(pstr);
	}

	/* if we are idle and not offline, include idle */
	if (js->idle && state != JABBER_BUDDY_STATE_UNAVAILABLE) {
		xmlnode *query = xmlnode_new_child(presence, "query");
		gchar seconds[10];
		g_snprintf(seconds, 10, "%d", (int) (time(NULL) - js->idle));

		xmlnode_set_namespace(query, NS_LAST_ACTIVITY);
		xmlnode_set_attrib(query, "seconds", seconds);
	}

	/* JEP-0115 */
	/* calculate hash */
	jabber_caps_calculate_own_hash(js);
	/* create xml */
	c = xmlnode_new_child(presence, "c");
	xmlnode_set_namespace(c, "http://jabber.org/protocol/caps");
	xmlnode_set_attrib(c, "node", CAPS0115_NODE);
	xmlnode_set_attrib(c, "hash", "sha-1");
	xmlnode_set_attrib(c, "ver", jabber_caps_get_own_hash(js));

#ifdef USE_VV
	/*
	 * MASSIVE HUGE DISGUSTING HACK
	 * This is a huge hack. As far as I can tell, Google Talk's gmail client
	 * doesn't bother to check the actual features we advertise; they
	 * just assume that if we specify a 'voice-v1' ext (ignoring that
	 * these are to be assigned no semantic value), we support receiving voice
	 * calls.
	 *
	 * Ditto for 'video-v1'.
	 */
	audio_enabled = jabber_audio_enabled(js, NULL /* unused */);
	video_enabled = jabber_video_enabled(js, NULL /* unused */);

	if (audio_enabled && video_enabled)
		xmlnode_set_attrib(c, "ext", "voice-v1 camera-v1 video-v1");
	else if (audio_enabled)
		xmlnode_set_attrib(c, "ext", "voice-v1");
	else if (video_enabled)
		xmlnode_set_attrib(c, "ext", "camera-v1 video-v1");
#endif

	return presence;
}
/**
 * \fn xmlnode_received_cb
 * \brief Reacts to requests and receipts
 */
static void
xmlnode_received_cb(PurpleConnection *gc, xmlnode **packet, gpointer null)
{
	if(*packet != NULL)
	{
		if(strcmp((*packet)->name, "message") == 0)
		{
			#ifdef DEBUG
			printf("got message\n");
			#endif

			xmlnode* nodeRequest = xmlnode_get_child (*packet, "request");

			const char* strFrom	= xmlnode_get_attrib(*packet , "from");

			//Answer to an request and verify namespace
			if(nodeRequest)
			{
				#ifdef DEBUG
				printf("got request\n");
				#endif

				const char* strId 	= xmlnode_get_attrib(*packet , "id");

				const char* strNS = xmlnode_get_namespace(nodeRequest);

				if(strcmp(strNS, "urn:xmpp:receipts") == 0)
				{
					xmlnode *message = xmlnode_new("message");
					xmlnode_set_attrib(message, "to", strFrom);
					
					xmlnode *received = xmlnode_new_child(message, "received");
					xmlnode_set_namespace(received, "urn:xmpp:receipts");
					
					xmlnode_set_attrib(received, "id", strId);

					purple_signal_emit(purple_connection_get_prpl(gc), "jabber-sending-xmlnode", gc, &message);
					
					if (message != NULL)
						xmlnode_free(message);
				}
			}
			//Find incoming receipt and call the display-function
			xmlnode* nodeReceived = xmlnode_get_child (*packet, "received");
			if(nodeReceived)
			{
				#ifdef DEBUG
				printf("got received\n");
				#endif

				const char* strNS 	= xmlnode_get_namespace(nodeReceived);
				const char* strId 	= xmlnode_get_attrib(nodeReceived , "id");

				if (strcmp(strNS, "urn:xmpp:receipts") == 0)
				{
					display_message_receipt(strId);
				}
			}
		}
	}
}
Пример #5
0
static void jabber_x_data_ok_cb(struct jabber_x_data_data *data, GaimRequestFields *fields) {
	xmlnode *result = xmlnode_new("x");
	jabber_x_data_cb cb = data->cb;
	gpointer user_data = data->user_data;
	JabberStream *js = data->js;
	GList *groups, *flds;

	xmlnode_set_namespace(result, "jabber:x:data");
	xmlnode_set_attrib(result, "type", "submit");

	for(groups = gaim_request_fields_get_groups(fields); groups; groups = groups->next) {
		for(flds = gaim_request_field_group_get_fields(groups->data); flds; flds = flds->next) {
			xmlnode *fieldnode, *valuenode;
			GaimRequestField *field = flds->data;
			const char *id = gaim_request_field_get_id(field);
			jabber_x_data_field_type type = GPOINTER_TO_INT(g_hash_table_lookup(data->fields, id));

			switch(type) {
				case JABBER_X_DATA_TEXT_SINGLE:
				case JABBER_X_DATA_JID_SINGLE:
					{
					const char *value = gaim_request_field_string_get_value(field);
					fieldnode = xmlnode_new_child(result, "field");
					xmlnode_set_attrib(fieldnode, "var", id);
					valuenode = xmlnode_new_child(fieldnode, "value");
					if(value)
						xmlnode_insert_data(valuenode, value, -1);
					break;
					}
				case JABBER_X_DATA_TEXT_MULTI:
					{
					char **pieces, **p;
					const char *value = gaim_request_field_string_get_value(field);
					fieldnode = xmlnode_new_child(result, "field");
					xmlnode_set_attrib(fieldnode, "var", id);

					pieces = g_strsplit(value, "\n", -1);
					for(p = pieces; *p != NULL; p++) {
						valuenode = xmlnode_new_child(fieldnode, "value");
						xmlnode_insert_data(valuenode, *p, -1);
					}
					g_strfreev(pieces);
					}
					break;
				case JABBER_X_DATA_LIST_SINGLE:
				case JABBER_X_DATA_LIST_MULTI:
					{
					const GList *selected = gaim_request_field_list_get_selected(field);
					char *value;
					fieldnode = xmlnode_new_child(result, "field");
					xmlnode_set_attrib(fieldnode, "var", id);

					while(selected) {
						value = gaim_request_field_list_get_data(field, selected->data);
						valuenode = xmlnode_new_child(fieldnode, "value");
						if(value)
							xmlnode_insert_data(valuenode, value, -1);
						selected = selected->next;
					}
					}
					break;
				case JABBER_X_DATA_BOOLEAN:
					fieldnode = xmlnode_new_child(result, "field");
					xmlnode_set_attrib(fieldnode, "var", id);
					valuenode = xmlnode_new_child(fieldnode, "value");
					if(gaim_request_field_bool_get_value(field))
						xmlnode_insert_data(valuenode, "1", -1);
					else
						xmlnode_insert_data(valuenode, "0", -1);
					break;
				case JABBER_X_DATA_IGNORE:
					break;
			}
		}
	}

	g_hash_table_destroy(data->fields);
	while(data->values) {
		g_free(data->values->data);
		data->values = g_slist_delete_link(data->values, data->values);
	}
	g_free(data);

	cb(js, result, user_data);
}
Пример #6
0
void
AddMobileBuddy(struct fetion_account_data *sip, struct sipmsg *msg,
	       struct transaction *tc)
{
	gint xml_len;
	xmlnode *root, *son, *item;
	gchar *body;
	const gchar *uri, *name, *group_id;
	struct group_attr *g_attr = NULL;
	gchar *buddy_name;
	PurpleBuddy *b;
	PurpleGroup *g = NULL;
	struct fetion_buddy *bs;
	struct sipmsg *old = NULL;
	const gchar *real_name;

	real_name =
	    purple_account_get_string(sip->account, "realname", sip->username);

	if (!real_name || strlen(real_name) < 1) {
		real_name = sip->username;
	}

	g_return_if_fail(tc->msg != NULL);
	old = tc->msg;
	g_return_if_fail(old != NULL);
	purple_debug_info("fetion:", "AddMobileBuddy:oldmsg[%s]", old->body);
	root = xmlnode_from_str(old->body, old->bodylen);
	item = xmlnode_get_child(root, "contacts/buddies/buddy");
	g_return_if_fail(item != NULL);

	uri = xmlnode_get_attrib(item, "uri");
	name = xmlnode_get_attrib(item, "local-name");
	group_id = xmlnode_get_attrib(item, "buddy-lists");
	buddy_name = g_strdup_printf("%s", uri);
	g_attr = g_hash_table_lookup(sip->group, group_id);
	g_return_if_fail(g_attr != NULL);
	g = purple_find_group(g_attr->name);
	if (!g)
		g = purple_group_new(g_attr->name);

	b = purple_find_buddy(sip->account, buddy_name);
	if (!b) {
		b = purple_buddy_new(sip->account, buddy_name, NULL);
	}

	purple_blist_add_buddy(b, NULL, g, NULL);
	if (name != NULL && *name != '\0')
		purple_blist_alias_buddy(b, name);
	bs = g_new0(struct fetion_buddy, 1);
	bs->name = g_strdup(b->name);
	g_hash_table_insert(sip->buddies, bs->name, bs);

	xmlnode_free(root);

	root = xmlnode_new("args");
	g_return_if_fail(root != NULL);
	son = xmlnode_new_child(root, "contacts");
	g_return_if_fail(son != NULL);
	son = xmlnode_new_child(son, "mobile-buddies");
	g_return_if_fail(son != NULL);
	item = xmlnode_new_child(son, "mobile-buddy");
	g_return_if_fail(item != NULL);

	xmlnode_set_attrib(item, "expose-mobile-no", "1");
	xmlnode_set_attrib(item, "expose-name", "1");
	xmlnode_set_attrib(item, "invite", "1");

	xmlnode_set_attrib(item, "uri", buddy_name);
	xmlnode_set_attrib(item, "buddy-lists", "1");
	//xmlnode_set_attrib(item,"desc",sip->mobileno);
	xmlnode_set_attrib(item, "desc", real_name);

	body = g_strdup_printf("%s",xmlnode_to_str(root, &xml_len));
	purple_debug_info("fetion:", "add_buddy:body=[%s]", body);

	send_sip_request(sip->gc, "S", "", "", "N: AddMobileBuddy\r\n", body,
			 NULL, (TransCallback) AddMobileBuddy_cb);

	g_free(buddy_name);
	xmlnode_free(root);
	g_free(body);

}
Пример #7
0
JabberChat *jabber_join_chat(JabberStream *js, const char *room,
                             const char *server, const char *handle,
                             const char *password, GHashTable *data)
{
	JabberChat *chat;

	PurpleConnection *gc;
	PurpleAccount *account;
	PurpleStatus *status;

	xmlnode *presence, *x;
	JabberBuddyState state;
	char *msg;
	int priority;

	char *jid;

	char *history_maxchars;
	char *history_maxstanzas;
	char *history_seconds;
	char *history_since;

	struct tm history_since_datetime;
	const char *history_since_string = NULL;

	chat = jabber_chat_new(js, room, server, handle, password, data);
	if (chat == NULL)
		return NULL;

	gc = js->gc;
	account = purple_connection_get_account(gc);
	status = purple_account_get_active_status(account);
	purple_status_to_jabber(status, &state, &msg, &priority);

	presence = jabber_presence_create_js(js, state, msg, priority);
	g_free(msg);

	jid = g_strdup_printf("%s@%s/%s", room, server, handle);
	xmlnode_set_attrib(presence, "to", jid);
	g_free(jid);

	history_maxchars   = g_hash_table_lookup(data, "history_maxchars");
	history_maxstanzas = g_hash_table_lookup(data, "history_maxstanzas");
	history_seconds    = g_hash_table_lookup(data, "history_seconds");
	history_since      = g_hash_table_lookup(data, "history_since");

	if (history_since) {
		if (purple_str_to_time(history_since, TRUE, &history_since_datetime, NULL, NULL) != 0) {
			history_since_string = purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", &history_since_datetime);
		} else {
			history_since_string = NULL;

			purple_debug_error("jabber", "Invalid date format for history_since"
			                             " while requesting history: %s", history_since);
		}
	}

	x = xmlnode_new_child(presence, "x");
	xmlnode_set_namespace(x, "http://jabber.org/protocol/muc");

	if (password && *password) {
		xmlnode *p = xmlnode_new_child(x, "password");
		xmlnode_insert_data(p, password, -1);
	}

	if ((history_maxchars && *history_maxchars)
	    || (history_maxstanzas && *history_maxstanzas)
	    || (history_seconds && *history_seconds)
	    || (history_since_string && *history_since_string)) {

		xmlnode *history = xmlnode_new_child(x, "history");

		if (history_maxchars && *history_maxchars) {
			xmlnode_set_attrib(history, "maxchars", history_maxchars);
		}
		if (history_maxstanzas && *history_maxstanzas) {
			xmlnode_set_attrib(history, "maxstanzas", history_maxstanzas);
		}
		if (history_seconds && *history_seconds) {
			xmlnode_set_attrib(history, "seconds", history_seconds);
		}
		if (history_since_string && *history_since_string) {
			xmlnode_set_attrib(history, "since", history_since_string);
		}
	}

	jabber_send(js, presence);
	xmlnode_free(presence);

	return chat;
}
Пример #8
0
Файл: si.c Проект: 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);
	}
}
Пример #9
0
/* ------------------
 * called on received message
 * ------------------ */
static gboolean
jabber_message_received(PurpleConnection *pc, const char *type, const char *id,
                        const char *from, const char *to, xmlnode *message)
{
	const xmlnode* parent_node = message;
	xmlnode* x_node = NULL;
	xmlnode* body_node = NULL;

	if (parent_node == NULL)
		return FALSE;

	// check if message is a key
	body_node = xmlnode_get_child(parent_node,"body");
	if (body_node != NULL)
	{
		char* data = xmlnode_get_data(body_node);
		if (data != NULL)
		{
			char* header = "-----BEGIN PGP PUBLIC KEY BLOCK-----";
			if (strncmp(data,header,strlen(header)) == 0)
			{
				// if we received a ascii armored key
				// try to import it
				//purple_conversation_write(conv,"","received key",PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
				if (import_key(data) == TRUE)
				{
					xmlnode_clear_data(body_node);
					xmlnode_insert_data(body_node,"key import ok",-1);
				}
				else
				{
					xmlnode_clear_data(body_node);
					xmlnode_insert_data(body_node,"key import failed",-1);
				}
			}
		}
	}

	// check if the user with the jid=from has signed his presence
	char* bare_jid = get_bare_jid(from);

	// get stored info about user
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item == NULL)
	{
		//TODO: maybe create item in list?
	}else
	{
		// set default value to "not encrypted mode"
		item->mode_sec = FALSE;
	}
	free(bare_jid);

	// check if message has special "x" child node => encrypted message
	x_node = xmlnode_get_child_with_namespace(parent_node,"x",NS_ENC);
	if (x_node != NULL)
	{
		purple_debug_info(PLUGIN_ID, "user %s sent us an encrypted message\n",from);

		// get data of "x" node
		char* cipher_str = xmlnode_get_data(x_node);
		if (cipher_str != NULL)
		{
			// try to decrypt
			char* plain_str = decrypt(cipher_str);
			if (plain_str != NULL)
			{
				purple_debug_info(PLUGIN_ID, "decrypted message: %s\n",plain_str);
				// find body node
				xmlnode *body_node = xmlnode_get_child(parent_node,"body");
				if (body_node != NULL)
				{
					// clear body node data if it is found
					xmlnode_clear_data(body_node);
				}else
				{
					// add body node if it is not found
					body_node = xmlnode_new_child(message,"body");
				}
				// set "body" content node to decrypted string
				//xmlnode_insert_data(body_node,"Encrypted message: ",-1);
				xmlnode_insert_data(body_node,plain_str,-1);

				// only set to encrypted mode, if we know other users key fingerprint
				if (item != NULL)
				{
					// all went well, we received an encrypted message
					item->mode_sec = TRUE;
				}
			}else
			{
				purple_debug_error(PLUGIN_ID, "could not decrypt message!\n");
			}
		}else
		{
			purple_debug_error(PLUGIN_ID, "xml token had no data!\n");
		}
	}

	/* We don't want the plugin to stop processing */
	return FALSE;
}
Пример #10
0
static void
yahoo_set_userinfo_cb(PurpleConnection *gc, PurpleRequestFields *fields)
{
	xmlnode *node = xmlnode_new("ab");
	xmlnode *ct = xmlnode_new_child(node, "ct");
	YahooData *yd = purple_connection_get_protocol_data(gc);
	PurpleAccount *account;
	PurpleUtilFetchUrlData *url_data;
	char *webaddress, *webpage;
	char *request, *content;
	int len;
	int i;
	char * yfields[] = { "fn", "ln", "nn", "mn", "hp", "wp", "mo", NULL };

	account = purple_connection_get_account(gc);

	xmlnode_set_attrib(node, "k", purple_connection_get_display_name(gc));
	xmlnode_set_attrib(node, "cc", "1");		/* XXX: ? */

	xmlnode_set_attrib(ct, "e", "1");
	xmlnode_set_attrib(ct, "yi", purple_request_fields_get_string(fields, "yname"));
	xmlnode_set_attrib(ct, "id", purple_request_fields_get_string(fields, "yid"));
	xmlnode_set_attrib(ct, "pr", "0");

	for (i = 0; yfields[i]; i++) {
		const char *v = purple_request_fields_get_string(fields, yfields[i]);
		xmlnode_set_attrib(ct, yfields[i], v ? v : "");
	}

	content = xmlnode_to_formatted_str(node, &len);
	xmlnode_free(node);
	purple_url_parse(yd->jp ? YAHOOJP_USERINFO_URL : YAHOO_USERINFO_URL, &webaddress, NULL, &webpage, NULL, NULL);

	request = g_strdup_printf("POST %s HTTP/1.1\r\n"
				  "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
				  "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
				  "Host: %s\r\n"
				  "Content-Length: %d\r\n"
				  "Cache-Control: no-cache\r\n\r\n"
				  "%s\r\n\r\n",
				  webpage,
				  yd->cookie_t, yd->cookie_y,
				  webaddress,
				  len + 4,
				  content);

#if 0
	{
		/* This is if we wanted to send our contact details to everyone
		 * in the buddylist. But this cannot be done now, because in the
		 * official messenger, doing this pops a conversation window at
		 * the receiver's end, which is stupid, and thus not really
		 * surprising. */
		struct yahoo_userinfo *ui = g_new(struct yahoo_userinfo, 1);
		node = xmlnode_new("contact");

		for (i = 0; yfields[i]; i++) {
			const char *v = purple_request_fields_get_string(fields, yfields[i]);
			if (v) {
				xmlnode *nd = xmlnode_new_child(node, yfields[i]);
				xmlnode_insert_data(nd, v, -1);
			}
		}

		ui->yd = yd;
		ui->xml = xmlnode_to_str(node, NULL);
		xmlnode_free(node);
	}
#endif

	url_data = purple_util_fetch_url_request_len_with_account(account, webaddress, FALSE,
			YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
			yahoo_fetch_aliases_cb, gc);
	if (url_data != NULL)
		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);

	g_free(webaddress);
	g_free(webpage);
	g_free(content);
	g_free(request);
}
Пример #11
0
Файл: si.c Проект: 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);
	}
}
Пример #12
0
static void
got_file_send_progress(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
{
	SkypeWebFileTransfer *swft = user_data;
	PurpleXfer *xfer = swft->xfer;
	SkypeWebAccount *sa = swft->sa;
	JsonParser *parser;
	JsonNode *node;
	JsonObject *obj;
	
	sa->url_datas = g_slist_remove(sa->url_datas, url_data);
	
	//{"content_length":0,"content_full_length":0,"view_length":0,"content_state":"no content","view_state":"none","view_location":"https://nus1-api.asm.skype.com/v1/objects/0-cus-d1-61121cfae8cf601944627a66afdb77ad/views/original","status_location":"https://nus1-api.asm.skype.com/v1/objects/0-cus-d1-61121cfae8cf601944627a66afdb77ad/views/original/status"}
	parser = json_parser_new();
	if (!json_parser_load_from_data(parser, url_text, len, NULL)) {
		//probably bad
		poll_file_send_progress(swft);
		return;
	}
	node = json_parser_get_root(parser);
	if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) {
		//probably bad
		poll_file_send_progress(swft);
		return;
	}
	obj = json_node_get_object(node);
	
	
	if (json_object_has_member(obj, "status_location")) {
		g_free(swft->url);
		swft->url = g_strdup(json_object_get_string_member(obj, "status_location"));
	}
	
	if (json_object_has_member(obj, "content_state") && g_str_equal(json_object_get_string_member(obj, "content_state"), "ready")) {
		xmlnode *uriobject = xmlnode_new("URIObject");
		xmlnode *title = xmlnode_new_child(uriobject, "Title");
		xmlnode *description = xmlnode_new_child(uriobject, "Description");
		xmlnode *anchor = xmlnode_new_child(uriobject, "a");
		xmlnode *originalname = xmlnode_new_child(uriobject, "OriginalName");
		xmlnode *filesize = xmlnode_new_child(uriobject, "FileSize");
		gchar *message, *temp;
		//We finally did it!
		// May the pesants rejoyce
		purple_xfer_set_completed(xfer, TRUE);
		
		// Don't forget to let the other end know about it
		
		xmlnode_set_attrib(uriobject, "type", "File.1");
		temp = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), NULL);
		xmlnode_set_attrib(uriobject, "uri", temp);
		g_free(temp);
		temp = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), "/views/thumbnail", NULL);
		xmlnode_set_attrib(uriobject, "url_thumbnail", temp);
		g_free(temp);
		xmlnode_insert_data(title, purple_xfer_get_filename(xfer), -1);
		xmlnode_insert_data(description, "Description: ", -1);
		temp = g_strconcat("https://login.skype.com/login/sso?go=webclient.xmm&docid=", purple_url_encode(swft->id), NULL);
		xmlnode_set_attrib(anchor, "href", temp);
		xmlnode_insert_data(anchor, temp, -1);
		g_free(temp);
		xmlnode_set_attrib(originalname, "v", purple_xfer_get_filename(xfer));
		temp = g_strdup_printf("%d", purple_xfer_get_size(xfer));
		xmlnode_set_attrib(filesize, "v", temp);
		g_free(temp);
		
		message = xmlnode_to_str(uriobject, NULL);
		skypeweb_send_im(sa->pc, swft->from, message, PURPLE_MESSAGE_SEND);
		g_free(message);
		
		skypeweb_free_xfer(xfer);
		purple_xfer_unref(xfer);
		
		xmlnode_free(uriobject);
		g_object_unref(parser);
		return;
	}
	
	
	g_object_unref(parser);
	
	// probably good
	poll_file_send_progress(swft);
}
Пример #13
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);
	}
}
Пример #14
0
void jabber_mam_request(JabberStream *js, const char* after)
{
	if (!js->mam)
		return;
	
	JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_SET, NS_XMPP_MAM);
	xmlnode *query = xmlnode_get_child(iq->node, "query");

	xmlnode *x = xmlnode_new_child(query, "x");
	xmlnode_set_namespace(x, "jabber:x:data");

	xmlnode *field = xmlnode_new_child(x, "field");
	xmlnode_set_attrib(field, "type", "hidden");
	xmlnode_set_attrib(field, "var", "FORM_TYPE");
	xmlnode *value = xmlnode_new_child(field, "value");
	xmlnode_insert_data(value, NS_XMPP_MAM, -1);

	if (after) {
		xmlnode *set = xmlnode_new_child(query, "set");
		xmlnode_set_namespace(set, NS_RSM);

		value = xmlnode_new_child(set, "after");
		xmlnode_insert_data(value, after, -1);
	}

	if (js->mam->current->start) {
		field = xmlnode_new_child(x, "field");
		xmlnode_set_attrib(field, "var", "start");

		value = xmlnode_new_child(field, "value");
		xmlnode_insert_data(value, js->mam->current->start, -1);
	}

	if (js->mam->current->end) {
		field = xmlnode_new_child(x, "field");
		xmlnode_set_attrib(field, "var", "end");

		value = xmlnode_new_child(field, "value");
		xmlnode_insert_data(value, js->mam->current->end, -1);
	}

	if (js->mam->current->with) {
		field = xmlnode_new_child(x, "field");
		xmlnode_set_attrib(field, "var", "with");

		value = xmlnode_new_child(field, "value");
		xmlnode_insert_data(value, js->mam->current->with, -1);
	}

	jabber_iq_send(iq);
}
Пример #15
0
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);
	}
}
Пример #16
0
/* ------------------
 * called on every sent packet
 * ------------------ */
void jabber_send_signal_cb(PurpleConnection *pc, xmlnode **packet,
                           gpointer unused)
{
	if (NULL == packet)
		return;

	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(pc));

	// if we are sending a presence stanza, add new child node
	//  so others know we support openpgp
	if (g_str_equal((*packet)->name, "presence"))
	{
		const char* status_str = NULL;
		xmlnode* status_node;

		// check if user selected a main key
		const char* fpr = purple_prefs_get_string(PREF_MY_KEY);
		if (fpr == NULL)
			fpr = "";
		if (strcmp(fpr,"") != 0)
		{// user did select a key
			// get status message from packet
			status_node = xmlnode_get_child(*packet,"status");
			if (status_node != NULL)
			{
				status_str = xmlnode_get_data(status_node);
			}

			// sign status message
			if (status_str == NULL)
				status_str = "";
			purple_debug_info(PLUGIN_ID, "signing status '%s' with key %s\n",status_str,fpr);

			char* sig_str = sign(status_str,fpr);
			if (sig_str == NULL)
			{
				purple_debug_error(PLUGIN_ID,"sign failed\n");
				return;
			}

			// create special "x" childnode
			purple_debug_info(PLUGIN_ID, "sending presence with signature\n");
			xmlnode *x_node = xmlnode_new_child(*packet,"x");
			xmlnode_set_namespace(x_node, NS_SIGNED);
			xmlnode_insert_data(x_node, sig_str,-1);
		}else
		{
			purple_debug_info(PLUGIN_ID, "no key selecteded!\n");
		}
	}else
	if (g_str_equal((*packet)->name, "message"))
	{
		const char* to = xmlnode_get_attrib(*packet,"to");
		xmlnode* body_node = xmlnode_get_child(*packet,"body");
		if (body_node != NULL && to != NULL)
		{
			// get message
			char* message = g_strdup(xmlnode_get_data(body_node));
			char* enc_str = NULL;
			char* bare_jid = get_bare_jid(to);

			// get encryption key
			struct list_item *item = g_hash_table_lookup(list_fingerprints,bare_jid);
			if (item == NULL)
			{
				purple_debug_info(PLUGIN_ID, "there is no key for encrypting message to %s\n",bare_jid);
				return;
			}
			// do not encrypt if mode_sec is disabled
			if (item->mode_sec == FALSE)
				return;

			char* fpr_to = item->fpr;
			purple_debug_info(PLUGIN_ID, "found key for encryption to user %s: %s\n",bare_jid,fpr_to);
			free(bare_jid);

			// encrypt message
			enc_str = encrypt(message,fpr_to);
			if (enc_str != NULL)
			{
				// remove message from body
				xmlnode_clear_data(body_node);
				xmlnode_insert_data(body_node,"[ERROR: This message is encrypted, and you are unable to decrypt it.]",-1);

				// add special "x" childnode for encrypted text
				purple_debug_info(PLUGIN_ID, "sending encrypted message\n");
				xmlnode *x_node = xmlnode_new_child(*packet,"x");
				xmlnode_set_namespace(x_node, NS_ENC);
				xmlnode_insert_data(x_node, enc_str,-1);
			}else
			{
				purple_debug_error(PLUGIN_ID, "could not encrypt message\n");
			}
		}else
		{
			// ignore this type of messages
			//purple_debug_warning(PLUGIN_ID, "empty message or empty 'to'\n");
		}
	}
}
Пример #17
0
/* jabber_roster_update frees the GSList* passed in */
static void jabber_roster_update(JabberStream *js, const char *name,
		GSList *groups)
{
	PurpleBuddy *b;
	PurpleGroup *g;
	GSList *l;
	JabberIq *iq;
	xmlnode *query, *item, *group;
	const char *balias;

	if (js->currently_parsing_roster_push)
		return;

	if(!(b = purple_find_buddy(js->gc->account, name)))
		return;

	if (groups) {
		char *tmp = roster_groups_join(groups);

		purple_debug_info("jabber", "jabber_roster_update(%s): [Source: "
		                  "groups]: groups: %s\n", name, tmp);
		g_free(tmp);
	} else {
		GSList *buddies = purple_find_buddies(js->gc->account, name);
		char *tmp;

		if(!buddies)
			return;
		while(buddies) {
			b = buddies->data;
			g = purple_buddy_get_group(b);
			groups = g_slist_append(groups, (char *)purple_group_get_name(g));
			buddies = g_slist_remove(buddies, b);
		}

		tmp = roster_groups_join(groups);
		purple_debug_info("jabber", "jabber_roster_update(%s): [Source: local blist]: groups: %s\n",
		                  name, tmp);
		g_free(tmp);
	}

	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");

	query = xmlnode_get_child(iq->node, "query");
	item = xmlnode_new_child(query, "item");

	xmlnode_set_attrib(item, "jid", name);

	balias = purple_buddy_get_local_buddy_alias(b);
	xmlnode_set_attrib(item, "name", balias ? balias : "");

	for(l = groups; l; l = l->next) {
		group = xmlnode_new_child(item, "group");
		xmlnode_insert_data(group, l->data, -1);
	}

	g_slist_free(groups);

	if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
		jabber_google_roster_outgoing(js, query, item);
		xmlnode_set_attrib(query, "xmlns:gr", "google:roster");
		xmlnode_set_attrib(query, "gr:ext", "2");
	}
	jabber_iq_send(iq);
}
Пример #18
0
void jabber_chat_join(PurpleConnection *gc, GHashTable *data)
{
	JabberChat *chat;
	char *room, *server, *handle, *passwd;
	xmlnode *presence, *x;
	char *tmp, *room_jid, *full_jid;
	JabberStream *js = gc->proto_data;
	PurplePresence *gpresence;
	PurpleStatus *status;
	JabberBuddyState state;
	char *msg;
	int priority;

	room = g_hash_table_lookup(data, "room");
	server = g_hash_table_lookup(data, "server");
	handle = g_hash_table_lookup(data, "handle");
	passwd = g_hash_table_lookup(data, "password");

	if(!room || !server)
		return;

	if(!handle)
		handle = js->user->node;

	if(!jabber_nodeprep_validate(room)) {
		char *buf = g_strdup_printf(_("%s is not a valid room name"), room);
		purple_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"),
				buf);
		g_free(buf);
		return;
	} else if(!jabber_nameprep_validate(server)) {
		char *buf = g_strdup_printf(_("%s is not a valid server name"), server);
		purple_notify_error(gc, _("Invalid Server Name"),
				_("Invalid Server Name"), buf);
		g_free(buf);
		return;
	} else if(!jabber_resourceprep_validate(handle)) {
		char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle);
		purple_notify_error(gc, _("Invalid Room Handle"),
				_("Invalid Room Handle"), buf);
	}

	if(jabber_chat_find(js, room, server))
		return;

	tmp = g_strdup_printf("%s@%s", room, server);
	room_jid = g_strdup(jabber_normalize(NULL, tmp));
	g_free(tmp);

	chat = g_new0(JabberChat, 1);
	chat->js = gc->proto_data;

	chat->room = g_strdup(room);
	chat->server = g_strdup(server);
	chat->handle = g_strdup(handle);

	chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
			(GDestroyNotify)jabber_chat_member_free);

	g_hash_table_insert(js->chats, room_jid, chat);

	gpresence = purple_account_get_presence(gc->account);
	status = purple_presence_get_active_status(gpresence);

	purple_status_to_jabber(status, &state, &msg, &priority);

	presence = jabber_presence_create(state, msg, priority);
	full_jid = g_strdup_printf("%s/%s", room_jid, handle);
	xmlnode_set_attrib(presence, "to", full_jid);
	g_free(full_jid);
	g_free(msg);

	x = xmlnode_new_child(presence, "x");
	xmlnode_set_namespace(x, "http://jabber.org/protocol/muc");

	if(passwd && *passwd) {
		xmlnode *password = xmlnode_new_child(x, "password");
		xmlnode_insert_data(password, passwd, -1);
	}

	jabber_send(js, presence);
	xmlnode_free(presence);
}
Пример #19
0
static void
xep_ft_si_offer(PurpleXfer *xfer, const gchar *to)
{
	xmlnode *si_node, *feature, *field, *file, *x;
	XepIq *iq;
	XepXfer *xf = xfer->data;
	BonjourData *bd = NULL;
	char buf[32];

	if(!xf)
		return;

	bd = xf->data;
	if(!bd)
		return;

	purple_debug_info("bonjour", "xep file transfer stream initialization offer-id=%d.\n", next_id);

	/* Assign stream id. */
	g_free(xf->iq_id);
	xf->iq_id = g_strdup_printf("%u", next_id++);
	iq = xep_iq_new(xf->data, XEP_IQ_SET, to, bonjour_get_jid(bd->jabber_data->account), xf->iq_id);
	if(iq == NULL)
		return;

	/*Construct Stream initialization offer message.*/
	si_node = xmlnode_new_child(iq->node, "si");
	xmlnode_set_namespace(si_node, "http://jabber.org/protocol/si");
	xmlnode_set_attrib(si_node, "profile", "http://jabber.org/protocol/si/profile/file-transfer");
	g_free(xf->sid);
	xf->sid = g_strdup(xf->iq_id);
	xmlnode_set_attrib(si_node, "id", xf->sid);

	file = xmlnode_new_child(si_node, "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);

	feature = xmlnode_new_child(si_node, "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");

	if (xf->mode & XEP_BYTESTREAMS) {
		xmlnode *option = xmlnode_new_child(field, "option");
		xmlnode *value = xmlnode_new_child(option, "value");
		xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", -1);
	}
	if (xf->mode & XEP_IBB) {
		xmlnode *option = xmlnode_new_child(field, "option");
		xmlnode *value = xmlnode_new_child(option, "value");
		xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1);
	}

	xep_iq_send_and_free(iq);
}
Пример #20
0
gint
hybrid_logs_write(HybridLogs *log, const gchar *name, const gchar *msg,
					gboolean sendout)
{
	xmlnode *head_node;
	xmlnode *body_node;
	xmlnode *time_node;
	xmlnode *font_node;
	xmlnode *name_node;
	xmlnode *cont_node;
	xmlnode *node;
	time_t now;
	const gchar *body;
	gchar *title;
	gchar *content;
	struct tm *local_time;
	gchar time_str[128];

	g_return_val_if_fail(log != NULL, HYBRID_ERROR);
	g_return_val_if_fail(name != NULL, HYBRID_ERROR);

	now = time(NULL);

	local_time = localtime(&now);


	/* log file doesn't exist, we create one. */
	if (!log->root) {
		body = "<html></html>";

		title = g_strdup_printf(_("Conversation with %s (%s) at %d-%d-%d"),
				name, log->id, local_time->tm_year + 1900,
				local_time->tm_mon, local_time->tm_mday);

		log->root = xmlnode_root(body, strlen(body));

		head_node = xmlnode_new_child(log->root, "head");

		node = xmlnode_new_child(head_node, "meta");
		xmlnode_new_prop(node, "http-equiv", "content-type");
		xmlnode_new_prop(node, "content", "text/html; charset=UTF-8");

		node = xmlnode_new_child(head_node, "title");

		xmlnode_set_content(node, title);

		node = xmlnode_new_child(log->root, "body");

		node = xmlnode_new_child(node, "h3");

		xmlnode_set_content(node, title);

		g_free(title);
	}

	if (!(body_node = xmlnode_find(log->root, "body"))) {

		hybrid_debug_error("logs", "invalid log file.");

		g_free(title);

		return HYBRID_ERROR;
	}

	node = xmlnode_new_child(body_node, "span");

	font_node = xmlnode_new_child(node, "font");
	if (sendout) {
		xmlnode_new_prop(font_node, "color", "#16569E");

	} else {
		xmlnode_new_prop(font_node, "color", "#A82F2F");
	}

	time_node = xmlnode_new_child(font_node, "font");
	xmlnode_new_prop(time_node, "size", "2");

	memset(time_str, 0, sizeof(time_str));
	strftime(time_str, sizeof(time_str) - 1, "(%H:%M:%S) ", local_time);

	xmlnode_set_content(time_node, time_str);

	content = g_strdup_printf("%s: ", name);
	name_node = xmlnode_new_child(font_node, "b");
	xmlnode_set_content(name_node, content);
	g_free(content);

	cont_node = xmlnode_new_child(node, "font");
	xmlnode_set_content(cont_node, msg);

	xmlnode_new_child(node, "br");

	xmlnode_save_file(log->root, log->log_path);

	return HYBRID_OK;
}