Ask for confirmation before doing a clone by default

This commit is contained in:
Kovid Goyal 2022-04-16 20:04:26 +05:30
parent 53788c4c89
commit df9b13fb74
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 31 additions and 2 deletions

View File

@ -2774,6 +2774,15 @@ pager, etc. on supported shells. Set to ``disabled`` to turn off shell
integration, completely. See :ref:`shell_integration` for details. integration, completely. See :ref:`shell_integration` for details.
''') ''')
opt('allow_cloning', 'ask', choices=('yes', 'no', 'ask'), long_text='''
Control whether programs running in the terminal can request new
windows to be created. The canonical example is :code:`clone-in-kitty`.
By default, kitty will ask for permission for each clone request.
Allowing cloning unconditionally gives programs running in the terminal
(including over SSH) permission to execute arbitrary code as the user
the terminal is running as on the computer the terminal is running on.
''')
opt('term', 'xterm-kitty', opt('term', 'xterm-kitty',
long_text=''' long_text='''
The value of the TERM environment variable to set. Changing this can break many The value of the TERM environment variable to set. Changing this can break many

View File

@ -50,6 +50,14 @@ class Parser:
def adjust_line_height(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: def adjust_line_height(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['adjust_line_height'] = adjust_line_height(val) ans['adjust_line_height'] = adjust_line_height(val)
def allow_cloning(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
val = val.lower()
if val not in self.choices_for_allow_cloning:
raise ValueError(f"The value {val} is not a valid choice for allow_cloning")
ans["allow_cloning"] = val
choices_for_allow_cloning = frozenset(('yes', 'no', 'ask'))
def allow_hyperlinks(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: def allow_hyperlinks(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['allow_hyperlinks'] = allow_hyperlinks(val) ans['allow_hyperlinks'] = allow_hyperlinks(val)

View File

@ -13,6 +13,7 @@ from kitty.types import FloatEdges, SingleKey
import kitty.types import kitty.types
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
choices_for_allow_cloning = typing.Literal['yes', 'no', 'ask']
choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled', 'clamped'] choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled', 'clamped']
choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'hand'] choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'hand']
choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11'] choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11']
@ -27,6 +28,7 @@ if typing.TYPE_CHECKING:
choices_for_tab_switch_strategy = typing.Literal['last', 'left', 'previous', 'right'] choices_for_tab_switch_strategy = typing.Literal['last', 'left', 'previous', 'right']
choices_for_window_logo_position = typing.Literal['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right'] choices_for_window_logo_position = typing.Literal['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']
else: else:
choices_for_allow_cloning = str
choices_for_background_image_layout = str choices_for_background_image_layout = str
choices_for_default_pointer_shape = str choices_for_default_pointer_shape = str
choices_for_linux_display_server = str choices_for_linux_display_server = str
@ -51,6 +53,7 @@ option_names = ( # {{{
'adjust_baseline', 'adjust_baseline',
'adjust_column_width', 'adjust_column_width',
'adjust_line_height', 'adjust_line_height',
'allow_cloning',
'allow_hyperlinks', 'allow_hyperlinks',
'allow_remote_control', 'allow_remote_control',
'background', 'background',
@ -461,6 +464,7 @@ class Options:
adjust_baseline: typing.Union[int, float] = 0 adjust_baseline: typing.Union[int, float] = 0
adjust_column_width: typing.Union[int, float] = 0 adjust_column_width: typing.Union[int, float] = 0
adjust_line_height: typing.Union[int, float] = 0 adjust_line_height: typing.Union[int, float] = 0
allow_cloning: choices_for_allow_cloning = 'ask'
allow_hyperlinks: int = 1 allow_hyperlinks: int = 1
allow_remote_control: str = 'n' allow_remote_control: str = 'n'
background: Color = Color(0, 0, 0) background: Color = Color(0, 0, 0)

View File

@ -1015,8 +1015,11 @@ class Window:
if not msg: if not msg:
if self.current_clone_data: if self.current_clone_data:
cdata, self.current_clone_data = self.current_clone_data, '' cdata, self.current_clone_data = self.current_clone_data, ''
from .launch import clone_and_launch get_boss().confirm(_(
clone_and_launch(cdata, self) 'A program running in this window wants to clone it into another window.'
' Allow it do so, once?'),
partial(self.handle_remote_clone_confirmation, cdata), window=self,
)
self.current_clone_data = '' self.current_clone_data = ''
return return
num, rest = msg.split(':', 1) num, rest = msg.split(':', 1)
@ -1024,6 +1027,11 @@ class Window:
self.current_clone_data = '' self.current_clone_data = ''
self.current_clone_data += rest self.current_clone_data += rest
def handle_remote_clone_confirmation(self, cdata: str, confirmed: bool) -> None:
if confirmed:
from .launch import clone_and_launch
clone_and_launch(cdata, self)
def handle_remote_askpass(self, msg: str) -> None: def handle_remote_askpass(self, msg: str) -> None:
from .shm import SharedMemory from .shm import SharedMemory
with SharedMemory(name=msg, readonly=True) as shm: with SharedMemory(name=msg, readonly=True) as shm: