diff options
author | Antenore Gatta (tmow) <antenore@simbiosi.org> | 2021-06-30 08:14:53 +0300 |
---|---|---|
committer | Antenore Gatta (tmow) <antenore@simbiosi.org> | 2021-06-30 08:14:53 +0300 |
commit | ae75b74ca7215fc44eee5558b51262e99a504fd8 (patch) | |
tree | d085f8ad87a6395e2b53bd3be1c6dde0689989b4 | |
parent | 34c174020b10d10d00c277ee922254d3654868dd (diff) | |
parent | 73724a5c0412cf8259aab65491b025e166b9a202 (diff) |
Add 'plugins/xdmcp/' from commit '73724a5c0412cf8259aab65491b025e166b9a202'
git-subtree-dir: plugins/xdmcp
git-subtree-mainline: 34c174020b10d10d00c277ee922254d3654868dd
git-subtree-split: 73724a5c0412cf8259aab65491b025e166b9a202
-rw-r--r-- | plugins/xdmcp/CMakeLists.txt | 54 | ||||
-rw-r--r-- | plugins/xdmcp/scalable/emblems/remmina-xdmcp-ssh-symbolic.svg | 89 | ||||
-rw-r--r-- | plugins/xdmcp/scalable/emblems/remmina-xdmcp-symbolic.svg | 109 | ||||
-rw-r--r-- | plugins/xdmcp/xdmcp_plugin.c | 425 |
4 files changed, 677 insertions, 0 deletions
diff --git a/plugins/xdmcp/CMakeLists.txt b/plugins/xdmcp/CMakeLists.txt new file mode 100644 index 0000000..df0f09c --- /dev/null +++ b/plugins/xdmcp/CMakeLists.txt @@ -0,0 +1,54 @@ +# remmina-plugin-xdmcp - The GTK+ Remote Desktop Client +# +# Copyright (C) 2011 Marc-Andre Moreau +# Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the +# OpenSSL library under certain conditions as described in each +# individual source file, and distribute linked combinations +# including the two. +# You must obey the GNU General Public License in all respects +# for all of the code used other than OpenSSL. If you modify +# file(s) with this exception, you may extend this exception to your +# version of the file(s), but you are not obligated to do so. If you +# do not wish to do so, delete this exception statement from your +# version. If you delete this exception statement from all source +# files in the program, then also delete it here. + + +set(REMMINA_PLUGIN_XDMCP_SRCS xdmcp_plugin.c) + +add_library(remmina-plugin-xdmcp MODULE ${REMMINA_PLUGIN_XDMCP_SRCS}) +set_target_properties(remmina-plugin-xdmcp PROPERTIES PREFIX "") +set_target_properties(remmina-plugin-xdmcp PROPERTIES NO_SONAME 1) + +include_directories(${REMMINA_COMMON_INCLUDE_DIRS}) +target_link_libraries(remmina-plugin-xdmcp ${REMMINA_COMMON_LIBRARIES}) + +install(TARGETS remmina-plugin-xdmcp DESTINATION ${REMMINA_PLUGINDIR}) + + +install(FILES + scalable/emblems/remmina-xdmcp-ssh-symbolic.svg + scalable/emblems/remmina-xdmcp-symbolic.svg + DESTINATION ${APPICONSCALE_EMBLEMS_DIR}) + +if(WITH_ICON_CACHE) + gtk_update_icon_cache("${REMMINA_DATADIR}/icons/hicolor") +endif() diff --git a/plugins/xdmcp/scalable/emblems/remmina-xdmcp-ssh-symbolic.svg b/plugins/xdmcp/scalable/emblems/remmina-xdmcp-ssh-symbolic.svg new file mode 100644 index 0000000..d76baf8 --- /dev/null +++ b/plugins/xdmcp/scalable/emblems/remmina-xdmcp-ssh-symbolic.svg @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="100" + height="100" + viewBox="0 0 26.458334 26.458332" + version="1.1" + id="svg8" + inkscape:version="0.92.2 2405546, 2018-03-11" + sodipodi:docname="remmina-xdmcp-ssh-symbolic.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="4" + inkscape:cx="25.558198" + inkscape:cy="61.982189" + inkscape:document-units="px" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + showgrid="false" + borderlayer="true" + inkscape:showpageshadow="true" + units="px" + inkscape:pagecheckerboard="false" + showguides="true" + inkscape:window-width="1920" + inkscape:window-height="1041" + inkscape:window-x="1600" + inkscape:window-y="18" + inkscape:window-maximized="0" + objecttolerance="10" + guidetolerance="10" + inkscape:snap-tangential="true" + inkscape:snap-perpendicular="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0"> + <inkscape:grid + type="xygrid" + id="grid10" + dotted="false" + originx="-179.27136" + originy="-128.69822" /> + </sodipodi:namedview> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + <cc:license + rdf:resource="" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-179.27135,-141.84345)"> + <g + id="g817" + transform="matrix(0.93878631,0,0,0.93878631,13.549948,10.22929)"> + <path + style="isolation:isolate;fill:#000000;stroke-width:0.93878627" + d="M 49.884766 0.27539062 C 34.886727 0.27539062 22.888672 12.506314 22.888672 27.273438 L 22.888672 32.117188 L 9.7363281 32.117188 L 9.7363281 99.724609 L 31.220703 99.724609 L 90.263672 99.724609 L 90.263672 32.117188 L 76.880859 32.117188 L 76.880859 27.273438 C 76.880859 12.275364 64.651854 0.27539062 49.884766 0.27539062 z M 49.654297 14.582031 C 56.806908 14.582031 62.34375 20.350818 62.34375 27.273438 L 62.34375 32.117188 L 36.732422 32.117188 L 36.732422 27.273438 L 36.962891 27.273438 C 36.962891 20.119868 42.732636 14.582031 49.654297 14.582031 z M 19.505859 35.171875 L 35.611328 35.171875 L 49.972656 54.789062 L 64.388672 35.171875 L 80.494141 35.171875 L 58.105469 65.525391 L 81.126953 96.828125 L 65.023438 96.828125 L 49.972656 76.427734 L 34.976562 96.828125 L 18.873047 96.828125 L 42 65.525391 L 19.505859 35.171875 z " + transform="matrix(0.28183552,0,0,0.28183552,176.52729,140.19608)" + id="path79" /> + </g> + </g> +</svg> diff --git a/plugins/xdmcp/scalable/emblems/remmina-xdmcp-symbolic.svg b/plugins/xdmcp/scalable/emblems/remmina-xdmcp-symbolic.svg new file mode 100644 index 0000000..f27500d --- /dev/null +++ b/plugins/xdmcp/scalable/emblems/remmina-xdmcp-symbolic.svg @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="100" + height="100" + viewBox="0 0 26.458334 26.458333" + version="1.1" + id="svg8" + inkscape:version="0.92.2 2405546, 2018-03-11" + sodipodi:docname="remmina-xdmcp-symbolic.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="0.74199836" + inkscape:cx="-124.28004" + inkscape:cy="-28.204733" + inkscape:document-units="px" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + showgrid="false" + borderlayer="true" + inkscape:showpageshadow="true" + units="px" + inkscape:pagecheckerboard="false" + showguides="true" + inkscape:window-width="1920" + inkscape:window-height="1041" + inkscape:window-x="1600" + inkscape:window-y="18" + inkscape:window-maximized="0" + objecttolerance="10" + guidetolerance="10" + inkscape:snap-tangential="true" + inkscape:snap-perpendicular="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0"> + <inkscape:grid + type="xygrid" + id="grid10" + dotted="false" + originx="-190.61239" + originy="-78.157086" /> + </sodipodi:namedview> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + <cc:license + rdf:resource="" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-190.61238,-192.38458)"> + <g + transform="matrix(0.26458333,0,0,0.26458333,153.78079,124.26165)" + style="isolation:isolate" + id="RDP Icons"> + <g + id="Group" /> + <g + id="g50"> + <path + style="fill:#000000" + d="M 50 0.41992188 C 22.636001 0.41992188 0.41992188 22.636001 0.41992188 50 C 0.41992188 77.363999 22.636001 99.580078 50 99.580078 C 77.363999 99.580078 99.580078 77.363999 99.580078 50 C 99.580078 22.636001 77.363999 0.41992188 50 0.41992188 z M 19.505859 19.171875 L 35.611328 19.171875 L 49.972656 38.787109 L 64.388672 19.171875 L 80.494141 19.171875 L 58.105469 49.525391 L 81.126953 80.828125 L 65.023438 80.828125 L 49.972656 60.427734 L 34.976562 80.828125 L 18.873047 80.828125 L 42 49.525391 L 19.505859 19.171875 z " + transform="translate(139.20601,257.47249)" + id="path48" /> + </g> + <g + id="g62"> + <g + id="g52" /> + <g + id="g54" /> + <g + id="g56" /> + <g + id="g60"> + <g + id="g58" /> + </g> + </g> + </g> + </g> +</svg> diff --git a/plugins/xdmcp/xdmcp_plugin.c b/plugins/xdmcp/xdmcp_plugin.c new file mode 100644 index 0000000..8e4fce3 --- /dev/null +++ b/plugins/xdmcp/xdmcp_plugin.c @@ -0,0 +1,425 @@ +/* + * Remmina - The GTK Remote Desktop Client + * Copyright (C) 2010 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2021 Antenore Gatta, Giovanni Panozzo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. * If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. * If you + * do not wish to do so, delete this exception statement from your + * version. * If you delete this exception statement from all source + * files in the program, then also delete it here. + * + */ + +#include "common/remmina_plugin.h" +#include <gtk/gtkx.h> + +INCLUDE_GET_AVAILABLE_XDISPLAY + +#define REMMINA_PLUGIN_XDMCP_FEATURE_TOOL_SENDCTRLALTDEL 1 +#define REMMINA_PLUGIN_XDMCP_FEATURE_GTKSOCKET 1 + +#define GET_PLUGIN_DATA(gp) (RemminaPluginXdmcpData*)g_object_get_data(G_OBJECT(gp), "plugin-data"); + +/* Forward declaration */ +static RemminaProtocolPlugin remmina_plugin_xdmcp; + +typedef struct _RemminaPluginXdmcpData { + GtkWidget *socket; + gint socket_id; + GPid pid; + gint output_fd; + gint error_fd; + gint display; + gboolean ready; + + pthread_t thread; + +} RemminaPluginXdmcpData; + +static RemminaPluginService *remmina_plugin_service = NULL; + + +static void remmina_plugin_xdmcp_on_plug_added(GtkSocket *socket, RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + + remmina_plugin_service->protocol_plugin_signal_connection_opened(gp); + gpdata->ready = TRUE; +} + +static void remmina_plugin_xdmcp_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); +} + +static gboolean remmina_plugin_xdmcp_start_xephyr(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + gchar *argv[50]; + gint argc; + gchar *host; + gint i; + GError *error = NULL; + gboolean ret; + + remminafile = remmina_plugin_service->protocol_plugin_get_file(gp); + + gpdata->display = remmina_get_available_xdisplay(); + if (gpdata->display == 0) { + remmina_plugin_service->protocol_plugin_set_error(gp, _("Ran out of available local X display numbers.")); + return FALSE; + } + + argc = 0; + argv[argc++] = g_strdup("Xephyr"); + + argv[argc++] = g_strdup_printf(":%i", gpdata->display); + + argv[argc++] = g_strdup("-parent"); + argv[argc++] = g_strdup_printf("%i", gpdata->socket_id); + + /* All Xephyr version between 1.5.0 and 1.6.4 will break when "-screen" argument is specified with "-parent". + * It’s not possible to support colour depth if you have those Xephyr version. Please see this bug + * http://bugs.freedesktop.org/show_bug.cgi?id=24144 + * As a workaround, a "Default" colour depth will not add the "-screen" argument. + */ + i = remmina_plugin_service->file_get_int(remminafile, "colordepth", 8); + if (i >= 8) { + argv[argc++] = g_strdup("-screen"); + argv[argc++] = g_strdup_printf("%ix%ix%i", + remmina_plugin_service->get_profile_remote_width(gp), + remmina_plugin_service->get_profile_remote_height(gp), i); + } + + if (i == 2) { + argv[argc++] = g_strdup("-grayscale"); + } + + if (remmina_plugin_service->file_get_int(remminafile, "showcursor", FALSE)) { + argv[argc++] = g_strdup("-host-cursor"); + } + if (remmina_plugin_service->file_get_int(remminafile, "once", FALSE)) { + argv[argc++] = g_strdup("-once"); + } + /* Listen on TCP protocol */ + if (remmina_plugin_service->file_get_int(remminafile, "listen_on_tcp", FALSE)) { + argv[argc++] = g_strdup("-listen"); + argv[argc++] = g_strdup("tcp"); + } + + if (!remmina_plugin_service->file_get_int(remminafile, "ssh_tunnel_enabled", FALSE)) { + remmina_plugin_service->get_server_port(remmina_plugin_service->file_get_string(remminafile, "server"), 0, + &host, &i); + + argv[argc++] = g_strdup("-query"); + argv[argc++] = host; + + if (i) { + argv[argc++] = g_strdup("-port"); + argv[argc++] = g_strdup_printf("%i", i); + } + }else { + /* When the connection is through an SSH tunnel, it connects back to local Unix socket, + * so for security we can disable TCP listening */ + argv[argc++] = g_strdup("-nolisten"); + argv[argc++] = g_strdup("tcp"); + + /* FIXME: It’s better to get the magic cookie back from xqproxy, then call xauth, + * instead of disable access control */ + argv[argc++] = g_strdup("-ac"); + } + + argv[argc++] = NULL; + + ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &gpdata->pid, &error); + for (i = 0; i < argc; i++) + g_free(argv[i]); + + if (!ret) { + remmina_plugin_service->protocol_plugin_set_error(gp, "%s", error->message); + return FALSE; + } + + return TRUE; +} + +static gboolean remmina_plugin_xdmcp_tunnel_init_callback(RemminaProtocolWidget *gp, gint remotedisplay, const gchar *server, + gint port) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + + remminafile = remmina_plugin_service->protocol_plugin_get_file(gp); + + if (!remmina_plugin_xdmcp_start_xephyr(gp)) + return FALSE; + while (!gpdata->ready) + sleep(1); + + remmina_plugin_service->protocol_plugin_set_display(gp, gpdata->display); + + if (remmina_plugin_service->file_get_string(remminafile, "exec")) { + return remmina_plugin_service->protocol_plugin_ssh_exec(gp, FALSE, "DISPLAY=localhost:%i.0 %s", remotedisplay, + remmina_plugin_service->file_get_string(remminafile, "exec")); + }else { + return remmina_plugin_service->protocol_plugin_ssh_exec(gp, TRUE, + "xqproxy -display %i -host %s -port %i -query -manage", remotedisplay, server, port); + } +} + +static gboolean remmina_plugin_xdmcp_main(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + + remminafile = remmina_plugin_service->protocol_plugin_get_file(gp); + + if (remmina_plugin_service->file_get_int(remminafile, "ssh_tunnel_enabled", FALSE)) { + if (!remmina_plugin_service->protocol_plugin_start_xport_tunnel(gp, remmina_plugin_xdmcp_tunnel_init_callback)) { + gpdata->thread = 0; + return FALSE; + } + }else { + if (!remmina_plugin_xdmcp_start_xephyr(gp)) { + gpdata->thread = 0; + return FALSE; + } + } + + gpdata->thread = 0; + return TRUE; +} + +static gpointer +remmina_plugin_xdmcp_main_thread(gpointer data) +{ + TRACE_CALL(__func__); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + CANCEL_ASYNC + if (!remmina_plugin_xdmcp_main((RemminaProtocolWidget*)data)) { + IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_signal_connection_closed, data); + } + return NULL; +} + +static void remmina_plugin_xdmcp_init(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata; + + gpdata = g_new0(RemminaPluginXdmcpData, 1); + g_object_set_data_full(G_OBJECT(gp), "plugin-data", gpdata, g_free); + + gpdata->socket = gtk_socket_new(); + remmina_plugin_service->protocol_plugin_register_hostkey(gp, gpdata->socket); + gtk_widget_show(gpdata->socket); + g_signal_connect(G_OBJECT(gpdata->socket), "plug-added", G_CALLBACK(remmina_plugin_xdmcp_on_plug_added), gp); + g_signal_connect(G_OBJECT(gpdata->socket), "plug-removed", G_CALLBACK(remmina_plugin_xdmcp_on_plug_removed), gp); + gtk_container_add(GTK_CONTAINER(gp), gpdata->socket); + +} + + + +static gboolean remmina_plugin_xdmcp_open_connection(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + gint width, height; + + if (!remmina_plugin_service->gtksocket_available()) { + remmina_plugin_service->protocol_plugin_set_error(gp, + _("The protocol “%s” is unavailable because GtkSocket only works under X.Org."), + remmina_plugin_xdmcp.name); + return FALSE; + } + + remminafile = remmina_plugin_service->protocol_plugin_get_file(gp); + + width = remmina_plugin_service->get_profile_remote_width(gp); + height = remmina_plugin_service->get_profile_remote_height(gp); + remmina_plugin_service->protocol_plugin_set_width(gp, width); + remmina_plugin_service->protocol_plugin_set_height(gp, height); + gtk_widget_set_size_request(GTK_WIDGET(gp), width, height); + gpdata->socket_id = gtk_socket_get_id(GTK_SOCKET(gpdata->socket)); + + + if (remmina_plugin_service->file_get_int(remminafile, "ssh_tunnel_enabled", FALSE)) { + if (pthread_create(&gpdata->thread, NULL, remmina_plugin_xdmcp_main_thread, gp)) { + remmina_plugin_service->protocol_plugin_set_error(gp, + "Could not start pthread. Using non-threaded mode instead…"); + gpdata->thread = 0; + return FALSE; + }else { + return TRUE; + } + }else { + return remmina_plugin_xdmcp_main(gp); + } + +} + +static gboolean remmina_plugin_xdmcp_close_connection(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + + if (gpdata->thread) { + pthread_cancel(gpdata->thread); + if (gpdata->thread) pthread_join(gpdata->thread, NULL); + } + + if (gpdata->pid) { + kill(gpdata->pid, SIGTERM); + g_spawn_close_pid(gpdata->pid); + gpdata->pid = 0; + } + + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); + + return FALSE; +} + +/* Send Ctrl+Alt+Del keystrokes to the plugin socket widget */ +static void remmina_plugin_xdmcp_send_ctrlaltdel(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete }; + RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); + + remmina_plugin_service->protocol_plugin_send_keys_signals(gpdata->socket, + keys, G_N_ELEMENTS(keys), GDK_KEY_PRESS | GDK_KEY_RELEASE); +} + +static gboolean remmina_plugin_xdmcp_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature) +{ + TRACE_CALL(__func__); + return TRUE; +} + +static void remmina_plugin_xdmcp_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature) +{ + TRACE_CALL(__func__); + + switch (feature->id) { + case REMMINA_PLUGIN_XDMCP_FEATURE_TOOL_SENDCTRLALTDEL: + remmina_plugin_xdmcp_send_ctrlaltdel(gp); + break; + default: + break; + } +} + +/* Array of key/value pairs for colour depths */ +static gpointer colordepth_list[] = +{ + "0", N_("Default"), + "2", N_("Grayscale"), + "8", N_("256 colours"), + "16", N_("High colour (16 bit)"), + "24", N_("True colour (24 bit)"), + NULL +}; + +/* Array of RemminaProtocolSetting for basic settings. + * Each item is composed by: + * a) RemminaProtocolSettingType for setting type + * b) Setting name + * c) Setting description + * d) Compact disposition + * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO + * f) Setting tooltip + */ +static const RemminaProtocolSetting remmina_plugin_xdmcp_basic_settings[] = +{ + { REMMINA_PROTOCOL_SETTING_TYPE_SERVER, "server", NULL, FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_RESOLUTION, "resolution", NULL, FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_SELECT, "colordepth", N_("Colour depth"), FALSE, colordepth_list, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_TEXT, "exec", N_("Start-up program"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "showcursor", N_("Use local cursor"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "once", N_("Disconnect after first session"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "listen_on_tcp", N_("Listen for TCP connections"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL } +}; + +/* Array for available features. + * The last element of the array must be REMMINA_PROTOCOL_FEATURE_TYPE_END. */ +static const RemminaProtocolFeature remmina_plugin_xdmcp_features[] = +{ + { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_XDMCP_FEATURE_TOOL_SENDCTRLALTDEL, N_("Send Ctrl+Alt+Delete"), NULL, NULL }, + { REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET, REMMINA_PLUGIN_XDMCP_FEATURE_GTKSOCKET, NULL, NULL, NULL}, + { REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL } +}; + +/* Protocol plugin definition and features */ +static RemminaProtocolPlugin remmina_plugin_xdmcp = +{ + REMMINA_PLUGIN_TYPE_PROTOCOL, // Type + "XDMCP", // Name + N_("XDMCP - X Remote Session"), // Description + GETTEXT_PACKAGE, // Translation domain + VERSION, // Version number + "remmina-xdmcp-symbolic", // Icon for normal connection + "remmina-xdmcp-ssh-symbolic", // Icon for SSH connection + remmina_plugin_xdmcp_basic_settings, // Array for basic settings + NULL, // Array for advanced settings + REMMINA_PROTOCOL_SSH_SETTING_TUNNEL, // SSH settings type + remmina_plugin_xdmcp_features, // Array for available features + remmina_plugin_xdmcp_init, // Plugin initialization + remmina_plugin_xdmcp_open_connection, // Plugin open connection + remmina_plugin_xdmcp_close_connection, // Plugin close connection + remmina_plugin_xdmcp_query_feature, // Query for available features + remmina_plugin_xdmcp_call_feature, // Call a feature + NULL, // Send a keystroke + NULL, // No screenshot support available + NULL, // RCW map event + NULL // RCW unmap event +}; + +G_MODULE_EXPORT gboolean +remmina_plugin_entry(RemminaPluginService *service) +{ + TRACE_CALL(__func__); + remmina_plugin_service = service; + + bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + + if (!service->register_plugin((RemminaPlugin*)&remmina_plugin_xdmcp)) { + return FALSE; + } + + return TRUE; +} |