Mercurial > pidgin
changeset 21864:e5208b29d807
merge of '1bb5970e91bf83784fd002fc78216157034e9257'
and '500a56d2072c36915fd9801be07f13c66f043050'
author | Will Thompson <will.thompson@collabora.co.uk> |
---|---|
date | Tue, 18 Dec 2007 11:05:40 +0000 |
parents | 7e833250a0ef (diff) aa4810065b91 (current diff) |
children | 886fa5f83f91 8c183ae7dac6 a92574a57460 |
files | |
diffstat | 13 files changed, 250 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.am Tue Dec 18 10:54:32 2007 +0000 +++ b/Makefile.am Tue Dec 18 11:05:40 2007 +0000 @@ -30,10 +30,12 @@ distcheck-hook: libpurple/plugins/perl/common/Purple.pm pidgin/plugins/perl/common/Pidgin.pm # cp libpurple/plugins/perl/common/Gaim.pm $(distdir)/libpurple/plugins/perl/common +if ENABLE_GTK appsdir = $(datadir)/applications apps_in_files = pidgin.desktop.in apps_DATA = $(apps_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ +endif if ENABLE_GTK GTK_DIR=pidgin
--- a/libpurple/dnsquery.c Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/dnsquery.c Tue Dec 18 11:05:40 2007 +0000 @@ -547,7 +547,7 @@ { #ifdef HAVE_GETADDRINFO g_snprintf(message, sizeof(message), _("Error resolving %s:\n%s"), - query_data->hostname, gai_strerror(err)); + query_data->hostname, purple_gai_strerror(err)); #else g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), query_data->hostname, err); @@ -695,7 +695,7 @@ } freeaddrinfo(tmp); } else { - query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"), query_data->hostname, gai_strerror(rc)); + query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"), query_data->hostname, purple_gai_strerror(rc)); } #else if ((hp = gethostbyname(query_data->hostname))) {
--- a/libpurple/network.c Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/network.c Tue Dec 18 11:05:40 2007 +0000 @@ -289,7 +289,7 @@ errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res); if (errnum != 0) { #ifndef _WIN32 - purple_debug_warning("network", "getaddrinfo: %s\n", gai_strerror(errnum)); + purple_debug_warning("network", "getaddrinfo: %s\n", purple_gai_strerror(errnum)); if (errnum == EAI_SYSTEM) purple_debug_warning("network", "getaddrinfo: system error: %s\n", g_strerror(errno)); #else
--- a/libpurple/protocols/jabber/auth.c Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Tue Dec 18 11:05:40 2007 +0000 @@ -330,14 +330,21 @@ disallow_plaintext_auth); g_free(msg); return; - /* Everything else has failed, so fail the - * connection. Should probably have a better - * error here. - */ + } else { - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, - _("Server does not use any supported authentication method")); + /* We have no mechs which can work. + * Try falling back on the old jabber:iq:auth method. We get here if the server supports + * one or more sasl mechs, we are compiled with cyrus-sasl support, but we support or can connect with none of + * the offerred mechs. jabberd 2.0 w/ SASL and Apple's iChat Server 10.5 both handle and expect + * jabber:iq:auth in this situation. iChat Server in particular offers SASL GSSAPI by default, which is often + * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails. + * + * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However, + * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms. + * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers + * which would connect without issue otherwise. -evands + */ + jabber_auth_start_old(js); return; } /* not reached */ @@ -563,6 +570,75 @@ } } +/*! + * @brief Given the server challenge (message) and the key (password), calculate the HMAC-MD5 digest + * + * This is the crammd5 response. Inspired by cyrus-sasl's _sasl_hmac_md5() + */ +static void +auth_hmac_md5(const char *challenge, size_t challenge_len, const char *key, size_t key_len, guchar *digest) +{ + PurpleCipher *cipher; + PurpleCipherContext *context; + int i; + /* inner padding - key XORd with ipad */ + unsigned char k_ipad[65]; + /* outer padding - key XORd with opad */ + unsigned char k_opad[65]; + + cipher = purple_ciphers_find_cipher("md5"); + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (strlen(key) > 64) { + guchar keydigest[16]; + + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, (const guchar *)key, strlen(key)); + purple_cipher_context_digest(context, 16, keydigest, NULL); + purple_cipher_context_destroy(context); + + key = (char *)keydigest; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + memset(k_ipad, '\0', sizeof k_ipad); + memset(k_opad, '\0', sizeof k_opad); + memcpy(k_ipad, (void *)key, key_len); + memcpy(k_opad, (void *)key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, k_ipad, 64); /* start with inner pad */ + purple_cipher_context_append(context, (const guchar *)challenge, challenge_len); /* then text of datagram */ + purple_cipher_context_digest(context, 16, digest, NULL); /* finish up 1st pass */ + purple_cipher_context_destroy(context); + + /* perform outer MD5 */ + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, k_opad, 64); /* start with outer pad */ + purple_cipher_context_append(context, digest, 16); /* then results of 1st hash */ + purple_cipher_context_digest(context, 16, digest, NULL); /* finish up 2nd pass */ + purple_cipher_context_destroy(context); +} + static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) { JabberIq *iq; @@ -608,6 +684,33 @@ jabber_iq_set_callback(iq, auth_old_result_cb, NULL); jabber_iq_send(iq); + } else if(js->stream_id && xmlnode_get_child(query, "crammd5")) { + const char *challenge; + guchar digest[16]; + char h[17], *p; + int i; + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); + query = xmlnode_get_child(iq->node, "query"); + + x = xmlnode_new_child(query, "username"); + xmlnode_insert_data(x, js->user->node, -1); + x = xmlnode_new_child(query, "resource"); + xmlnode_insert_data(x, js->user->resource, -1); + + x = xmlnode_new_child(query, "crammd5"); + challenge = xmlnode_get_attrib(xmlnode_get_child(query, "crammd5"), "challenge"); + auth_hmac_md5(challenge, strlen(challenge), pw, strlen(pw), &digest); + + /* Translate the digest to a hexadecimal notation */ + p = h; + for(i=0; i<16; i++, p+=2) + snprintf(p, 3, "%02x", digest[i]); + xmlnode_insert_data(x, h, -1); + + jabber_iq_set_callback(iq, auth_old_result_cb, NULL); + jabber_iq_send(iq); + } else if(xmlnode_get_child(query, "password")) { if(js->gsc == NULL && !purple_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) {
--- a/libpurple/protocols/jabber/jabber.c Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Tue Dec 18 11:05:40 2007 +0000 @@ -388,9 +388,29 @@ g_free(txt); } +static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer timeout) +{ + g_source_remove(GPOINTER_TO_INT(timeout)); +} + +static gboolean jabber_pong_timeout(PurpleConnection *gc) +{ + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Ping timeout")); + return FALSE; +} + void jabber_keepalive(PurpleConnection *gc) { - jabber_send_raw(gc->proto_data, "\t", -1); + JabberIq *iq = jabber_iq_new(gc->proto_data, JABBER_IQ_GET); + guint timeout; + + xmlnode *ping = xmlnode_new_child(iq->node, "ping"); + xmlnode_set_namespace(ping, "urn:xmpp:ping"); + + timeout = purple_timeout_add_seconds(20, (GSourceFunc)(jabber_pong_timeout), gc); + jabber_iq_set_callback(iq, jabber_pong_cb, GINT_TO_POINTER(timeout)); + jabber_iq_send(iq); } static void
--- a/libpurple/status.c Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/status.c Tue Dec 18 11:05:40 2007 +0000 @@ -607,13 +607,10 @@ if (old_status != NULL) { - tmp = g_strdup_printf(_("%s changed status from %s to %s"), buddy_alias, + tmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, buddy->name, purple_status_get_name(old_status), purple_status_get_name(new_status)); - logtmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, buddy->name, - purple_status_get_name(old_status), - purple_status_get_name(new_status)); - + logtmp = g_markup_escape_text(tmp, -1); } else { @@ -621,18 +618,15 @@ if (purple_status_is_active(new_status)) { - tmp = g_strdup_printf(_("%s is now %s"), buddy_alias, + tmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, buddy->name, purple_status_get_name(new_status)); - logtmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, buddy->name, - purple_status_get_name(new_status)); - + logtmp = g_markup_escape_text(tmp, -1); } else { - tmp = g_strdup_printf(_("%s is no longer %s"), buddy_alias, + tmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, buddy->name, purple_status_get_name(new_status)); - logtmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, buddy->name, - purple_status_get_name(new_status)); + logtmp = g_markup_escape_text(tmp, -1); } } @@ -1244,12 +1238,15 @@ if (log != NULL) { - char *tmp = g_strdup_printf(_("%s became idle"), + char *tmp, *tmp2; + tmp = g_strdup_printf(_("%s became idle"), purple_buddy_get_alias(buddy)); + tmp2 = g_markup_escape_text(tmp, -1); + g_free(tmp); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_buddy_get_alias(buddy), current_time, tmp); - g_free(tmp); + purple_buddy_get_alias(buddy), current_time, tmp2); + g_free(tmp2); } } } @@ -1261,12 +1258,15 @@ if (log != NULL) { - char *tmp = g_strdup_printf(_("%s became unidle"), + char *tmp, *tmp2; + tmp = g_strdup_printf(_("%s became unidle"), purple_buddy_get_alias(buddy)); + tmp2 = g_markup_escape_text(tmp, -1); + g_free(tmp); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_buddy_get_alias(buddy), current_time, tmp); - g_free(tmp); + purple_buddy_get_alias(buddy), current_time, tmp2); + g_free(tmp2); } } } @@ -1321,13 +1321,15 @@ if (log != NULL) { - char *msg; + char *msg, *tmp; if (idle) - msg = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account)); + tmp = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account)); else - msg = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account)); + tmp = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account)); + msg = g_markup_escape_text(tmp, -1); + g_free(tmp); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, purple_account_get_username(account), (idle ? idle_time : current_time), msg);
--- a/libpurple/util.c Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/util.c Tue Dec 18 11:05:40 2007 +0000 @@ -4257,6 +4257,53 @@ return g_string_free(workstr, FALSE); } +/* + * This function is copied from g_strerror() but changed to use + * gai_strerror(). + */ +G_CONST_RETURN gchar * +purple_gai_strerror(gint errnum) +{ + static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; + char *msg; + int saved_errno = errno; + + const char *msg_locale; + + msg_locale = gai_strerror(errnum); + if (g_get_charset(NULL)) + { + /* This string is already UTF-8--great! */ + errno = saved_errno; + return msg_locale; + } + else + { + gchar *msg_utf8 = g_locale_to_utf8(msg_locale, -1, NULL, NULL, NULL); + if (msg_utf8) + { + /* Stick in the quark table so that we can return a static result */ + GQuark msg_quark = g_quark_from_string(msg_utf8); + g_free(msg_utf8); + + msg_utf8 = (gchar *)g_quark_to_string(msg_quark); + errno = saved_errno; + return msg_utf8; + } + } + + msg = g_static_private_get(&msg_private); + if (!msg) + { + msg = g_new(gchar, 64); + g_static_private_set(&msg_private, msg, g_free); + } + + sprintf(msg, "unknown error (%d)", errnum); + + errno = saved_errno; + return msg; +} char * purple_utf8_ncr_encode(const char *str)
--- a/libpurple/util.h Tue Dec 18 10:54:32 2007 +0000 +++ b/libpurple/util.h Tue Dec 18 11:05:40 2007 +0000 @@ -1110,6 +1110,17 @@ gchar *purple_utf8_salvage(const char *str); /** + * Return the UTF-8 version of gai_strerror(). It calls gai_strerror() + * then converts the result to UTF-8. This function is analogous to + * g_strerror(). + * + * @param errnum The error code. + * + * @return The UTF-8 error message. + */ +G_CONST_RETURN gchar *purple_gai_strerror(gint errnum); + +/** * Compares two UTF-8 strings case-insensitively. This string is * more expensive than a simple g_utf8_collate() comparison because * it calls g_utf8_casefold() on each string, which allocates new
--- a/pidgin/gtkconv.c Tue Dec 18 10:54:32 2007 +0000 +++ b/pidgin/gtkconv.c Tue Dec 18 11:05:40 2007 +0000 @@ -4342,8 +4342,8 @@ lines = gtk_text_buffer_get_line_count(buffer); - /* Show a maximum of 4 lines, minimum of 2 */ - lines = MIN(MAX(lines, 2), 4); + /* Show a maximum of 4 lines */ + lines = MIN(lines, 4); wrapped_lines = MIN(MAX(wrapped_lines, 2), 4); pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
--- a/pidgin/gtkutils.c Tue Dec 18 10:54:32 2007 +0000 +++ b/pidgin/gtkutils.c Tue Dec 18 11:05:40 2007 +0000 @@ -1399,7 +1399,7 @@ char *str; str = g_strdup_printf(_("The following error has occurred loading %s: %s"), - data->filename, strerror(errno)); + data->filename, g_strerror(errno)); purple_notify_error(NULL, NULL, _("Failed to load image"), str);
--- a/pidgin/plugins/crazychat/cc_network.c Tue Dec 18 10:54:32 2007 +0000 +++ b/pidgin/plugins/crazychat/cc_network.c Tue Dec 18 11:05:40 2007 +0000 @@ -529,7 +529,7 @@ while (total < len) { n = send(s, buf + total, bytesleft, 0); if (n == -1) { - Debug("ERROR: %s\n", strerror(errno)); + Debug("ERROR: %s\n", g_strerror(errno)); return -1; } total += n;
--- a/pidgin/win32/nsis/pidgin-installer.nsi Tue Dec 18 10:54:32 2007 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Tue Dec 18 11:05:40 2007 +0000 @@ -1154,11 +1154,21 @@ !macro RunCheckMacro UN Function ${UN}RunCheck Push $R0 - System::Call 'kernel32::OpenMutex(i 2031617, b 0, t "pidgin_is_running") i .R0' - IntCmp $R0 0 done - MessageBox MB_OK|MB_ICONEXCLAMATION $(PIDGIN_IS_RUNNING) /SD IDOK + Push $R1 + + IntOp $R1 0 + 0 + retry_runcheck: + ; Close the Handle (needed if we're retrying) + IntCmp $R1 0 +2 + System::Call 'kernel32::CloseHandle(i $R1) i .R1' + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_is_running") i .R1 ?e' + Pop $R0 + IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume + MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(PIDGIN_IS_RUNNING) /SD IDCANCEL IDRETRY retry_runcheck Abort + done: + Pop $R1 Pop $R0 FunctionEnd !macroend @@ -1169,10 +1179,16 @@ Push $R0 Push $R1 Push $R2 - System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_installer_running") i .r1 ?e' + + IntOp $R1 0 + 0 + retry_runcheck: + ; Close the Handle (needed if we're retrying) + IntCmp $R1 0 +2 + System::Call 'kernel32::CloseHandle(i $R1) i .R1' + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_installer_running") i .R1 ?e' Pop $R0 - StrCmp $R0 0 +3 - MessageBox MB_OK|MB_ICONEXCLAMATION $(INSTALLER_IS_RUNNING) /SD IDOK + 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 Call RunCheck StrCpy $name "Pidgin ${PIDGIN_VERSION}"
--- a/pidgin/win32/winpidgin.c Tue Dec 18 10:54:32 2007 +0000 +++ b/pidgin/win32/winpidgin.c Tue Dec 18 11:05:40 2007 +0000 @@ -445,11 +445,12 @@ #define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13) #define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14) -static BOOL winpidgin_set_running() { +static BOOL winpidgin_set_running(BOOL fail_if_running) { HANDLE h; if ((h = CreateMutex(NULL, FALSE, "pidgin_is_running"))) { - if (GetLastError() == ERROR_ALREADY_EXISTS) { + DWORD err = GetLastError(); + if (err == ERROR_ALREADY_EXISTS && fail_if_running) { HWND msg_win; printf("An instance of Pidgin is already running.\n"); @@ -465,7 +466,8 @@ NULL, MB_OK | MB_TOPMOST); return FALSE; - } + } else + printf("Error (%d) accessing \"pidgin_is_running\" mutex.\n", err); } return TRUE; } @@ -628,8 +630,8 @@ winpidgin_set_locale(); /* If help, version or multiple flag used, do not check Mutex */ - if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v") && !strstr(lpszCmdLine, "-m")) - if (!getenv("PIDGIN_MULTI_INST") && !winpidgin_set_running()) + if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v")) + if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && strstr(lpszCmdLine, "-m") == NULL)) return 0; /* Now we are ready for Pidgin .. */