예제 #1
0
파일: msg.c 프로젝트: Distrotech/pidgin
void
msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
{
	PurpleConnection *gc;
	char *passport;

  	gc = purple_account_get_connection(cmdproc->session->account);
	passport = msg->remote_user;

	if (msn_message_get_header_value(msg, "TypingUser") == NULL)
		return;

	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
		MsnSwitchBoard *swboard = cmdproc->data;

		if (swboard->current_users == 1)
		{
			purple_serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
							PURPLE_IM_TYPING);
		}

	} else {
		purple_serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
						PURPLE_IM_TYPING);
	}
}
예제 #2
0
파일: msg.c 프로젝트: Distrotech/pidgin
char *
msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
{
	GString *payload;
	GList *l;
	size_t body_len;
	const void *body;

	g_return_val_if_fail(msg != NULL, NULL);

	/* 8192 is a reasonable guess at a large enough buffer to avoid realloc */
	payload = g_string_sized_new(8192);

	/* Standard header */
	if (msg->charset == NULL) {
		g_string_append_printf(payload,
				"MIME-Version: 1.0\r\n"
				"Content-Type: %s\r\n",
				msg->content_type);
	} else {
		g_string_append_printf(payload,
				"MIME-Version: 1.0\r\n"
				"Content-Type: %s; charset=%s\r\n",
				msg->content_type, msg->charset);
	}

	/* Headers */
	for (l = msg->header_list; l != NULL; l = l->next)
	{
		const char *key;
		const char *value;

		key = l->data;
		value = msn_message_get_header_value(msg, key);

		g_string_append_printf(payload, "%s: %s\r\n", key, value);
	}

	/* End of headers */
	g_string_append(payload, "\r\n");

	/* Body */
	body = msn_message_get_bin_data(msg, &body_len);
	if (body != NULL) {
		g_string_append_len(payload, body, body_len);
	}

	if (ret_size != NULL) {
		/* Use MIN to truncate the payload to 1664 bytes? Why do we do this?
		   It seems like it will lead to brokenness. */
		*ret_size = MIN(payload->len, 1664);
	}

	return g_string_free(payload, FALSE);
}
예제 #3
0
파일: msg.c 프로젝트: Distrotech/pidgin
void
msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
{
	const char *temp;
	char *new_name;

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

	temp = msn_message_get_header_value(msg, name);

	if (value == NULL)
	{
		if (temp != NULL)
		{
			GList *l;

			for (l = msg->header_list; l != NULL; l = l->next)
			{
				if (!g_ascii_strcasecmp(l->data, name))
				{
					msg->header_list = g_list_remove(msg->header_list, l->data);

					break;
				}
			}

			g_hash_table_remove(msg->header_table, name);
		}

		return;
	}

	new_name = g_strdup(name);

	g_hash_table_insert(msg->header_table, new_name, g_strdup(value));

	if (temp == NULL)
		msg->header_list = g_list_append(msg->header_list, new_name);
}
예제 #4
0
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_header_value(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);
	}
}
예제 #5
0
파일: msg.c 프로젝트: Distrotech/pidgin
/**************************************************************************
 * Message Handlers
 **************************************************************************/
