diff --git a/src/common/hexchat.h b/src/common/hexchat.h index dd30dce6..f3b9ce85 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -528,13 +528,12 @@ typedef struct server char servername[128]; /* what the server says is its name */ char password[86]; 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 linebuf[2048]; /* RFC says 512 chars including \r\n */ char *last_away_reason; int pos; /* current position in linebuf */ int nickcount; - int nickservtype; /* 0=/MSG nickserv 1=/NICKSERV 2=/NS */ + int loginmethod; /* see login_types[] */ char *chantypes; /* for 005 numeric - free me */ char *chanmodes; /* for 005 numeric - free me */ diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index 984f7f20..53225a95 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -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 */ - if (serv->password[0]) + if (serv->password[0] && serv->loginmethod == 7) { 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) { /* 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); break; - case 1: + case 2: tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; - case 2: + case 3: tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; - case 3: + case 4: tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; - case 4: + case 5: /* why couldn't QuakeNet implement one of the existing ones? */ 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 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, ""); } @@ -100,7 +100,7 @@ irc_ns_identify (server *serv, char *pass) static void irc_ns_ghost (server *serv, char *usname, char *pass) { - if (serv->nickservtype != 4) + if (serv->loginmethod != 5) 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); 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); free (pass); } @@ -1259,8 +1259,8 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) strcat (buffer, "extended-join "); want_cap = 1; } - /* if the SASL password is set, request SASL auth */ - if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0) + /* 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->password) != 0 && serv->loginmethod == 6) { strcat (buffer, "sasl "); want_cap = 1; diff --git a/src/common/servlist.c b/src/common/servlist.c index 4b04820b..d49b603e 100644 --- a/src/common/servlist.c +++ b/src/common/servlist.c @@ -43,7 +43,7 @@ struct defaultserver char *host; char *channel; char *charset; - int nsmode; /* default NickServ type */ + int loginmode; /* default authentication type */ }; static const struct defaultserver def[] = @@ -245,7 +245,7 @@ static const struct defaultserver def[] = {0, "irc.ggn.net"}, {0, "irc.vendetta.com"}, - {"freenode", 0, "#hexchat"}, + {"freenode", 0, "#hexchat", 0, 6}, #ifdef USE_OPENSSL {0, "irc.freenode.net/+6697"}, #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 { - serv->nickservtype = 1; /* use /NickServ by default */ + serv->loginmethod = 2; /* use /NickServ by default */ } serv->password[0] = 0; serv->sasluser[0] = 0; - serv->saslpassword[0] = 0; if (net->pass) { @@ -645,11 +644,6 @@ servlist_connect (session *sess, ircnet *net, gboolean join) 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) { strcpy (serv->nick, prefs.hex_irc_nick1); @@ -941,7 +935,6 @@ servlist_cleanup (void) { net = list->data; free_and_clear (net->pass); - free_and_clear (net->saslpass); free_and_clear (net->nickserv); } } @@ -964,7 +957,6 @@ servlist_net_remove (ircnet *net) if (net->real) free (net->real); free_and_clear (net->pass); - free_and_clear (net->saslpass); if (net->autojoin) free (net->autojoin); if (net->command) @@ -1029,9 +1021,9 @@ servlist_load_defaults (void) free (net->encoding); 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) { @@ -1100,9 +1092,6 @@ servlist_load (void) case 'P': net->pass = strdup (buf + 2); break; - case 'A': - net->saslpass = strdup (buf + 2); - break; case 'J': net->autojoin = strdup (buf + 2); break; @@ -1134,8 +1123,8 @@ servlist_load (void) case 'B': net->nickserv = strdup (buf + 2); break; - case 'T': - net->nstype = atoi (buf + 2); + case 'L': + net->logintype = atoi (buf + 2); break; } } @@ -1244,26 +1233,12 @@ servlist_save (void) fprintf (fp, "R=%s\n", net->real); if (net->pass) fprintf (fp, "P=%s\n", net->pass); - if (net->saslpass) - fprintf (fp, "A=%s\n", net->saslpass); if (net->autojoin) fprintf (fp, "J=%s\n", net->autojoin); if (net->nickserv) fprintf (fp, "B=%s\n", net->nickserv); - if (net->nstype) - { - 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->logintype) + fprintf (fp, "L=%d\n", net->logintype); if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") && g_ascii_strcasecmp (net->encoding, "System default")) { diff --git a/src/common/servlist.h b/src/common/servlist.h index b652f463..c70c3871 100644 --- a/src/common/servlist.h +++ b/src/common/servlist.h @@ -33,11 +33,10 @@ typedef struct ircnet char *user; char *real; char *pass; - char *saslpass; char *autojoin; char *command; char *nickserv; - int nstype; + int logintype; char *comment; char *encoding; GSList *servlist; diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c index 8d480dc4..4af648ca 100644 --- a/src/fe-gtk/servlistgui.c +++ b/src/fe-gtk/servlistgui.c @@ -64,7 +64,6 @@ static GtkWidget *edit_entry_user; static GtkWidget *edit_entry_real; static GtkWidget *edit_entry_join; static GtkWidget *edit_entry_pass; -static GtkWidget *edit_entry_saslpass; static GtkWidget *edit_entry_cmd; static GtkWidget *edit_entry_nickserv; static GtkWidget *edit_label_nick; @@ -103,24 +102,53 @@ static const char *pages[]= 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 - * the 1st row is not used. We can't use index 0 coz then "if (nstype)" would - * not be evaluated, it would give the same result as NULL (i.e. unset) nstype. - * For unset nstype we have a "Default" entry in place of this placeholder, so - * indices will be correct anyway. - */ - "PLACEHOLDER", /* nstype = 0 */ - "/msg NickServ", /* nstype = 1, nickservtype = 0 */ - "/NickServ", /* nstype = 2, nickservtype = 1 */ - "/NS", /* ... */ + 0, /* default - we don't use this but it makes indexing consistent with login_types[] so it's nice */ + 6, /* SASL */ + 7, /* /pass */ + 1, /* /msg NickServ */ + 2, /* /NickServ */ + 3, /* /NS */ + 4, /* /msg NS */ + 5, /* /auth */ +}; + +static const char *login_types[]= +{ + "Default", + "SASL", + "/pass", + "/msg NickServ", + "/NickServ", + "/NS", "/msg NS", "/auth", 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 servlist_select_and_show (GtkTreeView *treeview, GtkTreeIter *iter, 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->nickserv, edit_entry_nickserv); servlist_update_from_entry (&net->pass, edit_entry_pass); - servlist_update_from_entry (&net->saslpass, edit_entry_saslpass); } 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 -servlist_nscombo_cb (GtkEntry *entry, gpointer userdata) +servlist_logintypecombo_cb (GtkEntry *entry, gpointer userdata) { + int index; + if (!selected_net) { return; @@ -1338,7 +1368,15 @@ servlist_nscombo_cb (GtkEntry *entry, gpointer userdata) 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 * -servlist_create_nstypecombo (void) +servlist_create_logintypecombo (void) { GtkWidget *cb; int i; 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++; } - 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; } @@ -1430,9 +1467,9 @@ servlist_open_edit (GtkWidget *parent, ircnet *net) GtkWidget *label16; GtkWidget *label21; GtkWidget *label34; - GtkWidget *label_nstype; + GtkWidget *label_logintype; GtkWidget *comboboxentry_charset; - GtkWidget *comboboxentry_nstypes; + GtkWidget *comboboxentry_logintypes; GtkWidget *hbox1; GtkWidget *scrolledwindow2; 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.")); gtk_entry_set_visibility (GTK_ENTRY (edit_entry_nickserv), FALSE); - label_nstype = gtk_label_new (_("NickServ type:")); - gtk_widget_show (label_nstype); - gtk_table_attach (GTK_TABLE (table3), label_nstype, 1, 2, 18, 19, + label_logintype = gtk_label_new (_("Login method:")); + gtk_widget_show (label_logintype); + gtk_table_attach (GTK_TABLE (table3), label_logintype, 1, 2, 18, 19, (GtkAttachOptions) (GTK_FILL), (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; - 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; - gtk_widget_show (comboboxentry_nstypes); - gtk_table_attach (GTK_TABLE (table3), comboboxentry_nstypes, 2, 3, 18, 19, + gtk_widget_show (comboboxentry_logintypes); + gtk_table_attach (GTK_TABLE (table3), comboboxentry_logintypes, 2, 3, 18, 19, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 0); edit_entry_pass = - servlist_create_entry (table3, _("Server password:"), 20, + servlist_create_entry (table3, _("Password:"), 20, 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); - 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:")); 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) (0), 0, 0); 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"); ignore_changed = FALSE; 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), 0, 0);