GUACAMOLE-630: Allow color scheme to be changed from webapp via argv streams.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/2f16eadb
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/2f16eadb
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/2f16eadb

Branch: refs/heads/master
Commit: 2f16eadb358362d1925da343e530ab73417d4f55
Parents: 6f9f218
Author: Michael Jumper <mjum...@apache.org>
Authored: Sun Sep 23 00:24:19 2018 -0700
Committer: Michael Jumper <mjum...@apache.org>
Committed: Mon Oct 22 23:23:27 2018 -0700

----------------------------------------------------------------------
 src/protocols/ssh/Makefile.am    |   2 +
 src/protocols/ssh/argv.c         | 128 ++++++++++++++++++++++++++++++++++
 src/protocols/ssh/argv.h         |  35 ++++++++++
 src/protocols/ssh/user.c         |   4 ++
 src/protocols/telnet/Makefile.am |   2 +
 src/protocols/telnet/argv.c      | 128 ++++++++++++++++++++++++++++++++++
 src/protocols/telnet/argv.h      |  35 ++++++++++
 src/protocols/telnet/user.c      |   4 ++
 src/terminal/display.c           |   4 +-
 src/terminal/terminal.c          |  29 +++++++-
 src/terminal/terminal/display.h  |   4 +-
 src/terminal/terminal/terminal.h |  15 ++++
 12 files changed, 385 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/ssh/Makefile.am
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/Makefile.am b/src/protocols/ssh/Makefile.am
index d60cf00..7bb1e34 100644
--- a/src/protocols/ssh/Makefile.am
+++ b/src/protocols/ssh/Makefile.am
@@ -29,6 +29,7 @@ ACLOCAL_AMFLAGS = -I m4
 lib_LTLIBRARIES = libguac-client-ssh.la
 
 libguac_client_ssh_la_SOURCES = \
+    argv.c                      \
     client.c                    \
     clipboard.c                 \
     input.c                     \
@@ -40,6 +41,7 @@ libguac_client_ssh_la_SOURCES = \
     user.c
 
 noinst_HEADERS =                \
