# HG changeset patch # User Nathan Walp # Date 1176596132 0 # Node ID e5af828c2f54ffc280f97fc944bef398ac1ccfe7 # Parent e57d9d5e5c860dc26140316c7b4e6b4702bd31b2# Parent ac1a32ebd62caa97beddca365fbf07605483ef1c merge of 'aa2170e50c202539ea83f299b04eedf9a5d62178' and 'e6a776d806e488fa79eada7619f40300fdecda61' diff -r e57d9d5e5c86 -r e5af828c2f54 libpurple/account.c --- a/libpurple/account.c Sat Apr 14 23:47:24 2007 +0000 +++ b/libpurple/account.c Sun Apr 15 00:15:32 2007 +0000 @@ -932,8 +932,9 @@ purple_connection_new(account, FALSE, entry); } -static void -request_password(PurpleAccount *account) +void +purple_account_request_password(PurpleAccount *account, GCallback ok_cb, + GCallback cancel_cb, void *user_data) { gchar *primary; const gchar *username; @@ -965,9 +966,9 @@ primary, NULL, fields, - _("OK"), G_CALLBACK(request_password_ok_cb), - _("Cancel"), NULL, - account); + _("OK"), ok_cb, + _("Cancel"), cancel_cb, + user_data); g_free(primary); } @@ -1003,7 +1004,7 @@ if ((password == NULL) && !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) - request_password(account); + purple_account_request_password(account, G_CALLBACK(request_password_ok_cb), NULL, account); else purple_connection_new(account, FALSE, password); } diff -r e57d9d5e5c86 -r e5af828c2f54 libpurple/account.h --- a/libpurple/account.h Sat Apr 14 23:47:24 2007 +0000 +++ b/libpurple/account.h Sun Apr 15 00:15:32 2007 +0000 @@ -29,6 +29,7 @@ #include #include +#include typedef struct _PurpleAccountUiOps PurpleAccountUiOps; typedef struct _PurpleAccount PurpleAccount; @@ -223,6 +224,18 @@ void purple_account_request_close(void *ui_handle); /** + * Requests a password from the user for the account. Does not set the + * account password on success; do that in ok_cb if desired. + * + * @param account The account to request the password for. + * @param ok_cb The callback for the OK button. + * @param cancel_cb The callback for the cancel button. + * @param user_data User data to be passed into callbacks. + */ +void purple_account_request_password(PurpleAccount *account, GCallback ok_cb, + GCallback cancel_cb, void *user_data); + +/** * Requests information from the user to change the account's password. * * @param account The account to change the password on. diff -r e57d9d5e5c86 -r e5af828c2f54 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Sat Apr 14 23:47:24 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Sun Apr 15 00:15:32 2007 +0000 @@ -33,6 +33,7 @@ #include "auth.h" #include "jabber.h" #include "iq.h" +#include "notify.h" static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data); @@ -117,6 +118,7 @@ #ifdef HAVE_CYRUS_SASL static void jabber_auth_start_cyrus(JabberStream *); +static void jabber_sasl_build_callbacks(JabberStream *); /* Callbacks for Cyrus SASL */ @@ -179,6 +181,58 @@ jabber_auth_start_cyrus(account->gc->proto_data); } +static gboolean auth_pass_generic(JabberStream *js, PurpleRequestFields *fields) +{ + const char *entry; + gboolean remember; + + entry = purple_request_fields_get_string(fields, "password"); + remember = purple_request_fields_get_bool(fields, "remember"); + + if (!entry || !*entry) + { + purple_notify_error(js->gc->account, NULL, _("Password is required to sign on."), NULL); + return FALSE; + } + + if (remember) + purple_account_set_remember_password(js->gc->account, TRUE); + + purple_account_set_password(js->gc->account, entry); + + return TRUE; +} + +static void auth_pass_cb(JabberStream *js, PurpleRequestFields *fields) +{ + + if (!auth_pass_generic(js, fields)) + return; + + /* Rebuild our callbacks as we now have a password to offer */ + jabber_sasl_build_callbacks(js); + + /* Restart our connection */ + jabber_auth_start_cyrus(js); +} + +static void +auth_old_pass_cb(JabberStream *js, PurpleRequestFields *fields) +{ + if (!auth_pass_generic(js, fields)) + return; + + /* Restart our connection */ + jabber_auth_start_old(js); +} + + +static void +auth_no_pass_cb(JabberStream *js, PurpleRequestFields *fields) +{ + purple_connection_error(js->gc, _("Password is required to sign on.")); +} + static void jabber_auth_start_cyrus(JabberStream *js) { const char *clientout = NULL, *mech = NULL; @@ -222,12 +276,20 @@ case SASL_CONTINUE: break; case SASL_NOMECH: - /* No mechanisms do what we want. See if we can add - * plaintext ones to the list. */ + /* No mechanisms have offered to help */ + + /* Firstly, if we don't have a password try + * to get one + */ if (!purple_account_get_password(js->gc->account)) { - purple_connection_error(js->gc, _("Server couldn't authenticate you without a password")); + purple_account_request_password(js->gc->account, G_CALLBACK(auth_pass_cb), G_CALLBACK(auth_no_pass_cb), js); return; + + /* If we've got a password, but aren't sending + * it in plaintext, see if we can turn on + * plaintext auth + */ } else if (!plaintext) { purple_request_yes_no(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), @@ -236,6 +298,10 @@ allow_cyrus_plaintext_auth, disallow_plaintext_auth); return; + /* Everything else has failed, so fail the + * connection. Should probably have a better + * error here. + */ } else { purple_connection_error(js->gc, _("Server does not use any supported authentication method")); return; @@ -305,14 +371,52 @@ return SASL_OK; } +void +jabber_sasl_build_callbacks(JabberStream *js) +{ + int id; + + /* Set up our callbacks structure */ + if (js->sasl_cb == NULL) + js->sasl_cb = g_new0(sasl_callback_t,6); + + id = 0; + js->sasl_cb[id].id = SASL_CB_GETREALM; + js->sasl_cb[id].proc = jabber_sasl_cb_realm; + js->sasl_cb[id].context = (void *)js; + id++; + + js->sasl_cb[id].id = SASL_CB_AUTHNAME; + js->sasl_cb[id].proc = jabber_sasl_cb_simple; + js->sasl_cb[id].context = (void *)js; + id++; + + js->sasl_cb[id].id = SASL_CB_USER; + js->sasl_cb[id].proc = jabber_sasl_cb_simple; + js->sasl_cb[id].context = (void *)js; + id++; + + if (purple_account_get_password(js->gc->account) != NULL ) { + js->sasl_cb[id].id = SASL_CB_PASS; + js->sasl_cb[id].proc = jabber_sasl_cb_secret; + js->sasl_cb[id].context = (void *)js; + id++; + } + + js->sasl_cb[id].id = SASL_CB_LOG; + js->sasl_cb[id].proc = jabber_sasl_cb_log; + js->sasl_cb[id].context = (void*)js; + id++; + + js->sasl_cb[id].id = SASL_CB_LIST_END; +} + #endif void jabber_auth_start(JabberStream *js, xmlnode *packet) { -#ifdef HAVE_CYRUS_SASL - int id; -#else +#ifndef HAVE_CYRUS_SASL gboolean digest_md5 = FALSE, plain=FALSE; #endif @@ -354,38 +458,7 @@ #ifdef HAVE_CYRUS_SASL js->auth_type = JABBER_AUTH_CYRUS; - /* Set up our callbacks structure */ - js->sasl_cb = g_new0(sasl_callback_t,6); - - id = 0; - js->sasl_cb[id].id = SASL_CB_GETREALM; - js->sasl_cb[id].proc = jabber_sasl_cb_realm; - js->sasl_cb[id].context = (void *)js; - id++; - - js->sasl_cb[id].id = SASL_CB_AUTHNAME; - js->sasl_cb[id].proc = jabber_sasl_cb_simple; - js->sasl_cb[id].context = (void *)js; - id++; - - js->sasl_cb[id].id = SASL_CB_USER; - js->sasl_cb[id].proc = jabber_sasl_cb_simple; - js->sasl_cb[id].context = (void *)js; - id++; - - if (purple_account_get_password(js->gc->account)) { - js->sasl_cb[id].id = SASL_CB_PASS; - js->sasl_cb[id].proc = jabber_sasl_cb_secret; - js->sasl_cb[id].context = (void *)js; - id++; - } - - js->sasl_cb[id].id = SASL_CB_LOG; - js->sasl_cb[id].proc = jabber_sasl_cb_log; - js->sasl_cb[id].context = (void*)js; - id++; - - js->sasl_cb[id].id = SASL_CB_LIST_END; + jabber_sasl_build_callbacks(js); jabber_auth_start_cyrus(js); #else @@ -507,6 +580,17 @@ JabberIq *iq; xmlnode *query, *username; +#ifdef HAVE_CYRUS_SASL + /* If we have Cyrus SASL, then passwords will have been set + * to OPTIONAL for this protocol. So, we need to do our own + * password prompting here + */ + + if (!purple_account_get_password(js->gc->account)) { + purple_account_request_password(js->gc->account, G_CALLBACK(auth_old_pass_cb), G_CALLBACK(auth_no_pass_cb), js); + return; + } +#endif iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:auth"); query = xmlnode_get_child(iq->node, "query"); diff -r e57d9d5e5c86 -r e5af828c2f54 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sat Apr 14 23:47:24 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun Apr 15 00:15:32 2007 +0000 @@ -1858,7 +1858,12 @@ static PurplePluginProtocolInfo prpl_info = { +#ifdef HAVE_CYRUS_SASL + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | + OPT_PROTO_MAIL_CHECK | OPT_PROTO_PASSWORD_OPTIONAL, +#else OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK, +#endif NULL, /* user_splits */ NULL, /* protocol_options */ {"png,gif,jpeg", 32, 32, 96, 96, 8191, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */