# HG changeset patch
# User andrew.victor@mxit.com
# Date 1291741126 0
# Node ID 7c320e4c8d8c1c057896ea31fca0bdc4f9036e00
# Parent 0bbe0d78db2787e6448e68633258c6eb1b08830e# Parent c7f0decf419b303dbedb449ad7ba47e08e3112c9
propagate from branch 'im.pidgin.pidgin' (head 240af8944798738f4310d3fcc8f2bc9ff33c2797)
to branch 'im.pidgin.pidgin.mxit' (head d4d924811e4a96c620a632e02edaaaddd8b60820)
diff -r c7f0decf419b -r 7c320e4c8d8c ChangeLog
--- a/ChangeLog Tue Nov 30 07:07:42 2010 +0000
+++ b/ChangeLog Tue Dec 07 16:58:46 2010 +0000
@@ -10,11 +10,17 @@
of smileys, display the text representation of the smiley properly
when it contains HTML-escapable characters (e.g. "<3" was previously
displayed as "<3").
+ * Drop dependency on GdkGC and use Cairo instead.
+ * New UI hack to assist in first-time setup of Facebook accounts.
libpurple:
* Fix multipart parsing when '=' is included in the boundary for
purple_mime_document_parse. (Jakub Adam) (#11598)
+ AIM and ICQ:
+ * Buddies who unset their status message will now be correctly shown
+ without a message in your buddy list. (#12988)
+
Gadu-Gadu:
* Updated our bundled libgadu and minimum requirement for external
libgadu to 1.9.0. (#12789)
@@ -24,6 +30,13 @@
disconnected.
* Allow full-size display names, by not escaping (most) non-English
characters. (#8508)
+ * Fix receiving messages from users on Yahoo and other federated
+ services. (#13022)
+ * Correctly remove old endpoints from the list when they sign out.
+ * Add option to disable connections from multiple locations. (#13017)
+
+ XMPP:
+ * Terminate Jingle sessions with unsupported content types. (#13048)
version 2.7.7 (11/23/2010):
General:
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/jabber/jingle/jingle.c
--- a/libpurple/protocols/jabber/jingle/jingle.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/jabber/jingle/jingle.c Tue Dec 07 16:58:46 2010 +0000
@@ -98,7 +98,8 @@
if (pending_content == NULL) {
purple_debug_error("jingle",
"Error parsing \"content-add\" content.\n");
- /* XXX: send error here */
+ jabber_iq_send(jingle_session_terminate_packet(session,
+ "unsupported-applications"));
} else {
jingle_session_add_pending_content(session,
pending_content);
@@ -127,7 +128,8 @@
g_free(local_senders);
} else {
purple_debug_error("jingle", "content_modify: unknown content\n");
- /* XXX: send error */
+ jabber_iq_send(jingle_session_terminate_packet(session,
+ "unknown-applications"));
}
}
}
@@ -176,7 +178,8 @@
jingle_session_find_content(session, name, creator);
if (parsed_content == NULL) {
purple_debug_error("jingle", "Error parsing content\n");
- /* XXX: send error */
+ jabber_iq_send(jingle_session_terminate_packet(session,
+ "unsupported-applications"));
} else {
jingle_content_handle_action(parsed_content, content,
JINGLE_DESCRIPTION_INFO);
@@ -206,7 +209,8 @@
jingle_session_find_content(session, name, creator);
if (parsed_content == NULL) {
purple_debug_error("jingle", "Error parsing content\n");
- /* XXX: send error */
+ jabber_iq_send(jingle_session_terminate_packet(session,
+ "unsupported-applications"));
} else {
jingle_content_handle_action(parsed_content, content,
JINGLE_SESSION_ACCEPT);
@@ -230,7 +234,8 @@
JingleContent *parsed_content = jingle_content_parse(content);
if (parsed_content == NULL) {
purple_debug_error("jingle", "Error parsing content\n");
- /* XXX: send error */
+ jabber_iq_send(jingle_session_terminate_packet(session,
+ "unsupported-applications"));
} else {
jingle_session_add_content(session, parsed_content);
jingle_content_handle_action(parsed_content, content,
@@ -281,7 +286,8 @@
jingle_session_find_content(session, name, creator);
if (parsed_content == NULL) {
purple_debug_error("jingle", "Error parsing content\n");
- /* XXX: send error */
+ jabber_iq_send(jingle_session_terminate_packet(session,
+ "unsupported-applications"));
} else {
jingle_content_handle_action(parsed_content, content,
JINGLE_TRANSPORT_INFO);
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/contact.c
--- a/libpurple/protocols/msn/contact.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/contact.c Tue Dec 07 16:58:46 2010 +0000
@@ -41,7 +41,8 @@
"ContactSave",
"MessengerPendingList",
"ContactMsgrAPI",
- "BlockUnblock"
+ "BlockUnblock",
+ "Timer"
};
const char *MsnMemberRole[] =
@@ -189,6 +190,8 @@
strcat(buf, "Renaming Group,");
if (action & MSN_UPDATE_INFO)
strcat(buf, "Updating Contact Info,");
+ if (action & MSN_ANNOTATE_USER)
+ strcat(buf, "Annotating Contact,");
return buf;
}
@@ -709,8 +712,9 @@
uid = xmlnode_get_data(contactId);
type = xmlnode_get_data(contactType);
- /*setup the Display Name*/
+ /* Find out our settings */
if (type && !strcmp(type, "Me")) {
+ /* setup the Display Name */
if (purple_connection_get_display_name(pc) == NULL) {
char *friendly = NULL;
if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
@@ -719,6 +723,23 @@
friendly ? purple_url_decode(friendly) : NULL);
g_free(friendly);
}
+
+ for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
+ annotation;
+ annotation = xmlnode_get_next_twin(annotation)) {
+ char *name, *value;
+ name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
+ value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
+ if (!strcmp(name, "MSN.IM.MPOP")) {
+ if (!value || atoi(value) != 0)
+ session->enable_mpop = TRUE;
+ else
+ session->enable_mpop = FALSE;
+ }
+ g_free(name);
+ g_free(value);
+ }
+
continue; /* Not adding own account as buddy to buddylist */
}
@@ -1497,6 +1518,101 @@
xmlnode_insert_child(contact, contact_info);
xmlnode_insert_child(contact, changes);
+ xmlnode_insert_data(xmlnode_get_child(state->body,
+ "Header/ABApplicationHeader/PartnerScenario"),
+ MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
+
+ if (user) {
+ xmlnode *contactId = xmlnode_new_child(contact, "contactId");
+ msn_callback_state_set_uid(state, user->uid);
+ xmlnode_insert_data(contactId, state->uid, -1);
+ } else {
+ xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
+ xmlnode_insert_data(contactType, "Me", -1);
+ }
+
+ msn_contact_request(state);
+}
+
+static void
+msn_annotate_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+ gpointer data)
+{
+ MsnCallbackState *state = (MsnCallbackState *)data;
+ xmlnode *fault;
+
+ /* We don't know how to respond to this faultcode, so log it */
+ fault = xmlnode_get_child(resp->xml, "Body/Fault");
+ if (fault != NULL) {
+ char *fault_str = xmlnode_to_str(fault, NULL);
+ purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+ msn_contact_operation_str(state->action), fault_str);
+ g_free(fault_str);
+ return;
+ }
+
+ purple_debug_info("msn", "Contact annotated successfully\n");
+}
+
+/* Update a contact's annotations */
+void
+msn_annotate_contact(MsnSession *session, const char *passport, ...)
+{
+ va_list params;
+ MsnCallbackState *state;
+ xmlnode *contact;
+ xmlnode *contact_info;
+ xmlnode *annotations;
+ MsnUser *user = NULL;
+
+ g_return_if_fail(passport != NULL);
+
+ if (strcmp(passport, "Me") != 0) {
+ user = msn_userlist_find_user(session->userlist, passport);
+ if (!user)
+ return;
+ }
+
+ contact_info = xmlnode_new("contactInfo");
+ annotations = xmlnode_new_child(contact_info, "annotations");
+
+ va_start(params, passport);
+ while (TRUE) {
+ const char *name;
+ const char *value;
+ xmlnode *a, *n, *v;
+
+ name = va_arg(params, const char *);
+ if (!name)
+ break;
+
+ value = va_arg(params, const char *);
+ if (!value)
+ break;
+
+ a = xmlnode_new_child(annotations, "Annotation");
+ n = xmlnode_new_child(a, "Name");
+ xmlnode_insert_data(n, name, -1);
+ v = xmlnode_new_child(a, "Value");
+ xmlnode_insert_data(v, value, -1);
+ }
+ va_end(params);
+
+ state = msn_callback_state_new(session);
+
+ state->body = xmlnode_from_str(MSN_CONTACT_ANNOTATE_TEMPLATE, -1);
+ state->action = MSN_ANNOTATE_USER;
+ state->post_action = MSN_CONTACT_ANNOTATE_SOAP_ACTION;
+ state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+ state->cb = msn_annotate_contact_read_cb;
+
+ xmlnode_insert_data(xmlnode_get_child(state->body,
+ "Header/ABApplicationHeader/PartnerScenario"),
+ MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
+
+ contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
+ xmlnode_insert_child(contact, contact_info);
+
if (user) {
xmlnode *contactId = xmlnode_new_child(contact, "contactId");
msn_callback_state_set_uid(state, user->uid);
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/contact.h
--- a/libpurple/protocols/msn/contact.h Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/contact.h Tue Dec 07 16:58:46 2010 +0000
@@ -36,7 +36,8 @@
MSN_ADD_GROUP = 0x10,
MSN_DEL_GROUP = 0x20,
MSN_RENAME_GROUP = 0x40,
- MSN_UPDATE_INFO = 0x80
+ MSN_UPDATE_INFO = 0x80,
+ MSN_ANNOTATE_USER = 0x100
} MsnCallbackAction;
typedef enum
@@ -52,7 +53,8 @@
MSN_PS_SAVE_CONTACT,
MSN_PS_PENDING_LIST,
MSN_PS_CONTACT_API,
- MSN_PS_BLOCK_UNBLOCK
+ MSN_PS_BLOCK_UNBLOCK,
+ MSN_PS_TIMER
} MsnSoapPartnerScenario;
#include "session.h"
@@ -408,7 +410,7 @@
""\
"" MSN_APPLICATION_ID ""\
"false"\
- "Timer"\
+ ""\
""\
""\
"false"\
@@ -427,6 +429,37 @@
""\
""
+/* Update Contact Annotations */
+#define MSN_CONTACT_ANNOTATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate"
+#define MSN_CONTACT_ANNOTATE_TEMPLATE ""\
+""\
+ ""\
+ ""\
+ "" MSN_APPLICATION_ID ""\
+ "false"\
+ ""\
+ ""\
+ ""\
+ "false"\
+ "EMPTY"\
+ ""\
+ ""\
+ ""\
+ ""\
+ "00000000-0000-0000-0000-000000000000"\
+ ""\
+ ""\
+ "Annotation"\
+ ""\
+ ""\
+ ""\
+ ""\
+""
+
/*******************************************************
* Add/Delete contact from lists SOAP actions
*******************************************************/
@@ -686,6 +719,8 @@
/* contact SOAP operations */
void msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value);
+void msn_annotate_contact(MsnSession *session, const char *passport, ...) G_GNUC_NULL_TERMINATED;
+
void msn_add_contact(MsnSession *session, MsnCallbackState *state,
const char *passport);
void msn_delete_contact(MsnSession *session, MsnUser *user);
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/msn.c
--- a/libpurple/protocols/msn/msn.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/msn.c Tue Dec 07 16:58:46 2010 +0000
@@ -250,7 +250,7 @@
MsnSession *session;
MsnTransaction *trans;
PurpleAccount *account;
- char real_alias[BUDDY_ALIAS_MAXLEN+1];
+ char real_alias[BUDDY_ALIAS_MAXLEN + 1];
struct public_alias_closure *closure;
session = purple_connection_get_protocol_data(pc);
@@ -258,53 +258,25 @@
account = purple_connection_get_account(pc);
if (alias && *alias) {
- int i = 0;
- while (isspace(*alias))
- alias++;
-
- for (; *alias && i < BUDDY_ALIAS_MAXLEN; alias++) {
- if (*alias == '%') {
- if (i > BUF_LEN - 4)
- break;
- real_alias[i++] = '%';
- real_alias[i++] = '2';
- real_alias[i++] = '5';
- } else if (*alias == ' ') {
- if (i > BUF_LEN - 4)
- break;
- real_alias[i++] = '%';
- real_alias[i++] = '2';
- real_alias[i++] = '0';
+ if (!msn_encode_spaces(alias, real_alias, BUDDY_ALIAS_MAXLEN + 1)) {
+ if (failure_cb) {
+ struct public_alias_closure *closure =
+ g_new0(struct public_alias_closure, 1);
+ closure->account = account;
+ closure->failure_cb = failure_cb;
+ purple_timeout_add(0, set_public_alias_length_error, closure);
} else {
- real_alias[i++] = *alias;
+ purple_notify_error(pc, NULL,
+ _("Your new MSN friendly name is too long."),
+ NULL);
}
+ return;
}
- while (i && isspace(real_alias[i - 1]))
- i--;
-
- real_alias[i] = '\0';
+ if (real_alias[0] == '\0')
+ strcpy(real_alias, purple_account_get_username(account));
} else
- real_alias[0] = '\0';
-
- if (*alias) {
- if (failure_cb) {
- struct public_alias_closure *closure =
- g_new0(struct public_alias_closure, 1);
- closure->account = account;
- closure->failure_cb = failure_cb;
- purple_timeout_add(0, set_public_alias_length_error, closure);
- } else {
- purple_notify_error(pc, NULL,
- _("Your new MSN friendly name is too long."),
- NULL);
- }
- return;
- }
-
- if (real_alias[0] == '\0') {
strcpy(real_alias, purple_account_get_username(account));
- }
closure = g_new0(struct public_alias_closure, 1);
closure->account = account;
@@ -617,6 +589,67 @@
}
static void
+enable_mpop_cb(PurpleConnection *pc)
+{
+ MsnSession *session = purple_connection_get_protocol_data(pc);
+
+ purple_debug_info("msn", "Enabling MPOP\n");
+
+ session->enable_mpop = TRUE;
+ msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL);
+
+ purple_prpl_got_account_actions(purple_connection_get_account(pc));
+}
+
+static void
+disable_mpop_cb(PurpleConnection *pc)
+{
+ PurpleAccount *account = purple_connection_get_account(pc);
+ MsnSession *session = purple_connection_get_protocol_data(pc);
+ GSList *l;
+
+ purple_debug_info("msn", "Disabling MPOP\n");
+
+ session->enable_mpop = FALSE;
+ msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "0", NULL);
+
+ for (l = session->user->endpoints; l; l = l->next) {
+ MsnUserEndpoint *ep = l->data;
+ char *user;
+
+ if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
+ /* Don't kick myself */
+ continue;
+
+ purple_debug_info("msn", "Disconnecting Endpoint %s\n", ep->id);
+
+ user = g_strdup_printf("%s;%s", purple_account_get_username(account), ep->id);
+ msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
+ g_free(user);
+ }
+
+ purple_prpl_got_account_actions(account);
+}
+
+static void
+msn_show_set_mpop(PurplePluginAction *action)
+{
+ PurpleConnection *pc;
+
+ pc = (PurpleConnection *)action->context;
+
+ purple_request_action(pc, NULL, _("Allow multiple logins?"),
+ _("Do you want to allow or disallow connecting from "
+ "multiple locations simultaneously?"),
+ PURPLE_DEFAULT_ACTION_NONE,
+ purple_connection_get_account(pc), NULL, NULL,
+ pc, 3,
+ _("Allow"), G_CALLBACK(enable_mpop_cb),
+ _("Disallow"), G_CALLBACK(disable_mpop_cb),
+ _("Cancel"), NULL);
+}
+
+static void
msn_show_set_home_phone(PurplePluginAction *action)
{
PurpleConnection *gc;
@@ -1201,7 +1234,7 @@
m = g_list_append(m, act);
m = g_list_append(m, NULL);
- if (session->protocol_ver >= 16)
+ if (session->enable_mpop && session->protocol_ver >= 16)
{
act = purple_plugin_action_new(_("View Locations..."),
msn_show_locations);
@@ -1228,6 +1261,10 @@
m = g_list_append(m, act);
#endif
+ act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."),
+ msn_show_set_mpop);
+ m = g_list_append(m, act);
+
act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."),
msn_show_set_mobile_pages);
m = g_list_append(m, act);
@@ -3085,6 +3122,11 @@
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
option);
+ option = purple_account_option_bool_new(_("Allow connecting from multiple locations"),
+ "mpop", TRUE);
+ prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+ option);
+
purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL,
PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
"prpl-msn", msn_cmd_nudge,
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/msnutils.c
--- a/libpurple/protocols/msn/msnutils.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/msnutils.c Tue Dec 07 16:58:46 2010 +0000
@@ -182,29 +182,40 @@
* We need this because we're only supposed to encode spaces in the font
* names. purple_url_encode() isn't acceptable.
*/
-static const char *
-encode_spaces(const char *str)
+gboolean
+msn_encode_spaces(const char *str, char *buf, size_t len)
{
- static char buf[BUF_LEN];
- const char *c;
- char *d;
+ char *nonspace = buf;
- g_return_val_if_fail(str != NULL, NULL);
+ while (isspace(*str))
+ str++;
- for (c = str, d = buf; *c != '\0'; c++)
- {
- if (*c == ' ')
- {
- *d++ = '%';
- *d++ = '2';
- *d++ = '0';
+ for (; *str && len > 1; str++) {
+ if (*str == '%') {
+ if (len < 4)
+ break;
+ *buf++ = '%';
+ *buf++ = '2';
+ *buf++ = '5';
+ len -= 3;
+ nonspace = buf;
+ } else if (*str == ' ') {
+ if (len < 4)
+ break;
+ *buf++ = '%';
+ *buf++ = '2';
+ *buf++ = '0';
+ len -= 3;
+ } else {
+ *buf++ = *str;
+ len--;
+ nonspace = buf;
}
- else
- *d++ = *c;
}
- *d = '\0';
- return buf;
+ *nonspace = '\0';
+
+ return (*str == '\0');
}
/*
@@ -223,6 +234,7 @@
const char *c;
char *msg;
char *fontface = NULL;
+ char fontface_encoded[BUF_LEN];
char fonteffect[5];
char fontcolor[7];
char direction = '0';
@@ -449,8 +461,9 @@
if (fontface == NULL)
fontface = g_strdup("Segoe UI");
+ msn_encode_spaces(fontface, fontface_encoded, BUF_LEN);
*attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c",
- encode_spaces(fontface),
+ fontface_encoded,
fonteffect, fontcolor, direction);
*message = msg;
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/msnutils.h
--- a/libpurple/protocols/msn/msnutils.h Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/msnutils.h Tue Dec 07 16:58:46 2010 +0000
@@ -33,6 +33,18 @@
char *rand_guid(void);
/**
+ * Encodes the spaces in a string
+ *
+ * @param str The string to be encoded.
+ * @param buf The buffer to hold the encoded string.
+ * @param len The maximum length (including NUL) to put in @buf.
+ *
+ * @return Whether @str was able to fit in @buf.
+ */
+gboolean
+msn_encode_spaces(const char *str, char *buf, size_t len);
+
+/**
* Parses the MSN message formatting into a format compatible with Purple.
*
* @param mime The mime header with the formatting.
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/notification.c
--- a/libpurple/protocols/msn/notification.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/notification.c Tue Dec 07 16:58:46 2010 +0000
@@ -387,7 +387,10 @@
* command and we are processing it */
if (cmd->payload == NULL) {
cmdproc->last_cmd->payload_cb = msg_cmd_post;
- cmd->payload_len = atoi(cmd->params[3]);
+ if (cmdproc->session->protocol_ver >= 16)
+ cmd->payload_len = atoi(cmd->params[5]);
+ else
+ cmd->payload_len = atoi(cmd->params[3]);
} else {
g_return_if_fail(cmd->payload_cb != NULL);
@@ -1548,40 +1551,55 @@
static void
parse_user_endpoints(MsnUser *user, xmlnode *payloadNode)
{
+ MsnSession *session;
xmlnode *epNode, *capsNode;
MsnUserEndpoint data;
const char *id;
char *caps, *tmp;
+ gboolean is_me;
purple_debug_info("msn", "Get EndpointData\n");
+ session = user->userlist->session;
+ is_me = (user == session->user);
+
+ msn_user_clear_endpoints(user);
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
+ /* Disconnect others, if MPOP is disabled */
+ if (is_me
+ && !session->enable_mpop
+ && strncasecmp(id + 1, session->guid, 36) != 0) {
+ purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
+
+ tmp = g_strdup_printf("%s;%s", user->passport, id);
+ msn_notification_send_uun(session, tmp, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
+ g_free(tmp);
+ } else {
+ 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;
-
- g_free(caps);
-
- } else {
- data.clientid = 0;
- data.extcaps = 0;
+ }
+
+ msn_user_set_endpoint_data(user, id, &data);
}
-
- msn_user_set_endpoint_data(user, id, &data);
}
- /* Need to shortcut this check, probably... */
- if (user == user->userlist->session->user) {
+ if (is_me && session->enable_mpop) {
for (epNode = xmlnode_get_child(payloadNode, "PrivateEndpointData");
epNode;
epNode = xmlnode_get_next_twin(epNode)) {
@@ -1939,12 +1957,6 @@
/* This isn't an official message. */
return;
- 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_header_value(msg, "sid")) != NULL)
{
g_free(session->passport_info.sid);
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/session.c
--- a/libpurple/protocols/msn/session.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/session.c Tue Dec 07 16:58:46 2010 +0000
@@ -49,6 +49,7 @@
session->oim = msn_oim_new(session);
session->protocol_ver = 0;
+ session->enable_mpop = TRUE; /* Default only */
session->guid = rand_guid();
@@ -103,7 +104,6 @@
g_free(session->blocked_text);
#endif
- g_free(session->passport_info.kv);
g_free(session->passport_info.sid);
g_free(session->passport_info.mspauth);
g_free(session->passport_info.client_ip);
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/session.h
--- a/libpurple/protocols/msn/session.h Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/session.h Tue Dec 07 16:58:46 2010 +0000
@@ -79,12 +79,13 @@
MsnLoginStep login_step; /**< The current step in the login process. */
- gboolean connected;
- gboolean logged_in; /**< A temporal flag to ignore local buddy list adds. */
+ gboolean connected:1;
+ gboolean logged_in:1; /**< A temporal flag to ignore local buddy list adds. */
+ gboolean destroying:1; /**< A flag that states if the session is being destroyed. */
+ gboolean http_method:1;
+ gboolean enable_mpop:1; /**< Use Multiple Points of Presence? */
int adl_fqy; /**< A count of ADL/FQY so status is only changed once. */
guint login_timeout; /**< Timeout to force status change if ADL/FQY fail. */
- gboolean destroying; /**< A flag that states if the session is being destroyed. */
- gboolean http_method;
MsnNotification *notification;
MsnNexus *nexus;
@@ -105,7 +106,6 @@
struct
{
- char *kv;
char *sid;
char *mspauth;
unsigned long sl;
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/switchboard.c
--- a/libpurple/protocols/msn/switchboard.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/switchboard.c Tue Dec 07 16:58:46 2010 +0000
@@ -743,7 +743,10 @@
ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
{
purple_debug_misc("msn", "get UBM...\n");
- cmd->payload_len = atoi(cmd->params[3]);
+ if (cmdproc->session->protocol_ver >= 16)
+ cmd->payload_len = atoi(cmd->params[5]);
+ else
+ cmd->payload_len = atoi(cmd->params[3]);
cmdproc->last_cmd->payload_cb = msg_cmd_post;
}
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/user.c
--- a/libpurple/protocols/msn/user.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/user.c Tue Dec 07 16:58:46 2010 +0000
@@ -305,6 +305,22 @@
}
void
+msn_user_clear_endpoints(MsnUser *user)
+{
+ MsnUserEndpoint *ep;
+ GSList *l;
+
+ g_return_if_fail(user != NULL);
+
+ for (l = user->endpoints; l; l = g_slist_delete_link(l, l)) {
+ ep = l->data;
+ free_user_endpoint(ep);
+ }
+
+ user->endpoints = NULL;
+}
+
+void
msn_user_set_op(MsnUser *user, MsnListOp list_op)
{
g_return_if_fail(user != NULL);
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/msn/user.h
--- a/libpurple/protocols/msn/user.h Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/msn/user.h Tue Dec 07 16:58:46 2010 +0000
@@ -286,6 +286,14 @@
msn_user_set_endpoint_data(MsnUser *user, const char *endpoint, MsnUserEndpoint *data);
/**
+ * Clears all endpoint data for a user.
+ *
+ * @param user The user.
+ */
+void
+msn_user_clear_endpoints(MsnUser *user);
+
+/**
* Sets the client id for a user.
*
* @param user The user.
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/oscar/family_locate.c
--- a/libpurple/protocols/oscar/family_locate.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/oscar/family_locate.c Tue Dec 07 16:58:46 2010 +0000
@@ -1043,7 +1043,7 @@
} else {
byte_stream_advance(bs, length2);
outinfo->status_len = 0;
- outinfo->status = g_strdup("");
+ outinfo->status = NULL;
outinfo->status_encoding = NULL;
}
} break;
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/protocols/oscar/oscar.c
--- a/libpurple/protocols/oscar/oscar.c Tue Nov 30 07:07:42 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.c Tue Dec 07 16:58:46 2010 +0000
@@ -1366,7 +1366,7 @@
const char *status_id;
va_list ap;
aim_userinfo_t *info;
- char *message = NULL;
+ char *message;
char *itmsurl = NULL;
gc = od->gc;
@@ -1453,16 +1453,13 @@
purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
}
- /* Empty status means we should unset the status message. NULL status means we should keep it from the previous active status.
- * Same goes for itmsurl (which is available only for the "available" status).
- */
- if (info->status != NULL) {
- message = (info->status_len > 0) ? oscar_encoding_to_utf8(info->status_encoding, info->status, info->status_len) : NULL;
- } else if (previous_status != NULL) {
- message = g_strdup(purple_status_get_attr_string(previous_status, "message"));
- }
+ message = (info->status && info->status_len > 0)
+ ? oscar_encoding_to_utf8(info->status_encoding, info->status, info->status_len)
+ : NULL;
if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) {
+ /* TODO: If itmsurl is NULL, does that mean the URL has been
+ cleared? Or does it mean the URL should remain unchanged? */
if (info->itmsurl != NULL) {
itmsurl = (info->itmsurl_len > 0) ? oscar_encoding_to_utf8(info->itmsurl_encoding, info->itmsurl, info->itmsurl_len) : NULL;
} else if (previous_status != NULL && purple_status_is_available(previous_status)) {
diff -r c7f0decf419b -r 7c320e4c8d8c libpurple/xmlnode.c
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/gtkaccount.c
--- a/pidgin/gtkaccount.c Tue Nov 30 07:07:42 2010 +0000
+++ b/pidgin/gtkaccount.c Tue Dec 07 16:58:46 2010 +0000
@@ -559,10 +559,14 @@
/* Google Talk default domain hackery! */
menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
item = gtk_menu_get_active(GTK_MENU(menu));
- if (value == NULL && g_object_get_data(G_OBJECT(item), "fake") &&
+ if (value == NULL && g_object_get_data(G_OBJECT(item), "fakegoogle") &&
!strcmp(purple_account_user_split_get_text(split), _("Domain")))
value = "gmail.com";
+ if (value == NULL && g_object_get_data(G_OBJECT(item), "fakefacebook") &&
+ !strcmp(purple_account_user_split_get_text(split), _("Domain")))
+ value = "chat.facebook.com";
+
if (value != NULL)
gtk_entry_set_text(GTK_ENTRY(entry), value);
}
@@ -758,7 +762,7 @@
{
PurpleAccountOption *option;
PurpleAccount *account;
- GtkWidget *vbox, *check, *entry, *combo;
+ GtkWidget *vbox, *check, *entry, *combo, *menu, *item;
GList *list, *node;
gint i, idx, int_value;
GtkListStore *model;
@@ -797,6 +801,9 @@
gtk_label_new_with_mnemonic(_("Ad_vanced")), 1);
gtk_widget_show(vbox);
+ menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
+ item = gtk_menu_get_active(GTK_MENU(menu));
+
for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
{
option = (PurpleAccountOption *)l->data;
@@ -911,6 +918,10 @@
model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
+ if (g_object_get_data(G_OBJECT(item), "fakefacebook") &&
+ !strcmp(opt_entry->setting, "connection_security"))
+ str_value = "opportunistic_tls";
+
/* Loop through list of PurpleKeyValuePair items */
for (node = list; node != NULL; node = node->next) {
if (node->data != NULL) {
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/gtkimhtml.c
--- a/pidgin/gtkimhtml.c Tue Nov 30 07:07:42 2010 +0000
+++ b/pidgin/gtkimhtml.c Tue Dec 07 16:58:46 2010 +0000
@@ -756,7 +756,7 @@
GtkTextIter start, end, cur;
int buf_x, buf_y;
GdkRectangle visible_rect;
- GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window));
+ cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window));
GdkColor gcolor;
gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect);
@@ -774,16 +774,16 @@
if (GTK_IMHTML(widget)->edit.background) {
gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor);
- gdk_gc_set_rgb_fg_color(gc, &gcolor);
+ gdk_cairo_set_source_color(cr, &gcolor);
} else {
- gdk_gc_set_rgb_fg_color(gc, &(widget->style->base[GTK_WIDGET_STATE(widget)]));
+ gdk_cairo_set_source_color(cr, &(widget->style->base[GTK_WIDGET_STATE(widget)]));
}
- gdk_draw_rectangle(event->window,
- gc,
- TRUE,
- visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height);
- g_object_unref(G_OBJECT(gc));
+ cairo_rectangle(cr,
+ visible_rect.x, visible_rect.y,
+ visible_rect.width, visible_rect.height);
+ cairo_fill(cr);
+ cairo_destroy(cr);
if (GTK_WIDGET_CLASS (parent_class)->expose_event)
return (* GTK_WIDGET_CLASS (parent_class)->expose_event)
@@ -854,12 +854,12 @@
if (!gdk_color_parse(tmp, &gcolor))
gdk_color_parse("white", &gcolor);
}
- gdk_gc_set_rgb_fg_color(gc, &gcolor);
-
- gdk_draw_rectangle(event->window,
- gc,
- TRUE,
- rect.x, rect.y, rect.width, rect.height);
+ gdk_cairo_set_source_color(cr, &gcolor);
+
+ cairo_rectangle(cr,
+ rect.x, rect.y,
+ rect.width, rect.height);
+ cairo_fill(cr);
gtk_text_iter_backward_char(&cur); /* go back one, in case the end is the begining is the end
* note that above, we always moved cur ahead by at least
* one character */
@@ -874,7 +874,7 @@
!gtk_text_iter_begins_tag(&cur, NULL));
}
- g_object_unref(G_OBJECT(gc));
+ cairo_destroy(cr);
if (GTK_WIDGET_CLASS (parent_class)->expose_event)
return (* GTK_WIDGET_CLASS (parent_class)->expose_event)
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/gtkutils.c
--- a/pidgin/gtkutils.c Tue Nov 30 07:07:42 2010 +0000
+++ b/pidgin/gtkutils.c Tue Dec 07 16:58:46 2010 +0000
@@ -684,7 +684,7 @@
GdkPixbuf *pixbuf = NULL;
GtkSizeGroup *sg;
GList *p;
- const char *gtalk_name = NULL;
+ const char *gtalk_name = NULL, *facebook_name = NULL;
int i;
aop_menu = g_malloc0(sizeof(AopMenu));
@@ -693,8 +693,10 @@
gtk_widget_show(aop_menu->menu);
sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- if (purple_find_prpl("prpl-jabber"))
+ if (purple_find_prpl("prpl-jabber")) {
gtalk_name = _("Google Talk");
+ facebook_name = _("Facebook (XMPP)");
+ }
for (p = purple_plugins_get_protocols(), i = 0;
p != NULL;
@@ -712,7 +714,7 @@
gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
- g_object_set_data(G_OBJECT(item), "fake", GINT_TO_POINTER(1));
+ g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1));
if (pixbuf)
g_object_unref(pixbuf);
@@ -721,6 +723,25 @@
i++;
}
+ if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) {
+ char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
+ "16", "facebook.png", NULL);
+ GtkWidget *item;
+
+ pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+ g_free(filename);
+
+ gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+ item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol"));
+ g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1));
+
+ if (pixbuf)
+ g_object_unref(pixbuf);
+
+ facebook_name = NULL;
+ i++;
+ }
+
pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/gtkwhiteboard.c
--- a/pidgin/gtkwhiteboard.c Tue Nov 30 07:07:42 2010 +0000
+++ b/pidgin/gtkwhiteboard.c Tue Dec 07 16:58:46 2010 +0000
@@ -282,6 +282,9 @@
/* Clear graphical memory */
if(gtkwb->pixmap)
{
+ cairo_t *cr = g_object_get_data(G_OBJECT(gtkwb->pixmap), "cairo-context");
+ if (cr)
+ cairo_destroy(cr);
g_object_unref(gtkwb->pixmap);
gtkwb->pixmap = NULL;
}
@@ -353,25 +356,29 @@
static gboolean pidgin_whiteboard_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{
PidginWhiteboard *gtkwb = (PidginWhiteboard*)data;
-
GdkPixmap *pixmap = gtkwb->pixmap;
+ cairo_t *cr;
- if(pixmap)
+ if (pixmap) {
+ cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
+ if (cr)
+ cairo_destroy(cr);
g_object_unref(pixmap);
+ }
pixmap = gdk_pixmap_new(widget->window,
widget->allocation.width,
widget->allocation.height,
-1);
-
gtkwb->pixmap = pixmap;
- gdk_draw_rectangle(pixmap,
- widget->style->white_gc,
- TRUE,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+ cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
+ g_object_set_data(G_OBJECT(pixmap), "cairo-context", cr);
+ gdk_cairo_set_source_color(cr, &widget->style->white);
+ cairo_rectangle(cr,
+ 0, 0,
+ widget->allocation.width, widget->allocation.height);
+ cairo_fill(cr);
return TRUE;
}
@@ -380,13 +387,15 @@
{
PidginWhiteboard *gtkwb = (PidginWhiteboard*)(data);
GdkPixmap *pixmap = gtkwb->pixmap;
+ cairo_t *cr;
- gdk_draw_drawable(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- pixmap,
- event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
+ cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+ gdk_cairo_set_source_pixmap(cr, pixmap, 0, 0);
+ cairo_rectangle(cr,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ cairo_fill(cr);
+ cairo_destroy(cr);
return FALSE;
}
@@ -586,50 +595,24 @@
GtkWidget *widget = gtkwb->drawing_area;
GdkPixmap *pixmap = gtkwb->pixmap;
- GdkRectangle update_rect;
-
- GdkGC *gfx_con = gdk_gc_new(pixmap);
+ cairo_t *gfx_con = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
GdkColor col;
- update_rect.x = x - size / 2;
- update_rect.y = y - size / 2;
- update_rect.width = size;
- update_rect.height = size;
-
/* Interpret and convert color */
pidgin_whiteboard_rgb24_to_rgb48(color, &col);
- gdk_gc_set_rgb_fg_color(gfx_con, &col);
- /* gdk_gc_set_rgb_bg_color(gfx_con, &col); */
+ gdk_cairo_set_source_color(gfx_con, &col);
- /* NOTE 5 is a size constant for now... this is because of how poorly the
- * gdk_draw_arc draws small circles
- */
- if(size < 5)
- {
- /* Draw a rectangle/square */
- gdk_draw_rectangle(pixmap,
- gfx_con,
- TRUE,
- update_rect.x, update_rect.y,
- update_rect.width, update_rect.height);
- }
- else
- {
- /* Draw a circle */
- gdk_draw_arc(pixmap,
- gfx_con,
- TRUE,
- update_rect.x, update_rect.y,
- update_rect.width, update_rect.height,
- 0, FULL_CIRCLE_DEGREES);
- }
+ /* Draw a circle */
+ cairo_arc(gfx_con,
+ x, y,
+ size / 2.0,
+ 0.0, 2.0 * M_PI);
+ cairo_fill(gfx_con);
gtk_widget_queue_draw_area(widget,
- update_rect.x, update_rect.y,
- update_rect.width, update_rect.height);
-
- g_object_unref(G_OBJECT(gfx_con));
+ x - size / 2, y - size / 2,
+ size, size);
}
/* Uses Bresenham's algorithm (as provided by Wikipedia) */
@@ -720,13 +703,14 @@
PidginWhiteboard *gtkwb = wb->ui_data;
GdkPixmap *pixmap = gtkwb->pixmap;
GtkWidget *drawing_area = gtkwb->drawing_area;
+ cairo_t *cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
- gdk_draw_rectangle(pixmap,
- drawing_area->style->white_gc,
- TRUE,
- 0, 0,
- drawing_area->allocation.width,
- drawing_area->allocation.height);
+ gdk_cairo_set_source_color(cr, &drawing_area->style->white);
+ cairo_rectangle(cr,
+ 0, 0,
+ drawing_area->allocation.width,
+ drawing_area->allocation.height);
+ cairo_fill(cr);
gtk_widget_queue_draw_area(drawing_area,
0, 0,
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/pixmaps/Makefile.am
--- a/pidgin/pixmaps/Makefile.am Tue Nov 30 07:07:42 2010 +0000
+++ b/pidgin/pixmaps/Makefile.am Tue Dec 07 16:58:46 2010 +0000
@@ -225,6 +225,7 @@
PROTOCOLS_16 = \
protocols/16/aim.png \
protocols/16/bonjour.png \
+ protocols/16/facebook.png \
protocols/16/gadu-gadu.png \
protocols/16/google-talk.png \
protocols/16/novell.png \
@@ -281,6 +282,7 @@
PROTOCOLS_22 = \
protocols/22/aim.png \
protocols/22/bonjour.png \
+ protocols/22/facebook.png \
protocols/22/gadu-gadu.png \
protocols/22/google-talk.png \
protocols/22/novell.png \
@@ -299,6 +301,7 @@
PROTOCOLS_48 = \
protocols/48/aim.png \
protocols/48/bonjour.png \
+ protocols/48/facebook.png \
protocols/48/gadu-gadu.png \
protocols/48/novell.png \
protocols/48/icq.png \
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/pixmaps/protocols/16/facebook.png
Binary file pidgin/pixmaps/protocols/16/facebook.png has changed
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/pixmaps/protocols/22/facebook.png
Binary file pidgin/pixmaps/protocols/22/facebook.png has changed
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/pixmaps/protocols/48/facebook.png
Binary file pidgin/pixmaps/protocols/48/facebook.png has changed
diff -r c7f0decf419b -r 7c320e4c8d8c pidgin/plugins/markerline.c
--- a/pidgin/plugins/markerline.c Tue Nov 30 07:07:42 2010 +0000
+++ b/pidgin/plugins/markerline.c Tue Dec 07 16:58:46 2010 +0000
@@ -79,12 +79,14 @@
if (y >= event->area.y)
{
GdkColor red = {0, 0xffff, 0, 0};
- GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window));
+ cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window));
- gdk_gc_set_rgb_fg_color(gc, &red);
- gdk_draw_line(event->window, gc,
- 0, y, visible_rect.width, y);
- g_object_unref(G_OBJECT(gc));
+ gdk_cairo_set_source_color(cr, &red);
+ cairo_move_to(cr, 0.0, y + 0.5);
+ cairo_rel_line_to(cr, visible_rect.width, 0.0);
+ cairo_set_line_width(cr, 1.0);
+ cairo_stroke(cr);
+ cairo_destroy(cr);
}
return FALSE;
}