pidgin/pidgin

Fix coverity 1255966 and 1255964

2016-12-10, Gary Kramlich
20f33f108f99
Fix coverity 1255966 and 1255964
/**
* @file oim.c
* get and send MSN offline Instant Message via SOAP request
* Author
* MaYuan<mayuan2006@gmail.com>
* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "internal.h"
#include "debug.h"
#include "soap.h"
#include "oim.h"
#include "msnutils.h"
typedef struct _MsnOimSendReq {
char *from_member;
char *friendname;
char *to_member;
char *oim_msg;
} MsnOimSendReq;
typedef struct {
MsnOim *oim;
char *msg_id;
} MsnOimRecvData;
/*Local Function Prototype*/
static void msn_parse_oim_xml(MsnOim *oim, PurpleXmlNode *node);
static void msn_oim_free_send_req(MsnOimSendReq *req);
static void msn_oim_recv_data_free(MsnOimRecvData *data);
static void msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data);
/*new a OIM object*/
MsnOim *
msn_oim_new(MsnSession *session)
{
MsnOim *oim;
oim = g_new0(MsnOim, 1);
oim->session = session;
oim->oim_list = NULL;
oim->run_id = rand_guid();
oim->challenge = NULL;
oim->send_queue = g_queue_new();
oim->send_seq = 1;
return oim;
}
/*destroy the oim object*/
void
msn_oim_destroy(MsnOim *oim)
{
MsnOimSendReq *request;
purple_debug_info("msn", "destroy the OIM %p\n", oim);
g_free(oim->run_id);
g_free(oim->challenge);
while ((request = g_queue_pop_head(oim->send_queue)) != NULL)
msn_oim_free_send_req(request);
g_queue_free(oim->send_queue);
while (oim->oim_list != NULL)
msn_oim_recv_data_free((MsnOimRecvData *)oim->oim_list->data);
g_free(oim);
}
static MsnOimSendReq *
msn_oim_new_send_req(const char *from_member, const char*friendname,
const char* to_member, const char *msg)
{
MsnOimSendReq *request;
request = g_new0(MsnOimSendReq, 1);
request->from_member = g_strdup(from_member);
request->friendname = g_strdup(friendname);
request->to_member = g_strdup(to_member);
request->oim_msg = g_strdup(msg);
return request;
}
static void
msn_oim_free_send_req(MsnOimSendReq *req)
{
g_return_if_fail(req != NULL);
g_free(req->from_member);
g_free(req->friendname);
g_free(req->to_member);
g_free(req->oim_msg);
g_free(req);
}
static MsnOimRecvData *
msn_oim_recv_data_new(MsnOim *oim, char *msg_id)
{
MsnOimRecvData *data;
data = g_new0(MsnOimRecvData, 1);
data->oim = oim;
data->msg_id = msg_id;
oim->oim_list = g_list_append(oim->oim_list, data);
return data;
}
/* Probably only good for g_list_find_custom */
static gint
msn_recv_data_equal(MsnOimRecvData *a, const char *msg_id)
{
return strcmp(a->msg_id, msg_id);
}
static void
msn_oim_recv_data_free(MsnOimRecvData *data)
{
data->oim->oim_list = g_list_remove(data->oim->oim_list, data);
g_free(data->msg_id);
g_free(data);
}
/****************************************
* Manage OIM Tokens
****************************************/
typedef struct _MsnOimRequestData {
MsnOim *oim;
gboolean send;
const char *action;
const char *host;
const char *url;
PurpleXmlNode *body;
MsnSoapCallback cb;
gpointer cb_data;
} MsnOimRequestData;
static gboolean msn_oim_request_helper(MsnOimRequestData *data);
static void
msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
gpointer req_data)
{
MsnOimRequestData *data = (MsnOimRequestData *)req_data;
PurpleXmlNode *fault = NULL;
PurpleXmlNode *faultcode = NULL;
if (response != NULL)
fault = purple_xmlnode_get_child(msn_soap_message_get_xml(response), "Body/Fault");
if (fault && (faultcode = purple_xmlnode_get_child(fault, "faultcode"))) {
gchar *faultcode_str = purple_xmlnode_get_data(faultcode);
gboolean need_token_update = FALSE;
if (faultcode_str) {
if (g_str_equal(faultcode_str, "q0:BadContextToken") ||
g_str_equal(faultcode_str, "AuthenticationFailed") ||
g_str_equal(faultcode_str, "s:AuthenticationFailed"))
need_token_update = TRUE;
else if (g_str_equal(faultcode_str, "q0:AuthenticationFailed") &&
purple_xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL)
need_token_update = TRUE;
}
if (need_token_update) {
purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
msn_nexus_update_token(data->oim->session->nexus,
data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
(GSourceFunc)msn_oim_request_helper, data);
g_free(faultcode_str);
return;
}
g_free(faultcode_str);
}
if (data->cb)
data->cb(request, response, data->cb_data);
purple_xmlnode_free(data->body);
g_free(data);
}
static gboolean
msn_oim_request_helper(MsnOimRequestData *data)
{
MsnSession *session = data->oim->session;
if (data->send) {
/* The Sending of OIM's uses a different token for some reason. */
PurpleXmlNode *ticket;
ticket = purple_xmlnode_get_child(data->body, "Header/Ticket");
purple_xmlnode_set_attrib(ticket, "passport",
msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE));
}
else
{
PurpleXmlNode *passport;
PurpleXmlNode *xml_t;
PurpleXmlNode *xml_p;
GHashTable *token;
const char *msn_t;
const char *msn_p;
token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
g_return_val_if_fail(token != NULL, FALSE);
msn_t = g_hash_table_lookup(token, "t");
msn_p = g_hash_table_lookup(token, "p");
g_return_val_if_fail(msn_t != NULL, FALSE);
g_return_val_if_fail(msn_p != NULL, FALSE);
passport = purple_xmlnode_get_child(data->body, "Header/PassportCookie");
xml_t = purple_xmlnode_get_child(passport, "t");
xml_p = purple_xmlnode_get_child(passport, "p");
/* frees old token text, or the 'EMPTY' text if first time */
purple_xmlnode_free(xml_t->child);
purple_xmlnode_free(xml_p->child);
purple_xmlnode_insert_data(xml_t, msn_t, -1);
purple_xmlnode_insert_data(xml_p, msn_p, -1);
}
msn_soap_service_send_message(session->soap,
msn_soap_message_new(data->action, purple_xmlnode_copy(data->body)),
data->host, data->url, FALSE, msn_oim_request_cb, data);
return FALSE;
}
static void
msn_oim_make_request(MsnOim *oim, gboolean send, const char *action,
const char *host, const char *url, PurpleXmlNode *body, MsnSoapCallback cb,
gpointer cb_data)
{
MsnOimRequestData *data = g_new0(MsnOimRequestData, 1);
data->oim = oim;
data->send = send;
data->action = action;
data->host = host;
data->url = url;
data->body = body;
data->cb = cb;
data->cb_data = cb_data;
msn_oim_request_helper(data);
}
/****************************************
* OIM GetMetadata request
* **************************************/
static void
msn_oim_get_metadata_cb(MsnSoapMessage *request, MsnSoapMessage *response,
gpointer data)
{
MsnOim *oim = data;
if (response) {
msn_parse_oim_xml(oim,
purple_xmlnode_get_child(msn_soap_message_get_xml(response), "Body/GetMetadataResponse/MD"));
}
}
/* Post to get the OIM Metadata */
static void
msn_oim_get_metadata(MsnOim *oim)
{
msn_oim_make_request(oim, FALSE, MSN_OIM_GET_METADATA_ACTION,
MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL,
purple_xmlnode_from_str(MSN_OIM_GET_METADATA_TEMPLATE, -1),
msn_oim_get_metadata_cb, oim);
}
/****************************************
* OIM send SOAP request
* **************************************/
/*encode the message to OIM Message Format*/
static gchar *
msn_oim_msg_to_str(MsnOim *oim, const char *body)
{
GString *oim_body;
char *oim_base64;
char *c;
int len;
size_t base64_len;
purple_debug_info("msn", "Encoding OIM Message...\n");
len = strlen(body);
c = oim_base64 = purple_base64_encode((const guchar *)body, len);
base64_len = strlen(oim_base64);
purple_debug_info("msn", "Encoded base64 body:{%s}\n", oim_base64);
oim_body = g_string_new(NULL);
g_string_printf(oim_body, MSN_OIM_MSG_TEMPLATE,
oim->run_id, oim->send_seq);
#define OIM_LINE_LEN 76
while (base64_len > OIM_LINE_LEN) {
g_string_append_len(oim_body, c, OIM_LINE_LEN);
g_string_append_c(oim_body, '\n');
c += OIM_LINE_LEN;
base64_len -= OIM_LINE_LEN;
}
#undef OIM_LINE_LEN
g_string_append(oim_body, c);
g_free(oim_base64);
return g_string_free(oim_body, FALSE);
}
/*
* Process the send return SOAP string
* If got SOAP Fault,get the lock key,and resend it.
*/
static void
msn_oim_send_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
gpointer data)
{
MsnOim *oim = data;
MsnOimSendReq *msg = g_queue_pop_head(oim->send_queue);
g_return_if_fail(msg != NULL);
if (response == NULL) {
purple_debug_info("msn", "cannot send OIM: %s\n", msg->oim_msg);
} else {
PurpleXmlNode *faultNode = purple_xmlnode_get_child(msn_soap_message_get_xml(response), "Body/Fault");
if (faultNode == NULL) {
/*Send OK! return*/
purple_debug_info("msn", "sent OIM: %s\n", msg->oim_msg);
} else {
PurpleXmlNode *faultcode = purple_xmlnode_get_child(faultNode, "faultcode");
if (faultcode) {
char *faultcode_str = purple_xmlnode_get_data(faultcode);
if (faultcode_str && g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
PurpleXmlNode *challengeNode = purple_xmlnode_get_child(faultNode,
"detail/LockKeyChallenge");
char *challenge = NULL;
if (challengeNode == NULL || (challenge = purple_xmlnode_get_data(challengeNode)) == NULL) {
if (oim->challenge) {
g_free(oim->challenge);
oim->challenge = NULL;
purple_debug_info("msn", "Resending OIM: %s\n",
msg->oim_msg);
g_queue_push_head(oim->send_queue, msg);
msn_oim_send_msg(oim);
msg = NULL;
} else {
purple_debug_info("msn",
"Can't find lock key for OIM: %s\n",
msg->oim_msg);
}
} else {
char buf[33];
msn_handle_chl(challenge, buf);
g_free(oim->challenge);
oim->challenge = g_strndup(buf, sizeof(buf));
g_free(challenge);
purple_debug_info("msn", "Found lockkey:{%s}\n", oim->challenge);
/*repost the send*/
purple_debug_info("msn", "Resending OIM: %s\n", msg->oim_msg);
g_queue_push_head(oim->send_queue, msg);
msn_oim_send_msg(oim);
msg = NULL;
}
} else {
/* Report the error */
const char *str_reason = NULL;
if (faultcode_str) {
if (g_str_equal(faultcode_str, "q0:SystemUnavailable")) {
str_reason = _("Message was not sent because the system is "
"unavailable. This normally happens when the "
"user is blocked or does not exist.");
} else if (g_str_equal(faultcode_str, "q0:SenderThrottleLimitExceeded")) {
str_reason = _("Message was not sent because messages "
"are being sent too quickly.");
} else if (g_str_equal(faultcode_str, "q0:InvalidContent")) {
str_reason = _("Message was not sent because an unknown "
"encoding error occurred.");
}
}
if (str_reason == NULL) {
str_reason = _("Message was not sent because an unknown "
"error occurred.");
}
msn_session_report_user(oim->session, msg->to_member,
str_reason, PURPLE_MESSAGE_ERROR);
msn_session_report_user(oim->session, msg->to_member,
msg->oim_msg, PURPLE_MESSAGE_RAW);
}
g_free(faultcode_str);
}
}
}
if (msg)
msn_oim_free_send_req(msg);
}
void
msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
const char* friendname, const char *tomember,
const char * msg)
{
g_return_if_fail(oim != NULL);
g_queue_push_tail(oim->send_queue,
msn_oim_new_send_req(membername, friendname, tomember, msg));
}
/*post send single message request to oim server*/
void
msn_oim_send_msg(MsnOim *oim)
{
MsnOimSendReq *oim_request;
char *soap_body;
char *msg_body;
g_return_if_fail(oim != NULL);
oim_request = g_queue_peek_head(oim->send_queue);
g_return_if_fail(oim_request != NULL);
purple_debug_info("msn", "Sending OIM: %s\n", oim_request->oim_msg);
/* if we got the challenge lock key, we compute it
* else we go for the SOAP fault and resend it.
*/
if (oim->challenge == NULL){
purple_debug_info("msn", "No lock key challenge, waiting for SOAP Fault and Resend\n");
}
msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg);
soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE,
oim_request->from_member,
oim_request->friendname,
oim_request->to_member,
MSNP15_WLM_PRODUCT_ID,
oim->challenge ? oim->challenge : "",
oim->send_seq,
msg_body);
msn_oim_make_request(oim, TRUE, MSN_OIM_SEND_SOAP_ACTION, MSN_OIM_SEND_HOST,
MSN_OIM_SEND_URL, purple_xmlnode_from_str(soap_body, -1), msn_oim_send_read_cb,
oim);
/*increase the offline Sequence control*/
if (oim->challenge != NULL) {
oim->send_seq++;
}
g_free(msg_body);
g_free(soap_body);
}
/****************************************
* OIM delete SOAP request
* **************************************/
static void
msn_oim_delete_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
gpointer data)
{
MsnOimRecvData *rdata = data;
if (response && purple_xmlnode_get_child(msn_soap_message_get_xml(response), "Body/Fault") == NULL)
purple_debug_info("msn", "Delete OIM success\n");
else
purple_debug_info("msn", "Delete OIM failed\n");
msn_oim_recv_data_free(rdata);
}
/*Post to get the Offline Instant Message*/
static void
msn_oim_post_delete_msg(MsnOimRecvData *rdata)
{
MsnOim *oim = rdata->oim;
char *msgid = rdata->msg_id;
char *soap_body;
purple_debug_info("msn", "Delete single OIM Message {%s}\n",msgid);
soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, msgid);
msn_oim_make_request(oim, FALSE, MSN_OIM_DEL_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
MSN_OIM_RETRIEVE_URL, purple_xmlnode_from_str(soap_body, -1), msn_oim_delete_read_cb, rdata);
g_free(soap_body);
}
/****************************************
* OIM get SOAP request
* **************************************/
/* like purple_str_to_time, but different. The format of the timestamp
* is like this: 5 Sep 2007 21:42:12 -0700 */
static time_t
msn_oim_parse_timestamp(const char *timestamp)
{
char month_str[4], tz_str[6];
char *tz_ptr = tz_str;
static const char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
};
time_t tval = 0;
struct tm t;
memset(&t, 0, sizeof(t));
time(&tval);
localtime_r(&tval, &t);
if (sscanf(timestamp, "%02d %03s %04d %02d:%02d:%02d %05s",
&t.tm_mday, month_str, &t.tm_year,
&t.tm_hour, &t.tm_min, &t.tm_sec, tz_str) == 7) {
gboolean offset_positive = TRUE;
int tzhrs;
int tzmins;
for (t.tm_mon = 0;
months[t.tm_mon] != NULL &&
strcmp(months[t.tm_mon], month_str) != 0; t.tm_mon++);
if (months[t.tm_mon] != NULL) {
if (*tz_str == '-') {
offset_positive = FALSE;
tz_ptr++;
} else if (*tz_str == '+') {
tz_ptr++;
}
if (sscanf(tz_ptr, "%02d%02d", &tzhrs, &tzmins) == 2) {
time_t tzoff = tzhrs * 60 * 60 + tzmins * 60;
#ifdef _WIN32
long sys_tzoff;
#endif
if (offset_positive)
tzoff *= -1;
t.tm_year -= 1900;
#ifdef _WIN32
if ((sys_tzoff = wpurple_get_tz_offset()) != -1)
tzoff += sys_tzoff;
#else
#ifdef HAVE_TM_GMTOFF
tzoff += t.tm_gmtoff;
#else
# ifdef HAVE_TIMEZONE
tzset(); /* making sure */
tzoff -= timezone;
# endif
#endif
#endif /* _WIN32 */
return mktime(&t) + tzoff;
}
}
}
purple_debug_info("msn", "Can't parse timestamp %s\n", timestamp);
return tval;
}
/*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);
}
/* 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) {
PurpleXmlNode *msg_node = purple_xmlnode_get_child(msn_soap_message_get_xml(response),
"Body/GetMessageResponse/GetMessageResult");
if (msg_node) {
char *msg_str = purple_xmlnode_get_data(msg_node);
msn_oim_report_to_user(rdata, msg_str);
g_free(msg_str);
} else {
char *str = purple_xmlnode_to_str(msn_soap_message_get_xml(response), 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);
}
}
/* parse the oim XML data
* and post it to the soap server to get the Offline Message
* */
void
msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg)
{
PurpleXmlNode *node;
purple_debug_info("msn", "%s\n", xmlmsg);
if (!strcmp(xmlmsg, "too-large")) {
/* Too many OIM's to send via NS, so we need to request them via SOAP. */
msn_oim_get_metadata(oim);
} else {
node = purple_xmlnode_from_str(xmlmsg, -1);
msn_parse_oim_xml(oim, node);
purple_xmlnode_free(node);
}
}
static void
msn_parse_oim_xml(MsnOim *oim, PurpleXmlNode *node)
{
PurpleXmlNode *mNode;
PurpleXmlNode *iu_node;
MsnSession *session = oim->session;
g_return_if_fail(node != NULL);
if (strcmp(node->name, "MD") != 0) {
char *xmlmsg = purple_xmlnode_to_str(node, NULL);
purple_debug_info("msn", "WTF is this? %s\n", xmlmsg);
g_free(xmlmsg);
return;
}
iu_node = purple_xmlnode_get_child(node, "E/IU");
if (iu_node != NULL && purple_account_get_check_mail(session->account))
{
char *unread = purple_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;
/* XXX/khc: pretty sure this is wrong */
if (unread && (count = atoi(unread)) > 0)
purple_notify_emails(purple_account_get_connection(session->account), count, FALSE, NULL,
NULL, passports, urls, NULL, NULL);
g_free(unread);
}
for(mNode = purple_xmlnode_get_child(node, "M"); mNode;
mNode = purple_xmlnode_get_next_twin(mNode)){
char *passport, *msgid, *nickname, *rtime = NULL;
PurpleXmlNode *e_node, *i_node, *n_node, *rt_node;
e_node = purple_xmlnode_get_child(mNode, "E");
passport = purple_xmlnode_get_data(e_node);
i_node = purple_xmlnode_get_child(mNode, "I");
msgid = purple_xmlnode_get_data(i_node);
n_node = purple_xmlnode_get_child(mNode, "N");
nickname = purple_xmlnode_get_data(n_node);
rt_node = purple_xmlnode_get_child(mNode, "RT");
if (rt_node != NULL) {
rtime = purple_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);
}
}
/*Post to get the Offline Instant Message*/
static void
msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data)
{
char *soap_body;
purple_debug_info("msn", "Get single OIM Message\n");
soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, data->msg_id);
msn_oim_make_request(oim, FALSE, MSN_OIM_GET_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
MSN_OIM_RETRIEVE_URL, purple_xmlnode_from_str(soap_body, -1), msn_oim_get_read_cb,
data);
g_free(soap_body);
}