More work on the transfer kitten
This commit is contained in:
parent
2a9dff2846
commit
68436c93a7
@ -30,9 +30,9 @@ receiving computer. In :code:`normal` mode the last argument is assumed to be a
|
||||
destination path on the receiving computer.
|
||||
|
||||
|
||||
--permissions-password -p
|
||||
--permissions-bypass -p
|
||||
The password to use to skip the transfer confirmation popup in kitty. Must match the
|
||||
password set for the :opt:`file_transfer_password` option in kitty.conf. Note that
|
||||
password set for the :opt:`file_transfer_confirmation_bypass` option in kitty.conf. Note that
|
||||
leading and trailing whitespace is removed from the password. A password starting with
|
||||
., / or ~ characters is assumed to be a file name to read the password from. A value
|
||||
of - means read the password from STDIN. A password that is purely a number less than 256
|
||||
@ -71,8 +71,8 @@ def read_password(loc: str) -> str:
|
||||
|
||||
def main(args: List[str]) -> None:
|
||||
cli_opts, items = parse_transfer_args(args)
|
||||
if cli_opts.permissions_password:
|
||||
cli_opts.permissions_password = read_password(cli_opts.permissions_password).strip()
|
||||
if cli_opts.permissions_bypass:
|
||||
cli_opts.permissions_bypass = read_password(cli_opts.permissions_bypass).strip()
|
||||
|
||||
if not items:
|
||||
raise SystemExit('Usage: kitty +kitten transfer file_or_directory ...')
|
||||
|
||||
@ -18,7 +18,7 @@ from kitty.cli_stub import TransferCLIOptions
|
||||
from kitty.fast_data_types import FILE_TRANSFER_CODE, wcswidth
|
||||
from kitty.file_transmission import (
|
||||
Action, Compression, FileTransmissionCommand, FileType, NameReprEnum,
|
||||
TransmissionType, encode_password
|
||||
TransmissionType, encode_bypass
|
||||
)
|
||||
from kitty.typing import KeyEventType
|
||||
from kitty.utils import sanitize_control_codes
|
||||
@ -257,9 +257,9 @@ class ProgressTracker:
|
||||
|
||||
class SendManager:
|
||||
|
||||
def __init__(self, request_id: str, files: Tuple[File, ...], pw: Optional[str] = None, file_done: Callable[[File], None] = lambda f: None):
|
||||
def __init__(self, request_id: str, files: Tuple[File, ...], bypass: Optional[str] = None, file_done: Callable[[File], None] = lambda f: None):
|
||||
self.files = files
|
||||
self.password = encode_password(request_id, pw) if pw else ''
|
||||
self.bypass = encode_bypass(request_id, bypass) if bypass else ''
|
||||
self.fid_map = {f.file_id: f for f in self.files}
|
||||
self.request_id = request_id
|
||||
self.state = SendState.waiting_for_permission
|
||||
@ -306,7 +306,7 @@ class SendManager:
|
||||
self.all_started = not found_not_started
|
||||
|
||||
def start_transfer(self) -> str:
|
||||
return FileTransmissionCommand(action=Action.send, password=self.password).serialize()
|
||||
return FileTransmissionCommand(action=Action.send, bypass=self.bypass).serialize()
|
||||
|
||||
def next_chunks(self) -> Iterator[str]:
|
||||
if self.active_file is None:
|
||||
@ -368,7 +368,7 @@ class Send(Handler):
|
||||
|
||||
def __init__(self, cli_opts: TransferCLIOptions, files: Tuple[File, ...]):
|
||||
Handler.__init__(self)
|
||||
self.manager = SendManager(random_id(), files, cli_opts.permissions_password, self.on_file_done)
|
||||
self.manager = SendManager(random_id(), files, cli_opts.permissions_bypass, self.on_file_done)
|
||||
self.cli_opts = cli_opts
|
||||
self.transmit_started = False
|
||||
self.file_metadata_sent = False
|
||||
@ -504,8 +504,8 @@ class Send(Handler):
|
||||
|
||||
def initialize(self) -> None:
|
||||
self.send_payload(self.manager.start_transfer())
|
||||
if self.cli_opts.permissions_password:
|
||||
# dont wait for permission, not needed with a password and
|
||||
if self.cli_opts.permissions_bypass:
|
||||
# dont wait for permission, not needed with a bypass and
|
||||
# avoids a roundtrip
|
||||
self.send_file_metadata()
|
||||
self.cmd.set_cursor_visible(False)
|
||||
|
||||
@ -26,7 +26,7 @@ EXPIRE_TIME = 10 # minutes
|
||||
MAX_ACTIVE_RECEIVES = 10
|
||||
|
||||
|
||||
def encode_password(request_id: str, pw: str) -> str:
|
||||
def encode_bypass(request_id: str, pw: str) -> str:
|
||||
import hashlib
|
||||
q = request_id + ';' + pw
|
||||
return 'sha256:' + hashlib.sha256(q.encode('utf-8', 'replace')).hexdigest()
|
||||
@ -114,7 +114,7 @@ class FileTransmissionCommand:
|
||||
ttype: TransmissionType = TransmissionType.simple
|
||||
id: str = ''
|
||||
file_id: str = ''
|
||||
password: str = field(default='', metadata={'base64': True})
|
||||
bypass: str = field(default='', metadata={'base64': True})
|
||||
quiet: int = 0
|
||||
mtime: int = -1
|
||||
permissions: int = -1
|
||||
@ -341,12 +341,12 @@ class ActiveReceive:
|
||||
files: Dict[str, DestFile]
|
||||
accepted: bool = False
|
||||
|
||||
def __init__(self, request_id: str, quiet: int, password: str) -> None:
|
||||
def __init__(self, request_id: str, quiet: int, bypass: str) -> None:
|
||||
self.id = request_id
|
||||
self.password_ok: Optional[bool] = None
|
||||
pw = get_options().file_transfer_password
|
||||
if pw and password:
|
||||
self.password_ok = encode_password(request_id, pw) == password
|
||||
self.bypass_ok: Optional[bool] = None
|
||||
byp = get_options().file_transfer_confirmation_bypass
|
||||
if byp and bypass:
|
||||
self.bypass_ok = encode_bypass(request_id, byp) == byp
|
||||
self.files = {}
|
||||
self.last_activity_at = monotonic()
|
||||
self.send_acknowledgements = quiet < 1
|
||||
@ -477,7 +477,7 @@ class FileTransmission:
|
||||
if len(self.active_receives) >= MAX_ACTIVE_RECEIVES:
|
||||
log_error('New File transmission send with too many active receives, ignoring')
|
||||
return
|
||||
ar = self.active_receives[cmd.id] = ActiveReceive(cmd.id, cmd.quiet, cmd.password)
|
||||
ar = self.active_receives[cmd.id] = ActiveReceive(cmd.id, cmd.quiet, cmd.bypass)
|
||||
self.start_receive(ar.id)
|
||||
return
|
||||
|
||||
@ -568,8 +568,8 @@ class FileTransmission:
|
||||
|
||||
def start_receive(self, ar_id: str) -> None:
|
||||
ar = self.active_receives[ar_id]
|
||||
if ar.password_ok is not None:
|
||||
self.handle_send_confirmation(ar_id, {'response': 'y' if ar.password_ok else 'n'})
|
||||
if ar.bypass_ok is not None:
|
||||
self.handle_send_confirmation(ar_id, {'response': 'y' if ar.bypass_ok else 'n'})
|
||||
return
|
||||
boss = get_boss()
|
||||
window = boss.window_id_map.get(self.window_id)
|
||||
|
||||
@ -2566,11 +2566,12 @@ stored for writing to the system clipboard. See also :opt:`clipboard_control`.
|
||||
A value of zero means no size limit is applied.
|
||||
''')
|
||||
|
||||
opt('file_transfer_password', '', long_text='''
|
||||
A password, that can be supplied to the file transfer kitten to skip
|
||||
the transfer confirmation dialog. This should only be used
|
||||
when initiating transfers from trusted computers, over trusted networks
|
||||
or encrypted transports.
|
||||
opt('file_transfer_confirmation_bypass', '', long_text='''
|
||||
A password, that can be supplied to the file transfer kitten to skip the
|
||||
transfer confirmation prompt. This should only be used when initiating
|
||||
transfers from trusted computers, over trusted networks or encrypted
|
||||
transports, as it allows programs running on the remote machine to read/write
|
||||
to the local filesystem, without permission.
|
||||
''')
|
||||
|
||||
opt('allow_hyperlinks', 'yes',
|
||||
|
||||
4
kitty/options/parse.py
generated
4
kitty/options/parse.py
generated
@ -942,8 +942,8 @@ class Parser:
|
||||
for k, v in env(val, ans["env"]):
|
||||
ans["env"][k] = v
|
||||
|
||||
def file_transfer_password(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['file_transfer_password'] = str(val)
|
||||
def file_transfer_confirmation_bypass(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['file_transfer_confirmation_bypass'] = str(val)
|
||||
|
||||
def focus_follows_mouse(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['focus_follows_mouse'] = to_bool(val)
|
||||
|
||||
4
kitty/options/types.py
generated
4
kitty/options/types.py
generated
@ -345,7 +345,7 @@ option_names = ( # {{{
|
||||
'enable_audio_bell',
|
||||
'enabled_layouts',
|
||||
'env',
|
||||
'file_transfer_password',
|
||||
'file_transfer_confirmation_bypass',
|
||||
'focus_follows_mouse',
|
||||
'font_family',
|
||||
'font_features',
|
||||
@ -485,7 +485,7 @@ class Options:
|
||||
editor: str = '.'
|
||||
enable_audio_bell: bool = True
|
||||
enabled_layouts: typing.List[str] = ['fat', 'grid', 'horizontal', 'splits', 'stack', 'tall', 'vertical']
|
||||
file_transfer_password: str = ''
|
||||
file_transfer_confirmation_bypass: str = ''
|
||||
focus_follows_mouse: bool = False
|
||||
font_family: str = 'monospace'
|
||||
font_size: float = 11.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user