You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/01/30 19:08:29 UTC
[01/11] guacamole-server git commit: GUACAMOLE-313: Add guaclog
utility with stubbed interpretation of key events.
Repository: guacamole-server
Updated Branches:
refs/heads/master 08f854ffe -> 5f5b4ea8e
GUACAMOLE-313: Add guaclog utility with stubbed interpretation of key events.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/ebc731aa
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/ebc731aa
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/ebc731aa
Branch: refs/heads/master
Commit: ebc731aaf390ca06019af58bb6c512faa4605ee6
Parents: db85163
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Nov 26 15:44:03 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:04 2018 -0800
----------------------------------------------------------------------
Makefile.am | 5 ++
configure.ac | 16 ++++
src/guaclog/.gitignore | 5 ++
src/guaclog/Makefile.am | 51 +++++++++++++
src/guaclog/guaclog.c | 119 +++++++++++++++++++++++++++++
src/guaclog/guaclog.h | 31 ++++++++
src/guaclog/instruction-key.c | 43 +++++++++++
src/guaclog/instructions.c | 62 +++++++++++++++
src/guaclog/instructions.h | 108 ++++++++++++++++++++++++++
src/guaclog/interpret.c | 152 +++++++++++++++++++++++++++++++++++++
src/guaclog/interpret.h | 51 +++++++++++++
src/guaclog/log.c | 85 +++++++++++++++++++++
src/guaclog/log.h | 73 ++++++++++++++++++
src/guaclog/man/guaclog.1.in | 60 +++++++++++++++
src/guaclog/state.c | 97 +++++++++++++++++++++++
src/guaclog/state.h | 89 ++++++++++++++++++++++
16 files changed, 1047 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index 8dfa9d1..e923376 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,6 +27,7 @@ DIST_SUBDIRS = \
src/terminal \
src/guacd \
src/guacenc \
+ src/guaclog \
src/pulse \
src/protocols/rdp \
src/protocols/ssh \
@@ -75,6 +76,10 @@ if ENABLE_GUACENC
SUBDIRS += src/guacenc
endif
+if ENABLE_GUACLOG
+SUBDIRS += src/guaclog
+endif
+
EXTRA_DIST = \
.dockerignore \
CONTRIBUTING \
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 1906dc8..8ae0743 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1192,6 +1192,18 @@ AM_CONDITIONAL([ENABLE_GUACENC], [test "x${enable_guacenc}" = "xyes" \
-a "x${have_libswscale}" = "xyes"])
#
+# guaclog
+#
+
+AC_ARG_ENABLE([guaclog],
+ [AS_HELP_STRING([--disable-guaclog],
+ [do not build the Guacamole input logging tool])],
+ [],
+ [enable_guaclog=yes])
+
+AM_CONDITIONAL([ENABLE_GUACLOG], [test "x${enable_guaclog}" = "xyes"])
+
+#
# Output Makefiles
#
@@ -1207,6 +1219,8 @@ AC_CONFIG_FILES([Makefile
src/guacd/man/guacd.conf.5
src/guacenc/Makefile
src/guacenc/man/guacenc.1
+ src/guaclog/Makefile
+ src/guaclog/man/guaclog.1
src/pulse/Makefile
src/protocols/rdp/Makefile
src/protocols/ssh/Makefile
@@ -1229,6 +1243,7 @@ AM_COND_IF([ENABLE_VNC], [build_vnc=yes], [build_vnc=no])
AM_COND_IF([ENABLE_GUACD], [build_guacd=yes], [build_guacd=no])
AM_COND_IF([ENABLE_GUACENC], [build_guacenc=yes], [build_guacenc=no])
+AM_COND_IF([ENABLE_GUACLOG], [build_guaclog=yes], [build_guaclog=no])
#
# Init scripts
@@ -1272,6 +1287,7 @@ $PACKAGE_NAME version $PACKAGE_VERSION
guacd ...... ${build_guacd}
guacenc .... ${build_guacenc}
+ guaclog .... ${build_guaclog}
Init scripts: ${build_init}
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/.gitignore
----------------------------------------------------------------------
diff --git a/src/guaclog/.gitignore b/src/guaclog/.gitignore
new file mode 100644
index 0000000..4865f64
--- /dev/null
+++ b/src/guaclog/.gitignore
@@ -0,0 +1,5 @@
+
+# Compiled guaclog
+guaclog
+guaclog.exe
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/Makefile.am
----------------------------------------------------------------------
diff --git a/src/guaclog/Makefile.am b/src/guaclog/Makefile.am
new file mode 100644
index 0000000..f1ad152
--- /dev/null
+++ b/src/guaclog/Makefile.am
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+
+AUTOMAKE_OPTIONS = foreign
+
+bin_PROGRAMS = guaclog
+
+man_MANS = \
+ man/guaclog.1
+
+noinst_HEADERS = \
+ guaclog.h \
+ instructions.h \
+ interpret.h \
+ log.h \
+ state.h
+
+guaclog_SOURCES = \
+ guaclog.c \
+ instructions.c \
+ instruction-key.c \
+ interpret.c \
+ log.c \
+ state.c
+
+guaclog_CFLAGS = \
+ -Werror -Wall \
+ @LIBGUAC_INCLUDE@
+
+guaclog_LDADD = \
+ @LIBGUAC_LTLIB@
+
+EXTRA_DIST = \
+ man/guaclog.1.in
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/guaclog.c
----------------------------------------------------------------------
diff --git a/src/guaclog/guaclog.c b/src/guaclog/guaclog.c
new file mode 100644
index 0000000..4350289
--- /dev/null
+++ b/src/guaclog/guaclog.c
@@ -0,0 +1,119 @@
+/*
+ * 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 "guaclog.h"
+#include "interpret.h"
+#include "log.h"
+
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+
+ int i;
+
+ /* Load defaults */
+ bool force = false;
+
+ /* Parse arguments */
+ int opt;
+ while ((opt = getopt(argc, argv, "s:r:f")) != -1) {
+
+ /* -f: Force */
+ if (opt == 'f')
+ force = true;
+
+ /* Invalid option */
+ else {
+ goto invalid_options;
+ }
+
+ }
+
+ /* Log start */
+ guaclog_log(GUAC_LOG_INFO, "Guacamole input log interpreter (guaclog) "
+ "version " VERSION);
+
+ /* Track number of overall failures */
+ int total_files = argc - optind;
+ int failures = 0;
+
+ /* Abort if no files given */
+ if (total_files <= 0) {
+ guaclog_log(GUAC_LOG_INFO, "No input files specified. Nothing to do.");
+ return 0;
+ }
+
+ guaclog_log(GUAC_LOG_INFO, "%i input file(s) provided.", total_files);
+
+ /* Interpret all input files */
+ for (i = optind; i < argc; i++) {
+
+ /* Get current filename */
+ const char* path = argv[i];
+
+ /* Generate output filename */
+ char out_path[4096];
+ int len = snprintf(out_path, sizeof(out_path), "%s.txt", path);
+
+ /* Do not write if filename exceeds maximum length */
+ if (len >= sizeof(out_path)) {
+ guaclog_log(GUAC_LOG_ERROR, "Cannot write output file for \"%s\": "
+ "Name too long", path);
+ continue;
+ }
+
+ /* Attempt interpreting, log granular success/failure at debug level */
+ if (guaclog_interpret(path, out_path, force)) {
+ failures++;
+ guaclog_log(GUAC_LOG_DEBUG,
+ "%s was NOT successfully interpreted.", path);
+ }
+ else
+ guaclog_log(GUAC_LOG_DEBUG, "%s was successfully "
+ "interpreted.", path);
+
+ }
+
+ /* Warn if at least one file failed */
+ if (failures != 0)
+ guaclog_log(GUAC_LOG_WARNING, "Interpreting failed for %i of %i "
+ "file(s).", failures, total_files);
+
+ /* Notify of success */
+ else
+ guaclog_log(GUAC_LOG_INFO, "All files interpreted successfully.");
+
+ /* Interpreting complete */
+ return 0;
+
+ /* Display usage and exit with error if options are invalid */
+invalid_options:
+
+ fprintf(stderr, "USAGE: %s"
+ " [-f]"
+ " [FILE]...\n", argv[0]);
+
+ return 1;
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/guaclog.h
----------------------------------------------------------------------
diff --git a/src/guaclog/guaclog.h b/src/guaclog/guaclog.h
new file mode 100644
index 0000000..7390314
--- /dev/null
+++ b/src/guaclog/guaclog.h
@@ -0,0 +1,31 @@
+/*
+ * 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 GUACLOG_H
+#define GUACLOG_H
+
+#include "config.h"
+
+/**
+ * The default log level below which no messages should be logged.
+ */
+#define GUACLOG_DEFAULT_LOG_LEVEL GUAC_LOG_INFO
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/instruction-key.c
----------------------------------------------------------------------
diff --git a/src/guaclog/instruction-key.c b/src/guaclog/instruction-key.c
new file mode 100644
index 0000000..0e8501b
--- /dev/null
+++ b/src/guaclog/instruction-key.c
@@ -0,0 +1,43 @@
+/*
+ * 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 "log.h"
+#include "state.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+int guaclog_handle_key(guaclog_state* state, int argc, char** argv) {
+
+ /* Verify argument count */
+ if (argc < 2) {
+ guaclog_log(GUAC_LOG_WARNING, "\"key\" instruction incomplete");
+ return 1;
+ }
+
+ /* Parse arguments */
+ int keysym = atoi(argv[0]);
+ bool pressed = (atoi(argv[1]) != 0);
+
+ /* Update interpreter state accordingly */
+ return guaclog_state_update_key(state, keysym, pressed);
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/instructions.c
----------------------------------------------------------------------
diff --git a/src/guaclog/instructions.c b/src/guaclog/instructions.c
new file mode 100644
index 0000000..257e134
--- /dev/null
+++ b/src/guaclog/instructions.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "state.h"
+#include "instructions.h"
+#include "log.h"
+
+#include <string.h>
+
+guaclog_instruction_handler_mapping guaclog_instruction_handler_map[] = {
+ {"key", guaclog_handle_key},
+ {NULL, NULL}
+};
+
+int guaclog_handle_instruction(guaclog_state* state, const char* opcode,
+ int argc, char** argv) {
+
+ /* Search through mapping for instruction handler having given opcode */
+ guaclog_instruction_handler_mapping* current = guaclog_instruction_handler_map;
+ while (current->opcode != NULL) {
+
+ /* Invoke handler if opcode matches (if defined) */
+ if (strcmp(current->opcode, opcode) == 0) {
+
+ /* Invoke defined handler */
+ guaclog_instruction_handler* handler = current->handler;
+ if (handler != NULL)
+ return handler(state, argc, argv);
+
+ /* Log defined but unimplemented instructions */
+ guaclog_log(GUAC_LOG_DEBUG, "\"%s\" not implemented", opcode);
+ return 0;
+
+ }
+
+ /* Next candidate handler */
+ current++;
+
+ } /* end opcode search */
+
+ /* Ignore any unknown instructions */
+ return 0;
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/instructions.h
----------------------------------------------------------------------
diff --git a/src/guaclog/instructions.h b/src/guaclog/instructions.h
new file mode 100644
index 0000000..0c901f5
--- /dev/null
+++ b/src/guaclog/instructions.h
@@ -0,0 +1,108 @@
+/*
+ * 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 GUACLOG_INSTRUCTIONS_H
+#define GUACLOG_INSTRUCTIONS_H
+
+#include "config.h"
+#include "state.h"
+
+/**
+ * A callback function which, when invoked, handles a particular Guacamole
+ * instruction. The opcode of the instruction is implied (as it is expected
+ * that there will be a 1:1 mapping of opcode to callback function), while the
+ * arguments for that instruction are included in the parameters given to the
+ * callback.
+ *
+ * @param state
+ * The current state of the Guacamole input log interpreter.
+ *
+ * @param argc
+ * The number of arguments (excluding opcode) passed to the instruction
+ * being handled by the callback.
+ *
+ * @param argv
+ * All arguments (excluding opcode) associated with the instruction being
+ * handled by the callback.
+ *
+ * @return
+ * Zero if the instruction was handled successfully, non-zero if an error
+ * occurs.
+ */
+typedef int guaclog_instruction_handler(guaclog_state* state,
+ int argc, char** argv);
+
+/**
+ * Mapping of instruction opcode to corresponding handler function.
+ */
+typedef struct guaclog_instruction_handler_mapping {
+
+ /**
+ * The opcode of the instruction that the associated handler function
+ * should be invoked for.
+ */
+ const char* opcode;
+
+ /**
+ * The handler function to invoke whenever an instruction having the
+ * associated opcode is parsed.
+ */
+ guaclog_instruction_handler* handler;
+
+} guaclog_instruction_handler_mapping;
+
+/**
+ * Array of all opcode/handler mappings for all supported opcodes, terminated
+ * by an entry with a NULL opcode. All opcodes not listed here can be safely
+ * ignored.
+ */
+extern guaclog_instruction_handler_mapping guaclog_instruction_handler_map[];
+
+/**
+ * Handles the instruction having the given opcode and arguments, updating
+ * the state of the interpreter accordingly.
+ *
+ * @param state
+ * The current state of the Guacamole input log interpreter.
+ *
+ * @param opcode
+ * The opcode of the instruction being handled.
+ *
+ * @param argc
+ * The number of arguments (excluding opcode) passed to the instruction
+ * being handled by the callback.
+ *
+ * @param argv
+ * All arguments (excluding opcode) associated with the instruction being
+ * handled by the callback.
+ *
+ * @return
+ * Zero if the instruction was handled successfully, non-zero if an error
+ * occurs.
+ */
+int guaclog_handle_instruction(guaclog_state* state,
+ const char* opcode, int argc, char** argv);
+
+/**
+ * Handler for the Guacamole "key" instruction.
+ */
+guaclog_instruction_handler guaclog_handle_key;
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/interpret.c
----------------------------------------------------------------------
diff --git a/src/guaclog/interpret.c b/src/guaclog/interpret.c
new file mode 100644
index 0000000..d996c24
--- /dev/null
+++ b/src/guaclog/interpret.c
@@ -0,0 +1,152 @@
+/*
+ * 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 "instructions.h"
+#include "log.h"
+#include "state.h"
+
+#include <guacamole/client.h>
+#include <guacamole/error.h>
+#include <guacamole/parser.h>
+#include <guacamole/socket.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+/**
+ * Reads and handles all Guacamole instructions from the given guac_socket
+ * until end-of-stream is reached.
+ *
+ * @param state
+ * The current state of the Guacamole input log interpreter.
+ *
+ * @param path
+ * The name of the file being parsed (for logging purposes). This file
+ * must already be open and available through the given socket.
+ *
+ * @param socket
+ * The guac_socket through which instructions should be read.
+ *
+ * @return
+ * Zero on success, non-zero if parsing of Guacamole protocol data through
+ * the given socket fails.
+ */
+static int guaclog_read_instructions(guaclog_state* state,
+ const char* path, guac_socket* socket) {
+
+ /* Obtain Guacamole protocol parser */
+ guac_parser* parser = guac_parser_alloc();
+ if (parser == NULL)
+ return 1;
+
+ /* Continuously read and handle all instructions */
+ while (!guac_parser_read(parser, socket, -1)) {
+ guaclog_handle_instruction(state, parser->opcode,
+ parser->argc, parser->argv);
+ }
+
+ /* Fail on read/parse error */
+ if (guac_error != GUAC_STATUS_CLOSED) {
+ guaclog_log(GUAC_LOG_ERROR, "%s: %s",
+ path, guac_status_string(guac_error));
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Parse complete */
+ guac_parser_free(parser);
+ return 0;
+
+}
+
+int guaclog_interpret(const char* path, const char* out_path, bool force) {
+
+ /* Open input file */
+ int fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, strerror(errno));
+ return 1;
+ }
+
+ /* Lock entire input file for reading by the current process */
+ struct flock file_lock = {
+ .l_type = F_RDLCK,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 0,
+ .l_pid = getpid()
+ };
+
+ /* Abort if file cannot be locked for reading */
+ if (!force && fcntl(fd, F_SETLK, &file_lock) == -1) {
+
+ /* Warn if lock cannot be acquired */
+ if (errno == EACCES || errno == EAGAIN)
+ guaclog_log(GUAC_LOG_WARNING, "Refusing to interpret log of "
+ "in-progress session \"%s\" (specify the -f option to "
+ "override this behavior).", path);
+
+ /* Log an error if locking fails in an unexpected way */
+ else
+ guaclog_log(GUAC_LOG_ERROR, "Cannot lock \"%s\" for reading: %s",
+ path, strerror(errno));
+
+ close(fd);
+ return 1;
+ }
+
+ /* Allocate input state for interpreting process */
+ guaclog_state* state = guaclog_state_alloc(out_path);
+ if (state == NULL) {
+ close(fd);
+ return 1;
+ }
+
+ /* Obtain guac_socket wrapping file descriptor */
+ guac_socket* socket = guac_socket_open(fd);
+ if (socket == NULL) {
+ guaclog_log(GUAC_LOG_ERROR, "%s: %s", path,
+ guac_status_string(guac_error));
+ close(fd);
+ guaclog_state_free(state);
+ return 1;
+ }
+
+ guaclog_log(GUAC_LOG_INFO, "Writing input events from \"%s\" "
+ "to \"%s\" ...", path, out_path);
+
+ /* Attempt to read all instructions in the file */
+ if (guaclog_read_instructions(state, path, socket)) {
+ guac_socket_free(socket);
+ guaclog_state_free(state);
+ return 1;
+ }
+
+ /* Close input and finish interpreting process */
+ guac_socket_free(socket);
+ return guaclog_state_free(state);
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/interpret.h
----------------------------------------------------------------------
diff --git a/src/guaclog/interpret.h b/src/guaclog/interpret.h
new file mode 100644
index 0000000..c65764e
--- /dev/null
+++ b/src/guaclog/interpret.h
@@ -0,0 +1,51 @@
+/*
+ * 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 GUACLOG_INTERPRET_H
+#define GUACLOG_INTERPRET_H
+
+#include "config.h"
+
+#include <stdbool.h>
+
+/**
+ * Interprets all input events within the given Guacamole protocol dump,
+ * producing a human-readable log of those input events. A read lock will be
+ * acquired on the input file to ensure that in-progress logs are not
+ * interpreted. This behavior can be overridden by specifying true for the
+ * force parameter.
+ *
+ * @param path
+ * The path to the file containing the raw Guacamole protocol dump.
+ *
+ * @param out_path
+ * The full path to the file in which interpreted log should be written.
+ *
+ * @param force
+ * Interpret even if the input file appears to be an in-progress log (has
+ * an associated lock).
+ *
+ * @return
+ * Zero on success, non-zero if an error prevented successful
+ * interpretation of the log.
+ */
+int guaclog_interpret(const char* path, const char* out_path, bool force);
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/log.c
----------------------------------------------------------------------
diff --git a/src/guaclog/log.c b/src/guaclog/log.c
new file mode 100644
index 0000000..e99abac
--- /dev/null
+++ b/src/guaclog/log.c
@@ -0,0 +1,85 @@
+/*
+ * 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 "guaclog.h"
+#include "log.h"
+
+#include <guacamole/client.h>
+#include <guacamole/error.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int guaclog_log_level = GUACLOG_DEFAULT_LOG_LEVEL;
+
+void vguaclog_log(guac_client_log_level level, const char* format,
+ va_list args) {
+
+ const char* priority_name;
+ char message[2048];
+
+ /* Don't bother if the log level is too high */
+ if (level > guaclog_log_level)
+ return;
+
+ /* Copy log message into buffer */
+ vsnprintf(message, sizeof(message), format, args);
+
+ /* Convert log level to human-readable name */
+ switch (level) {
+
+ /* Error log level */
+ case GUAC_LOG_ERROR:
+ priority_name = "ERROR";
+ break;
+
+ /* Warning log level */
+ case GUAC_LOG_WARNING:
+ priority_name = "WARNING";
+ break;
+
+ /* Informational log level */
+ case GUAC_LOG_INFO:
+ priority_name = "INFO";
+ break;
+
+ /* Debug log level */
+ case GUAC_LOG_DEBUG:
+ priority_name = "DEBUG";
+ break;
+
+ /* Any unknown/undefined log level */
+ default:
+ priority_name = "UNKNOWN";
+ break;
+ }
+
+ /* Log to STDERR */
+ fprintf(stderr, GUACLOG_LOG_NAME ": %s: %s\n", priority_name, message);
+
+}
+
+void guaclog_log(guac_client_log_level level, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ vguaclog_log(level, format, args);
+ va_end(args);
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/log.h
----------------------------------------------------------------------
diff --git a/src/guaclog/log.h b/src/guaclog/log.h
new file mode 100644
index 0000000..bcf90a1
--- /dev/null
+++ b/src/guaclog/log.h
@@ -0,0 +1,73 @@
+/*
+ * 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 GUACLOG_LOG_H
+#define GUACLOG_LOG_H
+
+#include "config.h"
+
+#include <guacamole/client.h>
+
+#include <stdarg.h>
+
+/**
+ * The maximum level at which to log messages. All other messages will be
+ * dropped.
+ */
+extern int guaclog_log_level;
+
+/**
+ * The string to prepend to all log messages.
+ */
+#define GUACLOG_LOG_NAME "guaclog"
+
+/**
+ * Writes a message to guaclog's logs. This function takes a format and
+ * va_list, similar to vprintf.
+ *
+ * @param level
+ * The level at which to log this message.
+ *
+ * @param format
+ * A printf-style format string to log.
+ *
+ * @param args
+ * The va_list containing the arguments to be used when filling the format
+ * string for printing.
+ */
+void vguaclog_log(guac_client_log_level level, const char* format,
+ va_list args);
+
+/**
+ * Writes a message to guaclog's logs. This function accepts parameters
+ * identically to printf.
+ *
+ * @param level
+ * The level at which to log this message.
+ *
+ * @param format
+ * A printf-style format string to log.
+ *
+ * @param ...
+ * Arguments to use when filling the format string for printing.
+ */
+void guaclog_log(guac_client_log_level level, const char* format, ...);
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/man/guaclog.1.in
----------------------------------------------------------------------
diff --git a/src/guaclog/man/guaclog.1.in b/src/guaclog/man/guaclog.1.in
new file mode 100644
index 0000000..11896d5
--- /dev/null
+++ b/src/guaclog/man/guaclog.1.in
@@ -0,0 +1,60 @@
+.\"
+.\" 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.
+.\"
+.TH guaclog 1 "26 Jan 2018" "version @PACKAGE_VERSION@" "Apache Guacamole"
+.
+.SH NAME
+guaclog \- Guacamole input log interpreter
+.
+.SH SYNOPSIS
+.B guaclog
+[\fB-f\fR]
+[\fIFILE\fR]...
+.
+.SH DESCRIPTION
+.B guaclog
+is an interpreter which accepts Guacamole protocol dumps, such as those saved
+when input logging is enabled on a Guacamole connection, writing human-readable
+text logs as output.
+.B guaclog
+is essentially an implementation of a Guacamole client which accepts
+its input from files instead of a network connection, however unlike
+.B guacenc
+it only handles instructions related to user input.
+.P
+Each \fIFILE\fR specified will be translated into a new human-readable text
+file named \fIFILE\fR.txt. Existing files will not be overwritten; the
+interpreting process for any input file will be aborted if it would result in
+overwriting an existing file.
+.P
+Guacamole acquires a write lock on input logs as they are being written. By
+default,
+.B guaclog
+will check whether the each input file is locked and will refuse to read and
+interpret an input file if it appears to be an in-progress log. This behavior
+can be overridden by specifying the \fB-f\fR option. Interpreting an
+in-progress log will still work; the resulting human-readable text file will
+simply cover the user's session only up to the current point in time.
+.
+.SH OPTIONS
+.TP
+\fB-f\fR
+Overrides the default behavior of
+.B guaclog
+such that input files will be interpreted even if they appear to be logs of
+in-progress Guacamole sessions.
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/state.c
----------------------------------------------------------------------
diff --git a/src/guaclog/state.c b/src/guaclog/state.c
new file mode 100644
index 0000000..6167bd3
--- /dev/null
+++ b/src/guaclog/state.c
@@ -0,0 +1,97 @@
+/*
+ * 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 "log.h"
+#include "state.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+guaclog_state* guaclog_state_alloc(const char* path) {
+
+ /* Open output file */
+ int fd = open(path, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ guaclog_log(GUAC_LOG_ERROR, "Failed to open output file \"%s\": %s",
+ path, strerror(errno));
+ goto fail_output_fd;
+ }
+
+ /* Create stream for output file */
+ FILE* output = fdopen(fd, "wb");
+ if (output == NULL) {
+ guaclog_log(GUAC_LOG_ERROR, "Failed to allocate stream for output "
+ "file \"%s\": %s", path, strerror(errno));
+ goto fail_output_file;
+ }
+
+ /* Allocate state */
+ guaclog_state* state = (guaclog_state*) calloc(1, sizeof(guaclog_state));
+ if (state == NULL) {
+ goto fail_state;
+ }
+
+ /* Associate state with output file */
+ state->output = output;
+
+ return state;
+
+ /* Free all allocated data in case of failure */
+fail_state:
+ fclose(output);
+
+fail_output_file:
+ close(fd);
+
+fail_output_fd:
+ return NULL;
+
+}
+
+int guaclog_state_free(guaclog_state* state) {
+
+ /* Ignore NULL state */
+ if (state == NULL)
+ return 0;
+
+ /* Close output file */
+ fclose(state->output);
+
+ free(state);
+ return 0;
+
+}
+
+int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) {
+
+ /* STUB */
+ fprintf(state->output, "STUB: keysym=0x%X, pressed=%s\n",
+ keysym, pressed ? "true" : "false");
+
+ return 0;
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/ebc731aa/src/guaclog/state.h
----------------------------------------------------------------------
diff --git a/src/guaclog/state.h b/src/guaclog/state.h
new file mode 100644
index 0000000..5891cb5
--- /dev/null
+++ b/src/guaclog/state.h
@@ -0,0 +1,89 @@
+/*
+ * 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 GUACLOG_STATE_H
+#define GUACLOG_STATE_H
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+
+/**
+ * The current state of the Guacamole input log interpreter.
+ */
+typedef struct guaclog_state {
+
+ /**
+ * Output file stream.
+ */
+ FILE* output;
+
+} guaclog_state;
+
+/**
+ * Allocates a new state structure for the Guacamole input log interpreter.
+ * This structure serves as the representation of interpreter state as
+ * input-related instructions are read and handled.
+ *
+ * @param path
+ * The full path to the file in which interpreted, human-readable should be
+ * written.
+ *
+ * @return
+ * The newly-allocated Guacamole input log interpreter state, or NULL if
+ * the state could not be allocated.
+ */
+guaclog_state* guaclog_state_alloc(const char* path);
+
+/**
+ * Frees all memory associated with the given Guacamole input log interpreter
+ * state, and finishes any remaining interpreting process. If the given state
+ * is NULL, this function has no effect.
+ *
+ * @param state
+ * The Guacamole input log interpreter state to free, which may be NULL.
+ *
+ * @return
+ * Zero if the interpreting process completed successfully, non-zero
+ * otherwise.
+ */
+int guaclog_state_free(guaclog_state* state);
+
+/**
+ * Updates the given Guacamole input log interpreter state, marking the given
+ * key as pressed or released.
+ *
+ * @param state
+ * The Guacamole input log interpreter state being updated.
+ *
+ * @param keysym
+ * The X11 keysym of the key being pressed or released.
+ *
+ * @param pressed
+ * true if the key is being pressed, false if the key is being released.
+ *
+ * @return
+ * Zero if the interpreter state was updated successfully, non-zero
+ * otherwise.
+ */
+int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed);
+
+#endif
+
[02/11] guacamole-server git commit: GUACAMOLE-313: Continuously
track key press/release.
Posted by vn...@apache.org.
GUACAMOLE-313: Continuously track key press/release.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/d39757b4
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/d39757b4
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/d39757b4
Branch: refs/heads/master
Commit: d39757b4dc09ff7f255761ca9c2f18e105be626f
Parents: ebc731a
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Nov 26 17:24:49 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:14 2018 -0800
----------------------------------------------------------------------
src/guaclog/state.c | 106 +++++++++++++++++++++++++++++++++++++++++++++--
src/guaclog/state.h | 35 ++++++++++++++++
2 files changed, 138 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/d39757b4/src/guaclog/state.c
----------------------------------------------------------------------
diff --git a/src/guaclog/state.c b/src/guaclog/state.c
index 6167bd3..cc6f763 100644
--- a/src/guaclog/state.c
+++ b/src/guaclog/state.c
@@ -57,6 +57,9 @@ guaclog_state* guaclog_state_alloc(const char* path) {
/* Associate state with output file */
state->output = output;
+ /* No keys are initially tracked */
+ state->active_keys = 0;
+
return state;
/* Free all allocated data in case of failure */
@@ -85,11 +88,108 @@ int guaclog_state_free(guaclog_state* state) {
}
+/**
+ * Adds the given key state to the array of tracked keys. If the key is already
+ * being tracked, its corresponding entry within the array of tracked keys is
+ * updated, and the number of tracked keys remains the same. If the key is not
+ * already being tracked, it is added to the end of the array of tracked keys
+ * providing there is space available, and the number of tracked keys is
+ * updated. Failures to add keys will be automatically logged.
+ *
+ * @param state
+ * The Guacamole input log interpreter state being updated.
+ *
+ * @param keysym
+ * The X11 keysym of the key being pressed or released.
+ *
+ * @param pressed
+ * true if the key is being pressed, false if the key is being released.
+ *
+ * @return
+ * Zero if the key state was successfully added, non-zero otherwise.
+ */
+static int guaclog_state_add_key(guaclog_state* state, int keysym, bool pressed) {
+
+ int i;
+
+ /* Update existing key, if already tracked */
+ for (i = 0; i < state->active_keys; i++) {
+ guaclog_key_state* key = &state->key_states[i];
+ if (key->keysym == keysym) {
+ key->pressed = pressed;
+ return 0;
+ }
+ }
+
+ /* If not already tracked, we need space to add it */
+ if (state->active_keys == GUACLOG_MAX_KEYS) {
+ guaclog_log(GUAC_LOG_WARNING, "Unable to log key 0x%X: Too many "
+ "active keys.", keysym);
+ return 1;
+ }
+
+ /* Add key to state */
+ guaclog_key_state* key = &state->key_states[state->active_keys++];
+ key->keysym = keysym;
+ key->pressed = pressed;
+ return 0;
+
+}
+
+/**
+ * Removes released keys from the end of the array of tracked keys, such that
+ * the last key in the array is a pressed key. This function should be invoked
+ * after changes have been made to the interpreter state, to ensure that the
+ * array of tracked keys does not grow longer than necessary.
+ *
+ * @param state
+ * The Guacamole input log interpreter state to trim.
+ */
+static void guaclog_state_trim_keys(guaclog_state* state) {
+
+ int i;
+
+ /* Reset active_keys to contain only up to the last pressed key */
+ for (i = state->active_keys - 1; i >= 0; i--) {
+ guaclog_key_state* key = &state->key_states[i];
+ if (key->pressed) {
+ state->active_keys = i + 1;
+ return;
+ }
+ }
+
+ /* No keys are active */
+ state->active_keys = 0;
+
+}
+
int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) {
- /* STUB */
- fprintf(state->output, "STUB: keysym=0x%X, pressed=%s\n",
- keysym, pressed ? "true" : "false");
+ int i;
+
+ /* Update tracked keysysm state */
+ guaclog_state_add_key(state, keysym, pressed);
+ guaclog_state_trim_keys(state);
+
+ /* Output new log entries only when keys are pressed */
+ if (pressed) {
+
+ /* STUB: Output raw hex log entry */
+ for (i = 0; i < state->active_keys; i++) {
+
+ if (i != 0)
+ fprintf(state->output, " ");
+
+ guaclog_key_state* key = &state->key_states[i];
+ fprintf(state->output, "0x%X:%s", key->keysym,
+ key->pressed ? "*" : " ");
+
+ }
+
+ /* Terminate log entry with newline */
+ fprintf(state->output, "\n");
+
+ }
return 0;
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/d39757b4/src/guaclog/state.h
----------------------------------------------------------------------
diff --git a/src/guaclog/state.h b/src/guaclog/state.h
index 5891cb5..0dd2f2f 100644
--- a/src/guaclog/state.h
+++ b/src/guaclog/state.h
@@ -26,6 +26,29 @@
#include <stdio.h>
/**
+ * The maximum number of keys which may be tracked at any one time before
+ * newly-pressed keys are ignored.
+ */
+#define GUACLOG_MAX_KEYS 256
+
+/**
+ * The current state of a single key.
+ */
+typedef struct guaclog_key_state {
+
+ /**
+ * The X11 keysym of the key.
+ */
+ int keysym;
+
+ /**
+ * Whether the key is currently pressed (true) or released (false).
+ */
+ bool pressed;
+
+} guaclog_key_state;
+
+/**
* The current state of the Guacamole input log interpreter.
*/
typedef struct guaclog_state {
@@ -35,6 +58,18 @@ typedef struct guaclog_state {
*/
FILE* output;
+ /**
+ * The number of keys currently being tracked within the key_states array.
+ */
+ int active_keys;
+
+ /**
+ * Array of all keys currently being tracked. A key is added to the array
+ * when it is pressed for the first time. Released keys at the end of the
+ * array are automatically removed from tracking.
+ */
+ guaclog_key_state key_states[GUACLOG_MAX_KEYS];
+
} guaclog_state;
/**
[08/11] guacamole-server git commit: GUACAMOLE-313: Add missing
keysyms. Track modifier keys only.
Posted by vn...@apache.org.
GUACAMOLE-313: Add missing keysyms. Track modifier keys only.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/5e5f1fcb
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/5e5f1fcb
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/5e5f1fcb
Branch: refs/heads/master
Commit: 5e5f1fcb3e0d5d2fb2c1c679aacd337142f47393
Parents: 5b612b8
Author: Michael Jumper <mj...@apache.org>
Authored: Fri Dec 8 12:56:27 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guaclog/keydef.c | 58 +++++++++++++++++++++++++++++++++++------------
src/guaclog/keydef.h | 8 +++++++
src/guaclog/state.c | 24 ++++++++++++--------
3 files changed, 66 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5e5f1fcb/src/guaclog/keydef.c
----------------------------------------------------------------------
diff --git a/src/guaclog/keydef.c b/src/guaclog/keydef.c
index 9616500..427e3ca 100644
--- a/src/guaclog/keydef.c
+++ b/src/guaclog/keydef.c
@@ -30,24 +30,53 @@
* All known keys.
*/
const guaclog_keydef known_keys[] = {
- { 0xFE03, "AltGr" },
+ { 0xFE03, "AltGr", "", true },
{ 0xFF08, "Backspace" },
- { 0xFF09, "Tab", "<Tab>" },
+ { 0xFF09, "Tab" },
{ 0xFF0B, "Clear" },
{ 0xFF0D, "Return", "\n" },
{ 0xFF13, "Pause" },
+ { 0xFF14, "Scroll" },
+ { 0xFF15, "SysReq" },
{ 0xFF1B, "Escape" },
+ { 0xFF50, "Home" },
{ 0xFF51, "Left" },
{ 0xFF52, "Up" },
{ 0xFF53, "Right" },
{ 0xFF54, "Down" },
{ 0xFF55, "Page Up" },
{ 0xFF56, "Page Down" },
+ { 0xFF57, "End" },
{ 0xFF63, "Insert" },
{ 0xFF65, "Undo" },
{ 0xFF6A, "Help" },
+ { 0xFF7F, "Num" },
{ 0xFF80, "Space", " " },
{ 0xFF8D, "Enter", "\n" },
+ { 0xFF95, "Home" },
+ { 0xFF96, "Left" },
+ { 0xFF97, "Up" },
+ { 0xFF98, "Right" },
+ { 0xFF99, "Down" },
+ { 0xFF9A, "Page Up" },
+ { 0xFF9B, "Page Down" },
+ { 0xFF9C, "End" },
+ { 0xFF9E, "Insert" },
+ { 0xFFAA, "*", "*" },
+ { 0xFFAB, "+", "+" },
+ { 0xFFAD, "-", "-" },
+ { 0xFFAE, ".", "." },
+ { 0xFFAF, "/", "/" },
+ { 0xFFB0, "0", "0" },
+ { 0xFFB1, "1", "1" },
+ { 0xFFB2, "2", "2" },
+ { 0xFFB3, "3", "3" },
+ { 0xFFB4, "4", "4" },
+ { 0xFFB5, "5", "5" },
+ { 0xFFB6, "6", "6" },
+ { 0xFFB7, "7", "7" },
+ { 0xFFB8, "8", "8" },
+ { 0xFFB9, "9", "9" },
{ 0xFFBE, "F1" },
{ 0xFFBF, "F2" },
{ 0xFFC0, "F3" },
@@ -72,20 +101,19 @@ const guaclog_keydef known_keys[] = {
{ 0xFFD3, "F22" },
{ 0xFFD4, "F23" },
{ 0xFFD5, "F24" },
- { 0xFFE1, "Shift", "" },
- { 0xFFE2, "Shift", "" },
- { 0xFFE3, "Ctrl" },
- { 0xFFE4, "Ctrl" },
+ { 0xFFE1, "Shift", "", true },
+ { 0xFFE2, "Shift", "", true },
+ { 0xFFE3, "Ctrl", NULL, true },
+ { 0xFFE4, "Ctrl", NULL, true },
{ 0xFFE5, "Caps" },
- { 0xFFE7, "Meta" },
- { 0xFFE8, "Meta" },
- { 0xFFE9, "Alt" },
- { 0xFFEA, "Alt" },
- { 0xFFEB, "Super" },
- { 0xFFEB, "Win" },
- { 0xFFEC, "Super" },
- { 0xFFED, "Hyper" },
- { 0xFFEE, "Hyper" },
+ { 0xFFE7, "Meta", NULL, true },
+ { 0xFFE8, "Meta", NULL, true },
+ { 0xFFE9, "Alt", NULL, true },
+ { 0xFFEA, "Alt", NULL, true },
+ { 0xFFEB, "Super", NULL, true },
+ { 0xFFEC, "Super", NULL, true },
+ { 0xFFED, "Hyper", NULL, true },
+ { 0xFFEE, "Hyper", NULL, true },
{ 0xFFFF, "Delete" }
};
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5e5f1fcb/src/guaclog/keydef.h
----------------------------------------------------------------------
diff --git a/src/guaclog/keydef.h b/src/guaclog/keydef.h
index d0b2720..147fe20 100644
--- a/src/guaclog/keydef.h
+++ b/src/guaclog/keydef.h
@@ -22,6 +22,8 @@
#include "config.h"
+#include <stdbool.h>
+
/**
* A mapping of X11 keysym to its corresponding human-readable name.
*/
@@ -44,6 +46,12 @@ typedef struct guaclog_keydef {
*/
char* value;
+ /**
+ * Whether this key is a modifier which may affect the interpretation of
+ * other keys, and thus should be tracked as it is held down.
+ */
+ bool modifier;
+
} guaclog_keydef;
/**
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5e5f1fcb/src/guaclog/state.c
----------------------------------------------------------------------
diff --git a/src/guaclog/state.c b/src/guaclog/state.c
index 4965985..5e18708 100644
--- a/src/guaclog/state.c
+++ b/src/guaclog/state.c
@@ -217,14 +217,16 @@ int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) {
if (keydef == NULL)
return 0;
- /* Update tracked key state */
- if (guaclog_state_add_key(state, keydef, pressed))
- guaclog_keydef_free(keydef);
- else
- guaclog_state_trim_keys(state);
+ /* Update tracked key state for modifiers */
+ if (keydef->modifier) {
+ if (guaclog_state_add_key(state, keydef, pressed))
+ guaclog_keydef_free(keydef);
+ else
+ guaclog_state_trim_keys(state);
+ }
/* Output key states only for printable keys */
- if (pressed && keydef->value != NULL) {
+ else if (pressed) {
if (guaclog_state_is_shortcut(state)) {
@@ -244,13 +246,17 @@ int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) {
}
- fprintf(state->output, ">");
+ fprintf(state->output, "%s>", keydef->value);
}
/* Print the key itself */
- else
- fprintf(state->output, "%s", keydef->value);
+ else {
+ if (keydef->value != NULL)
+ fprintf(state->output, "%s", keydef->value);
+ else
+ fprintf(state->output, "<%s>", keydef->name);
+ }
}
[09/11] guacamole-server git commit: GUACAMOLE-313: Include unknown
keys within log.
Posted by vn...@apache.org.
GUACAMOLE-313: Include unknown keys within log.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/b7257d9a
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/b7257d9a
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/b7257d9a
Branch: refs/heads/master
Commit: b7257d9ae45287a8a9e1b80920c677d75863698c
Parents: 5e5f1fc
Author: Michael Jumper <mj...@apache.org>
Authored: Fri Dec 8 13:10:32 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guaclog/keydef.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b7257d9a/src/guaclog/keydef.c
----------------------------------------------------------------------
diff --git a/src/guaclog/keydef.c b/src/guaclog/keydef.c
index 427e3ca..6b979fa 100644
--- a/src/guaclog/keydef.c
+++ b/src/guaclog/keydef.c
@@ -21,6 +21,7 @@
#include "keydef.h"
#include "log.h"
+#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -169,6 +170,36 @@ static guaclog_keydef* guaclog_get_known_key(int keysym) {
}
/**
+ * Returns a statically-allocated guaclog_keydef representing an unknown key,
+ * deriving the name of the key from the hexadecimal value of the keysym.
+ *
+ * @param keysym
+ * The X11 keysym of the key.
+ *
+ * @return
+ * A statically-allocated guaclog_keydef representing the key associated
+ * with the given keysym.
+ */
+static guaclog_keydef* guaclog_get_unknown_key(int keysym) {
+
+ static char unknown_keydef_name[64];
+ static guaclog_keydef unknown_keydef;
+
+ /* Write keysym as hex */
+ int size = snprintf(unknown_keydef_name, sizeof(unknown_keydef_name),
+ "0x%X", keysym);
+
+ /* Hex string is guaranteed to fit within the provided 64 bytes */
+ assert(size < sizeof(unknown_keydef_name));
+
+ /* Return static key definition */
+ unknown_keydef.keysym = keysym;
+ unknown_keydef.name = unknown_keydef_name;
+ return &unknown_keydef;
+
+}
+
+/**
* Returns a statically-allocated guaclog_keydef representing the key
* associated with the given keysym, deriving the name and value of the key
* using its corresponding Unicode character.
@@ -286,7 +317,7 @@ guaclog_keydef* guaclog_keydef_alloc(int keysym) {
/* Key not known */
guaclog_log(GUAC_LOG_DEBUG, "Definition not found for key 0x%X.", keysym);
- return NULL;
+ return guaclog_copy_key(guaclog_get_unknown_key(keysym));
}
[06/11] guacamole-server git commit: GUACAMOLE-313: Use binary search
to find human-readable names for known keys.
Posted by vn...@apache.org.
GUACAMOLE-313: Use binary search to find human-readable names for known keys.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/3633af5e
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/3633af5e
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/3633af5e
Branch: refs/heads/master
Commit: 3633af5e418876932ab086b910ca5a43df425cbe
Parents: df29735
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Nov 26 18:54:59 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guaclog/key-name.c | 99 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/3633af5e/src/guaclog/key-name.c
----------------------------------------------------------------------
diff --git a/src/guaclog/key-name.c b/src/guaclog/key-name.c
index ffb622d..f3485a2 100644
--- a/src/guaclog/key-name.c
+++ b/src/guaclog/key-name.c
@@ -22,12 +22,107 @@
#include "log.h"
#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * A mapping of X11 keysym to its corresponding human-readable name.
+ */
+typedef struct guaclog_known_key {
+
+ /**
+ * The X11 keysym of the key.
+ */
+ const int keysym;
+
+ /**
+ * A human-readable name for the key.
+ */
+ const char* name;
+
+} guaclog_known_key;
+
+/**
+ * All known keys.
+ */
+const guaclog_known_key known_keys[] = {
+ { 0xFFE1, "Shift" }
+};
+
+/**
+ * Comparator for the standard bsearch() function which compares an integer
+ * keysym against the keysym associated with a guaclog_known_key.
+ *
+ * @param key
+ * The key value being compared against the member. This MUST be the
+ * keysym value, passed through typecasting to an intptr_t (NOT a pointer
+ * to the int itself).
+ *
+ * @param member
+ * The member within the known_keys array being compared against the given
+ * key.
+ *
+ * @return
+ * Zero if the given keysym is equal to that of the given member, a
+ * positive value if the given keysym is greater than that of the given
+ * member, or a negative value if the given keysym is less than that of the
+ * given member.
+ */
+static int guaclog_known_key_bsearch_compare(const void* key,
+ const void* member) {
+
+ int keysym = (int) ((intptr_t) key);
+ guaclog_known_key* current = (guaclog_known_key*) member;
+
+ /* Compare given keysym to keysym of current member */
+ return keysym - current->keysym;
+
+}
+
+/**
+ * Searches through the known_keys array of known keys for the name of the key
+ * having the given keysym. If found, the name of the keysym is copied into the
+ * given buffer, which must be at least GUACLOG_MAX_KEY_NAME_LENGTH bytes long.
+ *
+ * @param key_name
+ * The buffer to copy the key name into, which must be at least
+ * GUACLOG_MAX_KEY_NAME_LENGTH.
+ *
+ * @param keysym
+ * The X11 keysym of the key whose name should be stored in
+ * key_name.
+ *
+ * @return
+ * The length of the name, in bytes, excluding null terminator, or zero if
+ * the key could not be found.
+ */
+static int guaclog_locate_key_name(char* key_name, int keysym) {
+
+ /* Search through known keys for given keysym */
+ guaclog_known_key* found = bsearch((void*) ((intptr_t) keysym),
+ known_keys, sizeof(known_keys) / sizeof(known_keys[0]),
+ sizeof(known_keys[0]), guaclog_known_key_bsearch_compare);
+
+ /* If found, format name and return length of result */
+ if (found != NULL)
+ return snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH,
+ "[ %s ]", found->name);
+
+ /* Key not found */
+ return 0;
+
+}
int guaclog_key_name(char* key_name, int keysym) {
+ int name_length;
+
+ /* Search for name within list of known keys */
+ name_length = guaclog_locate_key_name(key_name, keysym);
+
/* Fallback to using hex keysym as name */
- int name_length = snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH,
- "0x%X", keysym);
+ if (name_length == 0)
+ name_length = snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH,
+ "0x%X", keysym);
/* Truncate name if necessary */
if (name_length >= GUACLOG_MAX_KEY_NAME_LENGTH) {
[10/11] guacamole-server git commit: GUACAMOLE-313: Note that
guacenc/guaclog are related.
Posted by vn...@apache.org.
GUACAMOLE-313: Note that guacenc/guaclog are related.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/fdd17e30
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/fdd17e30
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/fdd17e30
Branch: refs/heads/master
Commit: fdd17e30422dd91337d044ecff02db52aab32691
Parents: c0b2871
Author: Michael Jumper <mj...@apache.org>
Authored: Fri Jan 26 16:16:40 2018 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guacenc/man/guacenc.1.in | 5 ++++-
src/guaclog/man/guaclog.1.in | 4 +++-
2 files changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/fdd17e30/src/guacenc/man/guacenc.1.in
----------------------------------------------------------------------
diff --git a/src/guacenc/man/guacenc.1.in b/src/guacenc/man/guacenc.1.in
index edb75f6..4f00787 100644
--- a/src/guacenc/man/guacenc.1.in
+++ b/src/guacenc/man/guacenc.1.in
@@ -16,7 +16,7 @@
.\" specific language governing permissions and limitations
.\" under the License.
.\"
-.TH guacenc 1 "1 Jun 2017" "version @PACKAGE_VERSION@" "Apache Guacamole"
+.TH guacenc 1 "26 Jan 2018" "version @PACKAGE_VERSION@" "Apache Guacamole"
.
.SH NAME
guacenc \- Guacamole video encoder
@@ -75,3 +75,6 @@ Overrides the default behavior of
.B guacenc
such that input files will be encoded even if they appear to be recordings of
in-progress Guacamole sessions.
+.
+.SH SEE ALSO
+.BR guaclog (1)
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/fdd17e30/src/guaclog/man/guaclog.1.in
----------------------------------------------------------------------
diff --git a/src/guaclog/man/guaclog.1.in b/src/guaclog/man/guaclog.1.in
index e5dfa9d..de14559 100644
--- a/src/guaclog/man/guaclog.1.in
+++ b/src/guaclog/man/guaclog.1.in
@@ -94,4 +94,6 @@ would look like:
.PP
.RS 0
Hello WORLD!<Ctrl+a><Ctrl+c><Alt+Shift+Tab><Ctrl+v>
-
+.
+.SH SEE ALSO
+.BR guacenc (1)
[07/11] guacamole-server git commit: GUACAMOLE-313: Refactor guaclog
to produce simpler, greppable output.
Posted by vn...@apache.org.
GUACAMOLE-313: Refactor guaclog to produce simpler, greppable output.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/5b612b85
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/5b612b85
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/5b612b85
Branch: refs/heads/master
Commit: 5b612b856afc29073595d7ce450560b0bff65415
Parents: 86b09c8
Author: Michael Jumper <mj...@apache.org>
Authored: Wed Dec 6 21:25:58 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guaclog/Makefile.am | 4 +-
src/guaclog/key-name.c | 276 -------------------------------------------
src/guaclog/key-name.h | 50 --------
src/guaclog/keydef.c | 276 +++++++++++++++++++++++++++++++++++++++++++
src/guaclog/keydef.h | 73 ++++++++++++
src/guaclog/state.c | 111 ++++++++++++-----
src/guaclog/state.h | 5 +-
7 files changed, 434 insertions(+), 361 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/Makefile.am
----------------------------------------------------------------------
diff --git a/src/guaclog/Makefile.am b/src/guaclog/Makefile.am
index 5007708..6acced3 100644
--- a/src/guaclog/Makefile.am
+++ b/src/guaclog/Makefile.am
@@ -28,7 +28,7 @@ noinst_HEADERS = \
guaclog.h \
instructions.h \
interpret.h \
- key-name.h \
+ keydef.h \
log.h \
state.h
@@ -37,7 +37,7 @@ guaclog_SOURCES = \
instructions.c \
instruction-key.c \
interpret.c \
- key-name.c \
+ keydef.c \
log.c \
state.c
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/key-name.c
----------------------------------------------------------------------
diff --git a/src/guaclog/key-name.c b/src/guaclog/key-name.c
deleted file mode 100644
index 5ae73b5..0000000
--- a/src/guaclog/key-name.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * 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 "key-name.h"
-#include "log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/**
- * A mapping of X11 keysym to its corresponding human-readable name.
- */
-typedef struct guaclog_known_key {
-
- /**
- * The X11 keysym of the key.
- */
- const int keysym;
-
- /**
- * A human-readable name for the key.
- */
- const char* name;
-
-} guaclog_known_key;
-
-/**
- * All known keys.
- */
-const guaclog_known_key known_keys[] = {
- { 0x0020, "Space" },
- { 0xFE03, "AltGr" },
- { 0xFF08, "Backspace" },
- { 0xFF09, "Tab" },
- { 0xFF0B, "Clear" },
- { 0xFF0D, "Return" },
- { 0xFF13, "Pause" },
- { 0xFF1B, "Escape" },
- { 0xFF51, "Left" },
- { 0xFF52, "Up" },
- { 0xFF53, "Right" },
- { 0xFF54, "Down" },
- { 0xFF55, "Page Up" },
- { 0xFF56, "Page Down" },
- { 0xFF63, "Insert" },
- { 0xFF65, "Undo" },
- { 0xFF6A, "Help" },
- { 0xFF80, "Space" },
- { 0xFF8D, "Enter" },
- { 0xFFBD, "Equals" },
- { 0xFFBE, "F1" },
- { 0xFFBF, "F2" },
- { 0xFFC0, "F3" },
- { 0xFFC1, "F4" },
- { 0xFFC2, "F5" },
- { 0xFFC3, "F6" },
- { 0xFFC4, "F7" },
- { 0xFFC5, "F8" },
- { 0xFFC6, "F9" },
- { 0xFFC7, "F10" },
- { 0xFFC8, "F11" },
- { 0xFFC9, "F12" },
- { 0xFFCA, "F13" },
- { 0xFFCB, "F14" },
- { 0xFFCC, "F15" },
- { 0xFFCD, "F16" },
- { 0xFFCE, "F17" },
- { 0xFFCF, "F18" },
- { 0xFFD0, "F19" },
- { 0xFFD1, "F20" },
- { 0xFFD2, "F21" },
- { 0xFFD3, "F22" },
- { 0xFFD4, "F23" },
- { 0xFFD5, "F24" },
- { 0xFFE1, "Shift" },
- { 0xFFE2, "Shift" },
- { 0xFFE3, "Ctrl" },
- { 0xFFE4, "Ctrl" },
- { 0xFFE5, "Caps" },
- { 0xFFE7, "Meta" },
- { 0xFFE8, "Meta" },
- { 0xFFE9, "Alt" },
- { 0xFFEA, "Alt" },
- { 0xFFEB, "Super" },
- { 0xFFEB, "Win" },
- { 0xFFEC, "Super" },
- { 0xFFED, "Hyper" },
- { 0xFFEE, "Hyper" },
- { 0xFFFF, "Delete" }
-};
-
-/**
- * Comparator for the standard bsearch() function which compares an integer
- * keysym against the keysym associated with a guaclog_known_key.
- *
- * @param key
- * The key value being compared against the member. This MUST be the
- * keysym value, passed through typecasting to an intptr_t (NOT a pointer
- * to the int itself).
- *
- * @param member
- * The member within the known_keys array being compared against the given
- * key.
- *
- * @return
- * Zero if the given keysym is equal to that of the given member, a
- * positive value if the given keysym is greater than that of the given
- * member, or a negative value if the given keysym is less than that of the
- * given member.
- */
-static int guaclog_known_key_bsearch_compare(const void* key,
- const void* member) {
-
- int keysym = (int) ((intptr_t) key);
- guaclog_known_key* current = (guaclog_known_key*) member;
-
- /* Compare given keysym to keysym of current member */
- return keysym - current->keysym;
-
-}
-
-/**
- * Searches through the known_keys array of known keys for the name of the key
- * having the given keysym. If found, the name of the keysym is copied into the
- * given buffer, which must be at least GUACLOG_MAX_KEY_NAME_LENGTH bytes long.
- *
- * @param key_name
- * The buffer to copy the key name into, which must be at least
- * GUACLOG_MAX_KEY_NAME_LENGTH.
- *
- * @param keysym
- * The X11 keysym of the key whose name should be stored in
- * key_name.
- *
- * @return
- * The length of the name, in bytes, excluding null terminator, or zero if
- * the key could not be found.
- */
-static int guaclog_locate_key_name(char* key_name, int keysym) {
-
- /* Search through known keys for given keysym */
- guaclog_known_key* found = bsearch((void*) ((intptr_t) keysym),
- known_keys, sizeof(known_keys) / sizeof(known_keys[0]),
- sizeof(known_keys[0]), guaclog_known_key_bsearch_compare);
-
- /* If found, format name and return length of result */
- if (found != NULL)
- return snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH,
- "[ %s ]", found->name);
-
- /* Key not found */
- return 0;
-
-}
-
-/**
- * Produces a name for the key having the given keysym using its corresponding
- * Unicode character. If possible, the name of the keysym is copied into the
- * given buffer, which must be at least GUAC_MAX_KEY_NAME_LENGTH bytes long.
- *
- * @param key_name
- * The buffer to copy the key name into, which must be at least
- * GUACLOG_MAX_KEY_NAME_LENGTH.
- *
- * @param keysym
- * The X11 keysym of the key whose name should be stored in
- * key_name.
- *
- * @return
- * The length of the name, in bytes, excluding null terminator, or zero if
- * a readable name cannot be directly produced via Unicode alone.
- */
-static int guaclog_unicode_key_name(char* key_name, int keysym) {
-
- int i;
- int mask, bytes;
-
- /* Translate only if keysym maps to Unicode */
- if (keysym < 0x00 || (keysym > 0xFF && (keysym & 0xFFFF0000) != 0x01000000))
- return 0;
-
- /* Do not translate whitespace - it will be unreadable */
- if (keysym == 0x20)
- return 0;
-
- int codepoint = keysym & 0xFFFF;
-
- /* Determine size and initial byte mask */
- if (codepoint <= 0x007F) {
- mask = 0x00;
- bytes = 1;
- }
- else if (codepoint <= 0x7FF) {
- mask = 0xC0;
- bytes = 2;
- }
- else if (codepoint <= 0xFFFF) {
- mask = 0xE0;
- bytes = 3;
- }
- else if (codepoint <= 0x1FFFFF) {
- mask = 0xF0;
- bytes = 4;
- }
-
- /* Otherwise, invalid codepoint */
- else {
- *(key_name++) = '?';
- return 1;
- }
-
- /* Offset buffer by size */
- key_name += bytes;
-
- /* Add null terminator */
- *(key_name--) = '\0';
-
- /* Add trailing bytes, if any */
- for (i=1; i<bytes; i++) {
- *(key_name--) = 0x80 | (codepoint & 0x3F);
- codepoint >>= 6;
- }
-
- /* Set initial byte */
- *key_name = mask | codepoint;
-
- /* Done */
- return bytes;
-
-}
-
-int guaclog_key_name(char* key_name, int keysym) {
-
- int name_length;
-
- /* Attempt to translate straight into a Unicode character */
- name_length = guaclog_unicode_key_name(key_name, keysym);
-
- /* If not Unicode, search for name within list of known keys */
- if (name_length == 0)
- name_length = guaclog_locate_key_name(key_name, keysym);
-
- /* Fallback to using hex keysym as name */
- if (name_length == 0)
- name_length = snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH,
- "0x%X", keysym);
-
- /* Truncate name if necessary */
- if (name_length >= GUACLOG_MAX_KEY_NAME_LENGTH) {
- name_length = GUACLOG_MAX_KEY_NAME_LENGTH - 1;
- key_name[name_length] = '\0';
- guaclog_log(GUAC_LOG_DEBUG, "Name for key 0x%X was "
- "truncated.", keysym);
- }
-
- return name_length;
-
-}
-
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/key-name.h
----------------------------------------------------------------------
diff --git a/src/guaclog/key-name.h b/src/guaclog/key-name.h
deleted file mode 100644
index a033b36..0000000
--- a/src/guaclog/key-name.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 GUACLOG_KEY_NAME_H
-#define GUACLOG_KEY_NAME_H
-
-#include "config.h"
-
-/**
- * The maximum size of the name of any key, in bytes.
- */
-#define GUACLOG_MAX_KEY_NAME_LENGTH 64
-
-/**
- * Copies the name of the key having the given keysym into the given buffer,
- * which must be at least GUACLOG_MAX_KEY_NAME_LENGTH bytes long. This function
- * always succeeds, ultimately resorting to using the hex value of the keysym
- * as the name if no other human-readable name is known.
- *
- * @param key_name
- * The buffer to copy the key name into, which must be at least
- * GUACLOG_MAX_KEY_NAME_LENGTH.
- *
- * @param keysym
- * The X11 keysym of the key whose name should be stored in
- * key_name.
- *
- * @return
- * The length of the name, in bytes, excluding null terminator.
- */
-int guaclog_key_name(char* key_name, int keysym);
-
-#endif
-
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/keydef.c
----------------------------------------------------------------------
diff --git a/src/guaclog/keydef.c b/src/guaclog/keydef.c
new file mode 100644
index 0000000..9616500
--- /dev/null
+++ b/src/guaclog/keydef.c
@@ -0,0 +1,276 @@
+/*
+ * 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 "keydef.h"
+#include "log.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * All known keys.
+ */
+const guaclog_keydef known_keys[] = {
+ { 0xFE03, "AltGr" },
+ { 0xFF08, "Backspace" },
+ { 0xFF09, "Tab", "<Tab>" },
+ { 0xFF0B, "Clear" },
+ { 0xFF0D, "Return", "\n" },
+ { 0xFF13, "Pause" },
+ { 0xFF1B, "Escape" },
+ { 0xFF51, "Left" },
+ { 0xFF52, "Up" },
+ { 0xFF53, "Right" },
+ { 0xFF54, "Down" },
+ { 0xFF55, "Page Up" },
+ { 0xFF56, "Page Down" },
+ { 0xFF63, "Insert" },
+ { 0xFF65, "Undo" },
+ { 0xFF6A, "Help" },
+ { 0xFF80, "Space", " " },
+ { 0xFF8D, "Enter", "\n" },
+ { 0xFFBE, "F1" },
+ { 0xFFBF, "F2" },
+ { 0xFFC0, "F3" },
+ { 0xFFC1, "F4" },
+ { 0xFFC2, "F5" },
+ { 0xFFC3, "F6" },
+ { 0xFFC4, "F7" },
+ { 0xFFC5, "F8" },
+ { 0xFFC6, "F9" },
+ { 0xFFC7, "F10" },
+ { 0xFFC8, "F11" },
+ { 0xFFC9, "F12" },
+ { 0xFFCA, "F13" },
+ { 0xFFCB, "F14" },
+ { 0xFFCC, "F15" },
+ { 0xFFCD, "F16" },
+ { 0xFFCE, "F17" },
+ { 0xFFCF, "F18" },
+ { 0xFFD0, "F19" },
+ { 0xFFD1, "F20" },
+ { 0xFFD2, "F21" },
+ { 0xFFD3, "F22" },
+ { 0xFFD4, "F23" },
+ { 0xFFD5, "F24" },
+ { 0xFFE1, "Shift", "" },
+ { 0xFFE2, "Shift", "" },
+ { 0xFFE3, "Ctrl" },
+ { 0xFFE4, "Ctrl" },
+ { 0xFFE5, "Caps" },
+ { 0xFFE7, "Meta" },
+ { 0xFFE8, "Meta" },
+ { 0xFFE9, "Alt" },
+ { 0xFFEA, "Alt" },
+ { 0xFFEB, "Super" },
+ { 0xFFEB, "Win" },
+ { 0xFFEC, "Super" },
+ { 0xFFED, "Hyper" },
+ { 0xFFEE, "Hyper" },
+ { 0xFFFF, "Delete" }
+};
+
+/**
+ * Comparator for the standard bsearch() function which compares an integer
+ * keysym against the keysym associated with a guaclog_keydef.
+ *
+ * @param key
+ * The key value being compared against the member. This MUST be the
+ * keysym value, passed through typecasting to an intptr_t (NOT a pointer
+ * to the int itself).
+ *
+ * @param member
+ * The member within the known_keys array being compared against the given
+ * key.
+ *
+ * @return
+ * Zero if the given keysym is equal to that of the given member, a
+ * positive value if the given keysym is greater than that of the given
+ * member, or a negative value if the given keysym is less than that of the
+ * given member.
+ */
+static int guaclog_keydef_bsearch_compare(const void* key,
+ const void* member) {
+
+ int keysym = (int) ((intptr_t) key);
+ guaclog_keydef* current = (guaclog_keydef*) member;
+
+ /* Compare given keysym to keysym of current member */
+ return keysym - current->keysym;
+
+}
+
+/**
+ * Searches through the known_keys array of known keys for the name of the key
+ * having the given keysym, returning a pointer to the static guaclog_keydef
+ * within the array if found.
+ *
+ * @param keysym
+ * The X11 keysym of the key.
+ *
+ * @return
+ * A pointer to the static guaclog_keydef associated with the given keysym,
+ * or NULL if the key could not be found.
+ */
+static guaclog_keydef* guaclog_get_known_key(int keysym) {
+
+ /* Search through known keys for given keysym */
+ return bsearch((void*) ((intptr_t) keysym),
+ known_keys, sizeof(known_keys) / sizeof(known_keys[0]),
+ sizeof(known_keys[0]), guaclog_keydef_bsearch_compare);
+
+}
+
+/**
+ * Returns a statically-allocated guaclog_keydef representing the key
+ * associated with the given keysym, deriving the name and value of the key
+ * using its corresponding Unicode character.
+ *
+ * @param keysym
+ * The X11 keysym of the key.
+ *
+ * @return
+ * A statically-allocated guaclog_keydef representing the key associated
+ * with the given keysym, or NULL if the given keysym has no corresponding
+ * Unicode character.
+ */
+static guaclog_keydef* guaclog_get_unicode_key(int keysym) {
+
+ static char unicode_keydef_name[8];
+
+ static guaclog_keydef unicode_keydef;
+
+ int i;
+ int mask, bytes;
+
+ /* Translate only if keysym maps to Unicode */
+ if (keysym < 0x00 || (keysym > 0xFF && (keysym & 0xFFFF0000) != 0x01000000))
+ return NULL;
+
+ int codepoint = keysym & 0xFFFF;
+
+ /* Determine size and initial byte mask */
+ if (codepoint <= 0x007F) {
+ mask = 0x00;
+ bytes = 1;
+ }
+ else if (codepoint <= 0x7FF) {
+ mask = 0xC0;
+ bytes = 2;
+ }
+ else if (codepoint <= 0xFFFF) {
+ mask = 0xE0;
+ bytes = 3;
+ }
+ else if (codepoint <= 0x1FFFFF) {
+ mask = 0xF0;
+ bytes = 4;
+ }
+
+ /* Otherwise, invalid codepoint */
+ else
+ return NULL;
+
+ /* Offset buffer by size */
+ char* key_name = unicode_keydef_name + bytes;
+
+ /* Add null terminator */
+ *(key_name--) = '\0';
+
+ /* Add trailing bytes, if any */
+ for (i=1; i<bytes; i++) {
+ *(key_name--) = 0x80 | (codepoint & 0x3F);
+ codepoint >>= 6;
+ }
+
+ /* Set initial byte */
+ *key_name = mask | codepoint;
+
+ /* Return static key definition */
+ unicode_keydef.keysym = keysym;
+ unicode_keydef.name = unicode_keydef.value = unicode_keydef_name;
+ return &unicode_keydef;
+
+}
+
+/**
+ * Copies the given guaclog_keydef into a newly-allocated guaclog_keydef
+ * structure. The resulting guaclog_keydef must eventually be freed through a
+ * call to guaclog_keydef_free().
+ *
+ * @param keydef
+ * The guaclog_keydef to copy.
+ *
+ * @return
+ * A newly-allocated guaclog_keydef structure copied from the given
+ * guaclog_keydef.
+ */
+static guaclog_keydef* guaclog_copy_key(guaclog_keydef* keydef) {
+
+ guaclog_keydef* copy = malloc(sizeof(guaclog_keydef));
+
+ /* Always copy keysym and name */
+ copy->keysym = keydef->keysym;
+ copy->name = strdup(keydef->name);
+
+ /* Copy value only if defined */
+ if (keydef->value != NULL)
+ copy->value = strdup(keydef->value);
+ else
+ copy->value = NULL;
+
+ return copy;
+
+}
+
+guaclog_keydef* guaclog_keydef_alloc(int keysym) {
+
+ guaclog_keydef* keydef;
+
+ /* Check list of known keys first */
+ keydef = guaclog_get_known_key(keysym);
+ if (keydef != NULL)
+ return guaclog_copy_key(keydef);
+
+ /* Failing that, attempt to translate straight into a Unicode character */
+ keydef = guaclog_get_unicode_key(keysym);
+ if (keydef != NULL)
+ return guaclog_copy_key(keydef);
+
+ /* Key not known */
+ guaclog_log(GUAC_LOG_DEBUG, "Definition not found for key 0x%X.", keysym);
+ return NULL;
+
+}
+
+void guaclog_keydef_free(guaclog_keydef* keydef) {
+
+ /* Ignore NULL keydef */
+ if (keydef == NULL)
+ return;
+
+ free(keydef->name);
+ free(keydef->value);
+ free(keydef);
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/keydef.h
----------------------------------------------------------------------
diff --git a/src/guaclog/keydef.h b/src/guaclog/keydef.h
new file mode 100644
index 0000000..d0b2720
--- /dev/null
+++ b/src/guaclog/keydef.h
@@ -0,0 +1,73 @@
+/*
+ * 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 GUACLOG_KEYDEF_H
+#define GUACLOG_KEYDEF_H
+
+#include "config.h"
+
+/**
+ * A mapping of X11 keysym to its corresponding human-readable name.
+ */
+typedef struct guaclog_keydef {
+
+ /**
+ * The X11 keysym of the key.
+ */
+ int keysym;
+
+ /**
+ * A human-readable name for the key.
+ */
+ char* name;
+
+ /**
+ * The value which would be typed in a typical text editor, if any. If the
+ * key is not associated with any typable value, or if the typable value is
+ * not generally useful in an auditing context, this will be NULL.
+ */
+ char* value;
+
+} guaclog_keydef;
+
+/**
+ * Creates a new guaclog_keydef which represents the key having the given
+ * keysym. The resulting guaclog_keydef must eventually be freed through a
+ * call to guaclog_keydef_free().
+ *
+ * @param keysym
+ * The X11 keysym of the key.
+ *
+ * @return
+ * A new guaclog_keydef which represents the key having the given keysym,
+ * or NULL if no such key is known.
+ */
+guaclog_keydef* guaclog_keydef_alloc(int keysym);
+
+/**
+ * Frees all resources associated with the given guaclog_keydef. If the given
+ * guaclog_keydef is NULL, this function has no effect.
+ *
+ * @param keydef
+ * The guaclog_keydef to free, which may be NULL.
+ */
+void guaclog_keydef_free(guaclog_keydef* keydef);
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/state.c
----------------------------------------------------------------------
diff --git a/src/guaclog/state.c b/src/guaclog/state.c
index 616d043..4965985 100644
--- a/src/guaclog/state.c
+++ b/src/guaclog/state.c
@@ -18,7 +18,7 @@
*/
#include "config.h"
-#include "key-name.h"
+#include "keydef.h"
#include "log.h"
#include "state.h"
@@ -77,10 +77,16 @@ fail_output_fd:
int guaclog_state_free(guaclog_state* state) {
+ int i;
+
/* Ignore NULL state */
if (state == NULL)
return 0;
+ /* Free keydefs of all tracked keys */
+ for (i = 0; i < state->active_keys; i++)
+ guaclog_keydef_free(state->key_states[i].keydef);
+
/* Close output file */
fclose(state->output);
@@ -100,8 +106,11 @@ int guaclog_state_free(guaclog_state* state) {
* @param state
* The Guacamole input log interpreter state being updated.
*
- * @param keysym
- * The X11 keysym of the key being pressed or released.
+ * @param keydef
+ * The guaclog_keydef of the key being pressed or released. This
+ * guaclog_keydef will automatically be freed along with the guaclog_state
+ * if the key state was successfully added, and must be manually freed
+ * otherwise.
*
* @param pressed
* true if the key is being pressed, false if the key is being released.
@@ -109,14 +118,17 @@ int guaclog_state_free(guaclog_state* state) {
* @return
* Zero if the key state was successfully added, non-zero otherwise.
*/
-static int guaclog_state_add_key(guaclog_state* state, int keysym, bool pressed) {
+static int guaclog_state_add_key(guaclog_state* state, guaclog_keydef* keydef,
+ bool pressed) {
int i;
/* Update existing key, if already tracked */
for (i = 0; i < state->active_keys; i++) {
guaclog_key_state* key = &state->key_states[i];
- if (key->keysym == keysym) {
+ if (key->keydef->keysym == keydef->keysym) {
+ guaclog_keydef_free(key->keydef);
+ key->keydef = keydef;
key->pressed = pressed;
return 0;
}
@@ -125,13 +137,13 @@ static int guaclog_state_add_key(guaclog_state* state, int keysym, bool pressed)
/* If not already tracked, we need space to add it */
if (state->active_keys == GUACLOG_MAX_KEYS) {
guaclog_log(GUAC_LOG_WARNING, "Unable to log key 0x%X: Too many "
- "active keys.", keysym);
+ "active keys.", keydef->keysym);
return 1;
}
/* Add key to state */
guaclog_key_state* key = &state->key_states[state->active_keys++];
- key->keysym = keysym;
+ key->keydef = keydef;
key->pressed = pressed;
return 0;
@@ -152,11 +164,16 @@ static void guaclog_state_trim_keys(guaclog_state* state) {
/* Reset active_keys to contain only up to the last pressed key */
for (i = state->active_keys - 1; i >= 0; i--) {
+
guaclog_key_state* key = &state->key_states[i];
if (key->pressed) {
state->active_keys = i + 1;
return;
}
+
+ /* Free all trimmed states */
+ guaclog_keydef_free(key->keydef);
+
}
/* No keys are active */
@@ -164,44 +181,76 @@ static void guaclog_state_trim_keys(guaclog_state* state) {
}
+/**
+ * Returns whether the current tracked key state represents an in-progress
+ * keyboard shortcut.
+ *
+ * @param state
+ * The Guacamole input log interpreter state to test.
+ *
+ * @return
+ * true if the given state represents an in-progress keyboard shortcut,
+ * false otherwise.
+ */
+static bool guaclog_state_is_shortcut(guaclog_state* state) {
+
+ int i;
+
+ /* We are in a shortcut if at least one key is non-printable */
+ for (i = 0; i < state->active_keys; i++) {
+ guaclog_key_state* key = &state->key_states[i];
+ if (key->keydef->value == NULL)
+ return true;
+ }
+
+ /* All keys are printable - no shortcut */
+ return false;
+
+}
+
int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) {
int i;
- /* Update tracked keysysm state */
- guaclog_state_add_key(state, keysym, pressed);
- guaclog_state_trim_keys(state);
+ /* Determine nature of key */
+ guaclog_keydef* keydef = guaclog_keydef_alloc(keysym);
+ if (keydef == NULL)
+ return 0;
- /* Output new log entries only when keys are pressed */
- if (pressed) {
+ /* Update tracked key state */
+ if (guaclog_state_add_key(state, keydef, pressed))
+ guaclog_keydef_free(keydef);
+ else
+ guaclog_state_trim_keys(state);
- /* Compose log entry by inspecting the state of each tracked key */
- for (i = 0; i < state->active_keys; i++) {
+ /* Output key states only for printable keys */
+ if (pressed && keydef->value != NULL) {
- guaclog_key_state* key = &state->key_states[i];
+ if (guaclog_state_is_shortcut(state)) {
- /* Translate keysym into human-readable name */
- char key_name[GUACLOG_MAX_KEY_NAME_LENGTH];
- int name_length = guaclog_key_name(key_name, key->keysym);
+ fprintf(state->output, "<");
- /* If not the final key, omit the name (it was printed earlier) */
- if (i < state->active_keys - 1) {
- memset(key_name, ' ', name_length);
- if (key->pressed)
- key_name[name_length / 2] = '*';
- }
+ /* Compose log entry by inspecting the state of each tracked key */
+ for (i = 0; i < state->active_keys; i++) {
- /* Separate each key by a single space */
- if (i != 0)
- fprintf(state->output, " ");
+ /* Translate keysym into human-readable name */
+ guaclog_key_state* key = &state->key_states[i];
+
+ /* Print name of key */
+ if (i == 0)
+ fprintf(state->output, "%s", key->keydef->name);
+ else
+ fprintf(state->output, "+%s", key->keydef->name);
+
+ }
- /* Print name of key */
- fprintf(state->output, "%s", key_name);
+ fprintf(state->output, ">");
}
- /* Terminate log entry with newline */
- fprintf(state->output, "\n");
+ /* Print the key itself */
+ else
+ fprintf(state->output, "%s", keydef->value);
}
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/5b612b85/src/guaclog/state.h
----------------------------------------------------------------------
diff --git a/src/guaclog/state.h b/src/guaclog/state.h
index 0dd2f2f..b476dde 100644
--- a/src/guaclog/state.h
+++ b/src/guaclog/state.h
@@ -21,6 +21,7 @@
#define GUACLOG_STATE_H
#include "config.h"
+#include "keydef.h"
#include <stdbool.h>
#include <stdio.h>
@@ -37,9 +38,9 @@
typedef struct guaclog_key_state {
/**
- * The X11 keysym of the key.
+ * The definition of the key.
*/
- int keysym;
+ guaclog_keydef* keydef;
/**
* Whether the key is currently pressed (true) or released (false).
[05/11] guacamole-server git commit: GUACAMOLE-313: Add remaining key
names. Use Unicode where possible.
Posted by vn...@apache.org.
GUACAMOLE-313: Add remaining key names. Use Unicode where possible.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/86b09c8c
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/86b09c8c
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/86b09c8c
Branch: refs/heads/master
Commit: 86b09c8cf7fefd1f2dd7f368f1369f19d430bf7c
Parents: 3633af5
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Nov 26 19:35:47 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guaclog/key-name.c | 144 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 141 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/86b09c8c/src/guaclog/key-name.c
----------------------------------------------------------------------
diff --git a/src/guaclog/key-name.c b/src/guaclog/key-name.c
index f3485a2..5ae73b5 100644
--- a/src/guaclog/key-name.c
+++ b/src/guaclog/key-name.c
@@ -45,7 +45,65 @@ typedef struct guaclog_known_key {
* All known keys.
*/
const guaclog_known_key known_keys[] = {
- { 0xFFE1, "Shift" }
+ { 0x0020, "Space" },
+ { 0xFE03, "AltGr" },
+ { 0xFF08, "Backspace" },
+ { 0xFF09, "Tab" },
+ { 0xFF0B, "Clear" },
+ { 0xFF0D, "Return" },
+ { 0xFF13, "Pause" },
+ { 0xFF1B, "Escape" },
+ { 0xFF51, "Left" },
+ { 0xFF52, "Up" },
+ { 0xFF53, "Right" },
+ { 0xFF54, "Down" },
+ { 0xFF55, "Page Up" },
+ { 0xFF56, "Page Down" },
+ { 0xFF63, "Insert" },
+ { 0xFF65, "Undo" },
+ { 0xFF6A, "Help" },
+ { 0xFF80, "Space" },
+ { 0xFF8D, "Enter" },
+ { 0xFFBD, "Equals" },
+ { 0xFFBE, "F1" },
+ { 0xFFBF, "F2" },
+ { 0xFFC0, "F3" },
+ { 0xFFC1, "F4" },
+ { 0xFFC2, "F5" },
+ { 0xFFC3, "F6" },
+ { 0xFFC4, "F7" },
+ { 0xFFC5, "F8" },
+ { 0xFFC6, "F9" },
+ { 0xFFC7, "F10" },
+ { 0xFFC8, "F11" },
+ { 0xFFC9, "F12" },
+ { 0xFFCA, "F13" },
+ { 0xFFCB, "F14" },
+ { 0xFFCC, "F15" },
+ { 0xFFCD, "F16" },
+ { 0xFFCE, "F17" },
+ { 0xFFCF, "F18" },
+ { 0xFFD0, "F19" },
+ { 0xFFD1, "F20" },
+ { 0xFFD2, "F21" },
+ { 0xFFD3, "F22" },
+ { 0xFFD4, "F23" },
+ { 0xFFD5, "F24" },
+ { 0xFFE1, "Shift" },
+ { 0xFFE2, "Shift" },
+ { 0xFFE3, "Ctrl" },
+ { 0xFFE4, "Ctrl" },
+ { 0xFFE5, "Caps" },
+ { 0xFFE7, "Meta" },
+ { 0xFFE8, "Meta" },
+ { 0xFFE9, "Alt" },
+ { 0xFFEA, "Alt" },
+ { 0xFFEB, "Super" },
+ { 0xFFEB, "Win" },
+ { 0xFFEC, "Super" },
+ { 0xFFED, "Hyper" },
+ { 0xFFEE, "Hyper" },
+ { 0xFFFF, "Delete" }
};
/**
@@ -112,12 +170,92 @@ static int guaclog_locate_key_name(char* key_name, int keysym) {
}
+/**
+ * Produces a name for the key having the given keysym using its corresponding
+ * Unicode character. If possible, the name of the keysym is copied into the
+ * given buffer, which must be at least GUAC_MAX_KEY_NAME_LENGTH bytes long.
+ *
+ * @param key_name
+ * The buffer to copy the key name into, which must be at least
+ * GUACLOG_MAX_KEY_NAME_LENGTH.
+ *
+ * @param keysym
+ * The X11 keysym of the key whose name should be stored in
+ * key_name.
+ *
+ * @return
+ * The length of the name, in bytes, excluding null terminator, or zero if
+ * a readable name cannot be directly produced via Unicode alone.
+ */
+static int guaclog_unicode_key_name(char* key_name, int keysym) {
+
+ int i;
+ int mask, bytes;
+
+ /* Translate only if keysym maps to Unicode */
+ if (keysym < 0x00 || (keysym > 0xFF && (keysym & 0xFFFF0000) != 0x01000000))
+ return 0;
+
+ /* Do not translate whitespace - it will be unreadable */
+ if (keysym == 0x20)
+ return 0;
+
+ int codepoint = keysym & 0xFFFF;
+
+ /* Determine size and initial byte mask */
+ if (codepoint <= 0x007F) {
+ mask = 0x00;
+ bytes = 1;
+ }
+ else if (codepoint <= 0x7FF) {
+ mask = 0xC0;
+ bytes = 2;
+ }
+ else if (codepoint <= 0xFFFF) {
+ mask = 0xE0;
+ bytes = 3;
+ }
+ else if (codepoint <= 0x1FFFFF) {
+ mask = 0xF0;
+ bytes = 4;
+ }
+
+ /* Otherwise, invalid codepoint */
+ else {
+ *(key_name++) = '?';
+ return 1;
+ }
+
+ /* Offset buffer by size */
+ key_name += bytes;
+
+ /* Add null terminator */
+ *(key_name--) = '\0';
+
+ /* Add trailing bytes, if any */
+ for (i=1; i<bytes; i++) {
+ *(key_name--) = 0x80 | (codepoint & 0x3F);
+ codepoint >>= 6;
+ }
+
+ /* Set initial byte */
+ *key_name = mask | codepoint;
+
+ /* Done */
+ return bytes;
+
+}
+
int guaclog_key_name(char* key_name, int keysym) {
int name_length;
- /* Search for name within list of known keys */
- name_length = guaclog_locate_key_name(key_name, keysym);
+ /* Attempt to translate straight into a Unicode character */
+ name_length = guaclog_unicode_key_name(key_name, keysym);
+
+ /* If not Unicode, search for name within list of known keys */
+ if (name_length == 0)
+ name_length = guaclog_locate_key_name(key_name, keysym);
/* Fallback to using hex keysym as name */
if (name_length == 0)
[04/11] guacamole-server git commit: GUACAMOLE-313: Document log
format.
Posted by vn...@apache.org.
GUACAMOLE-313: Document log format.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/c0b2871b
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/c0b2871b
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/c0b2871b
Branch: refs/heads/master
Commit: c0b2871b31a6093627247c0fe084ee843f634896
Parents: b7257d9
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Dec 10 12:40:01 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:45 2018 -0800
----------------------------------------------------------------------
src/guaclog/man/guaclog.1.in | 55 ++++++++++++++++++++++++++++++++-------
1 file changed, 46 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/c0b2871b/src/guaclog/man/guaclog.1.in
----------------------------------------------------------------------
diff --git a/src/guaclog/man/guaclog.1.in b/src/guaclog/man/guaclog.1.in
index 11896d5..e5dfa9d 100644
--- a/src/guaclog/man/guaclog.1.in
+++ b/src/guaclog/man/guaclog.1.in
@@ -29,8 +29,8 @@ guaclog \- Guacamole input log interpreter
.SH DESCRIPTION
.B guaclog
is an interpreter which accepts Guacamole protocol dumps, such as those saved
-when input logging is enabled on a Guacamole connection, writing human-readable
-text logs as output.
+when input logging is enabled for a Guacamole session recording, writing
+human-readable text logs as output.
.B guaclog
is essentially an implementation of a Guacamole client which accepts
its input from files instead of a network connection, however unlike
@@ -42,19 +42,56 @@ file named \fIFILE\fR.txt. Existing files will not be overwritten; the
interpreting process for any input file will be aborted if it would result in
overwriting an existing file.
.P
-Guacamole acquires a write lock on input logs as they are being written. By
+Guacamole acquires a write lock on recordings as they are being written. By
default,
.B guaclog
will check whether the each input file is locked and will refuse to read and
-interpret an input file if it appears to be an in-progress log. This behavior
-can be overridden by specifying the \fB-f\fR option. Interpreting an
-in-progress log will still work; the resulting human-readable text file will
-simply cover the user's session only up to the current point in time.
+interpret an input file if it appears to be an in-progress recording. This
+behavior can be overridden by specifying the \fB-f\fR option. Interpreting an
+in-progress recording will still work; the resulting human-readable text file
+will simply cover the user's session only up to the current point in time.
.
.SH OPTIONS
.TP
\fB-f\fR
Overrides the default behavior of
.B guaclog
-such that input files will be interpreted even if they appear to be logs of
-in-progress Guacamole sessions.
+such that input files will be interpreted even if they appear to be recordings
+of in-progress Guacamole sessions.
+.
+.SH OUTPUT FORMAT
+The output format of
+.B guaclog
+is meant to match what the user would have typed within a typical text editor
+as closely as possible, while also representing non-printable characters and
+keyboard shortcuts in a human-readable way.
+.P
+All output is on one line, with new lines started only as a result of the user
+pressing enter/return. Keys which produce printable characters are translated
+into their corresponding Unicode codepoints and encoded as UTF-8, while
+non-printable characters are enclosed within angle brackets and represented
+with their human-readable names. Keyboard shortcuts which are made up of more
+than one key are enclosed within angle brackets, with each key within the
+shortcut separated by plus signs.
+.P
+Spaces and newlines are included as their Unicode character, except when
+represented within a keyboard shortcut, in which case their human-readable
+names are used instead. As the output of pressing tab can be easily mistaken
+for spaces, and as pressing tab frequently has special meaning within
+applications, tab is always represented by its human-readable name.
+.P
+Modifiers are output as part of keyboard shortcuts only. Simple pressing and
+releasing of a modifier will be ignored, as are presses of shift or AltGr while
+typing.
+.P
+For example, if the user typed "Hello WORLD!", selected everything by pressing
+Ctrl+a, copied the selected text by pressing Ctrl+c, switched to another
+application by pressing Alt+Shift+Tab, and then pasted the previously-copied
+text by pressing Ctrl+v, the resulting log from
+.B
+guaclog
+would look like:
+.PP
+.RS 0
+Hello WORLD!<Ctrl+a><Ctrl+c><Alt+Shift+Tab><Ctrl+v>
+
[11/11] guacamole-server git commit: GUACAMOLE-313: Merge add
"guaclog" utility for producing human-readable interpreatations of keys
pressed in session recordings.
Posted by vn...@apache.org.
GUACAMOLE-313: Merge add "guaclog" utility for producing human-readable interpreatations of keys pressed in session recordings.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/5f5b4ea8
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/5f5b4ea8
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/5f5b4ea8
Branch: refs/heads/master
Commit: 5f5b4ea8eb6d7198b6f7456101418ef97e53c5a1
Parents: 08f854f fdd17e3
Author: Nick Couchman <vn...@apache.org>
Authored: Tue Jan 30 14:07:35 2018 -0500
Committer: Nick Couchman <vn...@apache.org>
Committed: Tue Jan 30 14:07:35 2018 -0500
----------------------------------------------------------------------
Makefile.am | 5 +
configure.ac | 16 ++
src/guacenc/man/guacenc.1.in | 5 +-
src/guaclog/.gitignore | 5 +
src/guaclog/Makefile.am | 53 ++++++
src/guaclog/guaclog.c | 119 +++++++++++++
src/guaclog/guaclog.h | 31 ++++
src/guaclog/instruction-key.c | 43 +++++
src/guaclog/instructions.c | 62 +++++++
src/guaclog/instructions.h | 108 ++++++++++++
src/guaclog/interpret.c | 152 +++++++++++++++++
src/guaclog/interpret.h | 51 ++++++
src/guaclog/keydef.c | 335 +++++++++++++++++++++++++++++++++++++
src/guaclog/keydef.h | 81 +++++++++
src/guaclog/log.c | 85 ++++++++++
src/guaclog/log.h | 73 ++++++++
src/guaclog/man/guaclog.1.in | 99 +++++++++++
src/guaclog/state.c | 266 +++++++++++++++++++++++++++++
src/guaclog/state.h | 125 ++++++++++++++
19 files changed, 1713 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
[03/11] guacamole-server git commit: GUACAMOLE-313: Separate naming
logic for keysyms. Align previously-pressed keys.
Posted by vn...@apache.org.
GUACAMOLE-313: Separate naming logic for keysyms. Align previously-pressed keys.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/df29735c
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/df29735c
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/df29735c
Branch: refs/heads/master
Commit: df29735c83c210900ba55d60c1e1a29b3c3ef03e
Parents: d39757b
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Nov 26 18:00:29 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 26 16:24:43 2018 -0800
----------------------------------------------------------------------
src/guaclog/Makefile.am | 2 ++
src/guaclog/key-name.c | 43 +++++++++++++++++++++++++++++++++++++
src/guaclog/key-name.h | 50 ++++++++++++++++++++++++++++++++++++++++++++
src/guaclog/state.c | 22 +++++++++++++++----
4 files changed, 113 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/df29735c/src/guaclog/Makefile.am
----------------------------------------------------------------------
diff --git a/src/guaclog/Makefile.am b/src/guaclog/Makefile.am
index f1ad152..5007708 100644
--- a/src/guaclog/Makefile.am
+++ b/src/guaclog/Makefile.am
@@ -28,6 +28,7 @@ noinst_HEADERS = \
guaclog.h \
instructions.h \
interpret.h \
+ key-name.h \
log.h \
state.h
@@ -36,6 +37,7 @@ guaclog_SOURCES = \
instructions.c \
instruction-key.c \
interpret.c \
+ key-name.c \
log.c \
state.c
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/df29735c/src/guaclog/key-name.c
----------------------------------------------------------------------
diff --git a/src/guaclog/key-name.c b/src/guaclog/key-name.c
new file mode 100644
index 0000000..ffb622d
--- /dev/null
+++ b/src/guaclog/key-name.c
@@ -0,0 +1,43 @@
+/*
+ * 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 "key-name.h"
+#include "log.h"
+
+#include <stdio.h>
+
+int guaclog_key_name(char* key_name, int keysym) {
+
+ /* Fallback to using hex keysym as name */
+ int name_length = snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH,
+ "0x%X", keysym);
+
+ /* Truncate name if necessary */
+ if (name_length >= GUACLOG_MAX_KEY_NAME_LENGTH) {
+ name_length = GUACLOG_MAX_KEY_NAME_LENGTH - 1;
+ key_name[name_length] = '\0';
+ guaclog_log(GUAC_LOG_DEBUG, "Name for key 0x%X was "
+ "truncated.", keysym);
+ }
+
+ return name_length;
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/df29735c/src/guaclog/key-name.h
----------------------------------------------------------------------
diff --git a/src/guaclog/key-name.h b/src/guaclog/key-name.h
new file mode 100644
index 0000000..a033b36
--- /dev/null
+++ b/src/guaclog/key-name.h
@@ -0,0 +1,50 @@
+/*
+ * 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 GUACLOG_KEY_NAME_H
+#define GUACLOG_KEY_NAME_H
+
+#include "config.h"
+
+/**
+ * The maximum size of the name of any key, in bytes.
+ */
+#define GUACLOG_MAX_KEY_NAME_LENGTH 64
+
+/**
+ * Copies the name of the key having the given keysym into the given buffer,
+ * which must be at least GUACLOG_MAX_KEY_NAME_LENGTH bytes long. This function
+ * always succeeds, ultimately resorting to using the hex value of the keysym
+ * as the name if no other human-readable name is known.
+ *
+ * @param key_name
+ * The buffer to copy the key name into, which must be at least
+ * GUACLOG_MAX_KEY_NAME_LENGTH.
+ *
+ * @param keysym
+ * The X11 keysym of the key whose name should be stored in
+ * key_name.
+ *
+ * @return
+ * The length of the name, in bytes, excluding null terminator.
+ */
+int guaclog_key_name(char* key_name, int keysym);
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/df29735c/src/guaclog/state.c
----------------------------------------------------------------------
diff --git a/src/guaclog/state.c b/src/guaclog/state.c
index cc6f763..616d043 100644
--- a/src/guaclog/state.c
+++ b/src/guaclog/state.c
@@ -18,6 +18,7 @@
*/
#include "config.h"
+#include "key-name.h"
#include "log.h"
#include "state.h"
@@ -174,15 +175,28 @@ int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) {
/* Output new log entries only when keys are pressed */
if (pressed) {
- /* STUB: Output raw hex log entry */
+ /* Compose log entry by inspecting the state of each tracked key */
for (i = 0; i < state->active_keys; i++) {
+ guaclog_key_state* key = &state->key_states[i];
+
+ /* Translate keysym into human-readable name */
+ char key_name[GUACLOG_MAX_KEY_NAME_LENGTH];
+ int name_length = guaclog_key_name(key_name, key->keysym);
+
+ /* If not the final key, omit the name (it was printed earlier) */
+ if (i < state->active_keys - 1) {
+ memset(key_name, ' ', name_length);
+ if (key->pressed)
+ key_name[name_length / 2] = '*';
+ }
+
+ /* Separate each key by a single space */
if (i != 0)
fprintf(state->output, " ");
- guaclog_key_state* key = &state->key_states[i];
- fprintf(state->output, "0x%X:%s", key->keysym,
- key->pressed ? "*" : " ");
+ /* Print name of key */
+ fprintf(state->output, "%s", key_name);
}