/* Only called from chats. Handwritten messages for IMs come as a SLP message */ void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { const char *body; size_t body_len; body = msn_message_get_bin_data(msg, &body_len); msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body); }
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); }
char * msn_message_to_string(MsnMessage *msg) { size_t body_len; const char *body; g_return_val_if_fail(msg != NULL, NULL); g_return_val_if_fail(msg->type == MSN_MSG_TEXT, NULL); body = msn_message_get_bin_data(msg, &body_len); return g_strndup(body, body_len); }
void msn_slp_session_send_msg(MsnSlpSession *slpsession, MsnMessage *msg) { g_return_if_fail(slpsession != NULL); g_return_if_fail(msg != NULL); g_return_if_fail(msg->msnslp_message); g_return_if_fail(slpsession->outgoing_msg == NULL); msg->msnslp_header.session_id = slpsession->session_id; slpsession->outgoing_msg = msn_message_ref(msg); if (slpsession->base_id == 0) { slpsession->base_id = rand() % 0x0FFFFFF0 + 4; slpsession->prev_msg_id = slpsession->base_id; } else if (slpsession->offset == 0) slpsession->prev_msg_id = ++slpsession->base_id; msg->msnslp_header.id = slpsession->prev_msg_id; // msg->msnslp_header.ack_session_id = rand() % 0xFFFFFF00; msg->msnslp_header.ack_session_id = 0x1407C7DE; msn_message_set_charset(msg, NULL); if (msg->msnslp_header.session_id != 0) msg->msnslp_footer.app_id = 1; if (msg->bin_content) { const void *temp; temp = msn_message_get_bin_data(msg, &slpsession->orig_len); slpsession->orig_body = g_memdup(temp, slpsession->orig_len); } else { slpsession->orig_body = g_strdup(msn_message_get_body(msg)); slpsession->orig_len = strlen(slpsession->orig_body); } msg->msnslp_header.total_size_1 = slpsession->orig_len; send_msg_part(slpsession, msg); }
char * msn_message_gen_slp_body(MsnMessage *msg, size_t *ret_size) { MsnSlpHeader header; char *tmp, *base; const void *body; size_t len, body_len; g_return_val_if_fail(msg != NULL, NULL); len = MSN_BUF_LEN; base = tmp = g_malloc(len + 1); body = msn_message_get_bin_data(msg, &body_len); header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id); header.id = GUINT32_TO_LE(msg->msnslp_header.id); header.offset = GUINT64_TO_LE(msg->msnslp_header.offset); header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size); header.length = GUINT32_TO_LE(msg->msnslp_header.length); header.flags = GUINT32_TO_LE(msg->msnslp_header.flags); header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id); header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id); header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size); memcpy(tmp, &header, 48); tmp += 48; if (body != NULL) { memcpy(tmp, body, body_len); tmp += body_len; } if (ret_size != NULL) *ret_size = tmp - base; return base; }
GHashTable * msn_message_get_hashtable_from_body(const MsnMessage *msg) { GHashTable *table; size_t body_len; const char *body; char **elems, **cur, **tokens, *body_str; g_return_val_if_fail(msg != NULL, NULL); table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); body = msn_message_get_bin_data(msg, &body_len); g_return_val_if_fail(body != NULL, NULL); body_str = g_strndup(body, body_len); elems = g_strsplit(body_str, "\r\n", 0); g_free(body_str); for (cur = elems; *cur != NULL; cur++) { if (**cur == '\0') break; tokens = g_strsplit(*cur, ": ", 2); if (tokens[0] != NULL && tokens[1] != NULL) { g_hash_table_insert(table, tokens[0], tokens[1]); g_free(tokens); } else g_strfreev(tokens); } g_strfreev(elems); return table; }
void msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg) { MsnSlpMessage *slpmsg; const char *data; gsize offset; gsize len; #ifdef MSN_DEBUG_SLP msn_slpmsg_show(msg); #endif #ifdef MSN_DEBUG_SLP_FILES debug_msg_to_file(msg, FALSE); #endif if (msg->msnslp_header.total_size < msg->msnslp_header.length) { purple_debug_error("msn", "This can't be good\n"); g_return_if_reached(); } slpmsg = NULL; data = msn_message_get_bin_data(msg, &len); /* OVERHEAD! if (msg->msnslp_header.length < msg->msnslp_header.total_size) */ offset = msg->msnslp_header.offset; if (offset == 0) { slpmsg = msn_slpmsg_new(slplink); slpmsg->id = msg->msnslp_header.id; slpmsg->session_id = msg->msnslp_header.session_id; slpmsg->size = msg->msnslp_header.total_size; slpmsg->flags = msg->msnslp_header.flags; if (slpmsg->session_id) { if (slpmsg->slpcall == NULL) slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); if (slpmsg->slpcall != NULL) { if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { PurpleXfer *xfer; xfer = slpmsg->slpcall->xfer; if (xfer != NULL) { purple_xfer_ref(xfer); purple_xfer_start(xfer, 0, NULL, 0); if (xfer->data == NULL) { purple_xfer_unref(xfer); return; } else { purple_xfer_unref(xfer); slpmsg->fp = xfer->dest_fp; xfer->dest_fp = NULL; /* Disable double fclose() */ } } } } } if (!slpmsg->fp && slpmsg->size) { slpmsg->buffer = g_try_malloc(slpmsg->size); if (slpmsg->buffer == NULL) { purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n"); return; } } } else { slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id); } if (slpmsg == NULL) { /* Probably the transfer was canceled */ purple_debug_error("msn", "Couldn't find slpmsg\n"); return; } if (slpmsg->fp) { /* fseek(slpmsg->fp, offset, SEEK_SET); */ len = fwrite(data, 1, len, slpmsg->fp); } else if (slpmsg->size) { if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size) { purple_debug_error("msn", "Oversized slpmsg\n"); g_return_if_reached(); } else memcpy(slpmsg->buffer + offset, data, len); } if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) && (slpmsg->slpcall != NULL)) { slpmsg->slpcall->progress = TRUE; if (slpmsg->slpcall->progress_cb != NULL) { slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, len, offset); } } #if 0 if (slpmsg->buffer == NULL) return; #endif if (msg->msnslp_header.offset + msg->msnslp_header.length >= msg->msnslp_header.total_size) { /* All the pieces of the slpmsg have been received */ MsnSlpCall *slpcall; slpcall = msn_slp_process_msg(slplink, slpmsg); if (slpmsg->flags == 0x100) { MsnDirectConn *directconn; directconn = slplink->directconn; if (!directconn->acked) msn_directconn_send_handshake(directconn); } else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { /* Release all the messages and send the ACK */ msn_slplink_send_ack(slplink, msg); msn_slplink_unleash(slplink); } msn_slpmsg_destroy(slpmsg); if (slpcall != NULL && slpcall->wasted) msn_slp_call_destroy(slpcall); } }
void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnSession *session; MsnSlpLink *slplink; MsnSwitchBoard *swboard; MsnObject *obj; char **tokens; char *smile, *body_str; const char *body, *who, *sha1; guint tok; size_t body_len; PurpleConversation *conv; session = cmdproc->servconn->session; if (!purple_account_get_bool(session->account, "custom_smileys", TRUE)) return; swboard = cmdproc->data; conv = swboard->conv; body = msn_message_get_bin_data(msg, &body_len); if (!body || !body_len) return; body_str = g_strndup(body, body_len); /* MSN Messenger 7 may send more than one MSNObject in a single message... * Maybe 10 tokens is a reasonable max value. */ tokens = g_strsplit(body_str, "\t", 10); g_free(body_str); for (tok = 0; tok < 9; tok += 2) { if (tokens[tok] == NULL || tokens[tok + 1] == NULL) { break; } smile = tokens[tok]; obj = msn_object_new_from_string(purple_url_decode(tokens[tok + 1])); if (obj == NULL) break; who = msn_object_get_creator(obj); sha1 = msn_object_get_sha1(obj); slplink = msn_session_get_slplink(session, who); if (slplink->swboard != swboard) { if (slplink->swboard != NULL) /* * Apparently we're using a different switchboard now or * something? I don't know if this is normal, but it * definitely happens. So make sure the old switchboard * doesn't still have a reference to us. */ slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); slplink->swboard = swboard; slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); } /* If the conversation doesn't exist then this is a custom smiley * used in the first message in a MSN conversation: we need to create * the conversation now, otherwise the custom smiley won't be shown. * This happens because every GtkIMHtml has its own smiley tree: if * the conversation doesn't exist then we cannot associate the new * smiley with its GtkIMHtml widget. */ if (!conv) { conv = PURPLE_CONVERSATION(purple_im_conversation_new(session->account, who)); } if (purple_conversation_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) { msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj); } msn_object_destroy(obj, FALSE); obj = NULL; who = NULL; sha1 = NULL; } g_strfreev(tokens); }
/************************************************************************** * 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); }
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); }
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->attr_list; l; l = l->next) { char *key; const char *value; key = l->data; value = msn_message_get_attr(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 (msg->msnslp_message) { g_string_append_printf(str, "Session ID: %u\r\n", msg->msnslp_header.session_id); g_string_append_printf(str, "ID: %u\r\n", msg->msnslp_header.id); g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", msg->msnslp_header.offset); g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", msg->msnslp_header.total_size); g_string_append_printf(str, "Length: %u\r\n", msg->msnslp_header.length); g_string_append_printf(str, "Flags: 0x%x\r\n", msg->msnslp_header.flags); g_string_append_printf(str, "ACK ID: %u\r\n", msg->msnslp_header.ack_id); g_string_append_printf(str, "SUB ID: %u\r\n", msg->msnslp_header.ack_sub_id); g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", msg->msnslp_header.ack_size); #ifdef MSN_DEBUG_SLP_VERBOSE if (body != NULL) { if (text_body) { g_string_append_len(str, body, body_len); if (body[body_len - 1] == '\0') { str->len--; g_string_append(str, " 0x00"); } g_string_append(str, "\r\n"); } else { int i; for (i = 0; i < msg->body_len; i++) { g_string_append_printf(str, "%.2hhX ", body[i]); if ((i % 16) == 15) g_string_append(str, "\r\n"); } g_string_append(str, "\r\n"); } } #endif g_string_append_printf(str, "Footer: %u\r\n", msg->msnslp_footer.value); } else { if (body != NULL) { g_string_append_len(str, body, body_len); g_string_append(str, "\r\n"); } } purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str); g_string_free(str, TRUE); }
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->attr_list; l != NULL; l = l->next) { const char *key; const char *value; key = l->data; value = msn_message_get_attr(msg, key); g_snprintf(n, end - n, "%s: %s\r\n", key, value); n += strlen(n); } n += g_strlcpy(n, "\r\n", end - n); body = msn_message_get_bin_data(msg, &body_len); if (msg->msnslp_message) { MsnSlpHeader header; MsnSlpFooter footer; header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id); header.id = GUINT32_TO_LE(msg->msnslp_header.id); header.offset = GUINT64_TO_LE(msg->msnslp_header.offset); header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size); header.length = GUINT32_TO_LE(msg->msnslp_header.length); header.flags = GUINT32_TO_LE(msg->msnslp_header.flags); header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id); header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id); header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size); memcpy(n, &header, 48); n += 48; if (body != NULL) { memcpy(n, body, body_len); n += body_len; } footer.value = GUINT32_TO_BE(msg->msnslp_footer.value); memcpy(n, &footer, 4); n += 4; } else { if (body != NULL) { memcpy(n, body, body_len); n += body_len; } } if (ret_size != NULL) { *ret_size = n - base; if (*ret_size > 1664) *ret_size = 1664; } return base; }
/************************************************************************** * Message Handlers **************************************************************************/ static void plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { GaimConnection *gc; MsnSwitchBoard *swboard; const char *body; char *body_str; char *body_enc; char *body_final; size_t body_len; const char *passport; const char *value; gc = cmdproc->session->account->gc; swboard = cmdproc->data; body = msn_message_get_bin_data(msg, &body_len); body_str = g_strndup(body, body_len); body_enc = g_markup_escape_text(body_str, -1); g_free(body_str); passport = msg->remote_user; if (!strcmp(passport, "*****@*****.**") && strstr(body, "immediate security update")) { return; } #if 0 if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL) { gaim_debug_misc("msn", "User-Agent = '%s'\n", value); } #endif if ((value = msn_message_get_attr(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; } swboard->flag |= MSN_SB_FLAG_IM; if (swboard->current_users > 1 || ((swboard->conv != NULL) && gaim_conversation_get_type(swboard->conv) == GAIM_CONV_TYPE_CHAT)) { /* 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) gaim_debug_misc("msn", "plain_msg: current_users(%d)\n", swboard->current_users); serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final, time(NULL)); if (swboard->conv == NULL) { swboard->conv = gaim_find_chat(gc, swboard->chat_id); swboard->flag |= MSN_SB_FLAG_IM; } } else { serv_got_im(gc, passport, body_final, 0, time(NULL)); if (swboard->conv == NULL) { swboard->conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, passport, gaim_connection_get_account(gc)); swboard->flag |= MSN_SB_FLAG_IM; } } g_free(body_final); }
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; }
void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnSession *session; MsnSlpLink *slplink; MsnObject *obj; char **tokens; char *smile, *body_str; const char *body, *who, *sha1; guint tok; size_t body_len; PurpleConversation *conv; session = cmdproc->session; if (!purple_account_get_bool_without_default_value(session->account, "custom_smileys")) return; body = msn_message_get_bin_data(msg, &body_len); body_str = g_strndup(body, body_len); /* MSN Messenger 7 may send more than one MSNObject in a single message... * Maybe 10 tokens is a reasonable max value. */ tokens = g_strsplit(body_str, "\t", 10); g_free(body_str); for (tok = 0; tok < 9; tok += 2) { if (tokens[tok] == NULL || tokens[tok + 1] == NULL) { break; } smile = tokens[tok]; { gchar *tmp; tmp = pecan_url_decode (tokens[tok + 1]); obj = msn_object_new_from_string(tmp); g_free(tmp); } if (obj == NULL) break; who = msn_object_get_creator(obj); sha1 = msn_object_get_sha1(obj); slplink = msn_session_get_slplink(session, who); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, session->account); /* If the conversation doesn't exist then this is a custom smiley * used in the first message in a MSN conversation: we need to create * the conversation now, otherwise the custom smiley won't be shown. * This happens because every GtkIMHtml has its own smiley tree: if * the conversation doesn't exist then we cannot associate the new * smiley with its GtkIMHtml widget. */ if (!conv) { //conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who); } if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) { msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj); } msn_object_destroy(obj); obj = NULL; who = NULL; sha1 = NULL; } g_strfreev(tokens); }