# HG changeset patch # User Will Thompson # Date 1192231571 0 # Node ID fa3c4c5dea665c0ca902685c8a281e31bafd30de # Parent e967fd47baa5ad035a37a388d66b83fc42636c4c# Parent c521b0f72a7bc744acbc94bee28e821f73e3978e propagate from branch 'im.pidgin.pidgin.next.minor' (head 4018add8ebbf0e7dfc0fa002ebaeedb7048a26a6) to branch 'im.pidgin.cpw.resiak.disconnectreason' (head b9fff782d80fd2d1a999b82e31433db57c0c2db3) diff -r e967fd47baa5 -r fa3c4c5dea66 COPYRIGHT --- a/COPYRIGHT Fri Oct 12 03:53:58 2007 +0000 +++ b/COPYRIGHT Fri Oct 12 23:26:11 2007 +0000 @@ -80,6 +80,7 @@ Graham Cole Jono Cole Lorenzo Colitti +Collabora Ltd. Jeff Connelly Nathan Conrad Felipe Contreras diff -r e967fd47baa5 -r fa3c4c5dea66 ChangeLog.API --- a/ChangeLog.API Fri Oct 12 03:53:58 2007 +0000 +++ b/ChangeLog.API Fri Oct 12 23:26:11 2007 +0000 @@ -14,6 +14,20 @@ to unload a plugin--fails. This then prevents the plugin from being saved in the saved plugins list, so it'll won't be loaded at the next startup. + * PurpleDisconnectReason enumeration of machine-readable + types of connection error. + * purple_connection_error_reason(), to be used by prpls + (instead of purple_connection_error() and setting + gc->wants_to_die) to report errors along with a + PurpleDisconnectReason. + * PurpleConnectionUiOps.report_disconnect_reason, to be + implemented by UIs (rather than .report_disconnect) if + they want to use the reported PurpleDisconnectReason + to give a more specific error. + * purple_connection_reason_is_fatal(), acting as a hint + to whether automatic reconnection should be attempted + after a connection error (rather than checking + gc->wants_to_die). Changed: * purple_plugin_unload() now honors the return value of a @@ -86,7 +100,7 @@ * gnt_util_parse_xhtml_to_textview to parse XHTML strings in a GntTextView (this works only if libxml2 is available) -version 2.1.1 (08/20/2007): +Version 2.1.1 (08/20/2007): libpurple: Changed: * PurpleAccountUiOps.request_authorize's authorize_cb and diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/connection.c --- a/libpurple/connection.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/connection.c Fri Oct 12 23:26:11 2007 +0000 @@ -488,29 +488,105 @@ void purple_connection_error(PurpleConnection *gc, const char *text) { + /* prpls that have not been updated to use disconnection reasons will + * be setting wants_to_die before calling this function, so choose + * PURPLE_REASON_OTHER_ERROR (which is fatal) if it's true, and + * PURPLE_REASON_NETWORK_ERROR (which isn't) if not. See the + * documentation in connection.h. + */ + PurpleDisconnectReason reason = gc->wants_to_die + ? PURPLE_REASON_OTHER_ERROR + : PURPLE_REASON_NETWORK_ERROR; + purple_connection_error_reason (gc, reason, text); +} + +void +purple_connection_error_reason (PurpleConnection *gc, + PurpleDisconnectReason reason, + const char *description) +{ PurpleConnectionUiOps *ops; g_return_if_fail(gc != NULL); + g_return_if_fail(reason < PURPLE_NUM_REASONS); - if (text == NULL) { - purple_debug_error("connection", "purple_connection_error: check `text != NULL' failed\n"); - text = _("Unknown error"); + if (description == NULL) { + purple_debug_error("connection", "purple_connection_error_reason: check `description != NULL' failed\n"); + description = _("Unknown error"); } /* If we've already got one error, we don't need any more */ if (gc->disconnect_timeout) return; + gc->wants_to_die = purple_connection_reason_is_fatal (reason); + ops = purple_connections_get_ui_ops(); - if (ops != NULL && ops->report_disconnect != NULL) - ops->report_disconnect(gc, text); + if (ops != NULL) + { + if (ops->report_disconnect_reason != NULL) + ops->report_disconnect_reason (gc, reason, description); + if (ops->report_disconnect != NULL) + ops->report_disconnect (gc, description); + } gc->disconnect_timeout = purple_timeout_add(0, purple_connection_disconnect_cb, purple_connection_get_account(gc)); } void +purple_connection_ssl_error (PurpleConnection *gc, + PurpleSslErrorType ssl_error) +{ + PurpleDisconnectReason reason; + + switch (ssl_error) { + case PURPLE_SSL_HANDSHAKE_FAILED: + case PURPLE_SSL_CONNECT_FAILED: + reason = PURPLE_REASON_ENCRYPTION_ERROR; + break; + case PURPLE_SSL_CERTIFICATE_INVALID: + /* TODO: maybe PURPLE_SSL_* should be more specific? */ + reason = PURPLE_REASON_CERT_OTHER_ERROR; + break; + default: + g_assert_not_reached (); + reason = PURPLE_REASON_ENCRYPTION_ERROR; + } + + purple_connection_error_reason (gc, reason, purple_ssl_strerror(ssl_error)); +} + +gboolean +purple_connection_reason_is_fatal (PurpleDisconnectReason reason) +{ + switch (reason) + { + case PURPLE_REASON_NETWORK_ERROR: + case PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE: + case PURPLE_REASON_CERT_NOT_PROVIDED: + case PURPLE_REASON_CERT_UNTRUSTED: + case PURPLE_REASON_CERT_EXPIRED: + case PURPLE_REASON_CERT_NOT_ACTIVATED: + case PURPLE_REASON_CERT_HOSTNAME_MISMATCH: + case PURPLE_REASON_CERT_FINGERPRINT_MISMATCH: + case PURPLE_REASON_CERT_SELF_SIGNED: + case PURPLE_REASON_CERT_OTHER_ERROR: + return FALSE; + case PURPLE_REASON_AUTHENTICATION_FAILED: + case PURPLE_REASON_NO_SSL_SUPPORT: + case PURPLE_REASON_ENCRYPTION_ERROR: + case PURPLE_REASON_NAME_IN_USE: + case PURPLE_REASON_INVALID_SETTINGS: + case PURPLE_REASON_OTHER_ERROR: + return TRUE; + default: + g_return_val_if_reached(TRUE); + } +} + +void purple_connections_disconnect_all(void) { GList *l; diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/connection.h --- a/libpurple/connection.h Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/connection.h Fri Oct 12 23:26:11 2007 +0000 @@ -54,11 +54,83 @@ } PurpleConnectionState; +/** Possible errors that can cause a connection to be closed. + * @since 2.3.0 + */ +typedef enum +{ + /** There was an error sending or receiving on the network socket, or + * there was some protocol error (such as the server sending malformed + * data). + */ + PURPLE_REASON_NETWORK_ERROR = 0, + /** The username or password (or some other credential) was incorrect. + */ + PURPLE_REASON_AUTHENTICATION_FAILED = 1, + /** libpurple doesn't speak any of the authentication methods the + * server offered. + */ + PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE = 2, + /** libpurple was built without SSL support, and the connection needs + * SSL. + */ + PURPLE_REASON_NO_SSL_SUPPORT = 3, + /** There was an error negotiating SSL on this connection, or the + * server does not support encryption but an account option was set to + * require it. + */ + PURPLE_REASON_ENCRYPTION_ERROR = 4, + /** Someone is already connected to the server using the name you are + * trying to connect with. + */ + PURPLE_REASON_NAME_IN_USE = 5, + + /** The username/server/other preference for the account isn't valid. + * For instance, on IRC the screen name cannot contain white space. + * This reason should not be used for incorrect passwords etc: use + * #PURPLE_REASON_AUTHENTICATION_FAILED for that. + * + * @todo This reason really shouldn't be necessary. Usernames and + * other account preferences should be validated when the + * account is created. + */ + PURPLE_REASON_INVALID_SETTINGS = 6, + + /** The server did not provide a SSL certificate. */ + PURPLE_REASON_CERT_NOT_PROVIDED = 7, + /** The server's SSL certificate could not be trusted. */ + PURPLE_REASON_CERT_UNTRUSTED = 8, + /** The server's SSL certificate has expired. */ + PURPLE_REASON_CERT_EXPIRED = 9, + /** The server's SSL certificate is not yet valid. */ + PURPLE_REASON_CERT_NOT_ACTIVATED = 10, + /** The server's SSL certificate did not match its hostname. */ + PURPLE_REASON_CERT_HOSTNAME_MISMATCH = 11, + /** The server's SSL certificate does not have the expected + * fingerprint. + */ + PURPLE_REASON_CERT_FINGERPRINT_MISMATCH = 12, + /** The server's SSL certificate is self-signed. */ + PURPLE_REASON_CERT_SELF_SIGNED = 13, + /** There was some other error validating the server's SSL certificate. + */ + PURPLE_REASON_CERT_OTHER_ERROR = 14, + + /** Some other error occured which fits into none of the other + * categories. + */ + PURPLE_REASON_OTHER_ERROR = 15 +} PurpleDisconnectReason; + +/** 1 more than the value of the last #PurpleDisconnectReason. */ +#define PURPLE_NUM_REASONS 16 + #include #include "account.h" #include "plugin.h" #include "status.h" +#include "sslconn.h" /** Connection UI operations. Used to notify the user of changes to * connections, such as being disconnected, and to respond to the @@ -73,11 +145,13 @@ * the UI of what is happening, as well as which @a step out of @a * step_count has been reached (which might be displayed as a progress * bar). + * @see #purple_connection_update_progress */ void (*connect_progress)(PurpleConnection *gc, const char *text, size_t step, size_t step_count); + /** Called when a connection is established (just before the * @ref signed-on signal). */ @@ -86,17 +160,23 @@ * and @ref signed-off signals). */ void (*disconnected)(PurpleConnection *gc); + /** Used to display connection-specific notices. (Pidgin's Gtk user * interface implements this as a no-op; #purple_connection_notice(), * which uses this operation, is not used by any of the protocols * shipped with libpurple.) */ void (*notice)(PurpleConnection *gc, const char *text); + /** Called when an error causes a connection to be disconnected. * Called before #disconnected. * @param text a localized error message. + * @see #purple_connection_error + * @deprecated in favour of + * #PurpleConnectionUiOps.report_disconnect_reason. */ void (*report_disconnect)(PurpleConnection *gc, const char *text); + /** Called when libpurple discovers that the computer's network * connection is active. On Linux, this uses Network Manager if * available; on Windows, it uses Win32's network change notification @@ -108,10 +188,24 @@ */ void (*network_disconnected)(); + /** Called when an error causes a connection to be disconnected. + * Called before #disconnected. This op is intended to replace + * #report_disconnect. If both are implemented, this will be called + * first; however, there's no real reason to implement both. + * @param reason why the connection ended, if known, or + * #PURPLE_REASON_OTHER_ERROR, if not. + * @param text a localized message describing the disconnection + * in more detail to the user. + * @see #purple_connection_error_reason + * @since 2.3.0 + */ + void (*report_disconnect_reason)(PurpleConnection *gc, + PurpleDisconnectReason reason, + const char *text); + void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); } PurpleConnectionUiOps; struct _PurpleConnection @@ -125,19 +219,23 @@ char *password; /**< The password used. */ int inpa; /**< The input watcher. */ - GSList *buddy_chats; /**< A list of active chats. */ + GSList *buddy_chats; /**< A list of active chats + (#PurpleConversation structs of type + #PURPLE_CONV_TYPE_CHAT). */ void *proto_data; /**< Protocol-specific data. */ char *display_name; /**< How you appear to other people. */ guint keepalive; /**< Keep-alive. */ + /** Wants to Die state. This is set when the user chooses to log out, or + * when the protocol is disconnected and should not be automatically + * reconnected (incorrect password, etc.). prpls should rely on + * purple_connection_error_reason() to set this for them rather than + * setting it themselves. + * @see purple_connection_reason_is_fatal + */ + gboolean wants_to_die; - gboolean wants_to_die; /**< Wants to Die state. This is set - when the user chooses to log out, - or when the protocol is - disconnected and should not be - automatically reconnected - (incorrect password, etc.) */ guint disconnect_timeout; /**< Timer used for nasty stack tricks */ }; @@ -195,7 +293,7 @@ /** * Sets the connection state. PRPLs should call this and pass in - * the state "PURPLE_CONNECTED" when the account is completely + * the state #PURPLE_CONNECTED when the account is completely * signed on. What does it mean to be completely signed on? If * the core can call prpl->set_status, and it successfully changes * your status, then the account is online. @@ -289,9 +387,61 @@ * * @param gc The connection. * @param reason The error text. + * @deprecated in favour of #purple_connection_error_reason. Calling + * @c purple_connection_error(gc, text) is equivalent to calling + * @c purple_connection_error_reason(gc, reason, text) where @c reason is + * #PURPLE_REASON_OTHER_ERROR if @c gc->wants_to_die is @c TRUE, and + * #PURPLE_REASON_NETWORK_ERROR if not. (This is to keep auto-reconnection + * behaviour the same when using old prpls which don't use reasons yet.) */ void purple_connection_error(PurpleConnection *gc, const char *reason); +/** + * Closes a connection with an error and an optional description of the + * error. It also sets @c gc->wants_to_die to the value of + * #purple_connection_reason_is_fatal(@a reason). + * + * @param reason why the connection is closing. + * @param description a localized description of the error. + * @since 2.3.0 + */ +void +purple_connection_error_reason (PurpleConnection *gc, + PurpleDisconnectReason reason, + const char *description); + +/** + * Closes a connection due to an SSL error; this is basically a shortcut to + * turning the #PurpleSslErrorType into a #PurpleDisconnectReason and a + * human-readable string and then calling purple_connection_error_reason(). + * @since 2.3.0 + */ +void +purple_connection_ssl_error (PurpleConnection *gc, + PurpleSslErrorType ssl_error); + +/** + * Reports whether a disconnection reason is fatal (in which case the account + * should probably not be automatically reconnected) or transient (so + * auto-reconnection is a good idea). + * For instance, #PURPLE_REASON_NETWORK_ERROR is a temporary + * error, which might be caused by losing the network connection, so + * @a purple_connection_reason_is_fatal(PURPLE_REASON_NETWORK_ERROR) is + * @c FALSE. On the other hand, #PURPLE_REASON_AUTHENTICATION_FAILED probably + * indicates a misconfiguration of the account which needs the user to go fix + * it up, so @a + * purple_connection_reason_is_fatal(PURPLE_REASON_AUTHENTICATION_FAILED) + * is @c TRUE. + * + * (This function is meant to replace checking PurpleConnection.wants_to_die.) + * + * @return @c TRUE if the account should not be automatically reconnected, and + * @c FALSE otherwise. + * @since 2.3.0 + */ +gboolean +purple_connection_reason_is_fatal (PurpleDisconnectReason reason); + /*@}*/ /**************************************************************************/ diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Fri Oct 12 23:26:11 2007 +0000 @@ -102,8 +102,7 @@ #ifdef _WIN32 if (!dns_sd_available()) { - gc->wants_to_die = TRUE; - purple_connection_error(gc, + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, _("The Apple Bonjour For Windows toolkit wasn't found, see the FAQ at: " "http://developer.pidgin.im/wiki/Using%20Pidgin#CanIusePidginforBonjourLink-LocalMessaging" " for more information.")); @@ -121,7 +120,8 @@ if (bonjour_jabber_start(bd->jabber_data) == -1) { /* Send a message about the connection error */ - purple_connection_error(gc, _("Unable to listen for incoming IM connections\n")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to listen for incoming IM connections\n")); return; } @@ -146,7 +146,8 @@ bd->dns_sd_data->account = account; if (!bonjour_dns_sd_start(bd->dns_sd_data)) { - purple_connection_error(gc, _("Unable to establish connection with the local mDNS server. Is it running?")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to establish connection with the local mDNS server. Is it running?")); return; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Oct 12 23:26:11 2007 +0000 @@ -580,7 +580,8 @@ if ((data->socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) { purple_debug_error("bonjour", "Cannot open socket: %s\n", strerror(errno)); - purple_connection_error(data->account->gc, _("Cannot open socket")); + purple_connection_error_reason (data->account->gc, + PURPLE_REASON_NETWORK_ERROR, _("Cannot open socket")); return -1; } @@ -588,7 +589,8 @@ if (setsockopt(data->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0) { purple_debug_error("bonjour", "Error setting socket options: %s\n", strerror(errno)); - purple_connection_error(data->account->gc, _("Error setting socket options")); + purple_connection_error_reason (data->account->gc, + PURPLE_REASON_NETWORK_ERROR, _("Error setting socket options")); return -1; } @@ -612,7 +614,8 @@ if (!bind_successful) { purple_debug_error("bonjour", "Cannot bind socket: %s\n", strerror(errno)); - purple_connection_error(data->account->gc, _("Could not bind socket to port")); + purple_connection_error_reason (data->account->gc, + PURPLE_REASON_NETWORK_ERROR, _("Could not bind socket to port")); return -1; } @@ -620,7 +623,8 @@ if (listen(data->socket, 10) != 0) { purple_debug_error("bonjour", "Cannot listen on socket: %s\n", strerror(errno)); - purple_connection_error(data->account->gc, _("Could not listen on socket")); + purple_connection_error_reason (data->account->gc, + PURPLE_REASON_NETWORK_ERROR, _("Could not listen on socket")); return -1; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/gg/gg.c Fri Oct 12 23:26:11 2007 +0000 @@ -381,12 +381,15 @@ if (email == NULL || p1 == NULL || p2 == NULL || t == NULL || *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') { - purple_connection_error(gc, _("Fill in the registration fields.")); + purple_connection_error_reason (gc, PURPLE_REASON_OTHER_ERROR, + _("Fill in the registration fields.")); goto exit_err; } if (g_utf8_collate(p1, p2) != 0) { - purple_connection_error(gc, _("Passwords do not match.")); + purple_connection_error_reason (gc, + PURPLE_REASON_AUTHENTICATION_FAILED, + _("Passwords do not match.")); goto exit_err; } @@ -394,7 +397,7 @@ token->id, t); h = gg_register3(email, p1, token->id, t, 0); if (h == NULL || !(s = h->data) || !s->success) { - purple_connection_error(gc, + purple_connection_error_reason (gc, PURPLE_REASON_OTHER_ERROR, _("Unable to register new account. Error occurred.\n")); goto exit_err; } @@ -1307,7 +1310,8 @@ if (!(ev = gg_watch_fd(info->session))) { purple_debug_error("gg", "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n"); - purple_connection_error(gc, _("Unable to read socket")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to read socket")); return; } @@ -1460,7 +1464,8 @@ if (!(ev = gg_watch_fd(info->session))) { purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n"); - purple_connection_error(gc, _("Unable to read socket")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to read socket")); return; } purple_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd); @@ -1506,7 +1511,9 @@ case GG_EVENT_CONN_FAILED: purple_input_remove(gc->inpa); gc->inpa = 0; - purple_connection_error(gc, _("Connection failed.")); + purple_connection_error_reason (gc, + PURPLE_REASON_NETWORK_ERROR, + _("Connection failed.")); break; default: purple_debug_error("gg", "strange event: %d\n", ev->type); @@ -1712,7 +1719,8 @@ info->session = gg_login(glp); if (info->session == NULL) { - purple_connection_error(gc, _("Connection failed.")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection failed.")); g_free(glp); return; } @@ -1995,7 +2003,8 @@ if (gg_ping(info->session) < 0) { purple_debug_info("gg", "Not connected to the server " "or gg_session is not correct\n"); - purple_connection_error(gc, _("Not connected to the server.")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Not connected to the server.")); } } /* }}} */ diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/irc/irc.c --- a/libpurple/protocols/irc/irc.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/irc/irc.c Fri Oct 12 23:26:11 2007 +0000 @@ -123,8 +123,9 @@ if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { - purple_connection_error(purple_account_get_connection(irc->account), - _("Server has disconnected")); + PurpleConnection *gc = purple_account_get_connection(irc->account); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Server has disconnected")); return; } @@ -161,8 +162,9 @@ /* purple_debug(PURPLE_DEBUG_MISC, "irc", "sent%s: %s", irc->gsc ? " (ssl)" : "", tosend); */ if (ret <= 0 && errno != EAGAIN) { - purple_connection_error(purple_account_get_connection(irc->account), - _("Server has disconnected")); + PurpleConnection *gc = purple_account_get_connection(irc->account); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Server has disconnected")); } else if (ret < buflen) { if (ret < 0) ret = 0; @@ -295,7 +297,8 @@ gc->flags |= PURPLE_CONNECTION_NO_NEWLINES; if (strpbrk(username, " \t\v\r\n") != NULL) { - purple_connection_error(gc, _("IRC nicks may not contain whitespace")); + purple_connection_error_reason (gc, PURPLE_REASON_INVALID_SETTINGS, + _("IRC nicks may not contain whitespace")); return; } @@ -324,7 +327,8 @@ purple_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT), irc_login_cb_ssl, irc_ssl_connect_failure, gc); } else { - purple_connection_error(gc, _("SSL support unavailable")); + purple_connection_error_reason (gc, PURPLE_REASON_NO_SSL_SUPPORT, + _("SSL support unavailable")); return; } } @@ -335,7 +339,8 @@ purple_account_get_int(account, "port", IRC_DEFAULT_PORT), irc_login_cb, gc) == NULL) { - purple_connection_error(gc, _("Couldn't create socket")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Couldn't create socket")); return; } } @@ -352,7 +357,6 @@ if (pass && *pass) { buf = irc_format(irc, "vv", "PASS", pass); if (irc_send(irc, buf) < 0) { -/* purple_connection_error(gc, "Error sending password"); */ g_free(buf); return FALSE; } @@ -384,14 +388,12 @@ strlen(realname) ? realname : IRC_DEFAULT_ALIAS); g_free(tmp); if (irc_send(irc, buf) < 0) { -/* purple_connection_error(gc, "Error registering with server");*/ g_free(buf); return FALSE; } g_free(buf); buf = irc_format(irc, "vn", "NICK", purple_connection_get_display_name(gc)); if (irc_send(irc, buf) < 0) { -/* purple_connection_error(gc, "Error sending nickname");*/ g_free(buf); return FALSE; } @@ -418,7 +420,8 @@ struct irc_conn *irc = gc->proto_data; if (source < 0) { - purple_connection_error(gc, _("Couldn't connect to host")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Couldn't connect to host")); return; } @@ -438,7 +441,7 @@ irc->gsc = NULL; - purple_connection_error(gc, purple_ssl_strerror(error)); + purple_connection_ssl_error (gc, error); } static void irc_close(PurpleConnection *gc) @@ -606,10 +609,12 @@ /* Try again later */ return; } else if (len < 0) { - purple_connection_error(gc, _("Read error")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Read error")); return; } else if (len == 0) { - purple_connection_error(gc, _("Server has disconnected")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Server has disconnected")); return; } @@ -631,10 +636,12 @@ if (len < 0 && errno == EAGAIN) { return; } else if (len < 0) { - purple_connection_error(gc, _("Read error")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Read error")); return; } else if (len == 0) { - purple_connection_error(gc, _("Server has disconnected")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Server has disconnected")); return; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/irc/msgs.c --- a/libpurple/protocols/irc/msgs.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/irc/msgs.c Fri Oct 12 23:26:11 2007 +0000 @@ -913,9 +913,8 @@ _("Your selected nickname was rejected by the server. It probably contains invalid characters.")); } else { - gc->wants_to_die = TRUE; - purple_connection_error(purple_account_get_connection(irc->account), - _("Your selected account name was rejected by the server. It probably contains invalid characters.")); + purple_connection_error_reason (gc, PURPLE_REASON_INVALID_SETTINGS, + _("Your selected account name was rejected by the server. It probably contains invalid characters.")); } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/irc/parse.c --- a/libpurple/protocols/irc/parse.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/irc/parse.c Fri Oct 12 23:26:11 2007 +0000 @@ -612,6 +612,7 @@ struct _irc_msg *msgent; char *cur, *end, *tmp, *from, *msgname, *fmt, **args, *msg; guint i; + PurpleConnection *gc = purple_account_get_connection(irc->account); irc->recv_time = time(NULL); @@ -620,7 +621,7 @@ * TODO: It should be passed as an array of bytes and a length * instead of a null terminated string. */ - purple_signal_emit(_irc_plugin, "irc-receiving-text", purple_account_get_connection(irc->account), &input); + purple_signal_emit(_irc_plugin, "irc-receiving-text", gc, &input); if (!strncmp(input, "PING ", 5)) { msg = irc_format(irc, "vv", "PONG", input + 5); @@ -630,10 +631,11 @@ } else if (!strncmp(input, "ERROR ", 6)) { if (g_utf8_validate(input, -1, NULL)) { char *tmp = g_strdup_printf("%s\n%s", _("Disconnected."), input); - purple_connection_error(purple_account_get_connection(irc->account), tmp); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); } else - purple_connection_error(purple_account_get_connection(irc->account), _("Disconnected.")); + purple_connection_error_reason (gc, + PURPLE_REASON_NETWORK_ERROR, _("Disconnected.")); return; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/adhoccommands.c --- a/libpurple/protocols/jabber/adhoccommands.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Fri Oct 12 23:26:11 2007 +0000 @@ -132,7 +132,7 @@ const char *type = xmlnode_get_attrib(packet,"type"); if(type && !strcmp(type,"error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); if(!msg) msg = g_strdup(_("Unknown Error")); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Fri Oct 12 23:26:11 2007 +0000 @@ -50,7 +50,8 @@ "", -1); return TRUE; } else if(xmlnode_get_child(starttls, "required")) { - purple_connection_error(js->gc, _("Server requires TLS/SSL for login. No TLS/SSL support found.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NO_SSL_SUPPORT, + _("Server requires TLS/SSL for login. No TLS/SSL support found.")); return TRUE; } } @@ -113,7 +114,8 @@ static void disallow_plaintext_auth(PurpleAccount *account) { - purple_connection_error(account->gc, _("Server requires plaintext authentication over an unencrypted stream")); + purple_connection_error_reason (account->gc, PURPLE_REASON_ENCRYPTION_ERROR, + _("Server requires plaintext authentication over an unencrypted stream")); } #ifdef HAVE_CYRUS_SASL @@ -331,7 +333,9 @@ * error here. */ } else { - purple_connection_error(js->gc, _("Server does not use any supported authentication method")); + purple_connection_error_reason (js->gc, + PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE, + _("Server does not use any supported authentication method")); return; } /* not reached */ @@ -386,7 +390,9 @@ jabber_send(js, auth); xmlnode_free(auth); } else { - purple_connection_error(js->gc, "SASL authentication failed\n"); + purple_connection_error_reason (js->gc, + PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE, + "SASL authentication failed\n"); } } @@ -459,7 +465,8 @@ mechs = xmlnode_get_child(packet, "mechanisms"); if(!mechs) { - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); return; } @@ -519,7 +526,7 @@ } finish_plaintext_authentication(js); } else { - purple_connection_error(js->gc, + purple_connection_error_reason (js->gc, PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE, _("Server does not use any supported authentication method")); } #endif @@ -532,20 +539,22 @@ if(type && !strcmp(type, "result")) { jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); } else { - char *msg = jabber_parse_error(js, packet); + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; + char *msg = jabber_parse_error(js, packet, &reason); xmlnode *error; const char *err_code; + /* FIXME: Why is this not in jabber_parse_error? */ if((error = xmlnode_get_child(packet, "error")) && (err_code = xmlnode_get_attrib(error, "code")) && !strcmp(err_code, "401")) { - js->gc->wants_to_die = TRUE; + reason = PURPLE_REASON_AUTHENTICATION_FAILED; /* Clear the pasword if it isn't being saved */ if (!purple_account_get_remember_password(js->gc->account)) purple_account_set_password(js->gc->account, NULL); } - purple_connection_error(js->gc, msg); + purple_connection_error_reason (js->gc, reason, msg); g_free(msg); } } @@ -558,11 +567,13 @@ const char *pw = purple_connection_get_password(js->gc); if(!type) { - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); return; } else if(!strcmp(type, "error")) { - char *msg = jabber_parse_error(js, packet); - purple_connection_error(js->gc, msg); + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; + char *msg = jabber_parse_error(js, packet, &reason); + purple_connection_error_reason (js->gc, reason, msg); g_free(msg); } else if(!strcmp(type, "result")) { query = xmlnode_get_child(packet, "query"); @@ -606,8 +617,9 @@ } finish_plaintext_authentication(js); } else { - purple_connection_error(js->gc, - _("Server does not use any supported authentication method")); + purple_connection_error_reason (js->gc, + PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE, + _("Server does not use any supported authentication method")); return; } } @@ -773,7 +785,8 @@ GHashTable *parts; if(!enc_in) { - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); return; } @@ -794,7 +807,8 @@ "", -1); } else { - purple_connection_error(js->gc, _("Invalid challenge from server")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid challenge from server")); } g_free(js->expected_rspauth); } else { @@ -817,7 +831,8 @@ realm = js->user->domain; if (nonce == NULL || realm == NULL) - purple_connection_error(js->gc, _("Invalid challenge from server")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid challenge from server")); else { GString *response = g_string_new(""); char *a2; @@ -889,7 +904,8 @@ g_free(dec_in); if (js->sasl_state != SASL_CONTINUE && js->sasl_state != SASL_OK) { purple_debug_error("jabber", "Error is %d : %s\n",js->sasl_state,sasl_errdetail(js->sasl)); - purple_connection_error(js->gc, _("SASL error")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("SASL error")); return; } else { response = xmlnode_new("response"); @@ -914,7 +930,8 @@ #endif if(!ns || strcmp(ns, "urn:ietf:params:xml:ns:xmpp-sasl")) { - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); return; } @@ -939,7 +956,8 @@ if (js->sasl_state != SASL_OK) { /* This should never happen! */ - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); } } /* If we've negotiated a security layer, we need to enable it */ @@ -955,12 +973,14 @@ void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet) { - char *msg = jabber_parse_error(js, packet); + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; + char *msg = jabber_parse_error(js, packet, &reason); if(!msg) { - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); } else { - purple_connection_error(js->gc, msg); + purple_connection_error_reason (js->gc, reason, msg); g_free(msg); } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Fri Oct 12 23:26:11 2007 +0000 @@ -2334,7 +2334,7 @@ return; if(!(type = xmlnode_get_attrib(packet, "type")) || !strcmp(type, "error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); if(!msg) msg = g_strdup(_("Unknown error")); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/chat.c Fri Oct 12 23:26:11 2007 +0000 @@ -391,7 +391,7 @@ } } } else if(!strcmp(type, "error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg); @@ -465,7 +465,7 @@ const char *type = xmlnode_get_attrib(packet, "type"); if(type && !strcmp(type, "error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); @@ -534,7 +534,7 @@ } } } else if(!strcmp(type, "error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); @@ -673,7 +673,7 @@ return; if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) { - char *err = jabber_parse_error(js,packet); + char *err = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error"), _("Error retrieving room list"), err); purple_roomlist_set_in_progress(js->roomlist, FALSE); @@ -684,7 +684,7 @@ } if(!(query = xmlnode_get_child(packet, "query"))) { - char *err = jabber_parse_error(js, packet); + char *err = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error"), _("Error retrieving room list"), err); purple_roomlist_set_in_progress(js->roomlist, FALSE); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Oct 12 23:26:11 2007 +0000 @@ -89,7 +89,8 @@ if(js->unregistration) jabber_unregister_account_cb(js); } else { - purple_connection_error(js->gc, _("Error initializing session")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + ("Error initializing session")); } } @@ -120,15 +121,17 @@ JabberBuddy *my_jb = NULL; jabber_id_free(js->user); if(!(js->user = jabber_id_new(full_jid))) { - purple_connection_error(js->gc, _("Invalid response from server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid response from server.")); } if((my_jb = jabber_buddy_find(js, full_jid, TRUE))) my_jb->subscription |= JABBER_SUB_BOTH; g_free(full_jid); } } else { - char *msg = jabber_parse_error(js, packet); - purple_connection_error(js->gc, msg); + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; + char *msg = jabber_parse_error(js, packet, &reason); + purple_connection_error_reason (js->gc, reason, msg); g_free(msg); } @@ -141,8 +144,8 @@ if(jabber_process_starttls(js, packet)) return; } else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) { - js->gc->wants_to_die = TRUE; - purple_connection_error(js->gc, _("You require encryption, but it is not available on this server.")); + purple_connection_error_reason (js->gc, PURPLE_REASON_ENCRYPTION_ERROR, + _("You require encryption, but it is not available on this server.")); return; } @@ -173,9 +176,11 @@ static void jabber_stream_handle_error(JabberStream *js, xmlnode *packet) { - char *msg = jabber_parse_error(js, packet); + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; + char *msg = jabber_parse_error(js, packet, &reason); - purple_connection_error(js->gc, msg); + purple_connection_error_reason (js->gc, reason, msg); + g_free(msg); } @@ -256,7 +261,8 @@ if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { - purple_connection_error(js->gc, _("Write error")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Write error")); return; } @@ -309,7 +315,9 @@ } if (ret < 0 && errno != EAGAIN) - purple_connection_error(js->gc, _("Write error")); + purple_connection_error_reason (js->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Write error")); else if (ret < olen) { if (ret < 0) ret = 0; @@ -337,7 +345,9 @@ } if (ret < 0 && errno != EAGAIN) - purple_connection_error(js->gc, _("Write error")); + purple_connection_error_reason (js->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Write error")); else if (ret < len) { if (ret < 0) ret = 0; @@ -405,7 +415,9 @@ if(errno == EAGAIN) return; else - purple_connection_error(gc, _("Read Error")); + purple_connection_error_reason (js->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Read Error")); } static void @@ -442,7 +454,9 @@ } else if(errno == EAGAIN) { return; } else { - purple_connection_error(gc, _("Read Error")); + purple_connection_error_reason (js->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Read Error")); } } @@ -481,7 +495,7 @@ gchar *tmp; tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), error); - purple_connection_error(gc, tmp); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -509,7 +523,7 @@ js = gc->proto_data; js->gsc = NULL; - purple_connection_error(gc, purple_ssl_strerror(error)); + purple_connection_ssl_error (gc, error); } static void tls_init(JabberStream *js) @@ -526,7 +540,8 @@ if (purple_proxy_connect(js->gc, js->gc->account, host, port, jabber_login_callback, js->gc) == NULL) - purple_connection_error(js->gc, _("Unable to create socket")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to create socket")); } static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data) @@ -572,12 +587,14 @@ js->old_length = -1; if(!js->user) { - purple_connection_error(gc, _("Invalid XMPP ID")); + purple_connection_error_reason (gc, PURPLE_REASON_INVALID_SETTINGS, + _("Invalid XMPP ID")); return; } if (!js->user->domain || *(js->user->domain) == '\0') { - purple_connection_error(gc, _("Invalid XMPP ID. Domain must be set.")); + purple_connection_error_reason (gc, PURPLE_REASON_INVALID_SETTINGS, + _("Invalid XMPP ID. Domain must be set.")); return; } @@ -607,7 +624,8 @@ purple_account_get_int(account, "port", 5223), jabber_login_callback_ssl, jabber_ssl_connect_failure, js->gc); } else { - purple_connection_error(js->gc, _("SSL support unavailable")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NO_SSL_SUPPORT, + _("SSL support unavailable")); } } @@ -665,7 +683,7 @@ _("Registration Successful"), buf); g_free(buf); } else { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); if(!msg) msg = g_strdup(_("Unknown Error")); @@ -695,7 +713,7 @@ _("Unregistration Successful"), buf); g_free(buf); } else { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); if(!msg) msg = g_strdup(_("Unknown Error")); @@ -1060,7 +1078,8 @@ js->old_length = -1; if(!js->user) { - purple_connection_error(gc, _("Invalid XMPP ID")); + purple_connection_error_reason (gc, PURPLE_REASON_INVALID_SETTINGS, + _("Invalid XMPP ID")); return; } @@ -1092,7 +1111,8 @@ purple_account_get_int(account, "port", 5222), jabber_login_callback_ssl, jabber_ssl_connect_failure, gc); } else { - purple_connection_error(gc, _("SSL support unavailable")); + purple_connection_error_reason (gc, PURPLE_REASON_NO_SSL_SUPPORT, + _("SSL support unavailable")); } } @@ -1115,7 +1135,7 @@ PurpleAccount *account = purple_connection_get_account(js->gc); const char *type = xmlnode_get_attrib(packet,"type"); if(!strcmp(type,"error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error unregistering account"), _("Error unregistering account"), msg); @@ -1641,7 +1661,7 @@ purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"), _("Your password has been changed.")); } else { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error changing password"), _("Error changing password"), msg); @@ -1805,13 +1825,18 @@ } -char *jabber_parse_error(JabberStream *js, xmlnode *packet) +char *jabber_parse_error(JabberStream *js, + xmlnode *packet, + PurpleDisconnectReason *reason) { xmlnode *error; const char *code = NULL, *text = NULL; const char *xmlns = xmlnode_get_namespace(packet); char *cdata = NULL; +#define SET_REASON(x) \ + if(reason != NULL) { *reason = x; } + if((error = xmlnode_get_child(packet, "error"))) { cdata = xmlnode_get_data(error); code = xmlnode_get_attrib(error, "code"); @@ -1863,41 +1888,41 @@ text = _("Unknown Error"); } } else if(xmlns && !strcmp(xmlns, "urn:ietf:params:xml:ns:xmpp-sasl")) { + /* Most common reason can be the default */ + SET_REASON(PURPLE_REASON_AUTHENTICATION_FAILED); if(xmlnode_get_child(packet, "aborted")) { - js->gc->wants_to_die = TRUE; text = _("Authorization Aborted"); } else if(xmlnode_get_child(packet, "incorrect-encoding")) { + SET_REASON(PURPLE_REASON_NETWORK_ERROR); text = _("Incorrect encoding in authorization"); } else if(xmlnode_get_child(packet, "invalid-authzid")) { - js->gc->wants_to_die = TRUE; text = _("Invalid authzid"); } else if(xmlnode_get_child(packet, "invalid-mechanism")) { - js->gc->wants_to_die = TRUE; text = _("Invalid Authorization Mechanism"); } else if(xmlnode_get_child(packet, "mechanism-too-weak")) { - js->gc->wants_to_die = TRUE; text = _("Authorization mechanism too weak"); } else if(xmlnode_get_child(packet, "not-authorized")) { - js->gc->wants_to_die = TRUE; /* Clear the pasword if it isn't being saved */ if (!purple_account_get_remember_password(js->gc->account)) purple_account_set_password(js->gc->account, NULL); text = _("Not Authorized"); } else if(xmlnode_get_child(packet, "temporary-auth-failure")) { + SET_REASON(PURPLE_REASON_NETWORK_ERROR); text = _("Temporary Authentication Failure"); } else { - js->gc->wants_to_die = TRUE; text = _("Authentication Failure"); } } else if(!strcmp(packet->name, "stream:error") || (!strcmp(packet->name, "error") && xmlns && !strcmp(xmlns, "http://etherx.jabber.org/streams"))) { + /* Most common reason as default: */ + SET_REASON(PURPLE_REASON_NETWORK_ERROR); if(xmlnode_get_child(packet, "bad-format")) { text = _("Bad Format"); } else if(xmlnode_get_child(packet, "bad-namespace-prefix")) { text = _("Bad Namespace Prefix"); } else if(xmlnode_get_child(packet, "conflict")) { - js->gc->wants_to_die = TRUE; + SET_REASON(PURPLE_REASON_NAME_IN_USE); text = _("Resource Conflict"); } else if(xmlnode_get_child(packet, "connection-timeout")) { text = _("Connection Timeout"); @@ -1946,6 +1971,8 @@ } } +#undef SET_REASON + if(text || cdata) { char *ret = g_strdup_printf("%s%s%s", code ? code : "", code ? ": " : "", text ? text : cdata); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.h Fri Oct 12 23:26:11 2007 +0000 @@ -216,7 +216,14 @@ char *jabber_get_next_id(JabberStream *js); -char *jabber_parse_error(JabberStream *js, xmlnode *packet); +/** Parse an error into a human-readable string and optionally a disconnect + * reason. + * @param js the stream on which the error occurred. + * @param packet the error packet + * @param reason where to store the disconnection reason, or @c NULL if you + * don't care or you don't intend to close the connection. + */ +char *jabber_parse_error(JabberStream *js, xmlnode *packet, PurpleDisconnectReason *reason); void jabber_add_feature(const gchar *shortname, const gchar *namespace, JabberFeatureEnabled cb); /* cb may be NULL */ void jabber_remove_feature(const gchar *shortname); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/parser.c --- a/libpurple/protocols/jabber/parser.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/parser.c Fri Oct 12 23:26:11 2007 +0000 @@ -193,7 +193,8 @@ js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL); xmlParseChunk(js->context, "", 0, 0); } else if (xmlParseChunk(js->context, buf, len, 0) < 0) { - purple_connection_error(js->gc, _("XML Parse error")); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, + _("XML Parse error")); } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Fri Oct 12 23:26:11 2007 +0000 @@ -429,7 +429,7 @@ } if(type && !strcmp(type, "error")) { - char *msg = jabber_parse_error(js, packet); + char *msg = jabber_parse_error(js, packet, NULL); state = JABBER_BUDDY_STATE_ERROR; jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); @@ -561,7 +561,7 @@ char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); if(state == JABBER_BUDDY_STATE_ERROR) { - char *title, *msg = jabber_parse_error(js, packet); + char *title, *msg = jabber_parse_error(js, packet, NULL); if(chat->conv) { title = g_strdup_printf(_("Error in chat %s"), from); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/msn/contact.c --- a/libpurple/protocols/msn/contact.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/msn/contact.c Fri Oct 12 23:26:11 2007 +0000 @@ -945,7 +945,7 @@ msn_get_address_book(contact, NULL, NULL); */ msn_session_disconnect(session); - purple_connection_error(session->account->gc, _("Unable to retrieve MSN Address Book")); + purple_connection_error_reason(session->account->gc, PURPLE_REASON_NETWORK_ERROR, _("Unable to retrieve MSN Address Book")); return FALSE; } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Fri Oct 12 23:26:11 2007 +0000 @@ -820,8 +820,7 @@ if (!purple_ssl_is_supported()) { - gc->wants_to_die = TRUE; - purple_connection_error(gc, + purple_connection_error_reason (gc, PURPLE_REASON_NO_SSL_SUPPORT, _("SSL support is needed for MSN. Please install a supported " "SSL library.")); return; @@ -850,7 +849,8 @@ purple_account_set_username(account, username); if (!msn_session_connect(session, host, port, http_method)) - purple_connection_error(gc, _("Failed to connect to server.")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Failed to connect to server.")); } static void diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/msn/session.c Fri Oct 12 23:26:11 2007 +0000 @@ -325,6 +325,7 @@ const char *info) { PurpleConnection *gc; + PurpleDisconnectReason reason; char *msg; gc = purple_account_get_connection(session->account); @@ -332,49 +333,56 @@ switch (error) { case MSN_ERROR_SERVCONN: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(info); break; case MSN_ERROR_UNSUPPORTED_PROTOCOL: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(_("Our protocol is not supported by the " "server.")); break; case MSN_ERROR_HTTP_MALFORMED: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(_("Error parsing HTTP.")); break; case MSN_ERROR_SIGN_OTHER: - gc->wants_to_die = TRUE; + reason = PURPLE_REASON_NAME_IN_USE; msg = g_strdup(_("You have signed on from another location.")); if (!purple_account_get_remember_password(session->account)) purple_account_set_password(session->account, NULL); break; case MSN_ERROR_SERV_UNAVAILABLE: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(_("The MSN servers are temporarily " "unavailable. Please wait and try " "again.")); break; case MSN_ERROR_SERV_DOWN: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(_("The MSN servers are going down " "temporarily.")); break; case MSN_ERROR_AUTH: - gc->wants_to_die = TRUE; + reason = PURPLE_REASON_AUTHENTICATION_FAILED; msg = g_strdup_printf(_("Unable to authenticate: %s"), (info == NULL ) ? _("Unknown error") : info); break; case MSN_ERROR_BAD_BLIST: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(_("Your MSN buddy list is temporarily " "unavailable. Please wait and try " "again.")); break; default: + reason = PURPLE_REASON_NETWORK_ERROR; msg = g_strdup(_("Unknown error.")); break; } msn_session_disconnect(session); - purple_connection_error(gc, msg); + purple_connection_error_reason (gc, reason, msg); g_free(msg); } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Fri Oct 12 23:26:11 2007 +0000 @@ -291,8 +291,8 @@ /* Notify an error message also, because this is important! */ purple_notify_error(acct, _("MySpaceIM Error"), str, NULL); - gc->wants_to_die = TRUE; - purple_connection_error(gc, str); + purple_connection_error_reason (gc, + PURPLE_REASON_AUTHENTICATION_FAILED, str); g_free(str); return; } @@ -315,7 +315,8 @@ if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) { /* TODO: try other ports if in auto mode, then save * working port and try that first next time. */ - purple_connection_error(gc, _("Couldn't create socket")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Couldn't create socket")); return; } } @@ -353,7 +354,8 @@ if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) { purple_debug_info("msim", "bad nc length: %x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH); - purple_connection_error(session->gc, _("Unexpected challenge length from server")); + purple_connection_error_reason (session->gc, PURPLE_REASON_NETWORK_ERROR, + _("Unexpected challenge length from server")); return FALSE; } @@ -826,7 +828,6 @@ serv_got_typing_stopped(session->gc, username); g_free(username); - g_free(text); return TRUE; } @@ -1290,7 +1291,8 @@ purple_debug_info("msim", "msim_check_alive: %s > interval of %d, presumed dead\n", errmsg, MSIM_KEEPALIVE_INTERVAL); - purple_connection_error(session->gc, errmsg); + purple_connection_error_reason (session->gc, + PURPLE_REASON_NETWORK_ERROR, errmsg); purple_notify_error(session->gc, NULL, errmsg, NULL); @@ -1556,7 +1558,7 @@ purple_notify_error(session->account, _("No username set"), _("Please go to http://editprofile.myspace.com/index.cfm?fuseaction=profile.username and choose a username and try to login again."), NULL); - purple_connection_error(session->gc, _("No username set")); + purple_connection_error_reason (session->gc, PURPLE_REASON_AUTHENTICATION_FAILED, _("No username set")); return FALSE; } @@ -1792,16 +1794,21 @@ /* Destroy session if fatal. */ if (msim_msg_get(msg, "fatal")) { + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; purple_debug_info("msim", "fatal error, closing\n"); switch (err) { case 260: /* Incorrect password */ + reason = PURPLE_REASON_AUTHENTICATION_FAILED; + if (!purple_account_get_remember_password(session->account)) + purple_account_set_password(session->account, NULL); + break; case 6: /* Logged in elsewhere */ - session->gc->wants_to_die = TRUE; + reason = PURPLE_REASON_NAME_IN_USE; if (!purple_account_get_remember_password(session->account)) purple_account_set_password(session->account, NULL); break; } - purple_connection_error(session->gc, full_errmsg); + purple_connection_error_reason (session->gc, reason, full_errmsg); } else { purple_notify_error(session->account, _("MySpaceIM Error"), full_errmsg, NULL); } @@ -1871,7 +1878,6 @@ purple_blist_add_buddy(buddy, NULL, NULL, NULL); user = msim_get_user_from_buddy(buddy); - /* TODO: free user. memory leak? */ /* All buddies on list should have 'uid' integer associated with them. */ purple_blist_node_set_int(&buddy->node, "UserID", msim_msg_get_integer(msg, "f")); @@ -2313,7 +2319,8 @@ /* libpurple/eventloop.h only defines these two */ if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) { purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond); - purple_connection_error(gc, _("Invalid input condition")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Invalid input condition")); return; } @@ -2331,7 +2338,8 @@ purple_debug_error("msim", "msim_input_cb: %d-byte read buffer full! rxoff=%d\n", MSIM_READ_BUF_SIZE, session->rxoff); - purple_connection_error(gc, _("Read buffer full")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Read buffer full")); return; } @@ -2350,11 +2358,13 @@ purple_debug_error("msim", "msim_input_cb: read error, ret=%d, " "error=%s, source=%d, fd=%d (%X))\n", n, strerror(errno), source, session->fd, session->fd); - purple_connection_error(gc, _("Read error")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Read error")); return; } else if (n == 0) { purple_debug_info("msim", "msim_input_cb: server disconnected\n"); - purple_connection_error(gc, _("Server has disconnected")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Server has disconnected")); return; } @@ -2362,7 +2372,8 @@ purple_debug_info("msim_input_cb", "received %d bytes, pushing rxoff to %d, over buffer size of %d\n", n, n + session->rxoff, MSIM_READ_BUF_SIZE); /* TODO: g_realloc like msn, yahoo, irc, jabber? */ - purple_connection_error(gc, _("Read buffer full")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Read buffer full")); } /* Null terminate */ @@ -2377,7 +2388,8 @@ purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes" "--null byte encountered?\n", strlen(session->rxbuf + session->rxoff), n); - //purple_connection_error(gc, "Invalid message - null byte on input"); + /*purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + "Invalid message - null byte on input"); */ return; } #endif @@ -2400,7 +2412,8 @@ msg = msim_parse(g_strdup(session->rxbuf)); if (!msg) { purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n"); - purple_connection_error(gc, _("Unparseable message")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Unparseable message")); } else { /* Process message and then free it (processing function should * clone message if it wants to keep it afterwards.) */ @@ -2467,9 +2480,8 @@ session = (MsimSession *)gc->proto_data; if (source < 0) { - purple_connection_error(gc, _("Couldn't connect to host")); - purple_connection_error(gc, g_strdup_printf( - _("Couldn't connect to host: %s (%d)"), + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + g_strdup_printf(_("Couldn't connect to host: %s (%d)"), error_message ? error_message : "no message given", source)); return; @@ -2670,7 +2682,6 @@ /* TODO: other fields, store in 'user' */ msim_msg_free(contact_info); - g_free(username); } /** Add first ContactID in contact_info to buddy's list. Used to add diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/novell/novell.c --- a/libpurple/protocols/novell/novell.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/novell/novell.c Fri Oct 12 23:26:11 2007 +0000 @@ -120,21 +120,27 @@ _check_for_disconnect(user, rc); } else { - + PurpleDisconnectReason reason; char *err = g_strdup_printf(_("Login failed (%s)."), nm_error_to_string (ret_code)); - /* Don't attempt to auto-reconnect if our password - * was invalid. - */ - if (ret_code == NMERR_AUTHENTICATION_FAILED || - ret_code == NMERR_CREDENTIALS_MISSING || - ret_code == NMERR_PASSWORD_INVALID) { - if (!purple_account_get_remember_password(gc->account)) - purple_account_set_password(gc->account, NULL); - gc->wants_to_die = TRUE; + switch (ret_code) { + case NMERR_AUTHENTICATION_FAILED: + case NMERR_CREDENTIALS_MISSING: + case NMERR_PASSWORD_INVALID: + /* Don't attempt to auto-reconnect if our + * password was invalid. + */ + if (!purple_account_get_remember_password(gc->account)) + purple_account_set_password(gc->account, NULL); + reason = PURPLE_REASON_AUTHENTICATION_FAILED; + break; + default: + /* FIXME: There are other reasons login could fail */ + reason = PURPLE_REASON_NETWORK_ERROR; } - purple_connection_error(gc, err); + + purple_connection_error_reason (gc, reason, err); g_free(err); } } @@ -1120,8 +1126,8 @@ if (_is_disconnect_error(err)) { - purple_connection_error(gc, _("Error communicating with server." - " Closing connection.")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Error communicating with server. Closing connection.")); return TRUE; } @@ -1667,7 +1673,7 @@ user = gc->proto_data; user->conn->ssl_conn->data = NULL; - purple_connection_error(gc, _("Unable to make SSL connection to server.")); + purple_connection_ssl_error (gc, error); } static void @@ -1690,9 +1696,9 @@ if (_is_disconnect_error(rc)) { - purple_connection_error(gc, - _("Error communicating with server." - " Closing connection.")); + purple_connection_error_reason (gc, + PURPLE_REASON_NETWORK_ERROR, + _("Error communicating with server. Closing connection.")); } else { purple_debug(PURPLE_DEBUG_INFO, "novell", "Error processing event or response (%d).\n", rc); @@ -1731,7 +1737,8 @@ conn->connected = TRUE; purple_ssl_input_add(gsc, novell_ssl_recv_cb, gc); } else { - purple_connection_error(gc, _("Unable to connect to server.")); + purple_connection_error_reason (gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to connect to server.")); } purple_connection_update_progress(gc, _("Waiting for response..."), @@ -2011,10 +2018,10 @@ gc = purple_account_get_connection(account); if (gc) { - gc->wants_to_die = TRUE; /* we don't want to reconnect in this case */ if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error(gc, _("You have been logged out because you" + purple_connection_error_reason (gc, PURPLE_REASON_NAME_IN_USE, + _("You have been logged out because you" " logged in at another workstation.")); } } @@ -2169,9 +2176,9 @@ */ /* ...but for now just error out with a nice message. */ - purple_connection_error(gc, _("Unable to connect to server." - " Please enter the address of the server" - " you wish to connect to.")); + purple_connection_error_reason (gc, PURPLE_REASON_INVALID_SETTINGS, + _("Unable to connect to server. Please enter the " + "address of the server you wish to connect to.")); return; } @@ -2197,8 +2204,9 @@ user->conn->addr, user->conn->port, novell_ssl_connected_cb, novell_ssl_connect_error, gc); if (user->conn->ssl_conn->data == NULL) { - purple_connection_error(gc, _("Error." - " SSL support is not installed.")); + purple_connection_error_reason (gc, + PURPLE_REASON_NO_SSL_SUPPORT, + _("Error. SSL support is not installed.")); } } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/oscar/flap_connection.c --- a/libpurple/protocols/oscar/flap_connection.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Fri Oct 12 23:26:11 2007 +0000 @@ -380,11 +380,13 @@ { /* No more FLAP connections! Sign off this PurpleConnection! */ gchar *tmp; + PurpleDisconnectReason reason = PURPLE_REASON_NETWORK_ERROR; + if (conn->disconnect_code == 0x0001) { + reason = PURPLE_REASON_NAME_IN_USE; tmp = g_strdup(_("You have signed on from another location.")); if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - od->gc->wants_to_die = TRUE; } else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED) tmp = g_strdup(_("Server closed the connection.")); else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION) @@ -404,7 +406,7 @@ if (tmp != NULL) { - purple_connection_error(od->gc, tmp); + purple_connection_error_reason(od->gc, reason, tmp); g_free(tmp); } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Oct 12 23:26:11 2007 +0000 @@ -994,7 +994,7 @@ gchar *msg; msg = g_strdup_printf(_("Could not connect to authentication server:\n%s"), error_message); - purple_connection_error(gc, msg); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, msg); g_free(msg); } else if (conn->type == SNAC_FAMILY_LOCATE) @@ -1002,7 +1002,7 @@ gchar *msg; msg = g_strdup_printf(_("Could not connect to BOS server:\n%s"), error_message); - purple_connection_error(gc, msg); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, msg); g_free(msg); } else @@ -1260,8 +1260,7 @@ if (!aim_snvalid(purple_account_get_username(account))) { gchar *buf; buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid. Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); - gc->wants_to_die = TRUE; - purple_connection_error(gc, buf); + purple_connection_error_reason(gc, PURPLE_REASON_INVALID_SETTINGS, buf); g_free(buf); } @@ -1282,7 +1281,8 @@ connection_established_cb, newconn); if (newconn->connect_data == NULL) { - purple_connection_error(gc, _("Couldn't connect to host")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Couldn't connect to host")); return; } @@ -1343,43 +1343,37 @@ switch (info->errorcode) { case 0x01: /* Unregistered screen name */ - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("Invalid screen name.")); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, _("Invalid screen name.")); break; case 0x05: /* Incorrect password */ - gc->wants_to_die = TRUE; if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error(gc, _("Incorrect password.")); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, _("Incorrect password.")); break; case 0x11: /* Suspended account */ - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("Your account is currently suspended.")); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, _("Your account is currently suspended.")); break; case 0x14: /* service temporarily unavailable */ - purple_connection_error(gc, _("The AOL Instant Messenger service is temporarily unavailable.")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable.")); break; case 0x18: /* screen name connecting too frequently */ - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; case 0x1c: /* client too old */ - gc->wants_to_die = TRUE; g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), PURPLE_WEBSITE); - purple_connection_error(gc, buf); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, buf); break; case 0x1d: /* IP address connecting too frequently */ - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; default: - purple_connection_error(gc, _("Authentication failed")); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, _("Authentication failed")); break; } purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode); @@ -1409,7 +1403,7 @@ g_free(host); if (newconn->connect_data == NULL) { - purple_connection_error(gc, _("Could Not Connect")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, _("Could Not Connect")); return 0; } @@ -1434,8 +1428,8 @@ PurpleConnection *gc = user_data; /* Disconnect */ - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("The SecurID key entered is invalid.")); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, + _("The SecurID key entered is invalid.")); } static int diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/qq/keep_alive.c --- a/libpurple/protocols/qq/keep_alive.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/qq/keep_alive.c Fri Oct 12 23:26:11 2007 +0000 @@ -84,7 +84,8 @@ /* segments[0] and segment[1] are all 0x30 ("0") */ qd->all_online = strtol(segments[2], NULL, 10); if(0 == qd->all_online) - purple_connection_error(gc, _("Keep alive error")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Keep alive error")); g_free(qd->my_ip); qd->my_ip = g_strdup(segments[3]); qd->my_port = strtol(segments[4], NULL, 10); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/qq/login_logout.c --- a/libpurple/protocols/qq/login_logout.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/qq/login_logout.c Fri Oct 12 23:26:11 2007 +0000 @@ -405,7 +405,7 @@ ">>> %d bytes -> [default] decrypt and dump\n%s", buf_len, hex_dump); try_dump_as_gbk(buf, buf_len); - purple_connection_error(gc, _("Error requesting login token")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, _("Error requesting login token")); } g_free(hex_dump); } @@ -479,13 +479,14 @@ switch (ret) { case QQ_LOGIN_REPLY_PWD_ERROR: - gc->wants_to_die = TRUE; if (!purple_account_get_remember_password(gc->account)) purple_account_set_password(gc->account, NULL); - purple_connection_error(gc, _("Incorrect password.")); + purple_connection_error_reason(gc, + PURPLE_REASON_AUTHENTICATION_FAILED, _("Incorrect password.")); break; case QQ_LOGIN_REPLY_MISC_ERROR: - purple_connection_error(gc, _("Unable to login, check debug log")); + purple_connection_error_reason(gc, + PURPLE_REASON_NETWORK_ERROR, _("Unable to login, check debug log")); break; case QQ_LOGIN_REPLY_OK: purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login replys OK, everything is fine\n"); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/qq/qq.c Fri Oct 12 23:26:11 2007 +0000 @@ -136,7 +136,8 @@ purple_connection_update_progress(gc, _("Connecting"), 0, QQ_CONNECT_STEPS); if (qq_connect(account, qq_server, strtol(qq_port, NULL, 10), use_tcp, FALSE) < 0) - purple_connection_error(gc, _("Unable to connect.")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to connect.")); } /* directly goes for qq_disconnect */ diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/qq/qq_proxy.c --- a/libpurple/protocols/qq/qq_proxy.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/qq/qq_proxy.c Fri Oct 12 23:26:11 2007 +0000 @@ -139,7 +139,7 @@ g_return_if_fail(gc != NULL && gc->proto_data != NULL); if (source < 0) { /* socket returns -1 */ - purple_connection_error(gc, error_message); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, error_message); return; } @@ -494,7 +494,7 @@ ret = send(qd->fd, data, len, 0); } if (ret == -1) - purple_connection_error(qd->gc, strerror(errno)); + purple_connection_error_reason(qd->gc, PURPLE_REASON_NETWORK_ERROR, strerror(errno)); return ret; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/qq/recv_core.c --- a/libpurple/protocols/qq/recv_core.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/qq/recv_core.c Fri Oct 12 23:26:11 2007 +0000 @@ -306,7 +306,8 @@ gc = (PurpleConnection *) data; if(cond != PURPLE_INPUT_READ) { - purple_connection_error(gc, _("Socket error")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Socket error")); return; } @@ -316,7 +317,8 @@ /* here we have UDP proxy suppport */ len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE); if (len <= 0) { - purple_connection_error(gc, _("Unable to read from socket")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to read from socket")); return; } else { _qq_packet_process(buf, len, gc); diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/qq/sendqueue.c --- a/libpurple/protocols/qq/sendqueue.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/qq/sendqueue.c Fri Oct 12 23:26:11 2007 +0000 @@ -120,7 +120,8 @@ case QQ_CMD_KEEP_ALIVE: if (qd->logged_in) { purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Connection lost!\n"); - purple_connection_error(gc, _("Connection lost")); + purple_connection_error_reason(gc, + PURPLE_REASON_NETWORK_ERROR, _("Connection lost")); qd->logged_in = FALSE; } p->resend_times = -1; @@ -128,7 +129,8 @@ case QQ_CMD_LOGIN: case QQ_CMD_REQUEST_LOGIN_TOKEN: if (!qd->logged_in) /* cancel login progress */ - purple_connection_error(gc, _("Login failed, no reply")); + purple_connection_error_reason(gc, + PURPLE_REASON_NETWORK_ERROR, _("Login failed, no reply")); p->resend_times = -1; break; default:{ diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/sametime/sametime.c --- a/libpurple/protocols/sametime/sametime.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/sametime/sametime.c Fri Oct 12 23:26:11 2007 +0000 @@ -414,7 +414,8 @@ } else if(len > 0) { DEBUG_ERROR("write returned %i, %i bytes left unwritten\n", ret, len); - purple_connection_error(pd->gc, _("Connection closed (writing)")); + purple_connection_error_reason(pd->gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection closed (writing)")); #if 0 close(pd->socket); @@ -1552,7 +1553,38 @@ if(GPOINTER_TO_UINT(info) & ERR_FAILURE) { char *err = mwError(GPOINTER_TO_UINT(info)); - purple_connection_error(gc, err); + PurpleDisconnectReason reason; + switch (GPOINTER_TO_UINT(info)) { + case VERSION_MISMATCH: + reason = PURPLE_REASON_OTHER_ERROR; + break; + + case USER_RESTRICTED: + case INCORRECT_LOGIN: + case USER_UNREGISTERED: + case GUEST_IN_USE: + reason = PURPLE_REASON_AUTHENTICATION_FAILED; + break; + + case ENCRYPT_MISMATCH: + case ERR_ENCRYPT_NO_SUPPORT: + case ERR_NO_COMMON_ENCRYPT: + reason = PURPLE_REASON_ENCRYPTION_ERROR; + break; + + case VERIFICATION_DOWN: + reason = PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE; + break; + + case MULTI_SERVER_LOGIN: + case MULTI_SERVER_LOGIN2: + reason = PURPLE_REASON_NAME_IN_USE; + break; + + default: + reason = PURPLE_REASON_NETWORK_ERROR; + } + purple_connection_error_reason(gc, reason, err); g_free(err); } break; @@ -1698,8 +1730,9 @@ } if(! ret) { + const char *msg = _("Connection reset"); DEBUG_INFO("connection reset\n"); - purple_connection_error(pd->gc, _("Connection reset")); + purple_connection_error_reason(pd->gc, PURPLE_REASON_NETWORK_ERROR, msg); } else if(ret < 0) { char *msg = strerror(err); @@ -1707,7 +1740,7 @@ DEBUG_INFO("error in read callback: %s\n", msg); msg = g_strdup_printf(_("Error reading from socket: %s"), msg); - purple_connection_error(pd->gc, msg); + purple_connection_error_reason(pd->gc, PURPLE_REASON_NETWORK_ERROR, msg); g_free(msg); } } @@ -1729,7 +1762,8 @@ } else { /* this is a regular connect, error out */ - purple_connection_error(pd->gc, _("Unable to connect to host")); + const char *msg = _("Unable to connect to host"); + purple_connection_error_reason(pd->gc, PURPLE_REASON_NETWORK_ERROR, msg); } return; @@ -3611,7 +3645,8 @@ static void prompt_host_cancel_cb(PurpleConnection *gc) { - purple_connection_error(gc, _("No Sametime Community Server specified")); + const char *msg = _("No Sametime Community Server specified"); + purple_connection_error_reason(gc, PURPLE_REASON_INVALID_SETTINGS, msg); } @@ -3723,7 +3758,8 @@ purple_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS); if (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL) { - purple_connection_error(gc, _("Unable to connect to host")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to connect to host")); } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/silc/silc.c --- a/libpurple/protocols/silc/silc.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Fri Oct 12 23:26:11 2007 +0000 @@ -214,34 +214,40 @@ /* Close the connection */ if (!sg->detaching) - purple_connection_error(gc, _("Disconnected by server")); + purple_connection_error_reason(gc, + PURPLE_REASON_NETWORK_ERROR, + _("Disconnected by server")); else /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ purple_account_disconnect(purple_connection_get_account(gc)); break; case SILC_CLIENT_CONN_ERROR: - purple_connection_error(gc, _("Error during connecting to SILC Server")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Error during connecting to SILC Server")); g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); break; case SILC_CLIENT_CONN_ERROR_KE: - purple_connection_error(gc, _("Key Exchange failed")); + purple_connection_error_reason(gc, PURPLE_REASON_ENCRYPTION_ERROR, + _("Key Exchange failed")); break; case SILC_CLIENT_CONN_ERROR_AUTH: - purple_connection_error(gc, _("Authentication failed")); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, + _("Authentication failed")); break; case SILC_CLIENT_CONN_ERROR_RESUME: - purple_connection_error(gc, - _("Resuming detached session failed. " - "Press Reconnect to create new connection.")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Resuming detached session failed. " + "Press Reconnect to create new connection.")); g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); break; case SILC_CLIENT_CONN_ERROR_TIMEOUT: - purple_connection_error(gc, _("Connection Timeout")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection Timeout")); break; } @@ -262,7 +268,8 @@ sg = gc->proto_data; if (status != SILC_SOCKET_OK) { - purple_connection_error(gc, _("Connection failed")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection failed")); silc_pkcs_public_key_free(sg->public_key); silc_pkcs_private_key_free(sg->private_key); silc_free(sg); @@ -308,7 +315,8 @@ sg = gc->proto_data; if (source < 0) { - purple_connection_error(gc, _("Connection failed")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection failed")); silc_pkcs_public_key_free(sg->public_key); silc_pkcs_private_key_free(sg->private_key); silc_free(sg); @@ -349,8 +357,8 @@ (char *)purple_account_get_string(account, "private-key", prd), (gc->password == NULL) ? "" : gc->password, &sg->public_key, &sg->private_key)) { - g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair")); - purple_connection_error(gc, pkd); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Could not load SILC key pair")); gc->proto_data = NULL; silc_free(sg); return; @@ -363,7 +371,8 @@ purple_account_get_int(account, "port", 706), silcpurple_login_connected, gc) == NULL) { - purple_connection_error(gc, _("Unable to create connection")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Unable to create connection")); gc->proto_data = NULL; silc_free(sg); return; @@ -392,7 +401,8 @@ /* Allocate SILC client */ client = silc_client_alloc(&ops, ¶ms, gc, NULL); if (!client) { - purple_connection_error(gc, _("Out of memory")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Out of memory")); return; } @@ -434,15 +444,15 @@ /* Init SILC client */ if (!silc_client_init(client, username, hostname, realname, silcpurple_running, account)) { - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("Cannot initialize SILC protocol")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Cannot initialize SILC protocol")); return; } /* Check the ~/.silc dir and create it, and new key pair if necessary. */ if (!silcpurple_check_silc_dir(gc)) { - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("Error loading SILC key pair")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Error loading SILC key pair")); return; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/silc/util.c --- a/libpurple/protocols/silc/util.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/silc/util.c Fri Oct 12 23:26:11 2007 +0000 @@ -212,7 +212,8 @@ (gc->password == NULL) ? "" : gc->password, NULL, NULL, FALSE)) { - purple_connection_error(gc, _("Cannot create SILC key pair\n")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Cannot create SILC key pair\n")); return FALSE; } @@ -254,7 +255,8 @@ (gc->password == NULL) ? "" : gc->password, NULL, NULL, FALSE)) { - purple_connection_error(gc, _("Cannot create SILC key pair\n")); + purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, + _("Cannot create SILC key pair\n")); return FALSE; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/simple/simple.c Fri Oct 12 23:26:11 2007 +0000 @@ -413,7 +413,8 @@ written = 0; else if(written <= 0) { /*TODO: do we really want to disconnect on a failure to write?*/ - purple_connection_error(gc, _("Could not write")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Could not write")); return; } @@ -435,7 +436,8 @@ } if(source < 0) { - purple_connection_error(gc, _("Could not connect")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Could not connect")); return; } @@ -461,7 +463,7 @@ if(!sip->connecting) { purple_debug_info("simple", "connecting to %s port %d\n", sip->realhostname ? sip->realhostname : "{NULL}", sip->realport); if (purple_proxy_connect(gc, sip->account, sip->realhostname, sip->realport, send_later_cb, gc) == NULL) { - purple_connection_error(gc, _("Couldn't create socket")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, _("Couldn't create socket")); } sip->connecting = TRUE; } @@ -1040,11 +1042,11 @@ if(sip->registerstatus != SIMPLE_REGISTER_RETRY) { purple_debug_info("simple", "REGISTER retries %d\n", sip->registrar.retries); if(sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) { - purple_debug_info("simple", "Setting wants_to_die to true.\n"); - sip->gc->wants_to_die = TRUE; if (!purple_account_get_remember_password(sip->gc->account)) purple_account_set_password(sip->gc->account, NULL); - purple_connection_error(sip->gc, _("Incorrect password.")); + purple_connection_error_reason(sip->gc, + PURPLE_REASON_AUTHENTICATION_FAILED, + _("Incorrect password.")); return TRUE; } tmp = sipmsg_find_header(msg, "WWW-Authenticate"); @@ -1057,8 +1059,8 @@ if (sip->registerstatus != SIMPLE_REGISTER_RETRY) { purple_debug_info("simple", "Unrecognized return code for REGISTER.\n"); if (sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) { - sip->gc->wants_to_die = TRUE; - purple_connection_error(sip->gc, _("Unknown server response.")); + purple_connection_error_reason(sip->gc, PURPLE_REASON_OTHER_ERROR, + _("Unknown server response.")); return TRUE; } sip->registerstatus = SIMPLE_REGISTER_RETRY; @@ -1528,7 +1530,8 @@ } if(source < 0) { - purple_connection_error(gc, _("Could not connect")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Could not connect")); return; } @@ -1562,7 +1565,8 @@ sip->listen_data = NULL; if(listenfd == -1) { - purple_connection_error(sip->gc, _("Could not create listen socket")); + purple_connection_error_reason(sip->gc, PURPLE_REASON_NETWORK_ERROR, + _("Could not create listen socket")); return; } @@ -1585,7 +1589,9 @@ sip->query_data = NULL; if (!hosts || !hosts->data) { - purple_connection_error(sip->gc, _("Couldn't resolve host")); + purple_connection_error_reason(sip->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Couldn't resolve host")); return; } @@ -1604,7 +1610,9 @@ sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_DGRAM, simple_udp_host_resolved_listen_cb, sip); if (sip->listen_data == NULL) { - purple_connection_error(sip->gc, _("Could not create listen socket")); + purple_connection_error_reason(sip->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Could not create listen socket")); return; } } @@ -1617,7 +1625,9 @@ sip->listenfd = listenfd; if(sip->listenfd == -1) { - purple_connection_error(sip->gc, _("Could not create listen socket")); + purple_connection_error_reason(sip->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Could not create listen socket")); return; } @@ -1630,7 +1640,9 @@ /* open tcp connection to the server */ if (purple_proxy_connect(sip->gc, sip->account, sip->realhostname, sip->realport, login_cb, sip->gc) == NULL) { - purple_connection_error(sip->gc, _("Couldn't create socket")); + purple_connection_error_reason(sip->gc, + PURPLE_REASON_NETWORK_ERROR, + _("Couldn't create socket")); } } @@ -1668,7 +1680,8 @@ sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_STREAM, simple_tcp_connect_listen_cb, sip); if (sip->listen_data == NULL) { - purple_connection_error(sip->gc, _("Could not create listen socket")); + purple_connection_error_reason(sip->gc, PURPLE_REASON_NETWORK_ERROR, + _("Could not create listen socket")); return; } } else { /* UDP */ @@ -1676,7 +1689,8 @@ sip->query_data = purple_dnsquery_a(hostname, port, simple_udp_host_resolved, sip); if (sip->query_data == NULL) { - purple_connection_error(sip->gc, _("Could not resolve hostname")); + purple_connection_error_reason(sip->gc, PURPLE_REASON_NETWORK_ERROR, + _("Could not resolve hostname")); } } } @@ -1692,8 +1706,8 @@ gc = purple_account_get_connection(account); if (strpbrk(username, " \t\v\r\n") != NULL) { - gc->wants_to_die = TRUE; - purple_connection_error(gc, _("SIP screen names may not contain whitespaces or @ symbols")); + purple_connection_error_reason(gc, PURPLE_REASON_INVALID_SETTINGS, + _("SIP screen names may not contain whitespaces or @ symbols")); return; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Fri Oct 12 23:26:11 2007 +0000 @@ -201,10 +201,10 @@ char *message = NULL; if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { - gc->wants_to_die = TRUE; if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error(gc, _("You have signed on from another location.")); + purple_connection_error_reason(gc, PURPLE_REASON_NAME_IN_USE, + _("You have signed on from another location.")); return; } @@ -2139,8 +2139,7 @@ else fullmsg = g_strdup(msg); - gc->wants_to_die = TRUE; - purple_connection_error(gc, fullmsg); + purple_connection_error_reason(gc, PURPLE_REASON_AUTHENTICATION_FAILED, fullmsg); g_free(msg); g_free(fullmsg); } @@ -2464,11 +2463,12 @@ tmp = g_strdup_printf(_("Lost connection with server:\n%s"), strerror(errno)); - purple_connection_error(gc, tmp); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (len == 0) { - purple_connection_error(gc, _("Server closed the connection.")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Server closed the connection.")); return; } @@ -2559,7 +2559,7 @@ gchar *tmp; tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), error_message); - purple_connection_error(gc, tmp); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -2591,7 +2591,7 @@ gchar *tmp; tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), error_message); - purple_connection_error(gc, tmp); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -2631,11 +2631,12 @@ tmp = g_strdup_printf(_("Lost connection with server:\n%s"), strerror(errno)); - purple_connection_error(gc, tmp); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (len == 0) { - purple_connection_error(gc, _("Server closed the connection.")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Server closed the connection.")); return; } @@ -2650,7 +2651,8 @@ if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) && strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) { - purple_connection_error(gc, _("Received unexpected HTTP response from server.")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Received unexpected HTTP response from server.")); return; } @@ -2672,9 +2674,10 @@ yd->rxlen = 0; /* Now we have our cookies to login with. I'll go get the milk. */ if (purple_proxy_connect(gc, account, "wcs2.msg.dcn.yahoo.com", - purple_account_get_int(account, "port", YAHOO_PAGER_PORT), - yahoo_got_web_connected, gc) == NULL) { - purple_connection_error(gc, _("Connection problem")); + purple_account_get_int(account, "port", YAHOO_PAGER_PORT), + yahoo_got_web_connected, gc) == NULL) { + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection problem")); return; } } @@ -2702,7 +2705,7 @@ gc->inpa = 0; tmp = g_strdup_printf(_("Lost connection with %s:\n%s"), "login.yahoo.com:80", strerror(errno)); - purple_connection_error(gc, tmp); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -2727,7 +2730,7 @@ gchar *tmp; tmp = g_strdup_printf(_("Could not establish a connection with %s:\n%s"), "login.yahoo.com:80", error_message); - purple_connection_error(gc, tmp); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -2811,7 +2814,8 @@ if (error_message != NULL) { - purple_connection_error(gc, error_message); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + error_message); return; } @@ -2860,7 +2864,8 @@ g_hash_table_destroy(hash); yd->auth = g_string_free(url, FALSE); if (purple_proxy_connect(gc, account, "login.yahoo.com", 80, yahoo_got_cookies, gc) == NULL) { - purple_connection_error(gc, _("Connection problem")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection problem")); return; } @@ -2963,7 +2968,8 @@ purple_account_get_int(account, "port", YAHOO_PAGER_PORT), yahoo_got_connected, gc) == NULL) { - purple_connection_error(gc, _("Connection problem")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection problem")); return; } } else { @@ -2973,7 +2979,8 @@ purple_account_get_int(account, "port", YAHOO_PAGER_PORT), yahoo_got_connected, gc) == NULL) { - purple_connection_error(gc, _("Connection problem")); + purple_connection_error_reason(gc, PURPLE_REASON_NETWORK_ERROR, + _("Connection problem")); return; } } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/yahoo/yahoo_packet.c --- a/libpurple/protocols/yahoo/yahoo_packet.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Fri Oct 12 23:26:11 2007 +0000 @@ -304,7 +304,8 @@ return; else if (ret < 0) { /* TODO: what to do here - do we really have to disconnect? */ - purple_connection_error(yd->gc, _("Write Error")); + purple_connection_error_reason(yd->gc, PURPLE_REASON_NETWORK_ERROR, + _("Write Error")); return; } diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/protocols/yahoo/ycht.c --- a/libpurple/protocols/yahoo/ycht.c Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/protocols/yahoo/ycht.c Fri Oct 12 23:26:11 2007 +0000 @@ -285,7 +285,8 @@ else if (ret <= 0) { /* TODO: error handling */ /* - purple_connection_error(purple_account_get_connection(irc->account), + purple_connection_error_reason(purple_account_get_connection(irc->account), + PURPLE_REASON_NETWORK_ERROR, _("Server has disconnected")); */ return; diff -r e967fd47baa5 -r fa3c4c5dea66 libpurple/sslconn.h --- a/libpurple/sslconn.h Fri Oct 12 03:53:58 2007 +0000 +++ b/libpurple/sslconn.h Fri Oct 12 23:26:11 2007 +0000 @@ -26,11 +26,6 @@ #ifndef _PURPLE_SSLCONN_H_ #define _PURPLE_SSLCONN_H_ -#include "certificate.h" -#include "proxy.h" - -#define PURPLE_SSL_DEFAULT_PORT 443 - /** Possible SSL errors. */ typedef enum { @@ -39,6 +34,11 @@ PURPLE_SSL_CERTIFICATE_INVALID = 3 } PurpleSslErrorType; +#include "certificate.h" +#include "proxy.h" + +#define PURPLE_SSL_DEFAULT_PORT 443 + typedef struct _PurpleSslConnection PurpleSslConnection; typedef void (*PurpleSslInputFunction)(gpointer, PurpleSslConnection *, @@ -126,9 +126,9 @@ /** Obtains the certificate chain provided by the peer * * @param gsc Connection context - * @return A newly allocated list of #PurpleCertificate containing the - * certificates the peer provided. - * @see purple_ssl_get_peer_certificates + * @return A newly allocated list containing the certificates + * the peer provided. + * @see PurpleCertificate * @todo Decide whether the ordering of certificates in this * list can be guaranteed. */ diff -r e967fd47baa5 -r fa3c4c5dea66 pidgin/gtkconn.c --- a/pidgin/gtkconn.c Fri Oct 12 03:53:58 2007 +0000 +++ b/pidgin/gtkconn.c Fri Oct 12 23:26:11 2007 +0000 @@ -42,6 +42,7 @@ #define INITIAL_RECON_DELAY_MAX 60000 #define MAX_RECON_DELAY 600000 +#define MAX_RACCOON_DELAY "shorter in urban areas" typedef struct { int delay; @@ -137,7 +138,9 @@ } static void -pidgin_connection_report_disconnect(PurpleConnection *gc, const char *text) +pidgin_connection_report_disconnect_reason (PurpleConnection *gc, + PurpleDisconnectReason reason, + const char *text) { PurpleAccount *account = NULL; PidginAutoRecon *info; @@ -147,7 +150,7 @@ info = g_hash_table_lookup(auto_reconns, account); pidgin_blist_update_account_error_state(account, text); - if (!gc->wants_to_die) { + if (!purple_connection_reason_is_fatal (reason)) { if (info == NULL) { info = g_new0(PidginAutoRecon, 1); g_hash_table_insert(auto_reconns, account, info); @@ -178,9 +181,29 @@ } p = g_strdup_printf(_("%s disconnected"), n); - s = g_strdup_printf(_("%s\n\n" - "%s will not attempt to reconnect the account until you " - "correct the error and re-enable the account."), text, PIDGIN_NAME); + switch (reason) + { + case PURPLE_REASON_NO_SSL_SUPPORT: + s = g_strdup_printf( + _("%s\n\n" + "%s will not attempt to reconnect the account until you " + "re-enable the account. See %s for information on how to " + "compile %s with SSL support."), text, PIDGIN_NAME, + "http://developer.pidgin.im/wiki/FAQssl", PIDGIN_NAME); + break; + case PURPLE_REASON_NAME_IN_USE: + s = g_strdup_printf( + _("%s\n\n" + "%s will not attempt to reconnect the account until you " + "re-enable it."), text, PIDGIN_NAME); + break; + default: + s = g_strdup_printf( + _("%s\n\n" + "%s will not attempt to reconnect the account until you " + "correct the error and re-enable the account."), text, + PIDGIN_NAME); + } purple_notify_error(NULL, NULL, p, s); g_free(p); g_free(s); @@ -259,10 +282,10 @@ pidgin_connection_connected, pidgin_connection_disconnected, pidgin_connection_notice, - pidgin_connection_report_disconnect, + NULL, /* report_disconnect */ pidgin_connection_network_connected, pidgin_connection_network_disconnected, - NULL, + pidgin_connection_report_disconnect_reason, NULL, NULL, NULL