From f4bec5f4ab84caa0ba1a5e72e8b0f6a67c81a98d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 Jun 2024 11:15:19 +0530 Subject: [PATCH] Remote control: Fix empty password not working Fixes #7538 --- docs/changelog.rst | 2 ++ kitty/options/utils.py | 2 +- kitty/remote_control.py | 5 +++-- tools/cmd/at/main.go | 44 ++++++++++++++++++++++++----------------- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 7981e411c..609f8ce7a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -57,6 +57,8 @@ Detailed list of changes - A new option, :opt:`cursor_shape_unfocused` to specify the shape of the text cursor in unfocused OS windows (:pull:`7544`) +- Remote control: Fix empty password not working (:iss:`7538`) + 0.35.1 [2024-05-31] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/options/utils.py b/kitty/options/utils.py index 3930ad4f3..099a05f16 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -794,7 +794,7 @@ def remote_control_password(val: str, current_val: Dict[str, str]) -> Iterable[T # line of remote_control_password raise ValueError('Passwords are not allowed to start with hyphens, ignoring this password') if len(parts) == 1: - yield parts[0], tuple() + yield "", (parts[0],) else: yield parts[0], tuple(parts[1:]) diff --git a/kitty/remote_control.py b/kitty/remote_control.py index 3fce5cbf4..02075ac25 100644 --- a/kitty/remote_control.py +++ b/kitty/remote_control.py @@ -276,7 +276,8 @@ they will only work if this process is run within a kitty window. --password A password to use when contacting kitty. This will cause kitty to ask the user for permission to perform the specified action, unless the password has been -accepted before or is pre-configured in :file:`kitty.conf`. +accepted before or is pre-configured in :file:`kitty.conf`. To use a blank password +specify :option:`kitten @ --use-password` as :code:`always`. --password-file @@ -300,7 +301,7 @@ default=if-available choices=if-available,never,always If no password is available, kitty will usually just send the remote control command without a password. This option can be used to force it to :code:`always` or :code:`never` use -the supplied password. +the supplied password. If set to always and no password is provided, the blank password is used. '''.format, appname=appname) diff --git a/tools/cmd/at/main.go b/tools/cmd/at/main.go index cc684bfd6..826807f7d 100644 --- a/tools/cmd/at/main.go +++ b/tools/cmd/at/main.go @@ -32,10 +32,16 @@ const lowerhex = "0123456789abcdef" var ProtocolVersion [3]int = [3]int{0, 26, 0} +type password struct { + val string + is_set bool +} + type GlobalOptions struct { - to_network, to_address, password string - to_address_is_from_env_var bool - already_setup bool + to_network, to_address string + password password + to_address_is_from_env_var bool + already_setup bool } var global_options GlobalOptions @@ -135,15 +141,15 @@ func simple_serializer(rc *utils.RemoteControlCmd) (ans []byte, err error) { type serializer_func func(rc *utils.RemoteControlCmd) ([]byte, error) -func create_serializer(password string, encoded_pubkey string, io_data *rc_io_data) (err error) { +func create_serializer(password password, encoded_pubkey string, io_data *rc_io_data) (err error) { io_data.serializer = simple_serializer - if password != "" { + if password.is_set { encryption_version, pubkey, err := get_pubkey(encoded_pubkey) if err != nil { return err } io_data.serializer = func(rc *utils.RemoteControlCmd) (ans []byte, err error) { - ec, err := crypto.Encrypt_cmd(rc, global_options.password, pubkey, encryption_version) + ec, err := crypto.Encrypt_cmd(rc, global_options.password.val, pubkey, encryption_version) if err != nil { return } @@ -293,25 +299,26 @@ func send_rc_command(io_data *rc_io_data) (err error) { return } -func get_password(password string, password_file string, password_env string, use_password string) (ans string, err error) { +func get_password(password string, password_file string, password_env string, use_password string) (ans password, err error) { if use_password == "never" { return } if password != "" { - ans = password + ans.is_set, ans.val = true, password } - if ans == "" && password_file != "" { + if !ans.is_set && password_file != "" { if password_file == "-" { if tty.IsTerminal(os.Stdin.Fd()) { - ans, err = tui.ReadPassword("Password: ", true) + p, err := tui.ReadPassword("Password: ", true) if err != nil { - return + return ans, err } + ans.is_set, ans.val = true, p } else { var q []byte q, err = io.ReadAll(os.Stdin) if err == nil { - ans = strings.TrimRight(string(q), " \n\t") + ans.is_set, ans.val = true, strings.TrimRight(string(q), " \n\t") } ttyf, err := os.Open(tty.Ctermid()) if err == nil { @@ -323,7 +330,7 @@ func get_password(password string, password_file string, password_env string, us var q []byte q, err = os.ReadFile(password_file) if err == nil { - ans = strings.TrimRight(string(q), " \n\t") + ans.is_set, ans.val = true, strings.TrimRight(string(q), " \n\t") } else { if errors.Is(err, os.ErrNotExist) { err = nil @@ -334,13 +341,14 @@ func get_password(password string, password_file string, password_env string, us return } } - if ans == "" && password_env != "" { - ans = os.Getenv(password_env) + if !ans.is_set && password_env != "" { + ans.val, ans.is_set = os.LookupEnv(password_env) } - if ans == "" && use_password == "always" { - return ans, fmt.Errorf("No password was found") + if !ans.is_set && use_password == "always" { + ans.is_set = true + return ans, nil } - if len(ans) > 1024 { + if len(ans.val) > 1024 { return ans, fmt.Errorf("Specified password is too long") } return ans, nil