Commit 81c6066f for guacamole.apache.org

commit 81c6066f1235b8689481b05a98a1ab257174b98e
Merge: 2b010738 4e776b73
Author: Virtually Nick <vnick@apache.org>
Date:   Fri May 1 13:54:08 2026 -0400

    Merge patch branch changes to main.

diff --cc src/protocols/vnc/clipboard.c
index aea0bcd2,3d4a400d..83334250
--- a/src/protocols/vnc/clipboard.c
+++ b/src/protocols/vnc/clipboard.c
@@@ -115,32 -102,49 +116,59 @@@ int guac_vnc_clipboard_blob_handler(gua
  int guac_vnc_clipboard_end_handler(guac_user* user, guac_stream* stream) {

      guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data;
 +
 +    /* Ignore end of stream if no clipboard structure is available to handle
 +     * the data that was received */
 +    guac_common_clipboard* clipboard = vnc_client->clipboard;
 +    if (clipboard == NULL)
 +        return 0;
 +
      rfbClient* rfb_client = vnc_client->rfb_client;

+     /* Send via VNC only if finished connecting */
+     if (rfb_client == NULL)
+         return 0;
+
+     /*
+      * Guacamole stores clipboard text as UTF-8. The clipboard-encoding
+      * setting only applies to the classic VNC clipboard path, where text
+      * must be converted from UTF-8 to the configured wire encoding.
+      *
+      * If clipboard-encoding is UTF-8, try the Extended Clipboard  path first
+      * since it can send UTF-8 directly. Otherwise, or if that fails, fall
+      * back to classic clipboard conversion.
+      *
+      * Text coming back from the VNC server follows the same idea in reverse:
+      * classic clipboard text is decoded using clipboard-encoding, while
+      * Extended Clipboard text is already UTF-8.
+      */
+
+     const char* clipboard_encoding = vnc_client->settings->clipboard_encoding;
+     int use_utf8_clipboard = clipboard_encoding != NULL &&
+         strcmp(clipboard_encoding, "UTF-8") == 0;
+
+     if (use_utf8_clipboard) {
+         if (SendClientCutTextUTF8(rfb_client, vnc_client->clipboard->buffer,
+                     vnc_client->clipboard->length))
+             return 0;
+     }
+
+     /* Fall back to classic clipboard with encoding conversion */
 -    char output_data[GUAC_COMMON_CLIPBOARD_MAX_LENGTH];
 +    int output_buf_size = clipboard->available;
 +    char* output_data = guac_mem_alloc(output_buf_size);

 -    const char* input = vnc_client->clipboard->buffer;
 +    const char* input = clipboard->buffer;
      char* output = output_data;
      guac_iconv_write* writer = vnc_client->clipboard_writer;

      /* Convert clipboard contents */
 -    guac_iconv(GUAC_READ_UTF8, &input, vnc_client->clipboard->length,
 -               writer, &output, sizeof(output_data));
 +    guac_iconv(GUAC_READ_UTF8, &input, clipboard->length,
 +               writer, &output, output_buf_size);

-     /* Send via VNC only if finished connecting */
-     if (rfb_client != NULL)
-         SendClientCutText(rfb_client, output_data, output - output_data);
+     SendClientCutText(rfb_client, output_data, output - output_data);

 +    guac_mem_free(output_data);
 +
      return 0;
  }

@@@ -169,6 -172,31 +197,32 @@@ void guac_vnc_cut_text(rfbClient* clien
      guac_common_clipboard_append(vnc_client->clipboard, received_data, output - received_data);
      guac_common_clipboard_send(vnc_client->clipboard, gc);

 +    guac_mem_free(received_data);
  }

+ void guac_vnc_cut_text_utf8(rfbClient* client, const char* text, int textlen) {
+
+     guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY);
+     guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data;
+
+     /* Ignore received text if outbound clipboard transfer is disabled */
+     if (vnc_client->settings->disable_copy)
+         return;
+
+     char received_data[GUAC_COMMON_CLIPBOARD_MAX_LENGTH];
+
+     const char* input = text;
+     char* output = received_data;
+
+     /* Extended clipboard always delivers UTF-8; iconv() here enforces
+      * GUAC_COMMON_CLIPBOARD_MAX_LENGTH and replaces invalid lead bytes
+      * with the Unicode replacement character (U+FFFD, ?) */
+     guac_iconv(GUAC_READ_UTF8, &input, textlen,
+                GUAC_WRITE_UTF8, &output, sizeof(received_data));
+
+     /* Send converted data */
+     guac_common_clipboard_reset(vnc_client->clipboard, "text/plain");
+     guac_common_clipboard_append(vnc_client->clipboard, received_data, output - received_data);
+     guac_common_clipboard_send(vnc_client->clipboard, gc);
+
+ }