Replace various network options with universal login method option

This commit is contained in:
Berke Viktor 2013-05-10 23:52:47 +02:00
parent beb3ab506d
commit 873a3ef047
5 changed files with 98 additions and 94 deletions

View File

@ -528,13 +528,12 @@ typedef struct server
char servername[128]; /* what the server says is its name */ char servername[128]; /* what the server says is its name */
char password[86]; char password[86];
char sasluser[32]; /* this is just a buffer for network->user */ char sasluser[32]; /* this is just a buffer for network->user */
char saslpassword[86]; /* we could reuse password but then we couldn't guarantee NickServ doesn't register first */
char nick[NICKLEN]; char nick[NICKLEN];
char linebuf[2048]; /* RFC says 512 chars including \r\n */ char linebuf[2048]; /* RFC says 512 chars including \r\n */
char *last_away_reason; char *last_away_reason;
int pos; /* current position in linebuf */ int pos; /* current position in linebuf */
int nickcount; int nickcount;
int nickservtype; /* 0=/MSG nickserv 1=/NICKSERV 2=/NS */ int loginmethod; /* see login_types[] */
char *chantypes; /* for 005 numeric - free me */ char *chantypes; /* for 005 numeric - free me */
char *chanmodes; /* for 005 numeric - free me */ char *chanmodes; /* for 005 numeric - free me */

View File

