Пример #1
0
void GetBuddyInfo(struct fetion_account_data *sip, const char *who)
{
	gint xml_len;
	xmlnode *root, *son, *item;
	gchar *body;

	root = xmlnode_new("args");
	g_return_if_fail(root != NULL);
	son = xmlnode_new_child(root, "contacts");
	xmlnode_set_attrib(son, "attributes", "all");
	//xmlnode_set_attrib(son,"extended-attributes","score-level");
	g_return_if_fail(son != NULL);
	item = xmlnode_new_child(son, "contact");
	g_return_if_fail(item != NULL);

	xmlnode_set_attrib(item, "uri", who);

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

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

	xmlnode_free(root);
	g_free(body);

}
Пример #2
0
void CreateTempGroup(PurpleConnection * gc, PurpleBuddy * buddy)
{
	gchar *body, *hdr;
	gint xml_len;
	xmlnode *root, *son, *item;
	struct fetion_account_data *sip = gc->proto_data;

	root = xmlnode_new("args");
	g_return_if_fail(root != NULL);
	son = xmlnode_new_child(root, "participants");
	g_return_if_fail(son != NULL);
	son = xmlnode_new_child(son, "participant");
	g_return_if_fail(son != NULL);

	xmlnode_set_attrib(son, "uri", buddy->name);

	hdr = g_strdup("N: CreateTemporaryGroup\r\nK: text/html-fragment\r\n");
	body = g_strdup_printf(xmlnode_to_str(root, &xml_len));
	purple_debug(PURPLE_DEBUG_MISC, "fetion", "in CreateTempGroup[%s]\n",
		     body);
	send_sip_request(sip->gc, "S", "", "", hdr, body, NULL,
			 CreateTempGroup_cb);

	g_free(body);
	g_free(hdr);
	xmlnode_free(root);

}
static void
shinima_message_links_foreach(gchar **message,
							  void(*foreach_func)(xmlnode*,
												  const gchar*,
												  gchar**,
												  gboolean*,
												  gpointer),
							  gboolean *_changed,
							  gpointer *user_data)
{
	xmlnode *root, *a;
	gboolean *changed =
		(_changed != NULL) ? changed : g_malloc(sizeof(gboolean));

	g_return_if_fail(foreach_func != NULL);

	root = xmlnode_from_str(*message, -1);

	for(a=xmlnode_get_child(root, "a"); a; a=xmlnode_get_next_twin(a))
	{
		const gchar *href = xmlnode_get_attrib(a, "href");
		if(href) foreach_func(a, href, message, changed, user_data);
	}

	if(changed)
	{
		g_free(*message);
		*message = xmlnode_to_str(root, NULL);
	}

	if(_changed == NULL) g_free(changed);

	xmlnode_free(root);
}
Пример #4
0
/* Parse the XML data,
 * prepare to report the OIM to user
 */
static void
msn_oim_get_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
	gpointer data)
{
	MsnOimRecvData *rdata = data;

	if (response != NULL) {
		xmlnode *msg_node = xmlnode_get_child(response->xml,
			"Body/GetMessageResponse/GetMessageResult");

		if (msg_node) {
			char *msg_str = xmlnode_get_data(msg_node);
			msn_oim_report_to_user(rdata, msg_str);
			g_free(msg_str);
		} else {
			char *str = xmlnode_to_str(response->xml, NULL);
			purple_debug_info("msn", "Unknown OIM response: %s\n", str);
			g_free(str);
			msn_oim_recv_data_free(rdata);
		}
	} else {
		purple_debug_info("msn", "Failed to get OIM\n");
		msn_oim_recv_data_free(rdata);
	}

}
Пример #5
0
void
campfire_http_request(CampfireSslTransaction * xaction, gchar * uri,
		      gchar * method, xmlnode * postxml)
{
	CampfireConn *conn = xaction->campfire;
	const char *api_token =
		purple_account_get_string(conn->account, "api_token", "");
	gchar *xmlstr = NULL, *len = NULL, *encoded = NULL;
	gsize auth_len;

	xaction->http_request = g_string_new(method);
	g_string_append(xaction->http_request, " ");
	g_string_append(xaction->http_request, uri);
	g_string_append(xaction->http_request, " HTTP/1.1\r\n");

	g_string_append(xaction->http_request,
			"Content-Type: application/xml\r\n");

	g_string_append(xaction->http_request, "Authorization: Basic ");
	auth_len = strlen(api_token);
	encoded = purple_base64_encode((const guchar *) api_token, auth_len);
	g_string_append(xaction->http_request, encoded);
	g_string_append(xaction->http_request, "\r\n");
	g_free(encoded);

	g_string_append(xaction->http_request, "Host: ");
	g_string_append(xaction->http_request, conn->hostname);
	g_string_append(xaction->http_request, "\r\n");

	g_string_append(xaction->http_request, "Accept: */*\r\n");

	if (postxml) {
		xmlstr = xmlnode_to_str(postxml, NULL);
		g_string_append(xaction->http_request, "Content-Length: ");
		/* len = g_strdup_printf("%lu", strlen(xmlstr)); */
		len = g_strdup_printf("%" G_GSIZE_FORMAT, strlen(xmlstr));
		g_string_append(xaction->http_request, len);
		g_free(len);
		g_string_append(xaction->http_request, "\r\n\r\n");
		g_string_append(xaction->http_request, xmlstr);
		g_string_append(xaction->http_request, "\r\n");
	}
	g_string_append(xaction->http_request, "\r\n");
	purple_debug_info("campfire", "Formatted request:\n%s\n",
			  xaction->http_request->str);
}
Пример #6
0
static gchar *
get_xmlnode_contents(xmlnode *node)
{
	gchar *contents;

	contents = xmlnode_to_str(node, NULL);

	/* we just want the stuff inside <font></font>
	 * There isn't stuff exposed in xmlnode.c to do this more cleanly. */

	if (contents) {
		char *bodystart = strchr(contents, '>');
		char *bodyend = bodystart ? strrchr(bodystart, '<') : NULL;
		if (bodystart && bodyend && (bodystart + 1) != bodyend) {
			*bodyend = '\0';
			memmove(contents, bodystart + 1, (bodyend - bodystart));
		}
	}

	return contents;
}
static char*
xmlnode_get_content(xmlnode *node)
{
    GString *text = g_string_new("");
    xmlnode *c;
    char *esc;

    for(c = node->child; c; c = c->next) {
        if(c->type == XMLNODE_TYPE_TAG) {
            int esc_len;
            esc = xmlnode_to_str(c, &esc_len);
            text = g_string_append_len(text, esc, esc_len);
            g_free(esc);
        } else if(c->type == XMLNODE_TYPE_DATA && c->data_sz > 0) {
            esc = g_markup_escape_text(c->data, c->data_sz);
            text = g_string_append(text, esc);
            g_free(esc);
        }
    }

    return g_string_free(text, FALSE);
}
Пример #8
0
/*
 * WLM media PSM info build prcedure
 *
 * Result can like:
 *	<CurrentMedia>\0Music\01\0{0} - {1}\0Song Title\0Song Artist\0Song Album\0\0</CurrentMedia>\
 *	<CurrentMedia>\0Games\01\0Playing {0}\0Game Name\0</CurrentMedia>\
 *	<CurrentMedia>\0Office\01\0Office Message\0Office App Name\0</CurrentMedia>"
 */
static char *
msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr, guint protocol_ver)
{
	xmlnode *dataNode,*psmNode,*mediaNode,*guidNode;
	char *result;
	int length;

	dataNode = xmlnode_new("Data");

	psmNode = xmlnode_new("PSM");
	if(psmstr != NULL){
		xmlnode_insert_data(psmNode, psmstr, -1);
	}
	xmlnode_insert_child(dataNode, psmNode);

	mediaNode = xmlnode_new("CurrentMedia");
	if(mediastr != NULL){
		xmlnode_insert_data(mediaNode, mediastr, -1);
	}
	xmlnode_insert_child(dataNode, mediaNode);

	guidNode = xmlnode_new("MachineGuid");
	if(guidstr != NULL){
		xmlnode_insert_data(guidNode, guidstr, -1);
	}
	xmlnode_insert_child(dataNode, guidNode);

	if (protocol_ver >= 16) {
		/* TODO: What is this for? */
		xmlnode *ddpNode = xmlnode_new("DDP");
		xmlnode_insert_child(dataNode, ddpNode);
	}

	result = xmlnode_to_str(dataNode, &length);
	xmlnode_free(dataNode);
	return result;
}
Пример #9
0
static void
_jabber_parse_and_write_message_to_ui(xmlnode *message_node, PurpleBuddy *pb)
{
	xmlnode *body_node, *html_node, *events_node;
	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(pb));
	gchar *body = NULL;

	body_node = xmlnode_get_child(message_node, "body");
	html_node = xmlnode_get_child(message_node, "html");

	if (body_node == NULL && html_node == NULL) {
		purple_debug_error("bonjour", "No body or html node found, discarding message.\n");
		return;
	}

	events_node = xmlnode_get_child_with_namespace(message_node, "x", "jabber:x:event");
	if (events_node != NULL) {
#if 0
		if (xmlnode_get_child(events_node, "composing") != NULL)
			composing_event = TRUE;
#endif
		if (xmlnode_get_child(events_node, "id") != NULL) {
			/* The user is just typing */
			/* TODO: Deal with typing notification */
			return;
		}
	}

	if (html_node != NULL) {
		xmlnode *html_body_node;

		html_body_node = xmlnode_get_child(html_node, "body");
		if (html_body_node != NULL) {
			xmlnode *html_body_font_node;

			html_body_font_node = xmlnode_get_child(html_body_node, "font");
			/* Types of messages sent by iChat */
			if (html_body_font_node != NULL) {
				gchar *html_body;
				const char *font_face, *font_size,
					*ichat_balloon_color, *ichat_text_color;

				font_face = xmlnode_get_attrib(html_body_font_node, "face");
				/* The absolute iChat font sizes should be converted to 1..7 range */
				font_size = xmlnode_get_attrib(html_body_font_node, "ABSZ");
				if (font_size != NULL)
					font_size = _font_size_ichat_to_purple(atoi(font_size));
				/*font_color = xmlnode_get_attrib(html_body_font_node, "color");*/
				ichat_balloon_color = xmlnode_get_attrib(html_body_node, "ichatballooncolor");
				ichat_text_color = xmlnode_get_attrib(html_body_node, "ichattextcolor");

				html_body = get_xmlnode_contents(html_body_font_node);

				if (html_body == NULL)
					/* This is the kind of formatted messages that Purple creates */
					html_body = xmlnode_to_str(html_body_font_node, NULL);

				if (html_body != NULL) {
					GString *str = g_string_new("<font");

					if (font_face)
						g_string_append_printf(str, " face='%s'", font_face);
					if (font_size)
						g_string_append_printf(str, " size='%s'", font_size);
					if (ichat_text_color)
						g_string_append_printf(str, " color='%s'", ichat_text_color);
					if (ichat_balloon_color)
						g_string_append_printf(str, " back='%s'", ichat_balloon_color);
					g_string_append_printf(str, ">%s</font>", html_body);

					body = g_string_free(str, FALSE);

					g_free(html_body);
				}
			}
		}
	}

	/* Compose the message */
	if (body == NULL && body_node != NULL)
		body = xmlnode_get_data(body_node);

	if (body == NULL) {
		purple_debug_error("bonjour", "No html body or regular body found.\n");
		return;
	}

	/* Send the message to the UI */
	serv_got_im(gc, purple_buddy_get_name(pb), body, 0, time(NULL));

	g_free(body);
}
Пример #10
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);

}
Пример #11
0
static gboolean
msn_soap_connection_run(gpointer data)
{
	MsnSoapConnection *conn = data;
	MsnSoapRequest *req = g_queue_peek_head(conn->queue);

	conn->run_timer = 0;

	if (req) {
		if (conn->ssl == NULL) {
			conn->ssl = purple_ssl_connect(conn->session->account, conn->host,
				443, msn_soap_connected_cb, msn_soap_error_cb, conn);
		} else if (conn->connected) {
			int len = -1;
			char *body = xmlnode_to_str(req->message->xml, &len);
			GSList *iter;

			g_queue_pop_head(conn->queue);

			conn->buf = g_string_new("");

			g_string_append_printf(conn->buf,
				"POST /%s HTTP/1.1\r\n"
				"SOAPAction: %s\r\n"
				"Content-Type:text/xml; charset=utf-8\r\n"
				"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
				"Accept: */*\r\n"
				"Host: %s\r\n"
				"Content-Length: %d\r\n"
				"Connection: Keep-Alive\r\n"
				"Cache-Control: no-cache\r\n",
				req->path, req->message->action ? req->message->action : "",
				conn->host, len);

			for (iter = req->message->headers; iter; iter = iter->next) {
				g_string_append(conn->buf, (char *)iter->data);
				g_string_append(conn->buf, "\r\n");
			}

			g_string_append(conn->buf, "\r\n");
			g_string_append(conn->buf, body);

			if (req->secure && !purple_debug_is_unsafe())
				purple_debug_misc("soap", "Sending secure request.\n");
			else
				purple_debug_misc("soap", "%s\n", conn->buf->str);

			conn->handled_len = 0;
			conn->current_request = req;

			if (conn->event_handle)
				purple_input_remove(conn->event_handle);
			conn->event_handle = purple_input_add(conn->ssl->fd,
				PURPLE_INPUT_WRITE, msn_soap_write_cb, conn);
			if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) {
				/* Not connected => reconnect and retry */
				purple_debug_info("soap", "not connected, reconnecting\n");

				conn->connected = FALSE;
				conn->current_request = NULL;
				msn_soap_connection_sanitize(conn, FALSE);

				g_queue_push_head(conn->queue, req);
				conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
			}

			g_free(body);
		}
	}

	return FALSE;
}
Пример #12
0
static void
msn_parse_oim_xml(MsnOim *oim, xmlnode *node)
{
	xmlnode *mNode;
	xmlnode *iu_node;
	MsnSession *session = oim->session;

	g_return_if_fail(node != NULL);

	if (strcmp(node->name, "MD") != 0) {
		char *xmlmsg = xmlnode_to_str(node, NULL);
		purple_debug_info("msn", "WTF is this? %s\n", xmlmsg);
		g_free(xmlmsg);
		return;
	}

	iu_node = xmlnode_get_child(node, "E/IU");

	if (iu_node != NULL && purple_account_get_check_mail(session->account))
	{
		char *unread = xmlnode_get_data(iu_node);
		const char *passports[2] = { msn_user_get_passport(session->user) };
		const char *urls[2] = { session->passport_info.mail_url };
		int count = atoi(unread);

		/* XXX/khc: pretty sure this is wrong */
		if (count > 0)
			purple_notify_emails(session->account->gc, count, FALSE, NULL,
				NULL, passports, urls, NULL, NULL);
		g_free(unread);
	}

	for(mNode = xmlnode_get_child(node, "M"); mNode;
					mNode = xmlnode_get_next_twin(mNode)){
		char *passport, *msgid, *nickname, *rtime = NULL;
		xmlnode *e_node, *i_node, *n_node, *rt_node;

		e_node = xmlnode_get_child(mNode, "E");
		passport = xmlnode_get_data(e_node);

		i_node = xmlnode_get_child(mNode, "I");
		msgid = xmlnode_get_data(i_node);

		n_node = xmlnode_get_child(mNode, "N");
		nickname = xmlnode_get_data(n_node);

		rt_node = xmlnode_get_child(mNode, "RT");
		if (rt_node != NULL) {
			rtime = xmlnode_get_data(rt_node);
		}
/*		purple_debug_info("msn", "E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */

		if (!g_list_find_custom(oim->oim_list, msgid, (GCompareFunc)msn_recv_data_equal)) {
			MsnOimRecvData *data = msn_oim_recv_data_new(oim, msgid);
			msn_oim_post_single_get_msg(oim, data);
			msgid = NULL;
		}

		g_free(passport);
		g_free(msgid);
		g_free(rtime);
		g_free(nickname);
	}
}
Пример #13
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);
}
Пример #14
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);
}