osc: 52: treat OSC-52 replies as paste data (after all, they are)

This fixes an issue where other data (such as replies to other
requests) being interleaved with the OSC-52 reply.

The patch piggy backs on the already existing mechanism for handling
regular pastes, where other data is queued up until the paste is done.

There's one corner case that won't work; if the user *just* did a
normal paste (i.e. at virtually the same time the application
requested OSC-52 data), the OSC-52 request will return an empty reply.

Likewise, if there are multiple OSC-52 requests at the same time, only
the first will return data.

Closes #1734
This commit is contained in:
Daniel Eklöf 2024-06-08 08:39:47 +02:00
parent 4bb68282be
commit f3d848da01
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 34 additions and 8 deletions

View file

@ -91,10 +91,13 @@
* Unicode-mode in one foot client affecting other clients, in foot
server mode ([#1717][1717]).
* IME interfering in URL-mode ([#1718][1718]).
* OSC-52 reply interleaved with other data sent to the client
([#1734][1734]).
[1694]: https://codeberg.org/dnkl/foot/issues/1694
[1717]: https://codeberg.org/dnkl/foot/issues/1717
[1718]: https://codeberg.org/dnkl/foot/issues/1718
[1734]: https://codeberg.org/dnkl/foot/issues/1734
### Security

39
osc.c
View file

@ -5,6 +5,8 @@
#include <ctype.h>
#include <errno.h>
#include <sys/epoll.h>
#define LOG_MODULE "osc"
#define LOG_ENABLE_DBG 0
#include "log.h"
@ -124,7 +126,7 @@ from_clipboard_cb(char *text, size_t size, void *user)
xassert(chunk != NULL);
xassert(strlen(chunk) == 4);
term_to_slave(term, chunk, 4);
term_paste_data_to_slave(term, chunk, 4);
free(chunk);
ctx->idx = 0;
@ -144,7 +146,7 @@ from_clipboard_cb(char *text, size_t size, void *user)
char *chunk = base64_encode((const uint8_t *)t, left / 3 * 3);
xassert(chunk != NULL);
xassert(strlen(chunk) % 4 == 0);
term_to_slave(term, chunk, strlen(chunk));
term_paste_data_to_slave(term, chunk, strlen(chunk));
free(chunk);
}
@ -157,13 +159,19 @@ from_clipboard_done(void *user)
if (ctx->idx > 0) {
char res[4];
base64_encode_final(ctx->buf, ctx->idx, res);
term_to_slave(term, res, 4);
term_paste_data_to_slave(term, res, 4);
}
if (term->vt.osc.bel)
term_to_slave(term, "\a", 1);
term_paste_data_to_slave(term, "\a", 1);
else
term_to_slave(term, "\033\\", 2);
term_paste_data_to_slave(term, "\033\\", 2);
term->is_sending_paste_data = false;
/* Make sure we send any queued up non-paste data */
if (tll_length(term->ptmx_buffers) > 0)
fdm_event_add(term->fdm, term->ptmx, EPOLLOUT);
free(ctx);
}
@ -214,9 +222,24 @@ osc_from_clipboard(struct terminal *term, const char *source)
if (!from_clipboard && !from_primary)
return;
term_to_slave(term, "\033]52;", 5);
term_to_slave(term, &src, 1);
term_to_slave(term, ";", 1);
if (term->is_sending_paste_data) {
/* FIXME: we should wait for the paste to end, then continue
with the OSC-52 reply */
term_to_slave(term, "\033]52;", 5);
term_to_slave(term, &src, 1);
term_to_slave(term, ";", 1);
if (term->vt.osc.bel)
term_to_slave(term, "\a", 1);
else
term_to_slave(term, "\033\\", 2);
return;
}
term->is_sending_paste_data = true;
term_paste_data_to_slave(term, "\033]52;", 5);
term_paste_data_to_slave(term, &src, 1);
term_paste_data_to_slave(term, ";", 1);
struct clip_context *ctx = xmalloc(sizeof(*ctx));
*ctx = (struct clip_context) {.seat = seat, .term = term};