@ -49,7 +49,7 @@ irc_login (server *serv, char *user, char *realname)
{ {
tcp_sendf (serv, "CAP LS\r\n"); /* start with CAP LS as Charybdis sasl.txt suggests */ tcp_sendf (serv, "CAP LS\r\n"); /* start with CAP LS as Charybdis sasl.txt suggests */
if (serv->password[0]) if (serv->password[0] && serv->loginmethod == 7)
{ {
tcp_sendf (serv, "PASS %s\r\n", serv->password); tcp_sendf (serv, "PASS %s\r\n", serv->password);
} }
@ -64,21 +64,21 @@ static void
irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3) irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3)
{ {
/* are all ircd authors idiots? */ /* are all ircd authors idiots? */
switch (serv->nickservtype) switch (serv->loginmethod)
{ {
case 0: case 1:
tcp_sendf (serv, "PRIVMSG NICKSERV :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); tcp_sendf (serv, "PRIVMSG NICKSERV :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break; break;
case 1: case 2:
tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break; break;
case 2: case 3:
tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3); tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break; break;
case 3: case 4:
tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break; break;
case 4: case 5:
/* why couldn't QuakeNet implement one of the existing ones? */ /* why couldn't QuakeNet implement one of the existing ones? */
tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2); tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2);
} }
@ -87,7 +87,7 @@ irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3)
static void static void
irc_ns_identify (server *serv, char *pass) irc_ns_identify (server *serv, char *pass)
{ {
if (serv->nickservtype == 4) /* QuakeNet needs to do everything in its own ways... */ if (serv->loginmethod == 5) /* QuakeNet needs to do everything in its own ways... */
{ {
irc_nickserv (serv, "", serv->nick, pass, ""); irc_nickserv (serv, "", serv->nick, pass, "");
} }
@ -100,7 +100,7 @@ irc_ns_identify (server *serv, char *pass)
static void static void
irc_ns_ghost (server *serv, char *usname, char *pass) irc_ns_ghost (server *serv, char *usname, char *pass)
{ {
if (serv->nickservtype != 4) if (serv->loginmethod != 5)
irc_nickserv (serv, "GHOST", usname, " ", pass); irc_nickserv (serv, "GHOST", usname, " ", pass);
} }
@ -1221,7 +1221,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, sess->server->sasluser, NULL, NULL, NULL, 0); EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, sess->server->sasluser, NULL, NULL, NULL, 0);
tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20); tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20);
pass = encode_sasl_pass (sess->server->sasluser, sess->server->saslpassword); pass = encode_sasl_pass (sess->server->sasluser, sess->server->password);
tcp_sendf (sess->server, "AUTHENTICATE %s\r\n", pass); tcp_sendf (sess->server, "AUTHENTICATE %s\r\n", pass);
free (pass); free (pass);
} }
@ -1259,8 +1259,8 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
strcat (buffer, "extended-join "); strcat (buffer, "extended-join ");
want_cap = 1; want_cap = 1;
} }
/* if the SASL password is set, request SASL auth */ /* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0) if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->password) != 0 && serv->loginmethod == 6)
{ {
strcat (buffer, "sasl "); strcat (buffer, "sasl ");
want_cap = 1; want_cap = 1;

View File

@ -43,7 +43,7 @@ struct defaultserver
char *host; char *host;
char *channel; char *channel;
char *charset; char *charset;
int nsmode; /* default NickServ type */ int loginmode; /* default authentication type */
}; };
static const struct defaultserver def[] = static const struct defaultserver def[] =
@ -245,7 +245,7 @@ static const struct defaultserver def[] =
{0, "irc.ggn.net"}, {0, "irc.ggn.net"},
{0, "irc.vendetta.com"}, {0, "irc.vendetta.com"},
{"freenode", 0, "#hexchat"}, {"freenode", 0, "#hexchat", 0, 6},
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
{0, "irc.freenode.net/+6697"}, {0, "irc.freenode.net/+6697"},
#endif #endif
@ -618,18 +618,17 @@ servlist_connect (session *sess, ircnet *net, gboolean join)
} }
} }
if (net->nstype >= 1) /* once again, make sure gtk_combo_box_get_active() is not bugging us, just in case */ if (net->logintype)
{ {
serv->nickservtype = net->nstype - 1; /* ircnet->nstype starts at 1, server->nickservtype starts at 0! */ serv->loginmethod = net->logintype;
} }
else else
{ {
serv->nickservtype = 1; /* use /NickServ by default */ serv->loginmethod = 2; /* use /NickServ by default */
} }
serv->password[0] = 0; serv->password[0] = 0;
serv->sasluser[0] = 0; serv->sasluser[0] = 0;
serv->saslpassword[0] = 0;
if (net->pass) if (net->pass)
{ {
@ -645,11 +644,6 @@ servlist_connect (session *sess, ircnet *net, gboolean join)
safe_strcpy (serv->sasluser, net->user, sizeof (serv->sasluser)); safe_strcpy (serv->sasluser, net->user, sizeof (serv->sasluser));
} }
if (net->saslpass)
{
safe_strcpy (serv->saslpassword, net->saslpass, sizeof (serv->saslpassword));
}
if (net->flags & FLAG_USE_GLOBAL) if (net->flags & FLAG_USE_GLOBAL)
{ {
strcpy (serv->nick, prefs.hex_irc_nick1); strcpy (serv->nick, prefs.hex_irc_nick1);
@ -941,7 +935,6 @@ servlist_cleanup (void)
{ {
net = list->data; net = list->data;
free_and_clear (net->pass); free_and_clear (net->pass);
free_and_clear (net->saslpass);
free_and_clear (net->nickserv); free_and_clear (net->nickserv);
} }
} }
@ -964,7 +957,6 @@ servlist_net_remove (ircnet *net)
if (net->real) if (net->real)
free (net->real); free (net->real);
free_and_clear (net->pass); free_and_clear (net->pass);
free_and_clear (net->saslpass);
if (net->autojoin) if (net->autojoin)
free (net->autojoin); free (net->autojoin);
if (net->command) if (net->command)
@ -1029,9 +1021,9 @@ servlist_load_defaults (void)
free (net->encoding); free (net->encoding);
net->encoding = strdup (def[i].charset); net->encoding = strdup (def[i].charset);
} }
if (def[i].nsmode) if (def[i].loginmode)
{ {
net->nstype = def[i].nsmode; net->logintype = def[i].loginmode;
} }
if (g_str_hash (def[i].network) == def_hash) if (g_str_hash (def[i].network) == def_hash)
{ {
@ -1100,9 +1092,6 @@ servlist_load (void)
case 'P': case 'P':
net->pass = strdup (buf + 2); net->pass = strdup (buf + 2);
break; break;
case 'A':
net->saslpass = strdup (buf + 2);
break;
case 'J': case 'J':
net->autojoin = strdup (buf + 2); net->autojoin = strdup (buf + 2);
break; break;
@ -1134,8 +1123,8 @@ servlist_load (void)
case 'B': case 'B':
net->nickserv = strdup (buf + 2); net->nickserv = strdup (buf + 2);
break; break;
case 'T': case 'L':
net->nstype = atoi (buf + 2); net->logintype = atoi (buf + 2);
break; break;
} }
} }
@ -1244,26 +1233,12 @@ servlist_save (void)
fprintf (fp, "R=%s\n", net->real); fprintf (fp, "R=%s\n", net->real);
if (net->pass) if (net->pass)
fprintf (fp, "P=%s\n", net->pass); fprintf (fp, "P=%s\n", net->pass);
if (net->saslpass)
fprintf (fp, "A=%s\n", net->saslpass);
if (net->autojoin) if (net->autojoin)
fprintf (fp, "J=%s\n", net->autojoin); fprintf (fp, "J=%s\n", net->autojoin);
if (net->nickserv) if (net->nickserv)
fprintf (fp, "B=%s\n", net->nickserv); fprintf (fp, "B=%s\n", net->nickserv);
if (net->nstype) if (net->logintype)
{ fprintf (fp, "L=%d\n", net->logintype);
if (net->nstype == -1) /* gtk_combo_box_get_active() returns -1 for invalid indices */
{
net->nstype = 0; /* avoid further crashes for the current session */
buf = g_strdup_printf (_("Warning: invalid NickServ type. Falling back to default type for network %s."), net->name);
fe_message (buf, FE_MSG_WARN);
g_free (buf);
}
else /* the selection was fine, save it */
{
fprintf (fp, "T=%d\n", net->nstype);
}
}
if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") && if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") &&
g_ascii_strcasecmp (net->encoding, "System default")) g_ascii_strcasecmp (net->encoding, "System default"))
{ {

View File

@ -33,11 +33,10 @@ typedef struct ircnet
char *user; char *user;
char *real; char *real;
char *pass; char *pass;
char *saslpass;
char *autojoin; char *autojoin;
char *command; char *command;
char *nickserv; char *nickserv;
int nstype; int logintype;
char *comment; char *comment;
char *encoding; char *encoding;
GSList *servlist; GSList *servlist;

View File

@ -64,7 +64,6 @@ static GtkWidget *edit_entry_user;
static GtkWidget *edit_entry_real; static GtkWidget *edit_entry_real;
static GtkWidget *edit_entry_join; static GtkWidget *edit_entry_join;
static GtkWidget *edit_entry_pass; static GtkWidget *edit_entry_pass;
static GtkWidget *edit_entry_saslpass;
static GtkWidget *edit_entry_cmd; static GtkWidget *edit_entry_cmd;
static GtkWidget *edit_entry_nickserv; static GtkWidget *edit_entry_nickserv;
static GtkWidget *edit_label_nick; static GtkWidget *edit_label_nick;
@ -103,24 +102,53 @@ static const char *pages[]=
NULL NULL
}; };
static const char *nstypes[]= /* This is our dictionary for authentication types. Keep these in sync with
* login_types[]! This allows us to re-order the login type dropdown in the
* network list without breaking config compatibility.
*/
static int login_types_conf[] =
{ {
/* This list is the same as in irc_nickserv(), except starting at 1, because 0, /* default - we don't use this but it makes indexing consistent with login_types[] so it's nice */
* the 1st row is not used. We can't use index 0 coz then "if (nstype)" would 6, /* SASL */
* not be evaluated, it would give the same result as NULL (i.e. unset) nstype. 7, /* /pass */
* For unset nstype we have a "Default" entry in place of this placeholder, so 1, /* /msg NickServ */
* indices will be correct anyway. 2, /* /NickServ */
*/ 3, /* /NS */
"PLACEHOLDER", /* nstype = 0 */ 4, /* /msg NS */
"/msg NickServ", /* nstype = 1, nickservtype = 0 */ 5, /* /auth */
"/NickServ", /* nstype = 2, nickservtype = 1 */ };
"/NS", /* ... */
static const char *login_types[]=
{
"Default",
"SASL",
"/pass",
"/msg NickServ",
"/NickServ",
"/NS",
"/msg NS", "/msg NS",
"/auth", "/auth",
NULL NULL
/* This also means that we need to shift these values for irc_nickserv()! */
}; };
/* poor man's IndexOf() - find the dropdown string index that belongs to the given config value */
static int
servlist_get_login_desc_index (int conf_value)
{
int i;
int length = sizeof (login_types_conf) / sizeof (login_types_conf[0]); /* the number of elements in the conf array */
for (i = 0; i < length; i++)
{
if (login_types_conf[i] == conf_value)
{
return i;
}
}
return 0; /* make the compiler happy */
}
static void static void
servlist_select_and_show (GtkTreeView *treeview, GtkTreeIter *iter, servlist_select_and_show (GtkTreeView *treeview, GtkTreeIter *iter,
GtkListStore *store) GtkListStore *store)
@ -500,7 +528,6 @@ servlist_edit_update (ircnet *net)
servlist_update_from_entry (&net->command, edit_entry_cmd); servlist_update_from_entry (&net->command, edit_entry_cmd);
servlist_update_from_entry (&net->nickserv, edit_entry_nickserv); servlist_update_from_entry (&net->nickserv, edit_entry_nickserv);
servlist_update_from_entry (&net->pass, edit_entry_pass); servlist_update_from_entry (&net->pass, edit_entry_pass);
servlist_update_from_entry (&net->saslpass, edit_entry_saslpass);
} }
static void static void
@ -1328,9 +1355,12 @@ servlist_combo_cb (GtkEntry *entry, gpointer userdata)
} }
} }
/* Fills up the network's authentication type so that it's guaranteed to be either NULL or a valid value. */
static void static void
servlist_nscombo_cb (GtkEntry *entry, gpointer userdata) servlist_logintypecombo_cb (GtkEntry *entry, gpointer userdata)
{ {
int index;
if (!selected_net) if (!selected_net)
{ {
return; return;
@ -1338,7 +1368,15 @@ servlist_nscombo_cb (GtkEntry *entry, gpointer userdata)
if (!ignore_changed) if (!ignore_changed)
{ {
selected_net->nstype = gtk_combo_box_get_active (GTK_COMBO_BOX (entry)); index = gtk_combo_box_get_active (GTK_COMBO_BOX (entry)); /* starts at 0, returns -1 for invalid selections */
if (index != -1)
{
/* The selection is valid. It can be 0, which is the default type, but we need to allow
* that so that you can revert from other types. servlist_save() will dump 0 anyway.
*/
selected_net->logintype = login_types_conf[index];
}
} }
} }
@ -1364,23 +1402,22 @@ servlist_create_charsetcombo (void)
} }
static GtkWidget * static GtkWidget *
servlist_create_nstypecombo (void) servlist_create_logintypecombo (void)
{ {
GtkWidget *cb; GtkWidget *cb;
int i; int i;
cb = gtk_combo_box_entry_new_text (); cb = gtk_combo_box_entry_new_text ();
gtk_combo_box_append_text (GTK_COMBO_BOX (cb), "Default");
i = 1; /* start with the 2nd row, leave the placeholder 0th element alone */ i = 0;
while (nstypes[i]) while (login_types[i])
{ {
gtk_combo_box_append_text (GTK_COMBO_BOX (cb), (char *)nstypes[i]); gtk_combo_box_append_text (GTK_COMBO_BOX (cb), (char *)login_types[i]);
i++; i++;
} }
g_signal_connect (G_OBJECT (GTK_BIN (cb)), "changed", G_CALLBACK (servlist_nscombo_cb), NULL); g_signal_connect (G_OBJECT (GTK_BIN (cb)), "changed", G_CALLBACK (servlist_logintypecombo_cb), NULL);
return cb; return cb;
} }
@ -1430,9 +1467,9 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
GtkWidget *label16; GtkWidget *label16;
GtkWidget *label21; GtkWidget *label21;
GtkWidget *label34; GtkWidget *label34;
GtkWidget *label_nstype; GtkWidget *label_logintype;
GtkWidget *comboboxentry_charset; GtkWidget *comboboxentry_charset;
GtkWidget *comboboxentry_nstypes; GtkWidget *comboboxentry_logintypes;
GtkWidget *hbox1; GtkWidget *hbox1;
GtkWidget *scrolledwindow2; GtkWidget *scrolledwindow2;
GtkWidget *treeview_servers; GtkWidget *treeview_servers;
@ -1545,37 +1582,31 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
_("If your nickname requires a password, enter it here. Not all IRC networks support this.")); _("If your nickname requires a password, enter it here. Not all IRC networks support this."));
gtk_entry_set_visibility (GTK_ENTRY (edit_entry_nickserv), FALSE); gtk_entry_set_visibility (GTK_ENTRY (edit_entry_nickserv), FALSE);
label_nstype = gtk_label_new (_("NickServ type:")); label_logintype = gtk_label_new (_("Login method:"));
gtk_widget_show (label_nstype); gtk_widget_show (label_logintype);
gtk_table_attach (GTK_TABLE (table3), label_nstype, 1, 2, 18, 19, gtk_table_attach (GTK_TABLE (table3), label_logintype, 1, 2, 18, 19,
(GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0); (GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label_nstype), 0, 0.5); gtk_misc_set_alignment (GTK_MISC (label_logintype), 0, 0.5);
comboboxentry_nstypes = servlist_create_nstypecombo (); comboboxentry_logintypes = servlist_create_logintypecombo ();
ignore_changed = TRUE; ignore_changed = TRUE;
gtk_entry_set_text (GTK_ENTRY (GTK_BIN (comboboxentry_nstypes)->child), net->nstype ? nstypes[net->nstype] : "Default"); gtk_entry_set_text (GTK_ENTRY (GTK_BIN (comboboxentry_logintypes)->child), net->logintype ? login_types[servlist_get_login_desc_index (net->logintype)] : login_types[0]);
ignore_changed = FALSE; ignore_changed = FALSE;
gtk_widget_show (comboboxentry_nstypes); gtk_widget_show (comboboxentry_logintypes);
gtk_table_attach (GTK_TABLE (table3), comboboxentry_nstypes, 2, 3, 18, 19, gtk_table_attach (GTK_TABLE (table3), comboboxentry_logintypes, 2, 3, 18, 19,
(GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 0, 0); (GtkAttachOptions) (GTK_FILL), 0, 0);
edit_entry_pass = edit_entry_pass =
servlist_create_entry (table3, _("Server password:"), 20, servlist_create_entry (table3, _("Password:"), 20,
net->pass, 0, net->pass, 0,
_("Password for the server, if in doubt, leave blank.")); _("Password used for login. If in doubt, leave blank."));
gtk_entry_set_visibility (GTK_ENTRY (edit_entry_pass), FALSE); gtk_entry_set_visibility (GTK_ENTRY (edit_entry_pass), FALSE);
edit_entry_saslpass =
servlist_create_entry (table3, _("SASL password:"), 21,
net->saslpass, 0,
_("Password for SASL authentication, if in doubt, leave blank."));
gtk_entry_set_visibility (GTK_ENTRY (edit_entry_saslpass), FALSE);
label34 = gtk_label_new (_("Character set:")); label34 = gtk_label_new (_("Character set:"));
gtk_widget_show (label34); gtk_widget_show (label34);
gtk_table_attach (GTK_TABLE (table3), label34, 1, 2, 22, 23, gtk_table_attach (GTK_TABLE (table3), label34, 1, 2, 21, 22,
(GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0); (GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5); gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5);
@ -1585,7 +1616,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
gtk_entry_set_text (GTK_ENTRY (GTK_BIN (comboboxentry_charset)->child), net->encoding ? net->encoding : "System default"); gtk_entry_set_text (GTK_ENTRY (GTK_BIN (comboboxentry_charset)->child), net->encoding ? net->encoding : "System default");
ignore_changed = FALSE; ignore_changed = FALSE;
gtk_widget_show (comboboxentry_charset); gtk_widget_show (comboboxentry_charset);
gtk_table_attach (GTK_TABLE (table3), comboboxentry_charset, 2, 3, 22, 23, gtk_table_attach (GTK_TABLE (table3), comboboxentry_charset, 2, 3, 21, 22,
(GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 0, 0); (GtkAttachOptions) (GTK_FILL), 0, 0);