Esempio n. 1
0
void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
{
	MsnMessage *msg;
	const char *passport;
	char *data;
	size_t size;

	msg = msn_message_new_msnslp();

	passport = purple_normalize(slplink->session->account, slplink->remote_user);
	msn_message_set_header(msg, "P2P-Dest", passport);

	msg->part = msn_slpmsgpart_ref(part);
	data = msn_slpmsgpart_serialize(part, &size);
	msn_message_set_bin_data(msg, data, size);
	g_free(data);

	if (slplink->swboard == NULL)
	{
		slplink->swboard = msn_session_get_swboard(slplink->session,
				slplink->remote_user, MSN_SB_FLAG_FT);

		g_return_if_fail(slplink->swboard != NULL);

		/* If swboard is destroyed we will be too */
		slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
	}

	msn_switchboard_send_msg(slplink->swboard, msg, TRUE);
	msn_message_unref(msg);
}
Esempio n. 2
0
File: msg.c Progetto: bf4/pidgin-mac
void
msn_message_destroy(MsnMessage *msg)
{
	g_return_if_fail(msg != NULL);

	if (msg->ref_count > 0)
	{
		msn_message_unref(msg);

		return;
	}

#ifdef MSN_DEBUG_MSG
	purple_debug_info("msn", "message destroy (%p)\n", msg);
#endif

	if (msg->remote_user != NULL)
		g_free(msg->remote_user);

	if (msg->body != NULL)
		g_free(msg->body);

	if (msg->content_type != NULL)
		g_free(msg->content_type);

	if (msg->charset != NULL)
		g_free(msg->charset);

	g_hash_table_destroy(msg->attr_table);
	g_list_free(msg->attr_list);

	g_free(msg);
}
Esempio n. 3
0
/** Called when we receive a nak of a special message. */
static void
msg_nak(MsnCmdProc *cmdproc, MsnCommand *cmd)
{
	MsnMessage *msg;

	msg = cmd->trans->data;

	msn_message_unref(msg);
}
Esempio n. 4
0
/** Called when we receive an ack of a special message. */
static void
msg_ack(MsnCmdProc *cmdproc, MsnCommand *cmd)
{
	MsnMessage *msg;

	msg = cmd->trans->data;

	if (msg->ack_cb != NULL)
		msg->ack_cb(msg->ack_data);

	msn_message_unref(msg);
}
Esempio n. 5
0
/* We have received the message nak. */
static void
msg_nak(MsnMessage *msg, void *data)
{
	MsnSlpMessage *slpmsg;

	slpmsg = data;

	msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);

	slpmsg->msgs = g_list_remove(slpmsg->msgs, msg);
	msn_message_unref(msg);
}
Esempio n. 6
0
static void
send_clientcaps(MsnSwitchBoard *swboard)
{
	MsnMessage *msg;

	msg = msn_message_new(MSN_MSG_CAPS);
	msn_message_set_content_type(msg, "text/x-clientcaps");
	msn_message_set_flag(msg, 'U');
	msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO));

	msn_switchboard_send_msg(swboard, msg, TRUE);

	msn_message_unref(msg);
}
Esempio n. 7
0
static void
ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
{
	MsnSwitchBoard *swboard;
	MsnMessage *msg;

	msg = cmd->trans->data;

	if (msg->ack_cb != NULL)
		msg->ack_cb(msg, msg->ack_data);

	swboard = cmdproc->data;
	swboard->ack_list = g_list_remove(swboard->ack_list, msg);
	msn_message_unref(msg);
}
Esempio n. 8
0
void
msn_slp_session_destroy(MsnSlpSession *session)
{
	g_return_if_fail(session != NULL);

	if (session->orig_body != NULL)
		g_free(session->orig_body);

	if (session->outgoing_msg != NULL)
		msn_message_unref(session->outgoing_msg);

	if (session->call_id != NULL)
		g_free(session->call_id);

	g_free(session);
}
Esempio n. 9
0
static void
process_queue(MsnSwitchBoard *swboard)
{
	MsnMessage *msg;

	g_return_if_fail(swboard != NULL);

	purple_debug_info("msn", "Processing queue\n");

	while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
	{
		purple_debug_info("msn", "Sending message\n");
		release_msg(swboard, msg);
		msn_message_unref(msg);
	}
}
Esempio n. 10
0
static void
msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
{
	MsnMessage *msg;

	msg = msn_message_new_from_cmd(cmdproc->session, cmd);

	msn_message_parse_payload(msg, payload, len,
					MSG_LINE_DEM,MSG_BODY_DEM);
	if (purple_debug_is_verbose())
		msn_message_show_readable(msg, "SB RECV", FALSE);

	g_free (msg->remote_user);
	msg->remote_user = g_strdup(cmd->params[0]);

	msn_cmdproc_process_msg(cmdproc, msg);

	msn_message_unref(msg);
}
Esempio n. 11
0
/* We have received the message ack */
static void
msg_ack(MsnMessage *msg, void *data)
{
	MsnSlpMessage *slpmsg;
	long long real_size;

	slpmsg = data;

	real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size;

	slpmsg->offset += msg->msnslp_header.length;

	slpmsg->msgs = g_list_remove(slpmsg->msgs, msg);

	if (slpmsg->offset < real_size)
	{
		if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
		{
			slpmsg->slpcall->xfer_msg = slpmsg;
			msn_message_ref(msg);
			purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
		}
		else
			msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
	}
	else
	{
		/* The whole message has been sent */
		if (slpmsg->flags == 0x20 ||
		    slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030)
		{
			if (slpmsg->slpcall != NULL)
			{
				if (slpmsg->slpcall->cb)
					slpmsg->slpcall->cb(slpmsg->slpcall,
						NULL, 0);
			}
		}
	}

	msn_message_unref(msg);
}
Esempio n. 12
0
void
msn_transaction_destroy(MsnTransaction *trans)
{
	g_return_if_fail(trans != NULL);

	g_free(trans->command);
	g_free(trans->params);
	g_free(trans->payload);

	if (trans->data_free)
		trans->data_free(trans->data);

#if 0
	if (trans->pendent_cmd != NULL)
		msn_message_unref(trans->pendent_msg);
#endif

#if 0
	MsnTransaction *elem;
	if (trans->queue != NULL)
	{
		while ((elem = g_queue_pop_head(trans->queue)) != NULL)
			msn_transaction_destroy(elem);

		g_queue_free(trans->queue);
	}
#endif

	if (trans->callbacks != NULL && trans->has_custom_callbacks)
		g_hash_table_destroy(trans->callbacks);

	if (trans->timer)
		purple_timeout_remove(trans->timer);

	g_free(trans);
}
Esempio n. 13
0
void
msn_switchboard_destroy(MsnSwitchBoard *swboard)
{
	MsnSession *session;
	MsnMessage *msg;
	GList *l;

	if (purple_debug_is_verbose())
		purple_debug_info("msn", "switchboard destroy: swboard(%p)\n", swboard);

	g_return_if_fail(swboard != NULL);

	if (swboard->destroying)
		return;

	swboard->destroying = TRUE;

	if (swboard->reconn_timeout_h > 0)
		purple_timeout_remove(swboard->reconn_timeout_h);

	/* If it linked us is because its looking for trouble */
	while (swboard->slplinks != NULL)
		msn_slplink_destroy(swboard->slplinks->data);

	/* Destroy the message queue */
	while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
	{
		if (swboard->error != MSN_SB_ERROR_NONE)
		{
			/* The messages could not be sent due to a switchboard error */
			msg_error_helper(swboard->cmdproc, msg,
							 MSN_MSG_ERROR_SB);
		}
		msn_message_unref(msg);
	}

	g_queue_free(swboard->msg_queue);

	/* msg_error_helper will both remove the msg from ack_list and
	   unref it, so we don't need to do either here */
	while ((l = swboard->ack_list) != NULL)
		msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB);

	g_free(swboard->im_user);
	g_free(swboard->auth_key);
	g_free(swboard->session_id);

	for (; swboard->users; swboard->users = g_list_delete_link(swboard->users, swboard->users))
		g_free(swboard->users->data);

	session = swboard->session;
	session->switches = g_list_remove(session->switches, swboard);

	for (l = session->slplinks; l; l = l->next) {
		MsnSlpLink *slplink = l->data;
		if (slplink->swboard == swboard) slplink->swboard = NULL;
	}

#if 0
	/* This should never happen or we are in trouble. */
	if (swboard->servconn != NULL)
		msn_servconn_destroy(swboard->servconn);
#endif

	swboard->cmdproc->data = NULL;

	msn_servconn_set_disconnect_cb(swboard->servconn, NULL);

	msn_servconn_destroy(swboard->servconn);

	g_free(swboard);
}
Esempio n. 14
0
static void
msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error)
{
	MsnSwitchBoard *swboard;

	g_return_if_fail(cmdproc != NULL);
	g_return_if_fail(msg     != NULL);

	if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL))
		msg->nak_cb(msg, msg->ack_data);

	swboard = cmdproc->data;

	/* This is not good, and should be fixed somewhere else. */
	g_return_if_fail(swboard != NULL);

	if (msg->type == MSN_MSG_TEXT)
	{
		const char *format, *str_reason;
		char *body_str, *body_enc, *pre, *post;

#if 0
		if (swboard->conv == NULL)
		{
			if (msg->ack_ref)
				msn_message_unref(msg);

			return;
		}
#endif

		if (error == MSN_MSG_ERROR_TIMEOUT)
		{
			str_reason = _("Message may have not been sent "
						   "because a timeout occurred:");
		}
		else if (error == MSN_MSG_ERROR_SB)
		{
			switch (swboard->error)
			{
				case MSN_SB_ERROR_OFFLINE:
					str_reason = _("Message could not be sent, "
								   "not allowed while invisible:");
					break;
				case MSN_SB_ERROR_USER_OFFLINE:
					str_reason = _("Message could not be sent "
								   "because the user is offline:");
					break;
				case MSN_SB_ERROR_CONNECTION:
					str_reason = _("Message could not be sent "
								   "because a connection error occurred:");
					break;
				case MSN_SB_ERROR_TOO_FAST:
					str_reason = _("Message could not be sent "
								   "because we are sending too quickly:");
					break;					
				default:
					str_reason = _("Message could not be sent "
								   "because an error with "
								   "the switchboard occurred:");
					break;
			}
		}
		else
		{
			str_reason = _("Message may have not been sent "
						   "because an unknown error occurred:");
		}

		body_str = msn_message_to_string(msg);
		body_enc = g_markup_escape_text(body_str, -1);
		g_free(body_str);

		format = msn_message_get_attr(msg, "X-MMS-IM-Format");
		msn_parse_format(format, &pre, &post);
		body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
								   body_enc ? body_enc : "", post ? post : "");
		g_free(body_enc);
		g_free(pre);
		g_free(post);

		msn_switchboard_report_user(swboard, GAIM_MESSAGE_ERROR,
									str_reason);
		msn_switchboard_report_user(swboard, GAIM_MESSAGE_RAW,
									body_str);

		g_free(body_str);
	}

	/* If a timeout occures we will want the msg around just in case we
	 * receive the ACK after the timeout. */
	if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT)
	{
		swboard->ack_list = g_list_remove(swboard->ack_list, msg);
		msn_message_unref(msg);
	}
}
Esempio n. 15
0
static void
msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error)
{
	MsnSwitchBoard *swboard;

	g_return_if_fail(cmdproc != NULL);
	g_return_if_fail(msg     != NULL);

	if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL))
		msg->nak_cb(msg, msg->ack_data);

	swboard = cmdproc->data;

	/* This is not good, and should be fixed somewhere else. */
	g_return_if_fail(swboard != NULL);

	if (msg->type == MSN_MSG_TEXT)
	{
		const char *format, *str_reason;
		char *body_str, *body_enc, *pre, *post;

#if 0
		if (swboard->conv == NULL)
		{
			if (msg->ack_ref)
				msn_message_unref(msg);

			return;
		}
#endif

		if (error == MSN_MSG_ERROR_TIMEOUT)
		{
			str_reason = _("Message may have not been sent "
						   "because a timeout occurred:");
		}
		else if (error == MSN_MSG_ERROR_SB)
		{
			MsnSession *session = swboard->session;

			if (!session->destroying && msg->retries &&	swboard->im_user &&
				(swboard->error == MSN_SB_ERROR_CONNECTION ||
					swboard->error == MSN_SB_ERROR_UNKNOWN)) {
				MsnSwitchBoard *new_sw = msn_session_find_swboard(session,
					swboard->im_user);

				if (new_sw == NULL || new_sw->reconn_timeout_h == 0) {
					new_sw = msn_switchboard_new(session);
					new_sw->im_user = g_strdup(swboard->im_user);
					new_sw->reconn_timeout_h = purple_timeout_add_seconds(3, msg_resend_cb, new_sw);
					new_sw->flag |= MSN_SB_FLAG_IM;
				}

				body_str = msn_message_to_string(msg);
				body_enc = g_markup_escape_text(body_str, -1);
				g_free(body_str);

				purple_debug_info("msn", "queuing unsent message to %s: %s\n",
					swboard->im_user, body_enc);
				g_free(body_enc);
				msn_send_im_message(session, msg);
				msg->retries--;

				return;
			}

			switch (swboard->error)
			{
				case MSN_SB_ERROR_OFFLINE:
					str_reason = _("Message could not be sent, "
								   "not allowed while invisible:");
					break;
				case MSN_SB_ERROR_USER_OFFLINE:
					str_reason = _("Message could not be sent "
								   "because the user is offline:");
					break;
				case MSN_SB_ERROR_CONNECTION:
					str_reason = _("Message could not be sent "
								   "because a connection error occurred:");
					break;
				case MSN_SB_ERROR_TOO_FAST:
					str_reason = _("Message could not be sent "
								   "because we are sending too quickly:");
					break;
				case MSN_SB_ERROR_AUTHFAILED:
					str_reason = _("Message could not be sent "
								   "because we were unable to establish a "
								   "session with the server. This is "
								   "likely a server problem, try again in "
								   "a few minutes:");
					break;
				default:
					str_reason = _("Message could not be sent "
								   "because an error with "
								   "the switchboard occurred:");
					break;
			}
		}
		else
		{
			str_reason = _("Message may have not been sent "
						   "because an unknown error occurred:");
		}

		body_str = msn_message_to_string(msg);
		body_enc = g_markup_escape_text(body_str, -1);
		g_free(body_str);

		format = msn_message_get_attr(msg, "X-MMS-IM-Format");
		msn_parse_format(format, &pre, &post);
		body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
								   body_enc ? body_enc : "", post ? post : "");
		g_free(body_enc);
		g_free(pre);
		g_free(post);

		msn_switchboard_report_user(swboard, PURPLE_MESSAGE_ERROR,
									str_reason);
		msn_switchboard_report_user(swboard, PURPLE_MESSAGE_RAW,
									body_str);

		g_free(body_str);
	}

	/* If a timeout occures we will want the msg around just in case we
	 * receive the ACK after the timeout. */
	if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT)
	{
		swboard->ack_list = g_list_remove(swboard->ack_list, msg);
		msn_message_unref(msg);
	}
}
Esempio n. 16
0
/*Post the Offline Instant Message to User Conversation*/
static void
msn_oim_report_to_user(MsnOimRecvData *rdata, const char *msg_str)
{
    MsnMessage *message;
    const char *date;
    const char *from;
    const char *boundary;
    char *decode_msg = NULL, *clean_msg = NULL;
    gsize body_len;
    char **tokens;
    char *passport = NULL;
    time_t stamp;
    const char *charset = NULL;

    message = msn_message_new(MSN_MSG_UNKNOWN);

    msn_message_parse_payload(message, msg_str, strlen(msg_str),
                              MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
    purple_debug_info("msn", "oim body:{%s}\n", message->body);

    boundary = msn_message_get_header_value(message, "boundary");

    if (boundary != NULL) {
        char *bounds;
        char **part;

        bounds = g_strdup_printf("--%s" MSG_OIM_LINE_DEM, boundary);
        tokens = g_strsplit(message->body, bounds, 0);

        /* tokens+1 to skip the "This is a multipart message..." text */
        for (part = tokens+1; *part != NULL; part++) {
            MsnMessage *multipart;
            const char *type;
            multipart = msn_message_new(MSN_MSG_UNKNOWN);
            msn_message_parse_payload(multipart, *part, strlen(*part),
                                      MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);

            type = msn_message_get_content_type(multipart);
            if (type && !strcmp(type, "text/plain")) {
                decode_msg = (char *)purple_base64_decode(multipart->body, &body_len);
                charset = msn_message_get_charset(multipart);

                msn_message_unref(multipart);
                break;
            }
            msn_message_unref(multipart);
        }

        g_strfreev(tokens);
        g_free(bounds);

        if (decode_msg == NULL) {
            purple_debug_error("msn", "Couldn't find text/plain OIM message.\n");
            msn_message_unref(message);
            return;
        }
    } else {
        decode_msg = (char *)purple_base64_decode(message->body, &body_len);
        charset = msn_message_get_charset(message);
    }

    if (charset && !((g_ascii_strncasecmp(charset, "UTF-8", 5) == 0) || (g_ascii_strncasecmp(charset, "UTF8", 4) == 0))) {
        clean_msg = g_convert(decode_msg, body_len, "UTF-8", charset, NULL, NULL, NULL);

        if (!clean_msg) {
            char *clean = purple_utf8_salvage(decode_msg);

            purple_debug_error("msn", "Failed to convert charset from %s to UTF-8 for OIM message: %s\n", charset, clean);

            clean_msg = g_strdup_printf(_("%s (There was an error receiving this message. "
                                          "Converting the encoding from %s to UTF-8 failed.)"),
                                        clean, charset);
            g_free(clean);
        }

        g_free(decode_msg);

    } else if (!g_utf8_validate(decode_msg, body_len, NULL)) {
        char *clean = purple_utf8_salvage(decode_msg);

        purple_debug_error("msn", "Received an OIM message that is not UTF-8,"
                           " and no encoding specified: %s\n", clean);

        if (charset) {
            clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
                                          " The charset was %s, but it was not valid UTF-8.)"),
                                        clean, charset);
        } else {
            clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
                                          " The charset was missing, but it was not valid UTF-8.)"),
                                        clean);
        }

        g_free(clean);
        g_free(decode_msg);

    } else {
        clean_msg = decode_msg;
    }

    from = msn_message_get_header_value(message, "X-OIM-originatingSource");

    /* Match number to user's mobile number, FROM is a phone number
       if the other side pages you using your phone number */
    if (from && !strncmp(from, "tel:+", 5)) {
        MsnUser *user =	msn_userlist_find_user_with_mobile_phone(
                            rdata->oim->session->userlist, from + 4);

        if (user && user->passport)
            passport = g_strdup(user->passport);
    }

    if (passport == NULL) {
        char *start, *end;

        from = msn_message_get_header_value(message, "From");

        tokens = g_strsplit(from, " ", 2);
        if (tokens[1] != NULL)
            from = (const char *)tokens[1];

        start = strchr(from, '<');
        if (start != NULL) {
            start++;
            end = strchr(from, '>');
            if (end != NULL)
                passport = g_strndup(start, end - start);
        }
        if (passport == NULL)
            passport = g_strdup(_("Unknown"));

        g_strfreev(tokens);
    }

    date = msn_message_get_header_value(message, "Date");
    stamp = msn_oim_parse_timestamp(date);
    purple_debug_info("msn", "oim Date:{%s},passport{%s}\n",
                      date, passport);

    purple_serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, clean_msg, 0,
                       stamp);

    /*Now get the oim message ID from the oim_list.
     * and append to read list to prepare for deleting the Offline Message when sign out
     */
    msn_oim_post_delete_msg(rdata);

    g_free(passport);
    g_free(clean_msg);
    msn_message_unref(message);
}
Esempio n. 17
0
void
msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
{
	GHashTable *body;
	const gchar *command;
	const gchar *cookie;
	gboolean accepted = FALSE;

	g_return_if_fail(cmdproc != NULL);
	g_return_if_fail(msg != NULL);

	body = msn_message_get_hashtable_from_body(msg);

	if (body == NULL) {
		purple_debug_warning("msn",
				"Unable to parse invite msg body.\n");
		return;
	}

	/*
	 * GUID is NOT always present but Invitation-Command and Invitation-Cookie
	 * are mandatory.
	 */
	command = g_hash_table_lookup(body, "Invitation-Command");
	cookie = g_hash_table_lookup(body, "Invitation-Cookie");

	if (command == NULL || cookie == NULL) {
		purple_debug_warning("msn",
			"Invalid invitation message: either Invitation-Command "
			"or Invitation-Cookie is missing or invalid.\n"
		);
		return;

	} else if (!strcmp(command, "INVITE")) {
		const gchar	*guid = g_hash_table_lookup(body, "Application-GUID");

		if (guid == NULL) {
			purple_debug_warning("msn",
			                     "Invite msg missing Application-GUID.\n");

			accepted = TRUE;

		} else if (!strcmp(guid, MSN_FT_GUID)) {

		} else if (!strcmp(guid, "{02D3C01F-BF30-4825-A83A-DE7AF41648AA}")) {
			purple_debug_info("msn", "Computer call\n");

			if (cmdproc->session) {
				PurpleIMConversation *im = NULL;
				gchar *from = msg->remote_user;
				gchar *buf = NULL;

				if (from)
					im = purple_conversations_find_im_with_account(
							from, cmdproc->session->account);
				if (im)
					buf = g_strdup_printf(
							_("%s sent you a voice chat "
							"invite, which is not yet "
							"supported."), from);
				if (buf) {
					purple_conversation_write(PURPLE_CONVERSATION(im), NULL, buf,
							PURPLE_MESSAGE_SYSTEM |
							PURPLE_MESSAGE_NOTIFY,
							time(NULL));
					g_free(buf);
				}
			}
		} else {
			const gchar *application = g_hash_table_lookup(body, "Application-Name");
			purple_debug_warning("msn", "Unhandled invite msg with GUID %s: %s.\n",
			                     guid, application ? application : "(null)");
		}

		if (!accepted) {
			MsnSwitchBoard *swboard = cmdproc->data;
			char *text;
			MsnMessage *cancel;

			cancel = msn_message_new(MSN_MSG_TEXT);
			msn_message_set_content_type(cancel, "text/x-msmsgsinvite");
			msn_message_set_charset(cancel, "UTF-8");
			msn_message_set_flag(cancel, 'U');

			text = g_strdup_printf("Invitation-Command: CANCEL\r\n"
			                       "Invitation-Cookie: %s\r\n"
			                       "Cancel-Code: REJECT_NOT_INSTALLED\r\n",
			                       cookie);
			msn_message_set_bin_data(cancel, text, strlen(text));
			g_free(text);

			msn_switchboard_send_msg(swboard, cancel, TRUE);
			msn_message_unref(cancel);
		}

	} else if (!strcmp(command, "CANCEL")) {
		const gchar *code = g_hash_table_lookup(body, "Cancel-Code");
		purple_debug_info("msn", "MSMSGS invitation cancelled: %s.\n",
		                  code ? code : "no reason given");

	} else {
		/*
		 * Some other already established invitation session.
		 * Can be retrieved by Invitation-Cookie.
		 */
	}

	g_hash_table_destroy(body);
}