mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-10 04:27:45 -05:00
Merge branch 'osc52-clear-selection-on-invalid-payload' into master
This commit is contained in:
commit
fc510d423b
4 changed files with 109 additions and 31 deletions
|
|
@ -112,6 +112,8 @@
|
|||
* Handling of multi-column composed characters while reflowing.
|
||||
* Escape sequences sent for key combinations with `Return`, that did
|
||||
**not** include `Alt`.
|
||||
* Clipboard (or primary selection) is now cleared when receiving an
|
||||
OSC-52 command with an invalid base64 encoded payload.
|
||||
|
||||
|
||||
### Security
|
||||
|
|
|
|||
79
osc.c
79
osc.c
|
|
@ -23,17 +23,6 @@ static void
|
|||
osc_to_clipboard(struct terminal *term, const char *target,
|
||||
const char *base64_data)
|
||||
{
|
||||
char *decoded = base64_decode(base64_data);
|
||||
if (decoded == NULL) {
|
||||
if (errno == EINVAL)
|
||||
LOG_WARN("OSC: invalid clipboard data: %s", base64_data);
|
||||
else
|
||||
LOG_ERRNO("base64_decode() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("decoded: %s", decoded);
|
||||
|
||||
bool to_clipboard = false;
|
||||
bool to_primary = false;
|
||||
|
||||
|
|
@ -71,6 +60,22 @@ osc_to_clipboard(struct terminal *term, const char *target,
|
|||
return;
|
||||
}
|
||||
|
||||
char *decoded = base64_decode(base64_data);
|
||||
if (decoded == NULL) {
|
||||
if (errno == EINVAL)
|
||||
LOG_WARN("OSC: invalid clipboard data: %s", base64_data);
|
||||
else
|
||||
LOG_ERRNO("base64_decode() failed");
|
||||
|
||||
if (to_clipboard)
|
||||
selection_clipboard_unset(seat);
|
||||
if (to_primary)
|
||||
selection_primary_unset(seat);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("decoded: %s", decoded);
|
||||
|
||||
if (to_clipboard) {
|
||||
char *copy = xstrdup(decoded);
|
||||
if (!text_to_clipboard(seat, term, copy, seat->kbd.serial))
|
||||
|
|
@ -157,20 +162,6 @@ from_clipboard_done(void *user)
|
|||
static void
|
||||
osc_from_clipboard(struct terminal *term, const char *source)
|
||||
{
|
||||
/* Use clipboard if no source has been specified */
|
||||
char src = source[0] == '\0' ? 'c' : 0;
|
||||
|
||||
for (const char *s = source; *s != '\0'; s++) {
|
||||
if (*s == 'c' || *s == 'p' || *s == 's') {
|
||||
src = *s;
|
||||
break;
|
||||
} else
|
||||
LOG_WARN("unimplemented: clipboard source '%c'", *s);
|
||||
}
|
||||
|
||||
if (src == 0)
|
||||
return;
|
||||
|
||||
/* Find a seat in which the terminal has focus */
|
||||
struct seat *seat = NULL;
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
|
|
@ -185,6 +176,35 @@ osc_from_clipboard(struct terminal *term, const char *source)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Use clipboard if no source has been specified */
|
||||
char src = source[0] == '\0' ? 'c' : 0;
|
||||
bool from_clipboard = src == 'c';
|
||||
bool from_primary = false;
|
||||
|
||||
for (const char *s = source;
|
||||
*s != '\0' && !from_clipboard && !from_primary;
|
||||
s++)
|
||||
{
|
||||
if (*s == 'c' || *s == 'p' || *s == 's') {
|
||||
src = *s;
|
||||
|
||||
switch (src) {
|
||||
case 'c':
|
||||
from_clipboard = selection_clipboard_has_data(seat);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'p':
|
||||
from_primary = selection_primary_has_data(seat);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
LOG_WARN("unimplemented: clipboard source '%c'", *s);
|
||||
}
|
||||
|
||||
if (!from_clipboard && !from_primary)
|
||||
return;
|
||||
|
||||
term_to_slave(term, "\033]52;", 5);
|
||||
term_to_slave(term, &src, 1);
|
||||
term_to_slave(term, ";", 1);
|
||||
|
|
@ -192,17 +212,14 @@ osc_from_clipboard(struct terminal *term, const char *source)
|
|||
struct clip_context *ctx = xmalloc(sizeof(*ctx));
|
||||
*ctx = (struct clip_context) {.seat = seat, .term = term};
|
||||
|
||||
switch (src) {
|
||||
case 'c':
|
||||
if (from_clipboard) {
|
||||
text_from_clipboard(
|
||||
seat, term, &from_clipboard_cb, &from_clipboard_done, ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
case 'p':
|
||||
if (from_primary) {
|
||||
text_from_primary(
|
||||
seat, term, &from_clipboard_cb, &from_clipboard_done, ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
53
selection.c
53
selection.c
|
|
@ -661,6 +661,59 @@ selection_cancel(struct terminal *term)
|
|||
term->selection.ongoing = false;
|
||||
}
|
||||
|
||||
bool
|
||||
selection_clipboard_has_data(const struct seat *seat)
|
||||
{
|
||||
return seat->clipboard.data_offer != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
selection_primary_has_data(const struct seat *seat)
|
||||
{
|
||||
return seat->primary.data_offer != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
selection_clipboard_unset(struct seat *seat)
|
||||
{
|
||||
struct wl_clipboard *clipboard = &seat->clipboard;
|
||||
|
||||
if (clipboard->data_source == NULL)
|
||||
return;
|
||||
|
||||
/* Kill previous data source */
|
||||
assert(clipboard->serial != 0);
|
||||
wl_data_device_set_selection(seat->data_device, NULL, clipboard->serial);
|
||||
wl_data_source_destroy(clipboard->data_source);
|
||||
|
||||
clipboard->data_source = NULL;
|
||||
clipboard->serial = 0;
|
||||
|
||||
free(clipboard->text);
|
||||
clipboard->text = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
selection_primary_unset(struct seat *seat)
|
||||
{
|
||||
struct wl_primary *primary = &seat->primary;
|
||||
|
||||
if (primary->data_source == NULL)
|
||||
return;
|
||||
|
||||
assert(primary->serial != 0);
|
||||
zwp_primary_selection_device_v1_set_selection(
|
||||
seat->primary_selection_device, NULL, primary->serial);
|
||||
zwp_primary_selection_source_v1_destroy(primary->data_source);
|
||||
free(primary->text);
|
||||
|
||||
primary->data_source = NULL;
|
||||
primary->serial = 0;
|
||||
|
||||
free(primary->text);
|
||||
primary->text = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
selection_mark_word(struct seat *seat, struct terminal *term, int col, int row,
|
||||
bool spaces_only, uint32_t serial)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ void selection_mark_word(
|
|||
void selection_mark_row(
|
||||
struct seat *seat, struct terminal *term, int row, uint32_t serial);
|
||||
|
||||
void selection_clipboard_unset(struct seat *seat);
|
||||
void selection_primary_unset(struct seat *seat);
|
||||
|
||||
bool selection_clipboard_has_data(const struct seat *seat);
|
||||
bool selection_primary_has_data(const struct seat *seat);
|
||||
|
||||
char *selection_to_text(const struct terminal *term);
|
||||
void selection_to_clipboard(
|
||||
struct seat *seat, struct terminal *term, uint32_t serial);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue