mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-06 09:15:57 +02:00
Have top level symlink behavior match for local and remote drops
This commit is contained in:
@@ -171,15 +171,12 @@ MIME type is not present in the drop, the terminal must reply with
|
||||
If the client requests an entry that is not a supported URI type the
|
||||
terminal must reply with ``EUNKNOWN``.
|
||||
|
||||
Terminals must ONLY send data for regular files or directories. Symbolic links must be
|
||||
resolved and the corresponding file or directory read. Only if the symbolic
|
||||
link cannot be resolved must it be transmitted as a symbolic link (in which
|
||||
case ``X=1`` and the payload is the base64 encoded target of the symlink. See
|
||||
below for more details about sending symlinks.
|
||||
Terminals must ONLY send data for regular files, symbolic links and directories.
|
||||
See below for more details about sending symlinks.
|
||||
|
||||
If the terminal does not have permission to read the file it must reply with
|
||||
``EPERM``. Terminals must respond with ``EINVAL`` if the file is not a regular
|
||||
file after resolving symlinks and ``ENOENT`` if the file does not exist. If an
|
||||
file or symlink or directory and ``ENOENT`` if the file does not exist. If an
|
||||
I/O error occurs the terminal must send ``EIO``.
|
||||
|
||||
For security reasons, terminals must reply with ``EPERM`` if the drag
|
||||
|
||||
29
kitty/dnd.c
29
kitty/dnd.c
@@ -947,12 +947,14 @@ drop_send_dir_listing(Window *w, const char *path) {
|
||||
}
|
||||
|
||||
static void
|
||||
drop_send_symlink(Window *w, const char *target, size_t sz) {
|
||||
drop_send_symlink(Window *w, const char *path) {
|
||||
char target[PATH_MAX]; ssize_t tgtsz;
|
||||
if ((tgtsz = readlink(path, target, sizeof(target)-1)) < 0) { drop_send_error(w, EIO); return; }
|
||||
char hdr[128];
|
||||
int hdr_sz = snprintf(hdr, sizeof(hdr), "\x1b]%d;t=r", DND_CODE);
|
||||
hdr_sz += drop_append_request_keys(w, hdr + hdr_sz, sizeof(hdr) - hdr_sz);
|
||||
hdr_sz += snprintf(hdr + hdr_sz, sizeof(hdr) - hdr_sz, ":X=1");
|
||||
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, target, sz, true);
|
||||
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, target, tgtsz, true);
|
||||
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, NULL, 0, true);
|
||||
}
|
||||
|
||||
@@ -985,31 +987,24 @@ do_drop_request_uri_data(Window *w, int32_t mime_idx, int32_t file_idx) {
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(path, &st) < 0) {
|
||||
if (lstat(path, &st) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;
|
||||
case EACCES: case EPERM: drop_send_error(w, EPERM); break;
|
||||
default: drop_send_error(w, EIO); break;
|
||||
}
|
||||
return true;
|
||||
if (lstat(path, &st) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;
|
||||
case EACCES: case EPERM: drop_send_error(w, EPERM); break;
|
||||
default: drop_send_error(w, EIO); break;
|
||||
}
|
||||
// We have a broken symlink
|
||||
char target[PATH_MAX]; ssize_t tgtsz;
|
||||
if ((tgtsz = readlink(path, target, sizeof(target)-1)) < 0) drop_send_error(w, ENOENT);
|
||||
drop_send_symlink(w, target, tgtsz);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sync;
|
||||
bool sync = true;
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
drop_send_dir_listing(w, path);
|
||||
sync = true;
|
||||
} else if (S_ISREG(st.st_mode)) {
|
||||
sync = drop_send_file_data(w, path);
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
drop_send_symlink(w, path);
|
||||
} else {
|
||||
drop_send_error(w, EINVAL);
|
||||
sync = true;
|
||||
}
|
||||
return sync;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class Capture(WriteCapture):
|
||||
self.pty.write_to_child(data)
|
||||
|
||||
|
||||
def create_fs(base, include_toplevel_working_symlink=False):
|
||||
def create_fs(base, include_toplevel_working_symlink=True):
|
||||
join = partial(os.path.join, base)
|
||||
def w(sz, *path):
|
||||
if sz == 0:
|
||||
@@ -232,7 +232,7 @@ class TestDnDKitten(BaseTest):
|
||||
self.assertEqual('text/uri-list\x00image/png', self.probe_state('drop_mimes').rstrip('\x00'))
|
||||
self.wait_for_state('drop_data_requests', ((1,0,0), (4,0,0)))
|
||||
self.assertEqual('text/uri-list', self.probe_state('drop_getting_data_for_mime'))
|
||||
create_fs(self.src_data_dir, include_toplevel_working_symlink=not remote_client)
|
||||
create_fs(self.src_data_dir)
|
||||
uri_list, path_list = [], []
|
||||
for x in sorted(os.listdir(self.src_data_dir)):
|
||||
uri_list.append(as_file_url(self.src_data_dir, x))
|
||||
|
||||
Reference in New Issue
Block a user