void
msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
{
	PurpleConnection *gc;
	const char *body;
	char *body_enc;
	char *body_final;
	size_t body_len;
	const char *passport;
	const char *value;

	gc = purple_account_get_connection(cmdproc->session->account);

	body = msn_message_get_bin_data(msg, &body_len);
	body_enc = g_markup_escape_text(body, body_len);

	passport = msg->remote_user;

	if (!strcmp(passport, "*****@*****.**") &&
		strstr(body, "immediate security update"))
	{
		return;
	}

#if 0
	if ((value = msn_message_get_header_value(msg, "User-Agent")) != NULL)
	{
		purple_debug_misc("msn", "User-Agent = '%s'\n", value);
	}
#endif

	if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
	{
		char *pre, *post;

		msn_parse_format(value, &pre, &post);

		body_final = g_strdup_printf("%s%s%s", pre ? pre : "",
									 body_enc ? body_enc : "", post ? post : "");

		g_free(pre);
		g_free(post);
		g_free(body_enc);
	}
	else
	{
		body_final = body_enc;
	}

	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
		MsnSwitchBoard *swboard = cmdproc->data;

		swboard->flag |= MSN_SB_FLAG_IM;

		if (swboard->current_users > 1 ||
			((swboard->conv != NULL) &&
			 PURPLE_IS_CHAT_CONVERSATION(swboard->conv)))
		{
			/* If current_users is always ok as it should then there is no need to
			 * check if this is a chat. */
			if (swboard->current_users <= 1)
				purple_debug_misc("msn", "plain_msg: current_users(%d)\n",
								swboard->current_users);

			purple_serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final,
							 time(NULL));
			if (swboard->conv == NULL)
			{
				swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_chat(gc, swboard->chat_id));
				swboard->flag |= MSN_SB_FLAG_IM;
			}
		}
		else if (!g_str_equal(passport, purple_account_get_username(purple_connection_get_account(gc))))
		{
			/* Don't im ourselves ... */
			purple_serv_got_im(gc, passport, body_final, 0, time(NULL));
			if (swboard->conv == NULL)
			{
				swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(
										passport, purple_connection_get_account(gc)));
				swboard->flag |= MSN_SB_FLAG_IM;
			}
		}

	} else {
		purple_serv_got_im(gc, passport, body_final, 0, time(NULL));
	}

	g_free(body_final);
}
예제 #6
0
파일: msg.c 프로젝트: Distrotech/pidgin
void
msn_message_show_readable(MsnMessage *msg, const char *info,
						  gboolean text_body)
{
	GString *str;
	size_t body_len;
	const char *body;
	GList *l;

	g_return_if_fail(msg != NULL);

	str = g_string_new(NULL);

	/* Standard header. */
	if (msg->charset == NULL)
	{
		g_string_append_printf(str,
				   "MIME-Version: 1.0\r\n"
				   "Content-Type: %s\r\n",
				   msg->content_type);
	}
	else
	{
		g_string_append_printf(str,
				   "MIME-Version: 1.0\r\n"
				   "Content-Type: %s; charset=%s\r\n",
				   msg->content_type, msg->charset);
	}

	for (l = msg->header_list; l; l = l->next)
	{
		char *key;
		const char *value;

		key = l->data;
		value = msn_message_get_header_value(msg, key);

		g_string_append_printf(str, "%s: %s\r\n", key, value);
	}

	g_string_append(str, "\r\n");

	body = msn_message_get_bin_data(msg, &body_len);

	if (body != NULL)
	{
		if (msg->type == MSN_MSG_TEXT)
		{
			g_string_append_len(str, body, body_len);
			g_string_append(str, "\r\n");
		}
		else
		{
			size_t i;
			for (i = 0; i < body_len; i++, body++)
			{
				g_string_append_printf(str, "%02x ", (unsigned char)*body);
				if (i % 16 == 0 && i != 0)
					g_string_append_c(str, '\n');
			}
			g_string_append_c(str, '\n');
		}
	}

	purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);

	g_string_free(str, TRUE);
}
예제 #7
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);
}
예제 #8
0
파일: msg.c 프로젝트: ravikwow/libpurple
char *
msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
{
    GList *l;
    char *n, *base, *end;
    int len;
    size_t body_len = 0;
    const void *body;

    g_return_val_if_fail(msg != NULL, NULL);

    len = MSN_BUF_LEN;

    base = n = end = g_malloc(len + 1);
    end += len;

    /* Standard header. */
    if (msg->charset == NULL)
    {
        g_snprintf(n, len,
                   "MIME-Version: 1.0\r\n"
                   "Content-Type: %s\r\n",
                   msg->content_type);
    }
    else
    {
        g_snprintf(n, len,
                   "MIME-Version: 1.0\r\n"
                   "Content-Type: %s; charset=%s\r\n",
                   msg->content_type, msg->charset);
    }

    n += strlen(n);

    for (l = msg->header_list; l != NULL; l = l->next)
    {
        const char *key;
        const char *value;

        key = l->data;
        value = msn_message_get_header_value(msg, key);

        g_snprintf(n, end - n, "%s: %s\r\n", key, value);
        n += strlen(n);
    }

    if ((end - n) > 2)
        n += g_strlcpy(n, "\r\n", end - n);

    body = msn_message_get_bin_data(msg, &body_len);

    if (body != NULL && (end - n) > body_len)
    {
        memcpy(n, body, body_len);
        n += body_len;
        *n = '\0';
    }

    if (ret_size != NULL)
    {
        *ret_size = n - base;

        if (*ret_size > 1664)
            *ret_size = 1664;
    }

    return base;
}