From 0684c13898fce0f6896c34354a23297720a81ec2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 9 Apr 2026 07:47:57 +0530 Subject: [PATCH] Code to get and use machine id during DnD --- docs/dnd-protocol.rst | 4 ++-- kitty/dnd.c | 22 ++++++++++++++++++++++ kitty/machine_id.py | 24 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 kitty/machine_id.py diff --git a/docs/dnd-protocol.rst b/docs/dnd-protocol.rst index 7097021f6..60bdcfc5f 100644 --- a/docs/dnd-protocol.rst +++ b/docs/dnd-protocol.rst @@ -133,8 +133,8 @@ terminal emulator must then inform the OS that the drop is completed. Dropping from remote machines ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In order to support dropping of files from remote machines or to remote -machines, clients can first request the :rfc:`text/uri-list <2483>` MIME +In order to support dropping of files from remote machines, +clients can first request the :rfc:`text/uri-list <2483>` MIME type to get a list of dropped URIs. For every URI in the list, they can send the terminal emulator a data request of the form:: diff --git a/kitty/dnd.c b/kitty/dnd.c index 2d4caa472..53d844af1 100644 --- a/kitty/dnd.c +++ b/kitty/dnd.c @@ -25,6 +25,28 @@ static const size_t PRESENT_DATA_CAP = 64 * 1024 * 1024; // It receives (window_id: int, data: bytes) and its return value is ignored. static PyObject *g_dnd_test_write_func = NULL; +static const char* +machine_id(void) { + static bool done = false; + static char ans[512] = {0}; + if (!done) { + done = true; + RAII_PyObject(mname, PyUnicode_DecodeFSDefault("kitty.machine_id")); + if (mname) { + RAII_PyObject(module, PyImport_Import(mname)); + if (module) { + RAII_PyObject(func, PyObject_GetAttrString(module, "machine_id")); + if (func) { + RAII_PyObject(ret, PyObject_CallFunction(func, "s", "tty-dnd-protocol-machine-id")); + if (ret) snprintf(ans, sizeof(ans), "%s", PyUnicode_AsUTF8(ret)); + } + } + } + if (PyErr_Occurred()) PyErr_Print(); + } + return ans; +} + void dnd_set_test_write_func(PyObject *func) { Py_XDECREF(g_dnd_test_write_func); diff --git a/kitty/machine_id.py b/kitty/machine_id.py new file mode 100644 index 000000000..881420cfc --- /dev/null +++ b/kitty/machine_id.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# License: GPLv3 Copyright: 2026, Kovid Goyal + +import hashlib +import hmac +from contextlib import suppress +from functools import lru_cache + +from kitty.constants import is_macos + + +@lru_cache(maxsize=8) +def machine_id(salt: str = '') -> str: + mid = b'' + if is_macos: + from kitty.fast_data_types import cocoa_get_machine_id + mid = cocoa_get_machine_id().rstrip().encode() + else: + with suppress(OSError), open('/etc/machine-id', 'rb') as f: + mid = f.read().rstrip() + if not salt: + return mid.decode() + hmac_obj = hmac.new(salt.encode(), mid, hashlib.sha256) + return hmac_obj.hexdigest()