From b57fb48b274bdb5bea806d8aa4a08e7d4121e20d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 23 Sep 2024 16:59:11 +0100 Subject: [PATCH] Change type of CONF_username to the new CONF_TYPE_STR_AMBI. This is the pathfinding change that proves it's possible for _one_ Conf setting to become Unicode-capable. That seems like quite a small reward for all the refactoring in the previous patches this week! But changing over one configuration setting is enough to get started with: once all the bugs are out of this one, we can try switching over some more. Changing the type to CONF_TYPE_STR_AMBI is enough by itself to make the configuration dialog box write it into Conf as UTF-8, because conf_editbox_handler automatically checks whether that possibility is available. However, setting the same Conf entry from the command line isn't automatic: I had to add code in the handler for the -l command-line option in cmdline.c. This commit also doesn't yet handle the _other_ way to specify a username on the command line: including it as part of the hostname argument via "putty user@host" or similar. That's more difficult, because it also requires deciding what to do about UTF-8 in the actual hostname. (That looks as if it ought to be possible: Windows should be able to handle looking up Unicode hostnames if you use GetAddrInfoW() in place of getaddrinfo(). But plumbing it through everything in between cmdline.c and windows/network.c is a bigger job than I'm prepared to do in this proof-of-concept commit.) --- cmdline.c | 6 +++++- conf.h | 2 +- pscp.c | 2 +- settings.c | 4 +++- test/test_conf.c | 2 +- unix/plink.c | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cmdline.c b/cmdline.c index 682b5979..4a84fa1c 100644 --- a/cmdline.c +++ b/cmdline.c @@ -195,6 +195,7 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg, { int ret = 0; const char *p = cmdline_arg_to_str(arg); + const char *value_utf8 = cmdline_arg_to_utf8(nextarg); const char *value = cmdline_arg_to_str(nextarg); if (p[0] != '-') { @@ -459,7 +460,10 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg, RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); - conf_set_str(conf, CONF_username, value); + if (value_utf8) + conf_set_utf8(conf, CONF_username, value_utf8); + else + conf_set_str(conf, CONF_username, value); } if (!strcmp(p, "-loghost")) { RETURN(2); diff --git a/conf.h b/conf.h index c8ad4785..ce336b99 100644 --- a/conf.h +++ b/conf.h @@ -444,7 +444,7 @@ CONF_OPTION(environmt, LOAD_CUSTOM, SAVE_CUSTOM, /* necessary for mappings */ ) CONF_OPTION(username, - VALUE_TYPE(STR), + VALUE_TYPE(STR_AMBI), DEFAULT_STR(""), SAVE_KEYWORD("UserName"), ) diff --git a/pscp.c b/pscp.c index 7edee6ab..93e31204 100644 --- a/pscp.c +++ b/pscp.c @@ -391,7 +391,7 @@ static void do_cmd(char *host, char *user, char *cmd) /* Set username */ if (user != NULL && user[0] != '\0') { conf_set_str(conf, CONF_username, user); - } else if (conf_get_str(conf, CONF_username)[0] == '\0') { + } else if (conf_get_str_ambi(conf, CONF_username, NULL)[0] == '\0') { user = get_username(); if (!user) bump("Empty user name"); diff --git a/settings.c b/settings.c index 71b45fd1..e6d23101 100644 --- a/settings.c +++ b/settings.c @@ -112,7 +112,9 @@ const struct BackendVtable *backend_vt_from_proto(int proto) char *get_remote_username(Conf *conf) { - char *username = conf_get_str(conf, CONF_username); + /* We don't worry about whether the username is stored as UTF-8, + * because SSH wants it as UTF-8 */ + char *username = conf_get_str_ambi(conf, CONF_username, NULL); if (*username) { return dupstr(username); } else if (conf_get_bool(conf, CONF_username_from_env)) { diff --git a/test/test_conf.c b/test/test_conf.c index e305a2be..d71ea634 100644 --- a/test/test_conf.c +++ b/test/test_conf.c @@ -717,7 +717,7 @@ void test_simple(void) test_bool_simple(CONF_ssh_no_shell, "SshNoShell", false); test_str_simple(CONF_termtype, "TerminalType", "xterm"); test_str_simple(CONF_termspeed, "TerminalSpeed", "38400,38400"); - test_str_simple(CONF_username, "UserName", ""); + test_str_ambi_simple(CONF_username, "UserName", "", false); test_bool_simple(CONF_username_from_env, "UserNameFromEnvironment", false); test_str_simple(CONF_localusername, "LocalUserName", ""); test_bool_simple(CONF_rfc_environ, "RFCEnviron", false); diff --git a/unix/plink.c b/unix/plink.c index c316793c..0f8056e0 100644 --- a/unix/plink.c +++ b/unix/plink.c @@ -823,7 +823,7 @@ int main(int argc, char **argv) * If we have no better ideas for the remote username, use the local * one, as 'ssh' does. */ - if (conf_get_str(conf, CONF_username)[0] == '\0') { + if (conf_get_str_ambi(conf, CONF_username, NULL)[0] == '\0') { char *user = get_username(); if (user) { conf_set_str(conf, CONF_username, user);