Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Teichmann <daniel.teichmann@das-netzwerkteam.de>2021-10-01 16:44:42 +0300
committerDaniel Teichmann <daniel.teichmann@das-netzwerkteam.de>2021-10-01 16:44:42 +0300
commit54bbc52f32deb0ee5a1c53245b078677b07667db (patch)
tree6962101974f63371fb6cfe446f763941d7c795f9 /plugins
parentb8b840fbd4eb40d875e41eb01fb29908012418ee (diff)
x2go_plugin.c: Complete refactor; Use 8-space tab instead of 4; Introduce enumeration_prettifier; Add missing _() for translation; Comply more with style-guide.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/x2go/x2go_plugin.c937
1 files changed, 517 insertions, 420 deletions
diff --git a/plugins/x2go/x2go_plugin.c b/plugins/x2go/x2go_plugin.c
index 72673f4e7..e55b5b1be 100644
--- a/plugins/x2go/x2go_plugin.c
+++ b/plugins/x2go/x2go_plugin.c
@@ -57,62 +57,67 @@
#include <ctype.h>
#define FEATURE_AVAILABLE(gpdata, feature) \
- gpdata->available_features ? \
- (g_list_find_custom(gpdata->available_features, \
- feature, \
- remmina_plugin_x2go_safe_strcmp) \
- ? TRUE : FALSE) : FALSE
+ gpdata->available_features ? (g_list_find_custom( \
+ gpdata->available_features, \
+ feature, \
+ rmplugin_x2go_safe_strcmp \
+ ) ? TRUE : FALSE) : FALSE
#define GET_PLUGIN_DATA(gp) \
- (RemminaPluginX2GoData*) g_object_get_data(G_OBJECT(gp), "plugin-data")
+ (RemminaPluginX2GoData*) g_object_get_data(G_OBJECT(gp), "plugin-data")
#define SET_DIALOG_DATA(gp, ddata) \
- g_object_set_data_full(G_OBJECT(gp), "dialog-data", ddata, g_free);
+ g_object_set_data_full(G_OBJECT(gp), "dialog-data", ddata, g_free);
#define GET_DIALOG_DATA(gp) \
- (DialogData*) g_object_get_data(G_OBJECT(gp), "dialog-data");
+ (DialogData*) g_object_get_data(G_OBJECT(gp), "dialog-data");
#define REMMINA_PLUGIN_INFO(fmt, ...)\
- remmina_plugin_service->_remmina_info("[%s] " fmt, PLUGIN_NAME, ##__VA_ARGS__)
+ rm_plugin_service->_remmina_info("[%s] " fmt, \
+ PLUGIN_NAME, ##__VA_ARGS__)
#define REMMINA_PLUGIN_MESSAGE(fmt, ...)\
- remmina_plugin_service->_remmina_message("[%s] " fmt, PLUGIN_NAME, ##__VA_ARGS__)
+ rm_plugin_service->_remmina_message("[%s] " fmt, \
+ PLUGIN_NAME, ##__VA_ARGS__)
#define REMMINA_PLUGIN_DEBUG(fmt, ...)\
- remmina_plugin_service->_remmina_debug(__func__, "[%s] " fmt, \
- PLUGIN_NAME, ##__VA_ARGS__)
+ rm_plugin_service->_remmina_debug(__func__, "[%s] " fmt, \
+ PLUGIN_NAME, ##__VA_ARGS__)
#define REMMINA_PLUGIN_WARNING(fmt, ...)\
- remmina_plugin_service->_remmina_warning(__func__, "[%s] " fmt, \
- PLUGIN_NAME, ##__VA_ARGS__)
+ rm_plugin_service->_remmina_warning(__func__, "[%s] " fmt, \
+ PLUGIN_NAME, ##__VA_ARGS__)
#define REMMINA_PLUGIN_ERROR(fmt, ...)\
- remmina_plugin_service->_remmina_error(__func__, "[%s] " fmt, \
- PLUGIN_NAME, ##__VA_ARGS__)
+ rm_plugin_service->_remmina_error(__func__, "[%s] " fmt, \
+ PLUGIN_NAME, ##__VA_ARGS__)
#define REMMINA_PLUGIN_CRITICAL(fmt, ...)\
- remmina_plugin_service->_remmina_critical(__func__, "[%s] " fmt, \
- PLUGIN_NAME, ##__VA_ARGS__)
+ rm_plugin_service->_remmina_critical(__func__, "[%s] " fmt, \
+ PLUGIN_NAME, ##__VA_ARGS__)
#define GET_PLUGIN_STRING(value) \
- g_strdup(remmina_plugin_service->file_get_string(remminafile, value))
+ g_strdup(rm_plugin_service->file_get_string(remminafile, value))
+
#define GET_PLUGIN_PASSWORD(value) \
GET_PLUGIN_STRING(value)
+
#define GET_PLUGIN_INT(value, default_value) \
- remmina_plugin_service->file_get_int(remminafile, value, default_value)
+ rm_plugin_service->file_get_int(remminafile, value, default_value)
+
#define GET_PLUGIN_BOOLEAN(value) \
- remmina_plugin_service->file_get_int(remminafile, value, FALSE)
+ rm_plugin_service->file_get_int(remminafile, value, FALSE)
-static RemminaPluginService *remmina_plugin_service = NULL;
+static RemminaPluginService *rm_plugin_service = NULL;
// Following str2int code was adapted from Stackoverflow:
// https://stackoverflow.com/questions/7021725/how-to-convert-a-string-to-integer-in-c
typedef enum {
- STR2INT_SUCCESS,
- STR2INT_OVERFLOW,
- STR2INT_UNDERFLOW,
- STR2INT_INCONVERTIBLE,
- STR2INT_INVALID_DATA
+ STR2INT_SUCCESS,
+ STR2INT_OVERFLOW,
+ STR2INT_UNDERFLOW,
+ STR2INT_INCONVERTIBLE,
+ STR2INT_INVALID_DATA
} str2int_errno;
/**
@@ -121,34 +126,34 @@ typedef enum {
* @param out The converted int. Cannot be NULL.
*
* @param s Input string to be converted. \n
- * The format is the same as strtol,
- * except that the following are inconvertible: \n
- * empty string, leading whitespace \n
- * or any trailing characters that are not part of the number \n
- * Cannot be NULL.
+ * The format is the same as strtol,
+ * except that the following are inconvertible: \n
+ * * empty string \n
+ * * leading whitespace \n
+ * * or any trailing characters that are not part of the number \n
+ * Cannot be NULL.
* @param base Base to interpret string in. Same range as strtol (2 to 36).
*
* @return Indicates if the operation succeeded, or why it failed with str2int_errno enum.
*/
-str2int_errno str2int(gint *out, gchar *s, gint base) {
- gchar *end;
-
- if (!s || !out || base <= 0)
- return STR2INT_INVALID_DATA;
-
- if (s[0] == '\0' || isspace(s[0]))
- return STR2INT_INCONVERTIBLE;
- errno = 0;
- glong l = strtol(s, &end, base);
- /* Both checks are needed because INT_MAX == LONG_MAX is possible. */
- if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
- return STR2INT_OVERFLOW;
- if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN))
- return STR2INT_UNDERFLOW;
- if (*end != '\0')
- return STR2INT_INCONVERTIBLE;
- *out = l;
- return STR2INT_SUCCESS;
+str2int_errno str2int(gint *out, gchar *s, gint base)
+{
+ gchar *end;
+
+ if (!s || !out || base <= 0) return STR2INT_INVALID_DATA;
+
+ if (s[0] == '\0' || isspace(s[0])) return STR2INT_INCONVERTIBLE;
+
+ errno = 0;
+ glong l = strtol(s, &end, base);
+
+ /* Both checks are needed because INT_MAX == LONG_MAX is possible. */
+ if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX)) return STR2INT_OVERFLOW;
+ if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN)) return STR2INT_UNDERFLOW;
+ if (*end != '\0') return STR2INT_INCONVERTIBLE;
+
+ *out = l;
+ return STR2INT_SUCCESS;
}
/**
@@ -160,9 +165,8 @@ str2int_errno str2int(gint *out, gchar *s, gint base) {
* @brief Splits a string into a gchar* list using delim as a single-character delimeter.
*
*/
-static gchar** remmina_plugin_x2go_split_string(gchar* data,
- gchar delim,
- guint *occurences) {
+static gchar** rmplugin_x2go_split_string(gchar* data, gchar delim, guint *occurences)
+{
// Counts the occurence of 'delim', so the amount of numbers passed.
guint delim_occurence = 0;
// work on a copy of the string, because strchr alters the string.
@@ -200,12 +204,12 @@ static gchar** remmina_plugin_x2go_split_string(gchar* data,
return returning_string_list;
}
-// Wrapper for strcmp which doesn't throw an exception when 'a' or 'b' are a nullpointer.
-static gint remmina_plugin_x2go_safe_strcmp(gconstpointer a, gconstpointer b) {
- if (a && b) {
- return strcmp(a, b);
- }
-
+/**
+ * @brief Wrapper for strcmp which doesn't throw an exception
+ * when 'a' or 'b' are a nullpointer.
+ */
+static gint rmplugin_x2go_safe_strcmp(gconstpointer a, gconstpointer b) {
+ if (a && b) return strcmp(a, b);
return -1;
}
@@ -216,43 +220,41 @@ static gint remmina_plugin_x2go_safe_strcmp(gconstpointer a, gconstpointer b) {
* @param buttons see GtkButtonsType
* @param title Title of the Dialog
* @param message Message of the Dialog
- * @param callbackfunc A GCallback function like
- * callback(RemminaProtocolWidget *gp, GtkWidget *dialog)
- * which will be executed on the dialogs 'response' signal.
- * The callback function is obliged to destroy
- * the dialog widget.
+ * @param callbackfunc A GCallback function like: \n
+ * callback(RemminaProtocolWidget *gp, GtkWidget *dialog) \n
+ * which will be executed on the dialogs 'response' signal.
+ * The callback function is obliged to destroy the dialog widget.
*
- * The `DialogData` structure contains all info needed
- * to open a GTK dialog with remmina_plugin_x2go_open_dialog() \n
+ * The `DialogData` structure contains all info needed to open a
+ * GTK dialog with rmplugin_x2go_open_dialog() \n
*
* Quick example of a callback function: \n
- * static void remmina_plugin_x2go_test_callback(RemminaProtocolWidget *gp, \n
- * gint response_id, \n
- * GtkDialog *self) { \n
- * REMMINA_PLUGIN_DEBUG("response: %i", response_id); \n
- * if (response_id == GTK_RESPONSE_OK) { \n
- * REMMINA_PLUGIN_DEBUG("OK!"); \n
- * } \n
- * gtk_widget_destroy(self); \n
+ * static void rmplugin_x2go_test_callback(RemminaProtocolWidget *gp, gint response_id, \n
+ * GtkDialog *self) { \n
+ * REMMINA_PLUGIN_DEBUG("response: %i", response_id); \n
+ * if (response_id == GTK_RESPONSE_OK) { \n
+ * REMMINA_PLUGIN_DEBUG("OK!"); \n
+ * } \n
+ * gtk_widget_destroy(self); \n
* }
*
*/
struct _DialogData {
- /** see GtkWindow */
- GtkWindow *parent;
- /** see GtkDialogFlags */
- GtkDialogFlags flags;
- /** see GtkMessageType */
- GtkMessageType type;
- /** see GtkButtonsType */
- GtkButtonsType buttons;
- /** Title of the Dialog */
- gchar *title;
- /** Message of the Dialog */
- gchar *message;
- /** Calls this function if
- * the user pressed a button. */
- GCallback callbackfunc;
+ /** see GtkWindow */
+ GtkWindow* parent;
+ /** see GtkDialogFlags */
+ GtkDialogFlags flags;
+ /** see GtkMessageType */
+ GtkMessageType type;
+ /** see GtkButtonsType */
+ GtkButtonsType buttons;
+ /** Title of the Dialog */
+ gchar* title;
+ /** Message of the Dialog */
+ gchar* message;
+ /** Calls this function if
+ * the user pressed a button. */
+ GCallback callbackfunc;
};
typedef struct _DialogData DialogData;
@@ -260,7 +262,8 @@ typedef struct _DialogData DialogData;
* @param gp getting DialogData via dialog-data saved in gp.
* See define GET_DIALOG_DATA
*/
-static void remmina_plugin_x2go_open_dialog(RemminaProtocolWidget *gp) {
+static void rmplugin_x2go_open_dialog(RemminaProtocolWidget *gp)
+{
REMMINA_PLUGIN_DEBUG("Function entry.");
DialogData *ddata = GET_DIALOG_DATA(gp);
@@ -281,24 +284,22 @@ static void remmina_plugin_x2go_open_dialog(RemminaProtocolWidget *gp) {
GtkWidget *widget_gtk_dialog;
widget_gtk_dialog = gtk_message_dialog_new(ddata->parent,
- ddata->flags,
- ddata->type,
- ddata->buttons,
- ddata->title);
+ ddata->flags,
+ ddata->type,
+ ddata->buttons,
+ ddata->title);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG (widget_gtk_dialog),
- ddata->message);
+ ddata->message);
if (ddata->callbackfunc) {
- g_signal_connect_swapped(G_OBJECT(widget_gtk_dialog),
- "response",
- G_CALLBACK(ddata->callbackfunc),
- gp);
+ g_signal_connect_swapped(G_OBJECT(widget_gtk_dialog), "response",
+ G_CALLBACK(ddata->callbackfunc),
+ gp);
} else {
- g_signal_connect(G_OBJECT(widget_gtk_dialog),
- "response",
- G_CALLBACK(gtk_widget_destroy),
- NULL);
+ g_signal_connect(G_OBJECT(widget_gtk_dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ NULL);
}
gtk_widget_show_all(widget_gtk_dialog);
@@ -324,10 +325,10 @@ typedef struct _RemminaPluginX2GoData {
GList* available_features;
} RemminaPluginX2GoData;
-#define REMMINA_PLUGIN_X2GO_FEATURE_GTKSOCKET 1
+#define RMPLUGIN_X2GO_FEATURE_GTKSOCKET 1
/* Forward declaration */
-static RemminaProtocolPlugin remmina_plugin_x2go;
+static RemminaProtocolPlugin rmplugin_x2go;
/* 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.
@@ -335,9 +336,9 @@ static RemminaProtocolPlugin remmina_plugin_x2go;
static pthread_mutex_t remmina_x2go_init_mutex;
static GArray *remmina_x2go_window_id_array;
-/* --------- Support for execution on main thread of GTK functions -------------- */
-
-struct onMainThread_cb_data {
+/* ------------- Support for execution on main thread of GTK functions ------------- */
+struct onMainThread_cb_data
+{
enum { FUNC_GTK_SOCKET_ADD_ID } func;
GtkSocket* sk;
@@ -349,7 +350,8 @@ struct onMainThread_cb_data {
gboolean cancelled;
};
-static gboolean onMainThread_cb(struct onMainThread_cb_data *d) {
+static gboolean onMainThread_cb(struct onMainThread_cb_data *d)
+{
TRACE_CALL(__func__);
if (!d->cancelled) {
switch (d->func) {
@@ -366,13 +368,15 @@ static gboolean onMainThread_cb(struct onMainThread_cb_data *d) {
}
-static void onMainThread_cleanup_handler(gpointer data) {
+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) {
+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);
@@ -387,7 +391,8 @@ static void onMainThread_schedule_callback_and_wait(struct onMainThread_cb_data
pthread_mutex_destroy(&d->mu);
}
-static void onMainThread_gtk_socket_add_id(GtkSocket* sk, Window w) {
+static void onMainThread_gtk_socket_add_id(GtkSocket* sk, Window w)
+{
TRACE_CALL(__func__);
struct onMainThread_cb_data *d;
@@ -400,34 +405,34 @@ static void onMainThread_gtk_socket_add_id(GtkSocket* sk, Window w) {
onMainThread_schedule_callback_and_wait(d);
g_free(d);
}
+/* /-/-/-/-/-/-/ Support for execution on main thread of GTK functions /-/-/-/-/-/-/ */
-/* --------------------------------------- */
-
-static void remmina_plugin_x2go_remove_window_id (Window window_id) {
+static void rmplugin_x2go_remove_window_id (Window window_id)
+{
gint i;
gboolean already_seen = FALSE;
- pthread_mutex_lock (&remmina_x2go_init_mutex);
- for (i = 0; i < remmina_x2go_window_id_array->len; i++)
- {
- if (g_array_index (remmina_x2go_window_id_array, Window, i) == window_id)
- {
+ pthread_mutex_lock(&remmina_x2go_init_mutex);
+ for (i = 0; i < remmina_x2go_window_id_array->len; i++) {
+ if (g_array_index(remmina_x2go_window_id_array, Window, i) == window_id) {
already_seen = TRUE;
REMMINA_PLUGIN_DEBUG("Window for X2Go Agent with ID [0x%lx] already seen.",
- window_id);
+ window_id);
break;
}
}
- if (already_seen)
- {
- g_array_remove_index_fast (remmina_x2go_window_id_array, i);
+
+ if (already_seen) {
+ g_array_remove_index_fast(remmina_x2go_window_id_array, i);
REMMINA_PLUGIN_DEBUG("forgetting about window for X2Go Agent with ID [0x%lx]",
- window_id);
+ window_id);
}
- pthread_mutex_unlock (&remmina_x2go_init_mutex);
+
+ pthread_mutex_unlock(&remmina_x2go_init_mutex);
}
-static gboolean remmina_plugin_x2go_cleanup(RemminaProtocolWidget *gp) {
+static gboolean rmplugin_x2go_cleanup(RemminaProtocolWidget *gp)
+{
REMMINA_PLUGIN_DEBUG("Function entry.");
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
@@ -438,12 +443,11 @@ static gboolean remmina_plugin_x2go_cleanup(RemminaProtocolWidget *gp) {
if (gpdata->thread) {
pthread_cancel(gpdata->thread);
- if (gpdata->thread)
- pthread_join(gpdata->thread, NULL);
+ if (gpdata->thread) pthread_join(gpdata->thread, NULL);
}
if (gpdata->window_id) {
- remmina_plugin_x2go_remove_window_id(gpdata->window_id);
+ rmplugin_x2go_remove_window_id(gpdata->window_id);
}
if (gpdata->pidx2go) {
@@ -459,12 +463,13 @@ static gboolean remmina_plugin_x2go_cleanup(RemminaProtocolWidget *gp) {
}
g_object_steal_data(G_OBJECT(gp), "plugin-data");
- remmina_plugin_service->protocol_plugin_signal_connection_closed(gp);
+ rm_plugin_service->protocol_plugin_signal_connection_closed(gp);
return FALSE;
}
-static gboolean remmina_plugin_x2go_close_connection(RemminaProtocolWidget *gp) {
+static gboolean rmplugin_x2go_close_connection(RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
@@ -475,14 +480,15 @@ static gboolean remmina_plugin_x2go_close_connection(RemminaProtocolWidget *gp)
return FALSE;
}
- remmina_plugin_x2go_cleanup(gp);
+ rmplugin_x2go_cleanup(gp);
return TRUE;
}
-static void remmina_plugin_x2go_pyhoca_cli_exited(GPid pid,
- int status,
- struct _RemminaProtocolWidget *gp) {
+static void rmplugin_x2go_pyhoca_cli_exited(GPid pid,
+ gint status,
+ struct _RemminaProtocolWidget *gp)
+{
REMMINA_PLUGIN_DEBUG("Function entry.");
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
@@ -497,7 +503,7 @@ static void remmina_plugin_x2go_pyhoca_cli_exited(GPid pid,
}
REMMINA_PLUGIN_CRITICAL("%s", _("pyhoca-cli exited unexpectedly. "
- "This connection will now be closed."));
+ "This connection will now be closed."));
DialogData *ddata = g_new0(DialogData, 1);
SET_DIALOG_DATA(gp, ddata);
@@ -507,25 +513,34 @@ static void remmina_plugin_x2go_pyhoca_cli_exited(GPid pid,
ddata->buttons = GTK_BUTTONS_OK;
ddata->title = _("An error occured.");
ddata->message = _("The necessary child process 'pyhoca-cli' stopped unexpectedly.\n"
- "Please check your profile settings and pyhoca-cli's output for "
- "possible errors and ensure the remote server is "
- "reachable.");
- ddata->callbackfunc = NULL; // Dialog frees itself, no need for an callbackfunc.
- IDLE_ADD((GSourceFunc) remmina_plugin_x2go_open_dialog, gp);
+ "Please check your profile settings and pyhoca-cli's output for "
+ "possible errors and ensure the remote server is "
+ "reachable.");
+ // We don't need the response.
+ ddata->callbackfunc = NULL;
+ IDLE_ADD((GSourceFunc) rmplugin_x2go_open_dialog, gp);
// 1 Second. Give `Dialog` chance to open.
usleep(1000 * 1000);
- remmina_plugin_x2go_close_connection(gp);
+ rmplugin_x2go_close_connection(gp);
}
-// Returns either all features separated with a '\n' or NULL if it failed.
-static gchar* remmina_plugin_x2go_get_pyhoca_features() {
+/**
+ * @brief Get all available pyhoca-cli features by
+ * executing `pyhoca-cli --list-cmdline-features`.
+ *
+ * @returns Returns either a gchar* with all features,
+ * separated by a '\n' or NULL if it failed.
+ */
+static gchar* rmplugin_x2go_get_pyhoca_features()
+{
REMMINA_PLUGIN_DEBUG("Function entry.");
// We will now start pyhoca-cli with only the '--list-cmdline-features' option
- // and depending on the exit code and stdout output we will determine if some features
- // are available or not.
+ // and depending on the exit code and stdout output we will determine if some
+ // features are available or not.
+
gchar *argv[50];
gint argc = 0;
GError *error = NULL;
@@ -540,18 +555,34 @@ static gchar* remmina_plugin_x2go_get_pyhoca_features() {
gchar **envp = g_get_environ();
gboolean success_ret = g_spawn_sync (NULL, argv, envp, G_SPAWN_SEARCH_PATH,
- NULL, NULL, &standard_out, &standard_err,
- &exit_code, &error);
+ NULL, NULL, &standard_out, &standard_err,
+ &exit_code, &error);
+
+ REMMINA_PLUGIN_INFO("%s", _("Started pyhoca-cli with following arguments:"));
+ // Print every argument except passwords. Free all arg strings.
+ for (gint i = 0; i < argc - 1; i++) {
+ if (strcmp(argv[i], "--password") == 0) {
+ g_printf("%s ", argv[i]);
+ g_printf("XXXXXX ");
+ g_free (argv[i]);
+ g_free (argv[++i]);
+ continue;
+ } else {
+ g_printf("%s ", argv[i]);
+ g_free (argv[i]);
+ }
+ }
+ g_printf("\n");
if (!success_ret || error || strcmp(standard_out, "") == 0 || exit_code) {
if (!error) {
REMMINA_PLUGIN_WARNING("%s",
- g_strdup_printf(_("An unknown error happened while retrieving "
- "pyhoca-cli's cmdline features! "
- "Exit code: %i"), exit_code));
+ g_strdup_printf(_("An unknown error happened while retrieving "
+ "pyhoca-cli's cmdline features! Exit code: %i"),
+ exit_code));
} else {
REMMINA_PLUGIN_WARNING("%s",
- g_strdup_printf(_("Error: '%s'"), error->message));
+ g_strdup_printf(_("Error: '%s'"), error->message));
g_error_free(error);
}
@@ -561,6 +592,43 @@ static gchar* remmina_plugin_x2go_get_pyhoca_features() {
return standard_out;
}
+
+/**
+ * @brief Saves s_password and s_username if set.
+ * @returns either TRUE or FALSE. If FALSE gets returned `errmsg` is set.
+ */
+static gboolean rmplugin_x2go_save_credentials(RemminaFile* remminafile,
+ gchar* s_username, gchar* s_password,
+ gchar* errmsg)
+{
+ // User has requested to save credentials. We put all the new credentials
+ // into remminafile->settings. They will be saved later, on successful
+ // connection, by rcw.c
+ if (s_password && s_username) {
+ if (strcmp(s_username, "") == 0) {
+ g_strlcpy(errmsg, _("Given username can't get saved "
+ "since it's empty!"), 512);
+ //REMMINA_PLUGIN_CRITICAL("%s", errmsg); // No need.
+ return FALSE;
+ }
+
+ // We allow the possibility to set an empty password because a X2Go
+ // session can be still made using keyfiles or similar.
+ rm_plugin_service->file_set_string(remminafile, "password",
+ s_password);
+ rm_plugin_service->file_set_string(remminafile, "username",
+ s_username);
+ } else {
+ g_strlcpy(errmsg, _("An error occured while trying to save "
+ "new credentials: 's_password' or "
+ "'s_username' strings were not set."), 512);
+ //REMMINA_PLUGIN_CRITICAL("%s", errmsg); // No need.
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* @brief Asks the user for a username and password.
*
@@ -570,24 +638,24 @@ static gchar* remmina_plugin_x2go_get_pyhoca_features() {
*
* @returns FALSE if auth failed and TRUE on success.
*/
-static gboolean remmina_plugin_x2go_get_auth(RemminaProtocolWidget *gp, gchar* errmsg,
- gchar* username, gchar* password) {
+static gboolean rmplugin_x2go_get_auth(RemminaProtocolWidget *gp, gchar* errmsg,
+ gchar* username, gchar* password)
+{
gchar *s_username, *s_password;
gint ret;
gboolean save;
- gboolean password_storing_disabled;
+ gboolean disable_password_storing;
RemminaFile *remminafile;
- remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
+ remminafile = rm_plugin_service->protocol_plugin_get_file(gp);
- password_storing_disabled = remmina_plugin_service->file_get_int(
- remminafile,
- "disablepasswordstoring",
- FALSE);
- ret = remmina_plugin_service->protocol_plugin_init_auth(
- gp,
- (password_storing_disabled ? 0 : REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD |
- REMMINA_MESSAGE_PANEL_FLAG_USERNAME),
+ disable_password_storing = rm_plugin_service->file_get_int(remminafile,
+ "disablepasswordstoring",
+ FALSE);
+ ret = rm_plugin_service->protocol_plugin_init_auth(
+ gp, (disable_password_storing ? 0 :
+ REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD |
+ REMMINA_MESSAGE_PANEL_FLAG_USERNAME),
_("Enter X2Go credentials"),
username, // function arg 'username' is default username
password, // function arg 'password' is default password
@@ -596,38 +664,19 @@ static gboolean remmina_plugin_x2go_get_auth(RemminaProtocolWidget *gp, gchar* e
if (ret == GTK_RESPONSE_OK) {
- s_username = remmina_plugin_service->protocol_plugin_init_get_username(gp);
- s_password = remmina_plugin_service->protocol_plugin_init_get_password(gp);
- if (remmina_plugin_service->protocol_plugin_init_get_savepassword(gp))
- remmina_plugin_service->file_set_string(remminafile, "password", s_password);
+ s_username = rm_plugin_service->protocol_plugin_init_get_username(gp);
+ s_password = rm_plugin_service->protocol_plugin_init_get_password(gp);
+ if (rm_plugin_service->protocol_plugin_init_get_savepassword(gp))
+ rm_plugin_service->file_set_string(remminafile, "password",
+ s_password);
// Should be renamed to protocol_plugin_init_get_savecredentials()?!
- save = remmina_plugin_service->protocol_plugin_init_get_savepassword(gp);
+ save = rm_plugin_service->protocol_plugin_init_get_savepassword(gp);
if (save) {
- // User has requested to save credentials. We put all the new credentials
- // into remminafile->settings. They will be saved later, on successful
- // connection, by rcw.c
-
- if (s_password && s_username) {
- if (strcmp(s_username, "") == 0) {
- g_strlcpy(errmsg, _("Given username can't get saved since "
- "it's empty!"), 512);
- //REMMINA_PLUGIN_CRITICAL("%s", errmsg);
- return FALSE;
- }
-
- // We allow the possibility to set an empty password because a X2Go
- // session can be still made using keyfiles or similar.
- remmina_plugin_service->file_set_string(remminafile, "password",
- s_password);
- remmina_plugin_service->file_set_string(remminafile, "username",
- s_username);
- } else {
- g_strlcpy(errmsg, _("An error occured while trying to save "
- "new credentials: 's_password' or "
- "'s_username' strings were not set."), 512);
- //REMMINA_PLUGIN_CRITICAL("%s", errmsg);
- return FALSE;
+ if (!rmplugin_x2go_save_credentials(remminafile,
+ s_username, s_password,
+ errmsg)) {
+
}
}
if (s_username) {
@@ -647,26 +696,28 @@ static gboolean remmina_plugin_x2go_get_auth(RemminaProtocolWidget *gp, gchar* e
return TRUE;
}
-static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
- gint sshport,
- gchar *username,
- gchar *password,
- gchar *command,
- gchar *kbdlayout,
- gchar *kbdtype,
- gchar *audio,
- gchar *clipboard,
- gint dpi,
- gchar *resolution,
- RemminaProtocolWidget *gp,
- gchar *errmsg) {
+static gboolean rmplugin_x2go_exec_x2go(gchar *host,
+ gint sshport,
+ gchar *username,
+ gchar *password,
+ gchar *command,
+ gchar *kbdlayout,
+ gchar *kbdtype,
+ gchar *audio,
+ gchar *clipboard,
+ gint dpi,
+ gchar *resolution,
+ RemminaProtocolWidget *gp,
+ gchar *errmsg)
+{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
gchar *argv[50];
gint argc = 0;
- if(!remmina_plugin_x2go_get_auth(gp, errmsg, username, password)) {
+ // Sets `username` and `password`.
+ if (!rmplugin_x2go_get_auth(gp, errmsg, username, password)) {
return FALSE;
}
@@ -703,8 +754,9 @@ static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
if (FEATURE_AVAILABLE(gpdata, "COMMAND")) {
argv[argc++] = g_strdup("-c");
- // FIXME: pyhoca-cli is picky about multiple quotes around the command string...
- // argv[argc++] = g_strdup_printf ("%s", g_shell_quote(command));
+ // FIXME: pyhoca-cli is picky about multiple quotes around
+ // the command string...
+ // argv[argc++] = g_strdup_printf ("%s", g_shell_quote(command));
argv[argc++] = g_strdup(command);
}
@@ -759,10 +811,12 @@ static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
}
if (FEATURE_AVAILABLE(gpdata, "DPI")) {
+ // Event though we validate the users input in Remmina Editor,
+ // manipulating profile files is still very possible..
// Values are extracted from pyhoca-cli.
if (dpi < 20 || dpi > 400) {
- g_strlcpy(errmsg, _("DPI setting is out of bounds. "
- "Please adjust it in profile settings."), 512);
+ g_strlcpy(errmsg, _("DPI setting is out of bounds. Please adjust "
+ "it in profile settings."), 512);
// No need, start_session() will handle output.
//REMMINA_PLUGIN_CRITICAL("%s", errmsg);
return FALSE;
@@ -776,12 +830,12 @@ static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
GError *error = NULL;
gchar **envp = g_get_environ();
gboolean success = g_spawn_async_with_pipes (NULL, argv, envp,
- G_SPAWN_DO_NOT_REAP_CHILD |
- G_SPAWN_SEARCH_PATH, NULL,
- NULL, &gpdata->pidx2go,
- NULL, NULL, NULL, &error);
+ (G_SPAWN_DO_NOT_REAP_CHILD |
+ G_SPAWN_SEARCH_PATH), NULL,
+ NULL, &gpdata->pidx2go,
+ NULL, NULL, NULL, &error);
- REMMINA_PLUGIN_DEBUG("Started pyhoca-cli with following arguments:");
+ REMMINA_PLUGIN_INFO("%s", _("Started pyhoca-cli with following arguments:"));
// Print every argument except passwords. Free all arg strings.
for (gint i = 0; i < argc - 1; i++) {
if (strcmp(argv[i], "--password") == 0) {
@@ -798,11 +852,11 @@ static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
g_printf("\n");
if (!success || error) {
- if (!error)
- error = g_error_new(0, 0, "<error not available>");
+ // TRANSLATORS: Meta-error. Shouldn't be visible.
+ if (!error) error = g_error_new(0, 0, _("Internal error."));
gchar *error_title = _("An error occured while "
- "starting an X2Go session…");
+ "starting an X2Go session…");
DialogData *ddata = g_new0(DialogData, 1);
SET_DIALOG_DATA(gp, ddata);
@@ -812,14 +866,15 @@ static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
ddata->buttons = GTK_BUTTONS_OK;
ddata->title = _("Could not start X2Go session.");
ddata->message = g_strdup_printf(_("Could not start PyHoca-CLI (%i): '%s'"),
- error->code,
- error->message);
- ddata->callbackfunc = NULL; // Dialog frees itself, no need for an callbackfunc.
- IDLE_ADD((GSourceFunc) remmina_plugin_x2go_open_dialog, gp);
+ error->code,
+ error->message);
+ // We don't need the response.
+ ddata->callbackfunc = NULL;
+ IDLE_ADD((GSourceFunc) rmplugin_x2go_open_dialog, gp);
g_strlcpy(errmsg, error_title, 512);
- // No need to output here. remmina_plugin_x2go_start_session will do this.
+ // No need to output here. rmplugin_x2go_start_session will do this.
g_error_free(error);
@@ -834,15 +889,17 @@ static gboolean remmina_plugin_x2go_exec_x2go(gchar *host,
REMMINA_PLUGIN_DEBUG("Watching child pyhoca-cli process now…");
g_child_watch_add(gpdata->pidx2go,
- (GChildWatchFunc) remmina_plugin_x2go_pyhoca_cli_exited,
- gp);
+ (GChildWatchFunc) rmplugin_x2go_pyhoca_cli_exited,
+ gp);
return TRUE;
}
-// Returns a GList* with all features which pyhoca-cli had before even
-// implementing the feature system. (It can't change since its an old version)
-static GList* remmina_plugin_x2go_old_pyhoca_features() {
+/**
+ * @returns a GList* with all features which pyhoca-cli had before the feature system.
+ */
+static GList* rmplugin_x2go_old_pyhoca_features()
+{
REMMINA_PLUGIN_DEBUG("Function entry.");
#define AMOUNT_FEATURES 43
@@ -862,17 +919,21 @@ static GList* remmina_plugin_x2go_old_pyhoca_features() {
for (int i = 0; i < AMOUNT_FEATURES; i++) {
features_list = g_list_append(features_list, features[i]);
}
+
return features_list;
}
-// Returns a GList* which includes all features we *can* use.
-static GList* remmina_plugin_x2go_populate_available_features_list() {
+/**
+ * @returns a GList* which includes all pyhoca-cli command line features we can use.
+ */
+static GList* rmplugin_x2go_populate_available_features_list()
+{
REMMINA_PLUGIN_DEBUG("Function entry.");
GList* returning_glist = NULL;
// Querying pyhoca-cli's command line features.
- gchar* features_string = remmina_plugin_x2go_get_pyhoca_features();
+ gchar* features_string = rmplugin_x2go_get_pyhoca_features();
if (!features_string) {
// We added the '--list-cmdline-features' on commit 17d1be1319ba6 of
@@ -880,52 +941,58 @@ static GList* remmina_plugin_x2go_populate_available_features_list() {
// version of pyhoca-cli available yet we artificially create a list
// of an old limited set of features.
- REMMINA_PLUGIN_WARNING("%s", _("Couldn't get pyhoca-cli's cmdline-features. This "
- "indicates either your pyhoca-cli version is too "
- "old or pyhoca-cli is not installed! An old limited set "
- "of features will be used now."));
+ REMMINA_PLUGIN_WARNING("%s",
+ _("Couldn't get pyhoca-cli's cmdline-features. This "
+ "indicates either your pyhoca-cli version is too "
+ "old or pyhoca-cli is not installed! An old limited set "
+ "of features will be used now."));
- return remmina_plugin_x2go_old_pyhoca_features();
+ return rmplugin_x2go_old_pyhoca_features();
} else {
guint features_amount = 0;
- gchar **features_list = remmina_plugin_x2go_split_string(features_string,
- '\n', &features_amount);
+ gchar **features_list = rmplugin_x2go_split_string(features_string, '\n',
+ &features_amount);
+
if (features_list == NULL || features_amount <= 0) {
- gchar *error_msg = _("parsing pyhoca-cli functionality was not possible! "
- "Using a limited feature-set for now.");
+ gchar *error_msg = _("Parsing pyhoca-cli functionality was not "
+ "possible! Using a limited feature-set for "
+ "now.");
REMMINA_PLUGIN_WARNING("%s", error_msg);
- return remmina_plugin_x2go_old_pyhoca_features();
+ return rmplugin_x2go_old_pyhoca_features();
}
- REMMINA_PLUGIN_INFO("%s", _("Retrieved the following pyhoca-cli functionality:"));
+ REMMINA_PLUGIN_INFO("%s", _("Retrieved the following pyhoca-cli "
+ "functionality:"));
for(int k = 0; k < features_amount; k++) {
- REMMINA_PLUGIN_INFO("%s", g_strdup_printf(_("Available feature[%i]: '%s'"),
- k+1, features_list[k]));
+ REMMINA_PLUGIN_INFO("%s",
+ g_strdup_printf(_("Available feature[%i]: '%s'"),
+ k+1, features_list[k]));
returning_glist = g_list_append(returning_glist, features_list[k]);
}
return returning_glist;
}
}
-static void remmina_plugin_x2go_on_plug_added(GtkSocket *socket,
- RemminaProtocolWidget *gp) {
+static void rmplugin_x2go_on_plug_added(GtkSocket *socket, RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
REMMINA_PLUGIN_DEBUG("Socket %d", gpdata->socket_id);
- remmina_plugin_service->protocol_plugin_signal_connection_opened(gp);
+ rm_plugin_service->protocol_plugin_signal_connection_opened(gp);
return;
}
-static gboolean remmina_plugin_x2go_on_plug_removed(GtkSocket *socket,
- RemminaProtocolWidget *gp) {
+static gboolean rmplugin_x2go_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
REMMINA_PLUGIN_DEBUG("Function entry.");
- remmina_plugin_x2go_close_connection(gp);
+ rmplugin_x2go_close_connection(gp);
return TRUE;
}
-static void remmina_plugin_x2go_init(RemminaProtocolWidget *gp) {
+static void rmplugin_x2go_init(RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
REMMINA_PLUGIN_DEBUG("Function entry.", PLUGIN_NAME);
RemminaPluginX2GoData *gpdata;
@@ -933,12 +1000,12 @@ static void remmina_plugin_x2go_init(RemminaProtocolWidget *gp) {
gpdata = g_new0(RemminaPluginX2GoData, 1);
g_object_set_data_full(G_OBJECT(gp), "plugin-data", gpdata, g_free);
- if (!remmina_plugin_service->gtksocket_available()) {
+ if (!rm_plugin_service->gtksocket_available()) {
/* report this in open_connection, not reportable here... */
return;
}
- GList* available_features = remmina_plugin_x2go_populate_available_features_list();
+ GList* available_features = rmplugin_x2go_populate_available_features_list();
// available_features can't be NULL cause if it fails, it gets populated with an
// old standard feature set.
@@ -953,73 +1020,75 @@ static void remmina_plugin_x2go_init(RemminaProtocolWidget *gp) {
gpdata->orig_handler = NULL;
gpdata->socket = gtk_socket_new();
- remmina_plugin_service->protocol_plugin_register_hostkey(gp, gpdata->socket);
+ rm_plugin_service->protocol_plugin_register_hostkey(gp, gpdata->socket);
gtk_widget_show(gpdata->socket);
g_signal_connect(G_OBJECT(gpdata->socket), "plug-added",
- G_CALLBACK(remmina_plugin_x2go_on_plug_added), gp);
+ G_CALLBACK(rmplugin_x2go_on_plug_added), gp);
g_signal_connect(G_OBJECT(gpdata->socket), "plug-removed",
- G_CALLBACK(remmina_plugin_x2go_on_plug_removed), gp);
+ G_CALLBACK(rmplugin_x2go_on_plug_removed), gp);
gtk_container_add(GTK_CONTAINER(gp), gpdata->socket);
}
-static gboolean remmina_plugin_x2go_try_window_id(Window window_id) {
+static gboolean rmplugin_x2go_try_window_id(Window window_id)
+{
TRACE_CALL(__func__);
gint i;
gboolean already_seen = FALSE;
- REMMINA_PLUGIN_DEBUG("Check if X2Go Agent window [0x%lx] is already known or if it "
- "needs registration", window_id);
+ REMMINA_PLUGIN_DEBUG("Check if X2Go Agent window [0x%lx] is already known or if "
+ "it needs registration", window_id);
pthread_mutex_lock(&remmina_x2go_init_mutex);
for (i = 0; i < remmina_x2go_window_id_array->len; i++) {
if (g_array_index(remmina_x2go_window_id_array, Window, i) == window_id) {
already_seen = TRUE;
- REMMINA_PLUGIN_DEBUG("X2Go window for Agent with ID [0x%lx] already seen.",
- window_id);
+ REMMINA_PLUGIN_DEBUG("X2Go window for Agent with ID [0x%lx] "
+ "already seen.", window_id);
break;
}
}
if (!already_seen) {
g_array_append_val(remmina_x2go_window_id_array, window_id);
- REMMINA_PLUGIN_DEBUG("Registered new window for X2Go Agent with ID [0x%lx].",
- window_id);
+ REMMINA_PLUGIN_DEBUG("Registered new window for X2Go Agent with "
+ "ID [0x%lx].", window_id);
}
pthread_mutex_unlock(&remmina_x2go_init_mutex);
return (!already_seen);
}
-static int remmina_plugin_x2go_dummy_handler(Display *dsp, XErrorEvent *err) {
+static int rmplugin_x2go_dummy_handler(Display *dsp, XErrorEvent *err)
+{
TRACE_CALL(__func__);
return 0;
}
-static gboolean remmina_plugin_x2go_start_create_notify(RemminaProtocolWidget *gp,
- gchar *errmsg) {
+static gboolean rmplugin_x2go_start_create_notify(RemminaProtocolWidget *gp, gchar *errmsg)
+{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
gpdata->display = XOpenDisplay(gdk_display_get_name(gdk_display_get_default()));
if (gpdata->display == NULL) {
- g_strlcpy(errmsg, "Could not open X11 DISPLAY.", 512);
+ g_strlcpy(errmsg, _("Could not open X11 DISPLAY."), 512);
return FALSE;
}
- gpdata->orig_handler = XSetErrorHandler(remmina_plugin_x2go_dummy_handler);
+ gpdata->orig_handler = XSetErrorHandler(rmplugin_x2go_dummy_handler);
XSelectInput(gpdata->display,
- XDefaultRootWindow(gpdata->display),
- SubstructureNotifyMask);
+ XDefaultRootWindow(gpdata->display),
+ SubstructureNotifyMask);
REMMINA_PLUGIN_DEBUG("X11 event watcher created.");
return TRUE;
}
-static gboolean remmina_plugin_x2go_monitor_create_notify(RemminaProtocolWidget *gp,
- const gchar *cmd,
- gchar *errmsg)
+static gboolean rmplugin_x2go_monitor_create_notify(RemminaProtocolWidget *gp,
+ const gchar *cmd,
+ gchar *errmsg)
{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata;
@@ -1033,7 +1102,7 @@ static gboolean remmina_plugin_x2go_monitor_create_notify(RemminaProtocolWidget
unsigned long nitems, rest;
unsigned char *data = NULL;
- guint16 counter_x11_event_non_createnotify = 0;
+ guint16 non_createnotify_count = 0;
struct timespec ts;
// wait_amount * ts.tv_nsec = 20s
@@ -1068,8 +1137,8 @@ static gboolean remmina_plugin_x2go_monitor_create_notify(RemminaProtocolWidget
wait_amount--;
// Don't spam the console. Print every second though.
if (wait_amount % 5 == 0) {
- REMMINA_PLUGIN_INFO("%s", _("Waiting for pyhoca-cli "
- "to show the session's window."));
+ REMMINA_PLUGIN_INFO("%s", _("Waiting for pyhoca-cli to "
+ "show the session's window."));
}
continue;
}
@@ -1077,33 +1146,32 @@ static gboolean remmina_plugin_x2go_monitor_create_notify(RemminaProtocolWidget
XNextEvent(gpdata->display, &xev);
// Just ignore non CreatNotify events.
if (xev.type != CreateNotify) {
- counter_x11_event_non_createnotify++;
- if (counter_x11_event_non_createnotify % 5 == 0) {
- REMMINA_PLUGIN_DEBUG("Saw '%i' X11 events, which weren't CreateNotify.",
- counter_x11_event_non_createnotify);
+ non_createnotify_count++;
+ if (non_createnotify_count % 5 == 0) {
+ REMMINA_PLUGIN_DEBUG("Saw '%i' X11 events, which weren't "
+ "CreateNotify.", non_createnotify_count);
}
continue;
}
w = xev.xcreatewindow.window;
- if (XGetWindowProperty(gpdata->display, w, atom, 0, 255, False, AnyPropertyType,
- &type, &format, &nitems, &rest,
- &data) != Success) {
- REMMINA_PLUGIN_DEBUG("Could not get WM_COMMAND property from X11 window ID "
- "[0x%lx].", w);
+ if (XGetWindowProperty(gpdata->display, w, atom, 0, 255, False,
+ AnyPropertyType, &type, &format, &nitems, &rest,
+ &data) != Success) {
+ REMMINA_PLUGIN_DEBUG("Could not get WM_COMMAND property from X11 "
+ "window ID [0x%lx].", w);
continue;
}
if (data) {
- REMMINA_PLUGIN_DEBUG("Saw '%i' X11 events, which weren't CreateNotify.",
- counter_x11_event_non_createnotify);
- REMMINA_PLUGIN_DEBUG("Found X11 window with WM_COMMAND set to '%s', "
- "the window ID is [0x%lx].", (char*)data, w);
+ REMMINA_PLUGIN_DEBUG("Saw '%i' X11 events, which weren't "
+ "CreateNotify.", non_createnotify_count);
+ REMMINA_PLUGIN_DEBUG("Found X11 window with WM_COMMAND set "
+ "to '%s', the window ID is [0x%lx].",
+ (char*)data, w);
}
- if (data &&
- g_strrstr((gchar*)data, cmd) &&
- remmina_plugin_x2go_try_window_id(w)) {
-
+ if (data && g_strrstr((gchar*)data, cmd) &&
+ rmplugin_x2go_try_window_id(w)) {
gpdata->window_id = w;
agent_window_found = TRUE;
XFree(data);
@@ -1120,15 +1188,16 @@ static gboolean remmina_plugin_x2go_monitor_create_notify(RemminaProtocolWidget
CANCEL_ASYNC
if (!agent_window_found) {
- g_strlcpy(errmsg, "No X2Go session window appeared. Something went wrong…",
- 512);
+ g_strlcpy(errmsg, _("No X2Go session window appeared. "
+ "Something went wrong…"), 512);
return FALSE;
}
return TRUE;
}
-static gboolean remmina_plugin_x2go_start_session(RemminaProtocolWidget *gp) {
+static gboolean rmplugin_x2go_start_session(RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
REMMINA_PLUGIN_DEBUG("Function entry.");
@@ -1137,40 +1206,45 @@ static gboolean remmina_plugin_x2go_start_session(RemminaProtocolWidget *gp) {
const gchar errmsg[512] = {0};
gboolean ret = TRUE;
- gchar *servstr, *host, *username, *password, *command, *kbdlayout, *kbdtype, *audio,
- *clipboard, *res;
+ gchar *servstr, *host, *username, *password, *command, *kbdlayout, *kbdtype,
+ *audio, *clipboard, *res;
gint sshport, dpi;
GdkDisplay *default_dsp;
gint width, height;
- /* We save the X Display name (:0) as we will need to synchronize the clipboards */
+ // We save the X Display name (:0) as we will need to synchronize the clipboards
default_dsp = gdk_display_get_default();
const gchar *default_dsp_name = gdk_display_get_name(default_dsp);
REMMINA_PLUGIN_DEBUG("Default display is '%s'.", default_dsp_name);
- remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
+ remminafile = rm_plugin_service->protocol_plugin_get_file(gp);
servstr = GET_PLUGIN_STRING("server");
if (servstr) {
- remmina_plugin_service->get_server_port(servstr, 22, &host, &sshport);
+ rm_plugin_service->get_server_port(servstr, 22, &host, &sshport);
} else {
return FALSE;
}
- if (!sshport)
- sshport=22;
+
+ if (!sshport) sshport=22;
+
username = GET_PLUGIN_STRING("username");
password = GET_PLUGIN_PASSWORD("password");
+
command = GET_PLUGIN_STRING("command");
- if (!command)
- command = "TERMINAL";
+ if (!command) command = "TERMINAL";
+
kbdlayout = GET_PLUGIN_STRING("kbdlayout");
kbdtype = GET_PLUGIN_STRING("kbdtype");
+
audio = GET_PLUGIN_STRING("audio");
+
clipboard = GET_PLUGIN_STRING("clipboard");
+
dpi = GET_PLUGIN_INT("dpi", 0);
- width = remmina_plugin_service->get_profile_remote_width(gp);
- height = remmina_plugin_service->get_profile_remote_height(gp);
+ width = rm_plugin_service->get_profile_remote_width(gp);
+ height = rm_plugin_service->get_profile_remote_height(gp);
/* multiple of 4 */
width = (width + 3) & ~0x3;
height = (height + 3) & ~0x3;
@@ -1184,22 +1258,20 @@ static gboolean remmina_plugin_x2go_start_session(RemminaProtocolWidget *gp) {
REMMINA_PLUGIN_DEBUG("Attached window to socket '%d'.", gpdata->socket_id);
/* register for notifications of window creation events */
- if (ret)
- ret = remmina_plugin_x2go_start_create_notify(gp, (gchar*)&errmsg);
+ if (ret) ret = rmplugin_x2go_start_create_notify(gp, (gchar*)&errmsg);
/* trigger the session start, session window should appear soon after this */
- if (ret)
- ret = remmina_plugin_x2go_exec_x2go(host, sshport, username, password, command,
- kbdlayout, kbdtype, audio, clipboard, dpi,
- res, gp, (gchar*)&errmsg);
+ if (ret) ret = rmplugin_x2go_exec_x2go(host, sshport, username, password, command,
+ kbdlayout, kbdtype, audio, clipboard, dpi,
+ res, gp, (gchar*)&errmsg);
/* get the window id of the remote x2goagent */
- if (ret)
- ret = remmina_plugin_x2go_monitor_create_notify(gp, "x2goagent", (gchar*)&errmsg);
+ if (ret) ret = rmplugin_x2go_monitor_create_notify(gp, "x2goagent",
+ (gchar*)&errmsg);
if (!ret) {
- REMMINA_PLUGIN_CRITICAL("%s", errmsg);
- remmina_plugin_service->protocol_plugin_set_error(gp, "%s", errmsg);
+ REMMINA_PLUGIN_CRITICAL("%s", _(errmsg));
+ rm_plugin_service->protocol_plugin_set_error(gp, "%s", _(errmsg));
return FALSE;
}
@@ -1209,46 +1281,52 @@ static gboolean remmina_plugin_x2go_start_session(RemminaProtocolWidget *gp) {
return TRUE;
}
-static gboolean remmina_plugin_x2go_main(RemminaProtocolWidget *gp) {
+static gboolean rmplugin_x2go_main(RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
gboolean ret = FALSE;
- ret = remmina_plugin_x2go_start_session(gp);
+ ret = rmplugin_x2go_start_session(gp);
gpdata->thread = 0;
return ret;
}
-static gpointer remmina_plugin_x2go_main_thread(gpointer data) {
+static gpointer rmplugin_x2go_main_thread(RemminaProtocolWidget* gp)
+{
TRACE_CALL(__func__);
+ if (!gp) {
+ REMMINA_PLUGIN_CRITICAL("%s", _("RemminaProtocolWidget* gp is null!"));
+ return NULL;
+ }
+
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
CANCEL_ASYNC
- if (!remmina_plugin_x2go_main((RemminaProtocolWidget*)data)) {
- IDLE_ADD(
- (GSourceFunc) remmina_plugin_x2go_cleanup,
- (RemminaProtocolWidget*) data
- );
+ if (!rmplugin_x2go_main(gp)) {
+ IDLE_ADD((GSourceFunc) rmplugin_x2go_cleanup, gp);
}
+
return NULL;
}
-static gboolean remmina_plugin_x2go_open_connection(RemminaProtocolWidget *gp) {
+static gboolean rmplugin_x2go_open_connection(RemminaProtocolWidget *gp)
+{
TRACE_CALL(__func__);
RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp);
- if (!remmina_plugin_service->gtksocket_available()) {
- remmina_plugin_service->protocol_plugin_set_error(gp,
- _("The protocol %s is unavailable because GtkSocket only works under X.org"),
- PLUGIN_NAME);
+ if (!rm_plugin_service->gtksocket_available()) {
+ rm_plugin_service->protocol_plugin_set_error(gp, _("The protocol %s is "
+ "unavailable because GtkSocket only works under X.org"),
+ PLUGIN_NAME);
return FALSE;
}
gpdata->socket_id = gtk_socket_get_id(GTK_SOCKET(gpdata->socket));
- if (pthread_create(&gpdata->thread, NULL, remmina_plugin_x2go_main_thread, gp)) {
- remmina_plugin_service->protocol_plugin_set_error(gp,
- "Could not initialize pthread. Falling back to non-threaded mode…");
+ if (pthread_create(&gpdata->thread, NULL, rmplugin_x2go_main_thread, gp)) {
+ rm_plugin_service->protocol_plugin_set_error(gp, _("Could not initialize "
+ "pthread. Falling back to non-threaded mode…"));
gpdata->thread = 0;
return FALSE;
} else {
@@ -1256,35 +1334,85 @@ static gboolean remmina_plugin_x2go_open_connection(RemminaProtocolWidget *gp) {
}
}
-static gboolean remmina_plugin_x2go_query_feature(RemminaProtocolWidget* gp,
- const RemminaProtocolFeature* feature) {
+static gboolean rmplugin_x2go_query_feature(RemminaProtocolWidget* gp,
+ const RemminaProtocolFeature* feature)
+{
TRACE_CALL(__func__);
return TRUE;
}
-static const RemminaProtocolFeature remmina_plugin_x2go_features[] = {
- {REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET,
- REMMINA_PLUGIN_X2GO_FEATURE_GTKSOCKET, NULL, NULL, NULL},
- {REMMINA_PROTOCOL_FEATURE_TYPE_END,
- 0, NULL, NULL, NULL}
+static const RemminaProtocolFeature rmplugin_x2go_features[] = {
+ {REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET, RMPLUGIN_X2GO_FEATURE_GTKSOCKET, NULL, NULL, NULL},
+ {REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL}
};
+
+/**
+ * @brief This function builds a string like: "'value1', 'value2' and 'value3'" \n
+ * To be used in a loop. \n
+ * See rmplugin_x2go_string_setting_validator() for an example.
+ *
+ * @param max_elements Number of maximum elements.
+ * @param element_to_add Next element to add to the string
+ * @param current_element Which element is element_to_add?
+ * @param string The string to which `element_to_add` will be added.
+ */
+static gchar* rmplugin_x2go_enumeration_prettifier(const guint max_elements,
+ const guint current_element,
+ gchar* element_to_add,
+ gchar* string)
+{
+ if (max_elements > 2) {
+ if (current_element == max_elements - 1) {
+ // TRANSLATORS: Presumably you just want to translate 'and' into
+ // your language.
+ // (Except your listing-grammar differs from english.)
+ // 'value1', 'value2', 'valueN-1' and 'valueN'
+ return g_strdup_printf(_("%sand '%s'"), string, element_to_add);
+ } else if (current_element == max_elements - 2) {
+ // TRANSLATORS: Presumably you just want to leave it english.
+ // (Except your listing-grammar differs from english.)
+ // 'value1', 'value2', 'valueN-1' and 'valueN'
+ return g_strdup_printf(_("%s'%s' "), string, element_to_add);
+ } else {
+ // TRANSLATORS: Presumably you just want to leave it english.
+ // (Except your listing-grammar differs from english.)
+ // 'value1', 'value2', 'valueN-1' and 'valueN'
+ return g_strdup_printf(_("%s'%s', "), string, element_to_add);
+ }
+ } else if (max_elements == 2) {
+ if (current_element == max_elements - 1) {
+ // TRANSLATORS: Presumably you just want to translate 'and' into
+ // your language.
+ // (Except your listing-grammar differs from english.)
+ // 'value1' and 'value2'
+ return g_strdup_printf(_("%sand '%s'"), string, element_to_add);
+ } else {
+ // TRANSLATORS: Presumably you just want to leave it english.
+ // (Except your listing-grammar differs from english.)
+ // 'value1' and 'value2'
+ return g_strdup_printf(_("%s'%s' "), string, element_to_add);
+ }
+ } else {
+ return g_strdup(element_to_add);
+ }
+}
+
/**
* @brief Validator-functions are getting executed when the user wants to save profile
- * settings. It uses the given data (See RemminaProtocolSetting array) to determine
- * which strings are allowed and returns a end-user friendly error message.
+ * settings. It uses the given data (See RemminaProtocolSetting array) to determine
+ * which strings are allowed and returns a end-user friendly error message.
*
* @param key Key is the setting's name.
* @param value Value to validate.
* @param data Data needed for validation process. See RemminaProtocolSetting array.
*
* @returns End-user friendly and translated error message, explaining why the given
- * value is invalid. If the given value is error-free then NULL gets returned.
+ * value is invalid. If the given value is error-free then NULL gets returned.
*
*/
-static GError* remmina_plugin_x2go_string_setting_validator(gchar* key,
- gchar* value,
- gchar* data) {
+static GError* rmplugin_x2go_string_setting_validator(gchar* key, gchar* value, gchar* data)
+{
GError *error = NULL;
if (!data) {
@@ -1295,8 +1423,7 @@ static GError* remmina_plugin_x2go_string_setting_validator(gchar* key,
}
guint elements_amount = 0;
- gchar **elements_list = remmina_plugin_x2go_split_string(data, ',',
- &elements_amount);
+ gchar **elements_list = rmplugin_x2go_split_string(data, ',', &elements_amount);
if (elements_amount <= 0 || elements_list == NULL) {
// Something went wrong, there can't be less than 1 element!
@@ -1323,38 +1450,8 @@ static GError* remmina_plugin_x2go_string_setting_validator(gchar* key,
return NULL;
}
- if (elements_amount > 2) {
- if (i == elements_amount - 1) {
- // TRANSLATORS: Presumably you just want to translate 'and'
- // into your language. (Except your listing-grammar differs from english.)
- // 'value1', 'value2', 'valueN-1' and 'valueN'
- data_str = g_strdup_printf(_("%sand '%s'"), data_str, element);
- } else if (i == elements_amount - 2) {
- // TRANSLATORS: Presumably you just want to leave it english.
- // (Except your listing-grammar differs from english.)
- // 'value1', 'value2', 'valueN-1' and 'valueN'
- data_str = g_strdup_printf(_("%s'%s' "), data_str, element);
- } else {
- // TRANSLATORS: Presumably you just want to leave it english.
- // (Except your listing-grammar differs from english.)
- // 'value1', 'value2', 'valueN-1' and 'valueN'
- data_str = g_strdup_printf(_("%s'%s', "), data_str, element);
- }
- } else if (elements_amount == 2) {
- if (i == elements_amount - 1) {
- // TRANSLATORS: Presumably you just want to translate 'and'
- // into your language. (Except your listing-grammar differs from english.)
- // 'value1' and 'value2'
- data_str = g_strdup_printf(_("%sand '%s'"), data_str, element);
- } else {
- // TRANSLATORS: Presumably you just want to leave it english.
- // (Except your listing-grammar differs from english.)
- // 'value1' and 'value2'
- data_str = g_strdup_printf(_("%s'%s' "), data_str, element);
- }
- } else {
- data_str = g_strdup(element);
- }
+ data_str = rmplugin_x2go_enumeration_prettifier(elements_amount, i,
+ element, data_str);
}
if (elements_amount > 1) {
@@ -1371,25 +1468,24 @@ static GError* remmina_plugin_x2go_string_setting_validator(gchar* key,
/**
* @brief Validator-functions are getting executed when the user wants to save profile
- * settings. It uses the given data (See RemminaProtocolSetting array) to determine
- * if the given value is a valid integer is in range and returns
- * a end-user friendly error message.
+ * settings. It uses the given data (See RemminaProtocolSetting array) to determine
+ * if the given value is a valid integer is in range and returns a end-user
+ * friendly error message.
*
* @param key Key is the setting's name.
* @param value Value to validate.
* @param data Data needed for validation process. See RemminaProtocolSetting array.
*
* @returns End-user friendly and translated error message, explaining why the given
- * value is invalid. If the given value is error-free then NULL gets returned.
+ * value is invalid. If the given value is error-free then NULL gets returned.
*
*/
-static GError* remmina_plugin_x2go_int_setting_validator(gchar* key,
- gpointer value,
- gchar* data) {
+static GError* rmplugin_x2go_int_setting_validator(gchar* key, gpointer value, gchar* data)
+{
GError *error = NULL;
guint integer_amount = 0;
- gchar **integer_list = remmina_plugin_x2go_split_string(data, ';', &integer_amount);
+ gchar **integer_list = rmplugin_x2go_split_string(data, ';', &integer_amount);
if (integer_amount != 2 || integer_list == NULL) {
// Something went wrong, there can't be more or less than 2 list entries.
@@ -1449,7 +1545,7 @@ static GError* remmina_plugin_x2go_int_setting_validator(gchar* key,
if (err == STR2INT_SUCCESS && (minimum > int_value || int_value > maximum)) {
g_set_error(&error, 1, 1, _("Input must be a number between %i and %i."),
- minimum, maximum);
+ minimum, maximum);
}
return error;
@@ -1467,13 +1563,13 @@ static GError* remmina_plugin_x2go_int_setting_validator(gchar* key,
* h) Validation callback method (Can be null. Every entry will be valid then.)
* use following prototype:
* gboolean mysetting_validator_method(gpointer key, gpointer value,
- * gpointer validator_data);
+ * gpointer validator_data);
* gpointer key is a gchar* containing the setting's name,
* gpointer value contains the value which should be validated,
* gpointer validator_data contains your passed data.
*/
-static const RemminaProtocolSetting remmina_plugin_x2go_basic_settings[] = {
+static const RemminaProtocolSetting rmplugin_x2go_basic_settings[] = {
{REMMINA_PROTOCOL_SETTING_TYPE_SERVER, "server", NULL, FALSE, NULL, NULL,
/* Validation Data */ NULL,
/* Validation Method */ NULL},
@@ -1502,51 +1598,52 @@ static const RemminaProtocolSetting remmina_plugin_x2go_basic_settings[] = {
/* Options to select (or custom user string) */ "pulse,esd,none",
/* Tooltip */ N_("The X2Go server's sound system (default: 'pulse')."),
/* Validation Data */ "pulse,esd,none",
- /* Validation Method */ G_CALLBACK(remmina_plugin_x2go_string_setting_validator)},
+ /* Validation Method */ G_CALLBACK(rmplugin_x2go_string_setting_validator)},
{REMMINA_PROTOCOL_SETTING_TYPE_COMBO, "clipboard", N_("Clipboard direction"), FALSE,
/* Options to select (or custom user string) */ "none,server,client,both",
/* Tooltip */ N_("Which direction should clipboard content be copied? "
"(default: 'both')."),
/* Validation Data */ "none,server,client,both",
- /* Validation Method */ G_CALLBACK(remmina_plugin_x2go_string_setting_validator)},
+ /* Validation Method */ G_CALLBACK(rmplugin_x2go_string_setting_validator)},
{REMMINA_PROTOCOL_SETTING_TYPE_INT, "dpi", N_("DPI resolution"), FALSE, NULL,
/* Tooltip */ N_("Launch session with a specific resolution (in dots per inch). "
"Must be between 20 and 400."),
/* Validation Data */ "20;400", // "<min>;<max>;"
- /* Validation Method */ G_CALLBACK(remmina_plugin_x2go_int_setting_validator)},
+ /* Validation Method */ G_CALLBACK(rmplugin_x2go_int_setting_validator)},
{REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL}};
/* Protocol plugin definition and features */
-static RemminaProtocolPlugin remmina_plugin_x2go = {
- REMMINA_PLUGIN_TYPE_PROTOCOL, // Type
- PLUGIN_NAME, // Name
- PLUGIN_DESCRIPTION, // Description
- GETTEXT_PACKAGE, // Translation domain
- PLUGIN_VERSION, // Version number
- PLUGIN_APPICON, // Icon for normal connection
- PLUGIN_APPICON, // Icon for SSH connection
- remmina_plugin_x2go_basic_settings, // Array for basic settings
- NULL, // Array for advanced settings
- REMMINA_PROTOCOL_SSH_SETTING_TUNNEL, // SSH settings type
- /* REMMINA_PROTOCOL_SSH_SETTING_NONE, // SSH settings type */
- remmina_plugin_x2go_features, // Array for available features
- remmina_plugin_x2go_init, // Plugin initialization method
- remmina_plugin_x2go_open_connection, // Plugin open connection method
- remmina_plugin_x2go_close_connection, // Plugin connection-method closure
- remmina_plugin_x2go_query_feature, // Query for available features
- NULL, // Call a feature
- NULL, // Send a keystroke
- NULL, // Screenshot
+static RemminaProtocolPlugin rmplugin_x2go = {
+ REMMINA_PLUGIN_TYPE_PROTOCOL, // Type
+ PLUGIN_NAME, // Name
+ PLUGIN_DESCRIPTION, // Description
+ GETTEXT_PACKAGE, // Translation domain
+ PLUGIN_VERSION, // Version number
+ PLUGIN_APPICON, // Icon for normal connection
+ PLUGIN_APPICON, // Icon for SSH connection
+ rmplugin_x2go_basic_settings, // Array for basic settings
+ NULL, // Array for advanced settings
+ REMMINA_PROTOCOL_SSH_SETTING_TUNNEL, // SSH settings type
+ /* REMMINA_PROTOCOL_SSH_SETTING_NONE, // SSH settings type */
+ rmplugin_x2go_features, // Array for available features
+ rmplugin_x2go_init, // Plugin initialization method
+ rmplugin_x2go_open_connection, // Plugin open connection method
+ rmplugin_x2go_close_connection, // Plugin connection-method closure
+ rmplugin_x2go_query_feature, // Query for available features
+ NULL, // Call a feature
+ NULL, // Send a keystroke
+ NULL, // Screenshot
};
-G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service) {
+G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
+{
TRACE_CALL("remmina_plugin_entry");
- remmina_plugin_service = service;
+ rm_plugin_service = service;
bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- if (!service->register_plugin((RemminaPlugin *) &remmina_plugin_x2go)) {
+ if (!service->register_plugin((RemminaPlugin *) &rmplugin_x2go)) {
return FALSE;
}