# HG changeset patch # User Will Thompson # Date 1191599417 0 # Node ID f3cfcbbac3d8d494600281fdf38aa440bb17eb12 # Parent d3443cb6a60f51ebf21acca0a2c2f6f45e26e70e# Parent b4ac690a222592f9a7a04c474565af817d40e91b propagate from branch 'im.pidgin.pidgin' (head 294731552d0baf5f1f37a45e0c119b2188f34ba8) to branch 'im.pidgin.cpw.resiak.disconnectreason' (head 548e06334e7772c9583776ecbd80e8d2a68fcd79) diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/connection.c --- a/libpurple/connection.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/connection.c Fri Oct 05 15:50:17 2007 +0000 @@ -488,29 +488,103 @@ void purple_connection_error(PurpleConnection *gc, const char *text) { + purple_connection_error_reason (gc, PURPLE_REASON_OTHER_ERROR, text); +} + +void +purple_connection_error_reason (PurpleConnection *gc, + PurpleDisconnectReason reason, + const char *description) +{ PurpleConnectionUiOps *ops; + gboolean fatal; g_return_if_fail(gc != NULL); - 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"); } + g_assert (reason < PURPLE_NUM_REASONS); + + /* This should probably be removed at some point */ + fatal = purple_connection_reason_is_fatal (reason); + if (fatal != gc->wants_to_die) + purple_debug_warning ("connection", + "reason %u is %sfatal but wants_to_die is %u", + reason, (fatal ? "" : "not "), gc->wants_to_die); + /* If we've already got one error, we don't need any more */ if (gc->disconnect_timeout) return; 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_ENCRYPTION_ERROR: + case PURPLE_REASON_NAME_IN_USE: + case PURPLE_REASON_INVALID_SETTINGS: + case PURPLE_REASON_OTHER_ERROR: + return TRUE; + default: + g_assert_not_reached (); + return TRUE; + } +} + +void purple_connections_disconnect_all(void) { GList *l; diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/connection.h --- a/libpurple/connection.h Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/connection.h Fri Oct 05 15:50:17 2007 +0000 @@ -55,11 +55,77 @@ } PurpleConnectionState; +/** Possible errors that can cause a connection to be closed. */ +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, + /** libpurple doesn't speak any of the authentication methods the + * server offered. + */ + PURPLE_REASON_AUTHENTICATION_IMPOSSIBLE, + /** There was an error negotiating SSL on this connection, or encryption + * was unavailable and an account option was set to require it. + */ + PURPLE_REASON_ENCRYPTION_ERROR, + /** Someone is already connected to the server using the name you are + * trying to connect with. + */ + PURPLE_REASON_NAME_IN_USE, + + /** 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, + + /** The server did not provide a SSL certificate. */ + PURPLE_REASON_CERT_NOT_PROVIDED, + /** The server's SSL certificate could not be trusted. */ + PURPLE_REASON_CERT_UNTRUSTED, + /** The server's SSL certificate has expired. */ + PURPLE_REASON_CERT_EXPIRED, + /** The server's SSL certificate is not yet valid. */ + PURPLE_REASON_CERT_NOT_ACTIVATED, + /** The server's SSL certificate did not match its hostname. */ + PURPLE_REASON_CERT_HOSTNAME_MISMATCH, + /** The server's SSL certificate does not have the expected + * fingerprint. + */ + PURPLE_REASON_CERT_FINGERPRINT_MISMATCH, + /** The server's SSL certificate is self-signed. */ + PURPLE_REASON_CERT_SELF_SIGNED, + /** There was some other error validating the server's SSL certificate. + */ + PURPLE_REASON_CERT_OTHER_ERROR, + + /** Some other error occured which fits into none of the other + * categories. + */ + PURPLE_REASON_OTHER_ERROR, + + /** The number of PurpleDisconnectReason elements; not a valid reason. + */ + PURPLE_NUM_REASONS +} PurpleDisconnectReason; + #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 @@ -74,11 +140,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). */ @@ -87,17 +155,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 @@ -109,10 +183,21 @@ */ void (*network_disconnected)(); + /** Called when a connection is disconnected, whether due to an + * error or to user request. Called before #disconnected. + * @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 + */ + 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 @@ -290,9 +375,53 @@ * * @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, PURPLE_REASON_OTHER_ERROR, text). */ void purple_connection_error(PurpleConnection *gc, const char *reason); +/** + * Closes a connection with an error and an optional description of the + * error. + * + * @param reason why the connection is closing. + * @param description a localized description of the error. + */ +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(). + */ +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 + * @a 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 @a TRUE. + * + * (This function is meant to replace checking PurpleConnection.wants_to_die.) + * + * @return @a TRUE iff automatic reconnection is a bad idea. + */ +gboolean +purple_connection_reason_is_fatal (PurpleDisconnectReason reason); + /*@}*/ /**************************************************************************/ diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Fri Oct 05 15:50:17 2007 +0000 @@ -121,7 +121,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 +147,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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/gg/gg.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/irc/irc.c --- a/libpurple/protocols/irc/irc.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/irc/irc.c Fri Oct 05 15:50:17 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_ENCRYPTION_ERROR, + _("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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/irc/msgs.c --- a/libpurple/protocols/irc/msgs.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/irc/msgs.c Fri Oct 05 15:50:17 2007 +0000 @@ -914,8 +914,8 @@ } 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/irc/parse.c --- a/libpurple/protocols/irc/parse.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/irc/parse.c Fri Oct 05 15:50:17 2007 +0000 @@ -557,6 +557,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); @@ -565,7 +566,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); @@ -575,10 +576,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_OTHER_ERROR, tmp); g_free(tmp); } else - purple_connection_error(purple_account_get_connection(irc->account), _("Disconnected.")); + purple_connection_error_reason (gc, + PURPLE_REASON_OTHER_ERROR, _("Disconnected.")); return; } diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Fri Oct 05 15:50:17 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_ENCRYPTION_ERROR, + _("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 @@ -545,7 +552,7 @@ purple_account_set_password(js->gc->account, NULL); } - purple_connection_error(js->gc, msg); + purple_connection_error_reason (js->gc, PURPLE_REASON_OTHER_ERROR, msg); g_free(msg); } } @@ -558,11 +565,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); + purple_connection_error_reason (js->gc, PURPLE_REASON_AUTHENTICATION_FAILED, + msg); g_free(msg); } else if(!strcmp(type, "result")) { query = xmlnode_get_child(packet, "query"); @@ -606,8 +615,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 +783,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 +805,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 +829,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 +902,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 +928,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 +954,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 */ @@ -958,9 +974,11 @@ char *msg = jabber_parse_error(js, packet); 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, PURPLE_REASON_AUTHENTICATION_FAILED, + msg); g_free(msg); } } diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Oct 05 15:50:17 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,7 +121,8 @@ 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; @@ -128,7 +130,7 @@ } } else { char *msg = jabber_parse_error(js, packet); - purple_connection_error(js->gc, msg); + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, msg); g_free(msg); } @@ -142,7 +144,8 @@ 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; } @@ -175,7 +178,10 @@ { char *msg = jabber_parse_error(js, packet); - purple_connection_error(js->gc, msg); + if (js->gc->wants_to_die) + purple_connection_error_reason (js->gc, PURPLE_REASON_OTHER_ERROR, msg); + else + purple_connection_error_reason (js->gc, PURPLE_REASON_NETWORK_ERROR, msg); g_free(msg); } @@ -256,7 +262,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 +316,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 +346,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 +416,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 +455,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 +496,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 +524,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 +541,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 +588,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 +625,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_ENCRYPTION_ERROR, + _("SSL support unavailable")); } } @@ -1060,7 +1079,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 +1112,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_ENCRYPTION_ERROR, + _("SSL support unavailable")); } } diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/jabber/parser.c --- a/libpurple/protocols/jabber/parser.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/jabber/parser.c Fri Oct 05 15:50:17 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_OTHER_ERROR, + _("XML Parse error")); } } diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Fri Oct 05 15:50:17 2007 +0000 @@ -800,7 +800,7 @@ if (!purple_ssl_is_supported()) { gc->wants_to_die = TRUE; - purple_connection_error(gc, + purple_connection_error_reason (gc, PURPLE_REASON_ENCRYPTION_ERROR, _("SSL support is needed for MSN. Please install a supported " "SSL library.")); return; @@ -829,7 +829,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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/msn/session.c Fri Oct 05 15:50:17 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,58 @@ 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: + reason = PURPLE_REASON_AUTHENTICATION_FAILED; gc->wants_to_die = TRUE; 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Fri Oct 05 15:50:17 2007 +0000 @@ -292,7 +292,8 @@ 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 +316,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 +355,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 +829,6 @@ serv_got_typing_stopped(session->gc, username); g_free(username); - g_free(text); return TRUE; } @@ -1290,7 +1292,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 +1559,8 @@ 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")); + session->gc->wants_to_die = TRUE; + purple_connection_error_reason (session->gc, PURPLE_REASON_AUTHENTICATION_FAILED, _("No username set")); return FALSE; } @@ -1792,16 +1796,23 @@ /* 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; + session->gc->wants_to_die = TRUE; + if (!purple_account_get_remember_password(session->account)) + purple_account_set_password(session->account, NULL); + break; case 6: /* Logged in elsewhere */ + reason = PURPLE_REASON_NAME_IN_USE; session->gc->wants_to_die = TRUE; 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 +1882,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")); @@ -2317,7 +2327,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; } @@ -2335,7 +2346,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; } @@ -2354,11 +2366,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; } @@ -2366,7 +2380,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 */ @@ -2381,7 +2396,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 @@ -2404,7 +2420,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.) */ @@ -2471,9 +2488,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; @@ -2674,7 +2690,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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/novell/novell.c --- a/libpurple/protocols/novell/novell.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/novell/novell.c Fri Oct 05 15:50:17 2007 +0000 @@ -120,21 +120,28 @@ _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); + gc->wants_to_die = TRUE; + 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 +1127,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 +1674,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 +1697,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 +1738,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..."), @@ -2014,7 +2022,8 @@ 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 +2178,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_OTHER_ERROR, + _("Unable to connect to server. Please enter the " + "address of the server you wish to connect to.")); return; } @@ -2197,8 +2206,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_ENCRYPTION_ERROR, + _("Error. SSL support is not installed.")); } } } diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/oscar/flap_connection.c --- a/libpurple/protocols/oscar/flap_connection.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Fri Oct 05 15:50:17 2007 +0000 @@ -380,7 +380,10 @@ { /* 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); @@ -404,7 +407,7 @@ if (tmp != NULL) { - purple_connection_error(od->gc, tmp); + purple_connection_error_reason(od->gc, reason, tmp); g_free(tmp); } } diff -r d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Oct 05 15:50:17 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 @@ -1259,7 +1259,7 @@ 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_AUTHENTICATION_FAILED, buf); g_free(buf); } @@ -1280,7 +1280,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; } @@ -1342,42 +1343,42 @@ 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_NETWORK_ERROR, _("Authentication failed")); break; } purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode); @@ -1407,7 +1408,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; } @@ -1433,7 +1434,8 @@ /* 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/qq/keep_alive.c --- a/libpurple/protocols/qq/keep_alive.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/qq/keep_alive.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/qq/login_logout.c --- a/libpurple/protocols/qq/login_logout.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/qq/login_logout.c Fri Oct 05 15:50:17 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); } @@ -482,10 +482,12 @@ 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/qq/qq.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/qq/qq_proxy.c --- a/libpurple/protocols/qq/qq_proxy.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/qq/qq_proxy.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/qq/recv_core.c --- a/libpurple/protocols/qq/recv_core.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/qq/recv_core.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/qq/sendqueue.c --- a/libpurple/protocols/qq/sendqueue.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/qq/sendqueue.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/sametime/sametime.c --- a/libpurple/protocols/sametime/sametime.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/sametime/sametime.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/silc/silc.c --- a/libpurple/protocols/silc/silc.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Fri Oct 05 15:50:17 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; } @@ -435,14 +445,16 @@ 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/silc/util.c --- a/libpurple/protocols/silc/util.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/silc/util.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/simple/simple.c Fri Oct 05 15:50:17 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; } @@ -1044,7 +1046,9 @@ 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"); @@ -1058,7 +1062,8 @@ 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 +1533,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 +1568,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 +1592,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 +1613,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 +1628,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 +1643,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 +1683,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 +1692,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")); } } } @@ -1693,7 +1710,8 @@ 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Fri Oct 05 15:50:17 2007 +0000 @@ -204,7 +204,8 @@ 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; } @@ -2140,7 +2141,7 @@ 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 +2465,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 +2561,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 +2593,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 +2633,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 +2653,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 +2676,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 +2707,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 +2732,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 +2816,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 +2866,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 +2970,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 +2981,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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/protocols/yahoo/yahoo_packet.c --- a/libpurple/protocols/yahoo/yahoo_packet.c Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 libpurple/sslconn.h --- a/libpurple/sslconn.h Thu Oct 04 03:52:47 2007 +0000 +++ b/libpurple/sslconn.h Fri Oct 05 15:50:17 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 d3443cb6a60f -r f3cfcbbac3d8 pidgin/gtkconn.c --- a/pidgin/gtkconn.c Thu Oct 04 03:52:47 2007 +0000 +++ b/pidgin/gtkconn.c Fri Oct 05 15:50:17 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); @@ -259,10 +262,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