Mercurial > pidgin.yaz
changeset 31732:7c320e4c8d8c
propagate from branch 'im.pidgin.pidgin' (head 240af8944798738f4310d3fcc8f2bc9ff33c2797)
to branch 'im.pidgin.pidgin.mxit' (head d4d924811e4a96c620a632e02edaaaddd8b60820)
author | andrew.victor@mxit.com |
---|---|
date | Tue, 07 Dec 2010 16:58:46 +0000 |
parents | 0bbe0d78db27 (diff) c7f0decf419b (current diff) |
children | ed057c543e9e |
files | ChangeLog |
diffstat | 24 files changed, 489 insertions(+), 195 deletions(-) [+] |
line wrap: on
line diff
--- 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:
--- 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);
--- 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);
--- 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 @@ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\ "<IsMigration>false</IsMigration>"\ - "<PartnerScenario>Timer</PartnerScenario>"\ + "<PartnerScenario></PartnerScenario>"\ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ @@ -427,6 +429,37 @@ "</soap:Body>"\ "</soap:Envelope>" +/* Update Contact Annotations */ +#define MSN_CONTACT_ANNOTATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" +#define MSN_CONTACT_ANNOTATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario></PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>EMPTY</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<contacts>"\ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<propertiesChanged>Annotation</propertiesChanged>"\ + "</Contact>"\ + "</contacts>"\ + "</ABContactUpdate>"\ + "</soap:Body>"\ +"</soap:Envelope>" + /******************************************************* * 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);
--- 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,
--- 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;
--- 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.
--- 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);
--- 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);
--- 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;
--- 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; }
--- 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);
--- 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.
--- 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;
--- 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)) {
--- 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) {
--- 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)
--- 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),
--- 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,
--- 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 \
--- 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; }