Mercurial > pidgin
changeset 25712:3c9af6627767
propagate from branch 'im.pidgin.pidgin' (head 3da4a61feea56ff40dc5fdba355a1057c675a32d)
to branch 'im.pidgin.cpw.malu.xmpp.attention' (head 9acd8cb5119a41bd4ffda63a46297be07f0c3aca)
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Fri, 06 Feb 2009 22:49:01 +0000 |
parents | 8f5a63aebdb6 (diff) f931efdddfbb (current diff) |
children | fa22ec9d1e84 |
files | libpurple/protocols/jabber/jabber.c |
diffstat | 40 files changed, 636 insertions(+), 520 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Thu Jan 29 20:36:14 2009 +0000 +++ b/COPYRIGHT Fri Feb 06 22:49:01 2009 +0000 @@ -314,6 +314,7 @@ Ted Percival Eduardo Pérez Matt Perry +Luke Petre Diego Petten Nathan Peterson Sebastián E. Peyrott
--- a/ChangeLog Thu Jan 29 20:36:14 2009 +0000 +++ b/ChangeLog Fri Feb 06 22:49:01 2009 +0000 @@ -2,17 +2,29 @@ version 2.5.5 (??/??/????): libpurple: + * Fix a crash when removing an account with an unknown protocol id. + * Beta support for SSL connections for AIM and ICQ accounts. To + enable, check the "Use SSL" option from the Advanced tab when + editing your AIM or ICQ account. (Paul Aurich) + * Fix a memory leak in SILC. (Luke Petre) + + ICQ: + * Fix retrieval of status messages from users of ICQ 6.x, Miranda, and + other libpurple clients. (Daniel Ljungborg) + * Change client ID to match ICQ Basic 14.34.3096. This fixes publishing + of buddy icons and available messages. + * Properly publish status messages for statuses other than Available. + ICQ 6.x users can now see these status messages. (Daniel Ljungborg) + + MSN: * Fix transfer of buddy icons, custom smileys, and files from the latest Windows Live Messenger 9 official client. (Thomas Gibson-Robinson) - * Fix a crash when removing an account with an unknown protocol id. - * Large (multi-part) messages on MSN are now correctly re-combined. - * Beta support for SSL connections for AIM and ICQ accounts. To - enable, check the "Use SSL" option from the Advanced tab when - editing your AIM or ICQ account. (Paul Aurich) - * Fix retrieval of ICQ status messages from users of ICQ 6.x, Miranda, - and other libpurple clients (fixes with libpurple users only on - statuses other than Available). (Daniel Ljungborg) + * Large (multi-part) messages are now correctly re-combined. + * Federated/Yahoo! buddies should now stop creating sync issues at + every signin. You may need to remove duplicates in the Address + Book. See the FAQ for more information. + * Messages from Yahoo! buddies are no longer silently dropped. Finch: * Allow rebinding keys to change the focused widget (details in the
--- a/ChangeLog.API Thu Jan 29 20:36:14 2009 +0000 +++ b/ChangeLog.API Fri Feb 06 22:49:01 2009 +0000 @@ -6,6 +6,8 @@ * purple_status_type_new now defaults "saveable" to TRUE. This was necessary in order to maintain the current behavior while fixing non-saveable statuses not to be saved. + * xmlnode_get_prefix, xmlnode_to_str and xmlnode_to_formatted_str + now all take a const xmlnode* instead of an xmlnode* version 2.5.4 (01/12/2009): perl:
--- a/ChangeLog.win32 Thu Jan 29 20:36:14 2009 +0000 +++ b/ChangeLog.win32 Fri Feb 06 22:49:01 2009 +0000 @@ -1,3 +1,8 @@ +version 2.5.5 (??/??/2009): + * Remove the "Flash window when chat messages are received" pref from + the Windows Pidgin Options plugin - the Message Notification plugin + does this (and much more). + version 2.5.4 (01/12/2009): * Fix the "Hang on Exit" issue that a number of users encountered. * Updated GTK+ to 2.14.6
--- a/finch/finch.c Thu Jan 29 20:36:14 2009 +0000 +++ b/finch/finch.c Fri Feb 06 22:49:01 2009 +0000 @@ -210,7 +210,7 @@ text = g_strdup_printf(_("%s\n" "Usage: %s [OPTION]...\n\n" " -c, --config=DIR use DIR for config files\n" - " -d, --debug print debugging messages to stdout\n" + " -d, --debug print debugging messages to stderr\n" " -h, --help display this help and exit\n" " -n, --nologin don't automatically login\n" " -v, --version display the current version and exit\n"), DISPLAY_VERSION, name);
--- a/finch/libgnt/gntkeys.c Thu Jan 29 20:36:14 2009 +0000 +++ b/finch/libgnt/gntkeys.c Fri Feb 06 22:49:01 2009 +0000 @@ -163,7 +163,8 @@ (*(text + 2) >= 'A' && *(text + 2) <= 'D')) { /* Apparently this is necessary for urxvt and screen and xterm */ if (strstr(term, "screen") == term || strcmp(term, "rxvt-unicode") == 0 || - strstr(term, "xterm") == term) + strstr(term, "xterm") == term || + strstr(term, "vt100") == term) *(text + 1) = 'O'; } else if (*(unsigned char*)text == 195) { if (*(text + 2) == 0 && strstr(term, "xterm") == term) {
--- a/libpurple/dbus-analyze-functions.py Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/dbus-analyze-functions.py Fri Feb 06 22:49:01 2009 +0000 @@ -497,7 +497,7 @@ # This is a total hack, but self.call is set up before the parameters # are processed, so we can't tell it to pass a parameter by reference. self.call = "%s(%s)" % (self.function.name, - ", ".join(param.name if param.name != "len" else "&len" for param in self.params)) + ", ".join([(param.name, "&len")[param.name == "len"] for param in self.params])) self.cdecls.append("\tgconstpointer %s;" % name) self.ccode.append("\t%s = %s;" % (name, self.call))
--- a/libpurple/network.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/network.c Fri Feb 06 22:49:01 2009 +0000 @@ -74,8 +74,12 @@ /* Mutex for the other global vars */ static GStaticMutex mutex = G_STATIC_MUTEX_INIT; -static gboolean network_initialized; -static HANDLE network_change_handle; +static gboolean network_initialized = FALSE; +static HANDLE network_change_handle = NULL; +static int (WSAAPI *MyWSANSPIoctl) ( + HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, + DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, + LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL; #endif struct _PurpleNetworkListenData { @@ -538,27 +542,28 @@ return FALSE; } +static gboolean _print_debug_msg(gpointer data) { + gchar *msg = data; + purple_debug_warning("network", msg); + g_free(msg); + return FALSE; +} + static gpointer wpurple_network_change_thread(gpointer data) { WSAQUERYSET qs; WSAEVENT *nla_event; - time_t last_trigger = time(NULL); - - int (WSAAPI *MyWSANSPIoctl) ( - HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, - DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, - LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL; - - if (!(MyWSANSPIoctl = (void*) wpurple_find_and_loadproc("ws2_32.dll", "WSANSPIoctl"))) { - g_thread_exit(NULL); - return NULL; - } + time_t last_trigger = time(NULL) - 31; + char buf[4096]; + WSAQUERYSET *res = (LPWSAQUERYSET) buf; + DWORD size; if ((nla_event = WSACreateEvent()) == WSA_INVALID_EVENT) { int errorid = WSAGetLastError(); gchar *msg = g_win32_error_message(errorid); - purple_debug_warning("network", "Couldn't create WSA event. " - "Message: %s (%d).\n", msg, errorid); + purple_timeout_add(0, _print_debug_msg, + g_strdup_printf("Couldn't create WSA event. " + "Message: %s (%d).\n", msg, errorid)); g_free(msg); g_thread_exit(NULL); return NULL; @@ -579,30 +584,26 @@ return NULL; } - memset(&qs, 0, sizeof(WSAQUERYSET)); - qs.dwSize = sizeof(WSAQUERYSET); - qs.dwNameSpace = NS_NLA; - if (WSALookupServiceBegin(&qs, 0, &network_change_handle) == SOCKET_ERROR) { - int errorid = WSAGetLastError(); - gchar *msg = g_win32_error_message(errorid); - purple_debug_warning("network", "Couldn't retrieve NLA SP lookup handle. " - "NLA service is probably not running. Message: %s (%d).\n", - msg, errorid); - g_free(msg); - WSACloseEvent(nla_event); - g_static_mutex_unlock(&mutex); - g_thread_exit(NULL); - return NULL; + if (network_change_handle == NULL) { + memset(&qs, 0, sizeof(WSAQUERYSET)); + qs.dwSize = sizeof(WSAQUERYSET); + qs.dwNameSpace = NS_NLA; + if (WSALookupServiceBegin(&qs, 0, &network_change_handle) == SOCKET_ERROR) { + int errorid = WSAGetLastError(); + gchar *msg = g_win32_error_message(errorid); + purple_timeout_add(0, _print_debug_msg, + g_strdup_printf("Couldn't retrieve NLA SP lookup handle. " + "NLA service is probably not running. Message: %s (%d).\n", + msg, errorid)); + g_free(msg); + WSACloseEvent(nla_event); + g_static_mutex_unlock(&mutex); + g_thread_exit(NULL); + return NULL; + } } g_static_mutex_unlock(&mutex); - /* Make sure at least 30 seconds have elapsed since the last - * notification so we don't peg the cpu if this keeps changing. */ - if ((time(NULL) - last_trigger) < 30) - Sleep(30000); - - last_trigger = time(NULL); - memset(&completion, 0, sizeof(WSACOMPLETION)); completion.Type = NSP_NOTIFY_EVENT; overlapped.hEvent = nla_event; @@ -610,18 +611,34 @@ if (MyWSANSPIoctl(network_change_handle, SIO_NSP_NOTIFY_CHANGE, NULL, 0, NULL, 0, &retLen, &completion) == SOCKET_ERROR) { int errorid = WSAGetLastError(); + if (errorid == WSA_INVALID_HANDLE) { + purple_timeout_add(0, _print_debug_msg, + g_strdup("Invalid NLA handle; resetting.\n")); + g_static_mutex_lock(&mutex); + retval = WSALookupServiceEnd(network_change_handle); + network_change_handle = NULL; + g_static_mutex_unlock(&mutex); + continue; /* WSA_IO_PENDING indicates successful async notification will happen */ - if (errorid != WSA_IO_PENDING) { + } else if (errorid != WSA_IO_PENDING) { gchar *msg = g_win32_error_message(errorid); - purple_debug_warning("network", "Unable to wait for changes. Message: %s (%d).\n", - msg, errorid); + purple_timeout_add(0, _print_debug_msg, + g_strdup_printf("Unable to wait for changes. Message: %s (%d).\n", + msg, errorid)); g_free(msg); } } + /* Make sure at least 30 seconds have elapsed since the last + * notification so we don't peg the cpu if this keeps changing. */ + if ((time(NULL) - last_trigger) < 30) + Sleep(30000); + /* This will block until NLA notifies us */ retval = WaitForSingleObjectEx(nla_event, WSA_INFINITE, TRUE); + last_trigger = time(NULL); + g_static_mutex_lock(&mutex); if (network_initialized == FALSE) { /* Time to die */ @@ -631,8 +648,14 @@ return NULL; } - retval = WSALookupServiceEnd(network_change_handle); - network_change_handle = NULL; + size = sizeof(buf); + while ((retval = WSALookupServiceNext(network_change_handle, 0, &size, res)) == ERROR_SUCCESS) { + /*purple_timeout_add(0, _print_debug_msg, + g_strdup_printf("thread found network '%s'\n", + res->lpszServiceInstanceName ? res->lpszServiceInstanceName : "(NULL)"));*/ + size = sizeof(buf); + } + WSAResetEvent(nla_event); g_static_mutex_unlock(&mutex); @@ -768,11 +791,12 @@ if (cnt < 0) /* Assume there is a network */ current_network_count = 1; /* Don't listen for network changes if we can't tell anyway */ - else - { + else { current_network_count = cnt; - if (!g_thread_create(wpurple_network_change_thread, NULL, FALSE, &err)) - purple_debug_error("network", "Couldn't create Network Monitor thread: %s\n", err ? err->message : ""); + if ((MyWSANSPIoctl = (void*) wpurple_find_and_loadproc("ws2_32.dll", "WSANSPIoctl"))) { + if (!g_thread_create(wpurple_network_change_thread, NULL, FALSE, &err)) + purple_debug_error("network", "Couldn't create Network Monitor thread: %s\n", err ? err->message : ""); + } } #endif @@ -848,10 +872,12 @@ msg, errorid); g_free(msg); } + network_change_handle = NULL; + } g_static_mutex_unlock(&mutex); #endif purple_signal_unregister(purple_network_get_handle(), - "network-configuration-changed"); + "network-configuration-changed"); }
--- a/libpurple/protocols/jabber/data.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/data.c Fri Feb 06 22:49:01 2009 +0000 @@ -200,11 +200,9 @@ } void -jabber_data_parse(JabberStream *js, xmlnode *packet) +jabber_data_parse(JabberStream *js, xmlnode *data_node, const char *who, const char *id) { JabberIq *result = NULL; - const char *who = xmlnode_get_attrib(packet, "from"); - xmlnode *data_node = xmlnode_get_child(packet, "data"); const JabberData *data = jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid")); @@ -213,12 +211,12 @@ result = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_set_attrib(result->node, "to", who); - xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); + xmlnode_set_attrib(result->node, "id", id); xmlnode_insert_child(result->node, item_not_found); } else { result = jabber_iq_new(js, JABBER_IQ_RESULT); xmlnode_set_attrib(result->node, "to", who); - xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); + xmlnode_set_attrib(result->node, "id", id); xmlnode_insert_child(result->node, jabber_data_get_xml_definition(data)); }
--- a/libpurple/protocols/jabber/data.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/data.h Fri Feb 06 22:49:01 2009 +0000 @@ -65,7 +65,8 @@ void jabber_data_associate_remote(JabberData *data); /* handles iq requests */ -void jabber_data_parse(JabberStream *js, xmlnode *packet); +void jabber_data_parse(JabberStream *js, xmlnode *data_node, + const char *who, const char *id); void jabber_data_init(void); void jabber_data_uninit(void);
--- a/libpurple/protocols/jabber/google.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Fri Feb 06 22:49:01 2009 +0000 @@ -144,9 +144,8 @@ } void -jabber_gmail_poke(JabberStream *js, xmlnode *packet) +jabber_gmail_poke(JabberStream *js, const char *type) { - const char *type; xmlnode *query; JabberIq *iq; @@ -154,11 +153,8 @@ if (!purple_account_get_check_mail(js->gc->account)) return; - type = xmlnode_get_attrib(packet, "type"); - - /* Is this an initial incoming mail notification? If so, send a request for more info */ - if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail")) + if (strcmp(type, "set")) return; purple_debug(PURPLE_DEBUG_MISC, "jabber",
--- a/libpurple/protocols/jabber/google.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/google.h Fri Feb 06 22:49:01 2009 +0000 @@ -27,7 +27,7 @@ #include "jabber.h" void jabber_gmail_init(JabberStream *js); -void jabber_gmail_poke(JabberStream *js, xmlnode *node); +void jabber_gmail_poke(JabberStream *js, const char *type); void jabber_google_roster_init(JabberStream *js); void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item);
--- a/libpurple/protocols/jabber/iq.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Fri Feb 06 22:49:01 2009 +0000 @@ -309,7 +309,7 @@ void jabber_iq_parse(JabberStream *js, xmlnode *packet) { JabberCallbackData *jcd; - xmlnode *query, *error, *x; + xmlnode *child, *query, *error, *x; const char *xmlns; const char *type, *id, *from; JabberIqHandler *jih; @@ -371,25 +371,25 @@ } } - if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { - jabber_si_parse(js, packet); + if ((child = xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si"))) { + jabber_si_parse(js, child, from, id); return; } - if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { - jabber_gmail_poke(js, packet); + if (xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { + jabber_gmail_poke(js, type); return; } purple_debug_info("jabber", "jabber_iq_parse\n"); - if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) { - jabber_ping_parse(js, packet); + if (xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) { + jabber_ping_parse(js, from, id); return; } - if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) { - jabber_data_parse(js, packet); + if ((child = xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE))) { + jabber_data_parse(js, child, from, id); return; }
--- a/libpurple/protocols/jabber/jabber.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Feb 06 22:49:01 2009 +0000 @@ -1872,7 +1872,7 @@ type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE), - NULL, FALSE, TRUE, FALSE, + NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, type);
--- a/libpurple/protocols/jabber/ping.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/ping.c Fri Feb 06 22:49:01 2009 +0000 @@ -30,7 +30,7 @@ #include "iq.h" void -jabber_ping_parse(JabberStream *js, xmlnode *packet) +jabber_ping_parse(JabberStream *js, const char *from, const char *id) { JabberIq *iq; @@ -38,9 +38,9 @@ iq = jabber_iq_new(js, JABBER_IQ_RESULT); - xmlnode_set_attrib(iq->node, "to", xmlnode_get_attrib(packet, "from") ); + xmlnode_set_attrib(iq->node, "to", from); - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(iq, id); jabber_iq_send(iq); }
--- a/libpurple/protocols/jabber/ping.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/ping.h Fri Feb 06 22:49:01 2009 +0000 @@ -26,7 +26,8 @@ #include "conversation.h" void jabber_ping_parse(JabberStream *js, - xmlnode *packet); + const char *from, + const char *id); gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid);
--- a/libpurple/protocols/jabber/si.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/si.c Fri Feb 06 22:49:01 2009 +0000 @@ -1182,17 +1182,14 @@ purple_xfer_request(xfer); } -void jabber_si_parse(JabberStream *js, xmlnode *packet) +void jabber_si_parse(JabberStream *js, xmlnode *si, const char *from, const char *id) { JabberSIXfer *jsx; PurpleXfer *xfer; - xmlnode *si, *file, *feature, *x, *field, *option, *value; - const char *stream_id, *filename, *filesize_c, *profile, *from; + xmlnode *file, *feature, *x, *field, *option, *value; + const char *stream_id, *filename, *filesize_c, *profile; size_t filesize = 0; - if(!(si = xmlnode_get_child(packet, "si"))) - return; - if(!(profile = xmlnode_get_attrib(si, "profile")) || strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) return; @@ -1215,7 +1212,7 @@ if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) return; - if(!(from = xmlnode_get_attrib(packet, "from"))) + if(!from) return; /* if they've already sent us this file transfer with the same damn id @@ -1256,7 +1253,7 @@ jsx->js = js; jsx->stream_id = g_strdup(stream_id); - jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jsx->iq_id = g_strdup(id); xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); if (xfer)
--- a/libpurple/protocols/jabber/si.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/jabber/si.h Fri Feb 06 22:49:01 2009 +0000 @@ -27,7 +27,7 @@ #include "jabber.h" void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet); -void jabber_si_parse(JabberStream *js, xmlnode *packet); +void jabber_si_parse(JabberStream *js, xmlnode *si, const char *from, const char *id); PurpleXfer *jabber_si_new_xfer(PurpleConnection *gc, const char *who); void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file);
--- a/libpurple/protocols/msn/contact.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/contact.c Fri Feb 06 22:49:01 2009 +0000 @@ -158,6 +158,113 @@ state->action |= action; } +/*************************************************************** + * General SOAP handling + ***************************************************************/ + +static const char * +msn_contact_operation_str(MsnCallbackAction action) +{ + /* Make sure this is large enough when adding more */ + static char buf[BUF_LEN]; + buf[0] = '\0'; + + if (action & MSN_ADD_BUDDY) + strcat(buf, "Adding Buddy,"); + if (action & MSN_MOVE_BUDDY) + strcat(buf, "Moving Buddy,"); + if (action & MSN_ACCEPTED_BUDDY) + strcat(buf, "Accepted Buddy,"); + if (action & MSN_DENIED_BUDDY) + strcat(buf, "Denied Buddy,"); + if (action & MSN_ADD_GROUP) + strcat(buf, "Adding Group,"); + if (action & MSN_DEL_GROUP) + strcat(buf, "Deleting Group,"); + if (action & MSN_RENAME_GROUP) + strcat(buf, "Renaming Group,"); + if (action & MSN_UPDATE_INFO) + strcat(buf, "Updating Contact Info,"); + + return buf; +} + +static gboolean msn_contact_request(MsnCallbackState *state); + +static void +msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp, + gpointer data) +{ + MsnCallbackState *state = data; + xmlnode *fault; + char *faultcode_str; + + if (resp == NULL) { + purple_debug_error("msn", + "Operation {%s} failed. No response received from server.\n", + msn_contact_operation_str(state->action)); + return; + } + + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + + if (fault == NULL) { + /* No errors */ + if (state->cb) + ((MsnSoapCallback)state->cb)(req, resp, data); + msn_callback_state_free(state); + return; + } + + faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode")); + + if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) { + purple_debug_info("msn", + "Contact Operation {%s} failed because of bad token." + " Updating token now and retrying operation.\n", + msn_contact_operation_str(state->action)); + /* Token has expired, so renew it, and try again later */ + msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS, + (GSourceFunc)msn_contact_request, data); + } + else + { + if (state->cb) { + ((MsnSoapCallback)state->cb)(req, resp, data); + } else { + /* We don't know how to respond to this faultcode, so log it */ + char *str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), str); + g_free(str); + } + msn_callback_state_free(state); + } + + g_free(faultcode_str); +} + +static gboolean +msn_contact_request(MsnCallbackState *state) +{ + if (state->token == NULL) + state->token = xmlnode_get_child(state->body, + "Header/ABAuthHeader/TicketToken"); + /* delete old & replace with new token */ + xmlnode_free(state->token->child); + xmlnode_insert_data(state->token, + msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1); + msn_soap_message_send(state->session, + msn_soap_message_new(state->post_action, xmlnode_copy(state->body)), + MSN_CONTACT_SERVER, state->post_url, FALSE, + msn_contact_request_cb, state); + return FALSE; +} + +/*************************************************************** + * Address Book and Membership List Operations + ***************************************************************/ + /*get MSN member role utility*/ static MsnListId msn_get_memberrole(const char *role) @@ -180,9 +287,10 @@ static void msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { + MsnCallbackState *state = data; if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) { purple_debug_info("msn", "Address Book successfully created!\n"); - msn_get_address_book((MsnSession *)data, MSN_PS_INITIAL, NULL, NULL); + msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL); } else { purple_debug_info("msn", "Address Book creation failed!\n"); } @@ -192,7 +300,7 @@ msn_create_address_book(MsnSession *session) { gchar *body; - gchar *token_str; + MsnCallbackState *state; g_return_if_fail(session != NULL); g_return_if_fail(session->user != NULL); @@ -200,17 +308,15 @@ purple_debug_info("msn", "Creating an Address Book.\n"); - token_str = g_markup_escape_text( - msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1); body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE, - token_str, session->user->passport); - g_free(token_str); + session->user->passport); - msn_soap_message_send(session, - msn_soap_message_new(MSN_ADD_ADDRESSBOOK_SOAP_ACTION, - xmlnode_from_str(body, -1)), - MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE, - msn_create_address_cb, session); + state = msn_callback_state_new(session); + state->body = xmlnode_from_str(body, -1); + state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION; + state->post_url = MSN_ADDRESS_BOOK_POST_URL; + state->cb = msn_create_address_cb; + msn_contact_request(state); g_free(body); } @@ -243,7 +349,7 @@ g_free(name); } } - + purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s, NetworkID: %u\n", node, passport, type, member_id == NULL ? "(null)" : member_id, nid); @@ -362,8 +468,8 @@ msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { - GetContactListCbData *cb_data = data; - MsnSession *session = cb_data->session; + MsnCallbackState *state = data; + MsnSession *session = state->session; g_return_if_fail(session != NULL); @@ -379,7 +485,7 @@ dynamicItemLastChange = purple_account_get_string(session->account, "dynamicItemLastChange", NULL); - if (cb_data->which == MSN_PS_INITIAL) { + if (state->partner_scenario == MSN_PS_INITIAL) { #ifdef MSN_PARTIAL_LISTS /* XXX: this should be enabled when we can correctly do partial syncs with the server. Currently we need to retrieve the whole @@ -390,8 +496,6 @@ #endif } } - - g_free(cb_data); } /*SOAP get contact list*/ @@ -401,8 +505,7 @@ { gchar *body = NULL; gchar *update_str = NULL; - gchar *token_str; - GetContactListCbData cb_data = { session, partner_scenario }; + MsnCallbackState *state; const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario]; purple_debug_misc("msn", "Getting Contact List.\n"); @@ -412,17 +515,16 @@ update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time); } - token_str = g_markup_escape_text( - msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1); body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str, - token_str, update_str ? update_str : ""); - g_free(token_str); + update_str ? update_str : ""); - msn_soap_message_send(session, - msn_soap_message_new(MSN_GET_CONTACT_SOAP_ACTION, - xmlnode_from_str(body, -1)), - MSN_CONTACT_SERVER, MSN_GET_CONTACT_POST_URL, FALSE, - msn_get_contact_list_cb, g_memdup(&cb_data, sizeof(cb_data))); + state = msn_callback_state_new(session); + state->partner_scenario = partner_scenario; + state->body = xmlnode_from_str(body, -1); + state->post_action = MSN_GET_CONTACT_SOAP_ACTION; + state->post_url = MSN_GET_CONTACT_POST_URL; + state->cb = msn_get_contact_list_cb; + msn_contact_request(state); g_free(update_str); g_free(body); @@ -525,7 +627,7 @@ for(contactNode = xmlnode_get_child(node, "Contact"); contactNode; contactNode = xmlnode_get_next_twin(contactNode)) { - xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds, *messenger_user; + xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds; xmlnode *annotation; MsnUser *user; @@ -556,58 +658,52 @@ continue; /* Not adding own account as buddy to buddylist */ } - /* ignore non-messenger contacts */ - if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) { - char *is_messenger_user = xmlnode_get_data(messenger_user); - - if(is_messenger_user && !strcmp(is_messenger_user, "false")) { - g_free(is_messenger_user); - continue; - } - - g_free(is_messenger_user); - } - passportName = xmlnode_get_child(contactInfo, "passportName"); if (passportName == NULL) { xmlnode *emailsNode, *contactEmailNode, *emailNode; xmlnode *messengerEnabledNode; char *msnEnabled; - /*TODO: add it to the none-instant Messenger group and recognize as email Membership*/ - /*Yahoo User?*/ + /*TODO: add it to the non-instant Messenger group and recognize as email Membership*/ + /* Yahoo/Federated User? */ emailsNode = xmlnode_get_child(contactInfo, "emails"); if (emailsNode == NULL) { /*TODO: need to support the Mobile type*/ continue; } for (contactEmailNode = xmlnode_get_child(emailsNode, "ContactEmail"); contactEmailNode; - contactEmailNode = xmlnode_get_next_twin(contactEmailNode) ){ - if (!(messengerEnabledNode = xmlnode_get_child(contactEmailNode, "isMessengerEnabled"))) { - /* XXX: Should this be a continue instead of a break? It seems like it'd cause unpredictable results otherwise. */ - break; - } + contactEmailNode = xmlnode_get_next_twin(contactEmailNode)) { + if (!(messengerEnabledNode = xmlnode_get_child(contactEmailNode, "isMessengerEnabled"))) + continue; msnEnabled = xmlnode_get_data(messengerEnabledNode); - if ((emailNode = xmlnode_get_child(contactEmailNode, "email"))) { - g_free(passport); - passport = xmlnode_get_data(emailNode); - } + if (msnEnabled && !strcmp(msnEnabled, "true")) { + if ((emailNode = xmlnode_get_child(contactEmailNode, "email"))) + passport = xmlnode_get_data(emailNode); - if (msnEnabled && !strcmp(msnEnabled, "true")) { /*Messenger enabled, Get the Passport*/ - purple_debug_info("msn", "AB Yahoo User %s\n", passport ? passport : "(null)"); + purple_debug_info("msn", "AB Yahoo/Federated User %s\n", passport ? passport : "(null)"); g_free(msnEnabled); break; - } else { - /*TODO maybe we can just ignore it in Purple?*/ - purple_debug_info("msn", "AB Other type user\n"); } g_free(msnEnabled); } } else { + xmlnode *messenger_user; + /* ignore non-messenger contacts */ + if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) { + char *is_messenger_user = xmlnode_get_data(messenger_user); + + if (is_messenger_user && !strcmp(is_messenger_user, "false")) { + g_free(is_messenger_user); + continue; + } + + g_free(is_messenger_user); + } + passport = xmlnode_get_data(passportName); } @@ -777,10 +873,8 @@ static void msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { - MsnSession *session = data; - - if (resp == NULL) - return; + MsnCallbackState *state = data; + MsnSession *session = state->session; g_return_if_fail(session != NULL); @@ -809,7 +903,7 @@ const char *dynamicItemLastChange) { char *body, *update_str = NULL; - gchar *token_str; + MsnCallbackState *state; purple_debug_misc("msn", "Getting Address Book\n"); @@ -819,19 +913,16 @@ else if (LastChanged != NULL) update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged); - token_str = g_markup_escape_text( - msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1); body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], - token_str, update_str ? update_str : ""); - g_free(token_str); - msn_soap_message_send(session, - msn_soap_message_new(MSN_GET_ADDRESS_SOAP_ACTION, - xmlnode_from_str(body, -1)), - MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE, - msn_get_address_cb, session); + state = msn_callback_state_new(session); + state->body = xmlnode_from_str(body, -1); + state->post_action = MSN_GET_ADDRESS_SOAP_ACTION; + state->post_url = MSN_ADDRESS_BOOK_POST_URL; + state->cb = msn_get_address_cb; + msn_contact_request(state); g_free(update_str); g_free(body); @@ -841,105 +932,6 @@ * Contact Operations ***************************************************************/ -static const char * -msn_contact_operation_str(MsnCallbackAction action) -{ - /* Make sure this is large enough when adding more */ - static char buf[BUF_LEN]; - buf[0] = '\0'; - - if (action & MSN_ADD_BUDDY) - strcat(buf, "Adding Buddy,"); - if (action & MSN_MOVE_BUDDY) - strcat(buf, "Moving Buddy,"); - if (action & MSN_ACCEPTED_BUDDY) - strcat(buf, "Accepted Buddy,"); - if (action & MSN_DENIED_BUDDY) - strcat(buf, "Denied Buddy,"); - if (action & MSN_ADD_GROUP) - strcat(buf, "Adding Group,"); - if (action & MSN_DEL_GROUP) - strcat(buf, "Deleting Group,"); - if (action & MSN_RENAME_GROUP) - strcat(buf, "Renaming Group,"); - if (action & MSN_UPDATE_INFO) - strcat(buf, "Updating Contact Info,"); - - return buf; -} - -static gboolean msn_contact_request(MsnCallbackState *state); - -static void -msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp, - gpointer data) -{ - MsnCallbackState *state = data; - xmlnode *fault; - char *faultcode_str; - - if (resp == NULL) { - purple_debug_error("msn", - "Operation {%s} failed. No response received from server.\n", - msn_contact_operation_str(state->action)); - return; - } - - fault = xmlnode_get_child(resp->xml, "Body/Fault"); - - if (fault == NULL) { - /* No errors */ - if (state->cb) - ((MsnSoapCallback)state->cb)(req, resp, data); - msn_callback_state_free(state); - return; - } - - faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode")); - - if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) { - purple_debug_info("msn", - "Contact Operation {%s} failed because of bad token." - " Updating token now and retrying operation.\n", - msn_contact_operation_str(state->action)); - /* Token has expired, so renew it, and try again later */ - msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS, - (GSourceFunc)msn_contact_request, data); - } - else - { - if (state->cb) { - ((MsnSoapCallback)state->cb)(req, resp, data); - } else { - /* We don't know how to respond to this faultcode, so log it */ - char *str = xmlnode_to_str(fault, NULL); - purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", - msn_contact_operation_str(state->action), str); - g_free(str); - } - msn_callback_state_free(state); - } - - g_free(faultcode_str); -} - -static gboolean -msn_contact_request(MsnCallbackState *state) -{ - if (state->token == NULL) - state->token = xmlnode_get_child(state->body, - "Header/ABAuthHeader/TicketToken"); - /* delete old & replace with new token */ - xmlnode_free(state->token->child); - xmlnode_insert_data(state->token, - msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1); - msn_soap_message_send(state->session, - msn_soap_message_new(state->post_action, xmlnode_copy(state->body)), - MSN_CONTACT_SERVER, state->post_url, FALSE, - msn_contact_request_cb, state); - return FALSE; -} - static void msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--- a/libpurple/protocols/msn/contact.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/contact.h Fri Feb 06 22:49:01 2009 +0000 @@ -52,7 +52,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\ - "<TicketToken>%s</TicketToken>"\ + "<TicketToken>EMPTY</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ @@ -94,7 +94,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ - "<TicketToken>%s</TicketToken>"\ + "<TicketToken>EMPTY</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -135,7 +135,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ - "<TicketToken>%s</TicketToken>"\ + "<TicketToken>EMPTY</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -619,6 +619,15 @@ MSN_UPDATE_INFO = 0x80 } MsnCallbackAction; +typedef enum +{ + MSN_PS_INITIAL, + MSN_PS_SAVE_CONTACT, + MSN_PS_PENDING_LIST, + MSN_PS_CONTACT_API, + MSN_PS_BLOCK_UNBLOCK +} MsnSoapPartnerScenario; + typedef struct _MsnCallbackState MsnCallbackState; struct _MsnCallbackState @@ -636,19 +645,12 @@ const gchar *post_action; const gchar *post_url; MsnSoapCallback cb; + /* For msn_get_contact_list only */ + MsnSoapPartnerScenario partner_scenario; }; typedef enum { - MSN_PS_INITIAL, - MSN_PS_SAVE_CONTACT, - MSN_PS_PENDING_LIST, - MSN_PS_CONTACT_API, - MSN_PS_BLOCK_UNBLOCK -} MsnSoapPartnerScenario; - -typedef enum -{ MSN_UPDATE_DISPLAY, /* Real display name */ MSN_UPDATE_ALIAS, /* Aliased display name */ MSN_UPDATE_COMMENT
--- a/libpurple/protocols/msn/msg.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/msg.c Fri Feb 06 22:49:01 2009 +0000 @@ -23,6 +23,7 @@ */ #include "msn.h" #include "msg.h" +#include "msnutils.h" MsnMessage * msn_message_new(MsnMsgType type) @@ -79,7 +80,7 @@ msg->ref_count++; #ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message ref (%p)[%d]\n", msg, msg->ref_count); + purple_debug_info("msn", "message ref (%p)[%" G_GSIZE_FORMAT "]\n", msg, msg->ref_count); #endif return msg; @@ -94,7 +95,7 @@ msg->ref_count--; #ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message unref (%p)[%d]\n", msg, msg->ref_count); + purple_debug_info("msn", "message unref (%p)[%" G_GSIZE_FORMAT "]\n", msg, msg->ref_count); #endif if (msg->ref_count == 0) @@ -804,3 +805,174 @@ g_string_free(str, TRUE); } + +/************************************************************************** + * Message Handlers + **************************************************************************/ +void +msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) +{ + PurpleConnection *gc; + const char *body; + char *body_str; + char *body_enc; + char *body_final; + size_t body_len; + const char *passport; + const char *value; + + gc = cmdproc->session->account->gc; + + body = msn_message_get_bin_data(msg, &body_len); + body_str = g_strndup(body, body_len); + body_enc = g_markup_escape_text(body_str, -1); + g_free(body_str); + + passport = msg->remote_user; + + if (!strcmp(passport, "messenger@microsoft.com") && + strstr(body, "immediate security update")) + { + return; + } + +#if 0 + if ((value = msn_message_get_attr(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) + { + char *pre, *post; + + msn_parse_format(value, &pre, &post); + + body_final = g_strdup_printf("%s%s%s", pre ? pre : "", + body_enc ? body_enc : "", post ? post : ""); + + g_free(pre); + g_free(post); + g_free(body_enc); + } + else + { + body_final = body_enc; + } + + if (cmdproc->servconn->type == MSN_SERVCONN_SB) { + MsnSwitchBoard *swboard = cmdproc->data; + + swboard->flag |= MSN_SB_FLAG_IM; + + if (swboard->current_users > 1 || + ((swboard->conv != NULL) && + purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + { + /* If current_users is always ok as it should then there is no need to + * check if this is a chat. */ + if (swboard->current_users <= 1) + purple_debug_misc("msn", "plain_msg: current_users(%d)\n", + swboard->current_users); + + serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final, + time(NULL)); + if (swboard->conv == NULL) + { + swboard->conv = purple_find_chat(gc, swboard->chat_id); + swboard->flag |= MSN_SB_FLAG_IM; + } + } + else + { + serv_got_im(gc, passport, body_final, 0, time(NULL)); + if (swboard->conv == NULL) + { + swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + passport, purple_connection_get_account(gc)); + swboard->flag |= MSN_SB_FLAG_IM; + } + } + + } else { + serv_got_im(gc, passport, body_final, 0, time(NULL)); + } + + g_free(body_final); +} + +void +msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg) +{ + PurpleConnection *gc; + char *passport; + + gc = cmdproc->session->account->gc; + passport = msg->remote_user; + + if (msn_message_get_attr(msg, "TypingUser") == NULL) + return; + + if (cmdproc->servconn->type == MSN_SERVCONN_SB) { + MsnSwitchBoard *swboard = cmdproc->data; + + if (swboard->current_users == 1) + { + serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, + PURPLE_TYPING); + } + + } else { + serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, + PURPLE_TYPING); + } +} + +void +msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg) +{ + GHashTable *body; + const char *id; + body = msn_message_get_hashtable_from_body(msg); + + id = g_hash_table_lookup(body, "ID"); + + if (!strcmp(id, "1")) { + /* Nudge */ + PurpleAccount *account; + const char *user; + + account = cmdproc->session->account; + user = msg->remote_user; + + if (cmdproc->servconn->type == MSN_SERVCONN_SB) { + MsnSwitchBoard *swboard = cmdproc->data; + if (swboard->current_users > 1 || + ((swboard->conv != NULL) && + purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE); + + else + purple_prpl_got_attention(account->gc, user, MSN_NUDGE); + + } else { + purple_prpl_got_attention(account->gc, user, MSN_NUDGE); + } + + } else if (!strcmp(id, "2")) { + /* Wink */ + + } else if (!strcmp(id, "3")) { + /* Voiceclip */ + + } else if (!strcmp(id, "4")) { + /* Action */ + + } else { + purple_debug_warning("msn", "Got unknown datacast with ID %s.\n", id); + } + + g_hash_table_destroy(body); +} +
--- a/libpurple/protocols/msn/msg.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/msg.h Fri Feb 06 22:49:01 2009 +0000 @@ -339,4 +339,10 @@ char *msn_message_to_string(MsnMessage *msg); +void msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg); + +void msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg); + +void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg); + #endif /* _MSN_MSG_H_ */
--- a/libpurple/protocols/msn/msn.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/msn.c Fri Feb 06 22:49:01 2009 +0000 @@ -853,11 +853,11 @@ types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, - NULL, NULL, FALSE, TRUE, FALSE); + NULL, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, - NULL, NULL, FALSE, TRUE, FALSE); + NULL, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_MOBILE, @@ -1176,6 +1176,7 @@ MsnMessage *msg; char *msgformat; char *msgtext; + size_t msglen; const char *username; purple_debug_info("msn", "send IM {%s} to %s\n", message, who); @@ -1203,13 +1204,23 @@ } msn_import_html(message, &msgformat, &msgtext); + msglen = strlen(msgtext); + if (msglen == 0) { + /* Stuff like <hr> will be ignored. Don't send an empty message + if that's all there is. */ + g_free(msgtext); + g_free(msgformat); + + return 0; + } + if (msn_user_is_online(account, who) || msn_user_is_yahoo(account, who) || swboard != NULL) { /*User online or have a swboard open because it's invisible * and sent us a message,then send Online Instant Message*/ - if (strlen(msgtext) + strlen(msgformat) + strlen(VERSION) > 1564) + if (msglen + strlen(msgformat) + strlen(VERSION) > 1564) { g_free(msgformat); g_free(msgtext);
--- a/libpurple/protocols/msn/notification.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/notification.c Fri Feb 06 22:49:01 2009 +0000 @@ -1094,8 +1094,10 @@ return; } - serv_got_alias(gc, passport, friendly); - msn_user_set_friendly_name(user, friendly); + if (msn_user_set_friendly_name(user, friendly)) { + serv_got_alias(gc, passport, friendly); + msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly); + } g_free(friendly); msn_user_set_object(user, msnobj); @@ -1220,7 +1222,7 @@ MsnObject *msnobj; unsigned long clientid; int networkid; - const char *state, *passport, *friendly, *old_friendly; + const char *state, *passport, *friendly; session = cmdproc->session; account = session->account; @@ -1234,11 +1236,10 @@ user = msn_userlist_find_user(session->userlist, passport); if (user == NULL) return; - old_friendly = msn_user_get_friendly_name(user); - if (!old_friendly || (old_friendly && (!friendly || strcmp(old_friendly, friendly)))) + if (msn_user_set_friendly_name(user, friendly)) { serv_got_alias(gc, passport, friendly); - msn_user_set_friendly_name(user, friendly); + msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly); } if (cmd->param_count == 6) @@ -2095,6 +2096,13 @@ msn_table_add_msg_type(cbs_table, "application/x-msmsgssystemmessage", system_msg); + /* generic message handlers */ + msn_table_add_msg_type(cbs_table, "text/plain", + msn_plain_msg); + msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol", + msn_control_msg); + msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast", + msn_datacast_msg); } void
--- a/libpurple/protocols/msn/soap.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/soap.c Fri Feb 06 22:49:01 2009 +0000 @@ -342,12 +342,14 @@ } if (fault || body) { - MsnSoapRequest *request = conn->current_request; - conn->current_request = NULL; - request->cb(request->message, response, - request->cb_data); + if (conn->current_request) { + MsnSoapRequest *request = conn->current_request; + conn->current_request = NULL; + request->cb(request->message, response, + request->cb_data); + msn_soap_request_destroy(request, FALSE); + } msn_soap_message_destroy(response); - msn_soap_request_destroy(request, FALSE); } return TRUE;
--- a/libpurple/protocols/msn/switchboard.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/switchboard.c Fri Feb 06 22:49:01 2009 +0000 @@ -887,113 +887,6 @@ * Message Handlers **************************************************************************/ static void -plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - PurpleConnection *gc; - MsnSwitchBoard *swboard; - const char *body; - char *body_str; - char *body_enc; - char *body_final; - size_t body_len; - const char *passport; - const char *value; - - gc = cmdproc->session->account->gc; - swboard = cmdproc->data; - - body = msn_message_get_bin_data(msg, &body_len); - body_str = g_strndup(body, body_len); - body_enc = g_markup_escape_text(body_str, -1); - g_free(body_str); - - passport = msg->remote_user; - - if (!strcmp(passport, "messenger@microsoft.com") && - strstr(body, "immediate security update")) - { - return; - } - -#if 0 - if ((value = msn_message_get_attr(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) - { - char *pre, *post; - - msn_parse_format(value, &pre, &post); - - body_final = g_strdup_printf("%s%s%s", pre ? pre : "", - body_enc ? body_enc : "", post ? post : ""); - - g_free(pre); - g_free(post); - g_free(body_enc); - } - else - { - body_final = body_enc; - } - - swboard->flag |= MSN_SB_FLAG_IM; - - if (swboard->current_users > 1 || - ((swboard->conv != NULL) && - purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) - { - /* If current_users is always ok as it should then there is no need to - * check if this is a chat. */ - if (swboard->current_users <= 1) - purple_debug_misc("msn", "plain_msg: current_users(%d)\n", - swboard->current_users); - - serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final, - time(NULL)); - if (swboard->conv == NULL) - { - swboard->conv = purple_find_chat(gc, swboard->chat_id); - swboard->flag |= MSN_SB_FLAG_IM; - } - } - else - { - serv_got_im(gc, passport, body_final, 0, time(NULL)); - if (swboard->conv == NULL) - { - swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - passport, purple_connection_get_account(gc)); - swboard->flag |= MSN_SB_FLAG_IM; - } - } - - g_free(body_final); -} - -static void -control_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - PurpleConnection *gc; - MsnSwitchBoard *swboard; - char *passport; - - gc = cmdproc->session->account->gc; - swboard = cmdproc->data; - passport = msg->remote_user; - - if (swboard->current_users == 1 && - msn_message_get_attr(msg, "TypingUser") != NULL) - { - serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, - PURPLE_TYPING); - } -} - -static void clientcaps_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { #if 0 @@ -1012,49 +905,6 @@ #endif } -static void -datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - GHashTable *body; - const char *id; - body = msn_message_get_hashtable_from_body(msg); - - id = g_hash_table_lookup(body, "ID"); - - if (!strcmp(id, "1")) { - /* Nudge */ - MsnSwitchBoard *swboard; - PurpleAccount *account; - const char *user; - - swboard = cmdproc->data; - account = cmdproc->session->account; - user = msg->remote_user; - - if (swboard->current_users > 1 || - ((swboard->conv != NULL) && - purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) - purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE); - - else - purple_prpl_got_attention(account->gc, user, MSN_NUDGE); - - } else if (!strcmp(id, "2")) { - /* Wink */ - - } else if (!strcmp(id, "3")) { - /* Voiceclip */ - - } else if (!strcmp(id, "4")) { - /* Action */ - - } else { - purple_debug_warning("msn", "Got unknown datacast with ID %s.\n", id); - } - - g_hash_table_destroy(body); -} - /************************************************************************** * Connect stuff **************************************************************************/ @@ -1372,9 +1222,9 @@ /* Register the message type callbacks. */ msn_table_add_msg_type(cbs_table, "text/plain", - plain_msg); + msn_plain_msg); msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol", - control_msg); + msn_control_msg); msn_table_add_msg_type(cbs_table, "text/x-clientcaps", clientcaps_msg); msn_table_add_msg_type(cbs_table, "text/x-clientinfo", @@ -1384,9 +1234,9 @@ msn_table_add_msg_type(cbs_table, "text/x-mms-emoticon", msn_emoticon_msg); msn_table_add_msg_type(cbs_table, "text/x-mms-animemoticon", - msn_emoticon_msg); + msn_emoticon_msg); msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast", - datacast_msg); + msn_datacast_msg); #if 0 msn_table_add_msg_type(cbs_table, "text/x-msmmsginvite", msn_invite_msg);
--- a/libpurple/protocols/msn/user.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/user.c Fri Feb 06 22:49:01 2009 +0000 @@ -177,13 +177,18 @@ user->passport = g_strdup(passport); } -void +gboolean msn_user_set_friendly_name(MsnUser *user, const char *name) { - g_return_if_fail(user != NULL); + g_return_val_if_fail(user != NULL, FALSE); + + if (user->friendly_name && name && !strcmp(user->friendly_name, name)) + return FALSE; g_free(user->friendly_name); user->friendly_name = g_strdup(name); + + return TRUE; } void
--- a/libpurple/protocols/msn/user.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/msn/user.h Fri Feb 06 22:49:01 2009 +0000 @@ -178,8 +178,10 @@ * * @param user The user. * @param name The friendly name. + * + * @returns TRUE is name actually changed, FALSE otherwise. */ -void msn_user_set_friendly_name(MsnUser *user, const char *name); +gboolean msn_user_set_friendly_name(MsnUser *user, const char *name); /** * Sets the buddy icon for a local user.
--- a/libpurple/protocols/myspace/myspace.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/myspace/myspace.c Fri Feb 06 22:49:01 2009 +0000 @@ -1146,7 +1146,11 @@ break; case MSIM_CONTACT_LIST_INITIAL_FRIENDS: - /* Nothing */ + /* The session is now set up, ready to be connected. This emits the + * signedOn signal, so clients can now do anything with msimprpl, and + * we're ready for it (session key, userid, username all setup). */ + purple_connection_update_progress(session->gc, _("Connected"), 3, 4); + purple_connection_set_state(session->gc, PURPLE_CONNECTED); break; } @@ -1185,12 +1189,6 @@ /* Set display name to username (otherwise will show email address) */ purple_connection_set_display_name(session->gc, session->username); - /* The session is now set up, ready to be connected. This emits the - * signedOn signal, so clients can now do anything with msimprpl, and - * we're ready for it (session key, userid, username all setup). */ - purple_connection_update_progress(session->gc, _("Connected"), 3, 4); - purple_connection_set_state(session->gc, PURPLE_CONNECTED); - body = msim_msg_new( "UserID", MSIM_TYPE_INTEGER, session->userid, NULL);
--- a/libpurple/protocols/novell/novell.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/novell/novell.c Fri Feb 06 22:49:01 2009 +0000 @@ -2976,7 +2976,7 @@ NULL, TRUE, TRUE, FALSE); status_types = g_list_append(status_types, type); - type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE); status_types = g_list_append(status_types, type); return status_types;
--- a/libpurple/protocols/oscar/oscar.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Feb 06 22:49:01 2009 +0000 @@ -4782,7 +4782,7 @@ if (status_html != NULL) { status_text = purple_markup_strip_html(status_html); - /* If the status_text is longer than 60 character then truncate it */ + /* If the status_text is longer than 251 characters then truncate it */ if (strlen(status_text) > MAXAVAILMSGLEN) { char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]); @@ -4799,9 +4799,28 @@ } else { + char *status_text = NULL; + htmlaway = purple_status_get_attr_string(status, "message"); if ((htmlaway == NULL) || (*htmlaway == '\0')) htmlaway = purple_status_type_get_name(status_type); + + /* ICQ 6.x seems to use an available message for all statuses so set one */ + if (od->icq) + { + status_text = purple_markup_strip_html(htmlaway); + /* If the status_text is longer than 251 characters then truncate it */ + if (strlen(status_text) > MAXAVAILMSGLEN) + { + char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]); + strcpy(tmp, "..."); + } + aim_srv_setextrainfo(od, FALSE, 0, TRUE, status_text, NULL); + } + g_free(status_text); + + /* Set a proper away message for icq too so that they work for old third party clients */ + away = purple_prpl_oscar_convert_to_infotext(htmlaway, &awaylen, &away_encoding); if (awaylen > od->rights.maxawaymsglen)
--- a/libpurple/protocols/oscar/oscar.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.h Fri Feb 06 22:49:01 2009 +0000 @@ -286,6 +286,15 @@ "us", "en", \ } +#define CLIENTINFO_ICQBASIC_14_34_3096 { \ + "ICQBasic", \ + 0x010a, \ + 0x0014, 0x0034, \ + 0x0000, 0x0c18, \ + 0x0000043d, \ + "us", "en", \ +} + #define CLIENTINFO_NETSCAPE_7_0_1 { \ "Netscape 2000 an approved user of AOL Instant Messenger (SM)", \ 0x1d0d, \ @@ -312,14 +321,14 @@ #define CLIENTINFO_PURPLE_ICQ { \ "Purple/" VERSION, \ 0x010a, \ - 0x0006, 0x0000, \ - 0x0000, 0x17ab, \ - 0x00007535, \ + 0x0014, 0x0034, \ + 0x0000, 0x0c18, \ + 0x0000043d, \ "us", "en", \ } #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036 -#define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQBASIC_14_34_3000 +#define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQBASIC_14_34_3096 typedef enum {
--- a/libpurple/protocols/qq/qq.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/qq/qq.c Fri Feb 06 22:49:01 2009 +0000 @@ -406,15 +406,15 @@ GList *types = NULL; status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, - "available", _("Available"), FALSE, TRUE, FALSE); + "available", _("Available"), TRUE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "away", _("Away"), FALSE, TRUE, FALSE); + "away", _("Away"), TRUE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, - "invisible", _("Invisible"), FALSE, TRUE, FALSE); + "invisible", _("Invisible"), TRUE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, @@ -422,7 +422,7 @@ types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, - "offline", _("Offline"), FALSE, TRUE, FALSE); + "offline", _("Offline"), TRUE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
--- a/libpurple/protocols/silc/silc.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/silc/silc.c Fri Feb 06 22:49:01 2009 +0000 @@ -48,19 +48,19 @@ PurpleStatusType *type; GList *types = NULL; - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, type); return types; @@ -1357,6 +1357,7 @@ char tmp[256]; SilcClientEntry client_entry; SilcDList list; + gboolean free_list = FALSE; convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, sg->account); @@ -1373,6 +1374,8 @@ im->nick, FALSE); if (!clients) goto err; + + free_list = TRUE; } silc_dlist_start(clients); @@ -1413,6 +1416,9 @@ purple_conversation_write(convo, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); out: + if (free_list) { + silc_client_list_free(client, conn, clients); + } g_free(im->nick); g_free(im->message); silc_free(im);
--- a/libpurple/protocols/silc10/silc.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/protocols/silc10/silc.c Fri Feb 06 22:49:01 2009 +0000 @@ -39,19 +39,19 @@ PurpleStatusType *type; GList *types = NULL; - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE); types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, FALSE, TRUE, FALSE); + type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE); types = g_list_append(types, type); return types;
--- a/libpurple/xmlnode.c Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/xmlnode.c Fri Feb 06 22:49:01 2009 +0000 @@ -303,7 +303,7 @@ node->prefix = g_strdup(prefix); } -const char *xmlnode_get_prefix(xmlnode *node) +const char *xmlnode_get_prefix(const xmlnode *node) { g_return_val_if_fail(node != NULL, NULL); return node->prefix; @@ -443,11 +443,11 @@ } static char * -xmlnode_to_str_helper(xmlnode *node, int *len, gboolean formatting, int depth) +xmlnode_to_str_helper(const xmlnode *node, int *len, gboolean formatting, int depth) { GString *text = g_string_new(""); const char *prefix; - xmlnode *c; + const xmlnode *c; char *node_name, *esc, *esc2, *tab = NULL; gboolean need_end = FALSE, pretty = formatting; @@ -537,13 +537,13 @@ } char * -xmlnode_to_str(xmlnode *node, int *len) +xmlnode_to_str(const xmlnode *node, int *len) { return xmlnode_to_str_helper(node, len, FALSE, 0); } char * -xmlnode_to_formatted_str(xmlnode *node, int *len) +xmlnode_to_formatted_str(const xmlnode *node, int *len) { char *xml, *xml_with_declaration;
--- a/libpurple/xmlnode.h Thu Jan 29 20:36:14 2009 +0000 +++ b/libpurple/xmlnode.h Fri Feb 06 22:49:01 2009 +0000 @@ -243,7 +243,7 @@ * @param node The node to get the prefix from * @return The prefix of this node */ -const char *xmlnode_get_prefix(xmlnode *node); +const char *xmlnode_get_prefix(const xmlnode *node); /** * Returns the node in a string of xml. @@ -254,7 +254,7 @@ * @return The node represented as a string. You must * g_free this string when finished using it. */ -char *xmlnode_to_str(xmlnode *node, int *len); +char *xmlnode_to_str(const xmlnode *node, int *len); /** * Returns the node in a string of human readable xml. @@ -266,7 +266,7 @@ * tab and new line characters. You must * g_free this string when finished using it. */ -char *xmlnode_to_formatted_str(xmlnode *node, int *len); +char *xmlnode_to_formatted_str(const xmlnode *node, int *len); /** * Creates a node from a string of XML. Calling this on the
--- a/pidgin/gtkdialogs.c Thu Jan 29 20:36:14 2009 +0000 +++ b/pidgin/gtkdialogs.c Fri Feb 06 22:49:01 2009 +0000 @@ -198,7 +198,7 @@ {N_("Macedonian"), "mk", "Arangel Angov ", "arangel@linux.net.mk"}, {N_("Macedonian"), "mk", "Ivana Kirkovska", "ivana.kirkovska@gmail.com"}, {N_("Macedonian"), "mk", "Jovan Naumovski", "jovan@lugola.net"}, - {"Mongolian", "mn", "gooyo", NULL}, + {N_("Mongolian"), "mn", "gooyo", NULL}, {N_("Bokmål Norwegian"), "nb", "Hans Fredrik Nordhaug", "hans@nordhaug.priv.no"}, {N_("Nepali"), "ne", "Shyam Krishna Bal", "shyamkrishna_bal@yahoo.com"}, {N_("Dutch, Flemish"), "nl", "Vincent van Adrighem", "V.vanAdrighem@dirck.mine.nu"},
--- a/pidgin/plugins/win32/winprefs/winprefs.c Thu Jan 29 20:36:14 2009 +0000 +++ b/pidgin/plugins/win32/winprefs/winprefs.c Fri Feb 06 22:49:01 2009 +0000 @@ -55,9 +55,8 @@ static const char *PREF_DBLIST_HEIGHT = "/plugins/gtk/win32/winprefs/dblist_height"; static const char *PREF_DBLIST_SIDE = "/plugins/gtk/win32/winprefs/dblist_side"; static const char *PREF_BLIST_ON_TOP = "/plugins/gtk/win32/winprefs/blist_on_top"; +/* Deprecated */ static const char *PREF_CHAT_BLINK = "/plugins/gtk/win32/winprefs/chat_blink"; - -/* Deprecated */ static const char *PREF_DBLIST_ON_TOP = "/plugins/gtk/win32/winprefs/dblist_on_top"; static PurplePlugin *handle = NULL; @@ -229,17 +228,6 @@ blist_set_ontop(FALSE); } -static gboolean -winpidgin_conv_chat_blink(PurpleAccount *account, const char *who, char **message, - PurpleConversation *conv, PurpleMessageFlags flags, void *data) -{ - if(purple_prefs_get_bool(PREF_CHAT_BLINK)) - winpidgin_conv_blink(conv, flags); - - return FALSE; -} - - /* * EXPORTED FUNCTIONS */ @@ -258,10 +246,6 @@ purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-created", plugin, PURPLE_CALLBACK(blist_create_cb), NULL); - purple_signal_connect(pidgin_conversations_get_handle(), - "displaying-chat-msg", plugin, PURPLE_CALLBACK(winpidgin_conv_chat_blink), - NULL); - purple_signal_connect((void*)purple_get_core(), "quitting", plugin, PURPLE_CALLBACK(purple_quit_cb), NULL); @@ -336,11 +320,6 @@ _("Only when docked"), BLIST_TOP_DOCKED, NULL); - /* Conversations */ - vbox = pidgin_make_frame(ret, _("Conversations")); - pidgin_prefs_checkbox(_("_Flash window when chat messages are received"), - PREF_CHAT_BLINK, vbox); - gtk_widget_show_all(ret); return ret; } @@ -399,7 +378,6 @@ purple_prefs_add_bool(PREF_DBLIST_DOCKED, FALSE); purple_prefs_add_int(PREF_DBLIST_HEIGHT, 0); purple_prefs_add_int(PREF_DBLIST_SIDE, 0); - purple_prefs_add_bool(PREF_CHAT_BLINK, FALSE); /* Convert old preferences */ if(purple_prefs_exists(PREF_DBLIST_ON_TOP)) { @@ -413,6 +391,7 @@ purple_prefs_add_int(PREF_BLIST_ON_TOP, blist_top); } else purple_prefs_add_int(PREF_BLIST_ON_TOP, BLIST_TOP_NEVER); + purple_prefs_remove(PREF_CHAT_BLINK); } PURPLE_INIT_PLUGIN(winprefs, init_plugin, info)
--- a/pidgin/win32/nsis/pidgin-installer.nsi Thu Jan 29 20:36:14 2009 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Fri Feb 06 22:49:01 2009 +0000 @@ -1247,6 +1247,9 @@ Push $R0 Push $R1 Push $R2 + Push $R3 ; This is only used for the Parameters throughout the function + + ${GetParameters} $R3 IntOp $R1 0 + 0 retry_runcheck: @@ -1258,7 +1261,14 @@ IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(INSTALLER_IS_RUNNING) /SD IDCANCEL IDRETRY retry_runcheck Abort + + ; Allow installer to run even if pidgin is running via "/NOPIDGINRUNCHECK=1" + ; This is useful for testing + ClearErrors + ${GetOptions} "$R3" "/NOPIDGINRUNCHECK=" $R1 + IfErrors 0 +2 Call RunCheck + StrCpy $name "Pidgin ${PIDGIN_VERSION}" StrCpy $SPELLCHECK_SEL "" @@ -1312,16 +1322,13 @@ SetShellVarContext "current" StrCpy $ISSILENT "/S" - - ; GTK installer has two silent states.. one with Message boxes, one without + ; GTK installer has two silent states - one with Message boxes, one without ; If pidgin installer was run silently, we want to supress gtk installer msg boxes. - IfSilent 0 set_gtk_normal - StrCpy $ISSILENT "/NOUI" - set_gtk_normal: + IfSilent 0 +2 + StrCpy $ISSILENT "/NOUI" - ${GetParameters} $R0 ClearErrors - ${GetOptions} "$R0" "/L=" $R1 + ${GetOptions} "$R3" "/L=" $R1 IfErrors +3 StrCpy $LANGUAGE $R1 Goto skip_lang @@ -1332,7 +1339,7 @@ skip_lang: ClearErrors - ${GetOptions} "$R0" "/DS=" $R1 + ${GetOptions} "$R3" "/DS=" $R1 IfErrors +8 SectionGetFlags ${SecDesktopShortcut} $R2 StrCmp "1" $R1 0 +2 @@ -1343,7 +1350,7 @@ SectionSetFlags ${SecDesktopShortcut} $R2 ClearErrors - ${GetOptions} "$R0" "/SMS=" $R1 + ${GetOptions} "$R3" "/SMS=" $R1 IfErrors +8 SectionGetFlags ${SecStartMenuShortcut} $R2 StrCmp "1" $R1 0 +2 @@ -1380,6 +1387,7 @@ instdir_done: ;LogSet on + Pop $R3 Pop $R2 Pop $R1 Pop $R0 @@ -1694,6 +1702,7 @@ Push $R1 Push $R2 Push $R3 + Push $R4 check: ClearErrors @@ -1714,7 +1723,12 @@ StrCmp $R3 "success" +3 StrCpy $R0 $R3 Goto done + ; Use a specific temporary $OUTDIR for each dictionary because the installer doesn't clean up after itself + StrCpy $R4 "$OUTDIR" + SetOutPath "$TEMP\aspell_dict-$R0" ExecWait '"$R1"' + SetOutPath "$R4" + RMDir /r "$TEMP\aspell_dict-$R0" Delete $R1 Goto check ; Check that it is now installed correctly @@ -1723,6 +1737,7 @@ StrCpy $R0 '' done: + Pop $R4 Pop $R3 Pop $R2 Pop $R1