mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-22 16:28:19 +02:00
Cleanup previous PR
This commit is contained in:
@@ -3716,28 +3716,3 @@ class Boss:
|
|||||||
def copy_or_noop(self) -> None:
|
def copy_or_noop(self) -> None:
|
||||||
if w := self.active_window:
|
if w := self.active_window:
|
||||||
w.copy_or_noop()
|
w.copy_or_noop()
|
||||||
|
|
||||||
def nth_decoded_file_url(self, n: int, text_uri_list: bytes) -> tuple[bool, str]:
|
|
||||||
' Return the abspath of the nth url in text_uri_list if it is a valid file:// URL. Appropriate error code returned otherwise '
|
|
||||||
from urllib.parse import unquote, urlparse
|
|
||||||
for line in text_uri_list.decode().splitlines():
|
|
||||||
if line.startswith('#'):
|
|
||||||
continue
|
|
||||||
if n <= 0:
|
|
||||||
break
|
|
||||||
n -= 1
|
|
||||||
else:
|
|
||||||
return False, 'ENOENT'
|
|
||||||
try:
|
|
||||||
purl = urlparse(line.strip())
|
|
||||||
if purl.scheme != 'file':
|
|
||||||
return False, 'EUNKNOWN'
|
|
||||||
if not purl.path:
|
|
||||||
return False, 'EINVAL'
|
|
||||||
path = unquote(purl.path)
|
|
||||||
if not os.path.isabs(path):
|
|
||||||
return False, 'EINVAL'
|
|
||||||
path = os.path.abspath(os.path.realpath(path))
|
|
||||||
return True, path
|
|
||||||
except Exception:
|
|
||||||
return False, 'EINVAL'
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "dnd.h"
|
#include "dnd.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "control-codes.h"
|
#include "control-codes.h"
|
||||||
|
#include "safe-wrappers.h"
|
||||||
#include "iqsort.h"
|
#include "iqsort.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -516,7 +517,7 @@ drop_send_file_data(Window *w, const char *path) {
|
|||||||
}
|
}
|
||||||
if (!S_ISREG(st.st_mode)) { drop_send_error(w, EINVAL); return; }
|
if (!S_ISREG(st.st_mode)) { drop_send_error(w, EINVAL); return; }
|
||||||
|
|
||||||
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
int fd = safe_open(path, O_RDONLY | O_CLOEXEC, 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;
|
case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;
|
||||||
@@ -530,20 +531,20 @@ drop_send_file_data(Window *w, const char *path) {
|
|||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
if (data_sz) {
|
if (data_sz) {
|
||||||
data = malloc(data_sz);
|
data = malloc(data_sz);
|
||||||
if (!data) { close(fd); drop_send_error(w, EIO); return; }
|
if (!data) { safe_close(fd, __FILE__, __LINE__); drop_send_error(w, EIO); return; }
|
||||||
size_t done = 0;
|
size_t done = 0;
|
||||||
while (done < data_sz) {
|
while (done < data_sz) {
|
||||||
ssize_t n = read(fd, data + done, data_sz - done);
|
ssize_t n = read(fd, data + done, data_sz - done);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
free(data); close(fd); drop_send_error(w, EIO); return;
|
free(data); safe_close(fd, __FILE__, __LINE__); drop_send_error(w, EIO); return;
|
||||||
}
|
}
|
||||||
if (n == 0) break;
|
if (n == 0) break;
|
||||||
done += (size_t)n;
|
done += (size_t)n;
|
||||||
}
|
}
|
||||||
data_sz = done;
|
data_sz = done;
|
||||||
}
|
}
|
||||||
close(fd);
|
safe_close(fd, __FILE__, __LINE__);
|
||||||
|
|
||||||
char hdr[128];
|
char hdr[128];
|
||||||
int hdr_sz = snprintf(hdr, sizeof(hdr), "\x1b]%d;t=r", DND_CODE);
|
int hdr_sz = snprintf(hdr, sizeof(hdr), "\x1b]%d;t=r", DND_CODE);
|
||||||
|
|||||||
@@ -514,7 +514,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_uri_file_transfer_basic(self) -> None:
|
def test_uri_file_transfer_basic(self) -> None:
|
||||||
"""t=s request sends the content of a regular file as t=r chunks."""
|
"""t=s request sends the content of a regular file as t=r chunks."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
content = b'Hello, remote DnD world!\n' * 100
|
content = b'Hello, remote DnD world!\n' * 100
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
@@ -537,7 +538,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_uri_file_transfer_integrity(self) -> None:
|
def test_uri_file_transfer_integrity(self) -> None:
|
||||||
"""File content is transferred byte-for-byte (binary integrity)."""
|
"""File content is transferred byte-for-byte (binary integrity)."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
# Use binary content with all byte values to check integrity
|
# Use binary content with all byte values to check integrity
|
||||||
content = bytes(range(256)) * 512 # 128 KiB
|
content = bytes(range(256)) * 512 # 128 KiB
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
@@ -571,7 +573,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_uri_file_transfer_out_of_bounds(self) -> None:
|
def test_uri_file_transfer_out_of_bounds(self) -> None:
|
||||||
"""t=s with an index beyond the URI list returns ENOENT."""
|
"""t=s with an index beyond the URI list returns ENOENT."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
fpath = f.name
|
fpath = f.name
|
||||||
try:
|
try:
|
||||||
@@ -588,7 +591,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_uri_request_without_uri_list_returns_einval(self) -> None:
|
def test_uri_request_without_uri_list_returns_einval(self) -> None:
|
||||||
"""t=s without prior text/uri-list request returns EINVAL."""
|
"""t=s without prior text/uri-list request returns EINVAL."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
fpath = f.name
|
fpath = f.name
|
||||||
try:
|
try:
|
||||||
@@ -619,7 +623,9 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_uri_directory_transfer_tree(self) -> None:
|
def test_uri_directory_transfer_tree(self) -> None:
|
||||||
"""Full directory tree transfer: listing, sub-dirs, file integrity."""
|
"""Full directory tree transfer: listing, sub-dirs, file integrity."""
|
||||||
import os, tempfile, hashlib
|
import hashlib
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
# Build a tree: root/ a.txt b/ b/c.txt b/d/ b/d/e.txt
|
# Build a tree: root/ a.txt b/ b/c.txt b/d/ b/d/e.txt
|
||||||
with tempfile.TemporaryDirectory() as root:
|
with tempfile.TemporaryDirectory() as root:
|
||||||
@@ -739,7 +745,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_dir_handle_close_and_reuse(self) -> None:
|
def test_dir_handle_close_and_reuse(self) -> None:
|
||||||
"""Closing a directory handle invalidates it; subsequent requests return EINVAL."""
|
"""Closing a directory handle invalidates it; subsequent requests return EINVAL."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
with tempfile.TemporaryDirectory() as root:
|
with tempfile.TemporaryDirectory() as root:
|
||||||
open(os.path.join(root, 'f.txt'), 'w').close()
|
open(os.path.join(root, 'f.txt'), 'w').close()
|
||||||
uri_list = f'file://{root}\r\n'.encode()
|
uri_list = f'file://{root}\r\n'.encode()
|
||||||
@@ -765,7 +772,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_dir_entry_out_of_bounds_returns_enoent(self) -> None:
|
def test_dir_entry_out_of_bounds_returns_enoent(self) -> None:
|
||||||
"""Reading a directory entry with an out-of-range index returns ENOENT."""
|
"""Reading a directory entry with an out-of-range index returns ENOENT."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
with tempfile.TemporaryDirectory() as root:
|
with tempfile.TemporaryDirectory() as root:
|
||||||
open(os.path.join(root, 'only.txt'), 'w').close()
|
open(os.path.join(root, 'only.txt'), 'w').close()
|
||||||
uri_list = f'file://{root}\r\n'.encode()
|
uri_list = f'file://{root}\r\n'.encode()
|
||||||
@@ -786,7 +794,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_dir_unique_identifier_prevents_loops(self) -> None:
|
def test_dir_unique_identifier_prevents_loops(self) -> None:
|
||||||
"""Each directory listing starts with a unique id (dev:inode format)."""
|
"""Each directory listing starts with a unique id (dev:inode format)."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
with tempfile.TemporaryDirectory() as root:
|
with tempfile.TemporaryDirectory() as root:
|
||||||
sub = os.path.join(root, 'sub')
|
sub = os.path.join(root, 'sub')
|
||||||
os.mkdir(sub)
|
os.mkdir(sub)
|
||||||
@@ -822,7 +831,8 @@ class TestDnDProtocol(BaseTest):
|
|||||||
|
|
||||||
def test_window_close_during_transfer_no_leak(self) -> None:
|
def test_window_close_during_transfer_no_leak(self) -> None:
|
||||||
"""Closing the window while dir handles are open frees all resources (no crash)."""
|
"""Closing the window while dir handles are open frees all resources (no crash)."""
|
||||||
import os, tempfile
|
import os
|
||||||
|
import tempfile
|
||||||
with tempfile.TemporaryDirectory() as root:
|
with tempfile.TemporaryDirectory() as root:
|
||||||
open(os.path.join(root, 'f.txt'), 'w').close()
|
open(os.path.join(root, 'f.txt'), 'w').close()
|
||||||
uri_list = f'file://{root}\r\n'.encode()
|
uri_list = f'file://{root}\r\n'.encode()
|
||||||
|
|||||||
Reference in New Issue
Block a user