libghostty-vt 0.0.0
Loading...
Searching...
No Matches
Paste

Paste into a terminal, and check paste data for unsafe content. More...

Detailed Description

Paste into a terminal, and check paste data for unsafe content.

Paste into a terminal with ghostty_terminal_paste(), or validate and encode paste data without one.

What a paste writes depends on the terminal's modes, and ghostty_terminal_paste() reads them itself. If you have a terminal, that's the function you want.

Example

// What the clipboard holds. A real embedder would keep a handle to the
// pasteboard or its items here; the data is only produced on demand.
typedef struct {
const char* text;
} clipboard_t;
// Produces the data of one representation when the terminal needs it.
// Only the text is ever read: the image is listed on a paste event
// but never requested, so a large image costs nothing to paste.
// Nothing written to the writer is retained, so the data can be
// streamed from anywhere in pieces of any size.
static bool read_clipboard(void* userdata, GhosttyString mime, GhosttyWriter writer) {
clipboard_t* clipboard = userdata;
if (mime.len == strlen("text/plain") &&
memcmp(mime.ptr, "text/plain", mime.len) == 0) {
// Stream the text in small pieces just to show that it works.
const uint8_t* data = (const uint8_t*)clipboard->text;
size_t len = strlen(clipboard->text);
for (size_t offset = 0; offset < len; offset += 4) {
size_t n = len - offset < 4 ? len - offset : 4;
if (!writer.write(writer.userdata, data + offset, n)) return false;
}
return true;
}
printf(" image read requested, which never happens\n");
return false;
}
// Paste whatever the clipboard holds. The terminal applies its own
// state: bracketed paste framing (mode 2004) or a Kitty paste event
// (mode 5522) instead of the text.
static void paste_clipboard(GhosttyTerminal terminal, const char* text) {
clipboard_t clipboard = {.text = text};
GhosttyString mimes[] = {
// The first text representation is what a text paste writes.
GS("text/plain"),
// Listed on a paste event, never read.
GS("image/png"),
};
GhosttyPaste paste = {
.size = sizeof(paste),
.mimes = mimes,
.mimes_len = sizeof(mimes) / sizeof(mimes[0]),
.reader = {.read = read_clipboard, .userdata = &clipboard},
.allow_unsafe = false,
};
bool pasted = false;
GhosttyResult result = ghostty_terminal_paste(terminal, &paste, &pasted);
if (result == GHOSTTY_REJECTED) {
// The text could inject commands (e.g. a newline outside of a
// bracketed paste). Nothing was written; ask, then retry.
if (!confirm_with_user()) return;
paste.allow_unsafe = true;
result = ghostty_terminal_paste(terminal, &paste, &pasted);
}
if (result != GHOSTTY_SUCCESS) {
fprintf(stderr, "paste failed: %d\n", (int)result);
return;
}
// Whether the pty got the text or a paste event depends on the
// terminal's modes; either way it went through write_pty above, in
// chunks as the text was read.
printf(" %s\n", pasted ? "written" : "nothing to paste");
}

Full program: c-vt-paste/src/main.c

The Input guide covers what a paste writes and how unsafe pastes are refused.

Enumerations

enum  GhosttyPasteSource { GHOSTTY_PASTE_SOURCE_CLIPBOARD = 0 , GHOSTTY_PASTE_SOURCE_TEXT = 1 , GHOSTTY_PASTE_SOURCE_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE }

Functions

GHOSTTY_API GhosttyResult ghostty_terminal_paste (GhosttyTerminal terminal, const GhosttyPaste *paste, bool *out_pasted)
GHOSTTY_API bool ghostty_paste_is_safe (const char *data, size_t len)
GHOSTTY_API GhosttyResult ghostty_paste_encode (char *data, size_t data_len, bool bracketed, uint8_t *buf, size_t buf_len, size_t *out_written)

Data Structures

struct  GhosttyPaste

Enumeration Type Documentation

◆ GhosttyPasteSource

Why a paste happened.

Enumerator
GHOSTTY_PASTE_SOURCE_CLIPBOARD 

The user pasted from a clipboard: keybind, menu, middle click.

GHOSTTY_PASTE_SOURCE_TEXT 

Text inserted some other way: IME commit, drag and drop, scripted input. Always written as text, never as a paste event, matching kitty. This is not a way to opt out of paste events; an embedder that doesn't want them doesn't install a clipboard_read callback.

Definition at line 44 of file paste.h.

Function Documentation

◆ ghostty_paste_encode()

GHOSTTY_API GhosttyResult ghostty_paste_encode ( char * data,
size_t data_len,
bool bracketed,
uint8_t * buf,
size_t buf_len,
size_t * out_written )

Encode paste data for writing to the terminal pty.

This function prepares paste data for terminal input by:

  • Stripping unsafe control bytes (NUL, ESC, DEL, etc.) by replacing them with spaces
  • Wrapping the data in bracketed paste sequences if bracketed is true
  • Replacing newlines with carriage returns if bracketed is false

The input data buffer is modified in place during encoding. The encoded result (potentially with bracketed paste prefix/suffix) is written to the output buffer.

If buf is too small, this returns GHOSTTY_OUT_OF_SPACE, sets out_written to the size needed, and leaves buf unchanged. To get the size first, pass NULL for buf and 0 for buf_len. An empty result needs no space, so empty input with bracketed false returns GHOSTTY_SUCCESS with out_written set to 0.

The function modifies data even when it returns GHOSTTY_OUT_OF_SPACE. Encoding the modified data again gives the same result, so you can retry with the same data and a larger buffer:

size_t needed = 0;
GhosttyResult result = ghostty_paste_encode(data, data_len, bracketed,
NULL, 0, &needed);
if (result == GHOSTTY_OUT_OF_SPACE) {
uint8_t *buf = malloc(needed);
size_t written = 0;
result = ghostty_paste_encode(data, data_len, bracketed, buf, needed,
&written);
if (result == GHOSTTY_SUCCESS) write(pty_fd, buf, written);
free(buf);
}
GhosttyResult
Definition types.h:143
@ GHOSTTY_OUT_OF_SPACE
Definition types.h:158
@ GHOSTTY_SUCCESS
Definition types.h:145
GHOSTTY_API GhosttyResult ghostty_paste_encode(char *data, size_t data_len, bool bracketed, uint8_t *buf, size_t buf_len, size_t *out_written)

This is the encoder ghostty_terminal_paste() uses for a text paste; use it directly when there is no terminal to paste into.

Parameters
dataThe paste data to encode (modified in place, may be NULL)
data_lenThe length of the input data in bytes
bracketedWhether bracketed paste mode is active
bufBuffer to write the encoded result into. May be NULL if buf_len is 0.
buf_lenSize of buf in bytes
[out]out_writtenThe number of bytes written, or the size needed if the result is GHOSTTY_OUT_OF_SPACE
Returns
GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer is too small
Examples
c-vt-paste/src/main.c.

◆ ghostty_paste_is_safe()

GHOSTTY_API bool ghostty_paste_is_safe ( const char * data,
size_t len )

Check if paste data is safe to paste into the terminal.

Data is considered unsafe if it contains:

  • Line terminators (\n or \r) which can inject commands. A carriage return is what the Enter key sends, so it is as dangerous as a newline on an unbracketed paste.
  • The bracketed paste end sequence (\x1b[201~) which can be used to exit bracketed paste mode and inject commands

This check is conservative and considers data unsafe regardless of current terminal state. ghostty_terminal_paste() applies the terminal-state-aware rule itself (line terminators are safe inside a bracketed paste); use this to apply the stricter rule on top.

Parameters
dataThe paste data to check (must not be NULL)
lenThe length of the data in bytes
Returns
true if the data is safe to paste, false otherwise
Examples
c-vt-paste/src/main.c.

◆ ghostty_terminal_paste()

GHOSTTY_API GhosttyResult ghostty_terminal_paste ( GhosttyTerminal terminal,
const GhosttyPaste * paste,
bool * out_pasted )

Paste into the terminal according to its current state: a Kitty clipboard protocol paste event if mode 5522 is enabled and a clipboard_read callback is installed, otherwise the text framed per mode 2004. See Paste for the full behavior. Output streams through the write_pty callback in chunks. The viewport is not scrolled; that is up to you, as for key input.

A paste event records a session grant for its one-time password only once the event is written; a failed call never leaves a grant for an event that was never sent.

Parameters
terminalThe terminal handle
pasteThe paste request, borrowed for the duration of the call
[out]out_pastedOn success, whether anything was written to the pty (the encoded text or a paste event). False means there was nothing to paste: no non-empty text representation. May be NULL.
Returns
GHOSTTY_SUCCESS on success (see out_pasted); GHOSTTY_REJECTED if the text could inject commands and GhosttyPaste::allow_unsafe is false (nothing was written); GHOSTTY_INVALID_VALUE for a NULL terminal or paste, MIME types without a reader, or when no write_pty callback is installed; GHOSTTY_OUT_OF_MEMORY; GHOSTTY_IO_ERROR if the reader failed or there is no secure entropy source to mint a paste event password (wasm32-freestanding without GHOSTTY_SYS_OPT_RANDOM_SECURE set). Errors write nothing.
Examples
c-vt-paste/src/main.c.