# HG changeset patch
# User masca@cpw.pidgin.im
# Date 1275509333 0
# Node ID 562498203fe88e65056f38390576127d43e881f7
# Parent 2bc54dfae6271c0e8bd3b5012f242df14d03e497# Parent 320337ee96add191343c8070a567a0c5d24d54c2
propagate from branch 'im.pidgin.pidgin' (head a16b83242562658cc9f08739aedaa0a4b621077a)
to branch 'im.pidgin.cpw.qulogic.msnp16' (head 6f45ed65a9417053e242214f5c2bc51028f8e01f)
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/Makefile.am
--- a/libpurple/protocols/msn/Makefile.am Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/Makefile.am Wed Jun 02 20:08:53 2010 +0000
@@ -12,8 +12,6 @@
command.h \
contact.c\
contact.h\
- dialog.c \
- dialog.h \
directconn.c \
directconn.h \
error.c \
@@ -56,8 +54,6 @@
state.h \
switchboard.c \
switchboard.h \
- sync.c \
- sync.h \
table.c \
table.h \
transaction.c \
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/cmdproc.c
--- a/libpurple/protocols/msn/cmdproc.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/cmdproc.c Wed Jun 02 20:08:53 2010 +0000
@@ -122,7 +122,8 @@
return;
}
- msn_history_add(cmdproc->history, trans);
+ if (trans->saveable)
+ msn_history_add(cmdproc->history, trans);
data = msn_transaction_to_string(trans);
@@ -155,75 +156,6 @@
}
void
-msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command,
- const char *format, ...)
-{
- MsnServConn *servconn;
- char *data;
- char *params = NULL;
- va_list arg;
- size_t len;
-
- g_return_if_fail(cmdproc != NULL);
- g_return_if_fail(command != NULL);
-
- servconn = cmdproc->servconn;
-
- if (!servconn->connected)
- return;
-
- if (format != NULL)
- {
- va_start(arg, format);
- params = g_strdup_vprintf(format, arg);
- va_end(arg);
- }
-
- if (params != NULL)
- data = g_strdup_printf("%s %s\r\n", command, params);
- else
- data = g_strdup_printf("%s\r\n", command);
-
- g_free(params);
-
- len = strlen(data);
-
- show_debug_cmd(cmdproc, FALSE, data);
-
- msn_servconn_write(servconn, data, len);
-
- g_free(data);
-}
-
-void
-msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command,
- const char *format, ...)
-{
- MsnTransaction *trans;
- va_list arg;
-
- g_return_if_fail(cmdproc != NULL);
- g_return_if_fail(command != NULL);
-
- if (!cmdproc->servconn->connected)
- return;
-
- trans = g_new0(MsnTransaction, 1);
-
- trans->cmdproc = cmdproc;
- trans->command = g_strdup(command);
-
- if (format != NULL)
- {
- va_start(arg, format);
- trans->params = g_strdup_vprintf(format, arg);
- va_end(arg);
- }
-
- msn_cmdproc_send_trans(cmdproc, trans);
-}
-
-void
msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
int payload_len)
{
@@ -243,58 +175,71 @@
msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
{
MsnMsgTypeCb cb;
- const char *messageId = NULL;
+ const char *message_id = NULL;
/* Multi-part messages */
- if ((messageId = msn_message_get_attr(msg, "Message-ID")) != NULL) {
- const char *chunk_text = msn_message_get_attr(msg, "Chunks");
+ message_id = msn_message_get_header_value(msg, "Message-ID");
+ if (message_id != NULL) {
+ /* This is the first in a series of chunks */
+
+ const char *chunk_text = msn_message_get_header_value(msg, "Chunks");
guint chunk;
if (chunk_text != NULL) {
chunk = strtol(chunk_text, NULL, 10);
- /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent
+ /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent
some random client causing pidgin to hog a ton of memory.
Probably should figure out the maximum that the official client
actually supports, though. */
if (chunk > 0 && chunk < 1024) {
msg->total_chunks = chunk;
msg->received_chunks = 1;
- g_hash_table_insert(cmdproc->multiparts, (gpointer)messageId, msn_message_ref(msg));
- purple_debug_info("msn", "Received chunked message, messageId: '%s', total chunks: %d\n",
- messageId, chunk);
+ g_hash_table_insert(cmdproc->multiparts, (gpointer)message_id, msn_message_ref(msg));
+ purple_debug_info("msn", "Received chunked message, message_id: '%s', total chunks: %d\n",
+ message_id, chunk);
} else {
- purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", messageId, chunk);
+ purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", message_id, chunk);
}
return;
} else {
- chunk_text = msn_message_get_attr(msg, "Chunk");
+ chunk_text = msn_message_get_header_value(msg, "Chunk");
if (chunk_text != NULL) {
- MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, messageId);
+ /* This is one chunk in a series of chunks */
+
+ MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, message_id);
chunk = strtol(chunk_text, NULL, 10);
if (first == NULL) {
purple_debug_error("msn",
- "Unable to find first chunk of messageId '%s' to correspond with chunk %d.\n",
- messageId, chunk+1);
- } else if (first->received_chunks == chunk) {
- /* Chunk is from 1 to total-1 (doesn't count first one) */
- purple_debug_info("msn", "Received chunk %d of %d, messageId: '%s'\n",
- chunk+1, first->total_chunks, messageId);
- first->body = g_realloc(first->body, first->body_len + msg->body_len);
- memcpy(first->body + first->body_len, msg->body, msg->body_len);
- first->body_len += msg->body_len;
- first->received_chunks++;
- if (first->received_chunks != first->total_chunks)
- return;
- else
- /* We're done! Send it along... The caller takes care of
- freeing the old one. */
- msg = first;
- } else {
- /* TODO: Can you legitimately receive chunks out of order? */
- g_hash_table_remove(cmdproc->multiparts, messageId);
+ "Unable to find first chunk of message_id '%s' to correspond with chunk %d.\n",
+ message_id, chunk + 1);
+ } else if (first->received_chunks != chunk) {
+ /*
+ * We received an out of order chunk number (i.e. not the
+ * next one in the sequence). Not sure if this can happen
+ * legitimately, but we definitely don't handle it right
+ * now.
+ */
+ g_hash_table_remove(cmdproc->multiparts, message_id);
return;
}
+
+ /* Chunk is from 1 to total-1 (doesn't count first one) */
+ purple_debug_info("msn", "Received chunk %d of %d, message_id: '%s'\n",
+ chunk + 1, first->total_chunks, message_id);
+ first->body = g_realloc(first->body, first->body_len + msg->body_len);
+ memcpy(first->body + first->body_len, msg->body, msg->body_len);
+ first->body_len += msg->body_len;
+ first->received_chunks++;
+ if (first->received_chunks != first->total_chunks)
+ /* We're waiting for more chunks */
+ return;
+
+ /*
+ * We have all the chunks for this message, great! Send
+ * it along... The caller takes care of freeing the old one.
+ */
+ msg = first;
} else {
- purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", messageId);
+ purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", message_id);
}
}
}
@@ -314,8 +259,8 @@
purple_debug_warning("msn", "Unhandled content-type '%s'\n",
msn_message_get_content_type(msg));
- if (messageId != NULL)
- g_hash_table_remove(cmdproc->multiparts, messageId);
+ if (message_id != NULL)
+ g_hash_table_remove(cmdproc->multiparts, message_id);
}
void
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/cmdproc.h
--- a/libpurple/protocols/msn/cmdproc.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/cmdproc.h Wed Jun 02 20:08:53 2010 +0000
@@ -51,18 +51,45 @@
void *data; /**< Extra data, like the switchboard. */
};
+/**
+ * Creates a MsnCmdProc structure.
+ *
+ * @param session The session to associate with.
+ *
+ * @return A new MsnCmdProc structure.
+ */
MsnCmdProc *msn_cmdproc_new(MsnSession *session);
+
+/**
+ * Destroys an MsnCmdProc.
+ *
+ * @param cmdproc The object structure.
+ */
void msn_cmdproc_destroy(MsnCmdProc *cmdproc);
+/**
+ * Process the queued transactions.
+ *
+ * @param cmdproc The MsnCmdProc.
+ */
void msn_cmdproc_process_queue(MsnCmdProc *cmdproc);
+/**
+ * Sends transaction using this servconn.
+ *
+ * @param cmdproc The MsnCmdProc to be used.
+ * @param trans The MsnTransaction to be sent.
+ */
void msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
+
+/**
+ * Add a transaction to the queue to be processed latter.
+ *
+ * @param cmdproc The MsnCmdProc in which the transaction will be queued.
+ * @param trans The MsnTransaction to be queued.
+ */
void msn_cmdproc_queue_trans(MsnCmdProc *cmdproc,
MsnTransaction *trans);
-void msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command,
- const char *format, ...);
-void msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command,
- const char *format, ...);
void msn_cmdproc_process_msg(MsnCmdProc *cmdproc,
MsnMessage *msg);
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/command.h
--- a/libpurple/protocols/msn/command.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/command.h Wed Jun 02 20:08:53 2010 +0000
@@ -54,9 +54,39 @@
void *payload_cbdata;
};
+/**
+ * Create a command object from the incoming string and ref it.
+ *
+ * @param string The incoming string.
+ *
+ * @return A MsnCommand object.
+ */
MsnCommand *msn_command_from_string(const char *string);
+
+/**
+ * Destroy a MsnCommand object if its ref count is zero, otherwise
+ * just unref it.
+ *
+ * @param cmd The MsnCommand to be destroyed.
+ */
void msn_command_destroy(MsnCommand *cmd);
+
+/**
+ * Increment the ref count.
+ *
+ * @param cmd The MsnCommand to be ref.
+ *
+ * @return The ref command.
+ */
MsnCommand *msn_command_ref(MsnCommand *cmd);
+
+/**
+ * Decrement the ref count. If the count goes to 0, destroy it.
+ *
+ * @param cmd The MsnCommand to be unref.
+ *
+ * @return The ref command.
+ */
MsnCommand *msn_command_unref(MsnCommand *cmd);
#endif /* MSN_COMMAND_H */
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/dialog.c
--- a/libpurple/protocols/msn/dialog.c Wed Jun 02 02:36:24 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/**
- * @file dialog.c Dialog functions
- *
- * 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 02111-1301 USA
- */
-
-#include "msn.h"
-#include "dialog.h"
-
-typedef struct
-{
- PurpleConnection *gc;
- char *who;
- char *group;
- gboolean add;
-
-} MsnAddRemData;
-
-/* Remove the buddy referenced by the MsnAddRemData before the serverside list is changed.
- * If the buddy will be added, he'll be added back; if he will be removed, he won't be. */
-/* Actually with our MSNP14 code that isn't true yet, he won't be added back :( */
-static void
-msn_complete_sync_issue(MsnAddRemData *data)
-{
- PurpleBuddy *buddy;
- PurpleGroup *group = NULL;
-
- if (data->group != NULL)
- group = purple_find_group(data->group);
-
- if (group != NULL)
- buddy = purple_find_buddy_in_group(purple_connection_get_account(data->gc), data->who, group);
- else
- buddy = purple_find_buddy(purple_connection_get_account(data->gc), data->who);
-
- if (buddy != NULL)
- purple_blist_remove_buddy(buddy);
-}
-
-
-static void
-msn_add_cb(MsnAddRemData *data)
-{
-#if 0
- /* this *should* be necessary !! */
- msn_complete_sync_issue(data);
-#endif
-
- if (g_list_find(purple_connections_get_all(), data->gc) != NULL)
- {
- MsnSession *session = data->gc->proto_data;
- MsnUserList *userlist = session->userlist;
-
- msn_userlist_add_buddy(userlist, data->who, data->group);
- }
-
- g_free(data->group);
- g_free(data->who);
- g_free(data);
-}
-
-static void
-msn_rem_cb(MsnAddRemData *data)
-{
- msn_complete_sync_issue(data);
-
- if (g_list_find(purple_connections_get_all(), data->gc) != NULL)
- {
- MsnSession *session = data->gc->proto_data;
- MsnUserList *userlist = session->userlist;
-
- if (data->group == NULL) {
- msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
- } else {
- g_free(data->group);
- }
- }
-
- g_free(data->who);
- g_free(data);
-}
-
-void
-msn_show_sync_issue(MsnSession *session, const char *passport,
- const char *group_name)
-{
- PurpleConnection *gc;
- PurpleAccount *account;
- MsnAddRemData *data;
- char *msg, *reason;
-
- account = session->account;
- gc = purple_account_get_connection(account);
-
- data = g_new0(MsnAddRemData, 1);
- data->who = g_strdup(passport);
- data->group = g_strdup(group_name);
- data->gc = gc;
-
- msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
- purple_account_get_username(account),
- purple_account_get_protocol_name(account));
-
- if (group_name != NULL)
- {
- reason = g_strdup_printf(_("%s on the local list is "
- "inside the group \"%s\" but not on "
- "the server list. "
- "Do you want this buddy to be added?"),
- passport, group_name);
- }
- else
- {
- reason = g_strdup_printf(_("%s is on the local list but "
- "not on the server list. "
- "Do you want this buddy to be added?"),
- passport);
- }
-
- purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
- purple_connection_get_account(gc), data->who, NULL,
- data, 2,
- _("Yes"), G_CALLBACK(msn_add_cb),
- _("No"), G_CALLBACK(msn_rem_cb));
-
- g_free(reason);
- g_free(msg);
-}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/dialog.h
--- a/libpurple/protocols/msn/dialog.h Wed Jun 02 02:36:24 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/**
- * @file dialog.h Dialog functions
- *
- * 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 02111-1301 USA
- */
-#ifndef MSN_DIALOG_H
-#define MSN_DIALOG_H
-
-void msn_show_sync_issue(MsnSession *session, const char *passport,
- const char *group_name);
-
-#endif /* MSN_DIALOG_H */
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/error.c
--- a/libpurple/protocols/msn/error.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/error.c Wed Jun 02 20:08:53 2010 +0000
@@ -24,6 +24,15 @@
#include "msn.h"
#include "error.h"
+typedef struct
+{
+ PurpleConnection *gc;
+ char *who;
+ char *group;
+ gboolean add;
+
+} MsnAddRemData;
+
const char *
msn_error_get_text(unsigned int type, gboolean *debug)
{
@@ -264,3 +273,115 @@
g_free(buf);
}
+/* Remove the buddy referenced by the MsnAddRemData before the serverside list
+ * is changed. If the buddy will be added, he'll be added back; if he will be
+ * removed, he won't be. */
+/* Actually with our MSNP14 code that isn't true yet, he won't be added back :(
+ * */
+static void
+msn_complete_sync_issue(MsnAddRemData *data)
+{
+ PurpleBuddy *buddy;
+ PurpleGroup *group = NULL;
+
+ if (data->group != NULL)
+ group = purple_find_group(data->group);
+
+ if (group != NULL)
+ buddy = purple_find_buddy_in_group(purple_connection_get_account(data->gc), data->who, group);
+ else
+ buddy = purple_find_buddy(purple_connection_get_account(data->gc), data->who);
+
+ if (buddy != NULL)
+ purple_blist_remove_buddy(buddy);
+}
+
+
+static void
+msn_add_cb(MsnAddRemData *data)
+{
+#if 0
+ /* this *should* be necessary !! */
+ msn_complete_sync_issue(data);
+#endif
+
+ if (g_list_find(purple_connections_get_all(), data->gc) != NULL)
+ {
+ MsnSession *session = data->gc->proto_data;
+ MsnUserList *userlist = session->userlist;
+
+ msn_userlist_add_buddy(userlist, data->who, data->group);
+ }
+
+ g_free(data->group);
+ g_free(data->who);
+ g_free(data);
+}
+
+static void
+msn_rem_cb(MsnAddRemData *data)
+{
+ msn_complete_sync_issue(data);
+
+ if (g_list_find(purple_connections_get_all(), data->gc) != NULL)
+ {
+ MsnSession *session = data->gc->proto_data;
+ MsnUserList *userlist = session->userlist;
+
+ if (data->group == NULL) {
+ msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
+ } else {
+ g_free(data->group);
+ }
+ }
+
+ g_free(data->who);
+ g_free(data);
+}
+
+void
+msn_error_sync_issue(MsnSession *session, const char *passport,
+ const char *group_name)
+{
+ PurpleConnection *gc;
+ PurpleAccount *account;
+ MsnAddRemData *data;
+ char *msg, *reason;
+
+ account = session->account;
+ gc = purple_account_get_connection(account);
+
+ data = g_new0(MsnAddRemData, 1);
+ data->who = g_strdup(passport);
+ data->group = g_strdup(group_name);
+ data->gc = gc;
+
+ msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
+ purple_account_get_username(account),
+ purple_account_get_protocol_name(account));
+
+ if (group_name != NULL)
+ {
+ reason = g_strdup_printf(_("%s on the local list is "
+ "inside the group \"%s\" but not on "
+ "the server list. "
+ "Do you want this buddy to be added?"),
+ passport, group_name);
+ }
+ else
+ {
+ reason = g_strdup_printf(_("%s is on the local list but "
+ "not on the server list. "
+ "Do you want this buddy to be added?"),
+ passport);
+ }
+
+ purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
+ purple_connection_get_account(gc), data->who, NULL,
+ data, 2,
+ _("Yes"), G_CALLBACK(msn_add_cb),
+ _("No"), G_CALLBACK(msn_rem_cb));
+
+ g_free(reason);
+ g_free(msg);
+}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/error.h
--- a/libpurple/protocols/msn/error.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/error.h Wed Jun 02 20:08:53 2010 +0000
@@ -44,4 +44,14 @@
*/
void msn_error_handle(MsnSession *session, unsigned int type);
+/**
+ * Show the sync issue in a dialog using request api
+ *
+ * @param sesion MsnSession associated to this error.
+ * @param passport The passport associated with the error.
+ * @param group_name The group in the buddy is suppoused to be
+ */
+void msn_error_sync_issue(MsnSession *session, const char *passport,
+ const char *group_name);
+
#endif /* MSN_ERROR_H */
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/msg.c
--- a/libpurple/protocols/msn/msg.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/msg.c Wed Jun 02 20:08:53 2010 +0000
@@ -36,7 +36,7 @@
if (purple_debug_is_verbose())
purple_debug_info("msn", "message new (%p)(%d)\n", msg, type);
- msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
msn_message_ref(msg);
@@ -64,8 +64,8 @@
g_free(msg->content_type);
g_free(msg->charset);
- g_hash_table_destroy(msg->attr_table);
- g_list_free(msg->attr_list);
+ g_hash_table_destroy(msg->header_table);
+ g_list_free(msg->header_list);
g_free(msg);
}
@@ -112,11 +112,11 @@
msg = msn_message_new(MSN_MSG_TEXT);
msg->retries = 1;
- msn_message_set_attr(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
+ msn_message_set_header(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
msn_message_set_content_type(msg, "text/plain");
msn_message_set_charset(msg, "UTF-8");
msn_message_set_flag(msg, 'A');
- msn_message_set_attr(msg, "X-MMS-IM-Format",
+ msn_message_set_header(msg, "X-MMS-IM-Format",
"FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
message_cr = purple_str_add_cr(message);
@@ -133,7 +133,7 @@
msg = msn_message_new(MSN_MSG_SLP);
- msn_message_set_attr(msg, "User-Agent", NULL);
+ msn_message_set_header(msg, "User-Agent", NULL);
msg->msnslp_message = TRUE;
@@ -169,7 +169,7 @@
g_return_if_reached();
}
- /* Import the header. */
+ /* Extract the binary SLP header */
memcpy(&header, tmp, sizeof(header));
tmp += sizeof(header);
@@ -183,7 +183,7 @@
msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size);
- /* Import the body. */
+ /* Extract the body */
body_len = len - (tmp - body);
/* msg->body_len = msg->msnslp_header.length; */
@@ -211,7 +211,7 @@
memcpy(tmp_base, payload, payload_len);
tmp_base[payload_len] = '\0';
- /* Parse the attributes. */
+ /* Find the end of the headers */
end = strstr(tmp, body_dem);
/* TODO? some clients use \r delimiters instead of \r\n, the official client
* doesn't send such messages, but does handle receiving them. We'll just
@@ -222,8 +222,8 @@
}
*end = '\0';
+ /* Split the headers and parse each one */
elems = g_strsplit(tmp, line_dem, 0);
-
for (cur = elems; *cur != NULL; cur++)
{
const char *key, *value;
@@ -240,7 +240,7 @@
if (!strcmp(key, "boundary")) {
char *end = strchr(value, '\"');
*end = '\0';
- msn_message_set_attr(msg, key, value);
+ msn_message_set_header(msg, key, value);
}
g_strfreev(tokens);
@@ -278,12 +278,11 @@
}
else
{
- msn_message_set_attr(msg, key, value);
+ msn_message_set_header(msg, key, value);
}
g_strfreev(tokens);
}
-
g_strfreev(elems);
/* Proceed to the end of the "\r\n\r\n" */
@@ -306,7 +305,7 @@
msg->msnslp_message = TRUE;
- /* Import the header. */
+ /* Extract the binary SLP header */
memcpy(&header, tmp, sizeof(header));
tmp += sizeof(header);
@@ -322,7 +321,7 @@
body_len = payload_len - (tmp - tmp_base) - sizeof(footer);
- /* Import the body. */
+ /* Extract the body */
if (body_len > 0) {
msg->body_len = body_len;
g_free(msg->body);
@@ -332,7 +331,7 @@
tmp += body_len;
}
- /* Import the footer. */
+ /* Extract the footer */
if (body_len >= 0) {
memcpy(&footer, tmp, sizeof(footer));
tmp += sizeof(footer);
@@ -348,7 +347,7 @@
memcpy(msg->body, tmp, msg->body_len);
msg->body[msg->body_len] = '\0';
}
-
+
if ((!content_type || !strcmp(content_type, "text/plain"))
&& msg->charset == NULL) {
char *body = g_convert(msg->body, msg->body_len, "UTF-8",
@@ -454,13 +453,13 @@
n += strlen(n);
- for (l = msg->attr_list; l != NULL; l = l->next)
+ for (l = msg->header_list; l != NULL; l = l->next)
{
const char *key;
const char *value;
key = l->data;
- value = msn_message_get_attr(msg, key);
+ value = msn_message_get_header_value(msg, key);
g_snprintf(n, end - n, "%s: %s\r\n", key, value);
n += strlen(n);
@@ -610,15 +609,15 @@
}
void
-msn_message_set_attr(MsnMessage *msg, const char *attr, const char *value)
+msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
{
const char *temp;
- char *new_attr;
+ char *new_name;
g_return_if_fail(msg != NULL);
- g_return_if_fail(attr != NULL);
+ g_return_if_fail(name != NULL);
- temp = msn_message_get_attr(msg, attr);
+ temp = msn_message_get_header_value(msg, name);
if (value == NULL)
{
@@ -626,37 +625,37 @@
{
GList *l;
- for (l = msg->attr_list; l != NULL; l = l->next)
+ for (l = msg->header_list; l != NULL; l = l->next)
{
- if (!g_ascii_strcasecmp(l->data, attr))
+ if (!g_ascii_strcasecmp(l->data, name))
{
- msg->attr_list = g_list_remove(msg->attr_list, l->data);
+ msg->header_list = g_list_remove(msg->header_list, l->data);
break;
}
}
- g_hash_table_remove(msg->attr_table, attr);
+ g_hash_table_remove(msg->header_table, name);
}
return;
}
- new_attr = g_strdup(attr);
+ new_name = g_strdup(name);
- g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value));
+ g_hash_table_insert(msg->header_table, new_name, g_strdup(value));
if (temp == NULL)
- msg->attr_list = g_list_append(msg->attr_list, new_attr);
+ msg->header_list = g_list_append(msg->header_list, new_name);
}
const char *
-msn_message_get_attr(const MsnMessage *msg, const char *attr)
+msn_message_get_header_value(const MsnMessage *msg, const char *name)
{
g_return_val_if_fail(msg != NULL, NULL);
- g_return_val_if_fail(attr != NULL, NULL);
+ g_return_val_if_fail(name != NULL, NULL);
- return g_hash_table_lookup(msg->attr_table, attr);
+ return g_hash_table_lookup(msg->header_table, name);
}
GHashTable *
@@ -741,13 +740,13 @@
msg->content_type, msg->charset);
}
- for (l = msg->attr_list; l; l = l->next)
+ for (l = msg->header_list; l; l = l->next)
{
char *key;
const char *value;
key = l->data;
- value = msn_message_get_attr(msg, key);
+ value = msn_message_get_header_value(msg, key);
g_string_append_printf(str, "%s: %s\r\n", key, value);
}
@@ -817,7 +816,6 @@
{
PurpleConnection *gc;
const char *body;
- char *body_str;
char *body_enc;
char *body_final;
size_t body_len;
@@ -827,9 +825,7 @@
gc = cmdproc->session->account->gc;
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);
+ body_enc = g_markup_escape_text(body, body_len);
passport = msg->remote_user;
@@ -840,13 +836,13 @@
}
#if 0
- if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL)
+ 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_attr(msg, "X-MMS-IM-Format")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
{
char *pre, *post;
@@ -914,7 +910,7 @@
gc = cmdproc->session->account->gc;
passport = msg->remote_user;
- if (msn_message_get_attr(msg, "TypingUser") == NULL)
+ if (msn_message_get_header_value(msg, "TypingUser") == NULL)
return;
if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/msg.h
--- a/libpurple/protocols/msn/msg.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/msg.h Wed Jun 02 20:08:53 2010 +0000
@@ -109,8 +109,8 @@
MsnSlpHeader msnslp_header;
MsnSlpFooter msnslp_footer;
- GHashTable *attr_table;
- GList *attr_list;
+ GHashTable *header_table;
+ GList *header_list;
gboolean ack_ref; /**< A flag that states if this message has
been ref'ed for using it in a callback. */
@@ -295,24 +295,24 @@
const char *msn_message_get_charset(const MsnMessage *msg);
/**
- * Sets an attribute in a message.
+ * Sets a header in a message.
*
- * @param msg The message.
- * @param attr The attribute name.
- * @param value The attribute value.
+ * @param msg The message.
+ * @param header The header name.
+ * @param value The header value.
*/
-void msn_message_set_attr(MsnMessage *msg, const char *attr,
+void msn_message_set_header(MsnMessage *msg, const char *name,
const char *value);
/**
- * Returns an attribute from a message.
+ * Returns the value of a header from a message.
*
- * @param msg The message.
- * @param attr The attribute.
+ * @param msg The message.
+ * @param header The header value.
*
* @return The value, or @c NULL if not found.
*/
-const char *msn_message_get_attr(const MsnMessage *msg, const char *attr);
+const char *msn_message_get_header_value(const MsnMessage *msg, const char *name);
/**
* Parses the body and returns it in the form of a hashtable.
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/msn.c
--- a/libpurple/protocols/msn/msn.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/msn.c Wed Jun 02 20:08:53 2010 +0000
@@ -43,7 +43,6 @@
#include "msg.h"
#include "switchboard.h"
#include "notification.h"
-#include "sync.h"
#include "slplink.h"
#if PHOTO_SUPPORT
@@ -267,9 +266,9 @@
{
MsnCmdProc *cmdproc;
MsnSession *session;
+ MsnTransaction *trans;
PurpleAccount *account;
const char *real_alias;
- MsnTransaction *trans;
struct public_alias_closure *closure;
session = purple_connection_get_protocol_data(pc);
@@ -360,19 +359,21 @@
{
MsnCmdProc *cmdproc;
MsnSession *session;
+ MsnTransaction *trans;
session = gc->proto_data;
cmdproc = session->notification->cmdproc;
if (entry == NULL || *entry == '\0')
{
- msn_cmdproc_send(cmdproc, "PRP", "%s", type);
+ trans = msn_transaction_new(cmdproc, "PRP", "%s", type);
}
else
{
- msn_cmdproc_send(cmdproc, "PRP", "%s %s", type,
+ trans = msn_transaction_new(cmdproc, "PRP", "%s %s", type,
purple_url_encode(entry));
}
+ msn_cmdproc_send_trans(cmdproc, trans);
}
static void
@@ -478,7 +479,7 @@
tmp = g_strdup_printf(_("Set friendly name for %s."),
purple_account_get_username(account));
- purple_request_input(gc, _("Set your friendly name."), tmp,
+ purple_request_input(gc, _("Set Friendly Name"), tmp,
_("This is the name that other MSN buddies will "
"see you as."),
purple_connection_get_display_name(gc), FALSE, FALSE, NULL,
@@ -489,6 +490,111 @@
g_free(tmp);
}
+typedef struct MsnLocationData {
+ PurpleAccount *account;
+ MsnSession *session;
+ PurpleRequestFieldGroup *group;
+} MsnLocationData;
+
+static void
+update_endpoint_cb(MsnLocationData *data, PurpleRequestFields *fields)
+{
+ PurpleAccount *account;
+ MsnSession *session;
+ const char *old_name;
+ const char *name;
+ GList *others;
+
+ session = data->session;
+ account = data->account;
+
+ /* Update the current location's name */
+ old_name = purple_account_get_string(account, "endpoint-name", NULL);
+ name = purple_request_fields_get_string(fields, "endpoint-name");
+ if (!g_str_equal(old_name, name)) {
+ purple_account_set_string(account, "endpoint-name", name);
+ msn_notification_send_uux_private_endpointdata(session);
+ }
+
+ /* Sign out other locations */
+ for (others = purple_request_field_group_get_fields(data->group);
+ others;
+ others = g_list_next(others)) {
+ PurpleRequestField *field = others->data;
+ if (purple_request_field_get_type(field) != PURPLE_REQUEST_FIELD_BOOLEAN)
+ continue;
+ if (purple_request_field_bool_get_value(field)) {
+ const char *id = purple_request_field_get_id(field);
+ char *user;
+ purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
+
+ user = g_strdup_printf("%s;%s", purple_account_get_username(account), id);
+ msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
+ g_free(user);
+ }
+ }
+
+ g_free(data);
+}
+
+static void
+msn_show_locations(PurplePluginAction *action)
+{
+ PurpleConnection *pc;
+ PurpleAccount *account;
+ MsnSession *session;
+ PurpleRequestFields *fields;
+ PurpleRequestFieldGroup *group;
+ PurpleRequestField *field;
+ GSList *l;
+ MsnLocationData *data;
+
+ pc = (PurpleConnection *)action->context;
+ account = purple_connection_get_account(pc);
+ session = purple_connection_get_protocol_data(pc);
+
+ fields = purple_request_fields_new();
+
+ group = purple_request_field_group_new(_("This Location"));
+ purple_request_fields_add_group(fields, group);
+ field = purple_request_field_label_new("endpoint-label", _("This is the name that identifies this location"));
+ purple_request_field_group_add_field(group, field);
+ field = purple_request_field_string_new("endpoint-name",
+ _("Name"),
+ purple_account_get_string(account, "endpoint-name", NULL),
+ FALSE);
+ purple_request_field_set_required(field, TRUE);
+ purple_request_field_group_add_field(group, field);
+
+ group = purple_request_field_group_new(_("Other Locations"));
+ purple_request_fields_add_group(fields, group);
+ field = purple_request_field_label_new("others-label", _("You can sign out from other locations here"));
+ purple_request_field_group_add_field(group, field);
+
+ for (l = session->user->endpoints; l; l = l->next) {
+ MsnUserEndpoint *ep = l->data;
+
+ if (g_str_equal(ep->id, session->guid))
+ /* Don't add myself to the list */
+ continue;
+
+ field = purple_request_field_bool_new(ep->id, ep->name, FALSE);
+ purple_request_field_group_add_field(group, field);
+ }
+
+ data = g_new0(MsnLocationData, 1);
+ data->account = account;
+ data->session = session;
+ data->group = group;
+
+ purple_request_fields(pc, NULL, NULL, NULL,
+ fields,
+ _("OK"), G_CALLBACK(update_endpoint_cb),
+ _("Cancel"), G_CALLBACK(g_free),
+ account, NULL, NULL,
+ data);
+}
+
static void
msn_show_set_home_phone(PurplePluginAction *action)
{
@@ -659,6 +765,7 @@
PurpleAccount *account;
MsnSession *session;
MsnCmdProc *cmdproc;
+ MsnTransaction *trans;
account = purple_connection_get_account(gc);
session = gc->proto_data;
@@ -666,9 +773,11 @@
if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
- msn_cmdproc_send(cmdproc, "BLP", "%s", "AL");
+ trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
else
- msn_cmdproc_send(cmdproc, "BLP", "%s", "BL");
+ trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
+
+ msn_cmdproc_send_trans(cmdproc, trans);
}
static void
@@ -1071,6 +1180,11 @@
m = g_list_append(m, act);
m = g_list_append(m, NULL);
+ act = purple_plugin_action_new(_("View Locations..."),
+ msn_show_locations);
+ m = g_list_append(m, act);
+ m = g_list_append(m, NULL);
+
act = purple_plugin_action_new(_("Set Home Phone Number..."),
msn_show_set_home_phone);
m = g_list_append(m, act);
@@ -1205,6 +1319,13 @@
username = purple_account_get_string(account, "display-name", NULL);
purple_connection_set_display_name(gc, username);
+ if (purple_account_get_string(account, "endpoint-name", NULL) == NULL) {
+ GHashTable *ui_info = purple_core_get_ui_info();
+ const gchar *ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
+ purple_account_set_string(account, "endpoint-name",
+ ui_name && *ui_name ? ui_name : PACKAGE_NAME);
+ }
+
if (!msn_session_connect(session, host, port, http_method))
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -1415,7 +1536,7 @@
msg = msn_message_new_plain(msgtext);
msg->remote_user = g_strdup(who);
- msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat);
+ msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
g_free(msgformat);
g_free(msgtext);
@@ -1448,7 +1569,7 @@
body_enc = g_markup_escape_text(body_str, -1);
g_free(body_str);
- format = msn_message_get_attr(msg, "X-MMS-IM-Format");
+ 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 : "");
@@ -1523,7 +1644,7 @@
msg = msn_message_new(MSN_MSG_TYPING);
msn_message_set_content_type(msg, "text/x-msmsgscontrol");
msn_message_set_flag(msg, 'U');
- msn_message_set_attr(msg, "TypingUser",
+ msn_message_set_header(msg, "TypingUser",
purple_account_get_username(account));
msn_message_set_bin_data(msg, "\r\n", 2);
@@ -1930,7 +2051,7 @@
}
msg = msn_message_new_plain(msgtext);
- msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat);
+ msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
smileys = msn_msg_grab_emoticons(msg->body, username);
while (smileys) {
@@ -1970,6 +2091,7 @@
msn_keepalive(PurpleConnection *gc)
{
MsnSession *session;
+ MsnTransaction *trans;
session = gc->proto_data;
@@ -1979,7 +2101,9 @@
cmdproc = session->notification->cmdproc;
- msn_cmdproc_send_quick(cmdproc, "PNG", NULL, NULL);
+ trans = msn_transaction_new(cmdproc, "PNG", NULL);
+ msn_transaction_set_saveable(trans, FALSE);
+ msn_cmdproc_send_trans(cmdproc, trans);
}
}
@@ -2717,7 +2841,6 @@
{
msn_notification_init();
msn_switchboard_init();
- msn_sync_init();
return TRUE;
}
@@ -2726,7 +2849,6 @@
{
msn_notification_end();
msn_switchboard_end();
- msn_sync_end();
return TRUE;
}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/msn.h
--- a/libpurple/protocols/msn/msn.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/msn.h Wed Jun 02 20:08:53 2010 +0000
@@ -109,9 +109,9 @@
#define MSN_SERVER "messenger.hotmail.com"
#define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com"
#define MSN_PORT 1863
-#define WLM_PROT_VER 15
+#define WLM_PROT_VER 16
-#define WLM_MAX_PROTOCOL 15
+#define WLM_MAX_PROTOCOL 16
#define WLM_MIN_PROTOCOL 15
#define MSN_TYPING_RECV_TIMEOUT 6
@@ -134,15 +134,14 @@
/* Index into attention_types */
#define MSN_NUDGE 0
-#define MSN_CLIENT_ID_VERSION MSN_CLIENT_VER_7_0
+#define MSN_CLIENT_ID_VERSION MSN_CLIENT_VER_9_0
#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF|MSN_CLIENT_CAP_VOICEIM)
+#define MSN_CLIENT_ID_EXT_CAPS (0)
#define MSN_CLIENT_ID \
((MSN_CLIENT_ID_VERSION << 24) | \
(MSN_CLIENT_ID_CAPABILITIES))
-#define MSN_CLIENT_EXT_ID 0
-
gboolean msn_email_is_valid(const char *passport);
void
msn_set_public_alias(PurpleConnection *gc, const char *alias,
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/msnutils.c
--- a/libpurple/protocols/msn/msnutils.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/msnutils.c Wed Jun 02 20:08:53 2010 +0000
@@ -26,13 +26,11 @@
#include "cipher.h"
-char *rand_guid(void);
-
/**************************************************************************
* Util
**************************************************************************/
char *
-rand_guid()
+rand_guid(void)
{
return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
rand() % 0xAAFF + 0x1111,
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/msnutils.h
--- a/libpurple/protocols/msn/msnutils.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/msnutils.h Wed Jun 02 20:08:53 2010 +0000
@@ -54,7 +54,23 @@
*/
void msn_import_html(const char *html, char **attributes, char **message);
+/**
+ * Parses a socket string.
+ *
+ * @param str A host:port string.
+ * @param ret_host Return string value of the host.
+ * @param ret_port Return integer value of the port.
+ */
void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
+
+/**
+ * Handle MSN Challenge Computation
+ * This algorithm references
+ * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
+ *
+ * @param input Challenge input.
+ * @param output Callenge output.
+ */
void msn_handle_chl(char *input, char *output);
#endif /* MSN_UTILS_H */
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/notification.c
--- a/libpurple/protocols/msn/notification.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/notification.c Wed Jun 02 20:08:53 2010 +0000
@@ -22,6 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "msn.h"
+#include "core.h"
#include "notification.h"
#include "contact.h"
#include "state.h"
@@ -30,7 +31,6 @@
#include "page.h"
#include "userlist.h"
-#include "sync.h"
#include "slplink.h"
static MsnTable *cbs_table;
@@ -92,6 +92,7 @@
{
MsnCmdProc *cmdproc;
MsnSession *session;
+ MsnTransaction *trans;
PurpleAccount *account;
GString *vers;
const char *ver_str;
@@ -117,7 +118,8 @@
/* Skip the initial space */
ver_str = (vers->str + 1);
- msn_cmdproc_send(cmdproc, "VER", "%s", ver_str);
+ trans = msn_transaction_new(cmdproc, "VER", "%s", ver_str);
+ msn_cmdproc_send_trans(cmdproc, trans);
g_string_free(vers, TRUE);
}
@@ -156,22 +158,30 @@
msn_got_login_params(MsnSession *session, const char *ticket, const char *response)
{
MsnCmdProc *cmdproc;
+ MsnTransaction *trans;
cmdproc = session->notification->cmdproc;
msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
- msn_cmdproc_send(cmdproc, "USR", "SSO S %s %s", ticket, response);
+ if (session->protocol_ver >= 16)
+ trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s %s", ticket, response, session->guid);
+ else
+ trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s", ticket, response);
+
+ msn_cmdproc_send_trans(cmdproc, trans);
}
static void
cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
{
PurpleAccount *account;
+ MsnTransaction *trans;
account = cmdproc->session->account;
- msn_cmdproc_send(cmdproc, "USR", "SSO I %s", purple_account_get_username(account));
+ trans = msn_transaction_new(cmdproc, "USR", "SSO I %s", purple_account_get_username(account));
+ msn_cmdproc_send_trans(cmdproc, trans);
}
static void
@@ -231,22 +241,25 @@
ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
{
MsnSession *session;
+ MsnTransaction *trans;
PurpleAccount *account;
gboolean protocol_supported = FALSE;
- char proto_str[8];
+ int proto_ver;
size_t i;
session = cmdproc->session;
account = session->account;
- g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver);
-
+ session->protocol_ver = 0;
for (i = 1; i < cmd->param_count; i++)
{
- if (!strcmp(cmd->params[i], proto_str))
- {
- protocol_supported = TRUE;
- break;
+ if (sscanf(cmd->params[i], "MSNP%d", &proto_ver) == 1) {
+ if (proto_ver >= WLM_MIN_PROTOCOL
+ && proto_ver <= WLM_MAX_PROTOCOL
+ && proto_ver > session->protocol_ver) {
+ protocol_supported = TRUE;
+ session->protocol_ver = proto_ver;
+ }
}
}
@@ -257,15 +270,18 @@
return;
}
+ purple_debug_info("msn", "Negotiated protocol version %d with the server.\n", session->protocol_ver);
+
/*
* Windows Live Messenger 8.5
* Notice :CVR String discriminate!
* reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx
* to see the Local ID
*/
- msn_cmdproc_send(cmdproc, "CVR",
+ trans = msn_transaction_new(cmdproc, "CVR",
"0x0409 winnt 5.1 i386 MSNMSGR 8.5.1302 BC01 %s",
purple_account_get_username(account));
+ msn_cmdproc_send_trans(cmdproc, trans);
}
/**************************************************************************
@@ -287,12 +303,16 @@
void
msn_notification_close(MsnNotification *notification)
{
+ MsnTransaction *trans;
+
g_return_if_fail(notification != NULL);
if (!notification->in_use)
return;
- msn_cmdproc_send_quick(notification->cmdproc, "OUT", NULL, NULL);
+ trans = msn_transaction_new(notification->cmdproc, "OUT", NULL);
+ msn_transaction_set_saveable(trans, FALSE);
+ msn_cmdproc_send_trans(notification->cmdproc, trans);
msn_notification_disconnect(notification);
}
@@ -1001,7 +1021,8 @@
PurpleConnection *gc;
MsnUser *user;
MsnObject *msnobj = NULL;
- unsigned long clientid;
+ unsigned long clientid, extcaps;
+ char *extcap_str;
int networkid = 0;
const char *state, *passport;
char *friendly;
@@ -1022,7 +1043,11 @@
/* Yahoo! Buddy, looks like */
networkid = atoi(cmd->params[3]);
friendly = g_strdup(purple_url_decode(cmd->params[4]));
- clientid = strtoul(cmd->params[5], NULL, 10);
+ clientid = strtoul(cmd->params[5], &extcap_str, 10);
+ if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+ extcaps = strtoul(extcap_str+1, NULL, 10);
+ else
+ extcaps = 0;
/* cmd->params[7] seems to be a URL to a Yahoo! icon:
https://sec.yimg.com/i/us/nt/b/purpley.1.0.png
@@ -1032,7 +1057,11 @@
/* MSNP14+ with Display Picture object */
networkid = atoi(cmd->params[3]);
friendly = g_strdup(purple_url_decode(cmd->params[4]));
- clientid = strtoul(cmd->params[5], NULL, 10);
+ clientid = strtoul(cmd->params[5], &extcap_str, 10);
+ if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+ extcaps = strtoul(extcap_str+1, NULL, 10);
+ else
+ extcaps = 0;
msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[6]));
} else if (cmd->param_count == 6) {
/* Yes, this is 5. The friendly name could start with a number,
@@ -1041,17 +1070,29 @@
/* MSNP14 without Display Picture object */
networkid = atoi(cmd->params[3]);
friendly = g_strdup(purple_url_decode(cmd->params[4]));
- clientid = strtoul(cmd->params[5], NULL, 10);
+ clientid = strtoul(cmd->params[5], &extcap_str, 10);
+ if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+ extcaps = strtoul(extcap_str+1, NULL, 10);
+ else
+ extcaps = 0;
} else {
/* MSNP8+ with Display Picture object */
friendly = g_strdup(purple_url_decode(cmd->params[3]));
- clientid = strtoul(cmd->params[4], NULL, 10);
+ clientid = strtoul(cmd->params[4], &extcap_str, 10);
+ if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+ extcaps = strtoul(extcap_str+1, NULL, 10);
+ else
+ extcaps = 0;
msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5]));
}
} else if (cmd->param_count == 5) {
/* MSNP8+ without Display Picture object */
friendly = g_strdup(purple_url_decode(cmd->params[3]));
- clientid = strtoul(cmd->params[4], NULL, 10);
+ clientid = strtoul(cmd->params[4], &extcap_str, 10);
+ if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+ extcaps = strtoul(extcap_str+1, NULL, 10);
+ else
+ extcaps = 0;
} else {
purple_debug_warning("msn", "Received ILN with unknown number of parameters.\n");
return;
@@ -1066,6 +1107,7 @@
user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
msn_user_set_clientid(user, clientid);
+ msn_user_set_extcaps(user, extcaps);
msn_user_set_network(user, networkid);
msn_user_set_state(user, state);
@@ -1204,7 +1246,8 @@
PurpleConnection *gc;
MsnUser *user;
MsnObject *msnobj;
- unsigned long clientid;
+ unsigned long clientid, extcaps;
+ char *extcap_str;
int networkid;
const char *state, *passport, *friendly;
@@ -1217,7 +1260,10 @@
networkid = atoi(cmd->params[2]);
friendly = purple_url_decode(cmd->params[3]);
- user = msn_userlist_find_user(session->userlist, passport);
+ if (g_str_equal(passport, session->user->passport))
+ user = session->user;
+ else
+ user = msn_userlist_find_user(session->userlist, passport);
if (user == NULL) return;
if (msn_user_set_friendly_name(user, friendly))
@@ -1235,10 +1281,16 @@
msn_user_set_object(user, NULL);
}
- clientid = strtoul(cmd->params[4], NULL, 10);
+ clientid = strtoul(cmd->params[4], &extcap_str, 10);
+ if (session->protocol_ver >= 16 && extcap_str && *extcap_str)
+ extcaps = strtoul(extcap_str+1, NULL, 10);
+ else
+ extcaps = 0;
+
user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
msn_user_set_clientid(user, clientid);
+ msn_user_set_extcaps(user, extcaps);
msn_user_set_network(user, networkid);
msn_user_set_state(user, state);
@@ -1506,6 +1558,77 @@
/*get the payload content*/
}
+static void
+parse_user_endpoints(MsnUser *user, xmlnode *payloadNode)
+{
+ xmlnode *epNode, *capsNode;
+ MsnUserEndpoint data;
+ const char *id;
+ char *caps, *tmp;
+
+ purple_debug_info("msn", "Get EndpointData\n");
+
+ for (epNode = xmlnode_get_child(payloadNode, "EndpointData");
+ epNode;
+ epNode = xmlnode_get_next_twin(epNode)) {
+ id = xmlnode_get_attrib(epNode, "id");
+ capsNode = xmlnode_get_child(epNode, "Capabilities");
+
+ if (capsNode != NULL) {
+ caps = xmlnode_get_data(capsNode);
+
+ data.clientid = strtoul(caps, &tmp, 10);
+ if (tmp && *tmp)
+ data.extcaps = strtoul(tmp + 1, NULL, 10);
+ else
+ data.extcaps = 0;
+
+ g_free(caps);
+
+ } else {
+ data.clientid = 0;
+ data.extcaps = 0;
+ }
+
+ msn_user_set_endpoint_data(user, id, &data);
+ }
+
+ /* Need to shortcut this check, probably... */
+ if (user == user->userlist->session->user) {
+ for (epNode = xmlnode_get_child(payloadNode, "PrivateEndpointData");
+ epNode;
+ epNode = xmlnode_get_next_twin(epNode)) {
+ MsnUserEndpoint *ep;
+ xmlnode *nameNode, *clientNode;
+
+ /*
+ Endpoint Name
+ true/false
+ 1
+ NLN
+
+ */
+ id = xmlnode_get_attrib(epNode, "id");
+ ep = msn_user_get_endpoint_data(user, id);
+
+ if (ep != NULL) {
+ nameNode = xmlnode_get_child(epNode, "EpName");
+ if (nameNode != NULL) {
+ g_free(ep->name);
+ ep->name = xmlnode_get_data(nameNode);
+ }
+
+ clientNode = xmlnode_get_child(epNode, "ClientType");
+ if (clientNode != NULL) {
+ tmp = xmlnode_get_data(clientNode);
+ ep->type = strtoul(tmp, NULL, 10);
+ g_free(tmp);
+ }
+ }
+ }
+ }
+}
+
static void parse_currentmedia(MsnUser *user, const char *cmedia)
{
char **cmedia_array;
@@ -1572,15 +1695,19 @@
PurpleAccount *account;
MsnUser *user;
const char *passport;
- char *str;
+ xmlnode *payloadNode;
+ char *psm_str, *str;
session = cmdproc->session;
account = session->account;
passport = cmd->params[0];
- user = msn_userlist_find_user(session->userlist, passport);
+ if (g_str_equal(passport, session->user->passport))
+ user = session->user;
+ else
+ user = msn_userlist_find_user(session->userlist, passport);
if (user == NULL) {
- str = g_strndup(payload, len);
+ char *str = g_strndup(payload, len);
purple_debug_info("msn", "unknown user %s, payload is %s\n",
passport, str);
g_free(str);
@@ -1599,13 +1726,28 @@
}
if (len != 0) {
- str = msn_get_psm(cmd->payload,len);
- msn_user_set_statusline(user, str);
- g_free(str);
-
- str = msn_get_currentmedia(cmd->payload, len);
+ payloadNode = xmlnode_from_str(payload, len);
+ if (!payloadNode) {
+ purple_debug_error("msn", "UBX XML parse Error!\n");
+
+ msn_user_set_statusline(user, NULL);
+
+ msn_user_update(user);
+ return;
+ }
+
+ psm_str = msn_get_psm(payloadNode);
+ msn_user_set_statusline(user, psm_str);
+ g_free(psm_str);
+
+ str = msn_get_currentmedia(payloadNode);
parse_currentmedia(user, str);
g_free(str);
+
+ parse_user_endpoints(user, payloadNode);
+
+ xmlnode_free(payloadNode);
+
} else {
msn_user_set_statusline(user, NULL);
}
@@ -1643,6 +1785,158 @@
cmd->payload_len = atoi(cmd->params[1]);
}
+void
+msn_notification_send_uux(MsnSession *session, const char *payload)
+{
+ MsnTransaction *trans;
+ MsnCmdProc *cmdproc;
+ size_t len = strlen(payload);
+
+ cmdproc = session->notification->cmdproc;
+ purple_debug_misc("msn", "Sending UUX command with payload: %s\n", payload);
+ trans = msn_transaction_new(cmdproc, "UUX", "%" G_GSIZE_FORMAT, len);
+ msn_transaction_set_payload(trans, payload, len);
+ msn_cmdproc_send_trans(cmdproc, trans);
+}
+
+void msn_notification_send_uux_endpointdata(MsnSession *session)
+{
+ xmlnode *epDataNode;
+ xmlnode *capNode;
+ char *caps;
+ char *payload;
+ int length;
+
+ epDataNode = xmlnode_new("EndpointData");
+
+ capNode = xmlnode_new_child(epDataNode, "Capabilities");
+ caps = g_strdup_printf("%d:%02d", MSN_CLIENT_ID_CAPABILITIES, MSN_CLIENT_ID_EXT_CAPS);
+ xmlnode_insert_data(capNode, caps, -1);
+ g_free(caps);
+
+ payload = xmlnode_to_str(epDataNode, &length);
+
+ msn_notification_send_uux(session, payload);
+
+ xmlnode_free(epDataNode);
+ g_free(payload);
+}
+
+void msn_notification_send_uux_private_endpointdata(MsnSession *session)
+{
+ xmlnode *private;
+ const char *name;
+ xmlnode *epname;
+ xmlnode *idle;
+ GHashTable *ui_info;
+ const gchar *ui_type;
+ xmlnode *client_type;
+ xmlnode *state;
+ char *payload;
+ int length;
+
+ private = xmlnode_new("PrivateEndpointData");
+
+ name = purple_account_get_string(session->account, "endpoint-name", NULL);
+ epname = xmlnode_new_child(private, "EpName");
+ xmlnode_insert_data(epname, name, -1);
+
+ idle = xmlnode_new_child(private, "Idle");
+ xmlnode_insert_data(idle, "false", -1);
+
+ /* ClientType info (from amsn guys):
+ 0: None
+ 1: Computer
+ 2: Website
+ 3: Mobile / none
+ 4: Xbox / phone /mobile
+ 9: MsnGroup
+ 32: Email member, currently Yahoo!
+ */
+ client_type = xmlnode_new_child(private, "ClientType");
+ ui_info = purple_core_get_ui_info();
+ ui_type = ui_info ? g_hash_table_lookup(ui_info, "client_type") : NULL;
+ if (ui_type) {
+ if (strcmp(ui_type, "pc") == 0)
+ xmlnode_insert_data(client_type, "1", -1);
+ else if (strcmp(ui_type, "web") == 0)
+ xmlnode_insert_data(client_type, "2", -1);
+ else if (strcmp(ui_type, "phone") == 0)
+ xmlnode_insert_data(client_type, "3", -1);
+ else if (strcmp(ui_type, "handheld") == 0)
+ xmlnode_insert_data(client_type, "3", -1);
+ else
+ xmlnode_insert_data(client_type, "1", -1);
+ }
+ else
+ xmlnode_insert_data(client_type, "1", -1);
+
+ state = xmlnode_new_child(private, "State");
+ xmlnode_insert_data(state, msn_state_get_text(msn_state_from_account(session->account)), -1);
+
+ payload = xmlnode_to_str(private, &length);
+
+ msn_notification_send_uux(session, payload);
+
+ xmlnode_free(private);
+ g_free(payload);
+}
+
+static void
+ubn_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+ size_t len)
+{
+ /* Do Nothing, right now. */
+ if (payload != NULL)
+ purple_debug_info("msn", "UBN payload:\n%s\n", payload);
+}
+
+static void
+ubn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+ purple_debug_misc("msn", "UBN received from %s.\n", cmd->params[0]);
+ cmdproc->last_cmd->payload_cb = ubn_cmd_post;
+ cmd->payload_len = atoi(cmd->params[2]);
+}
+
+static void
+uun_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+ size_t len)
+{
+ /* Do Nothing, right now. */
+ if (payload != NULL)
+ purple_debug_info("msn", "UUN payload:\n%s\n", payload);
+}
+
+static void
+uun_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+ if (strcmp(cmd->params[1], "OK") != 0) {
+ purple_debug_misc("msn", "UUN received.\n");
+ cmdproc->last_cmd->payload_cb = uun_cmd_post;
+ cmd->payload_len = atoi(cmd->params[1]);
+ }
+ else
+ purple_debug_misc("msn", "UUN OK received.\n");
+}
+
+void
+msn_notification_send_uun(MsnSession *session, const char *user,
+ MsnUnifiedNotificationType type, const char *payload)
+{
+ MsnTransaction *trans;
+ MsnCmdProc *cmdproc;
+ size_t len = strlen(payload);
+
+ cmdproc = session->notification->cmdproc;
+ purple_debug_misc("msn", "Sending UUN command %d to %s with payload: %s\n",
+ type, user, payload);
+ trans = msn_transaction_new(cmdproc, "UUN", "%s %d %" G_GSIZE_FORMAT,
+ user, type, len);
+ msn_transaction_set_payload(trans, payload, len);
+ msn_cmdproc_send_trans(cmdproc, trans);
+}
+
/**************************************************************************
* Message Types
**************************************************************************/
@@ -1660,39 +1954,39 @@
/* This isn't an official message. */
return;
- if ((value = msn_message_get_attr(msg, "kv")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "kv")) != NULL)
{
g_free(session->passport_info.kv);
session->passport_info.kv = g_strdup(value);
}
- if ((value = msn_message_get_attr(msg, "sid")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "sid")) != NULL)
{
g_free(session->passport_info.sid);
session->passport_info.sid = g_strdup(value);
}
- if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "MSPAuth")) != NULL)
{
g_free(session->passport_info.mspauth);
session->passport_info.mspauth = g_strdup(value);
}
- if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "ClientIP")) != NULL)
{
g_free(session->passport_info.client_ip);
session->passport_info.client_ip = g_strdup(value);
}
- if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "ClientPort")) != NULL)
{
session->passport_info.client_port = ntohs(atoi(value));
}
- if ((value = msn_message_get_attr(msg, "LoginTime")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "LoginTime")) != NULL)
session->passport_info.sl = atol(value);
- if ((value = msn_message_get_attr(msg, "EmailEnabled")) != NULL)
+ if ((value = msn_message_get_header_value(msg, "EmailEnabled")) != NULL)
session->passport_info.email_enabled = (gboolean)atol(value);
/*starting retrieve the contact list*/
@@ -2099,6 +2393,9 @@
msn_table_add_cmd(cbs_table, NULL, "UBX", ubx_cmd);
msn_table_add_cmd(cbs_table, NULL, "UUX", uux_cmd);
+ msn_table_add_cmd(cbs_table, NULL, "UBN", ubn_cmd);
+ msn_table_add_cmd(cbs_table, NULL, "UUN", uun_cmd);
+
msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd);
msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/notification.h
--- a/libpurple/protocols/msn/notification.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/notification.h Wed Jun 02 20:08:53 2010 +0000
@@ -62,6 +62,15 @@
typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network, gpointer data);
+/* Type used for msn_notification_send_uun */
+typedef enum {
+ MSN_UNIFIED_NOTIFICATION_SHARED_FOLDERS = 1,
+ MSN_UNIFIED_NOTIFICATION_UNKNOWN1 = 2,
+ MSN_UNIFIED_NOTIFICATION_P2P = 3,
+ MSN_UNIFIED_NOTIFICATION_MPOP = 4
+
+} MsnUnifiedNotificationType;
+
void uum_send_msg(MsnSession *session, MsnMessage *msg);
void msn_notification_end(void);
@@ -83,6 +92,17 @@
void msn_notification_disconnect(MsnNotification *notification);
void msn_notification_dump_contact(MsnSession *session);
+void msn_notification_send_uux(MsnSession *session, const char *payload);
+
+void msn_notification_send_uux_endpointdata(MsnSession *session);
+
+void msn_notification_send_uux_private_endpointdata(MsnSession *session);
+
+void msn_notification_send_uun(MsnSession *session,
+ const char *user,
+ MsnUnifiedNotificationType type,
+ const char *payload);
+
/**
* Closes a notification.
*
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/oim.c
--- a/libpurple/protocols/msn/oim.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/oim.c Wed Jun 02 20:08:53 2010 +0000
@@ -618,7 +618,7 @@
MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
purple_debug_info("msn", "oim body:{%s}\n", message->body);
- boundary = msn_message_get_attr(message, "boundary");
+ boundary = msn_message_get_header_value(message, "boundary");
if (boundary != NULL) {
char *bounds;
@@ -656,7 +656,7 @@
decode_msg = (char *)purple_base64_decode(message->body, &body_len);
}
- from = msn_message_get_attr(message, "X-OIM-originatingSource");
+ 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 */
@@ -671,7 +671,7 @@
if (passport == NULL) {
char *start, *end;
- from = msn_message_get_attr(message, "From");
+ from = msn_message_get_header_value(message, "From");
tokens = g_strsplit(from, " ", 2);
if (tokens[1] != NULL)
@@ -690,7 +690,7 @@
g_strfreev(tokens);
}
- date = msn_message_get_attr(message, "Date");
+ 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);
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/session.c
--- a/libpurple/protocols/msn/session.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/session.c Wed Jun 02 20:08:53 2010 +0000
@@ -21,13 +21,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
+#include "error.h"
#include "msn.h"
+#include "msnutils.h"
#include "session.h"
#include "notification.h"
#include "oim.h"
-#include "dialog.h"
-
MsnSession *
msn_session_new(PurpleAccount *account)
{
@@ -45,7 +45,9 @@
purple_account_get_username(account), NULL);
session->oim = msn_oim_new(session);
- session->protocol_ver = WLM_PROT_VER;
+ session->protocol_ver = 0;
+
+ session->guid = rand_guid();
return session;
}
@@ -72,9 +74,6 @@
while (session->switches != NULL)
msn_switchboard_destroy(session->switches->data);
- if (session->sync != NULL)
- msn_sync_destroy(session->sync);
-
if (session->oim != NULL)
msn_oim_destroy(session->oim);
@@ -90,6 +89,7 @@
msn_userlist_destroy(session->userlist);
g_free(session->psm);
+ g_free(session->guid);
g_free(session->abch_cachekey);
#if 0
g_free(session->blocked_text);
@@ -297,7 +297,7 @@
if (!found) {
if ((remote_user == NULL) || !(remote_user->list_op & MSN_LIST_FL_OP)) {
/* The user is not on the server list */
- msn_show_sync_issue(session, buddy_name, group_name);
+ msn_error_sync_issue(session, buddy_name, group_name);
} else {
/* The user is not in that group on the server list */
to_remove = g_list_prepend(to_remove, buddy);
@@ -448,6 +448,11 @@
msn_session_sync_users(session);
}
+ if (session->protocol_ver >= 16) {
+ /* TODO: Send this when updating status instead? */
+ msn_notification_send_uux_endpointdata(session);
+ msn_notification_send_uux_private_endpointdata(session);
+ }
msn_change_status(session);
}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/session.h
--- a/libpurple/protocols/msn/session.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/session.h Wed Jun 02 20:08:53 2010 +0000
@@ -67,7 +67,6 @@
#include "slpcall.h"
#include "sslconn.h"
#include "switchboard.h"
-#include "sync.h"
#include "user.h"
#include "userlist.h"
@@ -89,7 +88,6 @@
MsnNotification *notification;
MsnNexus *nexus;
MsnOim *oim;
- MsnSync *sync;
MsnUserList *userlist;
char *abch_cachekey;
@@ -119,6 +117,7 @@
GHashTable *soap_table;
guint soap_cleanup_handle;
+ char *guid;
};
/**
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/slp.c
--- a/libpurple/protocols/msn/slp.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/slp.c Wed Jun 02 20:08:53 2010 +0000
@@ -960,6 +960,7 @@
if (!strncmp(body, "INVITE", strlen("INVITE")))
{
+ /* This is an INVITE request */
char *branch;
char *call_id;
char *content;
@@ -1011,6 +1012,7 @@
}
else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 ")))
{
+ /* This is a response */
char *content;
char *content_type;
/* Make sure this is "OK" */
@@ -1053,6 +1055,7 @@
}
else if (!strncmp(body, "BYE", strlen("BYE")))
{
+ /* This is a BYE request */
char *call_id;
call_id = get_token(body, "Call-ID: {", "}");
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/slplink.c
--- a/libpurple/protocols/msn/slplink.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/slplink.c Wed Jun 02 20:08:53 2010 +0000
@@ -447,7 +447,7 @@
msg->msnslp_header.total_size = slpmsg->size;
passport = purple_normalize(slplink->session->account, slplink->remote_user);
- msn_message_set_attr(msg, "P2P-Dest", passport);
+ msn_message_set_header(msg, "P2P-Dest", passport);
msg->ack_cb = msg_ack;
msg->nak_cb = msg_nak;
@@ -563,12 +563,14 @@
{
MsnSlpMessage *slpmsg;
guint64 offset;
- PurpleXfer *xfer = NULL;
if (header->total_size < header->length)
{
- purple_debug_error("msn", "This can't be good\n");
- g_return_if_reached();
+ /* We seem to have received a bad header */
+ purple_debug_warning("msn", "Total size listed in SLP binary header "
+ "was less than length of this particular message. This "
+ "should not happen. Dropping message.\n");
+ return;
}
offset = header->offset;
@@ -583,15 +585,13 @@
if (slpmsg->session_id)
{
- if (slpmsg->slpcall == NULL)
- slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);
-
+ slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);
if (slpmsg->slpcall != NULL)
{
if (slpmsg->flags == 0x20 ||
slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030)
{
- xfer = slpmsg->slpcall->xfer;
+ PurpleXfer *xfer = slpmsg->slpcall->xfer;
if (xfer != NULL)
{
slpmsg->ft = TRUE;
@@ -635,10 +635,9 @@
if (slpmsg->ft)
{
- xfer = slpmsg->slpcall->xfer;
slpmsg->slpcall->u.incoming_data =
g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len);
- purple_xfer_prpl_ready(xfer);
+ purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
}
else if (slpmsg->size && slpmsg->buffer)
{
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/state.c
--- a/libpurple/protocols/msn/state.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/state.c Wed Jun 02 20:08:53 2010 +0000
@@ -27,6 +27,7 @@
#include "core.h"
#include "msn.h"
+#include "notification.h"
#include "state.h"
static const char *away_text[] =
@@ -43,10 +44,6 @@
N_("Available")
};
-/* Local Function Prototype*/
-static char *msn_build_psm(const char *psmstr,const char *mediastr,
- const char *guidstr);
-
/*
* WLM media PSM info build prcedure
*
@@ -56,7 +53,7 @@
* \0Office\01\0Office Message\0Office App Name\0"
*/
static char *
-msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr)
+msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr, guint protocol_ver)
{
xmlnode *dataNode,*psmNode,*mediaNode,*guidNode;
char *result;
@@ -82,60 +79,50 @@
}
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;
}
-/* get the CurrentMedia info from the XML string */
+/* get the CurrentMedia info from the XML node */
char *
-msn_get_currentmedia(char *xml_str, gsize len)
+msn_get_currentmedia(xmlnode *payloadNode)
{
- xmlnode *payloadNode, *currentmediaNode;
+ xmlnode *currentmediaNode;
char *currentmedia;
purple_debug_info("msn", "Get CurrentMedia\n");
- payloadNode = xmlnode_from_str(xml_str, len);
- if (!payloadNode) {
- purple_debug_error("msn", "PSM XML parse Error!\n");
- return NULL;
- }
currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia");
if (currentmediaNode == NULL) {
purple_debug_info("msn", "No CurrentMedia Node\n");
- xmlnode_free(payloadNode);
return NULL;
}
currentmedia = xmlnode_get_data(currentmediaNode);
- xmlnode_free(payloadNode);
-
return currentmedia;
}
-/*get the PSM info from the XML string*/
+/* Get the PSM info from the XML node */
char *
-msn_get_psm(char *xml_str, gsize len)
+msn_get_psm(xmlnode *payloadNode)
{
- xmlnode *payloadNode, *psmNode;
+ xmlnode *psmNode;
char *psm;
purple_debug_info("msn", "msn get PSM\n");
- payloadNode = xmlnode_from_str(xml_str, len);
- if (!payloadNode) {
- purple_debug_error("msn", "PSM XML parse Error!\n");
- return NULL;
- }
psmNode = xmlnode_get_child(payloadNode, "PSM");
if (psmNode == NULL) {
purple_debug_info("msn", "No PSM status Node\n");
- xmlnode_free(payloadNode);
return NULL;
}
psm = xmlnode_get_data(psmNode);
- xmlnode_free(payloadNode);
-
return psm;
}
@@ -175,14 +162,12 @@
/* set the MSN's PSM info,Currently Read from the status Line
* Thanks for Cris Code
*/
-void
+static void
msn_set_psm(MsnSession *session)
{
PurpleAccount *account;
PurplePresence *presence;
PurpleStatus *status;
- MsnCmdProc *cmdproc;
- MsnTransaction *trans;
char *payload;
const char *statusline;
gchar *statusline_stripped, *media = NULL;
@@ -191,7 +176,6 @@
g_return_if_fail(session->notification != NULL);
account = session->account;
- cmdproc = session->notification->cmdproc;
/* Get the PSM string from Purple's Status Line */
presence = purple_account_get_presence(account);
@@ -202,13 +186,11 @@
statusline_stripped = purple_markup_strip_html(statusline);
media = create_media_string(presence);
g_free(session->psm);
- session->psm = msn_build_psm(statusline_stripped, media, NULL);
+ session->psm = msn_build_psm(statusline_stripped, media, session->protocol_ver >= 16 ? session->guid : NULL, session->protocol_ver);
payload = session->psm;
- purple_debug_misc("msn", "Sending UUX command with payload: %s\n", payload);
- trans = msn_transaction_new(cmdproc, "UUX", "%" G_GSIZE_FORMAT, strlen(payload));
- msn_transaction_set_payload(trans, payload, strlen(payload));
- msn_cmdproc_send_trans(cmdproc, trans);
+
+ msn_notification_send_uux(session, payload);
g_free(statusline_stripped);
g_free(media);
@@ -219,6 +201,7 @@
{
PurpleAccount *account;
MsnCmdProc *cmdproc;
+ MsnTransaction *trans;
MsnUser *user;
MsnObject *msnobj;
const char *state_text;
@@ -256,11 +239,16 @@
if (!session->logged_in)
return;
+ msn_set_psm(session);
+
msnobj = msn_user_get_object(user);
if (msnobj == NULL)
{
- msn_cmdproc_send(cmdproc, "CHG", "%s %u", state_text, caps);
+ if (session->protocol_ver >= 16)
+ trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u 0", state_text, caps, MSN_CLIENT_ID_EXT_CAPS);
+ else
+ trans = msn_transaction_new(cmdproc, "CHG", "%s %u", state_text, caps);
}
else
{
@@ -268,12 +256,17 @@
msnobj_str = msn_object_to_string(msnobj);
- msn_cmdproc_send(cmdproc, "CHG", "%s %u %s", state_text,
- caps, purple_url_encode(msnobj_str));
+ if (session->protocol_ver >= 16)
+ trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u %s", state_text,
+ caps, MSN_CLIENT_ID_EXT_CAPS, purple_url_encode(msnobj_str));
+ else
+ trans = msn_transaction_new(cmdproc, "CHG", "%s %u %s", state_text,
+ caps, purple_url_encode(msnobj_str));
g_free(msnobj_str);
}
- msn_set_psm(session);
+
+ msn_cmdproc_send_trans(cmdproc, trans);
}
const char *
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/state.h
--- a/libpurple/protocols/msn/state.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/state.h Wed Jun 02 20:08:53 2010 +0000
@@ -58,13 +58,11 @@
const char *msn_state_get_text(MsnAwayType state);
-void msn_set_psm(MsnSession *session);
+/* Get the CurrentMedia info from the XML node */
+char *msn_get_currentmedia(xmlnode *payloadNode);
-/* Get the CurrentMedia info from the XML string */
-char *msn_get_currentmedia(char *xml_str, gsize len);
-
-/*get the PSM info from the XML string*/
-char *msn_get_psm(char *xml_str, gsize len);
+/* Get the PSM info from the XML node */
+char *msn_get_psm(xmlnode *payloadNode);
MsnAwayType msn_state_from_account(PurpleAccount *account);
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/switchboard.c
--- a/libpurple/protocols/msn/switchboard.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/switchboard.c Wed Jun 02 20:08:53 2010 +0000
@@ -252,6 +252,12 @@
return;
}
+ /* Don't add ourselves either... */
+ if (g_str_equal(passport, purple_account_get_username(account))) {
+ g_free(passport);
+ return;
+ }
+
swboard->users = g_list_prepend(swboard->users, passport);
swboard->current_users++;
swboard->empty = FALSE;
@@ -274,7 +280,7 @@
PURPLE_CBFLAGS_NONE, TRUE);
msn_servconn_set_idle_timeout(swboard->servconn, 0);
}
- else if (swboard->current_users > 1 || swboard->total_users > 1)
+ else if (swboard->current_users > 1)
{
msn_servconn_set_idle_timeout(swboard->servconn, 0);
if (swboard->conv == NULL ||
@@ -514,7 +520,7 @@
body_enc = g_markup_escape_text(body_str, -1);
g_free(body_str);
- format = msn_message_get_attr(msg, "X-MMS-IM-Format");
+ 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 : "");
@@ -973,6 +979,7 @@
MsnTransaction *trans;
MsnCmdProc *cmdproc;
PurpleAccount *account;
+ char *username;
cmdproc = servconn->cmdproc;
g_return_if_fail(cmdproc != NULL);
@@ -981,24 +988,33 @@
swboard = cmdproc->data;
g_return_if_fail(swboard != NULL);
+ if (servconn->session->protocol_ver >= 16)
+ username = g_strdup_printf("%s;{%s}",
+ purple_account_get_username(account),
+ servconn->session->guid);
+ else
+ username = g_strdup(purple_account_get_username(account));
+
if (msn_switchboard_is_invited(swboard))
{
swboard->empty = FALSE;
trans = msn_transaction_new(cmdproc, "ANS", "%s %s %s",
- purple_account_get_username(account),
+ username,
swboard->auth_key, swboard->session_id);
}
else
{
trans = msn_transaction_new(cmdproc, "USR", "%s %s",
- purple_account_get_username(account),
+ username,
swboard->auth_key);
}
msn_transaction_set_error_cb(trans, ans_usr_error);
msn_transaction_set_data(trans, swboard);
msn_cmdproc_send_trans(cmdproc, trans);
+
+ g_free(username);
}
static void
@@ -1216,8 +1232,11 @@
!swboard->session->connected)
{
MsnCmdProc *cmdproc;
+ MsnTransaction *trans;
cmdproc = swboard->cmdproc;
- msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL);
+ trans = msn_transaction_new(cmdproc, "OUT", NULL);
+ msn_transaction_set_saveable(trans, FALSE);
+ msn_cmdproc_send_trans(cmdproc, trans);
msn_switchboard_destroy(swboard);
}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/sync.c
--- a/libpurple/protocols/msn/sync.c Wed Jun 02 02:36:24 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/**
- * @file sync.c MSN list synchronization functions
- *
- * 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 02111-1301 USA
- */
-#include "msn.h"
-#include "sync.h"
-#include "state.h"
-
-static MsnTable *cbs_table;
-
-static void
-blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
- PurpleConnection *gc = cmdproc->session->account->gc;
- const char *list_name;
-
- list_name = cmd->params[0];
-
- if (!g_ascii_strcasecmp(list_name, "AL"))
- {
- /*
- * If the current setting is AL, messages from users who
- * are not in BL will be delivered.
- *
- * In other words, deny some.
- */
- gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
- }
- else
- {
- /* If the current setting is BL, only messages from people
- * who are in the AL will be delivered.
- *
- * In other words, permit some.
- */
- gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
- }
-}
-
-static void
-prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
- MsnSession *session = cmdproc->session;
- const char *type, *value;
-
- type = cmd->params[0];
- value = cmd->params[1];
-
- if (cmd->param_count == 2)
- {
- if (!strcmp(type, "PHH"))
- msn_user_set_home_phone(session->user, purple_url_decode(value));
- else if (!strcmp(type, "PHW"))
- msn_user_set_work_phone(session->user, purple_url_decode(value));
- else if (!strcmp(type, "PHM"))
- msn_user_set_mobile_phone(session->user, purple_url_decode(value));
- }
- else
- {
- if (!strcmp(type, "PHH"))
- msn_user_set_home_phone(session->user, NULL);
- else if (!strcmp(type, "PHW"))
- msn_user_set_work_phone(session->user, NULL);
- else if (!strcmp(type, "PHM"))
- msn_user_set_mobile_phone(session->user, NULL);
- }
-}
-
-static void
-lsg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
- MsnSession *session = cmdproc->session;
- const char *name;
- const char *group_id;
-
- group_id = cmd->params[0];
- name = purple_url_decode(cmd->params[1]);
-
- msn_group_new(session->userlist, group_id, name);
-
- /* HACK */
- if (group_id == 0)
- {
- /* Group of ungroupped buddies */
- if (session->sync->total_users == 0)
- {
- cmdproc->cbs_table = session->sync->old_cbs_table;
-
- msn_session_finish_login(session);
-
- msn_sync_destroy(session->sync);
- session->sync = NULL;
- }
- return;
- }
-
- if ((purple_find_group(name)) == NULL)
- {
- PurpleGroup *g = purple_group_new(name);
- purple_blist_add_group(g, NULL);
- }
-}
-
-static void
-lst_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
- MsnSession *session = cmdproc->session;
- char *passport = NULL;
- const char *friend = NULL;
- int list_op;
- MsnUser *user;
-
- passport = cmd->params[0];
- friend = purple_url_decode(cmd->params[1]);
- list_op = atoi(cmd->params[2]);
-
- user = msn_user_new(session->userlist, passport, friend);
-
- msn_userlist_add_user(session->userlist, user);
-
- session->sync->last_user = user;
-
- /* TODO: This can be improved */
-
- if (list_op & MSN_LIST_FL_OP)
- {
- char **c;
- char **tokens;
- const char *group_nums;
- GSList *group_ids;
-
- group_nums = cmd->params[3];
-
- group_ids = NULL;
-
- tokens = g_strsplit(group_nums, ",", -1);
-
- for (c = tokens; *c != NULL; c++)
- {
- group_ids = g_slist_append(group_ids, *c);
- }
-
-
- msn_got_lst_user(session, user, list_op, group_ids);
-
- g_strfreev(tokens);
- g_slist_free(group_ids);
- }
- else
- {
- msn_got_lst_user(session, user, list_op, NULL);
- }
-
- session->sync->num_users++;
-
- if (session->sync->num_users == session->sync->total_users)
- {
- cmdproc->cbs_table = session->sync->old_cbs_table;
-
- msn_session_finish_login(session);
-
- msn_sync_destroy(session->sync);
- session->sync = NULL;
- }
-}
-
-static void
-bpr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
- MsnSync *sync = cmdproc->session->sync;
- const char *type, *value;
- MsnUser *user;
-
- user = sync->last_user;
-
- g_return_if_fail(user != NULL);
-
- type = cmd->params[0];
- value = cmd->params[1];
-
- if (value)
- {
- if (!strcmp(type, "MOB"))
- {
- if (!strcmp(value, "Y"))
- user->mobile = TRUE;
- }
- else if (!strcmp(type, "PHH"))
- msn_user_set_home_phone(user, purple_url_decode(value));
- else if (!strcmp(type, "PHW"))
- msn_user_set_work_phone(user, purple_url_decode(value));
- else if (!strcmp(type, "PHM"))
- msn_user_set_mobile_phone(user, purple_url_decode(value));
- }
-}
-
-void
-msn_sync_init(void)
-{
- cbs_table = msn_table_new();
-
- /* Syncing */
- msn_table_add_cmd(cbs_table, NULL, "GTC", NULL);
- msn_table_add_cmd(cbs_table, NULL, "BLP", blp_cmd);
- msn_table_add_cmd(cbs_table, NULL, "PRP", prp_cmd);
- msn_table_add_cmd(cbs_table, NULL, "LSG", lsg_cmd);
- msn_table_add_cmd(cbs_table, NULL, "LST", lst_cmd);
- msn_table_add_cmd(cbs_table, NULL, "BPR", bpr_cmd);
-}
-
-void
-msn_sync_end(void)
-{
- msn_table_destroy(cbs_table);
-}
-
-MsnSync *
-msn_sync_new(MsnSession *session)
-{
- MsnSync *sync;
-
- sync = g_new0(MsnSync, 1);
-
- sync->session = session;
- sync->cbs_table = cbs_table;
-
- return sync;
-}
-
-void
-msn_sync_destroy(MsnSync *sync)
-{
- g_free(sync);
-}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/sync.h
--- a/libpurple/protocols/msn/sync.h Wed Jun 02 02:36:24 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/**
- * @file sync.h MSN list synchronization functions
- *
- * 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 02111-1301 USA
- */
-#ifndef MSN_SYNC_H
-#define MSN_SYNC_H
-
-typedef struct _MsnSync MsnSync;
-
-#include "session.h"
-#include "table.h"
-#include "user.h"
-
-struct _MsnSync
-{
- MsnSession *session;
- MsnTable *cbs_table;
-
- /*
- * TODO: What is the intended purpose of old_cbs_table? Nothing
- * sets it and it is only read in two places.
- */
- MsnTable *old_cbs_table;
-
- int num_users;
- int total_users;
- int num_groups;
- int total_groups;
- MsnUser *last_user;
-};
-
-void msn_sync_init(void);
-void msn_sync_end(void);
-
-MsnSync *msn_sync_new(MsnSession *session);
-void msn_sync_destroy(MsnSync *sync);
-
-#endif /* MSN_SYNC_H */
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/table.h
--- a/libpurple/protocols/msn/table.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/table.h Wed Jun 02 20:08:53 2010 +0000
@@ -34,20 +34,60 @@
struct _MsnTable
{
- GHashTable *cmds;
- GHashTable *msgs;
- GHashTable *errors;
+ GHashTable *cmds; /**< Callbacks that manage command response. */
+ GHashTable *msgs; /**< Callbacks that manage incoming messages. */
+ GHashTable *errors; /**< Callbacks that manage command errors. */
- GHashTable *async;
- GHashTable *fallback;
+ GHashTable *async; /**< Callbacks that manage incoming asyncronous messages. */
+ /* TODO: Does this one is really needed? */
+ GHashTable *fallback; /**< Fallback callback. */
};
+/**
+ * Create a new instance of a MsnTable which map commands, errors and messages
+ * with callbacks that will handle it.
+ *
+ * @return A new MsnTable.
+ */
MsnTable *msn_table_new(void);
+
+/**
+ * Destroy a MsnTable.
+ *
+ * @param table The MsnTable to be destroyed.
+ */
void msn_table_destroy(MsnTable *table);
+/**
+ * Relate an incomming command from server with a callback able to handle
+ * the event.
+ *
+ * @param table The MsnTable.
+ * @param command If NULL this add an incoming asyncronous command set in answer.
+ * Else, the command sent.
+ * @param answer The server answer to 'command'. If 'command' is NULL,
+ * the asyncronous command sent by the server.
+ * @param cb Callback to handle this event.
+ */
void msn_table_add_cmd(MsnTable *table, char *command, char *answer,
MsnTransCb cb);
+
+/**
+ * Set a callback to handle incoming command errors.
+ *
+ * @param table The MsnTable.
+ * @param answer Incoming command with error.
+ * @param cb Callback to handle this error.
+ */
void msn_table_add_error(MsnTable *table, char *answer, MsnErrorCb cb);
+
+/**
+ * Relate a message Content-type with a callback able to handle it.
+ *
+ * @param table The MsnTable.
+ * @param type The Message Content-Type.
+ * @param cb Callback to handle this Content-type.
+ */
void msn_table_add_msg_type(MsnTable *table, char *type, MsnMsgTypeCb cb);
#endif /* MSN_TABLE_H */
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/transaction.c
--- a/libpurple/protocols/msn/transaction.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/transaction.c Wed Jun 02 20:08:53 2010 +0000
@@ -37,6 +37,7 @@
trans->cmdproc = cmdproc;
trans->command = g_strdup(command);
+ trans->saveable = TRUE;
if (format != NULL)
{
@@ -96,8 +97,10 @@
if (trans->params != NULL)
str = g_strdup_printf("%s %u %s\r\n", trans->command, trans->trId, trans->params);
+ else if (trans->saveable)
+ str = g_strdup_printf("%s %u\r\n", trans->command, trans->trId);
else
- str = g_strdup_printf("%s %u\r\n", trans->command, trans->trId);
+ str = g_strdup_printf("%s\r\n", trans->command);
return str;
}
@@ -175,6 +178,14 @@
}
void
+msn_transaction_set_saveable(MsnTransaction *trans, gboolean saveable)
+{
+ g_return_if_fail(trans != NULL);
+
+ trans->saveable = saveable;
+}
+
+void
msn_transaction_add_cb(MsnTransaction *trans, char *answer,
MsnTransCb cb)
{
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/transaction.h
--- a/libpurple/protocols/msn/transaction.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/transaction.h Wed Jun 02 20:08:53 2010 +0000
@@ -40,7 +40,9 @@
struct _MsnTransaction
{
MsnCmdProc *cmdproc;
- unsigned int trId;
+
+ gboolean saveable; /**< Whether to save this transaction in the history */
+ unsigned int trId; /**< The ID of this transaction, if it's being saved */
char *command;
char *params;
@@ -74,6 +76,7 @@
const char *payload, int payload_len);
void msn_transaction_set_data(MsnTransaction *trans, void *data);
void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn);
+void msn_transaction_set_saveable(MsnTransaction *trans, gboolean saveable);
void msn_transaction_add_cb(MsnTransaction *trans, char *answer,
MsnTransCb cb);
void msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb);
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/user.c
--- a/libpurple/protocols/msn/user.c Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/user.c Wed Jun 02 20:08:53 2010 +0000
@@ -25,6 +25,13 @@
#include "user.h"
#include "slp.h"
+static void free_user_endpoint(MsnUserEndpoint *data)
+{
+ g_free(data->id);
+ g_free(data->name);
+ g_free(data);
+}
+
/*new a user object*/
MsnUser *
msn_user_new(MsnUserList *userlist, const char *passport,
@@ -48,6 +55,11 @@
{
g_return_if_fail(user != NULL);
+ while (user->endpoints != NULL) {
+ free_user_endpoint(user->endpoints->data);
+ user->endpoints = g_slist_delete_link(user->endpoints, user->endpoints);
+ }
+
if (user->clientcaps != NULL)
g_hash_table_destroy(user->clientcaps);
@@ -186,6 +198,9 @@
{
g_return_val_if_fail(user != NULL, FALSE);
+ if (user == user->userlist->session->user)
+ return FALSE;
+
if (user->friendly_name && name && (!strcmp(user->friendly_name, name) ||
!strcmp(user->passport, name)))
return FALSE;
@@ -217,6 +232,47 @@
}
void
+msn_user_set_endpoint_data(MsnUser *user, const char *input, MsnUserEndpoint *newep)
+{
+ MsnUserEndpoint *ep;
+ char *endpoint;
+ GSList *l;
+
+ g_return_if_fail(user != NULL);
+ g_return_if_fail(input != NULL);
+
+ endpoint = g_ascii_strdown(input, -1);
+
+ for (l = user->endpoints; l; l = l->next) {
+ ep = l->data;
+ if (g_str_equal(ep->id, endpoint)) {
+ /* We have info about this endpoint! */
+
+ g_free(endpoint);
+
+ if (newep == NULL) {
+ /* Delete it and exit */
+ user->endpoints = g_slist_delete_link(user->endpoints, l);
+ free_user_endpoint(ep);
+ return;
+ }
+
+ /* Break out of our loop and update it */
+ break;
+ }
+ }
+ if (l == NULL) {
+ /* Need to add a new endpoint */
+ ep = g_new0(MsnUserEndpoint, 1);
+ ep->id = endpoint;
+ user->endpoints = g_slist_prepend(user->endpoints, ep);
+ }
+
+ ep->clientid = newep->clientid;
+ ep->extcaps = newep->extcaps;
+}
+
+void
msn_user_set_op(MsnUser *user, MsnListOp list_op)
{
g_return_if_fail(user != NULL);
@@ -406,6 +462,14 @@
}
void
+msn_user_set_extcaps(MsnUser *user, guint extcaps)
+{
+ g_return_if_fail(user != NULL);
+
+ user->extcaps = extcaps;
+}
+
+void
msn_user_set_network(MsnUser *user, MsnNetwork network)
{
g_return_if_fail(user != NULL);
@@ -423,7 +487,7 @@
user->msnobj = obj;
- if (user->list_op & MSN_LIST_FL_OP)
+ if (user != user->userlist->session->user && user->list_op & MSN_LIST_FL_OP)
msn_queue_buddy_icon_request(user);
}
@@ -496,6 +560,39 @@
return user->clientid;
}
+guint
+msn_user_get_extcaps(const MsnUser *user)
+{
+ g_return_val_if_fail(user != NULL, 0);
+
+ return user->extcaps;
+}
+
+MsnUserEndpoint *
+msn_user_get_endpoint_data(MsnUser *user, const char *input)
+{
+ char *endpoint;
+ GSList *l;
+ MsnUserEndpoint *ep;
+
+ g_return_val_if_fail(user != NULL, NULL);
+ g_return_val_if_fail(input != NULL, NULL);
+
+ endpoint = g_ascii_strdown(input, -1);
+
+ for (l = user->endpoints; l; l = l->next) {
+ ep = l->data;
+ if (g_str_equal(ep->id, endpoint)) {
+ g_free(endpoint);
+ return ep;
+ }
+ }
+
+ g_free(endpoint);
+
+ return NULL;
+}
+
MsnObject *
msn_user_get_object(const MsnUser *user)
{
@@ -520,3 +617,18 @@
return user->invite_message;
}
+gboolean
+msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap)
+{
+ g_return_val_if_fail(user != NULL, FALSE);
+
+ if (endpoint != NULL) {
+ MsnUserEndpoint *ep = msn_user_get_endpoint_data(user, endpoint);
+ if (ep != NULL)
+ return (ep->clientid & capability) && (ep->extcaps & extcap);
+ else
+ return FALSE;
+ }
+
+ return (user->clientid & capability) && (user->extcaps & extcap);
+}
diff -r 320337ee96ad -r 562498203fe8 libpurple/protocols/msn/user.h
--- a/libpurple/protocols/msn/user.h Wed Jun 02 02:36:24 2010 +0000
+++ b/libpurple/protocols/msn/user.h Wed Jun 02 20:08:53 2010 +0000
@@ -83,6 +83,7 @@
char *friendly_name; /**< The friendly name. */
char *uid; /*< User ID */
+ GSList *endpoints; /*< Endpoint-specific data */
const char *status; /**< The state of the user. */
char *statusline; /**< The state of the user. */
@@ -102,6 +103,7 @@
GHashTable *clientcaps; /**< The client's capabilities. */
guint clientid; /**< The client's ID */
+ guint extcaps; /**< The client's extended capabilities */
MsnNetwork networkid; /**< The user's network */
@@ -116,6 +118,18 @@
char *invite_message; /**< Invite message of user request */
};
+/**
+ * A specific user endpoint.
+ */
+typedef struct MsnUserEndpoint {
+ char *id; /**< The client's endpoint ID */
+ char *name; /**< The client's endpoint's name */
+ int type; /**< The client's endpoint type */
+ guint clientid; /**< The client's ID */
+ guint extcaps; /**< The client's extended capabilites */
+
+} MsnUserEndpoint;
+
/**************************************************************************
** @name User API *
**************************************************************************/
@@ -252,6 +266,16 @@
void msn_user_set_uid(MsnUser *user, const char *uid);
/**
+ * Sets endpoint data for a user.
+ *
+ * @param user The user.
+ * @param endpoint The endpoint.
+ * @param data The endpoint data.
+ */
+void
+msn_user_set_endpoint_data(MsnUser *user, const char *endpoint, MsnUserEndpoint *data);
+
+/**
* Sets the client id for a user.
*
* @param user The user.
@@ -260,6 +284,14 @@
void msn_user_set_clientid(MsnUser *user, guint clientid);
/**
+ * Sets the client id for a user.
+ *
+ * @param user The user.
+ * @param extcaps The client's extended capabilities.
+ */
+void msn_user_set_extcaps(MsnUser *user, guint extcaps);
+
+/**
* Sets the network id for a user.
*
* @param user The user.
@@ -346,6 +378,17 @@
const char *msn_user_get_mobile_phone(const MsnUser *user);
/**
+ * Gets endpoint data for a user.
+ *
+ * @param user The user.
+ * @param endpoint The endpoint.
+ *
+ * @return The user's endpoint data.
+ */
+MsnUserEndpoint *
+msn_user_get_endpoint_data(MsnUser *user, const char *endpoint);
+
+/**
* Returns the client id for a user.
*
* @param user The user.
@@ -355,6 +398,15 @@
guint msn_user_get_clientid(const MsnUser *user);
/**
+ * Returns the extended capabilities for a user.
+ *
+ * @param user The user.
+ *
+ * @return The user's extended capabilities.
+ */
+guint msn_user_get_extcaps(const MsnUser *user);
+
+/**
* Returns the network id for a user.
*
* @param user The user.
@@ -398,11 +450,24 @@
/**
* check to see if user is Yahoo User
*/
-gboolean msn_user_is_yahoo(PurpleAccount *account ,const char *name);
+gboolean msn_user_is_yahoo(PurpleAccount *account, const char *name);
void msn_user_set_op(MsnUser *user, MsnListOp list_op);
void msn_user_unset_op(MsnUser *user, MsnListOp list_op);
+/**
+ * Checks whether a user is capable of some task.
+ *
+ * @param user The user.
+ * @param endpoint The endpoint. Can be @NULL to check overall capabilities.
+ * @param capability The capability (including client version).
+ * @param extcap The extended capability.
+ *
+ * @return Whether the user supports the capability.
+ */
+gboolean
+msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap);
+
/*@}*/
#endif /* MSN_USER_H */
diff -r 320337ee96ad -r 562498203fe8 po/POTFILES.in
--- a/po/POTFILES.in Wed Jun 02 02:36:24 2010 +0000
+++ b/po/POTFILES.in Wed Jun 02 20:08:53 2010 +0000
@@ -106,7 +106,6 @@
libpurple/protocols/jabber/usernick.c
libpurple/protocols/jabber/xdata.c
libpurple/protocols/msn/contact.c
-libpurple/protocols/msn/dialog.c
libpurple/protocols/msn/error.c
libpurple/protocols/msn/group.h
libpurple/protocols/msn/msg.c