From 9bc4764fc981ba33e2bfe793151949e0fca74c14 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Fri, 23 Mar 2018 22:19:39 +0100 Subject: Refactoring - Moving all plugins inside the plugins directory --- 16x16/emblems/remmina-nx.png | Bin 0 -> 426 bytes 22x22/emblems/remmina-nx.png | Bin 0 -> 788 bytes CMakeLists.txt | 65 +++ nx_plugin.c | 801 +++++++++++++++++++++++++++++++++ nx_plugin.h | 81 ++++ nx_session.c | 1021 ++++++++++++++++++++++++++++++++++++++++++ nx_session.h | 107 +++++ nx_session_manager.c | 244 ++++++++++ nx_session_manager.h | 43 ++ 9 files changed, 2362 insertions(+) create mode 100644 16x16/emblems/remmina-nx.png create mode 100644 22x22/emblems/remmina-nx.png create mode 100644 CMakeLists.txt create mode 100644 nx_plugin.c create mode 100644 nx_plugin.h create mode 100644 nx_session.c create mode 100644 nx_session.h create mode 100644 nx_session_manager.c create mode 100644 nx_session_manager.h diff --git a/16x16/emblems/remmina-nx.png b/16x16/emblems/remmina-nx.png new file mode 100644 index 0000000..9d1b952 Binary files /dev/null and b/16x16/emblems/remmina-nx.png differ diff --git a/22x22/emblems/remmina-nx.png b/22x22/emblems/remmina-nx.png new file mode 100644 index 0000000..13766da Binary files /dev/null and b/22x22/emblems/remmina-nx.png differ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c383fbf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,65 @@ +# remmina-plugin-nx - The GTK+ Remote Desktop Client +# +# Copyright (C) 2011 Marc-Andre Moreau +# Copyright (C) 2014-2017 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_NX_SRCS + nx_session.c + nx_session.h + nx_session_manager.c + nx_session_manager.h + nx_plugin.c + nx_plugin.h + ) + +add_library(remmina-plugin-nx ${REMMINA_PLUGIN_NX_SRCS}) +set_target_properties(remmina-plugin-nx PROPERTIES PREFIX "") +set_target_properties(remmina-plugin-nx PROPERTIES NO_SONAME 1) + +find_package(X11) + +include_directories(${REMMINA_COMMON_INCLUDE_DIRS} + ${XKBFILE_INCLUDE_DIRS} ${LIBSSH_INCLUDE_DIRS}) +target_link_libraries(remmina-plugin-nx + ${REMMINA_COMMON_LIBRARIES} + ${XKBFILE_LIBRARIES} + ${LIBSSH_LIBRARIES} + ${X11_X11_LIB}) + +install(TARGETS remmina-plugin-nx DESTINATION ${REMMINA_PLUGINDIR}) + +install(FILES + 16x16/emblems/remmina-nx.png + DESTINATION ${APPICON16_EMBLEMS_DIR}) +install(FILES + 22x22/emblems/remmina-nx.png + DESTINATION ${APPICON22_EMBLEMS_DIR}) diff --git a/nx_plugin.c b/nx_plugin.c new file mode 100644 index 0000000..e1f87cd --- /dev/null +++ b/nx_plugin.c @@ -0,0 +1,801 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2010-2011 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2017 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 +#include +#include "common/remmina_plugin.h" +#if GTK_VERSION == 3 +# include +#endif +#include +#define LIBSSH_STATIC 1 +#include +#include +#include +#include +#include "nx_plugin.h" +#include "nx_session_manager.h" + +#define REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL 1 + +/* Forward declaration */ +static RemminaProtocolPlugin remmina_plugin_nx; + +RemminaPluginService *remmina_plugin_nx_service = NULL; + +static gchar *remmina_kbtype = "pc102/us"; + +/* When more than one NX sessions is connecting in progress, we need this mutex and array + * to prevent them from stealing the same window id. + */ +static pthread_mutex_t remmina_nx_init_mutex; +static GArray *remmina_nx_window_id_array; + +/* --------- Support for execution on main thread of GTK functions -------------- */ + +struct onMainThread_cb_data { + enum { FUNC_GTK_SOCKET_ADD_ID } func; + + GtkSocket* sk; + Window w; + + /* Mutex for thread synchronization */ + pthread_mutex_t mu; + /* Flag to catch cancellations */ + gboolean cancelled; +}; + +static gboolean onMainThread_cb(struct onMainThread_cb_data *d) +{ + TRACE_CALL(__func__); + if ( !d->cancelled ) { + switch ( d->func ) { + case FUNC_GTK_SOCKET_ADD_ID: + gtk_socket_add_id( d->sk, d->w ); + break; + } + pthread_mutex_unlock( &d->mu ); + } else { + /* thread has been cancelled, so we must free d memory here */ + g_free( d ); + } + return G_SOURCE_REMOVE; +} + + +static void onMainThread_cleanup_handler(gpointer data) +{ + TRACE_CALL(__func__); + struct onMainThread_cb_data *d = data; + d->cancelled = TRUE; +} + + +static void onMainThread_schedule_callback_and_wait( struct onMainThread_cb_data *d ) +{ + TRACE_CALL(__func__); + d->cancelled = FALSE; + pthread_cleanup_push( onMainThread_cleanup_handler, d ); + pthread_mutex_init( &d->mu, NULL ); + pthread_mutex_lock( &d->mu ); + gdk_threads_add_idle( (GSourceFunc)onMainThread_cb, (gpointer)d ); + + pthread_mutex_lock( &d->mu ); + + pthread_cleanup_pop(0); + pthread_mutex_unlock( &d->mu ); + pthread_mutex_destroy( &d->mu ); +} + +static void onMainThread_gtk_socket_add_id( GtkSocket* sk, Window w) +{ + TRACE_CALL(__func__); + + struct onMainThread_cb_data *d; + + d = (struct onMainThread_cb_data *)g_malloc( sizeof(struct onMainThread_cb_data) ); + d->func = FUNC_GTK_SOCKET_ADD_ID; + d->sk = sk; + d->w = w; + + onMainThread_schedule_callback_and_wait( d ); + g_free(d); + +} + + +/* --------------------------------------- */ + + +static gboolean remmina_plugin_nx_try_window_id(Window window_id) +{ + TRACE_CALL(__func__); + gint i; + gboolean found = FALSE; + + pthread_mutex_lock(&remmina_nx_init_mutex); + for (i = 0; i < remmina_nx_window_id_array->len; i++) { + if (g_array_index(remmina_nx_window_id_array, Window, i) == window_id) { + found = TRUE; + break; + } + } + if (!found) { + g_array_append_val(remmina_nx_window_id_array, window_id); + } + pthread_mutex_unlock(&remmina_nx_init_mutex); + + return (!found); +} + +static void remmina_plugin_nx_remove_window_id(Window window_id) +{ + TRACE_CALL(__func__); + gint i; + gboolean found = FALSE; + + pthread_mutex_lock(&remmina_nx_init_mutex); + for (i = 0; i < remmina_nx_window_id_array->len; i++) { + if (g_array_index(remmina_nx_window_id_array, Window, i) == window_id) { + found = TRUE; + break; + } + } + if (found) { + g_array_remove_index_fast(remmina_nx_window_id_array, i); + } + pthread_mutex_unlock(&remmina_nx_init_mutex); +} + +static void remmina_plugin_nx_on_plug_added(GtkSocket *socket, RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + remmina_plugin_nx_service->protocol_plugin_emit_signal(gp, "connect"); +} + +static void remmina_plugin_nx_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + remmina_plugin_nx_service->protocol_plugin_close_connection(gp); +} + +gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userdata) +{ + TRACE_CALL(__func__); + RemminaProtocolWidget *gp = (RemminaProtocolWidget*)userdata; + gint ret; + + /* SSH passwords must not be saved */ + ret = remmina_plugin_nx_service->protocol_plugin_init_authpwd(gp, REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY, FALSE); + + if (ret != GTK_RESPONSE_OK) + return FALSE; + *passphrase = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); + + return TRUE; +} + +static void remmina_plugin_nx_on_proxy_exit(GPid pid, gint status, gpointer data) +{ + TRACE_CALL(__func__); + RemminaProtocolWidget *gp = (RemminaProtocolWidget*)data; + + remmina_plugin_nx_service->protocol_plugin_close_connection(gp); +} + +static int remmina_plugin_nx_dummy_handler(Display *dsp, XErrorEvent *err) +{ + TRACE_CALL(__func__); + return 0; +} + +static gboolean remmina_plugin_nx_start_create_notify(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + + gpdata->display = XOpenDisplay(gdk_display_get_name(gdk_display_get_default())); + if (gpdata->display == NULL) + return FALSE; + + gpdata->orig_handler = XSetErrorHandler(remmina_plugin_nx_dummy_handler); + + XSelectInput(gpdata->display, XDefaultRootWindow(gpdata->display), SubstructureNotifyMask); + + return TRUE; +} + +static gboolean remmina_plugin_nx_monitor_create_notify(RemminaProtocolWidget *gp, const gchar *cmd) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata; + Atom atom; + XEvent xev; + Window w; + Atom type; + int format; + unsigned long nitems, rest; + unsigned char *data = NULL; + struct timespec ts; + + CANCEL_DEFER + + gpdata = GET_PLUGIN_DATA(gp); + atom = XInternAtom(gpdata->display, "WM_COMMAND", True); + if (atom == None) + return FALSE; + + ts.tv_sec = 0; + ts.tv_nsec = 200000000; + + while (1) { + pthread_testcancel(); + while (!XPending(gpdata->display)) { + nanosleep(&ts, NULL); + continue; + } + XNextEvent(gpdata->display, &xev); + if (xev.type != CreateNotify) + continue; + w = xev.xcreatewindow.window; + if (XGetWindowProperty(gpdata->display, w, atom, 0, 255, False, AnyPropertyType, &type, &format, &nitems, &rest, + &data) != Success) + continue; + if (data && strstr((char*)data, cmd) && remmina_plugin_nx_try_window_id(w)) { + gpdata->window_id = w; + XFree(data); + break; + } + if (data) + XFree(data); + } + + XSetErrorHandler(gpdata->orig_handler); + XCloseDisplay(gpdata->display); + gpdata->display = NULL; + + CANCEL_ASYNC + return TRUE; +} + +static gint remmina_plugin_nx_wait_signal(RemminaPluginNxData *gpdata) +{ + TRACE_CALL(__func__); + fd_set set; + guchar dummy = 0; + + FD_ZERO(&set); + FD_SET(gpdata->event_pipe[0], &set); + select(gpdata->event_pipe[0] + 1, &set, NULL, NULL, NULL); + if (read(gpdata->event_pipe[0], &dummy, 1)) { + } + return (gint)dummy; +} + +static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + RemminaNXSession *nx; + const gchar *type, *app; + gchar *s1, *s2; + gint port; + gint ret; + gboolean is_empty_list; + gint event_type = 0; + const gchar *cs; + gint i; + gboolean disablepasswordstoring; + + remminafile = remmina_plugin_nx_service->protocol_plugin_get_file(gp); + nx = gpdata->nx; + + /* Connect */ + + remmina_nx_session_set_encryption(nx, + remmina_plugin_nx_service->file_get_int(remminafile, "disableencryption", FALSE) ? 0 : 1); + remmina_nx_session_set_localport(nx, remmina_plugin_nx_service->pref_get_sshtunnel_port()); + remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_service->log_printf); + + s2 = remmina_plugin_nx_service->protocol_plugin_start_direct_tunnel(gp, 22, FALSE); + if (s2 == NULL) { + return FALSE; + } + remmina_plugin_nx_service->get_server_port(s2, 22, &s1, &port); + g_free(s2); + + if (!remmina_nx_session_open(nx, s1, port, remmina_plugin_nx_service->file_get_string(remminafile, "nx_privatekey"), + remmina_plugin_nx_ssh_auth_callback, gp)) { + g_free(s1); + return FALSE; + } + g_free(s1); + + /* Login */ + + s1 = g_strdup(remmina_plugin_nx_service->file_get_string(remminafile, "username")); + s2 = g_strdup(remmina_plugin_nx_service->file_get_string(remminafile, "password")); + + if (s1 && s2) { + ret = remmina_nx_session_login(nx, s1, s2); + }else { + g_free(s1); + g_free(s2); + + disablepasswordstoring = remmina_plugin_nx_service->file_get_int(remminafile, "disablepasswordstoring", FALSE); + ret = remmina_plugin_nx_service->protocol_plugin_init_authuserpwd(gp, FALSE, !disablepasswordstoring); + + if (ret != GTK_RESPONSE_OK) + return FALSE; + + s1 = remmina_plugin_nx_service->protocol_plugin_init_get_username(gp); + s2 = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); + ret = remmina_nx_session_login(nx, s1, s2); + } + g_free(s1); + g_free(s2); + + if (!ret) + return FALSE; + + remmina_plugin_nx_service->protocol_plugin_init_save_cred(gp); + + /* Prepare the session type and application */ + cs = remmina_plugin_nx_service->file_get_string(remminafile, "exec"); + if (!cs || g_strcmp0(cs, "GNOME") == 0) { + type = "unix-gnome"; + app = NULL; + }else + if (g_strcmp0(cs, "KDE") == 0) { + type = "unix-kde"; + app = NULL; + }else + if (g_strcmp0(cs, "Xfce") == 0) { + /* NX does not know Xfce. So we simply launch the Xfce startup program. */ + type = "unix-application"; + app = "startxfce4"; + }else + if (g_strcmp0(cs, "Shadow") == 0) { + type = "shadow"; + app = NULL; + }else { + type = "unix-application"; + app = cs; + } + + /* List sessions */ + + gpdata->attach_session = (g_strcmp0(type, "shadow") == 0); + while (1) { + remmina_nx_session_add_parameter(nx, "type", type); + if (!gpdata->attach_session) { + remmina_nx_session_add_parameter(nx, "user", + remmina_plugin_nx_service->file_get_string(remminafile, "username")); + remmina_nx_session_add_parameter(nx, "status", "suspended,running"); + } + + if (!remmina_nx_session_list(nx)) { + return FALSE; + } + + is_empty_list = !remmina_nx_session_iter_first(nx, &gpdata->iter); + if (is_empty_list && !gpdata->manager_started && !gpdata->attach_session) { + event_type = REMMINA_NX_EVENT_START; + }else { + remmina_nx_session_manager_start(gp); + event_type = remmina_plugin_nx_wait_signal(gpdata); + if (event_type == REMMINA_NX_EVENT_CANCEL) { + return FALSE; + } + if (event_type == REMMINA_NX_EVENT_TERMINATE) { + if (!is_empty_list) { + s1 = remmina_nx_session_iter_get(nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_ID); + remmina_nx_session_add_parameter(nx, "sessionid", s1); + g_free(s1); + if (!remmina_nx_session_terminate(nx)) { + remmina_nx_session_manager_start(gp); + remmina_plugin_nx_wait_signal(gpdata); + } + } + continue; + } + } + + break; + } + + /* Start, Restore or Attach, based on the setting and existing session */ + remmina_nx_session_add_parameter(nx, "type", type); + i = remmina_plugin_nx_service->file_get_int(remminafile, "quality", 0); + remmina_nx_session_add_parameter(nx, "link", i > 2 ? "lan" : i == 2 ? "adsl" : i == 1 ? "isdn" : "modem"); + remmina_nx_session_add_parameter(nx, "geometry", "%ix%i", + remmina_plugin_nx_service->get_profile_remote_width(gp), + remmina_plugin_nx_service->get_profile_remote_height(gp)); + remmina_nx_session_add_parameter(nx, "keyboard", remmina_kbtype); + remmina_nx_session_add_parameter(nx, "client", "linux"); + remmina_nx_session_add_parameter(nx, "media", "0"); + remmina_nx_session_add_parameter(nx, "clipboard", + remmina_plugin_nx_service->file_get_int(remminafile, "disableclipboard", FALSE) ? "none" : "both"); + + switch (event_type) { + + case REMMINA_NX_EVENT_START: + if (app) + remmina_nx_session_add_parameter(nx, "application", app); + + remmina_nx_session_add_parameter(nx, "session", + remmina_plugin_nx_service->file_get_string(remminafile, "name")); + remmina_nx_session_add_parameter(nx, "screeninfo", "%ix%ix24+render", + remmina_plugin_nx_service->file_get_int(remminafile, "resolution_width", 0), + remmina_plugin_nx_service->file_get_int(remminafile, "resolution_height", 0)); + + if (!remmina_nx_session_start(nx)) + return FALSE; + break; + + case REMMINA_NX_EVENT_ATTACH: + s1 = remmina_nx_session_iter_get(nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_ID); + remmina_nx_session_add_parameter(nx, "id", s1); + g_free(s1); + + s1 = remmina_nx_session_iter_get(nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_DISPLAY); + remmina_nx_session_add_parameter(nx, "display", s1); + g_free(s1); + + if (!remmina_nx_session_attach(nx)) + return FALSE; + break; + + case REMMINA_NX_EVENT_RESTORE: + s1 = remmina_nx_session_iter_get(nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_ID); + remmina_nx_session_add_parameter(nx, "id", s1); + g_free(s1); + + remmina_nx_session_add_parameter(nx, "session", + remmina_plugin_nx_service->file_get_string(remminafile, "name")); + + if (!remmina_nx_session_restore(nx)) + return FALSE; + break; + + default: + return FALSE; + } + + if (!remmina_nx_session_tunnel_open(nx)) + return FALSE; + + if (!remmina_plugin_nx_start_create_notify(gp)) + return FALSE; + + /* nxproxy */ + if (!remmina_nx_session_invoke_proxy(nx, -1, remmina_plugin_nx_on_proxy_exit, gp)) + return FALSE; + + /* get the window id of the remote nxagent */ + if (!remmina_plugin_nx_monitor_create_notify(gp, "nxagent")) + return FALSE; + + /* embed it */ + onMainThread_gtk_socket_add_id(GTK_SOCKET(gpdata->socket), gpdata->window_id); + + + return TRUE; +} + +static gboolean remmina_plugin_nx_main(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + gboolean ret; + const gchar *err; + + gpdata->nx = remmina_nx_session_new(); + ret = remmina_plugin_nx_start_session(gp); + if (!ret) { + err = remmina_nx_session_get_error(gpdata->nx); + if (err) { + remmina_plugin_nx_service->protocol_plugin_set_error(gp, "%s", err); + } + } + + gpdata->thread = 0; + return ret; +} + +static gpointer remmina_plugin_nx_main_thread(gpointer data) +{ + TRACE_CALL(__func__); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + CANCEL_ASYNC + if (!remmina_plugin_nx_main((RemminaProtocolWidget*)data)) { + IDLE_ADD((GSourceFunc)remmina_plugin_nx_service->protocol_plugin_close_connection, data); + } + return NULL; +} + +static void remmina_plugin_nx_init(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata; + gint flags; + + gpdata = g_new0(RemminaPluginNxData, 1); + g_object_set_data_full(G_OBJECT(gp), "plugin-data", gpdata, g_free); + + gpdata->socket = gtk_socket_new(); + remmina_plugin_nx_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_nx_on_plug_added), gp); + g_signal_connect(G_OBJECT(gpdata->socket), "plug-removed", G_CALLBACK(remmina_plugin_nx_on_plug_removed), gp); + gtk_container_add(GTK_CONTAINER(gp), gpdata->socket); + + if (pipe(gpdata->event_pipe)) { + g_print("Error creating pipes.\n"); + gpdata->event_pipe[0] = -1; + gpdata->event_pipe[1] = -1; + }else { + flags = fcntl(gpdata->event_pipe[0], F_GETFL, 0); + fcntl(gpdata->event_pipe[0], F_SETFL, flags | O_NONBLOCK); + } +} + +static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + gint width, height; + + if (!remmina_plugin_nx_service->gtksocket_available()) { + remmina_plugin_nx_service->protocol_plugin_set_error(gp, + _("Protocol %s is unavailable because GtkSocket only works under Xorg"), + remmina_plugin_nx.name); + return FALSE; + } + + remminafile = remmina_plugin_nx_service->protocol_plugin_get_file(gp); + + width = remmina_plugin_nx_service->get_profile_remote_width(gp); + height = remmina_plugin_nx_service->get_profile_remote_height(gp); + + remmina_plugin_nx_service->protocol_plugin_set_width(gp, width); + remmina_plugin_nx_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 (pthread_create(&gpdata->thread, NULL, remmina_plugin_nx_main_thread, gp)) { + remmina_plugin_nx_service->protocol_plugin_set_error(gp, + "Failed to initialize pthread. Falling back to non-thread mode..."); + gpdata->thread = 0; + return FALSE; + }else { + return TRUE; + } +} + +static gboolean remmina_plugin_nx_close_connection(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + + if (gpdata->thread) { + pthread_cancel(gpdata->thread); + if (gpdata->thread) + pthread_join(gpdata->thread, NULL); + } + if (gpdata->session_manager_start_handler) { + g_source_remove(gpdata->session_manager_start_handler); + gpdata->session_manager_start_handler = 0; + } + + if (gpdata->window_id) { + remmina_plugin_nx_remove_window_id(gpdata->window_id); + } + + if (gpdata->nx) { + remmina_nx_session_free(gpdata->nx); + gpdata->nx = NULL; + } + + if (gpdata->display) { + XSetErrorHandler(gpdata->orig_handler); + XCloseDisplay(gpdata->display); + gpdata->display = NULL; + } + close(gpdata->event_pipe[0]); + close(gpdata->event_pipe[1]); + + remmina_plugin_nx_service->protocol_plugin_emit_signal(gp, "disconnect"); + + return FALSE; +} + +/* Send CTRL+ALT+DEL keys keystrokes to the plugin socket widget */ +static void remmina_plugin_nx_send_ctrlaltdel(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete }; + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + + remmina_plugin_nx_service->protocol_plugin_send_keys_signals(gpdata->socket, + keys, G_N_ELEMENTS(keys), GDK_KEY_PRESS | GDK_KEY_RELEASE); +} + +static gboolean remmina_plugin_nx_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature) +{ + TRACE_CALL(__func__); + return TRUE; +} + +static void remmina_plugin_nx_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature) +{ + TRACE_CALL(__func__); + switch (feature->id) { + case REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL: + remmina_plugin_nx_send_ctrlaltdel(gp); + break; + default: + break; + } +} + +/* Array of key/value pairs for quality selection */ +static gpointer quality_list[] = +{ + "0", N_("Poor (fastest)"), + "1", N_("Medium"), + "2", N_("Good"), + "9", N_("Best (slowest)"), + 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) Unused pointer + */ +static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = +{ + { REMMINA_PROTOCOL_SETTING_TYPE_SERVER, "server", NULL, FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_FILE, "nx_privatekey", N_("Identity file"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_TEXT, "username", N_("User name"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD, "password", N_("User password"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_RESOLUTION, "resolution", NULL, FALSE, GINT_TO_POINTER(1), NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_SELECT, "quality", N_("Quality"), FALSE, quality_list, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_COMBO, "exec", N_("Startup program"), FALSE, "GNOME,KDE,Xfce,Shadow", NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL } +}; + +/* Array of RemminaProtocolSetting for advanced 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) Unused pointer + */ +static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[] = +{ + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disableclipboard", N_("Disable clipboard sync"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disableencryption", N_("Disable encryption"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "showcursor", N_("Use local cursor"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disablepasswordstoring", N_("Disable password storing"), 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_nx_features[] = +{ + { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL, N_("Send Ctrl+Alt+Delete"), NULL, NULL }, + { REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL } +}; + +/* Protocol plugin definition and features */ +static RemminaProtocolPlugin remmina_plugin_nx = +{ + REMMINA_PLUGIN_TYPE_PROTOCOL, // Type + "NX", // Name + N_("NX - NX Technology"), // Description + GETTEXT_PACKAGE, // Translation domain + VERSION, // Version number + "remmina-nx", // Icon for normal connection + "remmina-nx", // Icon for SSH connection + remmina_plugin_nx_basic_settings, // Array for basic settings + remmina_plugin_nx_advanced_settings, // Array for advanced settings + REMMINA_PROTOCOL_SSH_SETTING_TUNNEL, // SSH settings type + remmina_plugin_nx_features, // Array for available features + remmina_plugin_nx_init, // Plugin initialization + remmina_plugin_nx_open_connection, // Plugin open connection + remmina_plugin_nx_close_connection, // Plugin close connection + remmina_plugin_nx_query_feature, // Query for available features + remmina_plugin_nx_call_feature, // Call a feature + NULL, // Send a keystroke + NULL // Screenshot +}; + +G_MODULE_EXPORT gboolean +remmina_plugin_entry(RemminaPluginService *service) +{ + TRACE_CALL(__func__); + Display *dpy; + XkbRF_VarDefsRec vd; + gchar *s; + + remmina_plugin_nx_service = service; + + bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + + if ((dpy = XkbOpenDisplay(NULL, NULL, NULL, NULL, NULL, NULL)) != NULL) { + if (XkbRF_GetNamesProp(dpy, NULL, &vd)) { + remmina_kbtype = g_strdup_printf("%s/%s", vd.model, vd.layout); + if (vd.layout) + XFree(vd.layout); + if (vd.model) + XFree(vd.model); + if (vd.variant) + XFree(vd.variant); + if (vd.options) + XFree(vd.options); + s = strchr(remmina_kbtype, ','); + if (s) + *s = '\0'; + /* g_print("NX: detected keyboard type %s\n", remmina_kbtype); */ + } + XCloseDisplay(dpy); + } + + if (!service->register_plugin((RemminaPlugin*)&remmina_plugin_nx)) { + return FALSE; + } + + ssh_init(); + pthread_mutex_init(&remmina_nx_init_mutex, NULL); + remmina_nx_window_id_array = g_array_new(FALSE, TRUE, sizeof(Window)); + + return TRUE; +} + diff --git a/nx_plugin.h b/nx_plugin.h new file mode 100644 index 0000000..9a9e602 --- /dev/null +++ b/nx_plugin.h @@ -0,0 +1,81 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2010 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2017 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. + * + */ + +#pragma once + +#define GET_PLUGIN_DATA(gp) (RemminaPluginNxData*)g_object_get_data(G_OBJECT(gp), "plugin-data"); + +G_BEGIN_DECLS + +#include "nx_session.h" + +typedef enum { + REMMINA_NX_EVENT_CANCEL, + REMMINA_NX_EVENT_START, + REMMINA_NX_EVENT_RESTORE, + REMMINA_NX_EVENT_ATTACH, + REMMINA_NX_EVENT_TERMINATE +} RemminaNXEventType; + +typedef struct _RemminaPluginNxData { + GtkWidget *socket; + gint socket_id; + + pthread_t thread; + + RemminaNXSession *nx; + + Display *display; + Window window_id; + int (*orig_handler)(Display *, XErrorEvent *); + + /* Session Manager data */ + gboolean manager_started; + GtkWidget *manager_dialog; + gboolean manager_selected; + + /* Communication between the NX thread and the session manager */ + gint event_pipe[2]; + guint session_manager_start_handler; + gboolean attach_session; + GtkTreeIter iter; + gint default_response; +} RemminaPluginNxData; + +extern RemminaPluginService *remmina_plugin_nx_service; + +G_END_DECLS + diff --git a/nx_session.c b/nx_session.c new file mode 100644 index 0000000..fbf8b26 --- /dev/null +++ b/nx_session.c @@ -0,0 +1,1021 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2010 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2017 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 +#include +#include "common/remmina_plugin.h" +#include +#define LIBSSH_STATIC 1 +#include +#include "nx_session.h" + +/* Some missing stuff in libssh */ +#define REMMINA_SSH_TYPE_DSS 1 +#define REMMINA_SSH_TYPE_RSA 2 + +static gboolean remmina_get_keytype(const gchar *private_key_file, gint *keytype, gboolean *encrypted) +{ + TRACE_CALL(__func__); + FILE *fp; + gchar buf1[100], buf2[100]; + + if ((fp = g_fopen(private_key_file, "r")) == NULL) { + return FALSE; + } + if (!fgets(buf1, sizeof(buf1), fp) || !fgets(buf2, sizeof(buf2), fp)) { + fclose(fp); + return FALSE; + } + fclose(fp); + + if (strstr(buf1, "BEGIN RSA")) + *keytype = REMMINA_SSH_TYPE_RSA; + else if (strstr(buf1, "BEGIN DSA")) + *keytype = REMMINA_SSH_TYPE_DSS; + else + return FALSE; + + *encrypted = (strstr(buf2, "ENCRYPTED") ? TRUE : FALSE); + + return TRUE; +} + +/*****/ + +static const gchar nx_default_private_key[] = "-----BEGIN DSA PRIVATE KEY-----\n" + "MIIBuwIBAAKBgQCXv9AzQXjxvXWC1qu3CdEqskX9YomTfyG865gb4D02ZwWuRU/9\n" + "C3I9/bEWLdaWgJYXIcFJsMCIkmWjjeSZyTmeoypI1iLifTHUxn3b7WNWi8AzKcVF\n" + "aBsBGiljsop9NiD1mEpA0G+nHHrhvTXz7pUvYrsrXcdMyM6rxqn77nbbnwIVALCi\n" + "xFdHZADw5KAVZI7r6QatEkqLAoGBAI4L1TQGFkq5xQ/nIIciW8setAAIyrcWdK/z\n" + "5/ZPeELdq70KDJxoLf81NL/8uIc4PoNyTRJjtT3R4f8Az1TsZWeh2+ReCEJxDWgG\n" + "fbk2YhRqoQTtXPFsI4qvzBWct42WonWqyyb1bPBHk+JmXFscJu5yFQ+JUVNsENpY\n" + "+Gkz3HqTAoGANlgcCuA4wrC+3Cic9CFkqiwO/Rn1vk8dvGuEQqFJ6f6LVfPfRTfa\n" + "QU7TGVLk2CzY4dasrwxJ1f6FsT8DHTNGnxELPKRuLstGrFY/PR7KeafeFZDf+fJ3\n" + "mbX5nxrld3wi5titTnX+8s4IKv29HJguPvOK/SI7cjzA+SqNfD7qEo8CFDIm1xRf\n" + "8xAPsSKs6yZ6j1FNklfu\n" + "-----END DSA PRIVATE KEY-----\n"; + +static const gchar nx_hello_server_msg[] = "hello nxserver - version "; + +struct _RemminaNXSession { + /* Common SSH members */ + ssh_session session; + ssh_channel channel; + gchar *server; + gchar *error; + RemminaNXLogCallback log_callback; + + /* Tunnel related members */ + pthread_t thread; + gboolean running; + gint server_sock; + + /* NX related members */ + GHashTable *session_parameters; + + GString *response; + gint response_pos; + gint status; + gint encryption; + gint localport; + + gchar *version; + gchar *session_id; + gint session_display; + gchar *proxy_cookie; + + gboolean allow_start; + GtkListStore *session_list; + gint session_list_state; + + GPid proxy_pid; + guint proxy_watch_source; +}; + +RemminaNXSession* +remmina_nx_session_new(void) +{ + TRACE_CALL(__func__); + RemminaNXSession *nx; + + nx = g_new0(RemminaNXSession, 1); + + nx->session_parameters = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + nx->response = g_string_new(NULL); + nx->status = -1; + nx->encryption = 1; + nx->server_sock = -1; + + return nx; +} + +void remmina_nx_session_free(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + pthread_t thread; + + if (nx->proxy_watch_source) { + g_source_remove(nx->proxy_watch_source); + nx->proxy_watch_source = 0; + } + if (nx->proxy_pid) { + kill(nx->proxy_pid, SIGTERM); + g_spawn_close_pid(nx->proxy_pid); + nx->proxy_pid = 0; + } + thread = nx->thread; + if (thread) { + nx->running = FALSE; + pthread_cancel(thread); + pthread_join(thread, NULL); + nx->thread = 0; + } + if (nx->channel) { + ssh_channel_close(nx->channel); + ssh_channel_free(nx->channel); + } + if (nx->server_sock >= 0) { + close(nx->server_sock); + nx->server_sock = -1; + } + + g_free(nx->server); + g_free(nx->error); + g_hash_table_destroy(nx->session_parameters); + g_string_free(nx->response, TRUE); + g_free(nx->version); + g_free(nx->session_id); + g_free(nx->proxy_cookie); + + if (nx->session_list) { + g_object_unref(nx->session_list); + nx->session_list = NULL; + } + if (nx->session) { + ssh_free(nx->session); + nx->session = NULL; + } + g_free(nx); +} + +static void remmina_nx_session_set_error(RemminaNXSession *nx, const gchar *fmt) +{ + TRACE_CALL(__func__); + const gchar *err; + + if (nx->error) + g_free(nx->error); + err = ssh_get_error(nx->session); + nx->error = g_strdup_printf(fmt, err); +} + +static void remmina_nx_session_set_application_error(RemminaNXSession *nx, const gchar *fmt, ...) +{ + TRACE_CALL(__func__); + va_list args; + + if (nx->error) g_free(nx->error); + va_start(args, fmt); + nx->error = g_strdup_vprintf(fmt, args); + va_end(args); +} + +gboolean remmina_nx_session_has_error(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + return (nx->error != NULL); +} + +const gchar* +remmina_nx_session_get_error(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + return nx->error; +} + +void remmina_nx_session_clear_error(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + if (nx->error) { + g_free(nx->error); + nx->error = NULL; + } +} + +void remmina_nx_session_set_encryption(RemminaNXSession *nx, gint encryption) +{ + TRACE_CALL(__func__); + nx->encryption = encryption; +} + +void remmina_nx_session_set_localport(RemminaNXSession *nx, gint localport) +{ + TRACE_CALL(__func__); + nx->localport = localport; +} + +void remmina_nx_session_set_log_callback(RemminaNXSession *nx, RemminaNXLogCallback log_callback) +{ + TRACE_CALL(__func__); + nx->log_callback = log_callback; +} + +static gboolean remmina_nx_session_get_response(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + struct timeval timeout; + ssh_channel ch[2]; + ssh_buffer buffer; + gint len; + gint is_stderr; + + timeout.tv_sec = 60; + timeout.tv_usec = 0; + ch[0] = nx->channel; + ch[1] = NULL; + ssh_channel_select(ch, NULL, NULL, &timeout); + + is_stderr = 0; + while (is_stderr <= 1) { + len = ssh_channel_poll(nx->channel, is_stderr); + if (len == SSH_ERROR) { + remmina_nx_session_set_error(nx, "Error reading channel: %s"); + return FALSE; + } + if (len > 0) + break; + is_stderr++; + } + if (is_stderr > 1) + return FALSE; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + buffer = buffer_new(); + len = channel_read_buffer(nx->channel, buffer, len, is_stderr); + G_GNUC_END_IGNORE_DEPRECATIONS + if (len <= 0) { + remmina_nx_session_set_application_error(nx, "Channel closed."); + return FALSE; + } + if (len > 0) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + g_string_append_len(nx->response, (const gchar*)buffer_get(buffer), len); + G_GNUC_END_IGNORE_DEPRECATIONS + } + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + buffer_free(buffer); + G_GNUC_END_IGNORE_DEPRECATIONS + return TRUE; +} + +static void remmina_nx_session_parse_session_list_line(RemminaNXSession *nx, const gchar *line) +{ + TRACE_CALL(__func__); + gchar *p1, *p2; + gchar *val; + gint i; + GtkTreeIter iter; + + p1 = (char*)line; + while (*p1 == ' ') + p1++; + if (*p1 == '\0') + return; + + gtk_list_store_append(nx->session_list, &iter); + + p1 = (char*)line; + for (i = 0; i < 7; i++) { + p2 = strchr(p1, ' '); + if (!p2) + return; + val = g_strndup(p1, (gint)(p2 - p1)); + switch (i) { + case 0: + gtk_list_store_set(nx->session_list, &iter, REMMINA_NX_SESSION_COLUMN_DISPLAY, val, -1); + break; + case 1: + gtk_list_store_set(nx->session_list, &iter, REMMINA_NX_SESSION_COLUMN_TYPE, val, -1); + break; + case 2: + gtk_list_store_set(nx->session_list, &iter, REMMINA_NX_SESSION_COLUMN_ID, val, -1); + break; + case 6: + gtk_list_store_set(nx->session_list, &iter, REMMINA_NX_SESSION_COLUMN_STATUS, val, -1); + break; + default: + break; + } + g_free(val); + + while (*p2 == ' ') + p2++; + p1 = p2; + } + /* The last name column might contains space so it's not in the above loop. We simply rtrim it here. */ + i = strlen(p1); + if (i < 1) + return; + p2 = p1 + i - 1; + while (*p2 == ' ' && p2 > p1) + p2--; + val = g_strndup(p1, (gint)(p2 - p1 + 1)); + gtk_list_store_set(nx->session_list, &iter, REMMINA_NX_SESSION_COLUMN_NAME, val, -1); + g_free(val); +} + +static gint remmina_nx_session_parse_line(RemminaNXSession *nx, const gchar *line, gchar **valueptr) +{ + TRACE_CALL(__func__); + gchar *s; + gchar *ptr; + gint status; + + *valueptr = NULL; + + /* Get the server version from the initial line */ + if (!nx->version) { + s = g_ascii_strdown(line, -1); + ptr = strstr(s, nx_hello_server_msg); + if (!ptr) { + /* Try to use a default version */ + nx->version = g_strdup("3.3.0"); + } else { + nx->version = g_strdup(ptr + strlen(nx_hello_server_msg)); + ptr = strchr(nx->version, ' '); + if (ptr) + *ptr = '\0'; + /* NoMachine NX append a dash+subversion. Need to be removed. */ + ptr = strchr(nx->version, '-'); + if (ptr) + *ptr = '\0'; + } + g_free(s); + return nx->status; + } + + if (sscanf(line, "NX> %i ", &status) < 1) { + if (nx->session_list_state && nx->session_list) { + if (nx->session_list_state == 1 && strncmp(line, "----", 4) == 0) { + nx->session_list_state = 2; + } else if (nx->session_list_state == 2) { + remmina_nx_session_parse_session_list_line(nx, line); + } + return -1; + } + return nx->status; + } + + nx->session_list_state = 0; + nx->status = status; + ptr = strchr(line, ':'); + if (!ptr) + return status; + *valueptr = ptr + 2; + return status; +} + +static gchar* +remmina_nx_session_get_line(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + gchar *line; + gchar *pos, *ptr; + gint len; + gint l; + + if (nx->response_pos >= nx->response->len) + return NULL; + + pos = nx->response->str + nx->response_pos; + if ((ptr = strchr(pos, '\n')) == NULL) + return NULL; + + len = ((gint)(ptr - pos)) + 1; + line = g_strndup(pos, len - 1); + + l = strlen(line); + if (l > 0 && line[l - 1] == '\r') { + line[l - 1] = '\0'; + } + + nx->response_pos += len; + + return line; +} + +static gint remmina_nx_session_parse_response(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + gchar *line; + gchar *pos, *p; + gint status = -1; + + if (nx->response_pos >= nx->response->len) + return -1; + + while ((line = remmina_nx_session_get_line(nx)) != NULL) { + if (nx->log_callback) + nx->log_callback("[NX] %s\n", line); + + status = remmina_nx_session_parse_line(nx, line, &p); + if (status == 500) { + /* 500: Last operation failed. Should be ignored. */ + } else if (status >= 400 && status <= 599) { + remmina_nx_session_set_application_error(nx, "%s", line); + } else { + switch (status) { + case 127: /* Session list */ + nx->session_list_state = 1; + break; + case 148: /* Server capacity not reached for user xxx */ + nx->session_list_state = 0; + nx->allow_start = TRUE; + break; + case 700: + nx->session_id = g_strdup(p); + break; + case 705: + nx->session_display = atoi(p); + break; + case 701: + nx->proxy_cookie = g_strdup(p); + break; + } + } + g_free(line); + + nx->status = status; + } + + pos = nx->response->str + nx->response_pos; + if (sscanf(pos, "NX> %i ", &status) < 1) { + status = nx->status; + } else { + if (nx->log_callback) + nx->log_callback("[NX] %s\n", pos); + nx->response_pos += 8; + } + nx->status = -1; + return status; +} + +static gint remmina_nx_session_expect_status2(RemminaNXSession *nx, gint status, gint status2) +{ + TRACE_CALL(__func__); + gint response; + + while ((response = remmina_nx_session_parse_response(nx)) != status && response != status2) { + if (response == 999) + break; + if (!remmina_nx_session_get_response(nx)) + return -1; + } + nx->session_list_state = 0; + if (remmina_nx_session_has_error(nx)) + return -1; + return response; +} + +static gboolean remmina_nx_session_expect_status(RemminaNXSession *nx, gint status) +{ + TRACE_CALL(__func__); + return (remmina_nx_session_expect_status2(nx, status, 0) == status); +} + +static void remmina_nx_session_send_command(RemminaNXSession *nx, const gchar *cmdfmt, ...) +{ + TRACE_CALL(__func__); + va_list args; + gchar *cmd; + + va_start(args, cmdfmt); + cmd = g_strdup_vprintf(cmdfmt, args); + ssh_channel_write(nx->channel, cmd, strlen(cmd)); + g_free(cmd); + + ssh_set_fd_towrite(nx->session); + ssh_channel_write(nx->channel, "\n", 1); + va_end(args); +} + +gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, + RemminaNXPassphraseCallback passphrase_func, gpointer userdata) +{ + TRACE_CALL(__func__); + gint ret; + ssh_key priv_key; + gint keytype; + gboolean encrypted; + gchar *passphrase = NULL; + + nx->session = ssh_new(); + ssh_options_set(nx->session, SSH_OPTIONS_HOST, server); + ssh_options_set(nx->session, SSH_OPTIONS_PORT, &port); + ssh_options_set(nx->session, SSH_OPTIONS_USER, "nx"); + + if (private_key_file && private_key_file[0]) { + if (!remmina_get_keytype(private_key_file, &keytype, &encrypted)) { + remmina_nx_session_set_application_error(nx, "Invalid private key file."); + return FALSE; + } + if (encrypted && !passphrase_func(&passphrase, userdata)) { + return FALSE; + } + if ( ssh_pki_import_privkey_file(private_key_file, (passphrase ? passphrase : ""), NULL, NULL, &priv_key) != SSH_OK ) { + remmina_nx_session_set_application_error(nx, "Error importing private key from file."); + g_free(passphrase); + return FALSE; + } + g_free(passphrase); + } else { + /* Use NoMachine's default nx private key */ + if ( ssh_pki_import_privkey_base64(nx_default_private_key, NULL, NULL, NULL, &priv_key) != SSH_OK ) { + remmina_nx_session_set_application_error(nx, "Failed to import NX default private key."); + return FALSE; + } + } + + if (ssh_connect(nx->session)) { + ssh_key_free(priv_key); + remmina_nx_session_set_error(nx, "Failed to startup SSH session: %s"); + return FALSE; + } + + ret = ssh_userauth_publickey(nx->session, NULL, priv_key); + + ssh_key_free(priv_key); + + if (ret != SSH_AUTH_SUCCESS) { + remmina_nx_session_set_error(nx, "NX SSH authentication failed: %s"); + return FALSE; + } + + if ((nx->channel = ssh_channel_new(nx->session)) == NULL || ssh_channel_open_session(nx->channel) != SSH_OK) { + return FALSE; + } + + if (ssh_channel_request_shell(nx->channel) != SSH_OK) { + return FALSE; + } + + /* NX server starts the session with an initial 105 status */ + if (!remmina_nx_session_expect_status(nx, 105)) + return FALSE; + + /* Say hello to the NX server */ + remmina_nx_session_send_command(nx, "HELLO NXCLIENT - Version %s", nx->version); + if (!remmina_nx_session_expect_status(nx, 105)) + return FALSE; + + /* Set the NX session environment */ + remmina_nx_session_send_command(nx, "SET SHELL_MODE SHELL"); + if (!remmina_nx_session_expect_status(nx, 105)) + return FALSE; + remmina_nx_session_send_command(nx, "SET AUTH_MODE PASSWORD"); + if (!remmina_nx_session_expect_status(nx, 105)) + return FALSE; + + nx->server = g_strdup(server); + + return TRUE; +} + +gboolean remmina_nx_session_login(RemminaNXSession *nx, const gchar *username, const gchar *password) +{ + TRACE_CALL(__func__); + gint response; + + /* Login to the NX server */ + remmina_nx_session_send_command(nx, "login"); + if (!remmina_nx_session_expect_status(nx, 101)) + return FALSE; + remmina_nx_session_send_command(nx, username); + /* NoMachine Testdrive does not prompt for password, in which case 105 response is received without 102 */ + response = remmina_nx_session_expect_status2(nx, 102, 105); + if (response == 102) { + remmina_nx_session_send_command(nx, password); + if (!remmina_nx_session_expect_status(nx, 105)) + return FALSE; + } else if (response != 105) { + return FALSE; + } + + return TRUE; +} + +void remmina_nx_session_add_parameter(RemminaNXSession *nx, const gchar *name, const gchar *valuefmt, ...) +{ + TRACE_CALL(__func__); + va_list args; + gchar *value; + + va_start(args, valuefmt); + value = g_strdup_vprintf(valuefmt, args); + g_hash_table_insert(nx->session_parameters, g_strdup(name), value); + va_end(args); +} + +static gboolean remmina_nx_session_send_session_command(RemminaNXSession *nx, const gchar *cmd_type, gint response) +{ + TRACE_CALL(__func__); + GString *cmd; + GHashTableIter iter; + gchar *key, *value; + + cmd = g_string_new(cmd_type); + g_hash_table_iter_init(&iter, nx->session_parameters); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) { + g_string_append_printf(cmd, " --%s=\"%s\"", key, value); + } + + remmina_nx_session_send_command(nx, cmd->str); + g_string_free(cmd, TRUE); + + g_hash_table_remove_all(nx->session_parameters); + + return remmina_nx_session_expect_status(nx, response); +} + +gboolean remmina_nx_session_list(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + gboolean ret; + + if (nx->session_list == NULL) { + nx->session_list = gtk_list_store_new(REMMINA_NX_SESSION_N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING); + } else { + gtk_list_store_clear(nx->session_list); + } + ret = remmina_nx_session_send_session_command(nx, "listsession", 105); + + return ret; +} + +void remmina_nx_session_set_tree_view(RemminaNXSession *nx, GtkTreeView *tree) +{ + TRACE_CALL(__func__); + gtk_tree_view_set_model(tree, GTK_TREE_MODEL(nx->session_list)); +} + +gboolean remmina_nx_session_iter_first(RemminaNXSession *nx, GtkTreeIter *iter) +{ + TRACE_CALL(__func__); + if (!nx->session_list) + return FALSE; + return gtk_tree_model_get_iter_first(GTK_TREE_MODEL(nx->session_list), iter); +} + +gboolean remmina_nx_session_iter_next(RemminaNXSession *nx, GtkTreeIter *iter) +{ + TRACE_CALL(__func__); + if (!nx->session_list) + return FALSE; + return gtk_tree_model_iter_next(GTK_TREE_MODEL(nx->session_list), iter); +} + +gchar* +remmina_nx_session_iter_get(RemminaNXSession *nx, GtkTreeIter *iter, gint column) +{ + TRACE_CALL(__func__); + gchar *val; + + gtk_tree_model_get(GTK_TREE_MODEL(nx->session_list), iter, column, &val, -1); + return val; +} + +void remmina_nx_session_iter_set(RemminaNXSession *nx, GtkTreeIter *iter, gint column, const gchar *data) +{ + TRACE_CALL(__func__); + gtk_list_store_set(nx->session_list, iter, column, data, -1); +} + +gboolean remmina_nx_session_allow_start(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + return nx->allow_start; +} + +static void remmina_nx_session_add_common_parameters(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + gchar *value; + + /* Add fixed session parameters for startsession */ + remmina_nx_session_add_parameter(nx, "cache", "16M"); + remmina_nx_session_add_parameter(nx, "images", "64M"); + remmina_nx_session_add_parameter(nx, "render", "1"); + remmina_nx_session_add_parameter(nx, "backingstore", "1"); + remmina_nx_session_add_parameter(nx, "agent_server", ""); + remmina_nx_session_add_parameter(nx, "agent_user", ""); + remmina_nx_session_add_parameter(nx, "agent_password", ""); + + value = g_strdup_printf("%i", nx->encryption); + remmina_nx_session_add_parameter(nx, "encryption", value); + g_free(value); +} + +gboolean remmina_nx_session_start(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + remmina_nx_session_add_common_parameters(nx); + return remmina_nx_session_send_session_command(nx, "startsession", 105); +} + +gboolean remmina_nx_session_attach(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + remmina_nx_session_add_common_parameters(nx); + return remmina_nx_session_send_session_command(nx, "attachsession", 105); +} + +gboolean remmina_nx_session_restore(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + remmina_nx_session_add_common_parameters(nx); + return remmina_nx_session_send_session_command(nx, "restoresession", 105); +} + +gboolean remmina_nx_session_terminate(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + return remmina_nx_session_send_session_command(nx, "terminate", 105); +} + +static gpointer remmina_nx_session_tunnel_main_thread(gpointer data) +{ + TRACE_CALL(__func__); + RemminaNXSession *nx = (RemminaNXSession*)data; + gchar *ptr; + ssize_t len = 0, lenw = 0; + fd_set set; + struct timeval timeout; + ssh_channel channels[2]; + ssh_channel channels_out[2]; + gint sock; + gint ret; + gchar buffer[10240]; + gchar socketbuffer[10240]; + gchar *socketbuffer_ptr = NULL; + gint socketbuffer_len = 0; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + /* Accept a local connection */ + sock = accept(nx->server_sock, NULL, NULL); + if (sock < 0) { + remmina_nx_session_set_application_error(nx, "Failed to accept local socket"); + nx->thread = 0; + return NULL; + } + close(nx->server_sock); + nx->server_sock = -1; + + channels[0] = nx->channel; + channels[1] = NULL; + + /* Start the tunnel data transmittion */ + while (nx->running) { + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + FD_ZERO(&set); + FD_SET(sock, &set); + + ret = ssh_select(channels, channels_out, sock + 1, &set, &timeout); + if (!nx->running) + break; + if (ret == SSH_EINTR) + continue; + if (ret == -1) + break; + + if (FD_ISSET(sock, &set)) { + len = read(sock, buffer, sizeof(buffer)); + if (len == 0) + nx->running = FALSE; + else if (len > 0) { + for (ptr = buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw) { + ssh_set_fd_towrite(nx->session); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + lenw = channel_write(channels[0], (char*)ptr, len); + G_GNUC_END_IGNORE_DEPRECATIONS + if (lenw <= 0) { + nx->running = FALSE; + break; + } + } + } + } + + if (!nx->running) + break; + + if (channels_out[0] && socketbuffer_len <= 0) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + len = channel_read_nonblocking(channels_out[0], socketbuffer, sizeof(socketbuffer), 0); + G_GNUC_END_IGNORE_DEPRECATIONS + if (len == SSH_ERROR || len == SSH_EOF) { + nx->running = FALSE; + break; + } else if (len > 0) { + socketbuffer_ptr = socketbuffer; + socketbuffer_len = len; + } else { + /* Clean up the stderr buffer in case FreeNX send something there */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + len = channel_read_nonblocking(channels_out[0], buffer, sizeof(buffer), 1); + if (len == SSH_ERROR || len == SSH_EOF) { + nx->running = FALSE; + break; + } + G_GNUC_END_IGNORE_DEPRECATIONS + } + } + + if (nx->running && socketbuffer_len > 0) { + for (lenw = 0; socketbuffer_len > 0; socketbuffer_len -= lenw, socketbuffer_ptr += lenw) { + lenw = write(sock, socketbuffer_ptr, socketbuffer_len); + if (lenw == -1 && errno == EAGAIN && nx->running) { + /* Sometimes we cannot write to a socket (always EAGAIN), probably because it's internal + * buffer is full. We need read the pending bytes from the socket first. so here we simply + * break, leave the buffer there, and continue with other data */ + break; + } + if (lenw <= 0) { + nx->running = FALSE; + break; + } + } + } + } + + nx->thread = 0; + + return NULL; +} + +gboolean remmina_nx_session_tunnel_open(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + gint port; + gint sock; + gint sockopt = 1; + struct sockaddr_in sin; + + if (!nx->encryption) + return TRUE; + + remmina_nx_session_send_command(nx, "bye"); + if (!remmina_nx_session_expect_status(nx, 999)) { + /* Shoud not happen, just in case */ + remmina_nx_session_set_application_error(nx, "Server won't say bye to us?"); + return FALSE; + } + + port = (nx->localport ? nx->localport : nx->session_display) + 4000; + + /* Create the server socket that listens on the local port */ + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + remmina_nx_session_set_application_error(nx, "Failed to create socket."); + return FALSE; + } + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); + + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (bind(sock, (struct sockaddr *)&sin, sizeof(sin))) { + remmina_nx_session_set_application_error(nx, "Failed to bind on local port."); + close(sock); + return FALSE; + } + + if (listen(sock, 1)) { + remmina_nx_session_set_application_error(nx, "Failed to listen on local port."); + close(sock); + return FALSE; + } + + nx->server_sock = sock; + nx->running = TRUE; + + if (pthread_create(&nx->thread, NULL, remmina_nx_session_tunnel_main_thread, nx)) { + remmina_nx_session_set_application_error(nx, "Failed to initialize pthread."); + nx->thread = 0; + return FALSE; + } + return TRUE; +} + +static gchar* +remmina_nx_session_get_proxy_option(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + if (nx->encryption) { + return g_strdup_printf("nx,session=%s,cookie=%s,id=%s,shmem=1,shpix=1,connect=127.0.0.1:%i", + (gchar*)g_hash_table_lookup(nx->session_parameters, "session"), nx->proxy_cookie, + nx->session_id, (nx->localport ? nx->localport : nx->session_display)); + } else { + return g_strdup_printf("nx,session=%s,cookie=%s,id=%s,shmem=1,shpix=1,connect=%s:%i", + (gchar*)g_hash_table_lookup(nx->session_parameters, "session"), nx->proxy_cookie, + nx->session_id, nx->server, nx->session_display); + } +} + +gboolean remmina_nx_session_invoke_proxy(RemminaNXSession *nx, gint display, GChildWatchFunc exit_func, gpointer user_data) +{ + TRACE_CALL(__func__); + gchar *argv[50]; + gint argc; + GError *error = NULL; + gboolean ret; + gchar **envp; + gchar *s; + gint i; + + /* Copy all current environment variable, but change DISPLAY. Assume we should always have DISPLAY... */ + if (display >= 0) { + envp = g_listenv(); + for (i = 0; envp[i]; i++) { + if (g_strcmp0(envp[i], "DISPLAY") == 0) { + s = g_strdup_printf("DISPLAY=:%i", display); + } else { + s = g_strdup_printf("%s=%s", envp[i], g_getenv(envp[i])); + } + g_free(envp[i]); + envp[i] = s; + } + } else { + envp = NULL; + } + + argc = 0; + argv[argc++] = g_strdup("nxproxy"); + argv[argc++] = g_strdup("-S"); + argv[argc++] = remmina_nx_session_get_proxy_option(nx); + argv[argc++] = NULL; + + ret = g_spawn_async(NULL, argv, envp, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &nx->proxy_pid, + &error); + g_strfreev(envp); + for (i = 0; i < argc; i++) + g_free(argv[i]); + + if (!ret) { + remmina_nx_session_set_application_error(nx, "%s", error->message); + return FALSE; + } + + if (exit_func) { + nx->proxy_watch_source = g_child_watch_add(nx->proxy_pid, exit_func, user_data); + } + + return TRUE; +} + +void remmina_nx_session_bye(RemminaNXSession *nx) +{ + TRACE_CALL(__func__); + remmina_nx_session_send_command(nx, "bye"); + remmina_nx_session_get_response(nx); +} + diff --git a/nx_session.h b/nx_session.h new file mode 100644 index 0000000..0d9d3b9 --- /dev/null +++ b/nx_session.h @@ -0,0 +1,107 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2010 Vic Lee + * Copyright (C) 2017 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. + * + */ + +#pragma once + +G_BEGIN_DECLS + +enum { + REMMINA_NX_SESSION_COLUMN_DISPLAY, + REMMINA_NX_SESSION_COLUMN_TYPE, + REMMINA_NX_SESSION_COLUMN_ID, + REMMINA_NX_SESSION_COLUMN_STATUS, + REMMINA_NX_SESSION_COLUMN_NAME, + REMMINA_NX_SESSION_N_COLUMNS +}; + +typedef struct _RemminaNXSession RemminaNXSession; + +typedef gboolean (*RemminaNXPassphraseCallback)(gchar **passphrase, gpointer userdata); +typedef void (*RemminaNXLogCallback)(const gchar *fmt, ...); + +RemminaNXSession* remmina_nx_session_new(void); + +void remmina_nx_session_free(RemminaNXSession *nx); + +gboolean remmina_nx_session_has_error(RemminaNXSession *nx); + +const gchar* remmina_nx_session_get_error(RemminaNXSession *nx); + +void remmina_nx_session_clear_error(RemminaNXSession *nx); + +void remmina_nx_session_set_encryption(RemminaNXSession *nx, gint encryption); + +void remmina_nx_session_set_localport(RemminaNXSession *nx, gint localport); + +void remmina_nx_session_set_log_callback(RemminaNXSession *nx, RemminaNXLogCallback log_callback); + +gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, + RemminaNXPassphraseCallback passphrase_func, gpointer userdata); + +gboolean remmina_nx_session_login(RemminaNXSession *nx, const gchar *username, const gchar *password); + +void remmina_nx_session_add_parameter(RemminaNXSession *nx, const gchar *name, const gchar *valuefmt, ...); + +gboolean remmina_nx_session_list(RemminaNXSession *nx); + +void remmina_nx_session_set_tree_view(RemminaNXSession *nx, GtkTreeView *tree); + +gboolean remmina_nx_session_iter_first(RemminaNXSession *nx, GtkTreeIter *iter); + +gboolean remmina_nx_session_iter_next(RemminaNXSession *nx, GtkTreeIter *iter); + +gchar* remmina_nx_session_iter_get(RemminaNXSession *nx, GtkTreeIter *iter, gint column); + +void remmina_nx_session_iter_set(RemminaNXSession *nx, GtkTreeIter *iter, gint column, const gchar *data); + +gboolean remmina_nx_session_allow_start(RemminaNXSession *nx); + +gboolean remmina_nx_session_start(RemminaNXSession *nx); + +gboolean remmina_nx_session_attach(RemminaNXSession *nx); + +gboolean remmina_nx_session_restore(RemminaNXSession *nx); + +gboolean remmina_nx_session_terminate(RemminaNXSession *nx); + +gboolean remmina_nx_session_tunnel_open(RemminaNXSession *nx); + +gboolean remmina_nx_session_invoke_proxy(RemminaNXSession *nx, gint display, GChildWatchFunc exit_func, gpointer user_data); + +void remmina_nx_session_bye(RemminaNXSession *nx); + +G_END_DECLS + + diff --git a/nx_session_manager.c b/nx_session_manager.c new file mode 100644 index 0000000..d6b1e02 --- /dev/null +++ b/nx_session_manager.c @@ -0,0 +1,244 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2010 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2017 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 +#include "nx_plugin.h" +#include "nx_session_manager.h" + +static void remmina_nx_session_manager_set_sensitive(RemminaProtocolWidget *gp, gboolean sensitive) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + + if (gpdata->attach_session) { + gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_TERMINATE, sensitive); + gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_ATTACH, sensitive); + }else { + gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_TERMINATE, sensitive); + gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_RESTORE, sensitive); + } +} + +static gboolean remmina_nx_session_manager_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, + gboolean path_currently_selected, gpointer user_data) +{ + TRACE_CALL(__func__); + RemminaProtocolWidget *gp = (RemminaProtocolWidget*)user_data; + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + + gpdata->manager_selected = FALSE; + if (path_currently_selected) { + remmina_nx_session_manager_set_sensitive(gp, FALSE); + return TRUE; + } + + if (!gtk_tree_model_get_iter(model, &gpdata->iter, path)) + return TRUE; + gpdata->manager_selected = TRUE; + remmina_nx_session_manager_set_sensitive(gp, TRUE); + return TRUE; +} + +static void remmina_nx_session_manager_send_signal(RemminaPluginNxData *gpdata, gint event_type) +{ + TRACE_CALL(__func__); + guchar dummy = (guchar)event_type; + /* Signal the NX thread to resume execution */ + if (write(gpdata->event_pipe[1], &dummy, 1)) { + } +} + +static void remmina_nx_session_manager_on_response(GtkWidget *dialog, gint response_id, RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + gint event_type; + + remmina_nx_session_manager_set_sensitive(gp, FALSE); + if (response_id <= 0) { + event_type = REMMINA_NX_EVENT_CANCEL; + }else { + event_type = response_id; + } + if (response_id == REMMINA_NX_EVENT_TERMINATE && gpdata->manager_selected) { + remmina_nx_session_iter_set(gpdata->nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_STATUS, _("Terminating")); + } + if (response_id != REMMINA_NX_EVENT_TERMINATE) { + gtk_widget_destroy(dialog); + gpdata->manager_dialog = NULL; + } + if (response_id != REMMINA_NX_EVENT_TERMINATE && response_id != REMMINA_NX_EVENT_CANCEL) { + remmina_plugin_nx_service->protocol_plugin_init_show(gp); + } + remmina_nx_session_manager_send_signal(gpdata, event_type); +} + +/* Handle double click on a row in the NX Session manager + * Automatically close the dialog using the default response id */ +void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + remmina_plugin_nx_service->log_printf("[NX] Default response_id %d\n", + gpdata->default_response); + + if (gpdata->default_response >= 0) { + gtk_dialog_response(GTK_DIALOG(gpdata->manager_dialog), gpdata->default_response); + } +} + +static gboolean remmina_nx_session_manager_main(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + RemminaFile *remminafile; + GtkWidget *dialog; + gchar *s; + GtkWidget *scrolledwindow; + GtkWidget *tree; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + remminafile = remmina_plugin_nx_service->protocol_plugin_get_file(gp); + + gpdata->default_response = -1; + if (!gpdata->manager_started) { + remmina_plugin_nx_service->protocol_plugin_init_hide(gp); + + dialog = gtk_dialog_new(); + s = g_strdup_printf(_("NX Sessions on %s"), remmina_plugin_nx_service->file_get_string(remminafile, "server")); + gtk_window_set_title(GTK_WINDOW(dialog), s); + g_free(s); + if (gpdata->attach_session) { + gtk_dialog_add_button(GTK_DIALOG(dialog), _("Attach"), REMMINA_NX_EVENT_ATTACH); + /* Set default response id for attach */ + gpdata->default_response = REMMINA_NX_EVENT_ATTACH; + }else { + gtk_dialog_add_button(GTK_DIALOG(dialog), _("Restore"), REMMINA_NX_EVENT_RESTORE); + gtk_dialog_add_button(GTK_DIALOG(dialog), _("Start"), REMMINA_NX_EVENT_START); + /* Set default response id for restore */ + gpdata->default_response = REMMINA_NX_EVENT_RESTORE; + } + gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Cancel"), REMMINA_NX_EVENT_CANCEL); + + gtk_dialog_add_button(GTK_DIALOG(dialog), _("Terminate"), REMMINA_NX_EVENT_TERMINATE); + + gtk_window_set_default_size(GTK_WINDOW(dialog), 640, 300); + gpdata->manager_dialog = dialog; + + scrolledwindow = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrolledwindow); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), scrolledwindow, TRUE, TRUE, 0); + + tree = gtk_tree_view_new(); + gtk_container_add(GTK_CONTAINER(scrolledwindow), tree); + gtk_widget_show(tree); + remmina_nx_session_set_tree_view(gpdata->nx, GTK_TREE_VIEW(tree)); + /* Handle double click on the row */ + g_signal_connect(G_OBJECT(tree), "row-activated", + G_CALLBACK(remmina_nx_session_manager_on_row_activated), gp); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("#", renderer, "text", REMMINA_NX_SESSION_COLUMN_ID, NULL); + gtk_tree_view_column_set_resizable(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_ID); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Type"), renderer, "text", REMMINA_NX_SESSION_COLUMN_TYPE, + NULL); + gtk_tree_view_column_set_resizable(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_TYPE); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Display"), renderer, "text", + REMMINA_NX_SESSION_COLUMN_DISPLAY, NULL); + gtk_tree_view_column_set_resizable(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_DISPLAY); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Status"), renderer, "text", + REMMINA_NX_SESSION_COLUMN_STATUS, NULL); + gtk_tree_view_column_set_resizable(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_STATUS); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", REMMINA_NX_SESSION_COLUMN_NAME, + NULL); + gtk_tree_view_column_set_resizable(column, TRUE); + gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_NAME); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + + gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), + remmina_nx_session_manager_selection_func, gp, NULL); + + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(remmina_nx_session_manager_on_response), gp); + gpdata->manager_started = TRUE; + } + gpdata->manager_selected = FALSE; + if (gpdata->manager_dialog) { + remmina_nx_session_manager_set_sensitive(gp, FALSE); + gtk_widget_show(gpdata->manager_dialog); + } + if (remmina_nx_session_has_error(gpdata->nx)) { + dialog = gtk_message_dialog_new((gpdata->manager_dialog ? GTK_WINDOW(gpdata->manager_dialog) : NULL), + GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", + remmina_nx_session_get_error(gpdata->nx)); + remmina_nx_session_clear_error(gpdata->nx); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + remmina_nx_session_manager_send_signal(gpdata, 0); + } + + gpdata->session_manager_start_handler = 0; + return FALSE; +} + +void remmina_nx_session_manager_start(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); + + if (gpdata->session_manager_start_handler == 0) { + gpdata->session_manager_start_handler = IDLE_ADD((GSourceFunc)remmina_nx_session_manager_main, gp); + } +} + diff --git a/nx_session_manager.h b/nx_session_manager.h new file mode 100644 index 0000000..b0db0c2 --- /dev/null +++ b/nx_session_manager.h @@ -0,0 +1,43 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2010 Vic Lee + * Copyright (C) 2017 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. + * + */ + +#pragma once + +G_BEGIN_DECLS + +void remmina_nx_session_manager_start(RemminaProtocolWidget *gp); + +G_END_DECLS + -- cgit v1.2.3 From f92fedf5cd2576dcce1f4459e6eebc978e26f15c Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Wed, 4 Apr 2018 23:20:32 +0200 Subject: Copyright update 2016-2018 --- CMakeLists.txt | 2 +- nx_plugin.c | 2 +- nx_plugin.h | 2 +- nx_session.c | 2 +- nx_session.h | 2 +- nx_session_manager.c | 2 +- nx_session_manager.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c383fbf..faeecd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # remmina-plugin-nx - The GTK+ Remote Desktop Client # # Copyright (C) 2011 Marc-Andre Moreau -# Copyright (C) 2014-2017 Antenore Gatta, Giovanni Panozzo +# Copyright (C) 2014-2018 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 diff --git a/nx_plugin.c b/nx_plugin.c index e1f87cd..1116c28 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010-2011 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2017 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2018 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 diff --git a/nx_plugin.h b/nx_plugin.h index 9a9e602..7ecf566 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2017 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2018 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 diff --git a/nx_session.c b/nx_session.c index fbf8b26..30862b6 100644 --- a/nx_session.c +++ b/nx_session.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2017 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2018 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 diff --git a/nx_session.h b/nx_session.h index 0d9d3b9..7afc2a2 100644 --- a/nx_session.h +++ b/nx_session.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-2018 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 diff --git a/nx_session_manager.c b/nx_session_manager.c index d6b1e02..5b479ad 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2017 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2018 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 diff --git a/nx_session_manager.h b/nx_session_manager.h index b0db0c2..11a6eb1 100644 --- a/nx_session_manager.h +++ b/nx_session_manager.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-2018 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 -- cgit v1.2.3 From 1e4701c7139efa21d25aaf6f7622e75bbb6b1438 Mon Sep 17 00:00:00 2001 From: Denis Ollier Date: Sat, 14 Apr 2018 22:39:57 +0200 Subject: Remove checks for GTK >= 3 since GTK2 is not supported anymore --- nx_plugin.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 1116c28..16959b4 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -37,9 +37,7 @@ #include #include #include "common/remmina_plugin.h" -#if GTK_VERSION == 3 -# include -#endif +#include #include #define LIBSSH_STATIC 1 #include -- cgit v1.2.3 From 68a728ca92be951f929b03ff15805c40c7170b7e Mon Sep 17 00:00:00 2001 From: Denis Ollier Date: Sat, 21 Apr 2018 14:52:51 +0200 Subject: nx: remove unused remminafile variable --- nx_plugin.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 16959b4..c981154 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -577,7 +577,6 @@ static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); - RemminaFile *remminafile; gint width, height; if (!remmina_plugin_nx_service->gtksocket_available()) { @@ -587,8 +586,6 @@ static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) return FALSE; } - remminafile = remmina_plugin_nx_service->protocol_plugin_get_file(gp); - width = remmina_plugin_nx_service->get_profile_remote_width(gp); height = remmina_plugin_nx_service->get_profile_remote_height(gp); -- cgit v1.2.3 From 75da3d9521cca8b2b37b251bfb5cf74b9eebab76 Mon Sep 17 00:00:00 2001 From: Denis Ollier Date: Fri, 4 May 2018 09:30:32 +0200 Subject: plugins: explicitly set screenshot callback --- nx_plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_plugin.c b/nx_plugin.c index c981154..0155d14 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -748,7 +748,7 @@ static RemminaProtocolPlugin remmina_plugin_nx = remmina_plugin_nx_query_feature, // Query for available features remmina_plugin_nx_call_feature, // Call a feature NULL, // Send a keystroke - NULL // Screenshot + NULL // No screenshot support available }; G_MODULE_EXPORT gboolean -- cgit v1.2.3 From 9ab7d0ad4c0742dd328a24a5686c13b039aed600 Mon Sep 17 00:00:00 2001 From: Denis Ollier Date: Fri, 11 May 2018 18:32:27 +0200 Subject: nx: fix libssh deprecations --- nx_session.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/nx_session.c b/nx_session.c index 30862b6..19a2438 100644 --- a/nx_session.c +++ b/nx_session.c @@ -258,7 +258,7 @@ static gboolean remmina_nx_session_get_response(RemminaNXSession *nx) TRACE_CALL(__func__); struct timeval timeout; ssh_channel ch[2]; - ssh_buffer buffer; + gchar *buffer; gint len; gint is_stderr; @@ -282,23 +282,17 @@ static gboolean remmina_nx_session_get_response(RemminaNXSession *nx) if (is_stderr > 1) return FALSE; - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - buffer = buffer_new(); - len = channel_read_buffer(nx->channel, buffer, len, is_stderr); - G_GNUC_END_IGNORE_DEPRECATIONS + buffer = g_malloc(sizeof(*buffer) * len); + len = ssh_channel_read(nx->channel, buffer, len, is_stderr); if (len <= 0) { remmina_nx_session_set_application_error(nx, "Channel closed."); return FALSE; } if (len > 0) { - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - g_string_append_len(nx->response, (const gchar*)buffer_get(buffer), len); - G_GNUC_END_IGNORE_DEPRECATIONS + g_string_append_len(nx->response, buffer, len); } - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - buffer_free(buffer); - G_GNUC_END_IGNORE_DEPRECATIONS + g_free(buffer); return TRUE; } @@ -833,9 +827,7 @@ static gpointer remmina_nx_session_tunnel_main_thread(gpointer data) else if (len > 0) { for (ptr = buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw) { ssh_set_fd_towrite(nx->session); - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - lenw = channel_write(channels[0], (char*)ptr, len); - G_GNUC_END_IGNORE_DEPRECATIONS + lenw = ssh_channel_write(channels[0], (char*)ptr, len); if (lenw <= 0) { nx->running = FALSE; break; @@ -848,9 +840,7 @@ static gpointer remmina_nx_session_tunnel_main_thread(gpointer data) break; if (channels_out[0] && socketbuffer_len <= 0) { - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - len = channel_read_nonblocking(channels_out[0], socketbuffer, sizeof(socketbuffer), 0); - G_GNUC_END_IGNORE_DEPRECATIONS + len = ssh_channel_read_nonblocking(channels_out[0], socketbuffer, sizeof(socketbuffer), 0); if (len == SSH_ERROR || len == SSH_EOF) { nx->running = FALSE; break; @@ -859,13 +849,11 @@ static gpointer remmina_nx_session_tunnel_main_thread(gpointer data) socketbuffer_len = len; } else { /* Clean up the stderr buffer in case FreeNX send something there */ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - len = channel_read_nonblocking(channels_out[0], buffer, sizeof(buffer), 1); + len = ssh_channel_read_nonblocking(channels_out[0], buffer, sizeof(buffer), 1); if (len == SSH_ERROR || len == SSH_EOF) { nx->running = FALSE; break; } - G_GNUC_END_IGNORE_DEPRECATIONS } } -- cgit v1.2.3 From 8cd3c44d56ac8cae65f07851c489fa76d85f1ea2 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Sun, 3 Jun 2018 02:05:12 +0200 Subject: New icons preview --- 16x16/emblems/remmina-nx.png | Bin 426 -> 261 bytes 22x22/emblems/remmina-nx.png | Bin 788 -> 273 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/16x16/emblems/remmina-nx.png b/16x16/emblems/remmina-nx.png index 9d1b952..5dc10db 100644 Binary files a/16x16/emblems/remmina-nx.png and b/16x16/emblems/remmina-nx.png differ diff --git a/22x22/emblems/remmina-nx.png b/22x22/emblems/remmina-nx.png index 13766da..3b44056 100644 Binary files a/22x22/emblems/remmina-nx.png and b/22x22/emblems/remmina-nx.png differ -- cgit v1.2.3 From 1ee3d597f9aee9cff2a1a81783ccf221a8c01b31 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Mon, 4 Jun 2018 09:23:27 +0200 Subject: New icons all sizes --- 16x16/emblems/remmina-nx.png | Bin 261 -> 322 bytes 22x22/emblems/remmina-nx.png | Bin 273 -> 337 bytes 24x24/emblems/remmina-nx.png | Bin 0 -> 359 bytes 32x32/emblems/remmina-nx.png | Bin 0 -> 418 bytes 48x48/emblems/remmina-nx.png | Bin 0 -> 428 bytes 64x64/emblems/remmina-nx.png | Bin 0 -> 515 bytes scalable/emblems/remmina-nx.svg | 99 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 99 insertions(+) create mode 100644 24x24/emblems/remmina-nx.png create mode 100644 32x32/emblems/remmina-nx.png create mode 100644 48x48/emblems/remmina-nx.png create mode 100644 64x64/emblems/remmina-nx.png create mode 100644 scalable/emblems/remmina-nx.svg diff --git a/16x16/emblems/remmina-nx.png b/16x16/emblems/remmina-nx.png index 5dc10db..04e3ad4 100644 Binary files a/16x16/emblems/remmina-nx.png and b/16x16/emblems/remmina-nx.png differ diff --git a/22x22/emblems/remmina-nx.png b/22x22/emblems/remmina-nx.png index 3b44056..d159e3e 100644 Binary files a/22x22/emblems/remmina-nx.png and b/22x22/emblems/remmina-nx.png differ diff --git a/24x24/emblems/remmina-nx.png b/24x24/emblems/remmina-nx.png new file mode 100644 index 0000000..df646f7 Binary files /dev/null and b/24x24/emblems/remmina-nx.png differ diff --git a/32x32/emblems/remmina-nx.png b/32x32/emblems/remmina-nx.png new file mode 100644 index 0000000..5e5f246 Binary files /dev/null and b/32x32/emblems/remmina-nx.png differ diff --git a/48x48/emblems/remmina-nx.png b/48x48/emblems/remmina-nx.png new file mode 100644 index 0000000..bdea4fa Binary files /dev/null and b/48x48/emblems/remmina-nx.png differ diff --git a/64x64/emblems/remmina-nx.png b/64x64/emblems/remmina-nx.png new file mode 100644 index 0000000..82da026 Binary files /dev/null and b/64x64/emblems/remmina-nx.png differ diff --git a/scalable/emblems/remmina-nx.svg b/scalable/emblems/remmina-nx.svg new file mode 100644 index 0000000..a6c7bd1 --- /dev/null +++ b/scalable/emblems/remmina-nx.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + -- cgit v1.2.3 From 4aade0d4d7c3cb13d5d0419f715c530b67dde810 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Tue, 5 Jun 2018 22:26:22 +0200 Subject: Migrating to SVG icons format --- 16x16/emblems/remmina-nx.png | Bin 322 -> 0 bytes 16x16/emblems/remmina-nx.svg | 49 +++++++++++++++++++++++++++++++++++++++++++ 22x22/emblems/remmina-nx.png | Bin 337 -> 0 bytes 22x22/emblems/remmina-nx.svg | 49 +++++++++++++++++++++++++++++++++++++++++++ 24x24/emblems/remmina-nx.png | Bin 359 -> 0 bytes 24x24/emblems/remmina-nx.svg | 49 +++++++++++++++++++++++++++++++++++++++++++ 32x32/emblems/remmina-nx.png | Bin 418 -> 0 bytes 32x32/emblems/remmina-nx.svg | 49 +++++++++++++++++++++++++++++++++++++++++++ 48x48/emblems/remmina-nx.png | Bin 428 -> 0 bytes 48x48/emblems/remmina-nx.svg | 49 +++++++++++++++++++++++++++++++++++++++++++ 64x64/emblems/remmina-nx.png | Bin 515 -> 0 bytes 64x64/emblems/remmina-nx.svg | 49 +++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 4 ++-- 13 files changed, 296 insertions(+), 2 deletions(-) delete mode 100644 16x16/emblems/remmina-nx.png create mode 100644 16x16/emblems/remmina-nx.svg delete mode 100644 22x22/emblems/remmina-nx.png create mode 100644 22x22/emblems/remmina-nx.svg delete mode 100644 24x24/emblems/remmina-nx.png create mode 100644 24x24/emblems/remmina-nx.svg delete mode 100644 32x32/emblems/remmina-nx.png create mode 100644 32x32/emblems/remmina-nx.svg delete mode 100644 48x48/emblems/remmina-nx.png create mode 100644 48x48/emblems/remmina-nx.svg delete mode 100644 64x64/emblems/remmina-nx.png create mode 100644 64x64/emblems/remmina-nx.svg diff --git a/16x16/emblems/remmina-nx.png b/16x16/emblems/remmina-nx.png deleted file mode 100644 index 04e3ad4..0000000 Binary files a/16x16/emblems/remmina-nx.png and /dev/null differ diff --git a/16x16/emblems/remmina-nx.svg b/16x16/emblems/remmina-nx.svg new file mode 100644 index 0000000..af290e9 --- /dev/null +++ b/16x16/emblems/remmina-nx.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/22x22/emblems/remmina-nx.png b/22x22/emblems/remmina-nx.png deleted file mode 100644 index d159e3e..0000000 Binary files a/22x22/emblems/remmina-nx.png and /dev/null differ diff --git a/22x22/emblems/remmina-nx.svg b/22x22/emblems/remmina-nx.svg new file mode 100644 index 0000000..af290e9 --- /dev/null +++ b/22x22/emblems/remmina-nx.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/24x24/emblems/remmina-nx.png b/24x24/emblems/remmina-nx.png deleted file mode 100644 index df646f7..0000000 Binary files a/24x24/emblems/remmina-nx.png and /dev/null differ diff --git a/24x24/emblems/remmina-nx.svg b/24x24/emblems/remmina-nx.svg new file mode 100644 index 0000000..af290e9 --- /dev/null +++ b/24x24/emblems/remmina-nx.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/32x32/emblems/remmina-nx.png b/32x32/emblems/remmina-nx.png deleted file mode 100644 index 5e5f246..0000000 Binary files a/32x32/emblems/remmina-nx.png and /dev/null differ diff --git a/32x32/emblems/remmina-nx.svg b/32x32/emblems/remmina-nx.svg new file mode 100644 index 0000000..af290e9 --- /dev/null +++ b/32x32/emblems/remmina-nx.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/48x48/emblems/remmina-nx.png b/48x48/emblems/remmina-nx.png deleted file mode 100644 index bdea4fa..0000000 Binary files a/48x48/emblems/remmina-nx.png and /dev/null differ diff --git a/48x48/emblems/remmina-nx.svg b/48x48/emblems/remmina-nx.svg new file mode 100644 index 0000000..af290e9 --- /dev/null +++ b/48x48/emblems/remmina-nx.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/64x64/emblems/remmina-nx.png b/64x64/emblems/remmina-nx.png deleted file mode 100644 index 82da026..0000000 Binary files a/64x64/emblems/remmina-nx.png and /dev/null differ diff --git a/64x64/emblems/remmina-nx.svg b/64x64/emblems/remmina-nx.svg new file mode 100644 index 0000000..af290e9 --- /dev/null +++ b/64x64/emblems/remmina-nx.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/CMakeLists.txt b/CMakeLists.txt index faeecd9..0c33aab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,8 +58,8 @@ target_link_libraries(remmina-plugin-nx install(TARGETS remmina-plugin-nx DESTINATION ${REMMINA_PLUGINDIR}) install(FILES - 16x16/emblems/remmina-nx.png + 16x16/emblems/remmina-nx.svg DESTINATION ${APPICON16_EMBLEMS_DIR}) install(FILES - 22x22/emblems/remmina-nx.png + 22x22/emblems/remmina-nx.svg DESTINATION ${APPICON22_EMBLEMS_DIR}) -- cgit v1.2.3 From 4cae6b31998cd05f394a480cad56b5040287c3cd Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Fri, 8 Jun 2018 17:36:28 +0200 Subject: Moving to symbolic icons to match theme colors --- 16x16/emblems/remmina-nx.svg | 49 ---------------- 22x22/emblems/remmina-nx.svg | 49 ---------------- 24x24/emblems/remmina-nx.svg | 49 ---------------- 32x32/emblems/remmina-nx.svg | 49 ---------------- 48x48/emblems/remmina-nx.svg | 49 ---------------- 64x64/emblems/remmina-nx.svg | 49 ---------------- CMakeLists.txt | 7 +-- nx_plugin.c | 4 +- scalable/emblems/remmina-nx-symbolic.svg | 99 ++++++++++++++++++++++++++++++++ scalable/emblems/remmina-nx.svg | 99 -------------------------------- 10 files changed, 103 insertions(+), 400 deletions(-) delete mode 100644 16x16/emblems/remmina-nx.svg delete mode 100644 22x22/emblems/remmina-nx.svg delete mode 100644 24x24/emblems/remmina-nx.svg delete mode 100644 32x32/emblems/remmina-nx.svg delete mode 100644 48x48/emblems/remmina-nx.svg delete mode 100644 64x64/emblems/remmina-nx.svg create mode 100644 scalable/emblems/remmina-nx-symbolic.svg delete mode 100644 scalable/emblems/remmina-nx.svg diff --git a/16x16/emblems/remmina-nx.svg b/16x16/emblems/remmina-nx.svg deleted file mode 100644 index af290e9..0000000 --- a/16x16/emblems/remmina-nx.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/22x22/emblems/remmina-nx.svg b/22x22/emblems/remmina-nx.svg deleted file mode 100644 index af290e9..0000000 --- a/22x22/emblems/remmina-nx.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/24x24/emblems/remmina-nx.svg b/24x24/emblems/remmina-nx.svg deleted file mode 100644 index af290e9..0000000 --- a/24x24/emblems/remmina-nx.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/32x32/emblems/remmina-nx.svg b/32x32/emblems/remmina-nx.svg deleted file mode 100644 index af290e9..0000000 --- a/32x32/emblems/remmina-nx.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/48x48/emblems/remmina-nx.svg b/48x48/emblems/remmina-nx.svg deleted file mode 100644 index af290e9..0000000 --- a/48x48/emblems/remmina-nx.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/64x64/emblems/remmina-nx.svg b/64x64/emblems/remmina-nx.svg deleted file mode 100644 index af290e9..0000000 --- a/64x64/emblems/remmina-nx.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c33aab..7d073a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,8 +58,5 @@ target_link_libraries(remmina-plugin-nx install(TARGETS remmina-plugin-nx DESTINATION ${REMMINA_PLUGINDIR}) install(FILES - 16x16/emblems/remmina-nx.svg - DESTINATION ${APPICON16_EMBLEMS_DIR}) -install(FILES - 22x22/emblems/remmina-nx.svg - DESTINATION ${APPICON22_EMBLEMS_DIR}) + scalable/emblems/remmina-nx-symbolic.svg + DESTINATION ${APPICONSCALE_EMBLEMS_DIR}) diff --git a/nx_plugin.c b/nx_plugin.c index 0155d14..f4af629 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -736,8 +736,8 @@ static RemminaProtocolPlugin remmina_plugin_nx = N_("NX - NX Technology"), // Description GETTEXT_PACKAGE, // Translation domain VERSION, // Version number - "remmina-nx", // Icon for normal connection - "remmina-nx", // Icon for SSH connection + "remmina-nx-symbolic", // Icon for normal connection + "remmina-nx-symbolic", // Icon for SSH connection remmina_plugin_nx_basic_settings, // Array for basic settings remmina_plugin_nx_advanced_settings, // Array for advanced settings REMMINA_PROTOCOL_SSH_SETTING_TUNNEL, // SSH settings type diff --git a/scalable/emblems/remmina-nx-symbolic.svg b/scalable/emblems/remmina-nx-symbolic.svg new file mode 100644 index 0000000..a6c7bd1 --- /dev/null +++ b/scalable/emblems/remmina-nx-symbolic.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/scalable/emblems/remmina-nx.svg b/scalable/emblems/remmina-nx.svg deleted file mode 100644 index a6c7bd1..0000000 --- a/scalable/emblems/remmina-nx.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - -- cgit v1.2.3 From 49f37a8b125c413abc768152c3e3201e76796f2e Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Thu, 27 Sep 2018 00:33:00 +0200 Subject: Plugin declare it uses GtkSocket and rcw block the call if not supported --- nx_plugin.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nx_plugin.c b/nx_plugin.c index f4af629..d617b86 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -48,6 +48,7 @@ #include "nx_session_manager.h" #define REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL 1 +#define REMMINA_PLUGIN_NX_FEATURE_GTKSOCKET 1 /* Forward declaration */ static RemminaProtocolPlugin remmina_plugin_nx; @@ -725,6 +726,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[] = static const RemminaProtocolFeature remmina_plugin_nx_features[] = { { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL, N_("Send Ctrl+Alt+Delete"), NULL, NULL }, + { REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET, REMMINA_PLUGIN_NX_FEATURE_GTKSOCKET, NULL, NULL, NULL}, { REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL } }; -- cgit v1.2.3 From 4d28974bc73cdbac7bdec302aba6e333e647ba50 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Sat, 5 Jan 2019 02:37:22 +0100 Subject: Gtk icon cache update during install phase --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d073a3..9f89baf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,3 +60,5 @@ install(TARGETS remmina-plugin-nx DESTINATION ${REMMINA_PLUGINDIR}) install(FILES scalable/emblems/remmina-nx-symbolic.svg DESTINATION ${APPICONSCALE_EMBLEMS_DIR}) + +gtk_update_icon_cache("${REMMINA_DATADIR}/icons/hicolor") -- cgit v1.2.3 From 44447b9e1bec14ff5d97929360fe4d7c9c78aee5 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Thu, 10 Jan 2019 01:02:37 +0100 Subject: Updating coyright for year 2019 --- CMakeLists.txt | 2 +- nx_plugin.c | 2 +- nx_plugin.h | 2 +- nx_session.c | 2 +- nx_session.h | 2 +- nx_session_manager.c | 2 +- nx_session_manager.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f89baf..39644db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # remmina-plugin-nx - The GTK+ Remote Desktop Client # # Copyright (C) 2011 Marc-Andre Moreau -# Copyright (C) 2014-2018 Antenore Gatta, Giovanni Panozzo +# Copyright (C) 2014-2019 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 diff --git a/nx_plugin.c b/nx_plugin.c index d617b86..345f096 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010-2011 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2019 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 diff --git a/nx_plugin.h b/nx_plugin.h index 7ecf566..1122a78 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2019 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 diff --git a/nx_session.c b/nx_session.c index 19a2438..c8ec930 100644 --- a/nx_session.c +++ b/nx_session.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2019 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 diff --git a/nx_session.h b/nx_session.h index 7afc2a2..d97efae 100644 --- a/nx_session.h +++ b/nx_session.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017-2018 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-2019 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 diff --git a/nx_session_manager.c b/nx_session_manager.c index 5b479ad..bf43628 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2019 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 diff --git a/nx_session_manager.h b/nx_session_manager.h index 11a6eb1..add497f 100644 --- a/nx_session_manager.h +++ b/nx_session_manager.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017-2018 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-2019 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 -- cgit v1.2.3 From 3e1515960f3908253f8fc4e607fa93494bc9d17e Mon Sep 17 00:00:00 2001 From: Davy Defaud Date: Sun, 27 Jan 2019 17:30:54 +0100 Subject: =?UTF-8?q?Fix=20English=20typo=20transmittion=20=E2=86=92=20trans?= =?UTF-8?q?mission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nx_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_session.c b/nx_session.c index c8ec930..a717d19 100644 --- a/nx_session.c +++ b/nx_session.c @@ -804,7 +804,7 @@ static gpointer remmina_nx_session_tunnel_main_thread(gpointer data) channels[0] = nx->channel; channels[1] = NULL; - /* Start the tunnel data transmittion */ + /* Start the tunnel data transmission */ while (nx->running) { timeout.tv_sec = 1; timeout.tv_usec = 0; -- cgit v1.2.3 From 653ef08a74481842888c97b4a9c971b03baa39b4 Mon Sep 17 00:00:00 2001 From: Davy Defaud Date: Sun, 27 Jan 2019 19:08:53 +0100 Subject: Replace all triple points by ellipsis characters Remove spaces before ellipsis, except for German. --- nx_plugin.c | 2 +- nx_session.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 345f096..ed4488d 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -598,7 +598,7 @@ static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) if (pthread_create(&gpdata->thread, NULL, remmina_plugin_nx_main_thread, gp)) { remmina_plugin_nx_service->protocol_plugin_set_error(gp, - "Failed to initialize pthread. Falling back to non-thread mode..."); + "Failed to initialize pthread. Falling back to non-thread mode…"); gpdata->thread = 0; return FALSE; }else { diff --git a/nx_session.c b/nx_session.c index a717d19..da8cd2d 100644 --- a/nx_session.c +++ b/nx_session.c @@ -960,7 +960,7 @@ gboolean remmina_nx_session_invoke_proxy(RemminaNXSession *nx, gint display, GCh gchar *s; gint i; - /* Copy all current environment variable, but change DISPLAY. Assume we should always have DISPLAY... */ + /* Copy all current environment variable, but change DISPLAY. Assume we should always have DISPLAY… */ if (display >= 0) { envp = g_listenv(); for (i = 0; envp[i]; i++) { -- cgit v1.2.3 From bb864d77d5e7336e26ce3c5b7c59d8d2bcd2b1ca Mon Sep 17 00:00:00 2001 From: Davy Defaud Date: Sun, 27 Jan 2019 19:47:11 +0100 Subject: Replace single quotes by true apostrophes --- nx_session.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx_session.c b/nx_session.c index da8cd2d..49ed006 100644 --- a/nx_session.c +++ b/nx_session.c @@ -340,7 +340,7 @@ static void remmina_nx_session_parse_session_list_line(RemminaNXSession *nx, con p2++; p1 = p2; } - /* The last name column might contains space so it's not in the above loop. We simply rtrim it here. */ + /* The last name column might contains space so it’s not in the above loop. We simply rtrim it here. */ i = strlen(p1); if (i < 1) return; @@ -557,7 +557,7 @@ gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guin } g_free(passphrase); } else { - /* Use NoMachine's default nx private key */ + /* Use NoMachine’s default nx private key */ if ( ssh_pki_import_privkey_base64(nx_default_private_key, NULL, NULL, NULL, &priv_key) != SSH_OK ) { remmina_nx_session_set_application_error(nx, "Failed to import NX default private key."); return FALSE; @@ -861,7 +861,7 @@ static gpointer remmina_nx_session_tunnel_main_thread(gpointer data) for (lenw = 0; socketbuffer_len > 0; socketbuffer_len -= lenw, socketbuffer_ptr += lenw) { lenw = write(sock, socketbuffer_ptr, socketbuffer_len); if (lenw == -1 && errno == EAGAIN && nx->running) { - /* Sometimes we cannot write to a socket (always EAGAIN), probably because it's internal + /* Sometimes we cannot write to a socket (always EAGAIN), probably because it’s internal * buffer is full. We need read the pending bytes from the socket first. so here we simply * break, leave the buffer there, and continue with other data */ break; @@ -893,7 +893,7 @@ gboolean remmina_nx_session_tunnel_open(RemminaNXSession *nx) remmina_nx_session_send_command(nx, "bye"); if (!remmina_nx_session_expect_status(nx, 999)) { /* Shoud not happen, just in case */ - remmina_nx_session_set_application_error(nx, "Server won't say bye to us?"); + remmina_nx_session_set_application_error(nx, "Server won’t say bye to us?"); return FALSE; } -- cgit v1.2.3 From e67418603accac0587b2f70258fdf2b8a9ed5145 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Tue, 18 Jun 2019 23:02:51 +0200 Subject: Fixing typos of X.Org, Java and H.264 --- nx_plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_plugin.c b/nx_plugin.c index ed4488d..4bb3eab 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -582,7 +582,7 @@ static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) if (!remmina_plugin_nx_service->gtksocket_available()) { remmina_plugin_nx_service->protocol_plugin_set_error(gp, - _("Protocol %s is unavailable because GtkSocket only works under Xorg"), + _("Protocol %s is unavailable because GtkSocket only works under X.Org"), remmina_plugin_nx.name); return FALSE; } -- cgit v1.2.3 From aa3ee84746572ffdfe60935acc01c5b8d1961565 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Wed, 31 Jul 2019 01:56:49 +0200 Subject: Make icon cache optional. Partly solve #1045 --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39644db..604c0a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,4 +61,6 @@ install(FILES scalable/emblems/remmina-nx-symbolic.svg DESTINATION ${APPICONSCALE_EMBLEMS_DIR}) -gtk_update_icon_cache("${REMMINA_DATADIR}/icons/hicolor") +if(WITH_ICON_CACHE) + gtk_update_icon_cache("${REMMINA_DATADIR}/icons/hicolor") +endif() -- cgit v1.2.3 From ee36cd7eae226934c42e950eb69c599e62d07d80 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Sat, 7 Sep 2019 01:06:15 +0200 Subject: Adding setting tooltip in the remmina profile editor --- nx_plugin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 4bb3eab..68c9973 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -689,7 +689,7 @@ static gpointer quality_list[] = * c) Setting description * d) Compact disposition * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO - * f) Unused pointer + * f) Setting Tooltip */ static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = { @@ -710,7 +710,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = * c) Setting description * d) Compact disposition * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO - * f) Unused pointer + * f) Setting Tooltip */ static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[] = { -- cgit v1.2.3 From eb80f36aa98dc5bbbcc4a67cf21f659e459bafdb Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Sun, 29 Sep 2019 00:20:17 +0200 Subject: Fixing username typo --- nx_plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_plugin.c b/nx_plugin.c index 68c9973..34f44e0 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -695,7 +695,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = { { REMMINA_PROTOCOL_SETTING_TYPE_SERVER, "server", NULL, FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_FILE, "nx_privatekey", N_("Identity file"), FALSE, NULL, NULL }, - { REMMINA_PROTOCOL_SETTING_TYPE_TEXT, "username", N_("User name"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_TEXT, "username", N_("Username"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD, "password", N_("User password"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_RESOLUTION, "resolution", NULL, FALSE, GINT_TO_POINTER(1), NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_SELECT, "quality", N_("Quality"), FALSE, quality_list, NULL }, -- cgit v1.2.3 From 5f6dcafd264ab2eeb7aa0863f8a299c0b3911f2d Mon Sep 17 00:00:00 2001 From: Giovanni Panozzo Date: Sun, 27 Oct 2019 21:41:37 +0100 Subject: Plugin connection close refactoring --- nx_plugin.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 34f44e0..c16f0bf 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -182,13 +182,13 @@ static void remmina_plugin_nx_remove_window_id(Window window_id) static void remmina_plugin_nx_on_plug_added(GtkSocket *socket, RemminaProtocolWidget *gp) { TRACE_CALL(__func__); - remmina_plugin_nx_service->protocol_plugin_emit_signal(gp, "connect"); + remmina_plugin_nx_service->protocol_plugin_signal_connection_opened(gp); } static void remmina_plugin_nx_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp) { TRACE_CALL(__func__); - remmina_plugin_nx_service->protocol_plugin_close_connection(gp); + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); } gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userdata) @@ -212,7 +212,7 @@ static void remmina_plugin_nx_on_proxy_exit(GPid pid, gint status, gpointer data TRACE_CALL(__func__); RemminaProtocolWidget *gp = (RemminaProtocolWidget*)data; - remmina_plugin_nx_service->protocol_plugin_close_connection(gp); + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); } static int remmina_plugin_nx_dummy_handler(Display *dsp, XErrorEvent *err) @@ -539,11 +539,12 @@ static gboolean remmina_plugin_nx_main(RemminaProtocolWidget *gp) static gpointer remmina_plugin_nx_main_thread(gpointer data) { TRACE_CALL(__func__); + RemminaProtocolWidget *gp = (RemminaProtocolWidget *)data; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); CANCEL_ASYNC - if (!remmina_plugin_nx_main((RemminaProtocolWidget*)data)) { - IDLE_ADD((GSourceFunc)remmina_plugin_nx_service->protocol_plugin_close_connection, data); + if (!remmina_plugin_nx_main(gp)) { + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); } return NULL; } @@ -638,7 +639,7 @@ static gboolean remmina_plugin_nx_close_connection(RemminaProtocolWidget *gp) close(gpdata->event_pipe[0]); close(gpdata->event_pipe[1]); - remmina_plugin_nx_service->protocol_plugin_emit_signal(gp, "disconnect"); + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } @@ -795,4 +796,3 @@ remmina_plugin_entry(RemminaPluginService *service) return TRUE; } - -- cgit v1.2.3 From b5233e33ef48e66a4e4a887d8c37482450dabaaf Mon Sep 17 00:00:00 2001 From: Giovanni Panozzo Date: Thu, 31 Oct 2019 23:25:10 +0100 Subject: Better messagepanel plugin API --- nx_plugin.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index c16f0bf..8b98f1c 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -198,13 +198,16 @@ gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userda gint ret; /* SSH passwords must not be saved */ - ret = remmina_plugin_nx_service->protocol_plugin_init_authpwd(gp, REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY, FALSE); - - if (ret != GTK_RESPONSE_OK) + ret = remmina_plugin_nx_service->protocol_plugin_init_auth(gp, 0, + _("SSH credentials"), NULL, + NULL, + NULL, + _("SSH private key passphrase")); + if (ret == GTK_RESPONSE_OK) { + *passphrase = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); + return TRUE; + } else return FALSE; - *passphrase = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); - - return TRUE; } static void remmina_plugin_nx_on_proxy_exit(GPid pid, gint status, gpointer data) @@ -355,15 +358,34 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) g_free(s1); g_free(s2); + gchar *s_username, *s_password; + disablepasswordstoring = remmina_plugin_nx_service->file_get_int(remminafile, "disablepasswordstoring", FALSE); - ret = remmina_plugin_nx_service->protocol_plugin_init_authuserpwd(gp, FALSE, !disablepasswordstoring); - if (ret != GTK_RESPONSE_OK) - return FALSE; + ret = remmina_plugin_nx_service->protocol_plugin_init_auth(gp, + (disablepasswordstoring ? 0 : REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD) | REMMINA_MESSAGE_PANEL_FLAG_USERNAME, + _("Enter NX authentication credentials"), + remmina_plugin_nx_service->file_get_string(remminafile, "username"), + remmina_plugin_nx_service->file_get_string(remminafile, "password"), + NULL, + NULL); + if (ret == GTK_RESPONSE_OK) { + gboolean save; + s_username = remmina_plugin_nx_service->protocol_plugin_init_get_username(gp); + s_password = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); + save = remmina_plugin_nx_service->protocol_plugin_init_get_savepassword(gp); + if (save) { + remmina_plugin_nx_service->file_set_string(remminafile, "username", s_username); + remmina_plugin_nx_service->file_set_string(remminafile, "password", s_password); + } else + remmina_plugin_nx_service->file_unsave_passwords(remminafile); + } else { + return False; + } - s1 = remmina_plugin_nx_service->protocol_plugin_init_get_username(gp); - s2 = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); - ret = remmina_nx_session_login(nx, s1, s2); + ret = remmina_nx_session_login(nx, s_username, s_password); + g_free(s_username); + g_free(s_password); } g_free(s1); g_free(s2); -- cgit v1.2.3 From c5923fc3cc4434f6da092e42e99013269abe85ba Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Sun, 3 Nov 2019 15:37:36 +0100 Subject: Code cleaning --- nx_plugin.h | 31 +++++++++++++++---------------- nx_session.h | 11 ++++------- nx_session_manager.h | 1 - 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/nx_plugin.h b/nx_plugin.h index 1122a78..a55849b 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -36,7 +36,7 @@ #pragma once -#define GET_PLUGIN_DATA(gp) (RemminaPluginNxData*)g_object_get_data(G_OBJECT(gp), "plugin-data"); +#define GET_PLUGIN_DATA(gp) (RemminaPluginNxData *)g_object_get_data(G_OBJECT(gp), "plugin-data"); G_BEGIN_DECLS @@ -51,31 +51,30 @@ typedef enum { } RemminaNXEventType; typedef struct _RemminaPluginNxData { - GtkWidget *socket; - gint socket_id; + GtkWidget * socket; + gint socket_id; - pthread_t thread; + pthread_t thread; - RemminaNXSession *nx; + RemminaNXSession * nx; - Display *display; - Window window_id; + Display * display; + Window window_id; int (*orig_handler)(Display *, XErrorEvent *); /* Session Manager data */ - gboolean manager_started; - GtkWidget *manager_dialog; - gboolean manager_selected; + gboolean manager_started; + GtkWidget * manager_dialog; + gboolean manager_selected; /* Communication between the NX thread and the session manager */ - gint event_pipe[2]; - guint session_manager_start_handler; - gboolean attach_session; - GtkTreeIter iter; - gint default_response; + gint event_pipe[2]; + guint session_manager_start_handler; + gboolean attach_session; + GtkTreeIter iter; + gint default_response; } RemminaPluginNxData; extern RemminaPluginService *remmina_plugin_nx_service; G_END_DECLS - diff --git a/nx_session.h b/nx_session.h index d97efae..a59efc5 100644 --- a/nx_session.h +++ b/nx_session.h @@ -51,13 +51,13 @@ typedef struct _RemminaNXSession RemminaNXSession; typedef gboolean (*RemminaNXPassphraseCallback)(gchar **passphrase, gpointer userdata); typedef void (*RemminaNXLogCallback)(const gchar *fmt, ...); -RemminaNXSession* remmina_nx_session_new(void); +RemminaNXSession *remmina_nx_session_new(void); void remmina_nx_session_free(RemminaNXSession *nx); gboolean remmina_nx_session_has_error(RemminaNXSession *nx); -const gchar* remmina_nx_session_get_error(RemminaNXSession *nx); +const gchar *remmina_nx_session_get_error(RemminaNXSession *nx); void remmina_nx_session_clear_error(RemminaNXSession *nx); @@ -67,8 +67,7 @@ void remmina_nx_session_set_localport(RemminaNXSession *nx, gint localport); void remmina_nx_session_set_log_callback(RemminaNXSession *nx, RemminaNXLogCallback log_callback); -gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, - RemminaNXPassphraseCallback passphrase_func, gpointer userdata); +gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, RemminaNXPassphraseCallback passphrase_func, gpointer userdata); gboolean remmina_nx_session_login(RemminaNXSession *nx, const gchar *username, const gchar *password); @@ -82,7 +81,7 @@ gboolean remmina_nx_session_iter_first(RemminaNXSession *nx, GtkTreeIter *iter); gboolean remmina_nx_session_iter_next(RemminaNXSession *nx, GtkTreeIter *iter); -gchar* remmina_nx_session_iter_get(RemminaNXSession *nx, GtkTreeIter *iter, gint column); +gchar *remmina_nx_session_iter_get(RemminaNXSession *nx, GtkTreeIter *iter, gint column); void remmina_nx_session_iter_set(RemminaNXSession *nx, GtkTreeIter *iter, gint column, const gchar *data); @@ -103,5 +102,3 @@ gboolean remmina_nx_session_invoke_proxy(RemminaNXSession *nx, gint display, GCh void remmina_nx_session_bye(RemminaNXSession *nx); G_END_DECLS - - diff --git a/nx_session_manager.h b/nx_session_manager.h index add497f..4a51c3b 100644 --- a/nx_session_manager.h +++ b/nx_session_manager.h @@ -40,4 +40,3 @@ G_BEGIN_DECLS void remmina_nx_session_manager_start(RemminaProtocolWidget *gp); G_END_DECLS - -- cgit v1.2.3 From 6016116838502643dcdef167fba2ab6408be4ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Fri, 6 Dec 2019 07:44:28 +0000 Subject: Spelling: Private key, direct explanations --- nx_plugin.c | 16 ++++++++-------- nx_session_manager.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 8b98f1c..cce82d0 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -58,7 +58,7 @@ RemminaPluginService *remmina_plugin_nx_service = NULL; static gchar *remmina_kbtype = "pc102/us"; /* When more than one NX sessions is connecting in progress, we need this mutex and array - * to prevent them from stealing the same window id. + * to prevent them from stealing the same window ID. */ static pthread_mutex_t remmina_nx_init_mutex; static GArray *remmina_nx_window_id_array; @@ -88,7 +88,7 @@ static gboolean onMainThread_cb(struct onMainThread_cb_data *d) } pthread_mutex_unlock( &d->mu ); } else { - /* thread has been cancelled, so we must free d memory here */ + /* Thread has been cancelled, so we must free d memory here */ g_free( d ); } return G_SOURCE_REMOVE; @@ -202,7 +202,7 @@ gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userda _("SSH credentials"), NULL, NULL, NULL, - _("SSH private key passphrase")); + _("Password for private SSH key")); if (ret == GTK_RESPONSE_OK) { *passphrase = remmina_plugin_nx_service->protocol_plugin_init_get_password(gp); return TRUE; @@ -605,7 +605,7 @@ static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) if (!remmina_plugin_nx_service->gtksocket_available()) { remmina_plugin_nx_service->protocol_plugin_set_error(gp, - _("Protocol %s is unavailable because GtkSocket only works under X.Org"), + _("The protocol \"%s\" is unavailable because GtkSocket only works under X.Org."), remmina_plugin_nx.name); return FALSE; } @@ -712,7 +712,7 @@ static gpointer quality_list[] = * c) Setting description * d) Compact disposition * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO - * f) Setting Tooltip + * f) Setting tooltip */ static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = { @@ -733,7 +733,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = * c) Setting description * d) Compact disposition * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO - * f) Setting Tooltip + * f) Setting tooltip */ static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[] = { @@ -773,7 +773,7 @@ static RemminaProtocolPlugin remmina_plugin_nx = remmina_plugin_nx_query_feature, // Query for available features remmina_plugin_nx_call_feature, // Call a feature NULL, // Send a keystroke - NULL // No screenshot support available + NULL // Screenshot support unavailable }; G_MODULE_EXPORT gboolean @@ -803,7 +803,7 @@ remmina_plugin_entry(RemminaPluginService *service) s = strchr(remmina_kbtype, ','); if (s) *s = '\0'; - /* g_print("NX: detected keyboard type %s\n", remmina_kbtype); */ + /* g_print("NX: Detected \"%s\" keyboard type\n", remmina_kbtype); */ } XCloseDisplay(dpy); } diff --git a/nx_session_manager.c b/nx_session_manager.c index bf43628..39aeefa 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -95,7 +95,7 @@ static void remmina_nx_session_manager_on_response(GtkWidget *dialog, gint respo event_type = response_id; } if (response_id == REMMINA_NX_EVENT_TERMINATE && gpdata->manager_selected) { - remmina_nx_session_iter_set(gpdata->nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_STATUS, _("Terminating")); + remmina_nx_session_iter_set(gpdata->nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_STATUS, _("Terminating…")); } if (response_id != REMMINA_NX_EVENT_TERMINATE) { gtk_widget_destroy(dialog); @@ -108,7 +108,7 @@ static void remmina_nx_session_manager_on_response(GtkWidget *dialog, gint respo } /* Handle double click on a row in the NX Session manager - * Automatically close the dialog using the default response id */ + * Automatically close the dialog using the default response ID */ void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, RemminaProtocolWidget *gp) { TRACE_CALL(__func__); -- cgit v1.2.3 From 1f5a0337621296dd35ee65e6050cf5bc1e234aa5 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Fri, 10 Jan 2020 15:25:07 +0100 Subject: Updating copyrights and contribution lists --- CMakeLists.txt | 2 +- nx_plugin.c | 2 +- nx_plugin.h | 2 +- nx_session.c | 2 +- nx_session.h | 2 +- nx_session_manager.c | 2 +- nx_session_manager.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 604c0a2..c768d30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # remmina-plugin-nx - The GTK+ Remote Desktop Client # # Copyright (C) 2011 Marc-Andre Moreau -# Copyright (C) 2014-2019 Antenore Gatta, Giovanni Panozzo +# Copyright (C) 2014-2020 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 diff --git a/nx_plugin.c b/nx_plugin.c index cce82d0..1b4bb3b 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010-2011 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2019 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2020 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 diff --git a/nx_plugin.h b/nx_plugin.h index a55849b..3217ee6 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2019 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2020 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 diff --git a/nx_session.c b/nx_session.c index 49ed006..4a2d299 100644 --- a/nx_session.c +++ b/nx_session.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2019 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2020 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 diff --git a/nx_session.h b/nx_session.h index a59efc5..b1133a6 100644 --- a/nx_session.h +++ b/nx_session.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017-2019 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-2020 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 diff --git a/nx_session_manager.c b/nx_session_manager.c index 39aeefa..7a97378 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2019 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2016-2020 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 diff --git a/nx_session_manager.h b/nx_session_manager.h index 4a51c3b..d894a32 100644 --- a/nx_session_manager.h +++ b/nx_session_manager.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017-2019 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-2020 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 -- cgit v1.2.3 From d451f7e2b09f453ede403af761f98890d5d41850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82?= Date: Tue, 24 Mar 2020 21:55:35 +0000 Subject: Cppcheck and PVS Studio Fixes --- nx_session.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nx_session.c b/nx_session.c index 4a2d299..e698e92 100644 --- a/nx_session.c +++ b/nx_session.c @@ -288,9 +288,8 @@ static gboolean remmina_nx_session_get_response(RemminaNXSession *nx) remmina_nx_session_set_application_error(nx, "Channel closed."); return FALSE; } - if (len > 0) { - g_string_append_len(nx->response, buffer, len); - } + + g_string_append_len(nx->response, buffer, len); g_free(buffer); return TRUE; -- cgit v1.2.3 From 47fc95b611ea0cb67300a34805a4efbc3ecb2c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Sat, 9 May 2020 13:47:11 +0000 Subject: Spelling: Forget passwords after use, Ctrl+Alt+Del --- nx_plugin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 1b4bb3b..ba4a180 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -740,7 +740,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[] = { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disableclipboard", N_("Disable clipboard sync"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disableencryption", N_("Disable encryption"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "showcursor", N_("Use local cursor"), FALSE, NULL, NULL }, - { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disablepasswordstoring", N_("Disable password storing"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disablepasswordstoring", N_("Forget passwords after use"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL } }; @@ -748,7 +748,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[] = * The last element of the array must be REMMINA_PROTOCOL_FEATURE_TYPE_END. */ static const RemminaProtocolFeature remmina_plugin_nx_features[] = { - { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL, N_("Send Ctrl+Alt+Delete"), NULL, NULL }, + { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL, N_("Send Ctrl+Alt+Del"), NULL, NULL }, { REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET, REMMINA_PLUGIN_NX_FEATURE_GTKSOCKET, NULL, NULL, NULL}, { REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL } }; -- cgit v1.2.3 From c2a81834fc71cfe6a84f4a277a74fa2b26fe5baa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Sat, 9 May 2020 22:07:41 +0000 Subject: Spelling: NX sessions on %s --- nx_session_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_session_manager.c b/nx_session_manager.c index 7a97378..bfddfed 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -140,7 +140,7 @@ static gboolean remmina_nx_session_manager_main(RemminaProtocolWidget *gp) remmina_plugin_nx_service->protocol_plugin_init_hide(gp); dialog = gtk_dialog_new(); - s = g_strdup_printf(_("NX Sessions on %s"), remmina_plugin_nx_service->file_get_string(remminafile, "server")); + s = g_strdup_printf(_("NX sessions on %s"), remmina_plugin_nx_service->file_get_string(remminafile, "server")); gtk_window_set_title(GTK_WINDOW(dialog), s); g_free(s); if (gpdata->attach_session) { -- cgit v1.2.3 From a44deced5b8cbee7d1a7c3e2ceccaa42b3fce882 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Mon, 11 May 2020 00:25:01 +0200 Subject: Double free in the nx plugin, fixes #2173 --- nx_plugin.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index ba4a180..0c553d1 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -354,10 +354,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) if (s1 && s2) { ret = remmina_nx_session_login(nx, s1, s2); - }else { - g_free(s1); - g_free(s2); - + } else { gchar *s_username, *s_password; disablepasswordstoring = remmina_plugin_nx_service->file_get_int(remminafile, "disablepasswordstoring", FALSE); -- cgit v1.2.3 From 26a0a080bf3159416ceea48e48a5dbff2d7fdb9a Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Mon, 18 May 2020 13:17:05 +0000 Subject: New remmina_debug function, replaces remmina_log_print, remmina_log_printf and g_debug remmina_debug is meant to be used in place of remmina_log_print, remmina_log_printf and g_debug, to print debug messages in the remmina log window and in the STDOUT --- nx_plugin.c | 2 +- nx_session.c | 4 ++-- nx_session_manager.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 0c553d1..b959307 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -331,7 +331,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) remmina_nx_session_set_encryption(nx, remmina_plugin_nx_service->file_get_int(remminafile, "disableencryption", FALSE) ? 0 : 1); remmina_nx_session_set_localport(nx, remmina_plugin_nx_service->pref_get_sshtunnel_port()); - remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_service->log_printf); + remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_service->debug); s2 = remmina_plugin_nx_service->protocol_plugin_start_direct_tunnel(gp, 22, FALSE); if (s2 == NULL) { diff --git a/nx_session.c b/nx_session.c index e698e92..8fe2873 100644 --- a/nx_session.c +++ b/nx_session.c @@ -443,7 +443,7 @@ static gint remmina_nx_session_parse_response(RemminaNXSession *nx) while ((line = remmina_nx_session_get_line(nx)) != NULL) { if (nx->log_callback) - nx->log_callback("[NX] %s\n", line); + nx->log_callback(line); status = remmina_nx_session_parse_line(nx, line, &p); if (status == 500) { @@ -480,7 +480,7 @@ static gint remmina_nx_session_parse_response(RemminaNXSession *nx) status = nx->status; } else { if (nx->log_callback) - nx->log_callback("[NX] %s\n", pos); + nx->log_callback(pos); nx->response_pos += 8; } nx->status = -1; diff --git a/nx_session_manager.c b/nx_session_manager.c index bfddfed..d3a808e 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -113,7 +113,7 @@ void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath { TRACE_CALL(__func__); RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); - remmina_plugin_nx_service->log_printf("[NX] Default response_id %d\n", + remmina_plugin_nx_service->debug("Default response_id %d", gpdata->default_response); if (gpdata->default_response >= 0) { -- cgit v1.2.3 From 366ac5c4a67dfd68642b4220e332de23de509e99 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Thu, 21 May 2020 00:42:33 +0200 Subject: Refactoring remmina_debug to avoid memory leaks and overhead, should fix #2202 Signed-off-by: Antenore Gatta --- nx_plugin.c | 2 +- nx_session_manager.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index b959307..025bb15 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -331,7 +331,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) remmina_nx_session_set_encryption(nx, remmina_plugin_nx_service->file_get_int(remminafile, "disableencryption", FALSE) ? 0 : 1); remmina_nx_session_set_localport(nx, remmina_plugin_nx_service->pref_get_sshtunnel_port()); - remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_service->debug); + remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_service->_debug); s2 = remmina_plugin_nx_service->protocol_plugin_start_direct_tunnel(gp, 22, FALSE); if (s2 == NULL) { diff --git a/nx_session_manager.c b/nx_session_manager.c index d3a808e..14cb4fb 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -113,7 +113,7 @@ void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath { TRACE_CALL(__func__); RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); - remmina_plugin_nx_service->debug("Default response_id %d", + remmina_plugin_nx_service->_debug("Default response_id %d", gpdata->default_response); if (gpdata->default_response >= 0) { -- cgit v1.2.3 From 8170fa4f032af6b094f991aeeac1fe90301c5f7a Mon Sep 17 00:00:00 2001 From: Giovanni panozzo Date: Thu, 21 May 2020 14:28:56 +0200 Subject: Introduce remmina_plugin_debug() for plugins --- nx_plugin.c | 14 +++++++++++++- nx_plugin.h | 1 + nx_session_manager.c | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index 025bb15..c7b38de 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -36,6 +36,7 @@ #include #include +#include #include "common/remmina_plugin.h" #include #include @@ -307,6 +308,17 @@ static gint remmina_plugin_nx_wait_signal(RemminaPluginNxData *gpdata) return (gint)dummy; } +static void remmina_plugin_nx_log_callback(const gchar *fmt, ...) +{ + char buffer[256]; + va_list args; + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + remmina_plugin_debug(buffer); + va_end(args); +} + + static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); @@ -331,7 +343,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) remmina_nx_session_set_encryption(nx, remmina_plugin_nx_service->file_get_int(remminafile, "disableencryption", FALSE) ? 0 : 1); remmina_nx_session_set_localport(nx, remmina_plugin_nx_service->pref_get_sshtunnel_port()); - remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_service->_debug); + remmina_nx_session_set_log_callback(nx, remmina_plugin_nx_log_callback); s2 = remmina_plugin_nx_service->protocol_plugin_start_direct_tunnel(gp, 22, FALSE); if (s2 == NULL) { diff --git a/nx_plugin.h b/nx_plugin.h index 3217ee6..84cce97 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -76,5 +76,6 @@ typedef struct _RemminaPluginNxData { } RemminaPluginNxData; extern RemminaPluginService *remmina_plugin_nx_service; +#define remmina_plugin_debug(fmt, ...) remmina_plugin_nx_service->_remmina_debug(__func__, fmt __VA_OPT__(,) __VA_ARGS__) G_END_DECLS diff --git a/nx_session_manager.c b/nx_session_manager.c index 14cb4fb..f122cf0 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -113,7 +113,7 @@ void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath { TRACE_CALL(__func__); RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); - remmina_plugin_nx_service->_debug("Default response_id %d", + remmina_plugin_debug("Default response_id %d", gpdata->default_response); if (gpdata->default_response >= 0) { -- cgit v1.2.3 From 768e4a52780cef25d9a43da9acb6ba4893d8e919 Mon Sep 17 00:00:00 2001 From: Giovanni Panozzo Date: Thu, 21 May 2020 15:53:23 +0200 Subject: Change __VA_OPT__ to ## to support clang --- nx_plugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_plugin.h b/nx_plugin.h index 84cce97..aa294b9 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -76,6 +76,6 @@ typedef struct _RemminaPluginNxData { } RemminaPluginNxData; extern RemminaPluginService *remmina_plugin_nx_service; -#define remmina_plugin_debug(fmt, ...) remmina_plugin_nx_service->_remmina_debug(__func__, fmt __VA_OPT__(,) __VA_ARGS__) +#define remmina_plugin_debug(fmt, ...) remmina_plugin_nx_service->_remmina_debug(__func__, fmt, ##__VA_ARGS__) G_END_DECLS -- cgit v1.2.3 From c2e38f55c341aef7c59214c1e971d94716bbc679 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Thu, 21 May 2020 21:36:38 +0200 Subject: Set macro name to uppercase --- nx_plugin.c | 2 +- nx_plugin.h | 2 +- nx_session_manager.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index c7b38de..73ff7ff 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -314,7 +314,7 @@ static void remmina_plugin_nx_log_callback(const gchar *fmt, ...) va_list args; va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); - remmina_plugin_debug(buffer); + REMMINA_PLUGIN_DEBUG(buffer); va_end(args); } diff --git a/nx_plugin.h b/nx_plugin.h index aa294b9..eb0375d 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -76,6 +76,6 @@ typedef struct _RemminaPluginNxData { } RemminaPluginNxData; extern RemminaPluginService *remmina_plugin_nx_service; -#define remmina_plugin_debug(fmt, ...) remmina_plugin_nx_service->_remmina_debug(__func__, fmt, ##__VA_ARGS__) +#define REMMINA_PLUGIN_DEBUG(fmt, ...) remmina_plugin_nx_service->_remmina_debug(__func__, fmt, ##__VA_ARGS__) G_END_DECLS diff --git a/nx_session_manager.c b/nx_session_manager.c index f122cf0..3e5b625 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -113,7 +113,7 @@ void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath { TRACE_CALL(__func__); RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp); - remmina_plugin_debug("Default response_id %d", + REMMINA_PLUGIN_DEBUG("Default response_id %d", gpdata->default_response); if (gpdata->default_response >= 0) { -- cgit v1.2.3 From 34ecafd61d332c471a1491a3ec63ac47dabb84a0 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Mon, 4 Jan 2021 08:12:01 +0100 Subject: Updating Copyright notice for 2021 --- CMakeLists.txt | 2 +- nx_plugin.c | 2 +- nx_plugin.h | 2 +- nx_session.c | 2 +- nx_session.h | 2 +- nx_session_manager.c | 2 +- nx_session_manager.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c768d30..0106aa7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # remmina-plugin-nx - The GTK+ Remote Desktop Client # # Copyright (C) 2011 Marc-Andre Moreau -# Copyright (C) 2014-2020 Antenore Gatta, Giovanni Panozzo +# 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 diff --git a/nx_plugin.c b/nx_plugin.c index 73ff7ff..dfe9bc6 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010-2011 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2020 Antenore Gatta, 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 diff --git a/nx_plugin.h b/nx_plugin.h index eb0375d..2611751 100644 --- a/nx_plugin.h +++ b/nx_plugin.h @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2020 Antenore Gatta, 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 diff --git a/nx_session.c b/nx_session.c index 8fe2873..8162dd1 100644 --- a/nx_session.c +++ b/nx_session.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2020 Antenore Gatta, 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 diff --git a/nx_session.h b/nx_session.h index b1133a6..9f80919 100644 --- a/nx_session.h +++ b/nx_session.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017-2020 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-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 diff --git a/nx_session_manager.c b/nx_session_manager.c index 3e5b625..7245527 100644 --- a/nx_session_manager.c +++ b/nx_session_manager.c @@ -2,7 +2,7 @@ * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo - * Copyright (C) 2016-2020 Antenore Gatta, 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 diff --git a/nx_session_manager.h b/nx_session_manager.h index d894a32..302b9d3 100644 --- a/nx_session_manager.h +++ b/nx_session_manager.h @@ -1,7 +1,7 @@ /* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2010 Vic Lee - * Copyright (C) 2017-2020 Antenore Gatta, Giovanni Panozzo + * Copyright (C) 2017-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 -- cgit v1.2.3 From 6eeae920b9120c2d42ce783ff5df55bd310d8b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Fri, 15 Jan 2021 07:43:52 +0000 Subject: Spelling: Start-up --- nx_plugin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index dfe9bc6..6d8c2ef 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -415,7 +415,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp) app = NULL; }else if (g_strcmp0(cs, "Xfce") == 0) { - /* NX does not know Xfce. So we simply launch the Xfce startup program. */ + /* NX does not know Xfce. So we simply launch the Xfce start-up program. */ type = "unix-application"; app = "startxfce4"; }else @@ -731,7 +731,7 @@ static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = { REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD, "password", N_("User password"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_RESOLUTION, "resolution", NULL, FALSE, GINT_TO_POINTER(1), NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_SELECT, "quality", N_("Quality"), FALSE, quality_list, NULL }, - { REMMINA_PROTOCOL_SETTING_TYPE_COMBO, "exec", N_("Startup program"), FALSE, "GNOME,KDE,Xfce,Shadow", NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_COMBO, "exec", N_("Start-up program"), FALSE, "GNOME,KDE,Xfce,Shadow", NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL } }; -- cgit v1.2.3 From f373bfe0d10286176e6248e36f122b1b4ffbdf0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Fri, 15 Jan 2021 12:16:36 +0000 Subject: Spelling: SSH key, first, checksum of, either --- nx_plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_plugin.c b/nx_plugin.c index 6d8c2ef..b2923a3 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -726,7 +726,7 @@ static gpointer quality_list[] = static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[] = { { REMMINA_PROTOCOL_SETTING_TYPE_SERVER, "server", NULL, FALSE, NULL, NULL }, - { REMMINA_PROTOCOL_SETTING_TYPE_FILE, "nx_privatekey", N_("Identity file"), FALSE, NULL, NULL }, + { REMMINA_PROTOCOL_SETTING_TYPE_FILE, "nx_privatekey", N_("SSH identity file"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_TEXT, "username", N_("Username"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD, "password", N_("User password"), FALSE, NULL, NULL }, { REMMINA_PROTOCOL_SETTING_TYPE_RESOLUTION, "resolution", NULL, FALSE, GINT_TO_POINTER(1), NULL }, -- cgit v1.2.3 From 28135a5b5f1936cb524919b1196dbf2ae838b0bb Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Fri, 22 Jan 2021 08:43:30 +0100 Subject: Using curly double quotes where possible --- nx_plugin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx_plugin.c b/nx_plugin.c index b2923a3..821a43e 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -614,7 +614,7 @@ static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp) if (!remmina_plugin_nx_service->gtksocket_available()) { remmina_plugin_nx_service->protocol_plugin_set_error(gp, - _("The protocol \"%s\" is unavailable because GtkSocket only works under X.Org."), + _("The protocol “%s” is unavailable because GtkSocket only works under X.Org."), remmina_plugin_nx.name); return FALSE; } @@ -812,7 +812,7 @@ remmina_plugin_entry(RemminaPluginService *service) s = strchr(remmina_kbtype, ','); if (s) *s = '\0'; - /* g_print("NX: Detected \"%s\" keyboard type\n", remmina_kbtype); */ + /* g_print("NX: Detected “%s” keyboard type\n", remmina_kbtype); */ } XCloseDisplay(dpy); } -- cgit v1.2.3 From 5f0b72c8014b4d29a12f7a532a523d34307a9700 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Fri, 23 Apr 2021 15:10:01 +0200 Subject: Fixing RemminaConnectionWindow map/unmap events The remmina connection windows in fullscreen is a different object than when is in scrolled mode, therefore the old logic to map and unmap the windows from the plugin it was notr working. Now the events are managed directly from the RCW object and the RemminaProtocolWidget, with an API that can be used by any plugins. When in multi monitor and fullscreen, this mechanism doesn't work, Therefore, in the plugin itself I catch when we are in multi monitor fullscreen mode And I ignore the event. This last behaviour should be managed directly in the Remmina Protocol Widget (TODO). Fixes #2475 Signed-off-by: Antenore Gatta --- nx_plugin.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nx_plugin.c b/nx_plugin.c index 821a43e..01791ac 100644 --- a/nx_plugin.c +++ b/nx_plugin.c @@ -782,7 +782,9 @@ static RemminaProtocolPlugin remmina_plugin_nx = remmina_plugin_nx_query_feature, // Query for available features remmina_plugin_nx_call_feature, // Call a feature NULL, // Send a keystroke - NULL // Screenshot support unavailable + NULL, // No screenshot support available + NULL, // RCW map event + NULL // RCW unmap event }; G_MODULE_EXPORT gboolean -- cgit v1.2.3 From 251a2ef5210b2527ec2a959e7356f6cd1a8fc1d2 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 12 May 2021 13:07:05 +0200 Subject: Fix build with musl libc Use FindIntl cmake modules which will leave Intl_LIBRARIES empty if libintl is provided by the libc. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0106aa7..275a3a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ target_link_libraries(remmina-plugin-nx ${REMMINA_COMMON_LIBRARIES} ${XKBFILE_LIBRARIES} ${LIBSSH_LIBRARIES} + ${Intl_LIBRARIES} ${X11_X11_LIB}) install(TARGETS remmina-plugin-nx DESTINATION ${REMMINA_PLUGINDIR}) -- cgit v1.2.3