+    argv.h                      \
     client.h                    \
     clipboard.h                 \
     input.h                     \

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/ssh/argv.c
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/argv.c b/src/protocols/ssh/argv.c
new file mode 100644
index 0000000..85dca94
--- /dev/null
+++ b/src/protocols/ssh/argv.c
@@ -0,0 +1,128 @@
+/*
+ * 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 "ssh.h"
+#include "terminal/terminal.h"
+
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * The value or current status of a connection parameter received over an
+ * "argv" stream.
+ */
+typedef struct guac_ssh_argv {
+
+    /**
+     * Buffer space for containing the received argument value.
+     */
+    char buffer[16384];
+
+    /**
+     * The number of bytes received so far.
+     */
+    int length;
+
+} guac_ssh_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_ssh_argv_blob_handler(guac_user* user,
+        guac_stream* stream, void* data, int length) {
+
+    guac_ssh_argv* argv = (guac_ssh_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_ssh_argv_end_handler(guac_user* user,
+        guac_stream* stream) {
+
+    guac_client* client = user->client;
+    guac_ssh_client* telnet_client = (guac_ssh_client*) client->data;
+    guac_terminal* terminal = telnet_client->term;
+
+    /* Append null terminator to value */
+    guac_ssh_argv* argv = (guac_ssh_argv*) stream->data;
+    argv->buffer[argv->length] = '\0';
+
+    /* Update color scheme */
+    guac_terminal_apply_color_scheme(terminal, argv->buffer);
+    free(argv);
+    return 0;
+
+}
+
+int guac_ssh_argv_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* name) {
+
+    /* Allow users to update the color scheme */
+    if (strcmp(name, "color-scheme") == 0) {
+
+        guac_ssh_argv* argv = malloc(sizeof(guac_ssh_argv));
+        argv->length = 0;
+
+        /* Prepare stream to receive argument value */
+        stream->blob_handler = guac_ssh_argv_blob_handler;
+        stream->end_handler = guac_ssh_argv_end_handler;
+        stream->data = argv;
+
+        /* Signal stream is ready */
+        guac_protocol_send_ack(user->socket, stream, "Ready for color "
+                "scheme.", GUAC_PROTOCOL_STATUS_SUCCESS);
+        guac_socket_flush(user->socket);
+        return 0;
+
+    }
+
+    /* No other connection parameters may be updated */
+    guac_protocol_send_ack(user->socket, stream, "Not allowed.",
+            GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
+    guac_socket_flush(user->socket);
+    return 0;
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/ssh/argv.h
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/argv.h b/src/protocols/ssh/argv.h
new file mode 100644
index 0000000..27b08cb
--- /dev/null
+++ b/src/protocols/ssh/argv.h
@@ -0,0 +1,35 @@
+/*
+ * 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_SSH_ARGV_H
+#define GUAC_SSH_ARGV_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+/**
+ * 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_ssh_argv_handler;
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/ssh/user.c
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/user.c b/src/protocols/ssh/user.c
index e4dda40..97ed87c 100644
--- a/src/protocols/ssh/user.c
+++ b/src/protocols/ssh/user.c
@@ -19,6 +19,7 @@
 
 #include "config.h"
 
+#include "argv.h"
 #include "clipboard.h"
 #include "common/display.h"
 #include "input.h"
@@ -87,6 +88,9 @@ int guac_ssh_user_join_handler(guac_user* user, int argc, 
char** argv) {
         /* STDIN redirection */
         user->pipe_handler = guac_ssh_pipe_handler;
 
+        /* Updates to connection parameters */
+        user->argv_handler = guac_ssh_argv_handler;
+
         /* Display size change events */
         user->size_handler = guac_ssh_user_size_handler;
 

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/telnet/Makefile.am
----------------------------------------------------------------------
diff --git a/src/protocols/telnet/Makefile.am b/src/protocols/telnet/Makefile.am
index bec0e95..d0264f6 100644
--- a/src/protocols/telnet/Makefile.am
+++ b/src/protocols/telnet/Makefile.am
@@ -29,6 +29,7 @@ ACLOCAL_AMFLAGS = -I m4
 lib_LTLIBRARIES = libguac-client-telnet.la
 
 libguac_client_telnet_la_SOURCES = \
+    argv.c                         \
     client.c                       \
     clipboard.c                    \
     input.c                        \
@@ -38,6 +39,7 @@ libguac_client_telnet_la_SOURCES = \
     user.c
 
 noinst_HEADERS = \
+    argv.h       \
     client.h     \
     clipboard.h  \
     input.h      \

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/telnet/argv.c
----------------------------------------------------------------------
diff --git a/src/protocols/telnet/argv.c b/src/protocols/telnet/argv.c
new file mode 100644
index 0000000..da405aa
--- /dev/null
+++ b/src/protocols/telnet/argv.c
@@ -0,0 +1,128 @@
+/*
+ * 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 "telnet.h"
+#include "terminal/terminal.h"
+
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * The value or current status of a connection parameter received over an
+ * "argv" stream.
+ */
+typedef struct guac_telnet_argv {
+
+    /**
+     * Buffer space for containing the received argument value.
+     */
+    char buffer[16384];
+
+    /**
+     * The number of bytes received so far.
+     */
+    int length;
+
+} guac_telnet_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_telnet_argv_blob_handler(guac_user* user,
+        guac_stream* stream, void* data, int length) {
+
+    guac_telnet_argv* argv = (guac_telnet_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_telnet_argv_end_handler(guac_user* user,
+        guac_stream* stream) {
+
+    guac_client* client = user->client;
+    guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
+    guac_terminal* terminal = telnet_client->term;
+
+    /* Append null terminator to value */
+    guac_telnet_argv* argv = (guac_telnet_argv*) stream->data;
+    argv->buffer[argv->length] = '\0';
+
+    /* Update color scheme */
+    guac_terminal_apply_color_scheme(terminal, argv->buffer);
+    free(argv);
+    return 0;
+
+}
+
+int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* name) {
+
+    /* Allow users to update the color scheme */
+    if (strcmp(name, "color-scheme") == 0) {
+
+        guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv));
+        argv->length = 0;
+
+        /* Prepare stream to receive argument value */
+        stream->blob_handler = guac_telnet_argv_blob_handler;
+        stream->end_handler = guac_telnet_argv_end_handler;
+        stream->data = argv;
+
+        /* Signal stream is ready */
+        guac_protocol_send_ack(user->socket, stream, "Ready for color "
+                "scheme.", GUAC_PROTOCOL_STATUS_SUCCESS);
+        guac_socket_flush(user->socket);
+        return 0;
+
+    }
+
+    /* No other connection parameters may be updated */
+    guac_protocol_send_ack(user->socket, stream, "Not allowed.",
+            GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
+    guac_socket_flush(user->socket);
+    return 0;
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/telnet/argv.h
----------------------------------------------------------------------
diff --git a/src/protocols/telnet/argv.h b/src/protocols/telnet/argv.h
new file mode 100644
index 0000000..b1567ea
--- /dev/null
+++ b/src/protocols/telnet/argv.h
@@ -0,0 +1,35 @@
+/*
+ * 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_TELNET_ARGV_H
+#define GUAC_TELNET_ARGV_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+/**
+ * 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_telnet_argv_handler;
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/protocols/telnet/user.c
----------------------------------------------------------------------
diff --git a/src/protocols/telnet/user.c b/src/protocols/telnet/user.c
index 2e34f78..44ef9b5 100644
--- a/src/protocols/telnet/user.c
+++ b/src/protocols/telnet/user.c
@@ -19,6 +19,7 @@
 
 #include "config.h"
 
+#include "argv.h"
 #include "clipboard.h"
 #include "input.h"
 #include "pipe.h"
@@ -86,6 +87,9 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, 
char** argv) {
         /* STDIN redirection */
         user->pipe_handler = guac_telnet_pipe_handler;
 
+        /* Updates to connection parameters */
+        user->argv_handler = guac_telnet_argv_handler;
+
         /* Display size change events */
         user->size_handler = guac_telnet_user_size_handler;
 

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/terminal/display.c
----------------------------------------------------------------------
diff --git a/src/terminal/display.c b/src/terminal/display.c
index c4c7471..480e839 100644
--- a/src/terminal/display.c
+++ b/src/terminal/display.c
@@ -199,7 +199,7 @@ int __guac_terminal_set(guac_terminal_display* display, int 
row, int col, int co
 guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
         const char* font_name, int font_size, int dpi,
         guac_terminal_color* foreground, guac_terminal_color* background,
-        const guac_terminal_color (*palette)[256]) {
+        guac_terminal_color (*palette)[256]) {
 
     PangoFontMap* font_map;
     PangoFont* font;
@@ -271,7 +271,7 @@ guac_terminal_display* 
guac_terminal_display_alloc(guac_client* client,
 void guac_terminal_display_free(guac_terminal_display* display) {
 
     /* Free default palette. */
-    free((void*) display->default_palette);
+    free(display->default_palette);
 
     /* Free operations buffers */
     free(display->operations);

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/terminal/terminal.c
----------------------------------------------------------------------
diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c
index a99bfb0..c12df4b 100644
--- a/src/terminal/terminal.c
+++ b/src/terminal/terminal.c
@@ -384,7 +384,7 @@ guac_terminal* guac_terminal_create(guac_client* client,
             font_name, font_size, dpi,
             &default_char.attributes.foreground,
             &default_char.attributes.background,
-            (const guac_terminal_color(*)[256]) default_palette);
+            (guac_terminal_color(*)[256]) default_palette);
 
     /* Fail if display init failed */
     if (term->display == NULL) {
@@ -1940,3 +1940,30 @@ void guac_terminal_dup(guac_terminal* term, guac_user* 
user,
 
 }
 
+void guac_terminal_apply_color_scheme(guac_terminal* terminal,
+        const char* color_scheme) {
+
+    guac_client* client = terminal->client;
+    guac_terminal_char* default_char = &terminal->default_char;
+    guac_terminal_display* display = terminal->display;
+
+    /* Reinitialize default terminal colors with values from color scheme */
+    guac_terminal_parse_color_scheme(client, color_scheme,
+        &default_char->attributes.foreground,
+        &default_char->attributes.background,
+        display->default_palette);
+
+    /* Reinitialize default attributes of buffer and display */
+    terminal->buffer->default_character = *default_char;
+    display->default_foreground = default_char->attributes.foreground;
+    display->default_background = default_char->attributes.background;
+
+    /* Redraw background with new color */
+    guac_terminal_repaint_default_layer(terminal, client->socket);
+
+    /* Force reset of terminal state */
+    guac_terminal_reset(terminal);
+    guac_terminal_notify(terminal);
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/terminal/terminal/display.h
----------------------------------------------------------------------
diff --git a/src/terminal/terminal/display.h b/src/terminal/terminal/display.h
index e54003b..b127423 100644
--- a/src/terminal/terminal/display.h
+++ b/src/terminal/terminal/display.h
@@ -142,7 +142,7 @@ typedef struct guac_terminal_display {
      * The default palette. Use GUAC_TERMINAL_INITIAL_PALETTE if null.
      * Must free on destruction if not null.
      */
-    const guac_terminal_color (*default_palette)[256];
+    guac_terminal_color (*default_palette)[256];
 
     /**
      * Default foreground color for all glyphs.
@@ -215,7 +215,7 @@ typedef struct guac_terminal_display {
 guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
         const char* font_name, int font_size, int dpi,
         guac_terminal_color* foreground, guac_terminal_color* background,
-        const guac_terminal_color (*palette)[256]);
+        guac_terminal_color (*palette)[256]);
 
 /**
  * Frees the given display.

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/2f16eadb/src/terminal/terminal/terminal.h
----------------------------------------------------------------------
diff --git a/src/terminal/terminal/terminal.h b/src/terminal/terminal/terminal.h
index aee7742..6de984b 100644
--- a/src/terminal/terminal/terminal.h
+++ b/src/terminal/terminal/terminal.h
@@ -1072,5 +1072,20 @@ int guac_terminal_create_typescript(guac_terminal* term, 
const char* path,
  */
 int guac_terminal_available_scroll(guac_terminal* term);
 
+/**
+ * Immediately applies the given color scheme to the given terminal, overriding
+ * the color scheme provided when the terminal was created. Applying the color
+ * scheme implicitly clears the display and resets the terminal state. Valid
+ * color schemes are those accepted by guac_terminal_parse_color_scheme().
+ *
+ * @param terminal
+ *     The terminal to apply the color scheme to.
+ *
+ * @param color_scheme
+ *     The color scheme to apply.
+ */
+void guac_terminal_apply_color_scheme(guac_terminal* terminal,
+        const char* color_scheme);
+
 #endif
 

Reply via email to