From e6835795f0311f1e7f35ca4534811de4a316f10d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 3 Aug 2019 11:28:38 -0700 Subject: [PATCH] GUACAMOLE-623: Add support for setting terminal font for Kubernetes via "argv". --- src/protocols/kubernetes/Makefile.am | 2 + src/protocols/kubernetes/argv.c | 195 +++++++++++++++++++++++++++ src/protocols/kubernetes/argv.h | 41 ++++++ src/protocols/kubernetes/user.c | 4 + 4 files changed, 242 insertions(+) create mode 100644 src/protocols/kubernetes/argv.c create mode 100644 src/protocols/kubernetes/argv.h diff --git a/src/protocols/kubernetes/Makefile.am b/src/protocols/kubernetes/Makefile.am index b100c176..f22e91f8 100644 --- a/src/protocols/kubernetes/Makefile.am +++ b/src/protocols/kubernetes/Makefile.am @@ -29,6 +29,7 @@ ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-kubernetes.la libguac_client_kubernetes_la_SOURCES = \ + argv.c \ client.c \ clipboard.c \ input.c \ @@ -41,6 +42,7 @@ libguac_client_kubernetes_la_SOURCES = \ user.c noinst_HEADERS = \ + argv.h \ client.h \ clipboard.h \ input.h \ diff --git a/src/protocols/kubernetes/argv.c b/src/protocols/kubernetes/argv.c new file mode 100644 index 00000000..0bff3149 --- /dev/null +++ b/src/protocols/kubernetes/argv.c @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "config.h" +#include "argv.h" +#include "kubernetes.h" +#include "terminal/terminal.h" + +#include +#include +#include + +#include +#include + +/** + * All Kubernetes connection settings which may be updated by unprivileged + * users through "argv" streams. + */ +typedef enum guac_kubernetes_argv_setting { + + /** + * The color scheme of the terminal. + */ + GUAC_KUBERNETES_ARGV_SETTING_COLOR_SCHEME, + + /** + * The name of the font family used by the terminal. + */ + GUAC_KUBERNETES_ARGV_SETTING_FONT_NAME, + + /** + * The size of the font used by the terminal, in points. + */ + GUAC_KUBERNETES_ARGV_SETTING_FONT_SIZE + +} guac_kubernetes_argv_setting; + +/** + * The value or current status of a connection parameter received over an + * "argv" stream. + */ +typedef struct guac_kubernetes_argv { + + /** + * The specific setting being updated. + */ + guac_kubernetes_argv_setting setting; + + /** + * Buffer space for containing the received argument value. + */ + char buffer[GUAC_KUBERNETES_ARGV_MAX_LENGTH]; + + /** + * The number of bytes received so far. + */ + int length; + +} guac_kubernetes_argv; + +/** + * Handler for "blob" instructions which appends the data from received blobs + * to the end of the in-progress argument value buffer. + * + * @see guac_user_blob_handler + */ +static int guac_kubernetes_argv_blob_handler(guac_user* user, + guac_stream* stream, void* data, int length) { + + guac_kubernetes_argv* argv = (guac_kubernetes_argv*) stream->data; + + /* Calculate buffer size remaining, including space for null terminator, + * adjusting received length accordingly */ + int remaining = sizeof(argv->buffer) - argv->length - 1; + if (length > remaining) + length = remaining; + + /* Append received data to end of buffer */ + memcpy(argv->buffer + argv->length, data, length); + argv->length += length; + + return 0; + +} + +/** + * Handler for "end" instructions which applies the changes specified by the + * argument value buffer associated with the stream. + * + * @see guac_user_end_handler + */ +static int guac_kubernetes_argv_end_handler(guac_user* user, + guac_stream* stream) { + + int size; + + guac_client* client = user->client; + guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; + guac_terminal* terminal = kubernetes_client->term; + + /* Append null terminator to value */ + guac_kubernetes_argv* argv = (guac_kubernetes_argv*) stream->data; + argv->buffer[argv->length] = '\0'; + + /* Apply changes to chosen setting */ + switch (argv->setting) { + + /* Update color scheme */ + case GUAC_KUBERNETES_ARGV_SETTING_COLOR_SCHEME: + guac_terminal_apply_color_scheme(terminal, argv->buffer); + break; + + /* Update font name */ + case GUAC_KUBERNETES_ARGV_SETTING_FONT_NAME: + guac_terminal_apply_font(terminal, argv->buffer, -1, 0); + break; + + /* Update font size */ + case GUAC_KUBERNETES_ARGV_SETTING_FONT_SIZE: + + /* Update only if font size is sane */ + size = atoi(argv->buffer); + if (size > 0) { + guac_terminal_apply_font(terminal, NULL, size, + kubernetes_client->settings->resolution); + } + + break; + + } + + /* Update Kubernetes terminal size */ + guac_kubernetes_resize(client, terminal->term_height, + terminal->term_width); + + free(argv); + return 0; + +} + +int guac_kubernetes_argv_handler(guac_user* user, guac_stream* stream, + char* mimetype, char* name) { + + guac_kubernetes_argv_setting setting; + + /* Allow users to update the color scheme and font details */ + if (strcmp(name, "color-scheme") == 0) + setting = GUAC_KUBERNETES_ARGV_SETTING_COLOR_SCHEME; + else if (strcmp(name, "font-name") == 0) + setting = GUAC_KUBERNETES_ARGV_SETTING_FONT_NAME; + else if (strcmp(name, "font-size") == 0) + setting = GUAC_KUBERNETES_ARGV_SETTING_FONT_SIZE; + + /* No other connection parameters may be updated */ + else { + guac_protocol_send_ack(user->socket, stream, "Not allowed.", + GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + guac_socket_flush(user->socket); + return 0; + } + + guac_kubernetes_argv* argv = malloc(sizeof(guac_kubernetes_argv)); + argv->setting = setting; + argv->length = 0; + + /* Prepare stream to receive argument value */ + stream->blob_handler = guac_kubernetes_argv_blob_handler; + stream->end_handler = guac_kubernetes_argv_end_handler; + stream->data = argv; + + /* Signal stream is ready */ + guac_protocol_send_ack(user->socket, stream, "Ready for updated " + "parameter.", GUAC_PROTOCOL_STATUS_SUCCESS); + guac_socket_flush(user->socket); + return 0; + +} + diff --git a/src/protocols/kubernetes/argv.h b/src/protocols/kubernetes/argv.h new file mode 100644 index 00000000..da9e11b7 --- /dev/null +++ b/src/protocols/kubernetes/argv.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef GUAC_KUBERNETES_ARGV_H +#define GUAC_KUBERNETES_ARGV_H + +#include "config.h" + +#include + +/** + * The maximum number of bytes to allow for any argument value received via an + * argv stream, including null terminator. + */ +#define GUAC_KUBERNETES_ARGV_MAX_LENGTH 16384 + +/** + * Handles an incoming stream from a Guacamole "argv" instruction, updating the + * given connection parameter if that parameter is allowed to be updated. + */ +guac_user_argv_handler guac_kubernetes_argv_handler; + +#endif + diff --git a/src/protocols/kubernetes/user.c b/src/protocols/kubernetes/user.c index f90260e7..a2fdd200 100644 --- a/src/protocols/kubernetes/user.c +++ b/src/protocols/kubernetes/user.c @@ -17,6 +17,7 @@ * under the License. */ +#include "argv.h" #include "clipboard.h" #include "common/cursor.h" #include "input.h" @@ -87,6 +88,9 @@ int guac_kubernetes_user_join_handler(guac_user* user, int argc, char** argv) { /* STDIN redirection */ user->pipe_handler = guac_kubernetes_pipe_handler; + /* Updates to connection parameters */ + user->argv_handler = guac_kubernetes_argv_handler; + /* Display size change events */ user->size_handler = guac_kubernetes_user_size_handler;